mirror of
https://github.com/enso-org/enso.git
synced 2025-01-09 04:30:59 +03:00
Add Meta.get_annotation (#4049)
- add: `GeneralAnnotation` IR node for `@name expression` annotations - update: compilation pipeline to process the annotation expressions - update: rewrite `OverloadsResolution` compiler pass so that it keeps the order of module definitions - add: `Meta.get_annotation` builtin function that returns the result of annotation expression - misc: improvements (private methods, lazy arguments, build.sbt cleanup)
This commit is contained in:
parent
5b5a2be829
commit
bf9508603f
@ -525,6 +525,7 @@
|
|||||||
- [Introducing Meta.atom_with_hole][4023]
|
- [Introducing Meta.atom_with_hole][4023]
|
||||||
- [Report failures in name resolution in type signatures][4030]
|
- [Report failures in name resolution in type signatures][4030]
|
||||||
- [Attach visualizations to sub-expressions][4048]
|
- [Attach visualizations to sub-expressions][4048]
|
||||||
|
- [Add Meta.get_annotation method][4049]
|
||||||
- [Resolve Fully Qualified Names][4056]
|
- [Resolve Fully Qualified Names][4056]
|
||||||
- [Optimize Atom storage layouts][3862]
|
- [Optimize Atom storage layouts][3862]
|
||||||
|
|
||||||
@ -613,6 +614,7 @@
|
|||||||
[4023]: https://github.com/enso-org/enso/pull/4023
|
[4023]: https://github.com/enso-org/enso/pull/4023
|
||||||
[4030]: https://github.com/enso-org/enso/pull/4030
|
[4030]: https://github.com/enso-org/enso/pull/4030
|
||||||
[4048]: https://github.com/enso-org/enso/pull/4048
|
[4048]: https://github.com/enso-org/enso/pull/4048
|
||||||
|
[4056]: https://github.com/enso-org/enso/pull/4049
|
||||||
[4056]: https://github.com/enso-org/enso/pull/4056
|
[4056]: https://github.com/enso-org/enso/pull/4056
|
||||||
|
|
||||||
# Enso 2.0.0-alpha.18 (2021-10-12)
|
# Enso 2.0.0-alpha.18 (2021-10-12)
|
||||||
|
@ -1146,9 +1146,6 @@ lazy val `polyglot-api` = project
|
|||||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
||||||
),
|
),
|
||||||
libraryDependencies ++= jackson,
|
libraryDependencies ++= jackson,
|
||||||
addCompilerPlugin(
|
|
||||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
|
||||||
),
|
|
||||||
GenerateFlatbuffers.flatcVersion := flatbuffersVersion,
|
GenerateFlatbuffers.flatcVersion := flatbuffersVersion,
|
||||||
Compile / sourceGenerators += GenerateFlatbuffers.task
|
Compile / sourceGenerators += GenerateFlatbuffers.task
|
||||||
)
|
)
|
||||||
@ -1443,9 +1440,6 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
"-s",
|
"-s",
|
||||||
(Compile / sourceManaged).value.getAbsolutePath,
|
(Compile / sourceManaged).value.getAbsolutePath,
|
||||||
"-Xlint:unchecked"
|
"-Xlint:unchecked"
|
||||||
),
|
|
||||||
addCompilerPlugin(
|
|
||||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.settings(
|
.settings(
|
||||||
|
@ -10,6 +10,7 @@ import project.Data.Time.Duration.Duration
|
|||||||
import project.Data.Time.Time_Of_Day.Time_Of_Day
|
import project.Data.Time.Time_Of_Day.Time_Of_Day
|
||||||
import project.Data.Time.Time_Zone.Time_Zone
|
import project.Data.Time.Time_Zone.Time_Zone
|
||||||
import project.Data.Vector.Vector
|
import project.Data.Vector.Vector
|
||||||
|
import project.Nothing.Nothing
|
||||||
import project.Polyglot.Java
|
import project.Polyglot.Java
|
||||||
|
|
||||||
import project.Error.Error as Base_Error
|
import project.Error.Error as Base_Error
|
||||||
@ -333,10 +334,22 @@ java_instance_check value typ =
|
|||||||
Returns the type of the given value.
|
Returns the type of the given value.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
- value: the value to get the type of.
|
- value: The value to get the type of.
|
||||||
type_of : Any -> Any
|
type_of : Any -> Any
|
||||||
type_of value = @Builtin_Method "Meta.type_of"
|
type_of value = @Builtin_Method "Meta.type_of"
|
||||||
|
|
||||||
|
## UNSTABLE
|
||||||
|
ADVANCED
|
||||||
|
|
||||||
|
Given a type object, method name and a parameter name, return the associated annotation if it exists.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- target: The value or type to get the attribute from.
|
||||||
|
- method_name: The name of the method or constructor to get the attribute for.
|
||||||
|
- parameter_name: The name of the parameter to get the attribute for.
|
||||||
|
get_annotation : Any -> Text -> Text -> Any | Nothing
|
||||||
|
get_annotation target method_name parameter_name = @Builtin_Method "Meta.get_annotation"
|
||||||
|
|
||||||
## Represents a polyglot language.
|
## Represents a polyglot language.
|
||||||
type Language
|
type Language
|
||||||
|
|
||||||
|
@ -26,6 +26,11 @@ public final class EnsoCompiler implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IR.Module compile(CharSequence src) {
|
||||||
|
var tree = parser.parse(src);
|
||||||
|
return generateIR(tree);
|
||||||
|
}
|
||||||
|
|
||||||
boolean isReady() {
|
boolean isReady() {
|
||||||
return parser != null;
|
return parser != null;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ import org.enso.compiler.core.IR$Module$Scope$Import;
|
|||||||
import org.enso.compiler.core.IR$Module$Scope$Import$Module;
|
import org.enso.compiler.core.IR$Module$Scope$Import$Module;
|
||||||
import org.enso.compiler.core.IR$Module$Scope$Import$Polyglot;
|
import org.enso.compiler.core.IR$Module$Scope$Import$Polyglot;
|
||||||
import org.enso.compiler.core.IR$Module$Scope$Import$Polyglot$Java;
|
import org.enso.compiler.core.IR$Module$Scope$Import$Polyglot$Java;
|
||||||
import org.enso.compiler.core.IR$Name$Annotation;
|
import org.enso.compiler.core.IR$Name$BuiltinAnnotation;
|
||||||
|
import org.enso.compiler.core.IR$Name$GenericAnnotation;
|
||||||
import org.enso.compiler.core.IR$Name$Blank;
|
import org.enso.compiler.core.IR$Name$Blank;
|
||||||
import org.enso.compiler.core.IR$Name$Literal;
|
import org.enso.compiler.core.IR$Name$Literal;
|
||||||
import org.enso.compiler.core.IR$Name$Self;
|
import org.enso.compiler.core.IR$Name$Self;
|
||||||
@ -222,6 +223,7 @@ final class TreeToIr {
|
|||||||
private List<IR$Module$Scope$Definition> translateModuleSymbolImpl(Tree inputAst, List<IR$Module$Scope$Definition> appendTo) throws SyntaxException {
|
private List<IR$Module$Scope$Definition> translateModuleSymbolImpl(Tree inputAst, List<IR$Module$Scope$Definition> appendTo) throws SyntaxException {
|
||||||
return switch (inputAst) {
|
return switch (inputAst) {
|
||||||
case null -> appendTo;
|
case null -> appendTo;
|
||||||
|
|
||||||
case Tree.TypeDef def -> {
|
case Tree.TypeDef def -> {
|
||||||
var typeName = buildName(def.getName(), true);
|
var typeName = buildName(def.getName(), true);
|
||||||
List<IR> irBody = nil();
|
List<IR> irBody = nil();
|
||||||
@ -238,6 +240,7 @@ final class TreeToIr {
|
|||||||
);
|
);
|
||||||
yield cons(type, appendTo);
|
yield cons(type, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.Function fn -> {
|
case Tree.Function fn -> {
|
||||||
var methodRef = translateMethodReference(fn.getName(), false);
|
var methodRef = translateMethodReference(fn.getName(), false);
|
||||||
var args = translateArgumentsDefinition(fn.getArgs());
|
var args = translateArgumentsDefinition(fn.getArgs());
|
||||||
@ -256,6 +259,7 @@ final class TreeToIr {
|
|||||||
);
|
);
|
||||||
yield cons(binding, appendTo);
|
yield cons(binding, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.ForeignFunction fn when fn.getBody() instanceof Tree.TextLiteral body -> {
|
case Tree.ForeignFunction fn when fn.getBody() instanceof Tree.TextLiteral body -> {
|
||||||
var name = fn.getName();
|
var name = fn.getName();
|
||||||
var nameLoc = getIdentifiedLocation(name);
|
var nameLoc = getIdentifiedLocation(name);
|
||||||
@ -277,13 +281,21 @@ final class TreeToIr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Tree.AnnotatedBuiltin anno -> {
|
case Tree.AnnotatedBuiltin anno -> {
|
||||||
var annotation = new IR$Name$Annotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag());
|
var annotation = new IR$Name$BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag());
|
||||||
yield translateModuleSymbol(anno.getExpression(), cons(annotation, appendTo));
|
yield translateModuleSymbol(anno.getExpression(), cons(annotation, appendTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Tree.Annotated anno -> {
|
||||||
|
var annotationArgument = translateExpression(anno.getArgument());
|
||||||
|
var annotation = new IR$Name$GenericAnnotation(anno.getAnnotation().codeRepr(), annotationArgument, getIdentifiedLocation(anno), meta(), diag());
|
||||||
|
yield translateModuleSymbol(anno.getExpression(), cons(annotation, appendTo));
|
||||||
|
}
|
||||||
|
|
||||||
case Tree.Documented doc -> {
|
case Tree.Documented doc -> {
|
||||||
var comment = translateComment(doc, doc.getDocumentation());
|
var comment = translateComment(doc, doc.getDocumentation());
|
||||||
yield translateModuleSymbol(doc.getExpression(), cons(comment, appendTo));
|
yield translateModuleSymbol(doc.getExpression(), cons(comment, appendTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.Assignment a -> {
|
case Tree.Assignment a -> {
|
||||||
var reference = translateMethodReference(a.getPattern(), false);
|
var reference = translateMethodReference(a.getPattern(), false);
|
||||||
var body = translateExpression(a.getExpr());
|
var body = translateExpression(a.getExpr());
|
||||||
@ -307,6 +319,7 @@ final class TreeToIr {
|
|||||||
var ascription = new IR$Type$Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag());
|
var ascription = new IR$Type$Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag());
|
||||||
yield cons(ascription, appendTo);
|
yield cons(ascription, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
default -> {
|
default -> {
|
||||||
var error = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedExpression$.MODULE$);
|
var error = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedExpression$.MODULE$);
|
||||||
yield cons(error, appendTo);
|
yield cons(error, appendTo);
|
||||||
@ -328,7 +341,7 @@ final class TreeToIr {
|
|||||||
var constructorName = buildName(inputAst, cons.getConstructor());
|
var constructorName = buildName(inputAst, cons.getConstructor());
|
||||||
List<IR.DefinitionArgument> args = translateArgumentsDefinition(cons.getArguments());
|
List<IR.DefinitionArgument> args = translateArgumentsDefinition(cons.getArguments());
|
||||||
var cAt = getIdentifiedLocation(inputAst);
|
var cAt = getIdentifiedLocation(inputAst);
|
||||||
return new IR$Module$Scope$Definition$Data(constructorName, args, cAt, meta(), diag());
|
return new IR$Module$Scope$Definition$Data(constructorName, args, nil(), cAt, meta(), diag());
|
||||||
} catch (SyntaxException ex) {
|
} catch (SyntaxException ex) {
|
||||||
return ex.toError();
|
return ex.toError();
|
||||||
}
|
}
|
||||||
@ -353,12 +366,16 @@ final class TreeToIr {
|
|||||||
var inputAst = maybeManyParensed(exp);
|
var inputAst = maybeManyParensed(exp);
|
||||||
return switch (inputAst) {
|
return switch (inputAst) {
|
||||||
case null -> appendTo;
|
case null -> appendTo;
|
||||||
|
|
||||||
case Tree.ConstructorDefinition cons -> cons(translateConstructorDefinition(cons, inputAst), appendTo);
|
case Tree.ConstructorDefinition cons -> cons(translateConstructorDefinition(cons, inputAst), appendTo);
|
||||||
|
|
||||||
case Tree.TypeDef def -> {
|
case Tree.TypeDef def -> {
|
||||||
var ir = translateSyntaxError(def, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$);
|
var ir = translateSyntaxError(def, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$);
|
||||||
yield cons(ir, appendTo);
|
yield cons(ir, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.ArgumentBlockApplication app -> appendTo;
|
case Tree.ArgumentBlockApplication app -> appendTo;
|
||||||
|
|
||||||
case Tree.TypeSignature sig -> {
|
case Tree.TypeSignature sig -> {
|
||||||
var isMethod = false;
|
var isMethod = false;
|
||||||
if (sig.getVariable() instanceof Tree.Ident ident) {
|
if (sig.getVariable() instanceof Tree.Ident ident) {
|
||||||
@ -368,6 +385,7 @@ final class TreeToIr {
|
|||||||
var ir = translateTypeSignature(sig, sig.getType(), typeName);
|
var ir = translateTypeSignature(sig, sig.getType(), typeName);
|
||||||
yield cons(ir, appendTo);
|
yield cons(ir, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.Function fun -> {
|
case Tree.Function fun -> {
|
||||||
IR.Name name;
|
IR.Name name;
|
||||||
if (fun.getName() instanceof Tree.Ident ident) {
|
if (fun.getName() instanceof Tree.Ident ident) {
|
||||||
@ -379,6 +397,7 @@ final class TreeToIr {
|
|||||||
var ir = translateFunction(fun, name, fun.getArgs(), fun.getBody());
|
var ir = translateFunction(fun, name, fun.getArgs(), fun.getBody());
|
||||||
yield cons(ir, appendTo);
|
yield cons(ir, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In some cases this is a `Function` in IR, but an `Assignment` in Tree.
|
// In some cases this is a `Function` in IR, but an `Assignment` in Tree.
|
||||||
// See: https://discord.com/channels/401396655599124480/1001476608957349917
|
// See: https://discord.com/channels/401396655599124480/1001476608957349917
|
||||||
case Tree.Assignment assignment -> {
|
case Tree.Assignment assignment -> {
|
||||||
@ -387,6 +406,7 @@ final class TreeToIr {
|
|||||||
var ir = translateFunction(assignment, name, args, assignment.getExpr());
|
var ir = translateFunction(assignment, name, args, assignment.getExpr());
|
||||||
yield cons(ir, appendTo);
|
yield cons(ir, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.ForeignFunction fn when fn.getBody() instanceof Tree.TextLiteral body -> {
|
case Tree.ForeignFunction fn when fn.getBody() instanceof Tree.TextLiteral body -> {
|
||||||
var name = buildName(fn.getName());
|
var name = buildName(fn.getName());
|
||||||
var args = translateArgumentsDefinition(fn.getArgs());
|
var args = translateArgumentsDefinition(fn.getArgs());
|
||||||
@ -406,11 +426,19 @@ final class TreeToIr {
|
|||||||
var irDoc = translateComment(doc, doc.getDocumentation());
|
var irDoc = translateComment(doc, doc.getDocumentation());
|
||||||
yield translateTypeBodyExpression(doc.getExpression(), cons(irDoc, appendTo));
|
yield translateTypeBodyExpression(doc.getExpression(), cons(irDoc, appendTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree.AnnotatedBuiltin anno -> {
|
case Tree.AnnotatedBuiltin anno -> {
|
||||||
var ir = new IR$Name$Annotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag());
|
var ir = new IR$Name$BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag());
|
||||||
var annotation = translateAnnotation(ir, anno.getExpression(), nil());
|
var annotation = translateAnnotation(ir, anno.getExpression(), nil());
|
||||||
yield cons(annotation, appendTo);
|
yield cons(annotation, appendTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Tree.Annotated anno -> {
|
||||||
|
var annotationArgument = translateExpression(anno.getArgument());
|
||||||
|
var annotation = new IR$Name$GenericAnnotation(anno.getAnnotation().codeRepr(), annotationArgument, getIdentifiedLocation(anno), meta(), diag());
|
||||||
|
yield translateTypeBodyExpression(anno.getExpression(), cons(annotation, appendTo));
|
||||||
|
}
|
||||||
|
|
||||||
default -> {
|
default -> {
|
||||||
var ir = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$);
|
var ir = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$);
|
||||||
yield cons(ir, appendTo);
|
yield cons(ir, appendTo);
|
||||||
@ -937,7 +965,7 @@ final class TreeToIr {
|
|||||||
case Tree.TemplateFunction templ -> translateExpression(templ.getAst(), false);
|
case Tree.TemplateFunction templ -> translateExpression(templ.getAst(), false);
|
||||||
case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild), meta(), diag());
|
case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild), meta(), diag());
|
||||||
case Tree.AnnotatedBuiltin anno -> {
|
case Tree.AnnotatedBuiltin anno -> {
|
||||||
var ir = new IR$Name$Annotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag());
|
var ir = new IR$Name$BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag());
|
||||||
yield translateAnnotation(ir, anno.getExpression(), nil());
|
yield translateAnnotation(ir, anno.getExpression(), nil());
|
||||||
}
|
}
|
||||||
// Documentation can be attached to an expression in a few cases, like if someone documents a line of an
|
// Documentation can be attached to an expression in a few cases, like if someone documents a line of an
|
||||||
@ -1133,7 +1161,7 @@ final class TreeToIr {
|
|||||||
return new IR$Application$Prefix(pref.function(), withBlockArgs, pref.hasDefaultsSuspended(), pref.location(), meta(), diag());
|
return new IR$Application$Prefix(pref.function(), withBlockArgs, pref.hasDefaultsSuspended(), pref.location(), meta(), diag());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IR$Application$Prefix translateAnnotation(IR$Name$Annotation ir, Tree expr, List<IR.CallArgument> callArgs) {
|
private IR$Application$Prefix translateAnnotation(IR$Name$BuiltinAnnotation ir, Tree expr, List<IR.CallArgument> callArgs) {
|
||||||
return switch (expr) {
|
return switch (expr) {
|
||||||
case Tree.App fn -> {
|
case Tree.App fn -> {
|
||||||
var fnAsArg = translateCallArgument(fn.getArg());
|
var fnAsArg = translateCallArgument(fn.getArg());
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.enso.interpreter.node;
|
package org.enso.interpreter.node;
|
||||||
|
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
|
||||||
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
@ -26,7 +25,7 @@ public abstract class BaseNode extends Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @CompilationFinal TailStatus tailStatus = TailStatus.NOT_TAIL;
|
private @CompilerDirectives.CompilationFinal TailStatus tailStatus = TailStatus.NOT_TAIL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the new tail position status for this node.
|
* Sets the new tail position status for this node.
|
||||||
|
@ -2,6 +2,7 @@ package org.enso.interpreter.node.expression.builtin.meta;
|
|||||||
|
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
import org.enso.interpreter.runtime.EnsoContext;
|
import org.enso.interpreter.runtime.EnsoContext;
|
||||||
|
import org.enso.interpreter.runtime.callable.Annotation;
|
||||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
@ -9,7 +10,6 @@ import org.enso.interpreter.runtime.callable.atom.StructsLibrary;
|
|||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
import org.enso.interpreter.runtime.data.Vector;
|
|
||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
@ -19,12 +19,10 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
|||||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
import com.oracle.truffle.api.interop.TruffleObject;
|
import com.oracle.truffle.api.interop.TruffleObject;
|
||||||
import com.oracle.truffle.api.interop.UnknownIdentifierException;
|
import com.oracle.truffle.api.interop.UnknownIdentifierException;
|
||||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
|
||||||
import com.oracle.truffle.api.library.ExportLibrary;
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportMessage;
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import com.oracle.truffle.api.nodes.RootNode;
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
import com.oracle.truffle.api.profiles.ValueProfile;
|
|
||||||
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
||||||
import org.enso.interpreter.runtime.state.State;
|
import org.enso.interpreter.runtime.state.State;
|
||||||
|
|
||||||
@ -96,7 +94,7 @@ public abstract class AtomWithAHoleNode extends Node {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExportMessage Object getMembers(boolean includeInternal) throws UnsupportedMessageException {
|
@ExportMessage Object getMembers(boolean includeInternal) {
|
||||||
return new Array("value", "fill");
|
return new Array("value", "fill");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +116,6 @@ public abstract class AtomWithAHoleNode extends Node {
|
|||||||
}
|
}
|
||||||
static final class SwapAtomFieldNode extends RootNode {
|
static final class SwapAtomFieldNode extends RootNode {
|
||||||
private final FunctionSchema schema;
|
private final FunctionSchema schema;
|
||||||
private final ValueProfile sameAtom = ValueProfile.createClassProfile();
|
|
||||||
@CompilerDirectives.CompilationFinal
|
@CompilerDirectives.CompilationFinal
|
||||||
private int lastIndex = -1;
|
private int lastIndex = -1;
|
||||||
@Child private StructsLibrary structs = StructsLibrary.getFactory().createDispatched(10);
|
@Child private StructsLibrary structs = StructsLibrary.getFactory().createDispatched(10);
|
||||||
@ -130,7 +127,7 @@ public abstract class AtomWithAHoleNode extends Node {
|
|||||||
new ArgumentDefinition(1, "value", ArgumentDefinition.ExecutionMode.EXECUTE)
|
new ArgumentDefinition(1, "value", ArgumentDefinition.ExecutionMode.EXECUTE)
|
||||||
}, new boolean[]{
|
}, new boolean[]{
|
||||||
true, false
|
true, false
|
||||||
}, new CallArgumentInfo[0]);
|
}, new CallArgumentInfo[0], new Annotation[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SwapAtomFieldNode create() {
|
static SwapAtomFieldNode create() {
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.BaseNode;
|
||||||
|
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode;
|
||||||
|
import org.enso.interpreter.runtime.EnsoContext;
|
||||||
|
import org.enso.interpreter.runtime.callable.Annotation;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.data.Type;
|
||||||
|
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||||
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
import org.enso.interpreter.runtime.state.State;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "get_annotation",
|
||||||
|
description = "Get annotation associated with an object",
|
||||||
|
autoRegister = false)
|
||||||
|
public abstract class GetAnnotationNode extends BaseNode {
|
||||||
|
|
||||||
|
abstract Object execute(
|
||||||
|
VirtualFrame frame, State state, Object target, Object method, Object parameter);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Object doExecute(
|
||||||
|
VirtualFrame frame,
|
||||||
|
State state,
|
||||||
|
Object target,
|
||||||
|
Object method,
|
||||||
|
Object parameter,
|
||||||
|
@CachedLibrary(limit = "3") TypesLibrary types,
|
||||||
|
@Cached ThunkExecutorNode thunkExecutorNode,
|
||||||
|
@Cached ExpectStringNode expectStringNode) {
|
||||||
|
String methodName = expectStringNode.execute(method);
|
||||||
|
Type targetType = types.getType(target);
|
||||||
|
ModuleScope scope = targetType.getDefinitionScope();
|
||||||
|
Function methodFunction = scope.lookupMethodDefinition(targetType, methodName);
|
||||||
|
if (methodFunction != null) {
|
||||||
|
String parameterName = expectStringNode.execute(parameter);
|
||||||
|
Annotation annotation = methodFunction.getSchema().getAnnotation(parameterName);
|
||||||
|
if (annotation != null) {
|
||||||
|
Function thunk =
|
||||||
|
Function.thunk(annotation.getExpression().getCallTarget(), frame.materialize());
|
||||||
|
return thunkExecutorNode.executeThunk(thunk, state, getTailStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AtomConstructor constructor = getAtomConstructor(targetType, methodName);
|
||||||
|
if (constructor != null) {
|
||||||
|
Function constructorFunction = constructor.getConstructorFunction();
|
||||||
|
String parameterName = expectStringNode.execute(parameter);
|
||||||
|
Annotation annotation = constructorFunction.getSchema().getAnnotation(parameterName);
|
||||||
|
if (annotation != null) {
|
||||||
|
Function thunk =
|
||||||
|
Function.thunk(annotation.getExpression().getCallTarget(), frame.materialize());
|
||||||
|
return thunkExecutorNode.executeThunk(thunk, state, getTailStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EnsoContext.get(this).getNothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
static GetAnnotationNode build() {
|
||||||
|
return GetAnnotationNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
private static AtomConstructor getAtomConstructor(Type type, String name) {
|
||||||
|
return type.getConstructors().get(name);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.enso.interpreter.runtime.callable;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
|
|
||||||
|
/** Annotation with callable expression. */
|
||||||
|
public class Annotation {
|
||||||
|
|
||||||
|
private final RootNode expression;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Annotation(String name, RootNode expression) {
|
||||||
|
this.name = name;
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the annotation name. */
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the annotation expression. */
|
||||||
|
public RootNode getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
}
|
@ -70,15 +70,15 @@ public final class CallArgumentInfo {
|
|||||||
* Represents a mapping between the defined arguments of a function and the call site arguments.
|
* Represents a mapping between the defined arguments of a function and the call site arguments.
|
||||||
*/
|
*/
|
||||||
public static class ArgumentMappingBuilder {
|
public static class ArgumentMappingBuilder {
|
||||||
private int[] appliedMapping;
|
private final int[] appliedMapping;
|
||||||
private int[] oversaturatedArgumentMapping;
|
private final int[] oversaturatedArgumentMapping;
|
||||||
private boolean[] argumentShouldExecute;
|
private final boolean[] argumentShouldExecute;
|
||||||
private ArgumentDefinition[] definitions;
|
private final ArgumentDefinition[] definitions;
|
||||||
private CallArgumentInfo[] callArgs;
|
private final CallArgumentInfo[] callArgs;
|
||||||
private CallArgumentInfo[] existingOversaturatedArgs;
|
private final CallArgumentInfo[] existingOversaturatedArgs;
|
||||||
private boolean[] argumentUsed;
|
private final boolean[] argumentUsed;
|
||||||
private boolean[] callSiteArgApplied;
|
private final boolean[] callSiteArgApplied;
|
||||||
private FunctionSchema originalSchema;
|
private final FunctionSchema originalSchema;
|
||||||
private int oversaturatedWritePosition = 0;
|
private int oversaturatedWritePosition = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,7 +220,11 @@ public final class CallArgumentInfo {
|
|||||||
newOversaturatedArgInfo.length);
|
newOversaturatedArgInfo.length);
|
||||||
|
|
||||||
return new FunctionSchema(
|
return new FunctionSchema(
|
||||||
originalSchema.getCallerFrameAccess(), definitions, argumentUsed, oversaturatedArgInfo);
|
originalSchema.getCallerFrameAccess(),
|
||||||
|
definitions,
|
||||||
|
argumentUsed,
|
||||||
|
oversaturatedArgInfo,
|
||||||
|
originalSchema.getAnnotations());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import org.enso.interpreter.node.expression.atom.InstantiateNode;
|
|||||||
import org.enso.interpreter.node.expression.atom.QualifiedAccessorNode;
|
import org.enso.interpreter.node.expression.atom.QualifiedAccessorNode;
|
||||||
import org.enso.interpreter.runtime.callable.atom.unboxing.Layout;
|
import org.enso.interpreter.runtime.callable.atom.unboxing.Layout;
|
||||||
import org.enso.interpreter.runtime.EnsoContext;
|
import org.enso.interpreter.runtime.EnsoContext;
|
||||||
|
import org.enso.interpreter.runtime.callable.Annotation;
|
||||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||||
@ -50,7 +51,7 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Atom constructor for a given name. The constructor is not valid until {@link
|
* Creates a new Atom constructor for a given name. The constructor is not valid until {@link
|
||||||
* AtomConstructor#initializeFields(LocalScope, ExpressionNode[], ExpressionNode[],
|
* AtomConstructor#initializeFields(LocalScope, ExpressionNode[], ExpressionNode[], Annotation[],
|
||||||
* ArgumentDefinition...)} is called.
|
* ArgumentDefinition...)} is called.
|
||||||
*
|
*
|
||||||
* @param name the name of the Atom constructor
|
* @param name the name of the Atom constructor
|
||||||
@ -62,7 +63,7 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Atom constructor for a given name. The constructor is not valid until {@link
|
* Creates a new Atom constructor for a given name. The constructor is not valid until {@link
|
||||||
* AtomConstructor#initializeFields(LocalScope, ExpressionNode[], ExpressionNode[],
|
* AtomConstructor#initializeFields(LocalScope, ExpressionNode[], ExpressionNode[], Annotation[],
|
||||||
* ArgumentDefinition...)} is called.
|
* ArgumentDefinition...)} is called.
|
||||||
*
|
*
|
||||||
* @param name the name of the Atom constructor
|
* @param name the name of the Atom constructor
|
||||||
@ -95,7 +96,8 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
reads[i] = ReadArgumentNode.build(i, null);
|
reads[i] = ReadArgumentNode.build(i, null);
|
||||||
}
|
}
|
||||||
return initializeFields(LocalScope.root(), new ExpressionNode[0], reads, args);
|
return initializeFields(
|
||||||
|
LocalScope.root(), new ExpressionNode[0], reads, new Annotation[0], args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,6 +113,7 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
LocalScope localScope,
|
LocalScope localScope,
|
||||||
ExpressionNode[] assignments,
|
ExpressionNode[] assignments,
|
||||||
ExpressionNode[] varReads,
|
ExpressionNode[] varReads,
|
||||||
|
Annotation[] annotations,
|
||||||
ArgumentDefinition... args) {
|
ArgumentDefinition... args) {
|
||||||
CompilerDirectives.transferToInterpreterAndInvalidate();
|
CompilerDirectives.transferToInterpreterAndInvalidate();
|
||||||
|
|
||||||
@ -122,7 +125,8 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
if (Layout.isAritySupported(args.length)) {
|
if (Layout.isAritySupported(args.length)) {
|
||||||
boxedLayout = Layout.create(args.length, 0);
|
boxedLayout = Layout.create(args.length, 0);
|
||||||
}
|
}
|
||||||
this.constructorFunction = buildConstructorFunction(localScope, assignments, varReads, args);
|
this.constructorFunction =
|
||||||
|
buildConstructorFunction(localScope, assignments, varReads, annotations, args);
|
||||||
generateQualifiedAccessor();
|
generateQualifiedAccessor();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -144,6 +148,7 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
LocalScope localScope,
|
LocalScope localScope,
|
||||||
ExpressionNode[] assignments,
|
ExpressionNode[] assignments,
|
||||||
ExpressionNode[] varReads,
|
ExpressionNode[] varReads,
|
||||||
|
Annotation[] annotations,
|
||||||
ArgumentDefinition[] args) {
|
ArgumentDefinition[] args) {
|
||||||
|
|
||||||
ExpressionNode instantiateNode = InstantiateNode.build(this, varReads);
|
ExpressionNode instantiateNode = InstantiateNode.build(this, varReads);
|
||||||
@ -159,7 +164,7 @@ public final class AtomConstructor implements TruffleObject {
|
|||||||
null,
|
null,
|
||||||
false);
|
false);
|
||||||
RootCallTarget callTarget = rootNode.getCallTarget();
|
RootCallTarget callTarget = rootNode.getCallTarget();
|
||||||
return new Function(callTarget, null, new FunctionSchema(args));
|
return new Function(callTarget, null, new FunctionSchema(annotations, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateQualifiedAccessor() {
|
private void generateQualifiedAccessor() {
|
||||||
|
@ -16,6 +16,7 @@ import org.enso.interpreter.node.callable.InteropApplicationNode;
|
|||||||
import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode;
|
import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode;
|
||||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||||
import org.enso.interpreter.runtime.EnsoContext;
|
import org.enso.interpreter.runtime.EnsoContext;
|
||||||
|
import org.enso.interpreter.runtime.callable.Annotation;
|
||||||
import org.enso.interpreter.runtime.callable.CallerInfo;
|
import org.enso.interpreter.runtime.callable.CallerInfo;
|
||||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
@ -102,7 +103,8 @@ public final class Function implements TruffleObject {
|
|||||||
public static Function fromBuiltinRootNodeWithCallerFrameAccess(
|
public static Function fromBuiltinRootNodeWithCallerFrameAccess(
|
||||||
BuiltinRootNode node, ArgumentDefinition... args) {
|
BuiltinRootNode node, ArgumentDefinition... args) {
|
||||||
RootCallTarget callTarget = node.getCallTarget();
|
RootCallTarget callTarget = node.getCallTarget();
|
||||||
FunctionSchema schema = new FunctionSchema(FunctionSchema.CallerFrameAccess.FULL, args);
|
FunctionSchema schema =
|
||||||
|
new FunctionSchema(FunctionSchema.CallerFrameAccess.FULL, new Annotation[0], args);
|
||||||
return new Function(callTarget, null, schema);
|
return new Function(callTarget, null, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,12 @@ package org.enso.interpreter.runtime.callable.function;
|
|||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||||
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
||||||
|
import org.enso.interpreter.runtime.callable.Annotation;
|
||||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the definition site argument information together with information on the partially applied
|
* Holds the definition site argument information together with information on the partially applied
|
||||||
* arguments positions.
|
* arguments positions.
|
||||||
@ -34,32 +37,35 @@ public final class FunctionSchema {
|
|||||||
private final @CompilationFinal(dimensions = 1) ArgumentDefinition[] argumentInfos;
|
private final @CompilationFinal(dimensions = 1) ArgumentDefinition[] argumentInfos;
|
||||||
private final @CompilationFinal(dimensions = 1) boolean[] hasPreApplied;
|
private final @CompilationFinal(dimensions = 1) boolean[] hasPreApplied;
|
||||||
private final @CompilationFinal(dimensions = 1) CallArgumentInfo[] oversaturatedArguments;
|
private final @CompilationFinal(dimensions = 1) CallArgumentInfo[] oversaturatedArguments;
|
||||||
|
private final @CompilationFinal(dimensions = 1) Annotation[] annotations;
|
||||||
private final boolean hasAnyPreApplied;
|
private final boolean hasAnyPreApplied;
|
||||||
private final boolean hasOversaturatedArguments;
|
private final boolean hasOversaturatedArguments;
|
||||||
private final CallerFrameAccess callerFrameAccess;
|
private final CallerFrameAccess callerFrameAccess;
|
||||||
|
|
||||||
private final boolean isFullyApplied;
|
private final boolean isFullyApplied;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an {@link FunctionSchema} instance.
|
* Creates an {@link FunctionSchema} instance.
|
||||||
*
|
*
|
||||||
* @param callerFrameAccess the declaration of whether access to caller frame is required for this
|
* @param callerFrameAccess the declaration of whether access to caller frame is required for this
|
||||||
* function
|
* function.
|
||||||
* @param argumentInfos Definition site arguments information
|
* @param argumentInfos Definition site arguments information.
|
||||||
* @param hasPreApplied A flags collection such that {@code hasPreApplied[i]} is true iff a
|
* @param hasPreApplied A flags collection such that {@code hasPreApplied[i]} is true iff a
|
||||||
* function has a partially applied argument at position {@code i}
|
* function has a partially applied argument at position {@code i}.
|
||||||
* @param oversaturatedArguments information about any unused, oversaturated arguments passed to
|
* @param oversaturatedArguments information about any unused, oversaturated arguments passed to
|
||||||
* this function so far
|
* this function so far.
|
||||||
|
* @param annotations the list of annotations defined on this function.
|
||||||
*/
|
*/
|
||||||
public FunctionSchema(
|
public FunctionSchema(
|
||||||
CallerFrameAccess callerFrameAccess,
|
CallerFrameAccess callerFrameAccess,
|
||||||
ArgumentDefinition[] argumentInfos,
|
ArgumentDefinition[] argumentInfos,
|
||||||
boolean[] hasPreApplied,
|
boolean[] hasPreApplied,
|
||||||
CallArgumentInfo[] oversaturatedArguments) {
|
CallArgumentInfo[] oversaturatedArguments,
|
||||||
|
Annotation[] annotations) {
|
||||||
this.argumentInfos = argumentInfos;
|
this.argumentInfos = argumentInfos;
|
||||||
this.oversaturatedArguments = oversaturatedArguments;
|
this.oversaturatedArguments = oversaturatedArguments;
|
||||||
this.hasPreApplied = hasPreApplied;
|
this.hasPreApplied = hasPreApplied;
|
||||||
this.callerFrameAccess = callerFrameAccess;
|
this.callerFrameAccess = callerFrameAccess;
|
||||||
|
this.annotations = annotations;
|
||||||
boolean hasAnyPreApplied = false;
|
boolean hasAnyPreApplied = false;
|
||||||
for (boolean b : hasPreApplied) {
|
for (boolean b : hasPreApplied) {
|
||||||
if (b) {
|
if (b) {
|
||||||
@ -77,15 +83,20 @@ public final class FunctionSchema {
|
|||||||
* Creates an {@link FunctionSchema} instance assuming the function has no partially applied
|
* Creates an {@link FunctionSchema} instance assuming the function has no partially applied
|
||||||
* arguments.
|
* arguments.
|
||||||
*
|
*
|
||||||
* @param callerFrameAccess the declaration of need to access the caller frame from the function
|
* @param callerFrameAccess the declaration of need to access the caller frame from the function.
|
||||||
* @param argumentInfos Definition site arguments information
|
* @param argumentInfos Definition site arguments information.
|
||||||
|
* @param annotations the list of annotations defined on this function.
|
||||||
*/
|
*/
|
||||||
public FunctionSchema(CallerFrameAccess callerFrameAccess, ArgumentDefinition... argumentInfos) {
|
public FunctionSchema(
|
||||||
|
CallerFrameAccess callerFrameAccess,
|
||||||
|
Annotation[] annotations,
|
||||||
|
ArgumentDefinition... argumentInfos) {
|
||||||
this(
|
this(
|
||||||
callerFrameAccess,
|
callerFrameAccess,
|
||||||
argumentInfos,
|
argumentInfos,
|
||||||
new boolean[argumentInfos.length],
|
new boolean[argumentInfos.length],
|
||||||
new CallArgumentInfo[0]);
|
new CallArgumentInfo[0],
|
||||||
|
annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,10 +105,23 @@ public final class FunctionSchema {
|
|||||||
*
|
*
|
||||||
* <p>Caller frame access is assumed to be {@link CallerFrameAccess#NONE}.
|
* <p>Caller frame access is assumed to be {@link CallerFrameAccess#NONE}.
|
||||||
*
|
*
|
||||||
|
* @param annotations the list of annotations defined on this function.
|
||||||
|
* @param argumentInfos Definition site arguments information.
|
||||||
|
*/
|
||||||
|
public FunctionSchema(Annotation[] annotations, ArgumentDefinition... argumentInfos) {
|
||||||
|
this(CallerFrameAccess.NONE, annotations, argumentInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link FunctionSchema} instance assuming the function has no annotations or
|
||||||
|
* partially applied arguments.
|
||||||
|
*
|
||||||
|
* <p>Caller frame access is assumed to be {@link CallerFrameAccess#NONE}.
|
||||||
|
*
|
||||||
* @param argumentInfos Definition site arguments information
|
* @param argumentInfos Definition site arguments information
|
||||||
*/
|
*/
|
||||||
public FunctionSchema(ArgumentDefinition... argumentInfos) {
|
public FunctionSchema(ArgumentDefinition... argumentInfos) {
|
||||||
this(CallerFrameAccess.NONE, argumentInfos);
|
this(CallerFrameAccess.NONE, new Annotation[0], argumentInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,6 +220,25 @@ public final class FunctionSchema {
|
|||||||
return callerFrameAccess;
|
return callerFrameAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return annotations defined on this function. */
|
||||||
|
public Annotation[] getAnnotations() {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds annotation by name.
|
||||||
|
*
|
||||||
|
* @param name the annotation name.
|
||||||
|
* @return the matching annotation expression.
|
||||||
|
*/
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public Annotation getAnnotation(String name) {
|
||||||
|
return Arrays.stream(annotations)
|
||||||
|
.filter(annotation -> annotation.getName().equals(name))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the function is already fully applied.
|
* Checks whether the function is already fully applied.
|
||||||
*
|
*
|
||||||
|
@ -85,7 +85,8 @@ class Passes(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
DataflowAnalysis,
|
DataflowAnalysis,
|
||||||
CachePreferenceAnalysis,
|
CachePreferenceAnalysis,
|
||||||
UnusedBindings
|
UnusedBindings,
|
||||||
|
GenericAnnotations
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,7 +97,11 @@ class Passes(
|
|||||||
* these dependencies.
|
* these dependencies.
|
||||||
*/
|
*/
|
||||||
val passOrdering: List[PassGroup] = passes.getOrElse(
|
val passOrdering: List[PassGroup] = passes.getOrElse(
|
||||||
List(moduleDiscoveryPasses, globalTypingPasses, functionBodyPasses)
|
List(
|
||||||
|
moduleDiscoveryPasses,
|
||||||
|
globalTypingPasses,
|
||||||
|
functionBodyPasses
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
/** The ordered representation of all passes run by the compiler. */
|
/** The ordered representation of all passes run by the compiler. */
|
||||||
|
@ -135,7 +135,10 @@ object AstToIr {
|
|||||||
def translateModuleSymbol(inputAst: AST): Module.Scope.Definition = {
|
def translateModuleSymbol(inputAst: AST): Module.Scope.Definition = {
|
||||||
inputAst match {
|
inputAst match {
|
||||||
case AST.Ident.Annotation.any(annotation) =>
|
case AST.Ident.Annotation.any(annotation) =>
|
||||||
IR.Name.Annotation(annotation.name, getIdentifiedLocation(annotation))
|
IR.Name.BuiltinAnnotation(
|
||||||
|
annotation.name,
|
||||||
|
getIdentifiedLocation(annotation)
|
||||||
|
)
|
||||||
case AstView.Atom(consName, args) =>
|
case AstView.Atom(consName, args) =>
|
||||||
val newArgs = args.map(translateArgumentDefinition(_))
|
val newArgs = args.map(translateArgumentDefinition(_))
|
||||||
|
|
||||||
@ -306,16 +309,22 @@ object AstToIr {
|
|||||||
inputAst match {
|
inputAst match {
|
||||||
case AST.Ident.Cons.any(cons) =>
|
case AST.Ident.Cons.any(cons) =>
|
||||||
IR.Module.Scope.Definition
|
IR.Module.Scope.Definition
|
||||||
.Data(buildName(cons), List(), getIdentifiedLocation(inputAst))
|
.Data(
|
||||||
|
buildName(cons),
|
||||||
|
List(),
|
||||||
|
List(),
|
||||||
|
getIdentifiedLocation(inputAst)
|
||||||
|
)
|
||||||
case AstView.SpacedList(AST.Ident.Cons.any(cons) :: args) =>
|
case AstView.SpacedList(AST.Ident.Cons.any(cons) :: args) =>
|
||||||
IR.Module.Scope.Definition
|
IR.Module.Scope.Definition
|
||||||
.Data(
|
.Data(
|
||||||
buildName(cons),
|
buildName(cons),
|
||||||
args.map(translateArgumentDefinition(_)),
|
args.map(translateArgumentDefinition(_)),
|
||||||
|
List(),
|
||||||
getIdentifiedLocation(inputAst)
|
getIdentifiedLocation(inputAst)
|
||||||
)
|
)
|
||||||
case AST.Ident.Annotation.any(ann) =>
|
case AST.Ident.Annotation.any(ann) =>
|
||||||
IR.Name.Annotation(ann.name, getIdentifiedLocation(ann))
|
IR.Name.BuiltinAnnotation(ann.name, getIdentifiedLocation(ann))
|
||||||
case AstView.FunctionSugar(
|
case AstView.FunctionSugar(
|
||||||
AST.Ident.Var("foreign"),
|
AST.Ident.Var("foreign"),
|
||||||
header,
|
header,
|
||||||
@ -1040,7 +1049,7 @@ object AstToIr {
|
|||||||
buildName(identifier)
|
buildName(identifier)
|
||||||
}
|
}
|
||||||
case AST.Ident.Annotation(name) =>
|
case AST.Ident.Annotation(name) =>
|
||||||
Name.Annotation(name, getIdentifiedLocation(identifier))
|
Name.BuiltinAnnotation(name, getIdentifiedLocation(identifier))
|
||||||
case AST.Ident.Cons(name) =>
|
case AST.Ident.Cons(name) =>
|
||||||
if (name == Constants.Names.SELF_TYPE_ARGUMENT) {
|
if (name == Constants.Names.SELF_TYPE_ARGUMENT) {
|
||||||
Name.SelfType(getIdentifiedLocation(identifier))
|
Name.SelfType(getIdentifiedLocation(identifier))
|
||||||
|
@ -23,6 +23,7 @@ import org.enso.compiler.pass.analyse.{
|
|||||||
import org.enso.compiler.pass.optimise.ApplicationSaturation
|
import org.enso.compiler.pass.optimise.ApplicationSaturation
|
||||||
import org.enso.compiler.pass.resolve.{
|
import org.enso.compiler.pass.resolve.{
|
||||||
ExpressionAnnotations,
|
ExpressionAnnotations,
|
||||||
|
GenericAnnotations,
|
||||||
GlobalNames,
|
GlobalNames,
|
||||||
MethodDefinitions,
|
MethodDefinitions,
|
||||||
Patterns,
|
Patterns,
|
||||||
@ -67,6 +68,7 @@ import org.enso.interpreter.runtime.callable.function.{
|
|||||||
Function => RuntimeFunction
|
Function => RuntimeFunction
|
||||||
}
|
}
|
||||||
import org.enso.interpreter.runtime.callable.{
|
import org.enso.interpreter.runtime.callable.{
|
||||||
|
Annotation => RuntimeAnnotation,
|
||||||
UnresolvedConversion,
|
UnresolvedConversion,
|
||||||
UnresolvedSymbol
|
UnresolvedSymbol
|
||||||
}
|
}
|
||||||
@ -80,6 +82,7 @@ import org.enso.interpreter.runtime.scope.{
|
|||||||
import org.enso.interpreter.{Constants, EnsoLanguage}
|
import org.enso.interpreter.{Constants, EnsoLanguage}
|
||||||
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
@ -87,8 +90,7 @@ import scala.jdk.OptionConverters._
|
|||||||
import scala.jdk.CollectionConverters._
|
import scala.jdk.CollectionConverters._
|
||||||
|
|
||||||
/** This is an implementation of a codegeneration pass that lowers the Enso
|
/** This is an implementation of a codegeneration pass that lowers the Enso
|
||||||
* [[IR]] into the truffle [[org.enso.compiler.core.Core.Node]] structures that
|
* [[IR]] into the truffle structures that are actually executed.
|
||||||
* are actually executed.
|
|
||||||
*
|
*
|
||||||
* It should be noted that, as is, there is no support for cross-module links,
|
* It should be noted that, as is, there is no support for cross-module links,
|
||||||
* with each lowering pass operating solely on a single module.
|
* with each lowering pass operating solely on a single module.
|
||||||
@ -258,11 +260,42 @@ class IrToTruffle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val (assignments, reads) = argumentExpressions.unzip
|
val (assignments, reads) = argumentExpressions.unzip
|
||||||
|
// build annotations
|
||||||
|
val annotations = atomDefn.annotations.map { annotation =>
|
||||||
|
val scopeElements = Seq(
|
||||||
|
tpDef.name.name,
|
||||||
|
atomDefn.name.name,
|
||||||
|
annotation.name
|
||||||
|
)
|
||||||
|
val scopeName =
|
||||||
|
scopeElements.mkString(Constants.SCOPE_SEPARATOR)
|
||||||
|
val expressionProcessor = new ExpressionProcessor(
|
||||||
|
scopeName,
|
||||||
|
scopeInfo.graph,
|
||||||
|
scopeInfo.graph.rootScope,
|
||||||
|
dataflowInfo
|
||||||
|
)
|
||||||
|
val expressionNode =
|
||||||
|
expressionProcessor.run(annotation.expression)
|
||||||
|
val closureName = s"<default::$scopeName>"
|
||||||
|
val closureRootNode = ClosureRootNode.build(
|
||||||
|
language,
|
||||||
|
expressionProcessor.scope,
|
||||||
|
moduleScope,
|
||||||
|
expressionNode,
|
||||||
|
makeSection(moduleScope, annotation.location),
|
||||||
|
closureName,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
new RuntimeAnnotation(annotation.name, closureRootNode)
|
||||||
|
}
|
||||||
if (!atomCons.isInitialized) {
|
if (!atomCons.isInitialized) {
|
||||||
atomCons.initializeFields(
|
atomCons.initializeFields(
|
||||||
localScope,
|
localScope,
|
||||||
assignments.toArray,
|
assignments.toArray,
|
||||||
reads.toArray,
|
reads.toArray,
|
||||||
|
annotations.toArray,
|
||||||
argDefs: _*
|
argDefs: _*
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -384,7 +417,7 @@ class IrToTruffle(
|
|||||||
.map(fOpt =>
|
.map(fOpt =>
|
||||||
// Register builtin iff it has not been automatically registered at an early stage
|
// Register builtin iff it has not been automatically registered at an early stage
|
||||||
// of builtins initialization.
|
// of builtins initialization.
|
||||||
fOpt.filter(m => !m.isAutoRegister()).map(m => m.getFunction)
|
fOpt.filter(m => !m.isAutoRegister).map(m => m.getFunction)
|
||||||
)
|
)
|
||||||
case fn: IR.Function =>
|
case fn: IR.Function =>
|
||||||
val bodyBuilder =
|
val bodyBuilder =
|
||||||
@ -405,12 +438,63 @@ class IrToTruffle(
|
|||||||
)
|
)
|
||||||
val callTarget = rootNode.getCallTarget
|
val callTarget = rootNode.getCallTarget
|
||||||
val arguments = bodyBuilder.args()
|
val arguments = bodyBuilder.args()
|
||||||
|
// build annotations
|
||||||
|
val annotations =
|
||||||
|
methodDef.getMetadata(GenericAnnotations).toVector.flatMap {
|
||||||
|
meta =>
|
||||||
|
meta.annotations
|
||||||
|
.collect { case annotation: IR.Name.GenericAnnotation =>
|
||||||
|
val scopeElements = Seq(
|
||||||
|
cons.getName,
|
||||||
|
methodDef.methodName.name,
|
||||||
|
annotation.name
|
||||||
|
)
|
||||||
|
val scopeName =
|
||||||
|
scopeElements.mkString(Constants.SCOPE_SEPARATOR)
|
||||||
|
val scopeInfo = annotation
|
||||||
|
.unsafeGetMetadata(
|
||||||
|
AliasAnalysis,
|
||||||
|
s"Missing scope information for annotation " +
|
||||||
|
s"${annotation.name} of method " +
|
||||||
|
scopeElements.init.mkString(Constants.SCOPE_SEPARATOR)
|
||||||
|
)
|
||||||
|
.unsafeAs[AliasAnalysis.Info.Scope.Root]
|
||||||
|
val dataflowInfo = annotation.unsafeGetMetadata(
|
||||||
|
DataflowAnalysis,
|
||||||
|
"Missing dataflow information for annotation " +
|
||||||
|
s"${annotation.name} of method " +
|
||||||
|
scopeElements.init.mkString(Constants.SCOPE_SEPARATOR)
|
||||||
|
)
|
||||||
|
val expressionProcessor = new ExpressionProcessor(
|
||||||
|
scopeName,
|
||||||
|
scopeInfo.graph,
|
||||||
|
scopeInfo.graph.rootScope,
|
||||||
|
dataflowInfo
|
||||||
|
)
|
||||||
|
val expressionNode =
|
||||||
|
expressionProcessor.run(annotation.expression)
|
||||||
|
val closureName =
|
||||||
|
s"<default::${expressionProcessor.scopeName}>"
|
||||||
|
val closureRootNode = ClosureRootNode.build(
|
||||||
|
language,
|
||||||
|
expressionProcessor.scope,
|
||||||
|
moduleScope,
|
||||||
|
expressionNode,
|
||||||
|
makeSection(moduleScope, annotation.location),
|
||||||
|
closureName,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
new RuntimeAnnotation(annotation.name, closureRootNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Right(
|
Right(
|
||||||
Some(
|
Some(
|
||||||
new RuntimeFunction(
|
new RuntimeFunction(
|
||||||
callTarget,
|
callTarget,
|
||||||
null,
|
null,
|
||||||
new FunctionSchema(arguments: _*)
|
new FunctionSchema(annotations.toArray, arguments: _*)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1655,7 +1739,7 @@ class IrToTruffle(
|
|||||||
* @param application the function application to generate code for
|
* @param application the function application to generate code for
|
||||||
* @return the truffle nodes corresponding to `application`
|
* @return the truffle nodes corresponding to `application`
|
||||||
*/
|
*/
|
||||||
def processApplication(
|
private def processApplication(
|
||||||
application: IR.Application,
|
application: IR.Application,
|
||||||
subjectToInstrumentation: Boolean
|
subjectToInstrumentation: Boolean
|
||||||
): RuntimeExpression =
|
): RuntimeExpression =
|
||||||
|
@ -21,7 +21,6 @@ class FreshNameSupply {
|
|||||||
|
|
||||||
/** Generates a name guaranteed not to exist in this program.
|
/** Generates a name guaranteed not to exist in this program.
|
||||||
*
|
*
|
||||||
* @param isReferent whether or not the name should be marked as referent.
|
|
||||||
* @param isMethod whether or not the name should represent a method name.
|
* @param isMethod whether or not the name should represent a method name.
|
||||||
* @return a new name
|
* @return a new name
|
||||||
*/
|
*/
|
||||||
|
@ -75,6 +75,7 @@ final class SuggestionBuilder[A: IndexedSource](
|
|||||||
arguments,
|
arguments,
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
|
_,
|
||||||
_
|
_
|
||||||
) =>
|
) =>
|
||||||
buildAtomConstructor(
|
buildAtomConstructor(
|
||||||
|
@ -11,6 +11,7 @@ import org.enso.interpreter.epb.EpbParser
|
|||||||
import org.enso.syntax.text.{AST, Debug, Location}
|
import org.enso.syntax.text.{AST, Debug, Location}
|
||||||
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
import scala.annotation.unused
|
import scala.annotation.unused
|
||||||
|
|
||||||
/** [[IR]] is a temporary and fairly unsophisticated internal representation
|
/** [[IR]] is a temporary and fairly unsophisticated internal representation
|
||||||
@ -1068,6 +1069,7 @@ object IR {
|
|||||||
*
|
*
|
||||||
* @param name the name of the atom
|
* @param name the name of the atom
|
||||||
* @param arguments the arguments to the atom constructor
|
* @param arguments the arguments to the atom constructor
|
||||||
|
* @param annotations the list of annotations
|
||||||
* @param location the source location that the node corresponds to
|
* @param location the source location that the node corresponds to
|
||||||
* @param passData the pass metadata associated with this node
|
* @param passData the pass metadata associated with this node
|
||||||
* @param diagnostics compiler diagnostics for this node
|
* @param diagnostics compiler diagnostics for this node
|
||||||
@ -1075,6 +1077,7 @@ object IR {
|
|||||||
sealed case class Data(
|
sealed case class Data(
|
||||||
name: IR.Name,
|
name: IR.Name,
|
||||||
arguments: List[DefinitionArgument],
|
arguments: List[DefinitionArgument],
|
||||||
|
annotations: List[IR.Name.GenericAnnotation],
|
||||||
override val location: Option[IdentifiedLocation],
|
override val location: Option[IdentifiedLocation],
|
||||||
override val passData: MetadataStorage = MetadataStorage(),
|
override val passData: MetadataStorage = MetadataStorage(),
|
||||||
override val diagnostics: DiagnosticStorage = DiagnosticStorage()
|
override val diagnostics: DiagnosticStorage = DiagnosticStorage()
|
||||||
@ -1086,6 +1089,7 @@ object IR {
|
|||||||
*
|
*
|
||||||
* @param name the name of the atom
|
* @param name the name of the atom
|
||||||
* @param arguments the arguments to the atom constructor
|
* @param arguments the arguments to the atom constructor
|
||||||
|
* @param annotations the list of annotations
|
||||||
* @param location the source location that the node corresponds to
|
* @param location the source location that the node corresponds to
|
||||||
* @param passData the pass metadata associated with this node
|
* @param passData the pass metadata associated with this node
|
||||||
* @param diagnostics compiler diagnostics for this node
|
* @param diagnostics compiler diagnostics for this node
|
||||||
@ -1093,14 +1097,22 @@ object IR {
|
|||||||
* @return a copy of `this`, updated with the specified values
|
* @return a copy of `this`, updated with the specified values
|
||||||
*/
|
*/
|
||||||
def copy(
|
def copy(
|
||||||
name: IR.Name = name,
|
name: IR.Name = name,
|
||||||
arguments: List[DefinitionArgument] = arguments,
|
arguments: List[DefinitionArgument] = arguments,
|
||||||
location: Option[IdentifiedLocation] = location,
|
annotations: List[IR.Name.GenericAnnotation] = annotations,
|
||||||
passData: MetadataStorage = passData,
|
location: Option[IdentifiedLocation] = location,
|
||||||
diagnostics: DiagnosticStorage = diagnostics,
|
passData: MetadataStorage = passData,
|
||||||
id: Identifier = id
|
diagnostics: DiagnosticStorage = diagnostics,
|
||||||
|
id: Identifier = id
|
||||||
): Data = {
|
): Data = {
|
||||||
val res = Data(name, arguments, location, passData, diagnostics)
|
val res = Data(
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
annotations,
|
||||||
|
location,
|
||||||
|
passData,
|
||||||
|
diagnostics
|
||||||
|
)
|
||||||
res.id = id
|
res.id = id
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -1142,17 +1154,19 @@ object IR {
|
|||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def mapExpressions(fn: Expression => Expression): Data = {
|
override def mapExpressions(fn: Expression => Expression): Data = {
|
||||||
copy(
|
copy(
|
||||||
name = name.mapExpressions(fn),
|
name = name.mapExpressions(fn),
|
||||||
arguments = arguments.map(_.mapExpressions(fn))
|
arguments = arguments.map(_.mapExpressions(fn)),
|
||||||
|
annotations = annotations.map(_.mapExpressions(fn))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
s"""
|
s"""
|
||||||
|IR.Module.Scope.Definition.Atom(
|
|IR.Module.Scope.Definition.Data(
|
||||||
|name = $name,
|
|name = $name,
|
||||||
|arguments = $arguments,
|
|arguments = $arguments,
|
||||||
|
|annotations = $annotations,
|
||||||
|location = $location,
|
|location = $location,
|
||||||
|passData = ${this.showPassData},
|
|passData = ${this.showPassData},
|
||||||
|diagnostics = $diagnostics,
|
|diagnostics = $diagnostics,
|
||||||
@ -1161,7 +1175,7 @@ object IR {
|
|||||||
|""".toSingleLine
|
|""".toSingleLine
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def children: List[IR] = name :: arguments
|
override def children: List[IR] = name :: arguments ::: annotations
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def showCode(indent: Int): String = {
|
override def showCode(indent: Int): String = {
|
||||||
@ -2754,20 +2768,37 @@ object IR {
|
|||||||
override def showCode(indent: Int): String = name
|
override def showCode(indent: Int): String = name
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The representation of an annotation name.
|
/** Base trait for annotations. */
|
||||||
|
sealed trait Annotation extends Name with IR.Module.Scope.Definition {
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def mapExpressions(fn: Expression => Expression): Annotation
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def setLocation(location: Option[IdentifiedLocation]): Annotation
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def duplicate(
|
||||||
|
keepLocations: Boolean = true,
|
||||||
|
keepMetadata: Boolean = true,
|
||||||
|
keepDiagnostics: Boolean = true,
|
||||||
|
keepIdentifiers: Boolean = false
|
||||||
|
): Annotation
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The representation of builtin annotation.
|
||||||
*
|
*
|
||||||
* @param name the annotation text of the name
|
* @param name the annotation text of the name
|
||||||
* @param location the source location that the node corresponds to
|
* @param location the source location that the node corresponds to
|
||||||
* @param passData the pass metadata associated with this node
|
* @param passData the pass metadata associated with this node
|
||||||
* @param diagnostics compiler diagnostics for this node
|
* @param diagnostics compiler diagnostics for this node
|
||||||
*/
|
*/
|
||||||
sealed case class Annotation(
|
sealed case class BuiltinAnnotation(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val location: Option[IdentifiedLocation],
|
override val location: Option[IdentifiedLocation],
|
||||||
override val passData: MetadataStorage = MetadataStorage(),
|
override val passData: MetadataStorage = MetadataStorage(),
|
||||||
override val diagnostics: DiagnosticStorage = DiagnosticStorage()
|
override val diagnostics: DiagnosticStorage = DiagnosticStorage()
|
||||||
) extends Name
|
) extends Annotation
|
||||||
with IR.Module.Scope.Definition
|
|
||||||
with IRKind.Primitive {
|
with IRKind.Primitive {
|
||||||
override protected var id: Identifier = randomId
|
override protected var id: Identifier = randomId
|
||||||
|
|
||||||
@ -2786,8 +2817,8 @@ object IR {
|
|||||||
passData: MetadataStorage = passData,
|
passData: MetadataStorage = passData,
|
||||||
diagnostics: DiagnosticStorage = diagnostics,
|
diagnostics: DiagnosticStorage = diagnostics,
|
||||||
id: Identifier = id
|
id: Identifier = id
|
||||||
): Annotation = {
|
): BuiltinAnnotation = {
|
||||||
val res = Annotation(name, location, passData, diagnostics)
|
val res = BuiltinAnnotation(name, location, passData, diagnostics)
|
||||||
res.id = id
|
res.id = id
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -2798,7 +2829,7 @@ object IR {
|
|||||||
keepMetadata: Boolean = true,
|
keepMetadata: Boolean = true,
|
||||||
keepDiagnostics: Boolean = true,
|
keepDiagnostics: Boolean = true,
|
||||||
keepIdentifiers: Boolean = false
|
keepIdentifiers: Boolean = false
|
||||||
): Annotation =
|
): BuiltinAnnotation =
|
||||||
copy(
|
copy(
|
||||||
location = if (keepLocations) location else None,
|
location = if (keepLocations) location else None,
|
||||||
passData =
|
passData =
|
||||||
@ -2811,17 +2842,19 @@ object IR {
|
|||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def setLocation(
|
override def setLocation(
|
||||||
location: Option[IdentifiedLocation]
|
location: Option[IdentifiedLocation]
|
||||||
): Annotation =
|
): BuiltinAnnotation =
|
||||||
copy(location = location)
|
copy(location = location)
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def mapExpressions(fn: Expression => Expression): Annotation =
|
override def mapExpressions(
|
||||||
|
fn: Expression => Expression
|
||||||
|
): BuiltinAnnotation =
|
||||||
this
|
this
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
s"""
|
s"""
|
||||||
|IR.Name.Annotation(
|
|IR.Name.BuiltinAnnotation(
|
||||||
|name = $name,
|
|name = $name,
|
||||||
|location = $location,
|
|location = $location,
|
||||||
|passData = ${this.showPassData},
|
|passData = ${this.showPassData},
|
||||||
@ -2834,7 +2867,97 @@ object IR {
|
|||||||
override def children: List[IR] = List()
|
override def children: List[IR] = List()
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def showCode(indent: Int): String = name
|
override def showCode(indent: Int): String = s"@$name"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common annotations of form `@name expression`.
|
||||||
|
*
|
||||||
|
* @param name the annotation text of the name
|
||||||
|
* @param expression the annotation expression
|
||||||
|
* @param location the source location that the node corresponds to
|
||||||
|
* @param passData the pass metadata associated with this node
|
||||||
|
* @param diagnostics compiler diagnostics for this node
|
||||||
|
*/
|
||||||
|
sealed case class GenericAnnotation(
|
||||||
|
override val name: String,
|
||||||
|
expression: Expression,
|
||||||
|
override val location: Option[IdentifiedLocation],
|
||||||
|
override val passData: MetadataStorage = MetadataStorage(),
|
||||||
|
override val diagnostics: DiagnosticStorage = DiagnosticStorage()
|
||||||
|
) extends Annotation {
|
||||||
|
override protected var id: Identifier = randomId
|
||||||
|
|
||||||
|
/** Creates a copy of `this`.
|
||||||
|
*
|
||||||
|
* @param name the annotation text of the name
|
||||||
|
* @param expression the annotation expression
|
||||||
|
* @param location the source location that the node corresponds to
|
||||||
|
* @param passData the pass metadata associated with this node
|
||||||
|
* @param diagnostics compiler diagnostics for this node
|
||||||
|
* @param id the identifier for the new node
|
||||||
|
* @return a copy of `this`, updated with the specified values
|
||||||
|
*/
|
||||||
|
def copy(
|
||||||
|
name: String = name,
|
||||||
|
expression: Expression = expression,
|
||||||
|
location: Option[IdentifiedLocation] = location,
|
||||||
|
passData: MetadataStorage = passData,
|
||||||
|
diagnostics: DiagnosticStorage = diagnostics,
|
||||||
|
id: Identifier = id
|
||||||
|
): GenericAnnotation = {
|
||||||
|
val res =
|
||||||
|
GenericAnnotation(name, expression, location, passData, diagnostics)
|
||||||
|
res.id = id
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def duplicate(
|
||||||
|
keepLocations: Boolean = true,
|
||||||
|
keepMetadata: Boolean = true,
|
||||||
|
keepDiagnostics: Boolean = true,
|
||||||
|
keepIdentifiers: Boolean = false
|
||||||
|
): GenericAnnotation =
|
||||||
|
copy(
|
||||||
|
location = if (keepLocations) location else None,
|
||||||
|
passData =
|
||||||
|
if (keepMetadata) passData.duplicate else MetadataStorage(),
|
||||||
|
diagnostics =
|
||||||
|
if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(),
|
||||||
|
id = if (keepIdentifiers) id else randomId
|
||||||
|
)
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def setLocation(
|
||||||
|
location: Option[IdentifiedLocation]
|
||||||
|
): GenericAnnotation =
|
||||||
|
copy(location = location)
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def mapExpressions(
|
||||||
|
fn: Expression => Expression
|
||||||
|
): GenericAnnotation =
|
||||||
|
copy(expression = fn(expression))
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def toString: String =
|
||||||
|
s"""
|
||||||
|
|IR.Name.GenericAnnotation(
|
||||||
|
|name = $name,
|
||||||
|
|expression = $expression,
|
||||||
|
|location = $location,
|
||||||
|
|passData = ${this.showPassData},
|
||||||
|
|diagnostics = $diagnostics,
|
||||||
|
|id = $id
|
||||||
|
|)
|
||||||
|
|""".toSingleLine
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def children: List[IR] = List(expression)
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def showCode(indent: Int): String =
|
||||||
|
s"@$name ${expression.showCode(indent)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A representation of the name `self`, used to refer to the current type.
|
/** A representation of the name `self`, used to refer to the current type.
|
||||||
@ -4420,7 +4543,7 @@ object IR {
|
|||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
s"""
|
s"""
|
||||||
|IR.Function.Sugar(
|
|IR.Function.Binding(
|
||||||
|name = $name,
|
|name = $name,
|
||||||
|arguments = $arguments,
|
|arguments = $arguments,
|
||||||
|body = $body,
|
|body = $body,
|
||||||
@ -7512,7 +7635,7 @@ object IR {
|
|||||||
|
|
||||||
/** A representation of an Enso syntax error.
|
/** A representation of an Enso syntax error.
|
||||||
*
|
*
|
||||||
* @param ast the erroneous AST
|
* @param at the erroneous AST
|
||||||
* @param reason the cause of this error
|
* @param reason the cause of this error
|
||||||
* @param passData the pass metadata associated with this node
|
* @param passData the pass metadata associated with this node
|
||||||
* @param diagnostics compiler diagnostics for this node
|
* @param diagnostics compiler diagnostics for this node
|
||||||
@ -8863,7 +8986,7 @@ object IR {
|
|||||||
@throws[CompilerError]
|
@throws[CompilerError]
|
||||||
def unsafeGetMetadata[K <: IRPass](
|
def unsafeGetMetadata[K <: IRPass](
|
||||||
pass: IRPass,
|
pass: IRPass,
|
||||||
msg: String
|
msg: => String
|
||||||
): pass.Metadata = {
|
): pass.Metadata = {
|
||||||
ir.passData.getUnsafe(pass)(msg)
|
ir.passData.getUnsafe(pass)(msg)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ class MetadataStorage(
|
|||||||
@throws[CompilerError]
|
@throws[CompilerError]
|
||||||
def getUnsafe[K <: IRPass](
|
def getUnsafe[K <: IRPass](
|
||||||
pass: K
|
pass: K
|
||||||
)(msg: String = s"Missing metadata for pass $pass"): pass.Metadata = {
|
)(msg: => String = s"Missing metadata for pass $pass"): pass.Metadata = {
|
||||||
get(pass).getOrElse(throw new CompilerError(msg))
|
get(pass).getOrElse(throw new CompilerError(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class PassManager(
|
|||||||
* @throws CompilerError if a valid pass ordering cannot be computed
|
* @throws CompilerError if a valid pass ordering cannot be computed
|
||||||
* @return a valid pass ordering for the compiler, based on `passes`
|
* @return a valid pass ordering for the compiler, based on `passes`
|
||||||
*/
|
*/
|
||||||
def verifyPassOrdering(passes: List[IRPass]): List[IRPass] = {
|
private def verifyPassOrdering(passes: List[IRPass]): List[IRPass] = {
|
||||||
var validPasses: Set[IRPass] = Set()
|
var validPasses: Set[IRPass] = Set()
|
||||||
|
|
||||||
passes.foreach(pass => {
|
passes.foreach(pass => {
|
||||||
@ -161,7 +161,7 @@ class PassManager(
|
|||||||
* @param passGroup the pass group being run
|
* @param passGroup the pass group being run
|
||||||
* @return `true` if the condition holds, otherwise `false`
|
* @return `true` if the condition holds, otherwise `false`
|
||||||
*/
|
*/
|
||||||
def isLastRunOf(
|
private def isLastRunOf(
|
||||||
indexOfPassInGroup: Int,
|
indexOfPassInGroup: Int,
|
||||||
pass: IRPass,
|
pass: IRPass,
|
||||||
passGroup: PassGroup
|
passGroup: PassGroup
|
||||||
|
@ -14,7 +14,6 @@ import org.enso.syntax.text.Debug
|
|||||||
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.collection.mutable.ListBuffer
|
|
||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
/** This pass performs scope identification and analysis, as well as symbol
|
/** This pass performs scope identification and analysis, as well as symbol
|
||||||
@ -257,12 +256,23 @@ case object AliasAnalysis extends IRPass {
|
|||||||
),
|
),
|
||||||
members = t.members.map(d => {
|
members = t.members.map(d => {
|
||||||
val graph = new Graph
|
val graph = new Graph
|
||||||
d.copy(arguments =
|
d.copy(
|
||||||
analyseArgumentDefs(
|
arguments = analyseArgumentDefs(
|
||||||
d.arguments,
|
d.arguments,
|
||||||
graph,
|
graph,
|
||||||
graph.rootScope
|
graph.rootScope
|
||||||
)
|
),
|
||||||
|
annotations = d.annotations.map { ann =>
|
||||||
|
ann
|
||||||
|
.copy(
|
||||||
|
expression = analyseExpression(
|
||||||
|
ann.expression,
|
||||||
|
topLevelGraph,
|
||||||
|
topLevelGraph.rootScope
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.updateMetadata(this -->> Info.Scope.Root(topLevelGraph))
|
||||||
|
}
|
||||||
).updateMetadata(this -->> Info.Scope.Root(graph))
|
).updateMetadata(this -->> Info.Scope.Root(graph))
|
||||||
})
|
})
|
||||||
).updateMetadata(this -->> Info.Scope.Root(topLevelGraph))
|
).updateMetadata(this -->> Info.Scope.Root(topLevelGraph))
|
||||||
@ -280,11 +290,21 @@ case object AliasAnalysis extends IRPass {
|
|||||||
"Type signatures should not exist at the top level during " +
|
"Type signatures should not exist at the top level during " +
|
||||||
"alias analysis."
|
"alias analysis."
|
||||||
)
|
)
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of alias " +
|
"Annotations should already be associated by the point of alias " +
|
||||||
"analysis."
|
"analysis."
|
||||||
)
|
)
|
||||||
|
case ann: IR.Name.GenericAnnotation =>
|
||||||
|
ann
|
||||||
|
.copy(expression =
|
||||||
|
analyseExpression(
|
||||||
|
ann.expression,
|
||||||
|
topLevelGraph,
|
||||||
|
topLevelGraph.rootScope
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.updateMetadata(this -->> Info.Scope.Root(topLevelGraph))
|
||||||
case err: IR.Error => err
|
case err: IR.Error => err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -561,7 +581,7 @@ case object AliasAnalysis extends IRPass {
|
|||||||
* @param parentScope the scope in which the arguments are defined
|
* @param parentScope the scope in which the arguments are defined
|
||||||
* @return `args`, with aliasing information attached to each argument
|
* @return `args`, with aliasing information attached to each argument
|
||||||
*/
|
*/
|
||||||
def analyseCallArguments(
|
private def analyseCallArguments(
|
||||||
args: List[IR.CallArgument],
|
args: List[IR.CallArgument],
|
||||||
graph: AliasAnalysis.Graph,
|
graph: AliasAnalysis.Graph,
|
||||||
parentScope: AliasAnalysis.Graph.Scope
|
parentScope: AliasAnalysis.Graph.Scope
|
||||||
@ -1207,7 +1227,8 @@ case object AliasAnalysis extends IRPass {
|
|||||||
mapping.get(this) match {
|
mapping.get(this) match {
|
||||||
case Some(newCorrespondingScope) => newCorrespondingScope
|
case Some(newCorrespondingScope) => newCorrespondingScope
|
||||||
case None =>
|
case None =>
|
||||||
val childScopeCopies: mutable.ListBuffer[Scope] = ListBuffer()
|
val childScopeCopies: mutable.ListBuffer[Scope] =
|
||||||
|
mutable.ListBuffer()
|
||||||
this.childScopes.foreach(scope =>
|
this.childScopes.foreach(scope =>
|
||||||
childScopeCopies += scope.deepCopy(mapping)
|
childScopeCopies += scope.deepCopy(mapping)
|
||||||
)
|
)
|
||||||
|
@ -117,12 +117,13 @@ case object CachePreferenceAnalysis extends IRPass {
|
|||||||
"Type signatures should not exist at the top level during " +
|
"Type signatures should not exist at the top level during " +
|
||||||
"cache preference analysis."
|
"cache preference analysis."
|
||||||
)
|
)
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"cache preference analysis."
|
"cache preference analysis."
|
||||||
)
|
)
|
||||||
case err: IR.Error => err
|
case ann: IR.Name.GenericAnnotation => ann
|
||||||
|
case err: IR.Error => err
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Performs preference analysis on an arbitrary expression.
|
/** Performs preference analysis on an arbitrary expression.
|
||||||
|
@ -149,22 +149,21 @@ case object DataflowAnalysis extends IRPass {
|
|||||||
info.dependencies.updateAt(tpDep, Set(paramDep))
|
info.dependencies.updateAt(tpDep, Set(paramDep))
|
||||||
analyseDefinitionArgument(param, info)
|
analyseDefinitionArgument(param, info)
|
||||||
}
|
}
|
||||||
val newMembers = members.map {
|
val newMembers = members.map { data =>
|
||||||
case data @ IR.Module.Scope.Definition.Data(_, arguments, _, _, _) =>
|
val dataDep = asStatic(data)
|
||||||
val dataDep = asStatic(data)
|
info.dependents.updateAt(dataDep, Set(tpDep))
|
||||||
info.dependents.updateAt(dataDep, Set(tpDep))
|
info.dependencies.updateAt(tpDep, Set(dataDep))
|
||||||
info.dependencies.updateAt(tpDep, Set(dataDep))
|
data.arguments.foreach(arg => {
|
||||||
arguments.foreach(arg => {
|
val argDep = asStatic(arg)
|
||||||
val argDep = asStatic(arg)
|
info.dependents.updateAt(argDep, Set(dataDep))
|
||||||
info.dependents.updateAt(argDep, Set(dataDep))
|
info.dependencies.updateAt(dataDep, Set(argDep))
|
||||||
info.dependencies.updateAt(dataDep, Set(argDep))
|
})
|
||||||
})
|
|
||||||
|
|
||||||
data
|
data
|
||||||
.copy(
|
.copy(
|
||||||
arguments = arguments.map(analyseDefinitionArgument(_, info))
|
arguments = data.arguments.map(analyseDefinitionArgument(_, info))
|
||||||
)
|
)
|
||||||
.updateMetadata(this -->> info)
|
.updateMetadata(this -->> info)
|
||||||
}
|
}
|
||||||
tp.copy(params = newParams, members = newMembers)
|
tp.copy(params = newParams, members = newMembers)
|
||||||
.updateMetadata(this -->> info)
|
.updateMetadata(this -->> info)
|
||||||
@ -187,11 +186,15 @@ case object DataflowAnalysis extends IRPass {
|
|||||||
"Type signatures should not exist at the top level during " +
|
"Type signatures should not exist at the top level during " +
|
||||||
"dataflow analysis."
|
"dataflow analysis."
|
||||||
)
|
)
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"dataflow analysis."
|
"dataflow analysis."
|
||||||
)
|
)
|
||||||
|
case ann: IR.Name.GenericAnnotation =>
|
||||||
|
ann
|
||||||
|
.copy(expression = analyseExpression(ann.expression, info))
|
||||||
|
.updateMetadata(this -->> info)
|
||||||
case err: IR.Error => err
|
case err: IR.Error => err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ case object TailCall extends IRPass {
|
|||||||
* @param definition the top-level definition to analyse
|
* @param definition the top-level definition to analyse
|
||||||
* @return `definition`, annotated with tail call information
|
* @return `definition`, annotated with tail call information
|
||||||
*/
|
*/
|
||||||
def analyseModuleBinding(
|
private def analyseModuleBinding(
|
||||||
definition: IR.Module.Scope.Definition
|
definition: IR.Module.Scope.Definition
|
||||||
): IR.Module.Scope.Definition = {
|
): IR.Module.Scope.Definition = {
|
||||||
definition match {
|
definition match {
|
||||||
@ -126,11 +126,17 @@ case object TailCall extends IRPass {
|
|||||||
"Type signatures should not exist at the top level during " +
|
"Type signatures should not exist at the top level during " +
|
||||||
"tail call analysis."
|
"tail call analysis."
|
||||||
)
|
)
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"tail call analysis."
|
"tail call analysis."
|
||||||
)
|
)
|
||||||
|
case ann: IR.Name.GenericAnnotation =>
|
||||||
|
ann
|
||||||
|
.copy(expression =
|
||||||
|
analyseExpression(ann.expression, isInTailPosition = true)
|
||||||
|
)
|
||||||
|
.updateMetadata(this -->> TailPosition.Tail)
|
||||||
case err: IR.Error => err
|
case err: IR.Error => err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@ import org.enso.compiler.pass.resolve.{
|
|||||||
}
|
}
|
||||||
import org.enso.compiler.core.ir.MetadataStorage._
|
import org.enso.compiler.core.ir.MetadataStorage._
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** Desugars complex type definitions to simple type definitions in the module
|
/** Desugars complex type definitions to simple type definitions in the module
|
||||||
* scope.
|
* scope.
|
||||||
*
|
*
|
||||||
@ -75,7 +73,7 @@ case object ComplexType extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runModule(
|
override def runModule(
|
||||||
ir: IR.Module,
|
ir: IR.Module,
|
||||||
@unused moduleContext: ModuleContext
|
moduleContext: ModuleContext
|
||||||
): IR.Module =
|
): IR.Module =
|
||||||
ir.copy(
|
ir.copy(
|
||||||
bindings = ir.bindings.flatMap {
|
bindings = ir.bindings.flatMap {
|
||||||
@ -94,12 +92,12 @@ case object ComplexType extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runExpression(
|
override def runExpression(
|
||||||
ir: IR.Expression,
|
ir: IR.Expression,
|
||||||
@unused inlineContext: InlineContext
|
inlineContext: InlineContext
|
||||||
): IR.Expression = ir
|
): IR.Expression = ir
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -110,12 +108,25 @@ case object ComplexType extends IRPass {
|
|||||||
* @param typ the type definition to desugar
|
* @param typ the type definition to desugar
|
||||||
* @return the top-level definitions corresponding to the desugaring of `typ`
|
* @return the top-level definitions corresponding to the desugaring of `typ`
|
||||||
*/
|
*/
|
||||||
def desugarComplexType(
|
private def desugarComplexType(
|
||||||
typ: IR.Module.Scope.Definition.SugaredType
|
typ: IR.Module.Scope.Definition.SugaredType
|
||||||
): List[IR.Module.Scope.Definition] = {
|
): List[IR.Module.Scope.Definition] = {
|
||||||
val annotations = typ.getMetadata(ModuleAnnotations)
|
val annotations = typ.getMetadata(ModuleAnnotations)
|
||||||
|
var lastAnnotations = Seq.empty[IR.Name.GenericAnnotation]
|
||||||
|
var seenAnnotations = Set.empty[IR.Name.GenericAnnotation]
|
||||||
val atomDefs = typ.body
|
val atomDefs = typ.body
|
||||||
.collect { case d: IR.Module.Scope.Definition.Data => d }
|
.flatMap {
|
||||||
|
case ann: IR.Name.GenericAnnotation =>
|
||||||
|
lastAnnotations :+= ann
|
||||||
|
None
|
||||||
|
case d: IR.Module.Scope.Definition.Data =>
|
||||||
|
val res = Some(d.copy(annotations = d.annotations ++ lastAnnotations))
|
||||||
|
seenAnnotations ++= lastAnnotations
|
||||||
|
lastAnnotations = Seq()
|
||||||
|
res
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
// TODO[MK] this is probably removable
|
// TODO[MK] this is probably removable
|
||||||
.map(atom =>
|
.map(atom =>
|
||||||
annotations
|
annotations
|
||||||
@ -133,6 +144,7 @@ case object ComplexType extends IRPass {
|
|||||||
|
|
||||||
val remainingEntities = typ.body.filterNot {
|
val remainingEntities = typ.body.filterNot {
|
||||||
case _: IR.Module.Scope.Definition.Data => true
|
case _: IR.Module.Scope.Definition.Data => true
|
||||||
|
case ann: IR.Name.GenericAnnotation => seenAnnotations.contains(ann)
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +197,8 @@ case object ComplexType extends IRPass {
|
|||||||
matchSignaturesAndGenerate(name, binding)
|
matchSignaturesAndGenerate(name, binding)
|
||||||
case funSugar @ IR.Function.Binding(name, _, _, _, _, _, _) =>
|
case funSugar @ IR.Function.Binding(name, _, _, _, _, _, _) =>
|
||||||
matchSignaturesAndGenerate(name, funSugar)
|
matchSignaturesAndGenerate(name, funSugar)
|
||||||
case err: IR.Error => Seq(err)
|
case err: IR.Error => Seq(err)
|
||||||
|
case ann: IR.Name.GenericAnnotation => Seq(ann)
|
||||||
case _ =>
|
case _ =>
|
||||||
throw new CompilerError("Unexpected IR node in complex type body.")
|
throw new CompilerError("Unexpected IR node in complex type body.")
|
||||||
}
|
}
|
||||||
@ -217,11 +230,11 @@ case object ComplexType extends IRPass {
|
|||||||
* The signature _must_ correctly match the method definition.
|
* The signature _must_ correctly match the method definition.
|
||||||
*
|
*
|
||||||
* @param ir the definition to generate a method from
|
* @param ir the definition to generate a method from
|
||||||
* @param names the names on which the method is being defined
|
* @param typeName the type name on which the method is being defined
|
||||||
* @param signature the type signature for the method, if it exists
|
* @param signature the type signature for the method, if it exists
|
||||||
* @return `ir` as a method
|
* @return `ir` as a method
|
||||||
*/
|
*/
|
||||||
def genMethodDef(
|
private def genMethodDef(
|
||||||
ir: IR,
|
ir: IR,
|
||||||
typeName: IR.Name,
|
typeName: IR.Name,
|
||||||
signature: Option[IR.Type.Ascription]
|
signature: Option[IR.Type.Ascription]
|
||||||
@ -280,7 +293,7 @@ case object ComplexType extends IRPass {
|
|||||||
* @param signature the method's type signature, if it exists
|
* @param signature the method's type signature, if it exists
|
||||||
* @return a top-level method definition
|
* @return a top-level method definition
|
||||||
*/
|
*/
|
||||||
def genForName(
|
private def genForName(
|
||||||
typeName: IR.Name,
|
typeName: IR.Name,
|
||||||
name: IR.Name,
|
name: IR.Name,
|
||||||
args: List[IR.DefinitionArgument],
|
args: List[IR.DefinitionArgument],
|
||||||
|
@ -18,8 +18,6 @@ import org.enso.compiler.pass.optimise.LambdaConsolidate
|
|||||||
import org.enso.compiler.pass.resolve.IgnoredBindings
|
import org.enso.compiler.pass.resolve.IgnoredBindings
|
||||||
import org.enso.interpreter.Constants
|
import org.enso.interpreter.Constants
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** This pass handles the desugaring of long-form function and method
|
/** This pass handles the desugaring of long-form function and method
|
||||||
* definitions into standard bindings using lambdas.
|
* definitions into standard bindings using lambdas.
|
||||||
*
|
*
|
||||||
@ -64,7 +62,7 @@ case object FunctionBinding extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runModule(
|
override def runModule(
|
||||||
ir: IR.Module,
|
ir: IR.Module,
|
||||||
@unused moduleContext: ModuleContext
|
moduleContext: ModuleContext
|
||||||
): IR.Module = ir.copy(bindings = ir.bindings.map(desugarModuleSymbol))
|
): IR.Module = ir.copy(bindings = ir.bindings.map(desugarModuleSymbol))
|
||||||
|
|
||||||
/** Runs desugaring of function bindings on an arbitrary expression.
|
/** Runs desugaring of function bindings on an arbitrary expression.
|
||||||
@ -77,12 +75,12 @@ case object FunctionBinding extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runExpression(
|
override def runExpression(
|
||||||
ir: IR.Expression,
|
ir: IR.Expression,
|
||||||
@unused inlineContext: InlineContext
|
inlineContext: InlineContext
|
||||||
): IR.Expression = desugarExpression(ir)
|
): IR.Expression = desugarExpression(ir)
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -319,13 +317,14 @@ case object FunctionBinding extends IRPass {
|
|||||||
"Documentation should not be present during function binding" +
|
"Documentation should not be present during function binding" +
|
||||||
"desugaring."
|
"desugaring."
|
||||||
)
|
)
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"function binding desugaring."
|
"function binding desugaring."
|
||||||
)
|
)
|
||||||
case a: IR.Type.Ascription => a
|
case a: IR.Name.GenericAnnotation => a
|
||||||
case e: IR.Error => e
|
case a: IR.Type.Ascription => a
|
||||||
|
case e: IR.Error => e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ import org.enso.compiler.exception.CompilerError
|
|||||||
import org.enso.compiler.pass.IRPass
|
import org.enso.compiler.pass.IRPass
|
||||||
import org.enso.compiler.pass.desugar.{ComplexType, GenerateMethodBodies}
|
import org.enso.compiler.pass.desugar.{ComplexType, GenerateMethodBodies}
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** Associates doc comments with the commented entities as metadata.
|
/** Associates doc comments with the commented entities as metadata.
|
||||||
*
|
*
|
||||||
* If the first module definition is a documentation comment, it is treated as
|
* If the first module definition is a documentation comment, it is treated as
|
||||||
@ -61,7 +59,7 @@ case object DocumentationComments extends IRPass {
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -94,6 +92,8 @@ case object DocumentationComments extends IRPass {
|
|||||||
private def resolveList[T <: IR](items: List[T]): List[T] = {
|
private def resolveList[T <: IR](items: List[T]): List[T] = {
|
||||||
var lastDoc: Option[IR.Comment.Documentation] = None
|
var lastDoc: Option[IR.Comment.Documentation] = None
|
||||||
items.flatMap {
|
items.flatMap {
|
||||||
|
case annotation: IR.Name.Annotation =>
|
||||||
|
Some(annotation.asInstanceOf[T])
|
||||||
case doc: IR.Comment.Documentation =>
|
case doc: IR.Comment.Documentation =>
|
||||||
lastDoc = Some(doc)
|
lastDoc = Some(doc)
|
||||||
None
|
None
|
||||||
@ -158,10 +158,11 @@ case object DocumentationComments extends IRPass {
|
|||||||
method.copy(body = resolveExpression(method.body))
|
method.copy(body = resolveExpression(method.body))
|
||||||
case tpe: IR.Module.Scope.Definition.SugaredType =>
|
case tpe: IR.Module.Scope.Definition.SugaredType =>
|
||||||
tpe.copy(body = resolveList(tpe.body).map(resolveIr))
|
tpe.copy(body = resolveList(tpe.body).map(resolveIr))
|
||||||
case doc: IR.Comment.Documentation => doc
|
case doc: IR.Comment.Documentation => doc
|
||||||
case tySig: IR.Type.Ascription => tySig
|
case tySig: IR.Type.Ascription => tySig
|
||||||
case err: IR.Error => err
|
case err: IR.Error => err
|
||||||
case _: IR.Name.Annotation =>
|
case ann: IR.Name.GenericAnnotation => ann
|
||||||
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"documentation comment resolution."
|
"documentation comment resolution."
|
||||||
|
@ -8,8 +8,6 @@ import org.enso.compiler.pass.IRPass
|
|||||||
import org.enso.compiler.pass.analyse.AliasAnalysis
|
import org.enso.compiler.pass.analyse.AliasAnalysis
|
||||||
import org.enso.compiler.pass.resolve.ModuleAnnotations.Annotations
|
import org.enso.compiler.pass.resolve.ModuleAnnotations.Annotations
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
case object ExpressionAnnotations extends IRPass {
|
case object ExpressionAnnotations extends IRPass {
|
||||||
val tailCallName = "@Tail_Call"
|
val tailCallName = "@Tail_Call"
|
||||||
val builtinMethodName = "@Builtin_Method"
|
val builtinMethodName = "@Builtin_Method"
|
||||||
@ -62,7 +60,7 @@ case object ExpressionAnnotations extends IRPass {
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -71,7 +69,7 @@ case object ExpressionAnnotations extends IRPass {
|
|||||||
): IR.Expression =
|
): IR.Expression =
|
||||||
ir.transformExpressions {
|
ir.transformExpressions {
|
||||||
case app @ IR.Application.Prefix(
|
case app @ IR.Application.Prefix(
|
||||||
ann: IR.Name.Annotation,
|
ann: IR.Name.BuiltinAnnotation,
|
||||||
arguments,
|
arguments,
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
@ -104,7 +102,7 @@ case object ExpressionAnnotations extends IRPass {
|
|||||||
IR.Error.Resolution(ann, IR.Error.Resolution.UnknownAnnotation)
|
IR.Error.Resolution(ann, IR.Error.Resolution.UnknownAnnotation)
|
||||||
app.copy(function = err)
|
app.copy(function = err)
|
||||||
}
|
}
|
||||||
case ann: IR.Name.Annotation =>
|
case ann: IR.Name.BuiltinAnnotation =>
|
||||||
if (isKnownAnnotation(ann.name)) {
|
if (isKnownAnnotation(ann.name)) {
|
||||||
IR.Error.Resolution(
|
IR.Error.Resolution(
|
||||||
ann,
|
ann,
|
||||||
@ -120,7 +118,7 @@ case object ExpressionAnnotations extends IRPass {
|
|||||||
* @param name the annotation name to check
|
* @param name the annotation name to check
|
||||||
* @return `true` if `name` is a known annotation, otherwise `false`
|
* @return `true` if `name` is a known annotation, otherwise `false`
|
||||||
*/
|
*/
|
||||||
def isKnownAnnotation(name: String): Boolean = {
|
private def isKnownAnnotation(name: String): Boolean = {
|
||||||
knownAnnotations.contains(name)
|
knownAnnotations.contains(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
package org.enso.compiler.pass.resolve
|
||||||
|
|
||||||
|
import org.enso.compiler.context.{InlineContext, ModuleContext}
|
||||||
|
import org.enso.compiler.core.IR
|
||||||
|
import org.enso.compiler.core.IR.Module.Scope.Definition
|
||||||
|
import org.enso.compiler.core.ir.MetadataStorage._
|
||||||
|
import org.enso.compiler.exception.CompilerError
|
||||||
|
import org.enso.compiler.pass.IRPass
|
||||||
|
|
||||||
|
/** A pass responsible for the discovery of [[IR.Name.GenericAnnotation]]
|
||||||
|
* annotations, and for associating them with the corresponding construct.
|
||||||
|
*
|
||||||
|
* Compilation pipeline of generic annotations:
|
||||||
|
* - [[ModuleAnnotations]] pass ignores generic annotations and leaves them in
|
||||||
|
* the tree so that the consequent passes are able to process the annotation
|
||||||
|
* expression.
|
||||||
|
* - [[org.enso.compiler.pass.desugar.ComplexType]] pass associates generic
|
||||||
|
* annotations with the type constructor definitions.
|
||||||
|
* - [[GenericAnnotations]] pass associates generic annotations that are left
|
||||||
|
* in the tree with the appropriate definitions.
|
||||||
|
*/
|
||||||
|
case object GenericAnnotations extends IRPass {
|
||||||
|
override type Metadata = ModuleAnnotations.Annotations
|
||||||
|
override type Config = IRPass.Configuration.Default
|
||||||
|
override val precursorPasses: Seq[IRPass] = Seq()
|
||||||
|
override val invalidatedPasses: Seq[IRPass] = Seq()
|
||||||
|
|
||||||
|
/** Resolves annotations.
|
||||||
|
*
|
||||||
|
* @param ir the Enso IR to process
|
||||||
|
* @param moduleContext a context object that contains the information needed
|
||||||
|
* to process a module
|
||||||
|
* @return `ir`, possibly having made transformations or annotations to that
|
||||||
|
* IR.
|
||||||
|
*/
|
||||||
|
override def runModule(
|
||||||
|
ir: IR.Module,
|
||||||
|
moduleContext: ModuleContext
|
||||||
|
): IR.Module = {
|
||||||
|
var lastAnnotations: Seq[IR.Name.GenericAnnotation] = Seq()
|
||||||
|
val newBindings = ir.bindings.map {
|
||||||
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
|
throw new CompilerError(
|
||||||
|
s"Builtin annotations should not be present at generic annotations pass."
|
||||||
|
)
|
||||||
|
case _: Definition.SugaredType =>
|
||||||
|
throw new CompilerError(
|
||||||
|
s"Sugared types should not be present at generic annotations pass."
|
||||||
|
)
|
||||||
|
case _: IR.Comment =>
|
||||||
|
throw new CompilerError(
|
||||||
|
"Comments should not be present at generic annotations pass."
|
||||||
|
)
|
||||||
|
case ann: IR.Name.GenericAnnotation =>
|
||||||
|
lastAnnotations :+= ann
|
||||||
|
None
|
||||||
|
case entity =>
|
||||||
|
val res = Some(
|
||||||
|
entity.updateMetadata(
|
||||||
|
this -->> ModuleAnnotations.Annotations(lastAnnotations)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
lastAnnotations = Seq()
|
||||||
|
res
|
||||||
|
}
|
||||||
|
ir.copy(bindings = newBindings.flatten)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Execute the pass on an expression.
|
||||||
|
*
|
||||||
|
* As the pass only deals with module-level annotations this is a no-op.
|
||||||
|
*
|
||||||
|
* @param ir the Enso IR to process
|
||||||
|
* @param inlineContext a context object that contains the information needed
|
||||||
|
* for inline evaluation
|
||||||
|
* @return `ir`, possibly having made transformations or annotations to that
|
||||||
|
* IR.
|
||||||
|
*/
|
||||||
|
override def runExpression(
|
||||||
|
ir: IR.Expression,
|
||||||
|
inlineContext: InlineContext
|
||||||
|
): IR.Expression = ir
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
|
sourceIr: T,
|
||||||
|
copyOfIr: T
|
||||||
|
): T = copyOfIr
|
||||||
|
}
|
@ -15,8 +15,6 @@ import org.enso.compiler.pass.IRPass
|
|||||||
import org.enso.compiler.pass.analyse.{AliasAnalysis, BindingAnalysis}
|
import org.enso.compiler.pass.analyse.{AliasAnalysis, BindingAnalysis}
|
||||||
import org.enso.interpreter.Constants
|
import org.enso.interpreter.Constants
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** Resolves name occurences in non-pattern contexts.
|
/** Resolves name occurences in non-pattern contexts.
|
||||||
*
|
*
|
||||||
* 1. Attaches resolution metadata to encountered constructors, modules,
|
* 1. Attaches resolution metadata to encountered constructors, modules,
|
||||||
@ -61,7 +59,7 @@ case object GlobalNames extends IRPass {
|
|||||||
)
|
)
|
||||||
val freshNameSupply = moduleContext.freshNameSupply.getOrElse(
|
val freshNameSupply = moduleContext.freshNameSupply.getOrElse(
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"No fresh name supply passed to UppercaseNames resolver."
|
"No fresh name supply passed to GlobalNames resolver."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val new_bindings =
|
val new_bindings =
|
||||||
@ -96,7 +94,7 @@ case object GlobalNames extends IRPass {
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -139,7 +137,7 @@ case object GlobalNames extends IRPass {
|
|||||||
freshNameSupply: FreshNameSupply,
|
freshNameSupply: FreshNameSupply,
|
||||||
selfTypeResolution: Option[Resolution],
|
selfTypeResolution: Option[Resolution],
|
||||||
isInsideApplication: Boolean = false
|
isInsideApplication: Boolean = false
|
||||||
): IR.Expression =
|
): IR.Expression = {
|
||||||
ir.transformExpressions {
|
ir.transformExpressions {
|
||||||
case selfTp: IR.Name.SelfType =>
|
case selfTp: IR.Name.SelfType =>
|
||||||
selfTypeResolution
|
selfTypeResolution
|
||||||
@ -239,6 +237,7 @@ case object GlobalNames extends IRPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private def resolveReferantApplication(
|
private def resolveReferantApplication(
|
||||||
app: IR.Application.Prefix,
|
app: IR.Application.Prefix,
|
||||||
|
@ -13,8 +13,6 @@ import org.enso.compiler.pass.desugar.{
|
|||||||
GenerateMethodBodies
|
GenerateMethodBodies
|
||||||
}
|
}
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** A pass responsible for the discovery of module annotations, and for
|
/** A pass responsible for the discovery of module annotations, and for
|
||||||
* associating them with the corresponding construct.
|
* associating them with the corresponding construct.
|
||||||
*/
|
*/
|
||||||
@ -34,7 +32,7 @@ case object ModuleAnnotations extends IRPass {
|
|||||||
* @param ir the Enso IR to process
|
* @param ir the Enso IR to process
|
||||||
* @param moduleContext a context object that contains the information needed
|
* @param moduleContext a context object that contains the information needed
|
||||||
* to process a module
|
* to process a module
|
||||||
* @return `ir`, possibly having made transformations or annotations to that
|
* @return `ir`, possibly having made transformations or annotations to that
|
||||||
* IR.
|
* IR.
|
||||||
*/
|
*/
|
||||||
override def runModule(
|
override def runModule(
|
||||||
@ -42,27 +40,27 @@ case object ModuleAnnotations extends IRPass {
|
|||||||
moduleContext: ModuleContext
|
moduleContext: ModuleContext
|
||||||
): IR.Module = {
|
): IR.Module = {
|
||||||
var lastAnnotations: Seq[IR.Name.Annotation] = Seq()
|
var lastAnnotations: Seq[IR.Name.Annotation] = Seq()
|
||||||
val newBindings = for (binding <- ir.bindings) yield {
|
val newBindings = ir.bindings.map {
|
||||||
binding match {
|
case ann: Name.BuiltinAnnotation =>
|
||||||
case ann: Name.Annotation =>
|
lastAnnotations :+= ann
|
||||||
lastAnnotations :+= ann
|
None
|
||||||
None
|
case ann: Name.GenericAnnotation =>
|
||||||
case comment: IR.Comment => Some(comment)
|
Some(ann)
|
||||||
case typ: Definition.SugaredType =>
|
case comment: IR.Comment => Some(comment)
|
||||||
val res = Some(
|
case typ: Definition.SugaredType =>
|
||||||
resolveComplexType(typ).updateMetadata(
|
val res = Some(
|
||||||
this -->> Annotations(lastAnnotations)
|
resolveComplexType(typ).updateMetadata(
|
||||||
)
|
this -->> Annotations(lastAnnotations)
|
||||||
)
|
)
|
||||||
lastAnnotations = Seq()
|
)
|
||||||
res
|
lastAnnotations = Seq()
|
||||||
case entity =>
|
res
|
||||||
val res = Some(
|
case entity =>
|
||||||
entity.updateMetadata(this -->> Annotations(lastAnnotations))
|
val res = Some(
|
||||||
)
|
entity.updateMetadata(this -->> Annotations(lastAnnotations))
|
||||||
lastAnnotations = Seq()
|
)
|
||||||
res
|
lastAnnotations = Seq()
|
||||||
}
|
res
|
||||||
}
|
}
|
||||||
ir.copy(bindings = newBindings.flatten)
|
ir.copy(bindings = newBindings.flatten)
|
||||||
}
|
}
|
||||||
@ -72,14 +70,16 @@ case object ModuleAnnotations extends IRPass {
|
|||||||
* @param typ the type in which to resolve annotations
|
* @param typ the type in which to resolve annotations
|
||||||
* @return `typ` with all top-level annotations resolved
|
* @return `typ` with all top-level annotations resolved
|
||||||
*/
|
*/
|
||||||
def resolveComplexType(
|
private def resolveComplexType(
|
||||||
typ: Definition.SugaredType
|
typ: Definition.SugaredType
|
||||||
): Definition.SugaredType = {
|
): Definition.SugaredType = {
|
||||||
var lastAnnotations: Seq[IR.Name.Annotation] = Seq()
|
var lastAnnotations: Seq[IR.Name.Annotation] = Seq()
|
||||||
val newBodyElems = typ.body.flatMap {
|
val newBodyElems = typ.body.flatMap {
|
||||||
case ann: Name.Annotation =>
|
case ann: Name.BuiltinAnnotation =>
|
||||||
lastAnnotations :+= ann
|
lastAnnotations :+= ann
|
||||||
None
|
None
|
||||||
|
case ann: Name.GenericAnnotation =>
|
||||||
|
Some(ann)
|
||||||
case comment: IR.Comment => Some(comment)
|
case comment: IR.Comment => Some(comment)
|
||||||
case entity =>
|
case entity =>
|
||||||
val res = Some(
|
val res = Some(
|
||||||
@ -98,17 +98,17 @@ case object ModuleAnnotations extends IRPass {
|
|||||||
* @param ir the Enso IR to process
|
* @param ir the Enso IR to process
|
||||||
* @param inlineContext a context object that contains the information needed
|
* @param inlineContext a context object that contains the information needed
|
||||||
* for inline evaluation
|
* for inline evaluation
|
||||||
* @return `ir`, possibly having made transformations or annotations to that
|
* @return `ir`, possibly having made transformations or annotations to that
|
||||||
* IR.
|
* IR.
|
||||||
*/
|
*/
|
||||||
override def runExpression(
|
override def runExpression(
|
||||||
ir: IR.Expression,
|
ir: IR.Expression,
|
||||||
@unused inlineContext: InlineContext
|
inlineContext: InlineContext
|
||||||
): IR.Expression = ir
|
): IR.Expression = ir
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@ package org.enso.compiler.pass.resolve
|
|||||||
|
|
||||||
import org.enso.compiler.context.{InlineContext, ModuleContext}
|
import org.enso.compiler.context.{InlineContext, ModuleContext}
|
||||||
import org.enso.compiler.core.IR
|
import org.enso.compiler.core.IR
|
||||||
|
import org.enso.compiler.exception.CompilerError
|
||||||
import org.enso.compiler.pass.IRPass
|
import org.enso.compiler.pass.IRPass
|
||||||
import org.enso.compiler.pass.desugar.{ComplexType, GenerateMethodBodies}
|
import org.enso.compiler.pass.desugar.{ComplexType, GenerateMethodBodies}
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
/** This pass performs static detection of method overloads and emits errors
|
/** This pass performs static detection of method overloads and emits errors
|
||||||
@ -45,59 +45,56 @@ case object OverloadsResolution extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runModule(
|
override def runModule(
|
||||||
ir: IR.Module,
|
ir: IR.Module,
|
||||||
@unused moduleContext: ModuleContext
|
moduleContext: ModuleContext
|
||||||
): IR.Module = {
|
): IR.Module = {
|
||||||
var seenTypes: Set[String] = Set()
|
var seenTypes: Set[String] = Set()
|
||||||
var seenMethods: Map[Option[String], Set[(String, Boolean)]] = Map()
|
var seenMethods: Map[Option[String], Set[(String, Boolean)]] = Map()
|
||||||
|
|
||||||
val types = ir.bindings.collect {
|
val types = ir.bindings.collect {
|
||||||
case tp: IR.Module.Scope.Definition.Type => tp
|
case tp: IR.Module.Scope.Definition.Type =>
|
||||||
}
|
|
||||||
|
|
||||||
val newTypes: List[IR.Module.Scope.Definition] = types.map(tp => {
|
|
||||||
if (seenTypes.contains(tp.name.name)) {
|
|
||||||
IR.Error.Redefined.Type(tp.name, tp.location)
|
|
||||||
} else {
|
|
||||||
seenTypes = seenTypes + tp.name.name
|
|
||||||
tp
|
tp
|
||||||
}
|
}
|
||||||
})
|
ir.bindings.collect {
|
||||||
|
|
||||||
val methods = ir.bindings.collect {
|
|
||||||
case meth: IR.Module.Scope.Definition.Method.Explicit =>
|
case meth: IR.Module.Scope.Definition.Method.Explicit =>
|
||||||
seenMethods = seenMethods + (meth.typeName.map(_.name) -> Set())
|
seenMethods += meth.typeName.map(_.name) -> Set()
|
||||||
meth
|
meth
|
||||||
}
|
}
|
||||||
|
|
||||||
val newMethods: List[IR.Module.Scope.Definition] = methods.map(method => {
|
|
||||||
if (
|
|
||||||
seenMethods(method.typeName.map(_.name))
|
|
||||||
.contains((method.methodName.name, method.isStatic))
|
|
||||||
) {
|
|
||||||
IR.Error.Redefined
|
|
||||||
.Method(method.typeName, method.methodName, method.location)
|
|
||||||
} else {
|
|
||||||
types.find(_.name.name.equals(method.methodName.name)) match {
|
|
||||||
case Some(clashedAtom) if method.typeName.isEmpty =>
|
|
||||||
IR.Error.Redefined.MethodClashWithAtom(
|
|
||||||
clashedAtom.name,
|
|
||||||
method.methodName,
|
|
||||||
method.location
|
|
||||||
)
|
|
||||||
case _ =>
|
|
||||||
val currentMethods: Set[(String, Boolean)] =
|
|
||||||
seenMethods(method.typeName.map(_.name))
|
|
||||||
seenMethods = seenMethods + (method.typeName.map(_.name) ->
|
|
||||||
(currentMethods + ((method.methodName.name, method.isStatic))))
|
|
||||||
method
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
val conversionsForType: mutable.Map[Option[String], Set[String]] =
|
val conversionsForType: mutable.Map[Option[String], Set[String]] =
|
||||||
mutable.Map()
|
mutable.Map()
|
||||||
|
|
||||||
val conversions: List[IR.Module.Scope.Definition] = ir.bindings.collect {
|
val newBindings = ir.bindings.map {
|
||||||
|
case tp: IR.Module.Scope.Definition.Type =>
|
||||||
|
if (seenTypes.contains(tp.name.name)) {
|
||||||
|
IR.Error.Redefined.Type(tp.name, tp.location)
|
||||||
|
} else {
|
||||||
|
seenTypes += tp.name.name
|
||||||
|
tp
|
||||||
|
}
|
||||||
|
|
||||||
|
case method: IR.Module.Scope.Definition.Method.Explicit =>
|
||||||
|
if (
|
||||||
|
seenMethods(method.typeName.map(_.name))
|
||||||
|
.contains((method.methodName.name, method.isStatic))
|
||||||
|
) {
|
||||||
|
IR.Error.Redefined
|
||||||
|
.Method(method.typeName, method.methodName, method.location)
|
||||||
|
} else {
|
||||||
|
types.find(_.name.name.equals(method.methodName.name)) match {
|
||||||
|
case Some(clashedAtom) if method.typeName.isEmpty =>
|
||||||
|
IR.Error.Redefined.MethodClashWithAtom(
|
||||||
|
clashedAtom.name,
|
||||||
|
method.methodName,
|
||||||
|
method.location
|
||||||
|
)
|
||||||
|
case _ =>
|
||||||
|
val currentMethods: Set[(String, Boolean)] =
|
||||||
|
seenMethods(method.typeName.map(_.name))
|
||||||
|
seenMethods += (method.typeName.map(_.name) ->
|
||||||
|
(currentMethods + ((method.methodName.name, method.isStatic))))
|
||||||
|
method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case m: IR.Module.Scope.Definition.Method.Conversion =>
|
case m: IR.Module.Scope.Definition.Method.Conversion =>
|
||||||
val fromName = m.sourceTypeName.asInstanceOf[IR.Name]
|
val fromName = m.sourceTypeName.asInstanceOf[IR.Name]
|
||||||
conversionsForType.get(m.typeName.map(_.name)) match {
|
conversionsForType.get(m.typeName.map(_.name)) match {
|
||||||
@ -115,15 +112,32 @@ case object OverloadsResolution extends IRPass {
|
|||||||
conversionsForType.put(m.typeName.map(_.name), Set(fromName.name))
|
conversionsForType.put(m.typeName.map(_.name), Set(fromName.name))
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case diagnostic: IR.Diagnostic => diagnostic
|
||||||
|
case ann: IR.Name.GenericAnnotation => ann
|
||||||
|
case _: IR.Type.Ascription =>
|
||||||
|
throw new CompilerError(
|
||||||
|
"Type ascriptions should not be present during the overloads resolution."
|
||||||
|
)
|
||||||
|
case _: IR.Module.Scope.Definition.Method.Binding =>
|
||||||
|
throw new CompilerError(
|
||||||
|
"Method bindings should not be present during the overloads resolution."
|
||||||
|
)
|
||||||
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
|
throw new CompilerError(
|
||||||
|
"Builtin annotations should not be present during the overloads resolution."
|
||||||
|
)
|
||||||
|
case _: IR.Comment.Documentation =>
|
||||||
|
throw new CompilerError(
|
||||||
|
"Documentation comments should not be present during the overloads resolution."
|
||||||
|
)
|
||||||
|
case _: IR.Module.Scope.Definition.SugaredType =>
|
||||||
|
throw new CompilerError(
|
||||||
|
"Sugared types should not be present during the overloads resolution."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val diagnostics = ir.bindings.collect { case diag: IR.Diagnostic =>
|
ir.copy(bindings = newBindings)
|
||||||
diag
|
|
||||||
}
|
|
||||||
|
|
||||||
ir.copy(
|
|
||||||
bindings = newTypes ::: newMethods ::: conversions ::: diagnostics
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This pass does nothing for the expression flow.
|
/** This pass does nothing for the expression flow.
|
||||||
@ -141,7 +155,7 @@ case object OverloadsResolution extends IRPass {
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,6 @@ import org.enso.compiler.pass.lint.UnusedBindings
|
|||||||
import org.enso.compiler.pass.optimise.LambdaConsolidate
|
import org.enso.compiler.pass.optimise.LambdaConsolidate
|
||||||
import org.enso.compiler.pass.resolve.TypeSignatures.Signature
|
import org.enso.compiler.pass.resolve.TypeSignatures.Signature
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** This pass is responsible for analysing type signatures to determine which
|
/** This pass is responsible for analysing type signatures to determine which
|
||||||
* arguments in a function definition are suspended.
|
* arguments in a function definition are suspended.
|
||||||
*
|
*
|
||||||
@ -69,7 +67,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runModule(
|
override def runModule(
|
||||||
ir: IR.Module,
|
ir: IR.Module,
|
||||||
@unused moduleContext: ModuleContext
|
moduleContext: ModuleContext
|
||||||
): IR.Module =
|
): IR.Module =
|
||||||
ir.copy(
|
ir.copy(
|
||||||
bindings = ir.bindings.map(resolveModuleBinding)
|
bindings = ir.bindings.map(resolveModuleBinding)
|
||||||
@ -85,12 +83,12 @@ case object SuspendedArguments extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runExpression(
|
override def runExpression(
|
||||||
ir: IR.Expression,
|
ir: IR.Expression,
|
||||||
@unused inlineContext: InlineContext
|
inlineContext: InlineContext
|
||||||
): IR.Expression = resolveExpression(ir)
|
): IR.Expression = resolveExpression(ir)
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -104,7 +102,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
* @param binding the top-level binding to resolve suspensions in
|
* @param binding the top-level binding to resolve suspensions in
|
||||||
* @return `binding`, with any suspended arguments resolved
|
* @return `binding`, with any suspended arguments resolved
|
||||||
*/
|
*/
|
||||||
def resolveModuleBinding(
|
private def resolveModuleBinding(
|
||||||
binding: IR.Module.Scope.Definition
|
binding: IR.Module.Scope.Definition
|
||||||
): IR.Module.Scope.Definition = {
|
): IR.Module.Scope.Definition = {
|
||||||
binding match {
|
binding match {
|
||||||
@ -193,11 +191,12 @@ case object SuspendedArguments extends IRPass {
|
|||||||
throw new CompilerError("Type ascriptions should not be present.")
|
throw new CompilerError("Type ascriptions should not be present.")
|
||||||
case _: IR.Comment =>
|
case _: IR.Comment =>
|
||||||
throw new CompilerError("Comments should not be present.")
|
throw new CompilerError("Comments should not be present.")
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"suspended arguments analysis."
|
"suspended arguments analysis."
|
||||||
)
|
)
|
||||||
|
case ann: IR.Name.GenericAnnotation => ann
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +205,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
* @param expression the expression to perform resolution in
|
* @param expression the expression to perform resolution in
|
||||||
* @return `expression`, with any suspended arguments resolved
|
* @return `expression`, with any suspended arguments resolved
|
||||||
*/
|
*/
|
||||||
def resolveExpression(expression: IR.Expression): IR.Expression = {
|
private def resolveExpression(expression: IR.Expression): IR.Expression = {
|
||||||
expression.transformExpressions {
|
expression.transformExpressions {
|
||||||
case bind @ IR.Expression.Binding(_, expr, _, _, _) =>
|
case bind @ IR.Expression.Binding(_, expr, _, _, _) =>
|
||||||
val newExpr = bind.getMetadata(TypeSignatures) match {
|
val newExpr = bind.getMetadata(TypeSignatures) match {
|
||||||
@ -244,7 +243,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
* @param signature the type signature to split
|
* @param signature the type signature to split
|
||||||
* @return the segments of `signature`
|
* @return the segments of `signature`
|
||||||
*/
|
*/
|
||||||
def toSegments(signature: IR.Expression): List[IR.Expression] = {
|
private def toSegments(signature: IR.Expression): List[IR.Expression] = {
|
||||||
signature match {
|
signature match {
|
||||||
case IR.Type.Function(args, ret, _, _, _) => args :+ ret
|
case IR.Type.Function(args, ret, _, _, _) => args :+ ret
|
||||||
case _ => List(signature)
|
case _ => List(signature)
|
||||||
@ -270,7 +269,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
* @param pair an argument and its corresponding type signature segment
|
* @param pair an argument and its corresponding type signature segment
|
||||||
* @return the argument from `pair`, with its suspension marked appropriately
|
* @return the argument from `pair`, with its suspension marked appropriately
|
||||||
*/
|
*/
|
||||||
def markSuspended(
|
private def markSuspended(
|
||||||
pair: (IR.DefinitionArgument, IR.Expression)
|
pair: (IR.DefinitionArgument, IR.Expression)
|
||||||
): IR.DefinitionArgument =
|
): IR.DefinitionArgument =
|
||||||
pair match {
|
pair match {
|
||||||
@ -289,7 +288,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
* @param signature the signature of the function
|
* @param signature the signature of the function
|
||||||
* @return `args`, appropriately marked as suspended or not
|
* @return `args`, appropriately marked as suspended or not
|
||||||
*/
|
*/
|
||||||
def computeSuspensions(
|
private def computeSuspensions(
|
||||||
args: List[IR.DefinitionArgument],
|
args: List[IR.DefinitionArgument],
|
||||||
signature: IR.Expression
|
signature: IR.Expression
|
||||||
): List[IR.DefinitionArgument] = {
|
): List[IR.DefinitionArgument] = {
|
||||||
|
@ -9,8 +9,6 @@ import org.enso.compiler.pass.IRPass
|
|||||||
import org.enso.compiler.pass.analyse._
|
import org.enso.compiler.pass.analyse._
|
||||||
import org.enso.compiler.pass.lint.UnusedBindings
|
import org.enso.compiler.pass.lint.UnusedBindings
|
||||||
|
|
||||||
import scala.annotation.unused
|
|
||||||
|
|
||||||
/** This pass is responsible for resolving type signatures and associating
|
/** This pass is responsible for resolving type signatures and associating
|
||||||
* them as metadata with the typed object.
|
* them as metadata with the typed object.
|
||||||
*
|
*
|
||||||
@ -49,7 +47,7 @@ case object TypeSignatures extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runModule(
|
override def runModule(
|
||||||
ir: IR.Module,
|
ir: IR.Module,
|
||||||
@unused moduleContext: ModuleContext
|
moduleContext: ModuleContext
|
||||||
): IR.Module = resolveModule(ir)
|
): IR.Module = resolveModule(ir)
|
||||||
|
|
||||||
/** Resolves type signatures in an expression.
|
/** Resolves type signatures in an expression.
|
||||||
@ -62,12 +60,12 @@ case object TypeSignatures extends IRPass {
|
|||||||
*/
|
*/
|
||||||
override def runExpression(
|
override def runExpression(
|
||||||
ir: IR.Expression,
|
ir: IR.Expression,
|
||||||
@unused inlineContext: InlineContext
|
inlineContext: InlineContext
|
||||||
): IR.Expression = resolveExpression(ir)
|
): IR.Expression = resolveExpression(ir)
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def updateMetadataInDuplicate[T <: IR](
|
override def updateMetadataInDuplicate[T <: IR](
|
||||||
@unused sourceIr: T,
|
sourceIr: T,
|
||||||
copyOfIr: T
|
copyOfIr: T
|
||||||
): T = copyOfIr
|
): T = copyOfIr
|
||||||
|
|
||||||
@ -78,7 +76,7 @@ case object TypeSignatures extends IRPass {
|
|||||||
* @param mod the module to resolve signatures in
|
* @param mod the module to resolve signatures in
|
||||||
* @return `mod`, with type signatures resolved
|
* @return `mod`, with type signatures resolved
|
||||||
*/
|
*/
|
||||||
def resolveModule(mod: IR.Module): IR.Module = {
|
private def resolveModule(mod: IR.Module): IR.Module = {
|
||||||
var lastSignature: Option[IR.Type.Ascription] = None
|
var lastSignature: Option[IR.Type.Ascription] = None
|
||||||
|
|
||||||
val newBindings: List[IR.Module.Scope.Definition] = mod.bindings.flatMap {
|
val newBindings: List[IR.Module.Scope.Definition] = mod.bindings.flatMap {
|
||||||
@ -133,13 +131,14 @@ case object TypeSignatures extends IRPass {
|
|||||||
res
|
res
|
||||||
case ut: IR.Module.Scope.Definition.Type =>
|
case ut: IR.Module.Scope.Definition.Type =>
|
||||||
Some(ut.mapExpressions(resolveExpression))
|
Some(ut.mapExpressions(resolveExpression))
|
||||||
case err: IR.Error => Some(err)
|
case err: IR.Error => Some(err)
|
||||||
|
case ann: IR.Name.GenericAnnotation => Some(ann)
|
||||||
case _: IR.Module.Scope.Definition.SugaredType =>
|
case _: IR.Module.Scope.Definition.SugaredType =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Complex type definitions should not be present during type " +
|
"Complex type definitions should not be present during type " +
|
||||||
"signature resolution."
|
"signature resolution."
|
||||||
)
|
)
|
||||||
case _: IR.Name.Annotation =>
|
case _: IR.Name.BuiltinAnnotation =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Annotations should already be associated by the point of " +
|
"Annotations should already be associated by the point of " +
|
||||||
"type signature resolution."
|
"type signature resolution."
|
||||||
@ -163,7 +162,7 @@ case object TypeSignatures extends IRPass {
|
|||||||
* @param expr the expression to resolve signatures in
|
* @param expr the expression to resolve signatures in
|
||||||
* @return `expr`, with any type signatures resolved
|
* @return `expr`, with any type signatures resolved
|
||||||
*/
|
*/
|
||||||
def resolveExpression(expr: IR.Expression): IR.Expression = {
|
private def resolveExpression(expr: IR.Expression): IR.Expression = {
|
||||||
expr.transformExpressions {
|
expr.transformExpressions {
|
||||||
case block: IR.Expression.Block => resolveBlock(block)
|
case block: IR.Expression.Block => resolveBlock(block)
|
||||||
case sig: IR.Type.Ascription => resolveAscription(sig)
|
case sig: IR.Type.Ascription => resolveAscription(sig)
|
||||||
@ -175,7 +174,7 @@ case object TypeSignatures extends IRPass {
|
|||||||
* @param sig the signature to convert
|
* @param sig the signature to convert
|
||||||
* @return the typed expression in `sig`, with `signature` attached
|
* @return the typed expression in `sig`, with `signature` attached
|
||||||
*/
|
*/
|
||||||
def resolveAscription(sig: IR.Type.Ascription): IR.Expression = {
|
private def resolveAscription(sig: IR.Type.Ascription): IR.Expression = {
|
||||||
val newTyped = sig.typed.mapExpressions(resolveExpression)
|
val newTyped = sig.typed.mapExpressions(resolveExpression)
|
||||||
val newSig = sig.signature.mapExpressions(resolveExpression)
|
val newSig = sig.signature.mapExpressions(resolveExpression)
|
||||||
newTyped.updateMetadata(this -->> Signature(newSig))
|
newTyped.updateMetadata(this -->> Signature(newSig))
|
||||||
@ -186,7 +185,7 @@ case object TypeSignatures extends IRPass {
|
|||||||
* @param block the block to resolve signatures in
|
* @param block the block to resolve signatures in
|
||||||
* @return `block`, with any type signatures resolved
|
* @return `block`, with any type signatures resolved
|
||||||
*/
|
*/
|
||||||
def resolveBlock(block: IR.Expression.Block): IR.Expression.Block = {
|
private def resolveBlock(block: IR.Expression.Block): IR.Expression.Block = {
|
||||||
var lastSignature: Option[IR.Type.Ascription] = None
|
var lastSignature: Option[IR.Type.Ascription] = None
|
||||||
val allBlockExpressions =
|
val allBlockExpressions =
|
||||||
block.expressions :+ block.returnValue
|
block.expressions :+ block.returnValue
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
package org.enso.compiler;
|
||||||
|
|
||||||
|
import org.enso.compiler.core.IR$Function$Binding;
|
||||||
|
import org.enso.compiler.core.IR$Module$Scope$Definition$Data;
|
||||||
|
import org.enso.compiler.core.IR$Module$Scope$Definition$SugaredType;
|
||||||
|
import org.enso.compiler.core.IR$Name$Annotation;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class AnnotationsCompilerTest extends CompilerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModuleMethod() throws Exception {
|
||||||
|
var ir = parse("""
|
||||||
|
@a expr
|
||||||
|
@b (x y)
|
||||||
|
foo a b = a b
|
||||||
|
""");
|
||||||
|
|
||||||
|
var annotation1 = (IR$Name$Annotation) ir.bindings().apply(0);
|
||||||
|
var annotation2 = (IR$Name$Annotation) ir.bindings().apply(1);
|
||||||
|
|
||||||
|
assertEquals(annotation1.name(), "a");
|
||||||
|
assertEquals(annotation2.name(), "b");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExtensionMethod() throws Exception {
|
||||||
|
var ir = parse("""
|
||||||
|
@a expr
|
||||||
|
@b (x y)
|
||||||
|
Foo.foo a b = a b
|
||||||
|
""");
|
||||||
|
|
||||||
|
var annotation1 = (IR$Name$Annotation) ir.bindings().apply(0);
|
||||||
|
var annotation2 = (IR$Name$Annotation) ir.bindings().apply(1);
|
||||||
|
|
||||||
|
assertEquals(annotation1.name(), "a");
|
||||||
|
assertEquals(annotation2.name(), "b");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTypeMethod() throws Exception {
|
||||||
|
var ir = parse("""
|
||||||
|
type Foo
|
||||||
|
@a foo
|
||||||
|
@b bar
|
||||||
|
method a b = a b
|
||||||
|
""");
|
||||||
|
|
||||||
|
var typeDefinition = (IR$Module$Scope$Definition$SugaredType) ir.bindings().apply(0);
|
||||||
|
|
||||||
|
var annotation1 = (IR$Name$Annotation) typeDefinition.body().apply(0);
|
||||||
|
var annotation2 = (IR$Name$Annotation) typeDefinition.body().apply(1);
|
||||||
|
var function = (IR$Function$Binding) typeDefinition.body().apply(2);
|
||||||
|
|
||||||
|
assertEquals(annotation1.name(), "a");
|
||||||
|
assertEquals(annotation2.name(), "b");
|
||||||
|
assertEquals(function.name().name(), "method");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructor() throws Exception {
|
||||||
|
var ir = parse("""
|
||||||
|
type Foo
|
||||||
|
@a foo
|
||||||
|
@b bar
|
||||||
|
Cons a b = a b
|
||||||
|
""");
|
||||||
|
|
||||||
|
var typeDefinition = (IR$Module$Scope$Definition$SugaredType) ir.bindings().apply(0);
|
||||||
|
|
||||||
|
var annotation1 = (IR$Name$Annotation) typeDefinition.body().apply(0);
|
||||||
|
var annotation2 = (IR$Name$Annotation) typeDefinition.body().apply(1);
|
||||||
|
var constructor = (IR$Module$Scope$Definition$Data) typeDefinition.body().apply(2);
|
||||||
|
|
||||||
|
assertEquals(annotation1.name(), "a");
|
||||||
|
assertEquals(annotation2.name(), "b");
|
||||||
|
assertEquals(constructor.name().name(), "Cons");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidComplexType() throws Exception {
|
||||||
|
var ir = parse("""
|
||||||
|
type Foo
|
||||||
|
bar a =
|
||||||
|
""");
|
||||||
|
|
||||||
|
var typeDefinition = (IR$Module$Scope$Definition$SugaredType) ir.bindings().apply(0);
|
||||||
|
var method = (IR$Function$Binding) typeDefinition.body().apply(0);
|
||||||
|
|
||||||
|
assertEquals(method.name().name(), "bar");
|
||||||
|
// FIXME method body is null. Should be `IR.Error.Syntax.UnexpectedDeclarationInType`
|
||||||
|
assertEquals(method.body(), null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.enso.compiler;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.source.Source;
|
||||||
|
import org.enso.compiler.core.IR;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
public abstract class CompilerTest {
|
||||||
|
|
||||||
|
protected static EnsoCompiler ensoCompiler;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void initEnsoCompiler() {
|
||||||
|
ensoCompiler = new EnsoCompiler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void closeEnsoCompiler() throws Exception {
|
||||||
|
ensoCompiler.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static IR.Module parse(String code) throws IOException {
|
||||||
|
var src =
|
||||||
|
Source.newBuilder("enso", code, "test-" + Integer.toHexString(code.hashCode()) + ".enso")
|
||||||
|
.build();
|
||||||
|
IR.Module ir = ensoCompiler.compile(src);
|
||||||
|
assertNotNull("IR was generated", ir);
|
||||||
|
return ir;
|
||||||
|
}
|
||||||
|
}
|
@ -1229,7 +1229,6 @@ public class EnsoCompilerTest {
|
|||||||
equivalenceTest("a = x", "a = SKIP FREEZE x + y");
|
equivalenceTest("a = x", "a = SKIP FREEZE x + y");
|
||||||
equivalenceTest("a = x", "a = SKIP FREEZE x.f");
|
equivalenceTest("a = x", "a = SKIP FREEZE x.f");
|
||||||
equivalenceTest("a = x", "a = SKIP FREEZE x.f y");
|
equivalenceTest("a = x", "a = SKIP FREEZE x.f y");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
package org.enso.compiler;
|
package org.enso.compiler;
|
||||||
|
|
||||||
import com.oracle.truffle.api.source.Source;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.enso.compiler.core.IR;
|
import org.enso.compiler.core.IR;
|
||||||
import org.enso.compiler.core.IR$Error$Syntax;
|
import org.enso.compiler.core.IR$Error$Syntax;
|
||||||
import org.enso.compiler.core.IR$Error$Syntax$InvalidEscapeSequence$;
|
import org.enso.compiler.core.IR$Error$Syntax$InvalidEscapeSequence$;
|
||||||
@ -14,42 +10,28 @@ import org.enso.compiler.core.IR$Error$Syntax$UnrecognizedToken$;
|
|||||||
import org.enso.compiler.core.IR$Error$Syntax$UnsupportedSyntax;
|
import org.enso.compiler.core.IR$Error$Syntax$UnsupportedSyntax;
|
||||||
import org.enso.syntax.text.Location;
|
import org.enso.syntax.text.Location;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import scala.collection.immutable.List;
|
import scala.collection.immutable.List;
|
||||||
|
|
||||||
public class ErrorCompilerTest {
|
public class ErrorCompilerTest extends CompilerTest {
|
||||||
private static EnsoCompiler ensoCompiler;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void initEnsoCompiler() {
|
|
||||||
ensoCompiler = new EnsoCompiler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void closeEnsoCompiler() throws Exception {
|
|
||||||
ensoCompiler.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void spaceRequired() throws Exception {
|
public void spaceRequired() throws Exception {
|
||||||
var ir = parseTest("foo = if cond.x else.y");
|
var ir = parse("foo = if cond.x else.y");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 8);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void incompleteTypeDefinition() throws Exception {
|
public void incompleteTypeDefinition() throws Exception {
|
||||||
var ir = parseTest("type");
|
var ir = parse("type");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 4);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void badCase1() throws Exception {
|
public void badCase1() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
foo = case x of
|
foo = case x of
|
||||||
4
|
4
|
||||||
""");
|
""");
|
||||||
@ -58,7 +40,7 @@ public class ErrorCompilerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void badCase2() throws Exception {
|
public void badCase2() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
foo = case x of
|
foo = case x of
|
||||||
4 ->
|
4 ->
|
||||||
""");
|
""");
|
||||||
@ -67,7 +49,7 @@ public class ErrorCompilerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void badCase3() throws Exception {
|
public void badCase3() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
foo = case x of
|
foo = case x of
|
||||||
4->
|
4->
|
||||||
""");
|
""");
|
||||||
@ -76,7 +58,7 @@ public class ErrorCompilerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void badCase4() throws Exception {
|
public void badCase4() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
main =
|
main =
|
||||||
case value of
|
case value of
|
||||||
-1 ->"minus one"
|
-1 ->"minus one"
|
||||||
@ -86,253 +68,253 @@ public class ErrorCompilerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedSequence1() throws Exception {
|
public void malformedSequence1() throws Exception {
|
||||||
var ir = parseTest("(1, )");
|
var ir = parse("(1, )");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 5);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedSequence2() throws Exception {
|
public void malformedSequence2() throws Exception {
|
||||||
var ir = parseTest("foo = (1, )");
|
var ir = parse("foo = (1, )");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 7, 9);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 7, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter1() throws Exception {
|
public void unmatchedDemiliter1() throws Exception {
|
||||||
var ir = parseTest("(");
|
var ir = parse("(");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter2() throws Exception {
|
public void unmatchedDemiliter2() throws Exception {
|
||||||
var ir = parseTest(")");
|
var ir = parse(")");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter3() throws Exception {
|
public void unmatchedDemiliter3() throws Exception {
|
||||||
var ir = parseTest("[");
|
var ir = parse("[");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter4() throws Exception {
|
public void unmatchedDemiliter4() throws Exception {
|
||||||
var ir = parseTest("[");
|
var ir = parse("[");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter5() throws Exception {
|
public void unmatchedDemiliter5() throws Exception {
|
||||||
var ir = parseTest("foo = (");
|
var ir = parse("foo = (");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter6() throws Exception {
|
public void unmatchedDemiliter6() throws Exception {
|
||||||
var ir = parseTest("foo = )");
|
var ir = parse("foo = )");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter7() throws Exception {
|
public void unmatchedDemiliter7() throws Exception {
|
||||||
var ir = parseTest("foo = [");
|
var ir = parse("foo = [");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unmatchedDemiliter8() throws Exception {
|
public void unmatchedDemiliter8() throws Exception {
|
||||||
var ir = parseTest("foo = ]");
|
var ir = parse("foo = ]");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unexpectedSpecialOperator() throws Exception {
|
public void unexpectedSpecialOperator() throws Exception {
|
||||||
var ir = parseTest("foo = 1, 2");
|
var ir = parse("foo = 1, 2");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 10);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 6, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport1() throws Exception {
|
public void malformedImport1() throws Exception {
|
||||||
var ir = parseTest("import");
|
var ir = parse("import");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 6);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport2() throws Exception {
|
public void malformedImport2() throws Exception {
|
||||||
var ir = parseTest("import as Foo");
|
var ir = parse("import as Foo");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 13);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport3() throws Exception {
|
public void malformedImport3() throws Exception {
|
||||||
var ir = parseTest("import Foo as Foo, Bar");
|
var ir = parse("import Foo as Foo, Bar");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 22);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 22);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport4() throws Exception {
|
public void malformedImport4() throws Exception {
|
||||||
var ir = parseTest("import Foo as Foo.Bar");
|
var ir = parse("import Foo as Foo.Bar");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport5() throws Exception {
|
public void malformedImport5() throws Exception {
|
||||||
var ir = parseTest("import Foo as");
|
var ir = parse("import Foo as");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 13, 13);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 13, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport6() throws Exception {
|
public void malformedImport6() throws Exception {
|
||||||
var ir = parseTest("import Foo as Bar.Baz");
|
var ir = parse("import Foo as Bar.Baz");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport7() throws Exception {
|
public void malformedImport7() throws Exception {
|
||||||
var ir = parseTest("import Foo hiding");
|
var ir = parse("import Foo hiding");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 17, 17);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 17, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport8() throws Exception {
|
public void malformedImport8() throws Exception {
|
||||||
var ir = parseTest("import Foo hiding X,");
|
var ir = parse("import Foo hiding X,");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 18, 20);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 18, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport9() throws Exception {
|
public void malformedImport9() throws Exception {
|
||||||
var ir = parseTest("polyglot import Foo");
|
var ir = parse("polyglot import Foo");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnrecognizedToken$.MODULE$, "Unrecognized token.", 0, 19);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnrecognizedToken$.MODULE$, "Unrecognized token.", 0, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport10() throws Exception {
|
public void malformedImport10() throws Exception {
|
||||||
var ir = parseTest("polyglot java import");
|
var ir = parse("polyglot java import");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 20);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport11() throws Exception {
|
public void malformedImport11() throws Exception {
|
||||||
var ir = parseTest("from import all");
|
var ir = parse("from import all");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 4, 4);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 4, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport12() throws Exception {
|
public void malformedImport12() throws Exception {
|
||||||
var ir = parseTest("from Foo import all hiding");
|
var ir = parse("from Foo import all hiding");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 26, 26);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 26, 26);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedImport13() throws Exception {
|
public void malformedImport13() throws Exception {
|
||||||
var ir = parseTest("from Foo import all hiding X.Y");
|
var ir = parse("from Foo import all hiding X.Y");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 27, 30);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 27, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport1() throws Exception {
|
public void malformedExport1() throws Exception {
|
||||||
var ir = parseTest("export");
|
var ir = parse("export");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 6);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport2() throws Exception {
|
public void malformedExport2() throws Exception {
|
||||||
var ir = parseTest("export as Foo");
|
var ir = parse("export as Foo");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 13);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport3() throws Exception {
|
public void malformedExport3() throws Exception {
|
||||||
var ir = parseTest("export Foo as Foo, Bar");
|
var ir = parse("export Foo as Foo, Bar");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 22);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 22);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport4() throws Exception {
|
public void malformedExport4() throws Exception {
|
||||||
var ir = parseTest("export Foo as Foo.Bar");
|
var ir = parse("export Foo as Foo.Bar");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport5() throws Exception {
|
public void malformedExport5() throws Exception {
|
||||||
var ir = parseTest("export Foo as");
|
var ir = parse("export Foo as");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 13, 13);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 13, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport6() throws Exception {
|
public void malformedExport6() throws Exception {
|
||||||
var ir = parseTest("export Foo as Bar.Baz");
|
var ir = parse("export Foo as Bar.Baz");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 14, 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport7() throws Exception {
|
public void malformedExport7() throws Exception {
|
||||||
var ir = parseTest("export Foo hiding");
|
var ir = parse("export Foo hiding");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 7, 17);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 7, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport8() throws Exception {
|
public void malformedExport8() throws Exception {
|
||||||
var ir = parseTest("export Foo hiding X,");
|
var ir = parse("export Foo hiding X,");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 7, 20);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 7, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport9() throws Exception {
|
public void malformedExport9() throws Exception {
|
||||||
var ir = parseTest("from export all");
|
var ir = parse("from export all");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 4, 4);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 4, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport10() throws Exception {
|
public void malformedExport10() throws Exception {
|
||||||
var ir = parseTest("from Foo export all hiding");
|
var ir = parse("from Foo export all hiding");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 26, 26);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 26, 26);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void malformedExport11() throws Exception {
|
public void malformedExport11() throws Exception {
|
||||||
var ir = parseTest("from Foo export all hiding X.Y");
|
var ir = parse("from Foo export all hiding X.Y");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 27, 30);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidImport$.MODULE$, "Imports must have a valid module path.", 27, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidToken1() throws Exception {
|
public void invalidToken1() throws Exception {
|
||||||
var ir = parseTest("`");
|
var ir = parse("`");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidToken2() throws Exception {
|
public void invalidToken2() throws Exception {
|
||||||
var ir = parseTest("splice_outside_text = `");
|
var ir = parse("splice_outside_text = `");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 22, 23);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 22, 23);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void illegalForeignBody1() throws Exception {
|
public void illegalForeignBody1() throws Exception {
|
||||||
var ir = parseTest("foreign 4");
|
var ir = parse("foreign 4");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 9);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void illegalForeignBody2() throws Exception {
|
public void illegalForeignBody2() throws Exception {
|
||||||
var ir = parseTest("foreign 4 * 4");
|
var ir = parse("foreign 4 * 4");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 13);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void illegalForeignBody3() throws Exception {
|
public void illegalForeignBody3() throws Exception {
|
||||||
var ir = parseTest("foreign foo = \"4\"");
|
var ir = parse("foreign foo = \"4\"");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 17);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void illegalForeignBody4() throws Exception {
|
public void illegalForeignBody4() throws Exception {
|
||||||
var ir = parseTest("foreign js foo = 4");
|
var ir = parse("foreign js foo = 4");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 18);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression.", 0, 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void illegalEscapeSequence() throws Exception {
|
public void illegalEscapeSequence() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
escape = 'wrong \\c sequence'
|
escape = 'wrong \\c sequence'
|
||||||
""");
|
""");
|
||||||
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidEscapeSequence$.MODULE$.apply("wrong sequence"), "Invalid escape sequence wrong sequence.", 9, 28);
|
assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidEscapeSequence$.MODULE$.apply("wrong sequence"), "Invalid escape sequence wrong sequence.", 9, 28);
|
||||||
@ -340,7 +322,7 @@ public class ErrorCompilerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNPE183814303() throws Exception {
|
public void testNPE183814303() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
from Standard.Base import all
|
from Standard.Base import all
|
||||||
|
|
||||||
main =
|
main =
|
||||||
@ -353,7 +335,7 @@ public class ErrorCompilerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNPE183863754() throws Exception {
|
public void testNPE183863754() throws Exception {
|
||||||
var ir = parseTest("""
|
var ir = parse("""
|
||||||
main =
|
main =
|
||||||
# meh
|
# meh
|
||||||
42
|
42
|
||||||
@ -380,13 +362,4 @@ public class ErrorCompilerTest {
|
|||||||
assertEquals("Expecting errors: " + errors, count, errors.size());
|
assertEquals("Expecting errors: " + errors, count, errors.size());
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IR.Module parseTest(String code) throws IOException {
|
|
||||||
var src =
|
|
||||||
Source.newBuilder("enso", code, "test-" + Integer.toHexString(code.hashCode()) + ".enso")
|
|
||||||
.build();
|
|
||||||
var ir = ensoCompiler.compile(src);
|
|
||||||
assertNotNull("IR was generated", ir);
|
|
||||||
return ir;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.compiler.test
|
package org.enso.compiler.test
|
||||||
|
|
||||||
|
import org.enso.compiler.EnsoCompiler
|
||||||
import org.enso.compiler.codegen.AstToIr
|
import org.enso.compiler.codegen.AstToIr
|
||||||
import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext}
|
import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext}
|
||||||
import org.enso.compiler.core.IR
|
import org.enso.compiler.core.IR
|
||||||
@ -18,6 +19,8 @@ import org.enso.pkg.QualifiedName
|
|||||||
trait CompilerTest extends AnyWordSpecLike with Matchers with CompilerRunner
|
trait CompilerTest extends AnyWordSpecLike with Matchers with CompilerRunner
|
||||||
trait CompilerRunner {
|
trait CompilerRunner {
|
||||||
|
|
||||||
|
def useRustParser: Boolean = false
|
||||||
|
|
||||||
// === IR Utilities =========================================================
|
// === IR Utilities =========================================================
|
||||||
|
|
||||||
/** Adds an extension method for converting a string to its AST
|
/** Adds an extension method for converting a string to its AST
|
||||||
@ -61,7 +64,13 @@ trait CompilerRunner {
|
|||||||
* @return the [[IR]] representing [[source]]
|
* @return the [[IR]] representing [[source]]
|
||||||
*/
|
*/
|
||||||
def toIrModule: IR.Module = {
|
def toIrModule: IR.Module = {
|
||||||
AstToIr.translate(source.toAst)
|
if (useRustParser) {
|
||||||
|
val compiler = new EnsoCompiler()
|
||||||
|
try compiler.compile(source)
|
||||||
|
finally compiler.close()
|
||||||
|
} else {
|
||||||
|
AstToIr.translate(source.toAst)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +217,7 @@ trait CompilerRunner {
|
|||||||
None
|
None
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
List(),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1041,7 @@ class AstToIrTest extends CompilerTest with Inside {
|
|||||||
|type Foo a b
|
|type Foo a b
|
||||||
|""".stripMargin.toIrModule
|
|""".stripMargin.toIrModule
|
||||||
|
|
||||||
ir.bindings.head shouldBe an[IR.Name.Annotation]
|
ir.bindings.head shouldBe an[IR.Name.BuiltinAnnotation]
|
||||||
ir.bindings(1) shouldBe an[IR.Module.Scope.Definition.SugaredType]
|
ir.bindings(1) shouldBe an[IR.Module.Scope.Definition.SugaredType]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,8 +1059,8 @@ class AstToIrTest extends CompilerTest with Inside {
|
|||||||
val complexType =
|
val complexType =
|
||||||
ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.SugaredType]
|
ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.SugaredType]
|
||||||
|
|
||||||
complexType.body.head shouldBe an[IR.Name.Annotation]
|
complexType.body.head shouldBe an[IR.Name.BuiltinAnnotation]
|
||||||
complexType.body(2) shouldBe an[IR.Name.Annotation]
|
complexType.body(2) shouldBe an[IR.Name.BuiltinAnnotation]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ class ModuleAnnotationsTest extends CompilerTest {
|
|||||||
|
|
||||||
// === Test Setup ===========================================================
|
// === Test Setup ===========================================================
|
||||||
|
|
||||||
|
override val useRustParser = true
|
||||||
|
|
||||||
val passes = new Passes(defaultConfig)
|
val passes = new Passes(defaultConfig)
|
||||||
|
|
||||||
val precursorPasses: PassGroup = passes.getPrecursors(ModuleAnnotations).get
|
val precursorPasses: PassGroup = passes.getPrecursors(ModuleAnnotations).get
|
||||||
@ -115,60 +117,62 @@ class ModuleAnnotationsTest extends CompilerTest {
|
|||||||
anns.length shouldEqual 1
|
anns.length shouldEqual 1
|
||||||
anns.head.asInstanceOf[IR.Name].name shouldEqual "@My_Annotation"
|
anns.head.asInstanceOf[IR.Name].name shouldEqual "@My_Annotation"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"not associate generic annotations with method definitions" in {
|
||||||
|
val ir =
|
||||||
|
"""@a expr_1
|
||||||
|
|@b expr_2
|
||||||
|
|My_Type.add a b = this.frob(a + b)
|
||||||
|
|""".stripMargin.preprocessModule.resolve
|
||||||
|
|
||||||
|
ir.bindings.length shouldEqual 3
|
||||||
|
ir.bindings(0) shouldBe a[IR.Name.GenericAnnotation]
|
||||||
|
ir.bindings(1) shouldBe a[IR.Name.GenericAnnotation]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"Annotation desugaring in complex types" should {
|
"Annotation desugaring in complex types" should {
|
||||||
implicit val moduleContext: ModuleContext = mkModuleContext
|
implicit val moduleContext: ModuleContext = mkModuleContext
|
||||||
|
|
||||||
"associate annotations with atom definitions" in {
|
"not associate generic annotations with atom definitions" in {
|
||||||
val ir =
|
val ir =
|
||||||
"""@My_Annotation
|
"""@My_Annotation
|
||||||
|type Foo
|
|type Foo
|
||||||
| @My_Annotation
|
| @my annotation
|
||||||
| Bar
|
| Bar
|
||||||
|""".stripMargin.preprocessModule.resolve
|
|""".stripMargin.preprocessModule.resolve
|
||||||
|
|
||||||
ir.bindings.length shouldEqual 1
|
ir.bindings.length shouldEqual 1
|
||||||
ir.bindings.head shouldBe a[Definition.SugaredType]
|
ir.bindings.head shouldBe a[Definition.SugaredType]
|
||||||
val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType]
|
val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType]
|
||||||
typ.body.length shouldEqual 1
|
typ.body.length shouldEqual 2
|
||||||
typ.body.head shouldBe a[Definition.Data]
|
typ.body(0) shouldBe an[IR.Name.GenericAnnotation]
|
||||||
typ.body.head
|
typ.body(1) shouldBe a[Definition.Data]
|
||||||
.unsafeGetMetadata(ModuleAnnotations, "")
|
|
||||||
.annotations
|
|
||||||
.head
|
|
||||||
.asInstanceOf[IR.Name]
|
|
||||||
.name shouldEqual "@My_Annotation"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"associate annotations with method definitions" in {
|
"not associate generic annotations with method definitions" in {
|
||||||
val ir =
|
val ir =
|
||||||
"""type Foo
|
"""type Foo
|
||||||
| Foo
|
| Foo
|
||||||
|
|
|
|
||||||
| @My_Annotation
|
| @a expr
|
||||||
| my_method a = a
|
| my_method a = a
|
||||||
|""".stripMargin.preprocessModule.resolve
|
|""".stripMargin.preprocessModule.resolve
|
||||||
|
|
||||||
ir.bindings.length shouldEqual 1
|
ir.bindings.length shouldEqual 1
|
||||||
ir.bindings.head shouldBe a[Definition.SugaredType]
|
ir.bindings.head shouldBe a[Definition.SugaredType]
|
||||||
val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType]
|
val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType]
|
||||||
typ.body.length shouldEqual 2
|
typ.body.length shouldEqual 3
|
||||||
typ.body(1) shouldBe an[IR.Function.Binding]
|
typ.body(1) shouldBe an[IR.Name.GenericAnnotation]
|
||||||
typ
|
typ.body(2) shouldBe an[IR.Function.Binding]
|
||||||
.body(1)
|
|
||||||
.unsafeGetMetadata(ModuleAnnotations, "")
|
|
||||||
.annotations
|
|
||||||
.head
|
|
||||||
.asInstanceOf[IR.Name]
|
|
||||||
.name shouldEqual "@My_Annotation"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"not associate annotations with comments" in {
|
"not associate annotations with comments" in {
|
||||||
val ir =
|
val ir =
|
||||||
"""
|
"""
|
||||||
|type Foo
|
|type Foo
|
||||||
| @My_Annotation
|
| @my annotation
|
||||||
| ## Doc comment
|
| ## Doc comment
|
||||||
| Foo
|
| Foo
|
||||||
|""".stripMargin.preprocessModule.resolve
|
|""".stripMargin.preprocessModule.resolve
|
||||||
@ -176,16 +180,10 @@ class ModuleAnnotationsTest extends CompilerTest {
|
|||||||
ir.bindings.length shouldEqual 1
|
ir.bindings.length shouldEqual 1
|
||||||
ir.bindings.head shouldBe a[Definition.SugaredType]
|
ir.bindings.head shouldBe a[Definition.SugaredType]
|
||||||
val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType]
|
val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType]
|
||||||
typ.body.length shouldEqual 2
|
typ.body.length shouldEqual 3
|
||||||
typ.body.head shouldBe an[IR.Comment]
|
typ.body(0) shouldBe an[IR.Name.GenericAnnotation]
|
||||||
typ.body(1) shouldBe a[Definition.Data]
|
typ.body(1) shouldBe an[IR.Comment]
|
||||||
typ
|
typ.body(2) shouldBe a[Definition.Data]
|
||||||
.body(1)
|
|
||||||
.unsafeGetMetadata(ModuleAnnotations, "")
|
|
||||||
.annotations
|
|
||||||
.head
|
|
||||||
.asInstanceOf[IR.Name]
|
|
||||||
.name shouldEqual "@My_Annotation"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,27 @@ import Standard.Test.Extensions
|
|||||||
from Standard.Base.Error.Common import Uninitialized_State
|
from Standard.Base.Error.Common import Uninitialized_State
|
||||||
|
|
||||||
type My_Type
|
type My_Type
|
||||||
|
@foo (test_method)
|
||||||
|
@baz (My_Type.Value 1 2 3)
|
||||||
Value foo bar baz
|
Value foo bar baz
|
||||||
|
|
||||||
|
@param (test_method 5 6)
|
||||||
|
first_method self param = param
|
||||||
|
|
||||||
|
second_method self param = param
|
||||||
|
|
||||||
|
@a (test_method 5)
|
||||||
|
@b (self -> self.foo)
|
||||||
|
other_method self a = a
|
||||||
|
|
||||||
|
@self ("se" + "lf")
|
||||||
My_Type.my_method self = self.foo + self.bar + self.baz
|
My_Type.my_method self = self.foo + self.bar + self.baz
|
||||||
|
|
||||||
|
@a (test_method 3 4)
|
||||||
|
@b (Test_Type.Value 49)
|
||||||
|
@c (Error.throw "Error Value")
|
||||||
|
test_method a b = a + b
|
||||||
|
|
||||||
type Test_Type
|
type Test_Type
|
||||||
Value x
|
Value x
|
||||||
|
|
||||||
@ -172,6 +189,26 @@ spec =
|
|||||||
(Test_Type.Value a)==(Test_Type.Value b) . should_be_true
|
(Test_Type.Value a)==(Test_Type.Value b) . should_be_true
|
||||||
(Test_Type.Value a)==(Test_Type.Value c) . should_be_false
|
(Test_Type.Value a)==(Test_Type.Value c) . should_be_false
|
||||||
|
|
||||||
|
Test.specify "get annotations" <|
|
||||||
|
Meta.get_annotation Meta_Spec "test_method" "a" . should_equal 7
|
||||||
|
Meta.get_annotation Meta_Spec "test_method" "b" . should_equal (Test_Type.Value 49)
|
||||||
|
Meta.get_annotation Meta_Spec "test_method" "c" . should_fail_with "Error Value"
|
||||||
|
Meta.get_annotation Meta_Spec "test_method" "x" . should_equal Nothing
|
||||||
|
|
||||||
|
value = My_Type.Value 99 "bar" True
|
||||||
|
Meta.get_annotation value "first_method" "param" . should_equal 11
|
||||||
|
Meta.get_annotation value "second_method" "param" . should_equal Nothing
|
||||||
|
Meta.get_annotation value "third_method" "param" . should_equal Nothing
|
||||||
|
Meta.get_annotation value "other_method" "a" 7 . should_equal 12
|
||||||
|
Meta.get_annotation value "other_method" "b" value . should_equal 99
|
||||||
|
Meta.get_annotation value "other_method" "c" . should_equal Nothing
|
||||||
|
|
||||||
|
Meta.get_annotation value "my_method" "self" . should_equal "self"
|
||||||
|
|
||||||
|
Meta.get_annotation value "Value" "foo" 7 8 . should_equal 15
|
||||||
|
Meta.get_annotation value "Value" "bar" . should_equal Nothing
|
||||||
|
Meta.get_annotation value "Value" "baz" . should_equal (My_Type.Value 1 2 3)
|
||||||
|
|
||||||
Test.group "Atom with holes" <|
|
Test.group "Atom with holes" <|
|
||||||
Test.specify "construct and fill" <|
|
Test.specify "construct and fill" <|
|
||||||
pair = Meta.atom_with_hole (e -> My_Type.Value 1 e 3)
|
pair = Meta.atom_with_hole (e -> My_Type.Value 1 e 3)
|
||||||
|
Loading…
Reference in New Issue
Block a user