Skip to content

Commit

Permalink
Construct IR.Syntax.Error rather than throwing an exception (#3861)
Browse files Browse the repository at this point in the history
This PR mimics test cases from #3860 and makes sure `IR.Syntax.Error` is constructed at appropriate places rather than just yielding an `UnhandledEntity` exception.

# Important Notes
Merge before #3611 to minimize disruption when changing the parser.
  • Loading branch information
JaroslavTulach authored Nov 10, 2022
1 parent 23e04f9 commit 20686dd
Show file tree
Hide file tree
Showing 4 changed files with 432 additions and 57 deletions.
140 changes: 85 additions & 55 deletions engine/runtime/src/main/java/org/enso/compiler/TreeToIr.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.enso.compiler.core.IR$Error$Syntax$UnexpectedDeclarationInType$;
import org.enso.compiler.core.IR$Error$Syntax$UnexpectedExpression$;
import org.enso.compiler.core.IR$Error$Syntax$EmptyParentheses$;
import org.enso.compiler.core.IR$Error$Syntax$InvalidImport$;
import org.enso.compiler.core.IR$Error$Syntax$Reason;
import org.enso.compiler.core.IR$Error$Syntax$UnrecognizedToken$;
import org.enso.compiler.core.IR$Expression$Binding;
import org.enso.compiler.core.IR$Expression$Block;
Expand Down Expand Up @@ -60,9 +62,11 @@
import org.enso.syntax2.Base;
import org.enso.syntax2.DocComment;
import org.enso.syntax2.Line;
import org.enso.syntax2.MultiSegmentAppSegment;
import org.enso.syntax2.TextElement;
import org.enso.syntax2.Token;
import org.enso.syntax2.Tree;
import org.enso.syntax2.Tree.MultiSegmentApp;

import scala.Option;
import scala.collection.immutable.LinearSeq;
Expand Down Expand Up @@ -181,7 +185,7 @@ IR.Module translateModule(Tree module) {
var language = EpbParser.ForeignLanguage.getBySyntacticTag(languageName);
if (language == null) {
var message = "Language '" + languageName + "' is not a supported polyglot language.";
var error = new IR$Error$Syntax(inputAst, new IR$Error$Syntax$InvalidForeignDefinition(message), meta(), diag());
var error = translateSyntaxError(inputAst, new IR$Error$Syntax$InvalidForeignDefinition(message));
yield cons(error, appendTo);
}
var text = buildTextConstant(body.getElements(), true);
Expand Down Expand Up @@ -223,7 +227,7 @@ methodRef, args, def, getIdentifiedLocation(inputAst), meta(), diag()
yield cons(ascription, appendTo);
}
default -> {
var error = new IR$Error$Syntax(inputAst, new IR$Error$Syntax$UnexpectedExpression$(), meta(), diag());
var error = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedExpression$.MODULE$);
yield cons(error, appendTo);
}
};
Expand Down Expand Up @@ -294,7 +298,7 @@ private List<IR> translateTypeBodyExpression(Tree exp, List<IR> appendTo) {
var language = EpbParser.ForeignLanguage.getBySyntacticTag(languageName);
if (language == null) {
var message = "Language '" + languageName + "' is not a supported polyglot language.";
var error = new IR$Error$Syntax(inputAst, new IR$Error$Syntax$InvalidForeignDefinition(message), meta(), diag());
var error = translateSyntaxError(inputAst, new IR$Error$Syntax$InvalidForeignDefinition(message));
yield cons(error, appendTo);
}
var text = buildTextConstant(body.getElements(), true);
Expand All @@ -312,7 +316,7 @@ private List<IR> translateTypeBodyExpression(Tree exp, List<IR> appendTo) {
yield cons(annotation, appendTo);
}
default -> {
var ir = new IR$Error$Syntax(inputAst, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$, meta(), diag());
var ir = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$);
yield cons(ir, appendTo);
}
};
Expand Down Expand Up @@ -544,11 +548,11 @@ IR.Expression translateExpression(Tree tree, boolean isMethod) {
var arr = app.getOpr().getLeft().getOperators();
if (arr.size() > 0 && arr.get(0).codeRepr().equals("=")) {
var errLoc = arr.size() > 1 ? getIdentifiedLocation(arr.get(1)) : at;
var err = new IR$Error$Syntax(errLoc.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$, meta(), diag());
var err = translateSyntaxError(errLoc.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$);
var name = buildName(app.getLhs());
yield new IR$Expression$Binding(name, err, at, meta(), diag());
} else {
yield new IR$Error$Syntax(at.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$, meta(), diag());
yield translateSyntaxError(at.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$);
}
}
yield switch (op.codeRepr()) {
Expand Down Expand Up @@ -595,7 +599,7 @@ yield switch (op.codeRepr()) {
var rhs = unnamedCallArgument(app.getRhs());
if ("@".equals(op.codeRepr()) && lhs.value() instanceof IR$Application$Prefix fn) {
final Option<IdentifiedLocation> where = getIdentifiedLocation(op);
var err = new IR$Error$Syntax(where.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$, meta(), diag());
var err = translateSyntaxError(where.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$);
var errArg = new IR$CallArgument$Specified(Option.empty(), err, where, meta(), diag());
var args = cons(rhs, cons(errArg, fn.arguments()));
yield new IR$Application$Prefix(fn.function(), args.reverse(), false, getIdentifiedLocation(app), meta(), diag());
Expand Down Expand Up @@ -730,7 +734,7 @@ yield switch (fn) {
case Tree.TypeAnnotated anno -> translateTypeAnnotated(anno);
case Tree.Group group -> {
yield switch (translateExpression(group.getBody(), false)) {
case null -> new IR$Error$Syntax(getIdentifiedLocation(group).get(), IR$Error$Syntax$EmptyParentheses$.MODULE$, meta(), diag());
case null -> translateSyntaxError(group, IR$Error$Syntax$EmptyParentheses$.MODULE$);
case IR$Application$Prefix pref -> {
final Option<IdentifiedLocation> groupWithoutParenthesis = getIdentifiedLocation(group, 1, -1, pref.getExternalId());
yield pref.setLocation(groupWithoutParenthesis);
Expand Down Expand Up @@ -824,6 +828,7 @@ loc, meta(), diag()
yield fn.setLocation(loc);
}
}
case Tree.Invalid __ -> translateSyntaxError(tree, IR$Error$Syntax$UnexpectedExpression$.MODULE$);
default -> throw new UnhandledEntity(tree, "translateExpression");
};
}
Expand Down Expand Up @@ -1171,38 +1176,42 @@ private List<IR.Name> qualifiedNameSegments(Tree t, boolean generateId) {
*/
@SuppressWarnings("unchecked")
IR$Module$Scope$Import translateImport(Tree.Import imp) {
Option<IR$Name$Literal> rename = Option.apply(imp.getAs()).map(as -> buildName(as.getBody(), true));
if (imp.getPolyglot() != null) {
if (!imp.getPolyglot().getBody().codeRepr().equals("java")) {
throw new UnhandledEntity(imp, "translateImport");
try {
Option<IR$Name$Literal> rename = Option.apply(imp.getAs()).map(as -> buildName(as.getBody(), true));
if (imp.getPolyglot() != null) {
if (!imp.getPolyglot().getBody().codeRepr().equals("java")) {
return translateSyntaxError(imp, IR$Error$Syntax$UnrecognizedToken$.MODULE$);
}
List<IR.Name> qualifiedName = qualifiedNameSegments(imp.getImport().getBody(), true);
StringBuilder pkg = new StringBuilder();
String cls = extractPackageAndName(qualifiedName, pkg);
return new IR$Module$Scope$Import$Polyglot(
new IR$Module$Scope$Import$Polyglot$Java(pkg.toString(), cls),
rename.map(name -> name.name()), getIdentifiedLocation(imp),
meta(), diag()
);
}
List<IR.Name> qualifiedName = qualifiedNameSegments(imp.getImport().getBody(), true);
StringBuilder pkg = new StringBuilder();
String cls = extractPackageAndName(qualifiedName, pkg);
return new IR$Module$Scope$Import$Polyglot(
new IR$Module$Scope$Import$Polyglot$Java(pkg.toString(), cls),
rename.map(name -> name.name()), getIdentifiedLocation(imp),
meta(), diag()
);
}
var isAll = imp.getAll() != null;
IR$Name$Qualified qualifiedName;
Option<List<IR$Name$Literal>> onlyNames = Option.empty();
if (imp.getFrom() != null) {
qualifiedName = buildQualifiedName(imp.getFrom().getBody(), Option.empty(), true);
if (!isAll) {
onlyNames = Option.apply(buildNameSequence(imp.getImport().getBody()));
var isAll = imp.getAll() != null;
IR$Name$Qualified qualifiedName;
Option<List<IR$Name$Literal>> onlyNames = Option.empty();
if (imp.getFrom() != null) {
qualifiedName = buildQualifiedName(imp.getFrom().getBody(), Option.empty(), true);
if (!isAll) {
onlyNames = Option.apply(buildNameSequence(imp.getImport().getBody()));
}
} else {
qualifiedName = buildQualifiedName(imp.getImport().getBody(), Option.empty(), true);
}
} else {
qualifiedName = buildQualifiedName(imp.getImport().getBody(), Option.empty(), true);
}
Option<List<IR$Name$Literal>> hidingNames = Option.apply(imp.getHiding()).map(
hiding -> buildNameSequence(hiding.getBody()));
return new IR$Module$Scope$Import$Module(
qualifiedName, rename, isAll || onlyNames.isDefined() || hidingNames.isDefined(), onlyNames,
hidingNames, getIdentifiedLocation(imp), false,
Option<List<IR$Name$Literal>> hidingNames = Option.apply(imp.getHiding()).map(
hiding -> buildNameSequence(hiding.getBody()));
return new IR$Module$Scope$Import$Module(
qualifiedName, rename, isAll || onlyNames.isDefined() || hidingNames.isDefined(), onlyNames,
hidingNames, getIdentifiedLocation(imp), false,
meta(), diag()
);
);
} catch (UnhandledEntity err) {
return translateUnhandledEntity(err, IR$Error$Syntax$InvalidImport$.MODULE$);
}
}

@SuppressWarnings("unchecked")
Expand All @@ -1228,26 +1237,30 @@ private String extractPackageAndName(List<IR.Name> qualifiedName, StringBuilder
* @return the [[IR]] representation of `imp`
*/
@SuppressWarnings("unchecked")
IR$Module$Scope$Export$Module translateExport(Tree.Export exp) {
Option<IR$Name$Literal> rename = Option.apply(exp.getAs()).map(as -> buildName(as.getBody(), true));
Option<List<IR$Name$Literal>> hidingNames = Option.apply(exp.getHiding()).map(
hiding -> buildNameSequence(hiding.getBody()));
IR$Name$Qualified qualifiedName;
Option<List<IR$Name$Literal>> onlyNames = Option.empty();
if (exp.getFrom() != null) {
qualifiedName = buildQualifiedName(exp.getFrom().getBody(), Option.empty(), true);
var onlyBodies = exp.getExport().getBody();
if (exp.getAll() == null) {
onlyNames = Option.apply(buildNameSequence(onlyBodies));
IR$Module$Scope$Export translateExport(Tree.Export exp) {
try {
Option<IR$Name$Literal> rename = Option.apply(exp.getAs()).map(as -> buildName(as.getBody(), true));
Option<List<IR$Name$Literal>> hidingNames = Option.apply(exp.getHiding()).map(
hiding -> buildNameSequence(hiding.getBody()));
IR$Name$Qualified qualifiedName;
Option<List<IR$Name$Literal>> onlyNames = Option.empty();
if (exp.getFrom() != null) {
qualifiedName = buildQualifiedName(exp.getFrom().getBody(), Option.empty(), true);
var onlyBodies = exp.getExport().getBody();
if (exp.getAll() == null) {
onlyNames = Option.apply(buildNameSequence(onlyBodies));
}
} else {
qualifiedName = buildQualifiedName(exp.getExport().getBody(), Option.empty(), true);
}
} else {
qualifiedName = buildQualifiedName(exp.getExport().getBody(), Option.empty(), true);
return new IR$Module$Scope$Export$Module(
qualifiedName, rename, (exp.getFrom() != null), onlyNames,
hidingNames, getIdentifiedLocation(exp), false,
meta(), diag()
);
} catch (UnhandledEntity err) {
return translateUnhandledEntity(err, IR$Error$Syntax$InvalidImport$.MODULE$);
}
return new IR$Module$Scope$Export$Module(
qualifiedName, rename, (exp.getFrom() != null), onlyNames,
hidingNames, getIdentifiedLocation(exp), false,
meta(), diag()
);
}

/** Translates a comment from its [[AST]] representation into its [[IR]]
Expand All @@ -1261,6 +1274,23 @@ hidingNames, getIdentifiedLocation(exp), false,
return new IR$Comment$Documentation(text, getIdentifiedLocation(where), meta(), diag());
}

IR$Error$Syntax translateUnhandledEntity(UnhandledEntity err, IR$Error$Syntax$Reason reason) {
var where = (Tree) err.entity();
return translateSyntaxError(where, reason);
}
IR$Error$Syntax translateSyntaxError(Tree where, IR$Error$Syntax$Reason reason) {
var at = getIdentifiedLocation(where);
if (at.isEmpty()) {
return new IR$Error$Syntax(where, reason, meta(), diag());
} else {
return new IR$Error$Syntax(at.get(), reason, meta(), diag()).setLocation(at);
}
}

IR$Error$Syntax translateSyntaxError(IdentifiedLocation where, IR$Error$Syntax$Reason reason) {
return new IR$Error$Syntax(where, reason, meta(), diag());
}

private IR$Name$Literal buildName(Token name) {
return buildName(getIdentifiedLocation(name), name, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7433,6 +7433,7 @@ object IR {
) extends Error
with Diagnostic.Kind.Interactive
with IR.Module.Scope.Definition
with IR.Module.Scope.Export
with IR.Module.Scope.Import
with IRKind.Primitive {
override protected var id: Identifier = randomId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package org.enso.compiler.exception
/** This exception is thrown when compiler internal processing encounters an
* entity that it doesn't know how to deal with.
*
* @param entity the undhandled entity
* @param entity the unhandled entity
* @param methodName the method throwing the exception
*/
class UnhandledEntity(entity: Any, methodName: String)
class UnhandledEntity(val entity: Any, methodName: String)
extends RuntimeException(
"Fatal: Unhandled entity in " + methodName + " = " + entity.toString
) {}
Loading

0 comments on commit 20686dd

Please sign in to comment.