Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Construct IR.Syntax.Error rather than throwing an exception #3861

Merged
merged 8 commits into from
Nov 10, 2022
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