mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 19:21:54 +03:00
Better way of registering builtin functions (#255)
This commit is contained in:
parent
3c4fd0c55b
commit
6569cc5cb0
@ -32,7 +32,6 @@ import org.enso.interpreter.node.controlflow.DefaultFallbackNode;
|
|||||||
import org.enso.interpreter.node.controlflow.FallbackNode;
|
import org.enso.interpreter.node.controlflow.FallbackNode;
|
||||||
import org.enso.interpreter.node.controlflow.IfZeroNode;
|
import org.enso.interpreter.node.controlflow.IfZeroNode;
|
||||||
import org.enso.interpreter.node.controlflow.MatchNode;
|
import org.enso.interpreter.node.controlflow.MatchNode;
|
||||||
import org.enso.interpreter.node.expression.builtin.PrintNodeGen;
|
|
||||||
import org.enso.interpreter.node.expression.constant.ConstructorNode;
|
import org.enso.interpreter.node.expression.constant.ConstructorNode;
|
||||||
import org.enso.interpreter.node.expression.constant.DynamicSymbolNode;
|
import org.enso.interpreter.node.expression.constant.DynamicSymbolNode;
|
||||||
import org.enso.interpreter.node.expression.literal.IntegerLiteralNode;
|
import org.enso.interpreter.node.expression.literal.IntegerLiteralNode;
|
||||||
@ -370,17 +369,6 @@ public class ExpressionFactory implements AstExpressionVisitor<ExpressionNode> {
|
|||||||
return AssignmentNodeGen.create(expr.visit(this), slot);
|
return AssignmentNodeGen.create(expr.visit(this), slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a runtime node representing a print expression.
|
|
||||||
*
|
|
||||||
* @param body an expression that computes the value to print
|
|
||||||
* @return a runtime node representing the print
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ExpressionNode visitPrint(AstExpression body) {
|
|
||||||
return PrintNodeGen.create(body.visit(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a runtime node representing a pattern match.
|
* Creates a runtime node representing a pattern match.
|
||||||
*
|
*
|
||||||
|
@ -14,7 +14,7 @@ import org.enso.interpreter.runtime.type.TypesGen;
|
|||||||
*
|
*
|
||||||
* <p>Enso is an expression-oriented language, and hence doesn't have any statements. This means
|
* <p>Enso is an expression-oriented language, and hence doesn't have any statements. This means
|
||||||
* that all expression execution will return a value, even if that is just the {@link
|
* that all expression execution will return a value, even if that is just the {@link
|
||||||
* Builtins#UNIT} type.
|
* Builtins#unit()} type.
|
||||||
*
|
*
|
||||||
* <p>This class contains specialisations of the {@link #executeGeneric(VirtualFrame)
|
* <p>This class contains specialisations of the {@link #executeGeneric(VirtualFrame)
|
||||||
* executeGeneric} method for various scenarios in order to improve performance.
|
* executeGeneric} method for various scenarios in order to improve performance.
|
||||||
|
@ -1,52 +1,62 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin;
|
package org.enso.interpreter.node.expression.builtin;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CallTarget;
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.RootCallTarget;
|
||||||
|
import com.oracle.truffle.api.Truffle;
|
||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
import org.enso.interpreter.runtime.Builtins;
|
import org.enso.interpreter.runtime.Builtins;
|
||||||
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.function.ArgumentSchema;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
/** This node allows for printing the result of an arbitrary expression to standard output. */
|
/** This node allows for printing the result of arbitrary values to standard output. */
|
||||||
@NodeInfo(shortName = "print", description = "Prints the value of child expression.")
|
@NodeInfo(shortName = "print", description = "Root of the IO.println method.")
|
||||||
public abstract class PrintNode extends ExpressionNode {
|
public abstract class PrintNode extends RootNode {
|
||||||
@Child private ExpressionNode expression;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a node that prints the result of its expression.
|
* Creates a root node for the builtin IO.println method.
|
||||||
*
|
*
|
||||||
* @param expression the expression to print the result of
|
* @param language the current {@link Language} instance.
|
||||||
*/
|
*/
|
||||||
public PrintNode(ExpressionNode expression) {
|
public PrintNode(Language language) {
|
||||||
this.expression = expression;
|
super(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the print node.
|
|
||||||
*
|
|
||||||
* @param frame the stack frame for execution
|
|
||||||
* @return unit {@link Builtins#UNIT unit} type
|
|
||||||
*/
|
|
||||||
@Specialization
|
@Specialization
|
||||||
public Object doPrint(VirtualFrame frame, @CachedContext(Language.class) Context ctx) {
|
protected Object doPrint(VirtualFrame frame, @CachedContext(Language.class) Context ctx) {
|
||||||
doPrint(ctx.getOut(), expression.executeGeneric(frame));
|
doPrint(ctx.getOut(), Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
|
||||||
|
|
||||||
return Builtins.UNIT.newInstance();
|
return ctx.getUnit().newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints the provided value to standard output.
|
|
||||||
*
|
|
||||||
* @param object the value to print
|
|
||||||
*/
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
private void doPrint(PrintStream out, Object object) {
|
private void doPrint(PrintStream out, Object object) {
|
||||||
out.println(object);
|
out.println(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Function} object ignoring its first argument and printing the second to the
|
||||||
|
* standard output.
|
||||||
|
*
|
||||||
|
* @param language the current {@link Language} instance
|
||||||
|
* @return a {@link Function} object wrapping the behavior of this node
|
||||||
|
*/
|
||||||
|
public static Function toFunction(Language language) {
|
||||||
|
PrintNode node = PrintNodeGen.create(language);
|
||||||
|
RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(node);
|
||||||
|
ArgumentSchema schema =
|
||||||
|
new ArgumentSchema(
|
||||||
|
new ArgumentDefinition(0, "this", false), new ArgumentDefinition(1, "value", false));
|
||||||
|
return new Function(callTarget, null, schema);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.interpreter.node.scope;
|
package org.enso.interpreter.node.scope;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.NodeChild;
|
import com.oracle.truffle.api.dsl.NodeChild;
|
||||||
import com.oracle.truffle.api.dsl.NodeField;
|
import com.oracle.truffle.api.dsl.NodeField;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
@ -7,8 +8,10 @@ import com.oracle.truffle.api.frame.FrameSlot;
|
|||||||
import com.oracle.truffle.api.frame.FrameSlotKind;
|
import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
import org.enso.interpreter.runtime.Builtins;
|
import org.enso.interpreter.runtime.Builtins;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
|
||||||
/** This node represents an assignment to a variable in a given scope. */
|
/** This node represents an assignment to a variable in a given scope. */
|
||||||
@NodeInfo(shortName = "=", description = "Assigns expression result to a variable.")
|
@NodeInfo(shortName = "=", description = "Assigns expression result to a variable.")
|
||||||
@ -20,14 +23,16 @@ public abstract class AssignmentNode extends ExpressionNode {
|
|||||||
*
|
*
|
||||||
* @param frame the frame to write to
|
* @param frame the frame to write to
|
||||||
* @param value the value to write
|
* @param value the value to write
|
||||||
* @return the {@link Builtins#UNIT unit} type
|
* @param ctx language context for global values access
|
||||||
|
* @return the unit type
|
||||||
*/
|
*/
|
||||||
@Specialization
|
@Specialization
|
||||||
protected Object writeLong(VirtualFrame frame, long value) {
|
protected Object writeLong(
|
||||||
|
VirtualFrame frame, long value, @CachedContext(Language.class) Context ctx) {
|
||||||
frame.getFrameDescriptor().setFrameSlotKind(getFrameSlot(), FrameSlotKind.Long);
|
frame.getFrameDescriptor().setFrameSlotKind(getFrameSlot(), FrameSlotKind.Long);
|
||||||
frame.setLong(getFrameSlot(), value);
|
frame.setLong(getFrameSlot(), value);
|
||||||
|
|
||||||
return Builtins.UNIT.newInstance();
|
return ctx.getUnit().newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,14 +40,16 @@ public abstract class AssignmentNode extends ExpressionNode {
|
|||||||
*
|
*
|
||||||
* @param frame the frame to write to
|
* @param frame the frame to write to
|
||||||
* @param value the value to write
|
* @param value the value to write
|
||||||
* @return the {@link Builtins#UNIT unit} type
|
* @param ctx language context for global values access
|
||||||
|
* @return the unit type
|
||||||
*/
|
*/
|
||||||
@Specialization
|
@Specialization
|
||||||
protected Object writeObject(VirtualFrame frame, Object value) {
|
protected Object writeObject(
|
||||||
|
VirtualFrame frame, Object value, @CachedContext(Language.class) Context ctx) {
|
||||||
frame.getFrameDescriptor().setFrameSlotKind(getFrameSlot(), FrameSlotKind.Object);
|
frame.getFrameDescriptor().setFrameSlotKind(getFrameSlot(), FrameSlotKind.Object);
|
||||||
frame.setObject(getFrameSlot(), value);
|
frame.setObject(getFrameSlot(), value);
|
||||||
|
|
||||||
return Builtins.UNIT.newInstance();
|
return ctx.getUnit().newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,24 +1,55 @@
|
|||||||
package org.enso.interpreter.runtime;
|
package org.enso.interpreter.runtime;
|
||||||
|
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.PrintNode;
|
||||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
/** Container class for static predefined atoms and their containing scope. */
|
/** Container class for static predefined atoms, methods, and their containing scope. */
|
||||||
public class Builtins {
|
public class Builtins {
|
||||||
public static final ModuleScope BUILTIN_SCOPE = new ModuleScope();
|
private final ModuleScope scope;
|
||||||
public static final AtomConstructor UNIT =
|
private final AtomConstructor unit;
|
||||||
new AtomConstructor("Unit", BUILTIN_SCOPE).initializeFields();
|
|
||||||
public static final AtomConstructor NIL =
|
|
||||||
new AtomConstructor("Nil", BUILTIN_SCOPE).initializeFields();
|
|
||||||
public static final AtomConstructor CONS =
|
|
||||||
new AtomConstructor("Cons", BUILTIN_SCOPE)
|
|
||||||
.initializeFields(
|
|
||||||
new ArgumentDefinition(0, "head", false), new ArgumentDefinition(1, "rest", false));
|
|
||||||
|
|
||||||
static {
|
/**
|
||||||
BUILTIN_SCOPE.registerConstructor(Builtins.CONS);
|
* Creates an instance with builtin methods installed.
|
||||||
BUILTIN_SCOPE.registerConstructor(Builtins.NIL);
|
*
|
||||||
BUILTIN_SCOPE.registerConstructor(Builtins.UNIT);
|
* @param language the current {@link Language} instance
|
||||||
|
*/
|
||||||
|
public Builtins(Language language) {
|
||||||
|
scope = new ModuleScope();
|
||||||
|
unit = new AtomConstructor("Unit", scope).initializeFields();
|
||||||
|
|
||||||
|
AtomConstructor nil = new AtomConstructor("Nil", scope).initializeFields();
|
||||||
|
AtomConstructor cons =
|
||||||
|
new AtomConstructor("Cons", scope)
|
||||||
|
.initializeFields(
|
||||||
|
new ArgumentDefinition(0, "head", false), new ArgumentDefinition(1, "rest", false));
|
||||||
|
AtomConstructor io = new AtomConstructor("IO", scope).initializeFields();
|
||||||
|
|
||||||
|
scope.registerConstructor(cons);
|
||||||
|
scope.registerConstructor(nil);
|
||||||
|
scope.registerConstructor(unit);
|
||||||
|
scope.registerConstructor(io);
|
||||||
|
|
||||||
|
scope.registerMethod(io, "println", PrintNode.toFunction(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@code Unit} atom constructor.
|
||||||
|
*
|
||||||
|
* @return the {@code Unit} atom constructor
|
||||||
|
*/
|
||||||
|
public AtomConstructor unit() {
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the builtin module scope.
|
||||||
|
*
|
||||||
|
* @return the builtin module scope
|
||||||
|
*/
|
||||||
|
public ModuleScope getScope() {
|
||||||
|
return scope;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import org.enso.interpreter.Language;
|
|||||||
import org.enso.interpreter.builder.ModuleScopeExpressionFactory;
|
import org.enso.interpreter.builder.ModuleScopeExpressionFactory;
|
||||||
import org.enso.interpreter.node.EnsoRootNode;
|
import org.enso.interpreter.node.EnsoRootNode;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.error.ModuleDoesNotExistException;
|
import org.enso.interpreter.runtime.error.ModuleDoesNotExistException;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
import org.enso.interpreter.util.ScalaConversions;
|
import org.enso.interpreter.util.ScalaConversions;
|
||||||
@ -36,6 +37,7 @@ public class Context {
|
|||||||
private final Env environment;
|
private final Env environment;
|
||||||
private final Map<String, Module> knownFiles;
|
private final Map<String, Module> knownFiles;
|
||||||
private final PrintStream out;
|
private final PrintStream out;
|
||||||
|
private final Builtins builtins;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Enso context.
|
* Creates a new Enso context.
|
||||||
@ -47,6 +49,7 @@ public class Context {
|
|||||||
this.language = language;
|
this.language = language;
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.out = new PrintStream(environment.out());
|
this.out = new PrintStream(environment.out());
|
||||||
|
this.builtins = new Builtins(language);
|
||||||
|
|
||||||
List<File> packagePaths = RuntimeOptions.getPackagesPaths(environment);
|
List<File> packagePaths = RuntimeOptions.getPackagesPaths(environment);
|
||||||
// TODO [MK] Replace getTruffleFile with getInternalTruffleFile when Graal 19.3.0 comes out.
|
// TODO [MK] Replace getTruffleFile with getInternalTruffleFile when Graal 19.3.0 comes out.
|
||||||
@ -86,7 +89,7 @@ public class Context {
|
|||||||
* @return a call target which execution corresponds to the toplevel executable bits in the module
|
* @return a call target which execution corresponds to the toplevel executable bits in the module
|
||||||
*/
|
*/
|
||||||
public CallTarget parse(Source source) {
|
public CallTarget parse(Source source) {
|
||||||
return parse(source, new ModuleScope());
|
return parse(source, createScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,4 +134,29 @@ public class Context {
|
|||||||
public PrintStream getOut() {
|
public PrintStream getOut() {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new module scope that automatically imports all the builtin types and methods.
|
||||||
|
*
|
||||||
|
* @return a new module scope with automatic builtins dependency.
|
||||||
|
*/
|
||||||
|
public ModuleScope createScope() {
|
||||||
|
ModuleScope moduleScope = new ModuleScope();
|
||||||
|
moduleScope.addImport(getBuiltins().getScope());
|
||||||
|
return moduleScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Builtins getBuiltins() {
|
||||||
|
return builtins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the atom constructor corresponding to the {@code Unit} type, for builtin constructs
|
||||||
|
* that need to return an atom of this type.
|
||||||
|
*
|
||||||
|
* @return the builtin {@code Unit} atom constructor
|
||||||
|
*/
|
||||||
|
public AtomConstructor getUnit() {
|
||||||
|
return getBuiltins().unit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class Module {
|
|||||||
*/
|
*/
|
||||||
public ModuleScope requestParse(Context context) throws IOException {
|
public ModuleScope requestParse(Context context) throws IOException {
|
||||||
if (cachedScope == null) {
|
if (cachedScope == null) {
|
||||||
cachedScope = new ModuleScope();
|
cachedScope = context.createScope();
|
||||||
context.parse(file, cachedScope);
|
context.parse(file, cachedScope);
|
||||||
}
|
}
|
||||||
return cachedScope;
|
return cachedScope;
|
||||||
|
@ -48,7 +48,7 @@ public class ArgumentSchema {
|
|||||||
*
|
*
|
||||||
* @param argumentInfos Definition site arguments information
|
* @param argumentInfos Definition site arguments information
|
||||||
*/
|
*/
|
||||||
public ArgumentSchema(ArgumentDefinition[] argumentInfos) {
|
public ArgumentSchema(ArgumentDefinition... argumentInfos) {
|
||||||
this(argumentInfos, new boolean[argumentInfos.length], new CallArgumentInfo[0]);
|
this(argumentInfos, new boolean[argumentInfos.length], new CallArgumentInfo[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.enso.interpreter.runtime.scope;
|
package org.enso.interpreter.runtime.scope;
|
||||||
|
|
||||||
import org.enso.interpreter.runtime.Builtins;
|
import org.enso.interpreter.runtime.Builtins;
|
||||||
|
import org.enso.interpreter.runtime.Module;
|
||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
|
||||||
@ -14,11 +15,6 @@ public class ModuleScope {
|
|||||||
private final Set<ModuleScope> imports = new HashSet<>();
|
private final Set<ModuleScope> imports = new HashSet<>();
|
||||||
private final Set<ModuleScope> transitiveImports = new HashSet<>();
|
private final Set<ModuleScope> transitiveImports = new HashSet<>();
|
||||||
|
|
||||||
/** Creates a new scope. Every scope implicitly imports the builtin scope. */
|
|
||||||
public ModuleScope() {
|
|
||||||
imports.add(Builtins.BUILTIN_SCOPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an Atom constructor definition to the module scope.
|
* Adds an Atom constructor definition to the module scope.
|
||||||
*
|
*
|
||||||
@ -81,9 +77,13 @@ public class ModuleScope {
|
|||||||
*/
|
*/
|
||||||
public Function lookupMethodDefinition(AtomConstructor atom, String name) {
|
public Function lookupMethodDefinition(AtomConstructor atom, String name) {
|
||||||
Function definedWithAtom = atom.getDefinitionScope().getMethodMapFor(atom).get(name);
|
Function definedWithAtom = atom.getDefinitionScope().getMethodMapFor(atom).get(name);
|
||||||
if (definedWithAtom != null) { return definedWithAtom; }
|
if (definedWithAtom != null) {
|
||||||
|
return definedWithAtom;
|
||||||
|
}
|
||||||
Function definedHere = getMethodMapFor(atom).get(name);
|
Function definedHere = getMethodMapFor(atom).get(name);
|
||||||
if (definedHere != null) { return definedHere; }
|
if (definedHere != null) {
|
||||||
|
return definedHere;
|
||||||
|
}
|
||||||
return transitiveImports.stream()
|
return transitiveImports.stream()
|
||||||
.map(scope -> scope.getMethodMapFor(atom).get(name))
|
.map(scope -> scope.getMethodMapFor(atom).get(name))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
|
@ -41,8 +41,6 @@ trait AstExpressionVisitor[+T] {
|
|||||||
|
|
||||||
def visitAssignment(varName: String, expr: AstExpression): T
|
def visitAssignment(varName: String, expr: AstExpression): T
|
||||||
|
|
||||||
def visitPrint(body: AstExpression): T
|
|
||||||
|
|
||||||
def visitMatch(
|
def visitMatch(
|
||||||
target: AstExpression,
|
target: AstExpression,
|
||||||
branches: java.util.List[AstCase],
|
branches: java.util.List[AstCase],
|
||||||
@ -203,11 +201,6 @@ case class AstAssignment(name: String, body: AstExpression)
|
|||||||
visitor.visitAssignment(name, body)
|
visitor.visitAssignment(name, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class AstPrint(body: AstExpression) extends AstExpression {
|
|
||||||
override def visit[T](visitor: AstExpressionVisitor[T]): T =
|
|
||||||
visitor.visitPrint(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
case class AstIfZero(
|
case class AstIfZero(
|
||||||
cond: AstExpression,
|
cond: AstExpression,
|
||||||
ifTrue: AstExpression,
|
ifTrue: AstExpression,
|
||||||
@ -293,7 +286,7 @@ class EnsoParserInternal extends JavaTokenParsers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def expression: Parser[AstExpression] =
|
def expression: Parser[AstExpression] =
|
||||||
desuspend | print | ifZero | matchClause | arith | function
|
desuspend | ifZero | matchClause | arith | function
|
||||||
|
|
||||||
def functionCall: Parser[AstApply] =
|
def functionCall: Parser[AstApply] =
|
||||||
"@" ~> expression ~ (argList ?) ~ defaultSuspend ^^ {
|
"@" ~> expression ~ (argList ?) ~ defaultSuspend ^^ {
|
||||||
@ -313,8 +306,6 @@ class EnsoParserInternal extends JavaTokenParsers {
|
|||||||
case v ~ exp => AstAssignment(v, exp)
|
case v ~ exp => AstAssignment(v, exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
def print: Parser[AstPrint] = "print:" ~> expression ^^ AstPrint
|
|
||||||
|
|
||||||
def ifZero: Parser[AstIfZero] =
|
def ifZero: Parser[AstIfZero] =
|
||||||
"ifZero:" ~> "[" ~> (expression ~ ("," ~> expression ~ ("," ~> expression))) <~ "]" ^^ {
|
"ifZero:" ~> "[" ~> (expression ~ ("," ~> expression ~ ("," ~> expression))) <~ "]" ^^ {
|
||||||
case cond ~ (ift ~ iff) => AstIfZero(cond, ift, iff)
|
case cond ~ (ift ~ iff) => AstIfZero(cond, ift, iff)
|
||||||
|
@ -8,7 +8,7 @@ class LazyArgumentsTest extends LanguageTest {
|
|||||||
"""
|
"""
|
||||||
|@{
|
|@{
|
||||||
| foo = { |i, $x, $y| ifZero: [i, $x, $y] };
|
| foo = { |i, $x, $y| ifZero: [i, $x, $y] };
|
||||||
| @foo [1, (print: 1), (print: 2)]
|
| @foo [1, @println [@IO, 1], @println [@IO, 2]]
|
||||||
|}
|
|}
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
noException should be thrownBy parse(code)
|
noException should be thrownBy parse(code)
|
||||||
@ -53,9 +53,9 @@ class LazyArgumentsTest extends LanguageTest {
|
|||||||
|Bar.method = { |x| 10 }
|
|Bar.method = { |x| 10 }
|
||||||
|
|
|
|
||||||
|@{
|
|@{
|
||||||
| @method [@Foo, (print: 1)];
|
| @method [@Foo, @println [@IO, 1]];
|
||||||
| @method [@Bar, (print: 2)];
|
| @method [@Bar, @println [@IO, 2]];
|
||||||
| @method [@Foo, (print: 3)]
|
| @method [@Foo, @println [@IO, 3]]
|
||||||
|}
|
|}
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
@ -68,8 +68,8 @@ class LazyArgumentsTest extends LanguageTest {
|
|||||||
|@{
|
|@{
|
||||||
| if = { |c, $ifT, $ifF| ifZero: [c, $ifT, $ifF] };
|
| if = { |c, $ifT, $ifF| ifZero: [c, $ifT, $ifF] };
|
||||||
| foo = { |c| @if [c] };
|
| foo = { |c| @if [c] };
|
||||||
| @foo [0, (print: 1), (print: 2)];
|
| @foo [0, @println [@IO, 1], @println [@IO, 2]];
|
||||||
| @foo [1, (print: 3), (print: 4)]
|
| @foo [1, @println [@IO, 3], @println [@IO, 4]]
|
||||||
|}
|
|}
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
|
Loading…
Reference in New Issue
Block a user