mirror of
https://github.com/enso-org/enso.git
synced 2024-11-23 16:18:23 +03:00
Clean up the stopgap IR (#521)
This commit is contained in:
parent
06363f4126
commit
e8fcb445be
@ -481,7 +481,8 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
"org.scalactic" %% "scalactic" % "3.2.0-M2" % Test,
|
"org.scalactic" %% "scalactic" % "3.2.0-M2" % Test,
|
||||||
"org.scalatest" %% "scalatest" % "3.2.0-M2" % Test,
|
"org.scalatest" %% "scalatest" % "3.2.0-M2" % Test,
|
||||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % Benchmark,
|
"org.graalvm.truffle" % "truffle-api" % graalVersion % Benchmark,
|
||||||
"org.typelevel" %% "cats-core" % catsVersion
|
"org.typelevel" %% "cats-core" % catsVersion,
|
||||||
|
"eu.timepit" %% "refined" % "0.9.12"
|
||||||
),
|
),
|
||||||
// Note [Unmanaged Classpath]
|
// Note [Unmanaged Classpath]
|
||||||
Compile / unmanagedClasspath += (core_definition / Compile / packageBin).value,
|
Compile / unmanagedClasspath += (core_definition / Compile / packageBin).value,
|
||||||
|
@ -390,7 +390,7 @@ object CoreGraph {
|
|||||||
*/
|
*/
|
||||||
case class CentreSection(operator: Link[G])
|
case class CentreSection(operator: Link[G])
|
||||||
|
|
||||||
/** A representatin of a term that is explicitly forced.
|
/** A representation of a term that is explicitly forced.
|
||||||
*
|
*
|
||||||
* An explicitly forced term is one where the user has explicitly
|
* An explicitly forced term is one where the user has explicitly
|
||||||
* called the `force` operator on it. This is useful only while the
|
* called the `force` operator on it. This is useful only while the
|
||||||
|
@ -4,7 +4,7 @@ import com.oracle.truffle.api.RootCallTarget;
|
|||||||
import com.oracle.truffle.api.Truffle;
|
import com.oracle.truffle.api.Truffle;
|
||||||
import com.oracle.truffle.api.nodes.RootNode;
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
import org.enso.compiler.core.AstArgDefinitionVisitor;
|
import org.enso.compiler.core.AstArgDefinitionVisitor;
|
||||||
import org.enso.compiler.core.AstExpression;
|
import org.enso.compiler.core.IR.Expression;
|
||||||
import com.oracle.truffle.api.source.Source;
|
import com.oracle.truffle.api.source.Source;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.ClosureRootNode;
|
import org.enso.interpreter.node.ClosureRootNode;
|
||||||
@ -84,7 +84,7 @@ public class ArgDefinitionFactory implements AstArgDefinitionVisitor<ArgumentDef
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ArgumentDefinition visitArg(
|
public ArgumentDefinition visitArg(
|
||||||
String name, Optional<AstExpression> defaultValue, boolean suspended, int position) {
|
String name, Optional<Expression> defaultValue, boolean suspended, int position) {
|
||||||
ExpressionNode defExpression =
|
ExpressionNode defExpression =
|
||||||
defaultValue
|
defaultValue
|
||||||
.map(
|
.map(
|
||||||
|
@ -3,11 +3,11 @@ package org.enso.interpreter.builder;
|
|||||||
import com.oracle.truffle.api.RootCallTarget;
|
import com.oracle.truffle.api.RootCallTarget;
|
||||||
import com.oracle.truffle.api.Truffle;
|
import com.oracle.truffle.api.Truffle;
|
||||||
import org.enso.compiler.core.AstCallArgVisitor;
|
import org.enso.compiler.core.AstCallArgVisitor;
|
||||||
import org.enso.compiler.core.AstExpression;
|
import org.enso.compiler.core.IR.Expression;
|
||||||
import com.oracle.truffle.api.source.Source;
|
import com.oracle.truffle.api.source.Source;
|
||||||
|
|
||||||
import com.oracle.truffle.api.source.SourceSection;
|
import com.oracle.truffle.api.source.SourceSection;
|
||||||
import org.enso.compiler.core.AstForce;
|
import org.enso.compiler.core.IR.ForcedTerm;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.ClosureRootNode;
|
import org.enso.interpreter.node.ClosureRootNode;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
@ -64,12 +64,12 @@ public class CallArgFactory implements AstCallArgVisitor<CallArgument> {
|
|||||||
* @return a runtime representation of the argument
|
* @return a runtime representation of the argument
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public CallArgument visitCallArg(Optional<String> name, AstExpression value, int position) {
|
public CallArgument visitCallArg(Optional<String> name, Expression value, int position) {
|
||||||
ExpressionNode result;
|
ExpressionNode result;
|
||||||
|
|
||||||
if (value instanceof AstForce) {
|
if (value instanceof ForcedTerm) {
|
||||||
ExpressionFactory factory = new ExpressionFactory(language, source, scope, scopeName, moduleScope);
|
ExpressionFactory factory = new ExpressionFactory(language, source, scope, scopeName, moduleScope);
|
||||||
result = ((AstForce) value).target().visit(factory);
|
result = ((ForcedTerm) value).target().visit(factory);
|
||||||
} else {
|
} else {
|
||||||
LocalScope childScope = new LocalScope(scope);
|
LocalScope childScope = new LocalScope(scope);
|
||||||
ExpressionFactory factory =
|
ExpressionFactory factory =
|
||||||
|
@ -13,20 +13,20 @@ import java.util.Optional;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.enso.compiler.core.AstApply;
|
|
||||||
import org.enso.compiler.core.AstArgDefinition;
|
|
||||||
import org.enso.compiler.core.AstArithOp;
|
|
||||||
import org.enso.compiler.core.AstAssignment;
|
|
||||||
import org.enso.compiler.core.AstCallArg;
|
|
||||||
import org.enso.compiler.core.AstCaseFunction;
|
|
||||||
import org.enso.compiler.core.AstExpression;
|
|
||||||
import org.enso.compiler.core.AstExpressionVisitor;
|
import org.enso.compiler.core.AstExpressionVisitor;
|
||||||
import org.enso.compiler.core.AstForce;
|
import org.enso.compiler.core.IR.BinaryOperator;
|
||||||
import org.enso.compiler.core.AstFunction;
|
import org.enso.compiler.core.IR.Binding;
|
||||||
import org.enso.compiler.core.AstLong;
|
import org.enso.compiler.core.IR.CallArgumentDefinition;
|
||||||
import org.enso.compiler.core.AstMatch;
|
import org.enso.compiler.core.IR.CaseFunction;
|
||||||
import org.enso.compiler.core.AstStringLiteral;
|
import org.enso.compiler.core.IR.DefinitionSiteArgument;
|
||||||
import org.enso.compiler.core.AstVariable;
|
import org.enso.compiler.core.IR.Expression;
|
||||||
|
import org.enso.compiler.core.IR.ForcedTerm;
|
||||||
|
import org.enso.compiler.core.IR.Lambda;
|
||||||
|
import org.enso.compiler.core.IR.CaseExpr;
|
||||||
|
import org.enso.compiler.core.IR.LiteralName;
|
||||||
|
import org.enso.compiler.core.IR.NumberLiteral;
|
||||||
|
import org.enso.compiler.core.IR.Prefix;
|
||||||
|
import org.enso.compiler.core.IR.TextLiteral;
|
||||||
import org.enso.interpreter.Constants;
|
import org.enso.interpreter.Constants;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.ClosureRootNode;
|
import org.enso.interpreter.node.ClosureRootNode;
|
||||||
@ -142,7 +142,7 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @param expr the expression to make executable
|
* @param expr the expression to make executable
|
||||||
* @return a node representing the provided computation
|
* @return a node representing the provided computation
|
||||||
*/
|
*/
|
||||||
public ExpressionNode run(AstExpression expr) {
|
public ExpressionNode run(Expression expr) {
|
||||||
ExpressionNode result = expr.visit(this);
|
ExpressionNode result = expr.visit(this);
|
||||||
result.markNotTail();
|
result.markNotTail();
|
||||||
return result;
|
return result;
|
||||||
@ -169,8 +169,8 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @return a runtime node representing that value
|
* @return a runtime node representing that value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitLong(AstLong l) {
|
public ExpressionNode visitLong(NumberLiteral l) {
|
||||||
return setLocation(new IntegerLiteralNode(l.value()), l.getLocation());
|
return setLocation(new IntegerLiteralNode(Long.parseLong(l.value())), l.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,8 +180,8 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @return a runtime node representing this literal
|
* @return a runtime node representing this literal
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitStringLiteral(AstStringLiteral string) {
|
public ExpressionNode visitStringLiteral(TextLiteral string) {
|
||||||
ExpressionNode node = new TextLiteralNode(string.string());
|
ExpressionNode node = new TextLiteralNode(string.text());
|
||||||
return setLocation(node, string.getLocation());
|
return setLocation(node, string.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,10 +192,10 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @return a runtime node representing the arithmetic expression
|
* @return a runtime node representing the arithmetic expression
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitArithOp(AstArithOp ast) {
|
public ExpressionNode visitArithOp(BinaryOperator ast) {
|
||||||
ExpressionNode left = ast.left().visit(this);
|
ExpressionNode left = ast.left().visit(this);
|
||||||
ExpressionNode right = ast.right().visit(this);
|
ExpressionNode right = ast.right().visit(this);
|
||||||
String operator = ast.op();
|
String operator = ast.operator();
|
||||||
ExpressionNode resultOp = null;
|
ExpressionNode resultOp = null;
|
||||||
if (operator.equals("+")) {
|
if (operator.equals("+")) {
|
||||||
resultOp = AddOperatorNodeGen.create(left, right);
|
resultOp = AddOperatorNodeGen.create(left, right);
|
||||||
@ -233,12 +233,12 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* <p>This method is solely responsible for looking up a variable in the parent scope with the
|
* <p>This method is solely responsible for looking up a variable in the parent scope with the
|
||||||
* provided name and does not handle associating that variable with a value.
|
* provided name and does not handle associating that variable with a value.
|
||||||
*
|
*
|
||||||
* @param astVariable the AST to represent
|
* @param astName the AST to represent
|
||||||
* @return a runtime node representing the variable
|
* @return a runtime node representing the variable
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitVariable(AstVariable astVariable) {
|
public ExpressionNode visitName(LiteralName astName) {
|
||||||
String name = astVariable.name();
|
String name = astName.name();
|
||||||
Optional<ExpressionNode> currentModuleVariable =
|
Optional<ExpressionNode> currentModuleVariable =
|
||||||
name.equals(Constants.Names.CURRENT_MODULE)
|
name.equals(Constants.Names.CURRENT_MODULE)
|
||||||
? Optional.of(new ConstructorNode(moduleScope.getAssociatedType()))
|
? Optional.of(new ConstructorNode(moduleScope.getAssociatedType()))
|
||||||
@ -255,7 +255,7 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
.map(Optional::get)
|
.map(Optional::get)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseGet(() -> new DynamicSymbolNode(new UnresolvedSymbol(name, moduleScope)));
|
.orElseGet(() -> new DynamicSymbolNode(new UnresolvedSymbol(name, moduleScope)));
|
||||||
return setLocation(variableRead, astVariable.getLocation());
|
return setLocation(variableRead, astName.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,7 +270,7 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @return a runtime node representing the function body
|
* @return a runtime node representing the function body
|
||||||
*/
|
*/
|
||||||
public CreateFunctionNode processFunctionBody(
|
public CreateFunctionNode processFunctionBody(
|
||||||
Optional<Location> location, List<AstArgDefinition> arguments, AstExpression body) {
|
Optional<Location> location, List<DefinitionSiteArgument> arguments, Expression body) {
|
||||||
ArgDefinitionFactory argFactory =
|
ArgDefinitionFactory argFactory =
|
||||||
new ArgDefinitionFactory(scope, language, source, scopeName, moduleScope);
|
new ArgDefinitionFactory(scope, language, source, scopeName, moduleScope);
|
||||||
ArgumentDefinition[] argDefinitions = new ArgumentDefinition[arguments.size()];
|
ArgumentDefinition[] argDefinitions = new ArgumentDefinition[arguments.size()];
|
||||||
@ -333,17 +333,17 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* Creates a runtime node representing a function.
|
* Creates a runtime node representing a function.
|
||||||
*
|
*
|
||||||
* <p>Given that most of the work takes place in {@link #processFunctionBody(Optional, List,
|
* <p>Given that most of the work takes place in {@link #processFunctionBody(Optional, List,
|
||||||
* AstExpression)}, this node is solely responsible for handling the creation of a new scope for
|
* Expression)}, this node is solely responsible for handling the creation of a new scope for the
|
||||||
* the function, and marking it as tail recursive.
|
* function, and marking it as tail recursive.
|
||||||
*
|
*
|
||||||
* @param function the AST to represent
|
* @param lambda the AST to represent
|
||||||
* @return a runtime node representing the function
|
* @return a runtime node representing the function
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitFunction(AstFunction function) {
|
public ExpressionNode visitLambda(Lambda lambda) {
|
||||||
ExpressionFactory child = createChild(currentVarName);
|
ExpressionFactory child = createChild(currentVarName);
|
||||||
ExpressionNode fun =
|
ExpressionNode fun =
|
||||||
child.processFunctionBody(function.getLocation(), function.getArguments(), function.body());
|
child.processFunctionBody(lambda.getLocation(), lambda.getArguments(), lambda.body());
|
||||||
fun.markTail();
|
fun.markTail();
|
||||||
return fun;
|
return fun;
|
||||||
}
|
}
|
||||||
@ -352,17 +352,19 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* Creates a runtime node representing a case function.
|
* Creates a runtime node representing a case function.
|
||||||
*
|
*
|
||||||
* <p>Given that most of the work takes place in {@link #processFunctionBody(Optional, List,
|
* <p>Given that most of the work takes place in {@link #processFunctionBody(Optional, List,
|
||||||
* AstExpression) processFunctionBody}, this node is solely responsible for handling the creation
|
* Expression) processFunctionBody}, this node is solely responsible for handling the creation of
|
||||||
* of a new scope for the function.
|
* a new scope for the function.
|
||||||
*
|
*
|
||||||
* @param function the AST to represent
|
* @param function the AST to represent
|
||||||
* @return a runtime node representing the function
|
* @return a runtime node representing the function
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitCaseFunction(AstCaseFunction function) {
|
public ExpressionNode visitCaseFunction(CaseFunction function) {
|
||||||
ExpressionFactory child = createChild("case_expression");
|
ExpressionFactory child = createChild("case_expression");
|
||||||
return child.processFunctionBody(
|
return child.processFunctionBody(
|
||||||
function.getLocation(), function.getArguments(), function.body());
|
function.getLocation(), function.getArguments(), function.body());
|
||||||
|
|
||||||
|
// Explicitly not marked as tail
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -372,9 +374,9 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @return a runtime node representing the function call
|
* @return a runtime node representing the function call
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitFunctionApplication(AstApply application) {
|
public ExpressionNode visitFunctionApplication(Prefix application) {
|
||||||
CallArgFactory argFactory = new CallArgFactory(scope, language, source, scopeName, moduleScope);
|
CallArgFactory argFactory = new CallArgFactory(scope, language, source, scopeName, moduleScope);
|
||||||
List<AstCallArg> arguments = application.getArgs();
|
List<CallArgumentDefinition> arguments = application.getArgs();
|
||||||
List<CallArgument> callArgs = new ArrayList<>();
|
List<CallArgument> callArgs = new ArrayList<>();
|
||||||
for (int position = 0; position < arguments.size(); ++position) {
|
for (int position = 0; position < arguments.size(); ++position) {
|
||||||
CallArgument arg = arguments.get(position).visit(argFactory, position);
|
CallArgument arg = arguments.get(position).visit(argFactory, position);
|
||||||
@ -388,7 +390,7 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
|
|
||||||
ApplicationNode appNode =
|
ApplicationNode appNode =
|
||||||
new ApplicationNode(
|
new ApplicationNode(
|
||||||
application.fun().visit(this),
|
application.function().visit(this),
|
||||||
callArgs.toArray(new CallArgument[0]),
|
callArgs.toArray(new CallArgument[0]),
|
||||||
defaultsExecutionMode);
|
defaultsExecutionMode);
|
||||||
setLocation(appNode, application.getLocation());
|
setLocation(appNode, application.getLocation());
|
||||||
@ -402,40 +404,40 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
* @return a runtime node representing the assignment
|
* @return a runtime node representing the assignment
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitAssignment(AstAssignment ast) {
|
public ExpressionNode visitAssignment(Binding ast) {
|
||||||
currentVarName = ast.name();
|
currentVarName = ast.name();
|
||||||
FrameSlot slot = scope.createVarSlot(ast.name());
|
FrameSlot slot = scope.createVarSlot(ast.name());
|
||||||
return setLocation(AssignmentNodeGen.create(ast.body().visit(this), slot), ast.getLocation());
|
return setLocation(AssignmentNodeGen.create(ast.expression().visit(this), slot), ast.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a runtime node representing a pattern match.
|
* Creates a runtime node representing a pattern match.
|
||||||
*
|
*
|
||||||
* @param match the AST to represent
|
* @param caseExpr the AST to represent
|
||||||
* @return a runtime node representing a pattern match expression
|
* @return a runtime node representing a pattern match expression
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitMatch(AstMatch match) {
|
public ExpressionNode visitMatch(CaseExpr caseExpr) {
|
||||||
// AstExpression target, List<AstCase> branches, Optional<AstCaseFunction> fallback) {
|
// AstExpression target, List<AstCase> branches, Optional<AstCaseFunction> fallback) {
|
||||||
|
|
||||||
ExpressionNode targetNode = match.target().visit(this);
|
ExpressionNode targetNode = caseExpr.scrutinee().visit(this);
|
||||||
CaseNode[] cases =
|
CaseNode[] cases =
|
||||||
match.getBranches().stream()
|
caseExpr.getBranches().stream()
|
||||||
.map(
|
.map(
|
||||||
branch ->
|
branch ->
|
||||||
new ConstructorCaseNode(
|
new ConstructorCaseNode(
|
||||||
branch.cons().visit(this), branch.function().visit(this)))
|
branch.pattern().visit(this), branch.expression().visit(this)))
|
||||||
.toArray(CaseNode[]::new);
|
.toArray(CaseNode[]::new);
|
||||||
|
|
||||||
// Note [Pattern Match Fallbacks]
|
// Note [Pattern Match Fallbacks]
|
||||||
CaseNode fallbackNode =
|
CaseNode fallbackNode =
|
||||||
match
|
caseExpr
|
||||||
.getFallback()
|
.getFallback()
|
||||||
.map(fb -> (CaseNode) new FallbackNode(fb.visit(this)))
|
.map(fb -> (CaseNode) new FallbackNode(fb.visit(this)))
|
||||||
.orElseGet(DefaultFallbackNode::new);
|
.orElseGet(DefaultFallbackNode::new);
|
||||||
|
|
||||||
ExpressionNode matchExpr = MatchNodeGen.create(cases, fallbackNode, targetNode);
|
ExpressionNode matchExpr = MatchNodeGen.create(cases, fallbackNode, targetNode);
|
||||||
return setLocation(matchExpr, match.getLocation());
|
return setLocation(matchExpr, caseExpr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note [Pattern Match Fallbacks]
|
/* Note [Pattern Match Fallbacks]
|
||||||
@ -449,13 +451,13 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
/**
|
/**
|
||||||
* Creates a runtime representation of lazy function argument forcing.
|
* Creates a runtime representation of lazy function argument forcing.
|
||||||
*
|
*
|
||||||
* @param force the AST to represent
|
* @param forcedTerm the AST to represent
|
||||||
* @return the AST fragment representing forcing of the requested value
|
* @return the AST fragment representing forcing of the requested value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitForce(AstForce force) {
|
public ExpressionNode visitForce(ForcedTerm forcedTerm) {
|
||||||
ForceNode node = ForceNodeGen.create(force.target().visit(this));
|
ForceNode node = ForceNodeGen.create(forcedTerm.target().visit(this));
|
||||||
return setLocation(node, force.getLocation());
|
return setLocation(node, forcedTerm.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -467,7 +469,7 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode visitBlock(
|
public ExpressionNode visitBlock(
|
||||||
List<AstExpression> statements, AstExpression retValue, boolean suspended) {
|
List<Expression> statements, Expression retValue, boolean suspended) {
|
||||||
if (suspended) {
|
if (suspended) {
|
||||||
ExpressionFactory childFactory = this.createChild("suspended-block");
|
ExpressionFactory childFactory = this.createChild("suspended-block");
|
||||||
LocalScope childScope = childFactory.scope;
|
LocalScope childScope = childFactory.scope;
|
||||||
|
@ -1,8 +1,19 @@
|
|||||||
package org.enso.interpreter.builder;
|
package org.enso.interpreter.builder;
|
||||||
|
|
||||||
import org.enso.compiler.core.*;
|
|
||||||
import com.oracle.truffle.api.source.Source;
|
import com.oracle.truffle.api.source.Source;
|
||||||
import org.enso.interpreter.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import org.enso.compiler.core.IR.DefinitionSiteArgument;
|
||||||
|
import org.enso.compiler.core.IR.Expression;
|
||||||
|
import org.enso.compiler.core.IR.AstImport;
|
||||||
|
import org.enso.compiler.core.IR.Module;
|
||||||
|
import org.enso.compiler.core.AstModuleScopeVisitor;
|
||||||
|
import org.enso.compiler.core.IR.MethodDef;
|
||||||
|
import org.enso.compiler.core.IR.AtomDef;
|
||||||
|
import org.enso.interpreter.Constants;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.callable.function.CreateFunctionNode;
|
import org.enso.interpreter.node.callable.function.CreateFunctionNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
@ -12,11 +23,6 @@ import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
|||||||
import org.enso.interpreter.runtime.error.VariableDoesNotExistException;
|
import org.enso.interpreter.runtime.error.VariableDoesNotExistException;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@code GlobalScopeExpressionFactory} is responsible for converting the top-level definitions of
|
* A {@code GlobalScopeExpressionFactory} is responsible for converting the top-level definitions of
|
||||||
* an Enso program into AST nodes for the interpreter to evaluate.
|
* an Enso program into AST nodes for the interpreter to evaluate.
|
||||||
@ -44,7 +50,7 @@ public class ModuleScopeExpressionFactory implements AstModuleScopeVisitor<Funct
|
|||||||
*
|
*
|
||||||
* @param expr the expression to execute on
|
* @param expr the expression to execute on
|
||||||
*/
|
*/
|
||||||
public void run(AstModuleScope expr) {
|
public void run(Module expr) {
|
||||||
expr.visit(this);
|
expr.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +58,12 @@ public class ModuleScopeExpressionFactory implements AstModuleScopeVisitor<Funct
|
|||||||
* Processes definitions in the language global scope.
|
* Processes definitions in the language global scope.
|
||||||
*
|
*
|
||||||
* @param imports any imports requested by this module
|
* @param imports any imports requested by this module
|
||||||
* @param typeDefs any type definitions defined in the global scope
|
* @param atomDefs any type definitions defined in the global scope
|
||||||
* @param bindings any bindings made in the global scope
|
* @param bindings any bindings made in the global scope
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleScope(
|
public void visitModuleScope(
|
||||||
List<AstImport> imports, List<AstTypeDef> typeDefs, List<AstMethodDef> bindings) {
|
List<AstImport> imports, List<AtomDef> atomDefs, List<MethodDef> bindings) {
|
||||||
Context context = language.getCurrentContext();
|
Context context = language.getCurrentContext();
|
||||||
|
|
||||||
for (AstImport imp : imports) {
|
for (AstImport imp : imports) {
|
||||||
@ -65,7 +71,7 @@ public class ModuleScopeExpressionFactory implements AstModuleScopeVisitor<Funct
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<AtomConstructor> constructors =
|
List<AtomConstructor> constructors =
|
||||||
typeDefs.stream()
|
atomDefs.stream()
|
||||||
.map(type -> new AtomConstructor(type.name(), moduleScope))
|
.map(type -> new AtomConstructor(type.name(), moduleScope))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
@ -76,7 +82,7 @@ public class ModuleScopeExpressionFactory implements AstModuleScopeVisitor<Funct
|
|||||||
idx -> {
|
idx -> {
|
||||||
ArgDefinitionFactory argFactory =
|
ArgDefinitionFactory argFactory =
|
||||||
new ArgDefinitionFactory(language, source, moduleScope);
|
new ArgDefinitionFactory(language, source, moduleScope);
|
||||||
AstTypeDef type = typeDefs.get(idx);
|
AtomDef type = atomDefs.get(idx);
|
||||||
ArgumentDefinition[] argDefs = new ArgumentDefinition[type.getArguments().size()];
|
ArgumentDefinition[] argDefs = new ArgumentDefinition[type.getArguments().size()];
|
||||||
|
|
||||||
for (int i = 0; i < type.getArguments().size(); ++i) {
|
for (int i = 0; i < type.getArguments().size(); ++i) {
|
||||||
@ -86,10 +92,10 @@ public class ModuleScopeExpressionFactory implements AstModuleScopeVisitor<Funct
|
|||||||
constructors.get(idx).initializeFields(argDefs);
|
constructors.get(idx).initializeFields(argDefs);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (AstMethodDef method : bindings) {
|
for (MethodDef method : bindings) {
|
||||||
scala.Option<AstExpression> scalaNone = scala.Option.apply(null);
|
scala.Option<Expression> scalaNone = scala.Option.apply(null);
|
||||||
AstArgDefinition thisArgument =
|
DefinitionSiteArgument thisArgument =
|
||||||
new AstArgDefinition(Constants.Names.THIS_ARGUMENT, scalaNone, false);
|
new DefinitionSiteArgument(Constants.Names.THIS_ARGUMENT, scalaNone, false);
|
||||||
|
|
||||||
String typeName = method.typeName();
|
String typeName = method.typeName();
|
||||||
if (typeName.equals(Constants.Names.CURRENT_MODULE)) {
|
if (typeName.equals(Constants.Names.CURRENT_MODULE)) {
|
||||||
@ -103,12 +109,12 @@ public class ModuleScopeExpressionFactory implements AstModuleScopeVisitor<Funct
|
|||||||
typeName + Constants.SCOPE_SEPARATOR + method.methodName(),
|
typeName + Constants.SCOPE_SEPARATOR + method.methodName(),
|
||||||
moduleScope);
|
moduleScope);
|
||||||
|
|
||||||
List<AstArgDefinition> realArgs = new ArrayList<>(method.fun().getArguments());
|
List<DefinitionSiteArgument> realArgs = new ArrayList<>(method.function().getArguments());
|
||||||
realArgs.add(0, thisArgument);
|
realArgs.add(0, thisArgument);
|
||||||
|
|
||||||
CreateFunctionNode funNode =
|
CreateFunctionNode funNode =
|
||||||
expressionFactory.processFunctionBody(
|
expressionFactory.processFunctionBody(
|
||||||
method.fun().getLocation(), realArgs, method.fun().body());
|
method.function().getLocation(), realArgs, method.function().body());
|
||||||
funNode.markTail();
|
funNode.markTail();
|
||||||
Function function =
|
Function function =
|
||||||
new Function(
|
new Function(
|
||||||
|
@ -4,7 +4,8 @@ import java.io.StringReader
|
|||||||
|
|
||||||
import com.oracle.truffle.api.TruffleFile
|
import com.oracle.truffle.api.TruffleFile
|
||||||
import com.oracle.truffle.api.source.Source
|
import com.oracle.truffle.api.source.Source
|
||||||
import org.enso.compiler.core.{AstExpression, AstModuleScope}
|
import org.enso.compiler.core.IR.Expression
|
||||||
|
import org.enso.compiler.core.IR.Module
|
||||||
import org.enso.compiler.generate.AstToAstExpression
|
import org.enso.compiler.generate.AstToAstExpression
|
||||||
import org.enso.flexer.Reader
|
import org.enso.flexer.Reader
|
||||||
import org.enso.interpreter.builder.{ExpressionFactory, ModuleScopeExpressionFactory}
|
import org.enso.interpreter.builder.{ExpressionFactory, ModuleScopeExpressionFactory}
|
||||||
@ -157,7 +158,7 @@ class Compiler(
|
|||||||
* @param sourceAST the parser AST input
|
* @param sourceAST the parser AST input
|
||||||
* @return an IR representation of the program represented by `sourceAST`
|
* @return an IR representation of the program represented by `sourceAST`
|
||||||
*/
|
*/
|
||||||
def translate(sourceAST: AST): AstModuleScope =
|
def translate(sourceAST: AST): Module =
|
||||||
AstToAstExpression.translate(sourceAST)
|
AstToAstExpression.translate(sourceAST)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,6 +168,6 @@ class Compiler(
|
|||||||
* @param sourceAST the parser AST representing the program source
|
* @param sourceAST the parser AST representing the program source
|
||||||
* @return an IR representation of the program represented by `sourceAST`
|
* @return an IR representation of the program represented by `sourceAST`
|
||||||
*/
|
*/
|
||||||
def translateInline(sourceAST: AST): Option[AstExpression] =
|
def translateInline(sourceAST: AST): Option[Expression] =
|
||||||
AstToAstExpression.translateInline(sourceAST)
|
AstToAstExpression.translateInline(sourceAST)
|
||||||
}
|
}
|
||||||
|
577
engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala
Normal file
577
engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala
Normal file
@ -0,0 +1,577 @@
|
|||||||
|
package org.enso.compiler.core
|
||||||
|
|
||||||
|
import java.util.Optional
|
||||||
|
|
||||||
|
import org.enso.compiler.core.IR._
|
||||||
|
import org.enso.syntax.text.{AST, Location}
|
||||||
|
import shapeless.HList
|
||||||
|
|
||||||
|
import scala.jdk.CollectionConverters._
|
||||||
|
import scala.jdk.OptionConverters._
|
||||||
|
|
||||||
|
// TODO [AA] Refactor into a proper nested hierarchy once all clients are
|
||||||
|
// written in scala.
|
||||||
|
// TODO [AA] Add location information to the constructs that are currently
|
||||||
|
// missing it but should have it (primarily for tracking during desugaring).
|
||||||
|
// TODO [AA] Loosen type-based restrictions on what can appear where as
|
||||||
|
// necessary.
|
||||||
|
// TODO [AA] Have more things fall into the expression hierarchy as the visitor
|
||||||
|
// goes away.
|
||||||
|
|
||||||
|
/** [[IR]] is a temporary and fairly unsophisticated internal representation
|
||||||
|
* format for Enso programs.
|
||||||
|
*
|
||||||
|
* It is a purely tree-based representation to support basic desugaring and
|
||||||
|
* analysis passes that do not rely on the ability to create cycles in the IR
|
||||||
|
* itself. Its existence is the natural evolution of the older AstExpression
|
||||||
|
* format used during the initial development of the interpreter.
|
||||||
|
*
|
||||||
|
* In time, it will be replaced by [[Core]], but expediency dictates that we
|
||||||
|
* retain and evolve this representation for the near future.
|
||||||
|
*
|
||||||
|
* PLEASE NOTE: None of the visitor functions are documented as they are slated
|
||||||
|
* for removal as part of the next task.
|
||||||
|
*/
|
||||||
|
sealed trait IR
|
||||||
|
object IR {
|
||||||
|
|
||||||
|
// === Basic Shapes =========================================================
|
||||||
|
|
||||||
|
/** An IR node representing an empty construct. */
|
||||||
|
sealed case class Empty() extends IR with IRKind.Primitive
|
||||||
|
|
||||||
|
/** Allows for the tagging of [[IR]] nodes with arbitrary [[data]].
|
||||||
|
*
|
||||||
|
* The [[data]] is represented as an [[HList]] to allow for the stacking of
|
||||||
|
* multiple pieces of arbitrary data as needed.
|
||||||
|
*
|
||||||
|
* @param ir the [[IR]] node being tagged
|
||||||
|
* @param data the data to associated with [[ir]]
|
||||||
|
* @tparam T the type of the arbitrary data
|
||||||
|
*/
|
||||||
|
sealed case class Tagged[T <: HList](ir: IR, data: T)
|
||||||
|
extends IR
|
||||||
|
with IRKind.Primitive
|
||||||
|
|
||||||
|
// === Literals =============================================================
|
||||||
|
|
||||||
|
/** A trait representing all Enso literals. */
|
||||||
|
sealed trait Literal extends Expression with IRKind.Primitive
|
||||||
|
|
||||||
|
/** A numeric Enso literal.
|
||||||
|
*
|
||||||
|
* @param location the source location of the literal
|
||||||
|
* @param value the textual representation of the numeric literal
|
||||||
|
*/
|
||||||
|
sealed case class NumberLiteral(location: Option[Location], value: String)
|
||||||
|
extends Literal {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitLong(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A textual Enso literal.
|
||||||
|
*
|
||||||
|
* @param location the source location of the literal
|
||||||
|
* @param text the text of the literal
|
||||||
|
*/
|
||||||
|
sealed case class TextLiteral(location: Option[Location], text: String)
|
||||||
|
extends Literal {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitStringLiteral(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Names ================================================================
|
||||||
|
|
||||||
|
/** A trait representing all kinds of name in Enso. */
|
||||||
|
sealed trait Name extends Expression with IRKind.Primitive
|
||||||
|
|
||||||
|
/** The representation of a literal name.
|
||||||
|
*
|
||||||
|
* @param location the source location of tha name occurrence.
|
||||||
|
* @param name the literal text of the name
|
||||||
|
*/
|
||||||
|
sealed case class LiteralName(location: Option[Location], name: String)
|
||||||
|
extends Name {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitName(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO [AA] Add `this` and `here` as names.
|
||||||
|
|
||||||
|
// === Module ===============================================================
|
||||||
|
|
||||||
|
// TODO [AA] Need to add a `name` field to the module
|
||||||
|
/** A representation of a top-level Enso module.
|
||||||
|
*
|
||||||
|
* Modules may only contain imports and top-level bindings, with no top-level
|
||||||
|
* executable code.
|
||||||
|
*
|
||||||
|
* @param imports the import statements that bring other modules into scope
|
||||||
|
* @param bindings the top-level bindings for this module
|
||||||
|
*/
|
||||||
|
sealed case class Module(
|
||||||
|
imports: List[AstImport],
|
||||||
|
bindings: List[TopLevelSymbol]
|
||||||
|
) extends IR
|
||||||
|
with IRKind.Primitive {
|
||||||
|
|
||||||
|
def visit[T](visitor: AstModuleScopeVisitor[T]): Unit = {
|
||||||
|
val types = new java.util.ArrayList[AtomDef]()
|
||||||
|
val defs = new java.util.ArrayList[MethodDef]()
|
||||||
|
|
||||||
|
bindings.foreach {
|
||||||
|
case assignment: MethodDef => defs.add(assignment)
|
||||||
|
case typeDef: AtomDef => types.add(typeDef)
|
||||||
|
}
|
||||||
|
|
||||||
|
visitor.visitModuleScope(
|
||||||
|
imports.asJava,
|
||||||
|
types,
|
||||||
|
defs
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Top-Level Symbols ====================================================
|
||||||
|
|
||||||
|
/** A top-level symbol is one that can occur only at the top-level of an Enso
|
||||||
|
* module.
|
||||||
|
*/
|
||||||
|
sealed trait TopLevelSymbol extends IR
|
||||||
|
|
||||||
|
/** The definition of an atom constructor and its associated arguments.
|
||||||
|
*
|
||||||
|
* @param name the name of the atom
|
||||||
|
* @param arguments the arguments to the atom constructor
|
||||||
|
*/
|
||||||
|
sealed case class AtomDef(
|
||||||
|
name: String,
|
||||||
|
arguments: List[DefinitionSiteArgument]
|
||||||
|
) extends TopLevelSymbol
|
||||||
|
with IRKind.Primitive {
|
||||||
|
def getArguments: java.util.List[DefinitionSiteArgument] = arguments.asJava
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The definition of a method for a given constructor [[typeName]].
|
||||||
|
*
|
||||||
|
* @param typeName the name of the atom that the method is being defined on
|
||||||
|
* @param methodName the name of the method being defined on `typename`
|
||||||
|
* @param function the body of the method
|
||||||
|
*/
|
||||||
|
sealed case class MethodDef(
|
||||||
|
typeName: String,
|
||||||
|
methodName: String,
|
||||||
|
function: Lambda
|
||||||
|
) extends TopLevelSymbol
|
||||||
|
with IRKind.Primitive
|
||||||
|
|
||||||
|
/** An import statement.
|
||||||
|
*
|
||||||
|
* @param name the full `.`-separated path representing the import
|
||||||
|
*/
|
||||||
|
sealed case class AstImport(name: String) extends IR with IRKind.Primitive
|
||||||
|
|
||||||
|
// === Expression ===========================================================
|
||||||
|
|
||||||
|
/** A representation of all Enso program expressions. */
|
||||||
|
sealed trait Expression extends IR {
|
||||||
|
|
||||||
|
/** The source location of the Expression.
|
||||||
|
*
|
||||||
|
* @return the expression's source location
|
||||||
|
*/
|
||||||
|
def location: Option[Location]
|
||||||
|
|
||||||
|
/** Gets the location from the expression.
|
||||||
|
*
|
||||||
|
* @return the location, if it exists, otherwise `null`
|
||||||
|
*/
|
||||||
|
def getLocation: Optional[Location] = Optional.ofNullable(location.orNull)
|
||||||
|
|
||||||
|
def visit[T](visitor: AstExpressionVisitor[T]): T
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Typing ===============================================================
|
||||||
|
|
||||||
|
sealed trait Type extends IR
|
||||||
|
|
||||||
|
// TODO [AA] Type ascription, context ascription, typeset member and the
|
||||||
|
// typeset operators
|
||||||
|
|
||||||
|
// === Function =============================================================
|
||||||
|
|
||||||
|
/** A trait to represent all Enso function formats. */
|
||||||
|
sealed trait Function extends Expression
|
||||||
|
|
||||||
|
/** The primitive function type in Enso: `->`.
|
||||||
|
*
|
||||||
|
* It should be noted that while the _surface_ language does not support
|
||||||
|
* multi-argument lambdas, our internal representation does so to allow for
|
||||||
|
* better optimisation.
|
||||||
|
*
|
||||||
|
* @param location the source location of the lambda definition
|
||||||
|
* @param arguments the arguments to the lambda
|
||||||
|
* @param body the body of the lambda
|
||||||
|
*/
|
||||||
|
case class Lambda(
|
||||||
|
location: Option[Location],
|
||||||
|
arguments: List[DefinitionSiteArgument],
|
||||||
|
body: Expression
|
||||||
|
) extends Function
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitLambda(this)
|
||||||
|
|
||||||
|
def getArguments: java.util.List[DefinitionSiteArgument] = arguments.asJava
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Definition-Site Arguments ============================================
|
||||||
|
|
||||||
|
/** The representation of an argument from a [[Lambda]] or [[AtomDef]]
|
||||||
|
* definition site.
|
||||||
|
*
|
||||||
|
* @param name the name of the argument
|
||||||
|
* @param defaultValue the default value of the argument, if present
|
||||||
|
* @param suspended whether or not the argument has its execution suspended
|
||||||
|
*/
|
||||||
|
sealed case class DefinitionSiteArgument(
|
||||||
|
name: String,
|
||||||
|
defaultValue: Option[Expression],
|
||||||
|
suspended: Boolean
|
||||||
|
) extends IR
|
||||||
|
with IRKind.Primitive {
|
||||||
|
|
||||||
|
def visit[T](visitor: AstArgDefinitionVisitor[T], position: Int): T =
|
||||||
|
visitor.visitArg(
|
||||||
|
name,
|
||||||
|
Optional.ofNullable(defaultValue.orNull),
|
||||||
|
suspended,
|
||||||
|
position
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO [AA] Add support for `_` ignored arguments.
|
||||||
|
|
||||||
|
// === Applications =========================================================
|
||||||
|
|
||||||
|
/** A representation of all function applications in Enso. */
|
||||||
|
sealed trait Application extends Expression
|
||||||
|
|
||||||
|
/** A standard prefix function application
|
||||||
|
*
|
||||||
|
* @param location the source location of the application
|
||||||
|
* @param function the function being called
|
||||||
|
* @param arguments the arguments to the function being called
|
||||||
|
* @param hasDefaultsSuspended whether the function application has any
|
||||||
|
* argument defaults in `function` suspended
|
||||||
|
*/
|
||||||
|
sealed case class Prefix(
|
||||||
|
location: Option[Location],
|
||||||
|
function: Expression,
|
||||||
|
arguments: List[CallArgumentDefinition],
|
||||||
|
hasDefaultsSuspended: Boolean
|
||||||
|
) extends Application
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitFunctionApplication(this)
|
||||||
|
def getArgs: java.util.List[CallArgumentDefinition] = arguments.asJava
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A representation of a generic binary operator in Enso.
|
||||||
|
*
|
||||||
|
* @param location the source location of the operator
|
||||||
|
* @param left the left operand to `operator`
|
||||||
|
* @param operator the operator function being called
|
||||||
|
* @param right the right operand to `operator`
|
||||||
|
*/
|
||||||
|
sealed case class BinaryOperator(
|
||||||
|
location: Option[Location],
|
||||||
|
left: Expression,
|
||||||
|
operator: String,
|
||||||
|
right: Expression
|
||||||
|
) extends Application
|
||||||
|
with IRKind.Sugar {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitArithOp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A representation of a term that is explicitly forced.
|
||||||
|
*
|
||||||
|
* @param location the source location of the force
|
||||||
|
* @param target the expression being forced
|
||||||
|
*/
|
||||||
|
sealed case class ForcedTerm(location: Option[Location], target: Expression)
|
||||||
|
extends Application
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitForce(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO [AA] Add support for left, right, and centre sections
|
||||||
|
|
||||||
|
// === Call-Site Arguments ==================================================
|
||||||
|
|
||||||
|
/** A representation of an argument at a function call site.
|
||||||
|
*
|
||||||
|
* @param name the name of the argument being called, if present
|
||||||
|
* @param value the expression being passed as the argument's value
|
||||||
|
*/
|
||||||
|
sealed case class CallArgumentDefinition(
|
||||||
|
name: Option[String],
|
||||||
|
value: Expression
|
||||||
|
) extends IR
|
||||||
|
with IRKind.Primitive {
|
||||||
|
def visit[T](visitor: AstCallArgVisitor[T], position: Int): T =
|
||||||
|
visitor.visitCallArg(name.toJava, value, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO [AA] Add support for the `_` lambda shorthand argument.
|
||||||
|
|
||||||
|
// === Structure ============================================================
|
||||||
|
|
||||||
|
// TODO [AA] Remove suspended blocks from Enso.
|
||||||
|
/** A block expression.
|
||||||
|
*
|
||||||
|
* @param location the source location of the block
|
||||||
|
* @param expressions the expressions in the block
|
||||||
|
* @param returnValue the final expression in the block
|
||||||
|
* @param suspended whether or not the block is suspended
|
||||||
|
*/
|
||||||
|
sealed case class Block(
|
||||||
|
location: Option[Location],
|
||||||
|
expressions: List[Expression],
|
||||||
|
returnValue: Expression,
|
||||||
|
suspended: Boolean = false
|
||||||
|
) extends Expression
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitBlock(expressions.asJava, returnValue, suspended)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A binding expression of the form `name = expr`
|
||||||
|
*
|
||||||
|
* @param location the source location of the binding
|
||||||
|
* @param name the name being bound to
|
||||||
|
* @param expression the expression being bound to `name`
|
||||||
|
*/
|
||||||
|
case class Binding(
|
||||||
|
location: Option[Location],
|
||||||
|
name: String,
|
||||||
|
expression: Expression
|
||||||
|
) extends Expression
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitAssignment(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Case Expression ======================================================
|
||||||
|
|
||||||
|
/** The Enso case expression.
|
||||||
|
*
|
||||||
|
* @param location the source location of the case expression
|
||||||
|
* @param scrutinee the expression whose value is being matched on
|
||||||
|
* @param branches the branches of the case expression
|
||||||
|
* @param fallback a fallback branch, if provided explicitly
|
||||||
|
*/
|
||||||
|
sealed case class CaseExpr(
|
||||||
|
location: Option[Location],
|
||||||
|
scrutinee: Expression,
|
||||||
|
branches: Seq[CaseBranch],
|
||||||
|
fallback: Option[CaseFunction]
|
||||||
|
) extends Expression
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitMatch(this)
|
||||||
|
def getBranches: java.util.List[CaseBranch] = branches.asJava
|
||||||
|
def getFallback: Optional[CaseFunction] =
|
||||||
|
Optional.ofNullable(fallback.orNull)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO [AA] Should become an expression
|
||||||
|
/** A branch in a case statement.
|
||||||
|
*
|
||||||
|
* @param location the source location of the case branch
|
||||||
|
* @param pattern the pattern that attempts to match against the scrutinee
|
||||||
|
* @param expression the expression that is executed if the pattern matches
|
||||||
|
*/
|
||||||
|
sealed case class CaseBranch(
|
||||||
|
location: Option[Location],
|
||||||
|
pattern: Expression,
|
||||||
|
expression: CaseFunction
|
||||||
|
) extends IRKind.Primitive
|
||||||
|
|
||||||
|
// TODO [AA] Get rid of case function as ExpressionFactory is moved across.
|
||||||
|
/** A representation of the expression body of a case branch.
|
||||||
|
*
|
||||||
|
* This function type is temporary to aid the visitor and should be removed
|
||||||
|
* as part of the next task.
|
||||||
|
*
|
||||||
|
* @param location the source location of the case function
|
||||||
|
* @param arguments the arguments to the function
|
||||||
|
* @param body the body of the function
|
||||||
|
*/
|
||||||
|
case class CaseFunction(
|
||||||
|
location: Option[Location],
|
||||||
|
arguments: List[DefinitionSiteArgument],
|
||||||
|
body: Expression
|
||||||
|
) extends Expression
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitCaseFunction(this)
|
||||||
|
|
||||||
|
def getArguments: java.util.List[DefinitionSiteArgument] = arguments.asJava
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO [AA] Better differentiate the types of patterns that can occur
|
||||||
|
|
||||||
|
// === Comments =============================================================
|
||||||
|
|
||||||
|
/** A documentation comment in the Enso source.
|
||||||
|
*
|
||||||
|
* @param location the source location of the comment
|
||||||
|
* @param commented the expression with which the comment is associated
|
||||||
|
* @param doc the documentation of `commented`
|
||||||
|
*/
|
||||||
|
sealed case class DocComment(
|
||||||
|
location: Option[Location],
|
||||||
|
commented: Expression,
|
||||||
|
doc: String
|
||||||
|
) extends IRKind.Primitive
|
||||||
|
|
||||||
|
// TODO [AA] The above needs to extend `Expression` once the visitor is gone.
|
||||||
|
|
||||||
|
// === Foreign ==============================================================
|
||||||
|
|
||||||
|
/** A foreign code definition in Enso.
|
||||||
|
*
|
||||||
|
* @param location the source location of the foreign code definition
|
||||||
|
* @param lang the foreign language being written
|
||||||
|
* @param code the code written in `lang`
|
||||||
|
*/
|
||||||
|
sealed case class ForeignDefinition(
|
||||||
|
location: Option[Location],
|
||||||
|
lang: String,
|
||||||
|
code: String
|
||||||
|
) extends Expression
|
||||||
|
with IRKind.Primitive {
|
||||||
|
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
||||||
|
visitor.visitForeign(lang, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Errors ===============================================================
|
||||||
|
|
||||||
|
/** A trait for all errors in Enso's IR. */
|
||||||
|
sealed trait Error extends IR with IRKind.Primitive
|
||||||
|
object Error {
|
||||||
|
|
||||||
|
/** A representation of an Enso syntax error.
|
||||||
|
*
|
||||||
|
* @param ast the erroneous AST
|
||||||
|
*/
|
||||||
|
sealed case class Syntax(ast: AST) extends Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// === Primitive / Sugar ====================================================
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
/** A trait representing the classification of IR nodes into either primitive
|
||||||
|
* (constructs which will remain after desugaring) or sugar (constructs that
|
||||||
|
* should be removed by the desugaring passes).
|
||||||
|
*/
|
||||||
|
sealed trait IRKind {}
|
||||||
|
object IRKind {
|
||||||
|
|
||||||
|
/** This trait encodes that a given piece of the [[IR]] is considered to be
|
||||||
|
* a primitive construct in Enso.
|
||||||
|
*/
|
||||||
|
sealed trait Primitive extends IRKind
|
||||||
|
|
||||||
|
/** This trait encodes that a given piece of the [[IR]] is considered to
|
||||||
|
* represent syntax sugar in Enso.
|
||||||
|
*
|
||||||
|
* All [[Sugar]] constructs should be desugared into [[Primitive]]
|
||||||
|
* constructs as soon as possible.
|
||||||
|
*/
|
||||||
|
sealed trait Sugar extends IRKind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// === Visitors ===============================================================
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/** The visitor pattern for the [[Expression]] types.
|
||||||
|
*
|
||||||
|
* @tparam T the type resultant from the visitor
|
||||||
|
*/
|
||||||
|
trait AstExpressionVisitor[+T] {
|
||||||
|
def visitLong(l: NumberLiteral): T
|
||||||
|
|
||||||
|
def visitArithOp(astArithOp: BinaryOperator): T
|
||||||
|
|
||||||
|
def visitForeign(lang: String, code: String): T
|
||||||
|
|
||||||
|
def visitName(astName: LiteralName): T
|
||||||
|
|
||||||
|
def visitLambda(function: Lambda): T
|
||||||
|
|
||||||
|
def visitCaseFunction(function: CaseFunction): T
|
||||||
|
|
||||||
|
def visitFunctionApplication(application: Prefix): T
|
||||||
|
|
||||||
|
def visitAssignment(assignment: Binding): T
|
||||||
|
|
||||||
|
def visitMatch(astMatch: CaseExpr): T
|
||||||
|
|
||||||
|
def visitForce(target: ForcedTerm): T
|
||||||
|
|
||||||
|
def visitStringLiteral(string: TextLiteral): T
|
||||||
|
|
||||||
|
def visitBlock(
|
||||||
|
statements: java.util.List[Expression],
|
||||||
|
retValue: Expression,
|
||||||
|
suspended: Boolean
|
||||||
|
): T
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The visitor pattern for the [[AstModuleScope]] types.
|
||||||
|
*
|
||||||
|
* @tparam T the type resultant from the visitor
|
||||||
|
*/
|
||||||
|
trait AstModuleScopeVisitor[T] {
|
||||||
|
|
||||||
|
@throws(classOf[Exception])
|
||||||
|
def visitModuleScope(
|
||||||
|
imports: java.util.List[AstImport],
|
||||||
|
typeDefs: java.util.List[AtomDef],
|
||||||
|
bindings: java.util.List[MethodDef]
|
||||||
|
): Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The visitor pattern for the [[DefinitionSiteArgument]] types.
|
||||||
|
*
|
||||||
|
* @tparam T the type resultant from the visitor
|
||||||
|
*/
|
||||||
|
trait AstArgDefinitionVisitor[+T] {
|
||||||
|
|
||||||
|
def visitArg(
|
||||||
|
name: String,
|
||||||
|
value: Optional[Expression],
|
||||||
|
suspended: Boolean,
|
||||||
|
position: Int
|
||||||
|
): T
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The visitor pattern for the [[CallArgumentDefinition]] types.
|
||||||
|
*
|
||||||
|
* @tparam T the type resultant from the visitor
|
||||||
|
*/
|
||||||
|
trait AstCallArgVisitor[+T] {
|
||||||
|
|
||||||
|
def visitCallArg(
|
||||||
|
name: Optional[String],
|
||||||
|
value: Expression,
|
||||||
|
position: Int
|
||||||
|
): T
|
||||||
|
}
|
@ -1,247 +0,0 @@
|
|||||||
package org.enso.compiler.core
|
|
||||||
|
|
||||||
import java.util.Optional
|
|
||||||
|
|
||||||
import org.enso.syntax.text.Location
|
|
||||||
|
|
||||||
import scala.jdk.CollectionConverters._
|
|
||||||
|
|
||||||
trait AstExpressionVisitor[+T] {
|
|
||||||
def visitLong(l: AstLong): T
|
|
||||||
|
|
||||||
def visitArithOp(astArithOp: AstArithOp): T
|
|
||||||
|
|
||||||
def visitForeign(lang: String, code: String): T
|
|
||||||
|
|
||||||
def visitVariable(astVariable: AstVariable): T
|
|
||||||
|
|
||||||
def visitFunction(function: AstFunction): T
|
|
||||||
|
|
||||||
def visitCaseFunction(function: AstCaseFunction): T
|
|
||||||
|
|
||||||
def visitFunctionApplication(application: AstApply): T
|
|
||||||
|
|
||||||
def visitAssignment(assignment: AstAssignment): T
|
|
||||||
|
|
||||||
def visitMatch(astMatch: AstMatch): T
|
|
||||||
|
|
||||||
def visitForce(target: AstForce): T
|
|
||||||
|
|
||||||
def visitStringLiteral(string: AstStringLiteral): T
|
|
||||||
|
|
||||||
def visitBlock(
|
|
||||||
statements: java.util.List[AstExpression],
|
|
||||||
retValue: AstExpression,
|
|
||||||
suspended: Boolean
|
|
||||||
): T
|
|
||||||
}
|
|
||||||
|
|
||||||
trait AstModuleScopeVisitor[T] {
|
|
||||||
|
|
||||||
@throws(classOf[Exception])
|
|
||||||
def visitModuleScope(
|
|
||||||
imports: java.util.List[AstImport],
|
|
||||||
typeDefs: java.util.List[AstTypeDef],
|
|
||||||
bindings: java.util.List[AstMethodDef],
|
|
||||||
): Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait AstModuleSymbol
|
|
||||||
|
|
||||||
case class AstTypeDef(name: String, arguments: List[AstArgDefinition])
|
|
||||||
extends AstModuleSymbol {
|
|
||||||
def getArguments: java.util.List[AstArgDefinition] = arguments.asJava
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstMethodDef(typeName: String, methodName: String, fun: AstFunction)
|
|
||||||
extends AstModuleSymbol
|
|
||||||
|
|
||||||
case class AstImport(name: String)
|
|
||||||
|
|
||||||
case class AstModuleScope(
|
|
||||||
imports: List[AstImport],
|
|
||||||
bindings: List[AstModuleSymbol],
|
|
||||||
) {
|
|
||||||
|
|
||||||
def visit[T](visitor: AstModuleScopeVisitor[T]): Unit = {
|
|
||||||
val types = new java.util.ArrayList[AstTypeDef]()
|
|
||||||
val defs = new java.util.ArrayList[AstMethodDef]()
|
|
||||||
|
|
||||||
bindings.foreach {
|
|
||||||
case assignment: AstMethodDef => defs.add(assignment)
|
|
||||||
case typeDef: AstTypeDef => types.add(typeDef)
|
|
||||||
}
|
|
||||||
|
|
||||||
visitor.visitModuleScope(
|
|
||||||
imports.asJava,
|
|
||||||
types,
|
|
||||||
defs
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait AstExpression {
|
|
||||||
def location: Option[Location]
|
|
||||||
def getLocation: Optional[Location] = Optional.ofNullable(location.orNull)
|
|
||||||
def visit[T](visitor: AstExpressionVisitor[T]): T
|
|
||||||
}
|
|
||||||
|
|
||||||
trait AstArgDefinitionVisitor[+T] {
|
|
||||||
|
|
||||||
def visitArg(
|
|
||||||
name: String,
|
|
||||||
value: Optional[AstExpression],
|
|
||||||
suspended: Boolean,
|
|
||||||
position: Int
|
|
||||||
): T
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstArgDefinition(
|
|
||||||
name: String,
|
|
||||||
defaultValue: Option[AstExpression],
|
|
||||||
suspended: Boolean
|
|
||||||
) {
|
|
||||||
|
|
||||||
def visit[T](visitor: AstArgDefinitionVisitor[T], position: Int): T =
|
|
||||||
visitor.visitArg(
|
|
||||||
name,
|
|
||||||
Optional.ofNullable(defaultValue.orNull),
|
|
||||||
suspended,
|
|
||||||
position
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait AstCallArg {
|
|
||||||
def visit[T](visitor: AstCallArgVisitor[T], position: Int): T
|
|
||||||
}
|
|
||||||
|
|
||||||
trait AstCallArgVisitor[+T] {
|
|
||||||
|
|
||||||
def visitCallArg(
|
|
||||||
name: Optional[String],
|
|
||||||
value: AstExpression,
|
|
||||||
position: Int
|
|
||||||
): T
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstNamedCallArg(name: String, value: AstExpression)
|
|
||||||
extends AstCallArg {
|
|
||||||
override def visit[T](visitor: AstCallArgVisitor[T], position: Int): T =
|
|
||||||
visitor.visitCallArg(Optional.of(name), value, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstUnnamedCallArg(value: AstExpression) extends AstCallArg {
|
|
||||||
override def visit[T](visitor: AstCallArgVisitor[T], position: Int): T =
|
|
||||||
visitor.visitCallArg(Optional.empty(), value, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstLong(location: Option[Location], value: Long)
|
|
||||||
extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitLong(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstStringLiteral(location: Option[Location], string: String)
|
|
||||||
extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitStringLiteral(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstArithOp(
|
|
||||||
location: Option[Location],
|
|
||||||
op: String,
|
|
||||||
left: AstExpression,
|
|
||||||
right: AstExpression
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitArithOp(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstForeign(location: Option[Location], lang: String, code: String)
|
|
||||||
extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitForeign(lang, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstVariable(location: Option[Location], name: String)
|
|
||||||
extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitVariable(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstApply(
|
|
||||||
location: Option[Location],
|
|
||||||
fun: AstExpression,
|
|
||||||
args: List[AstCallArg],
|
|
||||||
hasDefaultsSuspended: Boolean
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitFunctionApplication(this)
|
|
||||||
def getArgs: java.util.List[AstCallArg] = args.asJava
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstFunction(
|
|
||||||
location: Option[Location],
|
|
||||||
arguments: List[AstArgDefinition],
|
|
||||||
body: AstExpression
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitFunction(this)
|
|
||||||
|
|
||||||
def getArguments: java.util.List[AstArgDefinition] = arguments.asJava
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstCaseFunction(
|
|
||||||
location: Option[Location],
|
|
||||||
arguments: List[AstArgDefinition],
|
|
||||||
body: AstExpression
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitCaseFunction(this)
|
|
||||||
|
|
||||||
def getArguments: java.util.List[AstArgDefinition] = arguments.asJava
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstAssignment(
|
|
||||||
location: Option[Location],
|
|
||||||
name: String,
|
|
||||||
body: AstExpression
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitAssignment(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstCase(
|
|
||||||
location: Option[Location],
|
|
||||||
cons: AstExpression,
|
|
||||||
function: AstCaseFunction
|
|
||||||
)
|
|
||||||
|
|
||||||
case class AstMatch(
|
|
||||||
location: Option[Location],
|
|
||||||
target: AstExpression,
|
|
||||||
branches: Seq[AstCase],
|
|
||||||
fallback: Option[AstCaseFunction]
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitMatch(this)
|
|
||||||
def getBranches: java.util.List[AstCase] = branches.asJava
|
|
||||||
def getFallback: Optional[AstCaseFunction] =
|
|
||||||
Optional.ofNullable(fallback.orNull)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstForce(location: Option[Location], target: AstExpression)
|
|
||||||
extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitForce(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstBlock(
|
|
||||||
location: Option[Location],
|
|
||||||
statements: List[AstExpression],
|
|
||||||
retVal: AstExpression,
|
|
||||||
suspended: Boolean = false
|
|
||||||
) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitBlock(statements.asJava, retVal, suspended)
|
|
||||||
}
|
|
@ -2,8 +2,7 @@ package org.enso.compiler.generate
|
|||||||
|
|
||||||
import cats.Foldable
|
import cats.Foldable
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import org.enso.compiler.core
|
import org.enso.compiler.core.IR._
|
||||||
import org.enso.compiler.core._
|
|
||||||
import org.enso.compiler.exception.UnhandledEntity
|
import org.enso.compiler.exception.UnhandledEntity
|
||||||
import org.enso.interpreter.Constants
|
import org.enso.interpreter.Constants
|
||||||
import org.enso.syntax.text.{AST, Location}
|
import org.enso.syntax.text.{AST, Location}
|
||||||
@ -15,7 +14,7 @@ import org.enso.syntax.text.{AST, Location}
|
|||||||
* This file contains the functionality that translates from the parser's
|
* This file contains the functionality that translates from the parser's
|
||||||
* [[AST]] type to the internal representation used by the compiler.
|
* [[AST]] type to the internal representation used by the compiler.
|
||||||
*
|
*
|
||||||
* This representation is currently [[AstExpression]], but this will change as
|
* This representation is currently [[Expression]], but this will change as
|
||||||
* [[Core]] becomes implemented. Most function docs will refer to [[Core]]
|
* [[Core]] becomes implemented. Most function docs will refer to [[Core]]
|
||||||
* now, as this will become true soon.
|
* now, as this will become true soon.
|
||||||
*/
|
*/
|
||||||
@ -27,7 +26,7 @@ object AstToAstExpression {
|
|||||||
* @param inputAST the [[AST]] representing the program to translate
|
* @param inputAST the [[AST]] representing the program to translate
|
||||||
* @return the [[Core]] representation of `inputAST`
|
* @return the [[Core]] representation of `inputAST`
|
||||||
*/
|
*/
|
||||||
def translate(inputAST: AST): AstModuleScope = {
|
def translate(inputAST: AST): Module = {
|
||||||
inputAST match {
|
inputAST match {
|
||||||
case AST.Module.any(inputAST) => translateModule(inputAST)
|
case AST.Module.any(inputAST) => translateModule(inputAST)
|
||||||
case _ => {
|
case _ => {
|
||||||
@ -46,7 +45,7 @@ object AstToAstExpression {
|
|||||||
* @return the [[Core]] representation of `inputAST` if it is valid,
|
* @return the [[Core]] representation of `inputAST` if it is valid,
|
||||||
* otherwise [[None]]
|
* otherwise [[None]]
|
||||||
*/
|
*/
|
||||||
def translateInline(inputAST: AST): Option[AstExpression] = {
|
def translateInline(inputAST: AST): Option[Expression] = {
|
||||||
inputAST match {
|
inputAST match {
|
||||||
case AST.Module.any(module) =>
|
case AST.Module.any(module) =>
|
||||||
val presentBlocks = module.lines.collect {
|
val presentBlocks = module.lines.collect {
|
||||||
@ -60,7 +59,7 @@ object AstToAstExpression {
|
|||||||
case List(expr) => Some(expr)
|
case List(expr) => Some(expr)
|
||||||
case _ =>
|
case _ =>
|
||||||
Some(
|
Some(
|
||||||
AstBlock(
|
Block(
|
||||||
Foldable[List].foldMap(expressions)(_.location),
|
Foldable[List].foldMap(expressions)(_.location),
|
||||||
expressions.dropRight(1),
|
expressions.dropRight(1),
|
||||||
expressions.last
|
expressions.last
|
||||||
@ -76,7 +75,7 @@ object AstToAstExpression {
|
|||||||
* @param module the [[AST]] representation of the module to translate
|
* @param module the [[AST]] representation of the module to translate
|
||||||
* @return the [[Core]] representation of `module`
|
* @return the [[Core]] representation of `module`
|
||||||
*/
|
*/
|
||||||
def translateModule(module: AST.Module): AstModuleScope = {
|
def translateModule(module: AST.Module): Module = {
|
||||||
module match {
|
module match {
|
||||||
case AST.Module(blocks) => {
|
case AST.Module(blocks) => {
|
||||||
val presentBlocks = blocks.collect {
|
val presentBlocks = blocks.collect {
|
||||||
@ -93,7 +92,7 @@ object AstToAstExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val statements = nonImportBlocks.map(translateModuleSymbol)
|
val statements = nonImportBlocks.map(translateModuleSymbol)
|
||||||
core.AstModuleScope(imports, statements)
|
Module(imports, statements)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,13 +103,13 @@ object AstToAstExpression {
|
|||||||
* @param inputAST the definition to be translated
|
* @param inputAST the definition to be translated
|
||||||
* @return the [[Core]] representation of `inputAST`
|
* @return the [[Core]] representation of `inputAST`
|
||||||
*/
|
*/
|
||||||
def translateModuleSymbol(inputAST: AST): AstModuleSymbol = {
|
def translateModuleSymbol(inputAST: AST): TopLevelSymbol = {
|
||||||
inputAST match {
|
inputAST match {
|
||||||
case AST.Def(consName, args, body) =>
|
case AST.Def(consName, args, body) =>
|
||||||
if (body.isDefined) {
|
if (body.isDefined) {
|
||||||
throw new RuntimeException("Cannot support complex type defs yet!!!!")
|
throw new RuntimeException("Cannot support complex type defs yet!!!!")
|
||||||
} else {
|
} else {
|
||||||
AstTypeDef(consName.name, args.map(translateArgumentDefinition(_)))
|
AtomDef(consName.name, args.map(translateArgumentDefinition(_)))
|
||||||
}
|
}
|
||||||
case AstView.MethodDefinition(targetPath, name, definition) =>
|
case AstView.MethodDefinition(targetPath, name, definition) =>
|
||||||
val path = if (targetPath.nonEmpty) {
|
val path = if (targetPath.nonEmpty) {
|
||||||
@ -120,11 +119,11 @@ object AstToAstExpression {
|
|||||||
}
|
}
|
||||||
val nameStr = name match { case AST.Ident.Var(name) => name }
|
val nameStr = name match { case AST.Ident.Var(name) => name }
|
||||||
val defExpression = translateExpression(definition)
|
val defExpression = translateExpression(definition)
|
||||||
val defExpr: AstFunction = defExpression match {
|
val defExpr: Lambda = defExpression match {
|
||||||
case fun: AstFunction => fun
|
case fun: Lambda => fun
|
||||||
case expr => AstFunction(expr.location, List(), expr)
|
case expr => Lambda(expr.location, List(), expr)
|
||||||
}
|
}
|
||||||
AstMethodDef(path, nameStr, defExpr)
|
MethodDef(path, nameStr, defExpr)
|
||||||
case _ =>
|
case _ =>
|
||||||
throw new UnhandledEntity(inputAST, "translateModuleSymbol")
|
throw new UnhandledEntity(inputAST, "translateModuleSymbol")
|
||||||
}
|
}
|
||||||
@ -135,14 +134,14 @@ object AstToAstExpression {
|
|||||||
* @param inputAST the expresion to be translated
|
* @param inputAST the expresion to be translated
|
||||||
* @return the [[Core]] representation of `inputAST`
|
* @return the [[Core]] representation of `inputAST`
|
||||||
*/
|
*/
|
||||||
def translateExpression(inputAST: AST): AstExpression = {
|
def translateExpression(inputAST: AST): Expression = {
|
||||||
inputAST match {
|
inputAST match {
|
||||||
case AstView
|
case AstView
|
||||||
.SuspendedBlock(name, block @ AstView.Block(lines, lastLine)) =>
|
.SuspendedBlock(name, block @ AstView.Block(lines, lastLine)) =>
|
||||||
AstAssignment(
|
Binding(
|
||||||
inputAST.location,
|
inputAST.location,
|
||||||
name.name,
|
name.name,
|
||||||
AstBlock(
|
Block(
|
||||||
block.location,
|
block.location,
|
||||||
lines.map(translateExpression),
|
lines.map(translateExpression),
|
||||||
translateExpression(lastLine),
|
translateExpression(lastLine),
|
||||||
@ -152,7 +151,7 @@ object AstToAstExpression {
|
|||||||
case AstView.Assignment(name, expr) =>
|
case AstView.Assignment(name, expr) =>
|
||||||
translateBinding(inputAST.location, name, expr)
|
translateBinding(inputAST.location, name, expr)
|
||||||
case AstView.MethodCall(target, name, args) =>
|
case AstView.MethodCall(target, name, args) =>
|
||||||
AstApply(
|
Prefix(
|
||||||
inputAST.location,
|
inputAST.location,
|
||||||
translateExpression(name),
|
translateExpression(name),
|
||||||
(target :: args).map(translateCallArgument),
|
(target :: args).map(translateCallArgument),
|
||||||
@ -169,7 +168,7 @@ object AstToAstExpression {
|
|||||||
.drop(nonFallbackBranches.length)
|
.drop(nonFallbackBranches.length)
|
||||||
.headOption
|
.headOption
|
||||||
.map(translateFallbackBranch)
|
.map(translateFallbackBranch)
|
||||||
AstMatch(
|
CaseExpr(
|
||||||
inputAST.location,
|
inputAST.location,
|
||||||
actualScrutinee,
|
actualScrutinee,
|
||||||
nonFallbackBranches,
|
nonFallbackBranches,
|
||||||
@ -182,7 +181,7 @@ object AstToAstExpression {
|
|||||||
translateGroup(inputAST, translateExpression)
|
translateGroup(inputAST, translateExpression)
|
||||||
case AST.Ident.any(inputAST) => translateIdent(inputAST)
|
case AST.Ident.any(inputAST) => translateIdent(inputAST)
|
||||||
case AstView.Block(lines, retLine) =>
|
case AstView.Block(lines, retLine) =>
|
||||||
AstBlock(
|
Block(
|
||||||
inputAST.location,
|
inputAST.location,
|
||||||
lines.map(translateExpression),
|
lines.map(translateExpression),
|
||||||
translateExpression(retLine)
|
translateExpression(retLine)
|
||||||
@ -204,14 +203,14 @@ object AstToAstExpression {
|
|||||||
* @param literal the literal to translate
|
* @param literal the literal to translate
|
||||||
* @return the [[Core]] representation of `literal`
|
* @return the [[Core]] representation of `literal`
|
||||||
*/
|
*/
|
||||||
def translateLiteral(literal: AST.Literal): AstExpression = {
|
def translateLiteral(literal: AST.Literal): Expression = {
|
||||||
literal match {
|
literal match {
|
||||||
case AST.Literal.Number(base, number) => {
|
case AST.Literal.Number(base, number) => {
|
||||||
if (base.isDefined && base.get != "10") {
|
if (base.isDefined && base.get != "10") {
|
||||||
throw new RuntimeException("Only base 10 is currently supported")
|
throw new RuntimeException("Only base 10 is currently supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
AstLong(literal.location, number.toLong)
|
NumberLiteral(literal.location, number)
|
||||||
}
|
}
|
||||||
case AST.Literal.Text.any(literal) =>
|
case AST.Literal.Text.any(literal) =>
|
||||||
literal.shape match {
|
literal.shape match {
|
||||||
@ -221,7 +220,7 @@ object AstToAstExpression {
|
|||||||
case AST.Literal.Text.Segment.RawEsc(code) => code.repr
|
case AST.Literal.Text.Segment.RawEsc(code) => code.repr
|
||||||
}.mkString
|
}.mkString
|
||||||
|
|
||||||
AstStringLiteral(literal.location, fullString)
|
TextLiteral(literal.location, fullString)
|
||||||
case AST.Literal.Text.Block.Raw(lines, _, _) =>
|
case AST.Literal.Text.Block.Raw(lines, _, _) =>
|
||||||
val fullString = lines
|
val fullString = lines
|
||||||
.map(
|
.map(
|
||||||
@ -233,7 +232,7 @@ object AstToAstExpression {
|
|||||||
)
|
)
|
||||||
.mkString("\n")
|
.mkString("\n")
|
||||||
|
|
||||||
AstStringLiteral(literal.location, fullString)
|
TextLiteral(literal.location, fullString)
|
||||||
case AST.Literal.Text.Block.Fmt(_, _, _) =>
|
case AST.Literal.Text.Block.Fmt(_, _, _) =>
|
||||||
throw new RuntimeException("Format strings not yet supported")
|
throw new RuntimeException("Format strings not yet supported")
|
||||||
case AST.Literal.Text.Line.Fmt(_) =>
|
case AST.Literal.Text.Line.Fmt(_) =>
|
||||||
@ -255,10 +254,10 @@ object AstToAstExpression {
|
|||||||
def translateArgumentDefinition(
|
def translateArgumentDefinition(
|
||||||
arg: AST,
|
arg: AST,
|
||||||
isSuspended: Boolean = false
|
isSuspended: Boolean = false
|
||||||
): AstArgDefinition = {
|
): DefinitionSiteArgument = {
|
||||||
arg match {
|
arg match {
|
||||||
case AstView.LazyAssignedArgumentDefinition(name, value) =>
|
case AstView.LazyAssignedArgumentDefinition(name, value) =>
|
||||||
AstArgDefinition(
|
DefinitionSiteArgument(
|
||||||
name.name,
|
name.name,
|
||||||
Some(translateExpression(value)),
|
Some(translateExpression(value)),
|
||||||
true
|
true
|
||||||
@ -266,9 +265,9 @@ object AstToAstExpression {
|
|||||||
case AstView.LazyArgument(arg) =>
|
case AstView.LazyArgument(arg) =>
|
||||||
translateArgumentDefinition(arg, isSuspended = true)
|
translateArgumentDefinition(arg, isSuspended = true)
|
||||||
case AstView.DefinitionArgument(arg) =>
|
case AstView.DefinitionArgument(arg) =>
|
||||||
AstArgDefinition(arg.name, None, isSuspended)
|
DefinitionSiteArgument(arg.name, None, isSuspended)
|
||||||
case AstView.AssignedArgument(name, value) =>
|
case AstView.AssignedArgument(name, value) =>
|
||||||
AstArgDefinition(
|
DefinitionSiteArgument(
|
||||||
name.name,
|
name.name,
|
||||||
Some(translateExpression(value)),
|
Some(translateExpression(value)),
|
||||||
isSuspended
|
isSuspended
|
||||||
@ -284,10 +283,10 @@ object AstToAstExpression {
|
|||||||
* @param arg the argument to translate
|
* @param arg the argument to translate
|
||||||
* @return the [[Core]] representation of `arg`
|
* @return the [[Core]] representation of `arg`
|
||||||
*/
|
*/
|
||||||
def translateCallArgument(arg: AST): AstCallArg = arg match {
|
def translateCallArgument(arg: AST): CallArgumentDefinition = arg match {
|
||||||
case AstView.AssignedArgument(left, right) =>
|
case AstView.AssignedArgument(left, right) =>
|
||||||
AstNamedCallArg(left.name, translateExpression(right))
|
CallArgumentDefinition(Some(left.name), translateExpression(right))
|
||||||
case _ => AstUnnamedCallArg(translateExpression(arg))
|
case _ => CallArgumentDefinition(None, translateExpression(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Translates an arbitrary expression that takes the form of a syntactic
|
/** Translates an arbitrary expression that takes the form of a syntactic
|
||||||
@ -296,10 +295,10 @@ object AstToAstExpression {
|
|||||||
* @param callable the callable to translate
|
* @param callable the callable to translate
|
||||||
* @return the [[Core]] representation of `callable`
|
* @return the [[Core]] representation of `callable`
|
||||||
*/
|
*/
|
||||||
def translateApplicationLike(callable: AST): AstExpression = {
|
def translateApplicationLike(callable: AST): Expression = {
|
||||||
callable match {
|
callable match {
|
||||||
case AstView.ForcedTerm(term) =>
|
case AstView.ForcedTerm(term) =>
|
||||||
AstForce(callable.location, translateExpression(term))
|
ForcedTerm(callable.location, translateExpression(term))
|
||||||
case AstView.Application(name, args) =>
|
case AstView.Application(name, args) =>
|
||||||
val validArguments = args.filter {
|
val validArguments = args.filter {
|
||||||
case AstView.SuspendDefaultsOperator(_) => false
|
case AstView.SuspendDefaultsOperator(_) => false
|
||||||
@ -312,7 +311,7 @@ object AstToAstExpression {
|
|||||||
|
|
||||||
val hasDefaultsSuspended = suspendPositions.contains(args.length - 1)
|
val hasDefaultsSuspended = suspendPositions.contains(args.length - 1)
|
||||||
|
|
||||||
AstApply(
|
Prefix(
|
||||||
callable.location,
|
callable.location,
|
||||||
translateExpression(name),
|
translateExpression(name),
|
||||||
validArguments.map(translateCallArgument),
|
validArguments.map(translateCallArgument),
|
||||||
@ -321,18 +320,13 @@ object AstToAstExpression {
|
|||||||
case AstView.Lambda(args, body) =>
|
case AstView.Lambda(args, body) =>
|
||||||
val realArgs = args.map(translateArgumentDefinition(_))
|
val realArgs = args.map(translateArgumentDefinition(_))
|
||||||
val realBody = translateExpression(body)
|
val realBody = translateExpression(body)
|
||||||
AstFunction(callable.location, realArgs, realBody)
|
Lambda(callable.location, realArgs, realBody)
|
||||||
case AST.App.Infix(left, fn, right) =>
|
case AST.App.Infix(left, fn, right) =>
|
||||||
// TODO [AA] We should accept all ops when translating to core
|
// TODO [AA] We should accept all ops when translating to core
|
||||||
val validInfixOps = List("+", "/", "-", "*", "%")
|
val validInfixOps = List("+", "/", "-", "*", "%")
|
||||||
|
|
||||||
if (validInfixOps.contains(fn.name)) {
|
if (validInfixOps.contains(fn.name)) {
|
||||||
AstArithOp(
|
BinaryOperator(callable.location, translateExpression(left), fn.name, translateExpression(right))
|
||||||
callable.location,
|
|
||||||
fn.name,
|
|
||||||
translateExpression(left),
|
|
||||||
translateExpression(right)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
s"${fn.name} is not currently a valid infix operator"
|
s"${fn.name} is not currently a valid infix operator"
|
||||||
@ -358,7 +352,7 @@ object AstToAstExpression {
|
|||||||
val functionName =
|
val functionName =
|
||||||
AST.Ident.Var(realNameSegments.map(_.name).mkString("_"))
|
AST.Ident.Var(realNameSegments.map(_.name).mkString("_"))
|
||||||
|
|
||||||
AstApply(
|
Prefix(
|
||||||
callable.location,
|
callable.location,
|
||||||
translateExpression(functionName),
|
translateExpression(functionName),
|
||||||
args.map(translateCallArgument).toList,
|
args.map(translateCallArgument).toList,
|
||||||
@ -374,10 +368,10 @@ object AstToAstExpression {
|
|||||||
* @param identifier the identifier to translate
|
* @param identifier the identifier to translate
|
||||||
* @return the [[Core]] representation of `identifier`
|
* @return the [[Core]] representation of `identifier`
|
||||||
*/
|
*/
|
||||||
def translateIdent(identifier: AST.Ident): AstExpression = {
|
def translateIdent(identifier: AST.Ident): Expression = {
|
||||||
identifier match {
|
identifier match {
|
||||||
case AST.Ident.Var(name) => AstVariable(identifier.location, name)
|
case AST.Ident.Var(name) => LiteralName(identifier.location, name)
|
||||||
case AST.Ident.Cons(name) => AstVariable(identifier.location, name)
|
case AST.Ident.Cons(name) => LiteralName(identifier.location, name)
|
||||||
case AST.Ident.Blank(_) =>
|
case AST.Ident.Blank(_) =>
|
||||||
throw new RuntimeException("Blanks not yet properly supported")
|
throw new RuntimeException("Blanks not yet properly supported")
|
||||||
case AST.Ident.Opr.any(_) =>
|
case AST.Ident.Opr.any(_) =>
|
||||||
@ -403,10 +397,10 @@ object AstToAstExpression {
|
|||||||
location: Option[Location],
|
location: Option[Location],
|
||||||
name: AST,
|
name: AST,
|
||||||
expr: AST
|
expr: AST
|
||||||
): AstAssignment = {
|
): Binding = {
|
||||||
name match {
|
name match {
|
||||||
case AST.Ident.Var(name) =>
|
case AST.Ident.Var(name) =>
|
||||||
AstAssignment(location, name, translateExpression(expr))
|
Binding(location, name, translateExpression(expr))
|
||||||
case _ =>
|
case _ =>
|
||||||
throw new UnhandledEntity(name, "translateAssignment")
|
throw new UnhandledEntity(name, "translateAssignment")
|
||||||
}
|
}
|
||||||
@ -418,13 +412,13 @@ object AstToAstExpression {
|
|||||||
* @param branch the case branch to translate
|
* @param branch the case branch to translate
|
||||||
* @return the [[Core]] representation of `branch`
|
* @return the [[Core]] representation of `branch`
|
||||||
*/
|
*/
|
||||||
def translateCaseBranch(branch: AST): AstCase = {
|
def translateCaseBranch(branch: AST): CaseBranch = {
|
||||||
branch match {
|
branch match {
|
||||||
case AstView.ConsCaseBranch(cons, args, body) =>
|
case AstView.ConsCaseBranch(cons, args, body) =>
|
||||||
AstCase(
|
CaseBranch(
|
||||||
branch.location,
|
branch.location,
|
||||||
translateExpression(cons),
|
translateExpression(cons),
|
||||||
AstCaseFunction(
|
CaseFunction(
|
||||||
body.location,
|
body.location,
|
||||||
args.map(translateArgumentDefinition(_)),
|
args.map(translateArgumentDefinition(_)),
|
||||||
translateExpression(body)
|
translateExpression(body)
|
||||||
@ -441,10 +435,10 @@ object AstToAstExpression {
|
|||||||
* @param branch the fallback branch to translate
|
* @param branch the fallback branch to translate
|
||||||
* @return the [[Core]] representation of `branch`
|
* @return the [[Core]] representation of `branch`
|
||||||
*/
|
*/
|
||||||
def translateFallbackBranch(branch: AST): AstCaseFunction = {
|
def translateFallbackBranch(branch: AST): CaseFunction = {
|
||||||
branch match {
|
branch match {
|
||||||
case AstView.FallbackCaseBranch(body) =>
|
case AstView.FallbackCaseBranch(body) =>
|
||||||
AstCaseFunction(body.location, List(), translateExpression(body))
|
CaseFunction(body.location, List(), translateExpression(body))
|
||||||
case _ => throw new UnhandledEntity(branch, "translateFallbackBranch")
|
case _ => throw new UnhandledEntity(branch, "translateFallbackBranch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,7 +479,7 @@ object AstToAstExpression {
|
|||||||
* @param invalid the invalid entity to translate
|
* @param invalid the invalid entity to translate
|
||||||
* @return the [[Core]] representation of `invalid`
|
* @return the [[Core]] representation of `invalid`
|
||||||
*/
|
*/
|
||||||
def translateInvalid(invalid: AST.Invalid): AstExpression = {
|
def translateInvalid(invalid: AST.Invalid): Expression = {
|
||||||
invalid match {
|
invalid match {
|
||||||
case AST.Invalid.Unexpected(_, _) =>
|
case AST.Invalid.Unexpected(_, _) =>
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
@ -519,7 +513,7 @@ object AstToAstExpression {
|
|||||||
* @param comment the comment to transform
|
* @param comment the comment to transform
|
||||||
* @return the [[Core]] representation of `comment`
|
* @return the [[Core]] representation of `comment`
|
||||||
*/
|
*/
|
||||||
def translateComment(comment: AST): AstExpression = {
|
def translateComment(comment: AST): Expression = {
|
||||||
comment match {
|
comment match {
|
||||||
case AST.Comment(_) =>
|
case AST.Comment(_) =>
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
|
@ -2,7 +2,7 @@ package org.enso.interpreter.test.semantic
|
|||||||
|
|
||||||
import org.enso.interpreter.test.InterpreterTest
|
import org.enso.interpreter.test.InterpreterTest
|
||||||
|
|
||||||
class FunctionArgumentsTest extends InterpreterTest {
|
class LambdaArgumentsTest extends InterpreterTest {
|
||||||
"Functions" should "take arguments and use them in their bodies" in {
|
"Functions" should "take arguments and use them in their bodies" in {
|
||||||
val code =
|
val code =
|
||||||
"""
|
"""
|
Loading…
Reference in New Issue
Block a user