| Index: pkg/kernel/lib/interpreter/interpreter.dart
|
| diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
|
| index a232e75363f8a0475e3376401452a88448a6651a..3c03c70da76346a5d873306d833a19365bbc8033 100644
|
| --- a/pkg/kernel/lib/interpreter/interpreter.dart
|
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart
|
| @@ -30,8 +30,8 @@ class Interpreter {
|
| if (mainMethod == null) return;
|
|
|
| Statement statementBlock = mainMethod.function.body;
|
| - ExecConfiguration configuration =
|
| - new ExecConfiguration(statementBlock, new State.initial());
|
| + ExecConfiguration configuration = new ExecConfiguration(
|
| + statementBlock, new Environment.empty(), const State.initial());
|
| visitor.trampolinedExecution(configuration);
|
| }
|
| }
|
| @@ -53,9 +53,11 @@ class Environment {
|
| final List<Binding> bindings = <Binding>[];
|
| final Environment parent;
|
|
|
| - Value get thisInstance => (parent != null)
|
| - ? parent.thisInstance
|
| - : throw "Invalid reference to 'this' expression";
|
| + Value get thisInstance {
|
| + return containsThis()
|
| + ? lookupThis().value
|
| + : throw "Invalid reference to 'this' expression";
|
| + }
|
|
|
| Environment.empty() : parent = null;
|
| Environment(this.parent);
|
| @@ -67,6 +69,13 @@ class Environment {
|
| return parent?.contains(variable) ?? false;
|
| }
|
|
|
| + bool containsThis() {
|
| + for (Binding b in bindings.reversed) {
|
| + if (identical(b.variable.name, 'this')) return true;
|
| + }
|
| + return parent?.containsThis() ?? false;
|
| + }
|
| +
|
| Binding lookupBinding(VariableDeclaration variable) {
|
| assert(contains(variable));
|
| for (Binding b in bindings) {
|
| @@ -75,6 +84,14 @@ class Environment {
|
| return parent.lookupBinding(variable);
|
| }
|
|
|
| + Location lookupThis() {
|
| + assert(containsThis());
|
| + for (Binding b in bindings) {
|
| + if (identical(b.variable.name, 'this')) return b.location;
|
| + }
|
| + return parent.lookupThis();
|
| + }
|
| +
|
| Value lookup(VariableDeclaration variable) {
|
| return lookupBinding(variable).location.value;
|
| }
|
| @@ -84,17 +101,16 @@ class Environment {
|
| lookupBinding(variable).location.value = value;
|
| }
|
|
|
| - void expand(VariableDeclaration variable, Value value) {
|
| + Environment extend(VariableDeclaration variable, Value value) {
|
| assert(!contains(variable));
|
| - bindings.add(new Binding(variable, new Location(value)));
|
| + return new Environment(this)
|
| + ..bindings.add(new Binding(variable, new Location(value)));
|
| }
|
| -}
|
|
|
| -class InstanceEnvironment extends Environment {
|
| - final ObjectValue _thisInstance;
|
| - Value get thisInstance => _thisInstance;
|
| -
|
| - InstanceEnvironment(this._thisInstance, Environment env) : super(env);
|
| + Environment extendWithThis(ObjectValue v) {
|
| + assert(!containsThis());
|
| + return extend(new VariableDeclaration('this'), v);
|
| + }
|
| }
|
|
|
| /// Evaluate expressions.
|
| @@ -106,7 +122,7 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
| ApplicationContinuation cont) {
|
| if (list.isNotEmpty) {
|
| return new EvalConfiguration(list.first.expression, env,
|
| - new ExpressionListContinuation(list.first, list.skip(1), env, cont));
|
| + new ExpressionListEK(list.first, list.skip(1), env, cont));
|
| }
|
| return new ApplicationConfiguration(cont, <InterpreterValue>[]);
|
| }
|
| @@ -127,18 +143,18 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
| }
|
|
|
| Configuration visitVariableSet(VariableSet node, EvalConfiguration config) {
|
| - var cont = new VariableSetContinuation(
|
| + var cont = new VariableSetEK(
|
| node.variable, config.environment, config.continuation);
|
| return new EvalConfiguration(node.value, config.environment, cont);
|
| }
|
|
|
| Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) {
|
| - var cont = new PropertyGetContinuation(node.name, config.continuation);
|
| + var cont = new PropertyGetEK(node.name, config.continuation);
|
| return new EvalConfiguration(node.receiver, config.environment, cont);
|
| }
|
|
|
| Configuration visitPropertySet(PropertySet node, EvalConfiguration config) {
|
| - var cont = new PropertySetContinuation(
|
| + var cont = new PropertySetEK(
|
| node.value, node.name, config.environment, config.continuation);
|
| return new EvalConfiguration(node.receiver, config.environment, cont);
|
| }
|
| @@ -151,7 +167,7 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
| Configuration visitStaticInvocation(
|
| StaticInvocation node, EvalConfiguration config) {
|
| if ('print' == node.name.toString()) {
|
| - var cont = new PrintContinuation(config.continuation);
|
| + var cont = new PrintEK(config.continuation);
|
| return new EvalConfiguration(
|
| node.arguments.positional.first, config.environment, cont);
|
| } else {
|
| @@ -159,8 +175,8 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
|
|
| List<InterpreterExpression> args =
|
| _createArgumentExpressionList(node.arguments, node.target.function);
|
| - ApplicationContinuation cont = new StaticInvocationApplication(
|
| - node.target.function, config.continuation);
|
| + ApplicationContinuation cont =
|
| + new StaticInvocationA(node.target.function, config.continuation);
|
| return new EvalListConfiguration(args, config.environment, cont);
|
| }
|
| }
|
| @@ -169,51 +185,43 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
| MethodInvocation node, EvalConfiguration config) {
|
| // Currently supports only method invocation with <2 arguments and is used
|
| // to evaluate implemented operators for int, double and String values.
|
| - var cont = new MethodInvocationContinuation(
|
| + var cont = new MethodInvocationEK(
|
| node.arguments, node.name, config.environment, config.continuation);
|
|
|
| return new EvalConfiguration(node.receiver, config.environment, cont);
|
| }
|
|
|
| Configuration visitConstructorInvocation(
|
| - ConstructorInvocation node, EvalConfiguration config) {
|
| - ApplicationContinuation cont =
|
| - new ConstructorInvocationApplication(node.target, config.continuation);
|
| - var args =
|
| - _createArgumentExpressionList(node.arguments, node.target.function);
|
| -
|
| - return new EvalListConfiguration(args, config.environment, cont);
|
| - }
|
| + ConstructorInvocation node, EvalConfiguration config) =>
|
| + defaultExpression(node, config);
|
|
|
| Configuration visitNot(Not node, EvalConfiguration config) {
|
| - return new EvalConfiguration(node.operand, config.environment,
|
| - new NotContinuation(config.continuation));
|
| + return new EvalConfiguration(
|
| + node.operand, config.environment, new NotEK(config.continuation));
|
| }
|
|
|
| Configuration visitLogicalExpression(
|
| LogicalExpression node, EvalConfiguration config) {
|
| if ('||' == node.operator) {
|
| - var cont = new OrContinuation(
|
| - node.right, config.environment, config.continuation);
|
| + var cont = new OrEK(node.right, config.environment, config.continuation);
|
| return new EvalConfiguration(node.left, config.environment, cont);
|
| } else {
|
| assert('&&' == node.operator);
|
| - var cont = new AndContinuation(
|
| - node.right, config.environment, config.continuation);
|
| + var cont = new AndEK(node.right, config.environment, config.continuation);
|
| return new EvalConfiguration(node.left, config.environment, cont);
|
| }
|
| }
|
|
|
| Configuration visitConditionalExpression(
|
| ConditionalExpression node, EvalConfiguration config) {
|
| - var cont = new ConditionalContinuation(
|
| + var cont = new ConditionalEK(
|
| node.then, node.otherwise, config.environment, config.continuation);
|
| return new EvalConfiguration(node.condition, config.environment, cont);
|
| }
|
|
|
| Configuration visitStringConcatenation(
|
| StringConcatenation node, EvalConfiguration config) {
|
| - var cont = new StringConcatenationContinuation(config.continuation);
|
| + var cont = new StringConcatenationA(config.continuation);
|
| var expressions = node.expressions
|
| .map((Expression e) => new PositionalExpression(e))
|
| .toList();
|
| @@ -255,7 +263,7 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
| }
|
|
|
| Configuration visitLet(Let node, EvalConfiguration config) {
|
| - var letCont = new LetContinuation(
|
| + var letCont = new LetEK(
|
| node.variable, node.body, config.environment, config.continuation);
|
| return new EvalConfiguration(
|
| node.variable.initializer, config.environment, letCont);
|
| @@ -264,33 +272,30 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
|
|
|
| /// Represents a state for statement execution.
|
| class State {
|
| - final Environment environment;
|
| final Label labels;
|
| - final ExecConfiguration statementConfiguration;
|
| -
|
| + // TODO: Add switch labels.
|
| + // TODO: Add component for exception support
|
| final ExpressionContinuation returnContinuation;
|
| + final StatementContinuation continuation;
|
|
|
| - State(this.environment, this.labels, this.statementConfiguration,
|
| - this.returnContinuation);
|
| + State(this.labels, this.returnContinuation, this.continuation);
|
|
|
| - State.initial() : this(new Environment.empty(), null, null, null);
|
| -
|
| - State withEnvironment(Environment env) {
|
| - return new State(env, labels, statementConfiguration, returnContinuation);
|
| - }
|
| + const State.initial()
|
| + : labels = null,
|
| + returnContinuation = null,
|
| + continuation = null;
|
|
|
| - State withBreak(Statement stmt) {
|
| - Label breakLabels = new Label(stmt, statementConfiguration, labels);
|
| - return new State(
|
| - environment, breakLabels, statementConfiguration, returnContinuation);
|
| + State withBreak(Statement stmt, Environment env) {
|
| + Label breakLabels = new Label(stmt, env, continuation, labels);
|
| + return new State(breakLabels, returnContinuation, continuation);
|
| }
|
|
|
| - State withConfiguration(Configuration config) {
|
| - return new State(environment, labels, config, returnContinuation);
|
| + State withReturnContinuation(ExpressionContinuation returnCont) {
|
| + return new State(labels, returnCont, continuation);
|
| }
|
|
|
| - State withExpressionContinuation(ExpressionContinuation cont) {
|
| - return new State(environment, labels, statementConfiguration, cont);
|
| + State withContinuation(StatementContinuation cont) {
|
| + return new State(labels, returnContinuation, cont);
|
| }
|
|
|
| Label lookupLabel(LabeledStatement s) {
|
| @@ -303,10 +308,12 @@ class State {
|
| /// enclosing label.
|
| class Label {
|
| final LabeledStatement statement;
|
| - final ExecConfiguration configuration;
|
| + final Environment environment;
|
| + final StatementContinuation continuation;
|
| final Label enclosingLabel;
|
|
|
| - Label(this.statement, this.configuration, this.enclosingLabel);
|
| + Label(
|
| + this.statement, this.environment, this.continuation, this.enclosingLabel);
|
|
|
| Label lookupLabel(LabeledStatement s) {
|
| if (identical(s, statement)) return this;
|
| @@ -315,45 +322,66 @@ class Label {
|
| }
|
| }
|
|
|
| +// ------------------------------------------------------------------------
|
| +// Configurations
|
| +// ------------------------------------------------------------------------
|
| +
|
| abstract class Configuration {
|
| /// Executes the current and returns the next configuration.
|
| Configuration step(StatementExecuter executer);
|
| }
|
|
|
| -/// Represents the configuration for execution of statement.
|
| -class ExecConfiguration extends Configuration {
|
| - final Statement statement;
|
| - final State state;
|
| +/// Configuration for evaluating an [Expression].
|
| +class EvalConfiguration extends Configuration {
|
| + final Expression expression;
|
| +
|
| + /// Environment in which the expression is evaluated.
|
| + final Environment environment;
|
| +
|
| + /// Next continuation to be applied.
|
| + final Continuation continuation;
|
|
|
| - ExecConfiguration(this.statement, this.state);
|
| + EvalConfiguration(this.expression, this.environment, this.continuation);
|
|
|
| Configuration step(StatementExecuter executer) =>
|
| - executer.exec(statement, state);
|
| + executer.eval(expression, this);
|
| }
|
|
|
| -class ExitConfiguration extends ExecConfiguration {
|
| - final ExpressionContinuation returnContinuation;
|
| +/// Configuration for evaluating a [List<InterpreterExpression>].
|
| +class EvalListConfiguration extends Configuration {
|
| + final List<InterpreterExpression> expressions;
|
| + final Environment environment;
|
| + final ApplicationContinuation continuation;
|
|
|
| - ExitConfiguration(this.returnContinuation) : super(null, null);
|
| + EvalListConfiguration(this.expressions, this.environment, this.continuation);
|
|
|
| - Configuration step(StatementExecuter _) {
|
| - return returnContinuation(Value.nullInstance);
|
| - }
|
| + Configuration step(StatementExecuter executer) =>
|
| + executer.evalList(expressions, environment, continuation);
|
| }
|
|
|
| -class NewInstanceConfiguration extends ExecConfiguration {
|
| - final ExpressionContinuation continuation;
|
| - final ObjectValue newObject;
|
| +/// Configuration for execution of a [Statement].
|
| +class ExecConfiguration extends Configuration {
|
| + final Statement currentStatement;
|
| + final Environment environment;
|
| + final State state;
|
|
|
| - NewInstanceConfiguration(this.continuation, this.newObject)
|
| - : super(null, new State.initial());
|
| + ExecConfiguration(this.currentStatement, this.environment, this.state);
|
|
|
| - Configuration step(StatementExecuter _) {
|
| - return continuation(newObject);
|
| - }
|
| + Configuration step(StatementExecuter executer) =>
|
| + executer.exec(currentStatement, this);
|
| +}
|
| +
|
| +/// Configuration for applying a [StatementContinuation] to an [Environment].
|
| +class ForwardConfiguration extends Configuration {
|
| + final StatementContinuation continuation;
|
| + final Environment environment;
|
| +
|
| + ForwardConfiguration(this.continuation, this.environment);
|
| +
|
| + Configuration step(StatementExecuter _) => continuation?.call(environment);
|
| }
|
|
|
| -/// Represents the configuration for applying an [ExpressionContinuation].
|
| +/// Configuration for applying [ExpressionContinuation] to a [Value].
|
| class ValuePassingConfiguration extends Configuration {
|
| final ExpressionContinuation continuation;
|
| final Value value;
|
| @@ -363,7 +391,8 @@ class ValuePassingConfiguration extends Configuration {
|
| Configuration step(StatementExecuter _) => continuation(value);
|
| }
|
|
|
| -/// Represents the configuration for applying an [ApplicationContinuation].
|
| +/// Configuration for applying an [ApplicationContinuation] to a
|
| +/// [List<InterpreterValue>].
|
| class ApplicationConfiguration extends Configuration {
|
| final ApplicationContinuation continuation;
|
| final List<InterpreterValue> values;
|
| @@ -373,33 +402,9 @@ class ApplicationConfiguration extends Configuration {
|
| Configuration step(StatementExecuter _) => continuation(values);
|
| }
|
|
|
| -/// Represents the configuration for evaluating an [Expression].
|
| -class EvalConfiguration extends Configuration {
|
| - final Expression expression;
|
| -
|
| - /// Environment in which the expression is evaluated.
|
| - final Environment environment;
|
| -
|
| - /// Next continuation to be applied.
|
| - final Continuation continuation;
|
| -
|
| - EvalConfiguration(this.expression, this.environment, this.continuation);
|
| -
|
| - Configuration step(StatementExecuter executer) =>
|
| - executer.eval(expression, this);
|
| -}
|
| -
|
| -/// Represents the configuration for evaluating a list of expressions.
|
| -class EvalListConfiguration extends Configuration {
|
| - final List<InterpreterExpression> expressions;
|
| - final Environment environment;
|
| - final Continuation continuation;
|
| -
|
| - EvalListConfiguration(this.expressions, this.environment, this.continuation);
|
| -
|
| - Configuration step(StatementExecuter executer) =>
|
| - executer.evalList(expressions, environment, continuation);
|
| -}
|
| +// ------------------------------------------------------------------------
|
| +// Interpreter Expressions and Values
|
| +// ------------------------------------------------------------------------
|
|
|
| abstract class InterpreterExpression {
|
| Expression get expression;
|
| @@ -423,17 +428,6 @@ class NamedExpression extends InterpreterExpression {
|
| InterpreterValue assignValue(Value v) => new NamedValue(name, v);
|
| }
|
|
|
| -class LocalInitializerExpression extends InterpreterExpression {
|
| - final VariableDeclaration variable;
|
| -
|
| - Expression get expression => variable.initializer;
|
| -
|
| - LocalInitializerExpression(this.variable);
|
| -
|
| - InterpreterValue assignValue(Value v) =>
|
| - new LocalInitializerValue(variable, v);
|
| -}
|
| -
|
| class FieldInitializerExpression extends InterpreterExpression {
|
| final Field field;
|
| final Expression expression;
|
| @@ -460,13 +454,6 @@ class NamedValue extends InterpreterValue {
|
| NamedValue(this.name, this.value);
|
| }
|
|
|
| -class LocalInitializerValue extends InterpreterValue {
|
| - final VariableDeclaration variable;
|
| - final Value value;
|
| -
|
| - LocalInitializerValue(this.variable, this.value);
|
| -}
|
| -
|
| class FieldInitializerValue extends InterpreterValue {
|
| final Field field;
|
| final Value value;
|
| @@ -476,8 +463,89 @@ class FieldInitializerValue extends InterpreterValue {
|
|
|
| abstract class Continuation {}
|
|
|
| +// ------------------------------------------------------------------------
|
| +// Statement Continuations
|
| +// ------------------------------------------------------------------------
|
| +
|
| +/// Represents a the continuation for the execution of the next statement of
|
| +/// the program.
|
| +///
|
| +/// There are various kinds of [StatementContinuation]s and their names are
|
| +/// suffixed with "SK"
|
| +abstract class StatementContinuation extends Continuation {
|
| + Configuration call(Environment env);
|
| +}
|
| +
|
| +/// Applies the expression continuation to the provided value.
|
| +class ExitSK extends StatementContinuation {
|
| + final ExpressionContinuation continuation;
|
| + final Value value;
|
| +
|
| + ExitSK(this.continuation, this.value);
|
| +
|
| + Configuration call(Environment _) =>
|
| + new ValuePassingConfiguration(continuation, value);
|
| +}
|
| +
|
| +/// Executes the next statement from a block with the corresponding environment
|
| +/// or proceeds with next statement continuation.
|
| +class BlockSK extends StatementContinuation {
|
| + final List<Statement> statements;
|
| + final Environment enclosingEnv;
|
| + final State state;
|
| +
|
| + BlockSK(this.statements, this.enclosingEnv, this.state);
|
| +
|
| + BlockSK.fromConfig(this.statements, ExecConfiguration conf)
|
| + : enclosingEnv = conf.environment,
|
| + state = conf.state;
|
| +
|
| + Configuration call(Environment env) {
|
| + if (statements.isEmpty) {
|
| + return new ForwardConfiguration(state.continuation, enclosingEnv);
|
| + }
|
| + // Proceed with the execution statement when there are some remaining to
|
| + // be executed.
|
| + var cont = new BlockSK(statements.skip(1).toList(), enclosingEnv, state);
|
| + return new ExecConfiguration(
|
| + statements.first, env, state.withContinuation(cont));
|
| + }
|
| +}
|
| +
|
| +class NewSK extends StatementContinuation {
|
| + final ExpressionContinuation continuation;
|
| + final Location location;
|
| +
|
| + NewSK(this.continuation, this.location);
|
| +
|
| + Configuration call(Environment _) =>
|
| + new ValuePassingConfiguration(continuation, location.value);
|
| +}
|
| +
|
| +class WhileConditionSK extends StatementContinuation {
|
| + final Expression condition;
|
| + final Statement body;
|
| + final Environment enclosingEnv;
|
| + final State state;
|
| +
|
| + WhileConditionSK(this.condition, this.body, this.enclosingEnv, this.state);
|
| +
|
| + Configuration call(Environment _) {
|
| + // Evaluate the condition for the while loop execution.
|
| + var cont = new WhileConditionEK(condition, body, enclosingEnv, state);
|
| + return new EvalConfiguration(condition, enclosingEnv, cont);
|
| + }
|
| +}
|
| +
|
| +// ------------------------------------------------------------------------
|
| +// Application Continuations
|
| +// ------------------------------------------------------------------------
|
| +
|
| /// Represents the continuation called after the evaluation of argument
|
| /// expressions.
|
| +///
|
| +/// There are various kinds of [ApplicationContinuation] and their names are
|
| +/// suffixed with "A".
|
| abstract class ApplicationContinuation extends Continuation {
|
| Configuration call(List<InterpreterValue> values);
|
|
|
| @@ -487,14 +555,16 @@ abstract class ApplicationContinuation extends Continuation {
|
| static Environment createEnvironment(
|
| FunctionNode function, List<InterpreterValue> args,
|
| [Environment parentEnv]) {
|
| - Environment newEnv = new Environment(parentEnv);
|
| + Environment newEnv = new Environment(parentEnv ?? new Environment.empty());
|
| +
|
| List<PositionalValue> positional = args.reversed
|
| .where((InterpreterValue av) => av is PositionalValue)
|
| .toList();
|
|
|
| // Add positional parameters.
|
| for (int i = 0; i < positional.length; ++i) {
|
| - newEnv.expand(function.positionalParameters[i], positional[i].value);
|
| + newEnv =
|
| + newEnv.extend(function.positionalParameters[i], positional[i].value);
|
| }
|
|
|
| Map<String, Value> named = new Map.fromIterable(
|
| @@ -504,314 +574,88 @@ abstract class ApplicationContinuation extends Continuation {
|
|
|
| // Add named parameters.
|
| for (VariableDeclaration v in function.namedParameters) {
|
| - newEnv.expand(v, named[v.name.toString()]);
|
| + newEnv = newEnv.extend(v, named[v.name.toString()]);
|
| }
|
|
|
| return newEnv;
|
| }
|
| }
|
|
|
| -/// Represents the application continuation for static invocation.
|
| -class StaticInvocationApplication extends ApplicationContinuation {
|
| - final FunctionNode function;
|
| - final ExpressionContinuation continuation;
|
| -
|
| - StaticInvocationApplication(this.function, this.continuation);
|
| +/// Represents the application continuation called after the evaluation of all
|
| +/// argument expressions for an invocation.
|
| +class ValueA extends ApplicationContinuation {
|
| + final InterpreterValue value;
|
| + final ApplicationContinuation applicationContinuation;
|
|
|
| - Configuration call(List<InterpreterValue> argValues) {
|
| - Environment functionEnv =
|
| - ApplicationContinuation.createEnvironment(function, argValues);
|
| + ValueA(this.value, this.applicationContinuation);
|
|
|
| - State bodyState = new State.initial()
|
| - .withExpressionContinuation(continuation)
|
| - .withConfiguration(new ExitConfiguration(continuation))
|
| - .withEnvironment(functionEnv);
|
| - return new ExecConfiguration(function.body, bodyState);
|
| + Configuration call(List<InterpreterValue> args) {
|
| + args.add(value);
|
| + return new ApplicationConfiguration(applicationContinuation, args);
|
| }
|
| }
|
|
|
| -/// Represents the application continuation for constructor invocation applied
|
| -/// on the list of evaluated arguments.
|
| -class ConstructorInvocationApplication extends ApplicationContinuation {
|
| - final Constructor constructor;
|
| +class StringConcatenationA extends ApplicationContinuation {
|
| final ExpressionContinuation continuation;
|
|
|
| - ConstructorInvocationApplication(this.constructor, this.continuation);
|
| -
|
| - Configuration call(List<InterpreterValue> argValues) {
|
| - Environment ctrEnv = ApplicationContinuation.createEnvironment(
|
| - constructor.function, argValues);
|
| -
|
| - var class_ = new Class(constructor.enclosingClass.reference);
|
| - var newObject =
|
| - new ObjectValue(class_, new List<Value>(class_.instanceSize));
|
| -
|
| - return new ObjectInitializationConfiguration(
|
| - constructor,
|
| - new InstanceEnvironment(newObject, ctrEnv),
|
| - new NewInstanceConfiguration(continuation, newObject));
|
| - }
|
| -}
|
| -
|
| -/// Represents the application continuation for redirecting constructor
|
| -/// invocation applied on the list of evaluated arguments.
|
| -class RedirectingConstructorApplication extends ApplicationContinuation {
|
| - final Constructor constructor;
|
| - final Environment environment;
|
| - final ExecConfiguration configuration;
|
| -
|
| - RedirectingConstructorApplication(
|
| - this.constructor, this.environment, this.configuration);
|
| + StringConcatenationA(this.continuation);
|
|
|
| - Configuration call(List<InterpreterValue> argValues) {
|
| - Value object = environment.thisInstance;
|
| - Environment ctrEnv = ApplicationContinuation.createEnvironment(
|
| - constructor.function,
|
| - argValues,
|
| - new InstanceEnvironment(object, new Environment.empty()));
|
| -
|
| - return new ObjectInitializationConfiguration(
|
| - constructor, ctrEnv, configuration);
|
| - }
|
| -}
|
| -
|
| -/// Represents the application continuation for super constructor
|
| -/// invocation applied on the list of evaluated arguments.
|
| -class SuperConstructorApplication extends ApplicationContinuation {
|
| - final Constructor constructor;
|
| - final Environment environment;
|
| - final ExecConfiguration configuration;
|
| -
|
| - SuperConstructorApplication(
|
| - this.constructor, this.environment, this.configuration);
|
| -
|
| - Configuration call(List<InterpreterValue> argValues) {
|
| - Value object = environment.thisInstance;
|
| -
|
| - Environment superEnv = ApplicationContinuation.createEnvironment(
|
| - constructor.function,
|
| - argValues,
|
| - new InstanceEnvironment(object, new Environment.empty()));
|
| -
|
| - return new ObjectInitializationConfiguration(
|
| - constructor, superEnv, configuration);
|
| - }
|
| -}
|
| -
|
| -/// Represents the configuration for execution of initializer and
|
| -/// constructor body statements for initialization of a newly allocated object.
|
| -class ObjectInitializationConfiguration extends Configuration {
|
| - final Constructor constructor;
|
| - final Environment environment;
|
| - final ExecConfiguration configuration;
|
| -
|
| - ObjectInitializationConfiguration(
|
| - this.constructor, this.environment, this.configuration);
|
| -
|
| - Configuration step(StatementExecuter _) {
|
| - if (constructor.initializers.isNotEmpty &&
|
| - constructor.initializers.last is RedirectingInitializer) {
|
| - // Constructor is redirecting.
|
| - Initializer initializer = constructor.initializers.first;
|
| - if (initializer is RedirectingInitializer) {
|
| - var app = new RedirectingConstructorApplication(
|
| - initializer.target, environment, configuration);
|
| - var args = _createArgumentExpressionList(
|
| - initializer.arguments, initializer.target.function);
|
| -
|
| - return new EvalListConfiguration(args, environment, app);
|
| - }
|
| - // Redirecting initializer is not the only initializer.
|
| - for (Initializer i in constructor.initializers.reversed.skip(1)) {
|
| - assert(i is LocalInitializer);
|
| - }
|
| - var class_ = new Class(constructor.enclosingClass.reference);
|
| - var initEnv = new Environment(environment);
|
| - var cont = new InitializerContinuation(
|
| - class_, initEnv, constructor.initializers, configuration);
|
| - return new EvalConfiguration(
|
| - (initializer as LocalInitializer).variable.initializer,
|
| - initEnv,
|
| - cont);
|
| - }
|
| -
|
| - // Set head of configurations to be executed to configuration for current
|
| - // constructor body.
|
| - var state = new State.initial()
|
| - .withEnvironment(environment)
|
| - .withConfiguration(configuration);
|
| - var bodyConfig = new ExecConfiguration(constructor.function.body, state);
|
| -
|
| - // Initialize fields in immediately enclosing class.
|
| - var cont =
|
| - new InstanceFieldsApplication(constructor, environment, bodyConfig);
|
| - var fieldExpressions = _createInstanceInitializers(constructor);
|
| -
|
| - return new EvalListConfiguration(
|
| - fieldExpressions, new Environment.empty(), cont);
|
| - }
|
| -
|
| - /// Creates a list of expressions for instance field initializers in
|
| - /// immediately enclosing class.
|
| - static List<InterpreterExpression> _createInstanceInitializers(
|
| - Constructor ctr) {
|
| - Class currentClass = new Class(ctr.enclosingClass.reference);
|
| - List<InterpreterExpression> es = <InterpreterExpression>[];
|
| -
|
| - for (int i = currentClass.superclass?.instanceSize ?? 0;
|
| - i < currentClass.instanceSize;
|
| - i++) {
|
| - Field current = currentClass.instanceFields[i];
|
| - if (current.initializer != null) {
|
| - es.add(new FieldInitializerExpression(current, current.initializer));
|
| - }
|
| - }
|
| -
|
| - return es;
|
| - }
|
| -}
|
| -
|
| -/// Represents the application continuation applied on the list of evaluated
|
| -/// field initializer expressions.
|
| -class InstanceFieldsApplication extends ApplicationContinuation {
|
| - final Constructor constructor;
|
| - final Environment environment;
|
| - final ExecConfiguration configuration;
|
| -
|
| - final Class _currentClass;
|
| - final ObjectValue _newObject;
|
| -
|
| - InstanceFieldsApplication(
|
| - this.constructor, this.environment, this.configuration)
|
| - : _currentClass = new Class(constructor.enclosingClass.reference),
|
| - _newObject = environment.thisInstance;
|
| -
|
| - Configuration call(List<InterpreterValue> fieldValues) {
|
| - for (FieldInitializerValue current in fieldValues.reversed) {
|
| - _currentClass.setProperty(_newObject, current.field, current.value);
|
| - }
|
| -
|
| - if (constructor.initializers.isEmpty) {
|
| - _initializeNullFields(_currentClass, _newObject);
|
| - return configuration;
|
| - }
|
| -
|
| - // Produce next configuration.
|
| - if (constructor.initializers.first is SuperInitializer) {
|
| - // SuperInitializer appears last in the initializer list.
|
| - assert(constructor.initializers.length == 1);
|
| - SuperInitializer current = constructor.initializers.first;
|
| - var args = _createArgumentExpressionList(
|
| - current.arguments, current.target.function);
|
| -
|
| - var superApp = new SuperConstructorApplication(
|
| - current.target, environment, configuration);
|
| - _initializeNullFields(_currentClass, _newObject);
|
| - return new EvalListConfiguration(args, environment, superApp);
|
| + Configuration call(List<InterpreterValue> values) {
|
| + StringBuffer result = new StringBuffer();
|
| + for (InterpreterValue v in values.reversed) {
|
| + result.write(v.value.value);
|
| }
|
| -
|
| - Class class_ = new Class(constructor.enclosingClass.reference);
|
| - Environment initEnv = new Environment(environment);
|
| -
|
| - var cont = new InitializerContinuation(
|
| - class_, initEnv, constructor.initializers, configuration);
|
| - return new EvalConfiguration(
|
| - _getExpression(constructor.initializers.first), initEnv, cont);
|
| + return new ValuePassingConfiguration(
|
| + continuation, new StringValue(result.toString()));
|
| }
|
| }
|
|
|
| -/// Represents the expression continuation applied on the list of evaluated
|
| -/// initializer expressions preceding a super call in the list.
|
| -class InitializerContinuation extends ExpressionContinuation {
|
| - final Class currentClass;
|
| - final Environment initializerEnvironment;
|
| - final List<Initializer> initializers;
|
| - final ExecConfiguration configuration;
|
| -
|
| - InitializerContinuation(this.currentClass, this.initializerEnvironment,
|
| - this.initializers, this.configuration);
|
| -
|
| - Configuration call(Value v) {
|
| - ObjectValue newObject = initializerEnvironment.thisInstance;
|
| - Initializer current = initializers.first;
|
| - if (current is FieldInitializer) {
|
| - currentClass.setProperty(newObject, current.field, v);
|
| - } else if (current is LocalInitializer) {
|
| - initializerEnvironment.expand(current.variable, v);
|
| - } else {
|
| - throw 'Assigning value $v to ${current.runtimeType}';
|
| - }
|
| -
|
| - if (initializers.length <= 1) {
|
| - _initializeNullFields(currentClass, newObject);
|
| - return configuration;
|
| - }
|
| -
|
| - Initializer next = initializers[1];
|
| +/// Represents the application continuation for static invocation.
|
| +class StaticInvocationA extends ApplicationContinuation {
|
| + final FunctionNode function;
|
| + final ExpressionContinuation continuation;
|
|
|
| - if (next is RedirectingInitializer) {
|
| - // RedirectingInitializer appears last in the initializer list.
|
| - assert(initializers.length == 2);
|
| - var app = new RedirectingConstructorApplication(
|
| - next.target, initializerEnvironment, configuration);
|
| - var args =
|
| - _createArgumentExpressionList(next.arguments, next.target.function);
|
| - return new EvalListConfiguration(args, initializerEnvironment, app);
|
| - }
|
| + StaticInvocationA(this.function, this.continuation);
|
|
|
| - if (next is SuperInitializer) {
|
| - // SuperInitializer appears last in the initializer list.
|
| - assert(initializers.length == 2);
|
| - var args =
|
| - _createArgumentExpressionList(next.arguments, next.target.function);
|
| - var superApp = new SuperConstructorApplication(
|
| - next.target, initializerEnvironment, configuration);
|
| - _initializeNullFields(currentClass, newObject);
|
| - return new EvalListConfiguration(args, initializerEnvironment, superApp);
|
| - }
|
| + Configuration call(List<InterpreterValue> argValues) {
|
| + Environment functionEnv =
|
| + ApplicationContinuation.createEnvironment(function, argValues);
|
| + State bodyState = new State(
|
| + null, continuation, new ExitSK(continuation, Value.nullInstance));
|
|
|
| - var cont = new InitializerContinuation(currentClass, initializerEnvironment,
|
| - initializers.skip(1).toList(), configuration);
|
| - return new EvalConfiguration(
|
| - _getExpression(next), initializerEnvironment, cont);
|
| + return new ExecConfiguration(function.body, functionEnv, bodyState);
|
| }
|
| }
|
|
|
| -/// Represents the application continuation called after the evaluation of all
|
| -/// argument expressions for an invocation.
|
| -class ValueApplication extends ApplicationContinuation {
|
| - final InterpreterValue value;
|
| - final ApplicationContinuation applicationContinuation;
|
| -
|
| - ValueApplication(this.value, this.applicationContinuation);
|
| -
|
| - Configuration call(List<InterpreterValue> args) {
|
| - args.add(value);
|
| - return new ApplicationConfiguration(applicationContinuation, args);
|
| - }
|
| -}
|
| +// ------------------------------------------------------------------------
|
| +// Expression Continuations
|
| +// ------------------------------------------------------------------------
|
|
|
| /// Represents an expression continuation.
|
| +///
|
| +/// There are various kinds of [ExpressionContinuation]s and their names are
|
| +/// suffixed with "EK".
|
| abstract class ExpressionContinuation extends Continuation {
|
| Configuration call(Value v);
|
| }
|
|
|
| /// Represents a continuation that returns the next [ExecConfiguration]
|
| /// to be executed.
|
| -class ExpressionStatementContinuation extends ExpressionContinuation {
|
| - final ExecConfiguration configuration;
|
| +class ExpressionSK extends ExpressionContinuation {
|
| + final StatementContinuation continuation;
|
| + final Environment environment;
|
|
|
| - ExpressionStatementContinuation(this.configuration);
|
| + ExpressionSK(this.continuation, this.environment);
|
|
|
| Configuration call(Value _) {
|
| - return configuration;
|
| + return new ForwardConfiguration(continuation, environment);
|
| }
|
| }
|
|
|
| -class PrintContinuation extends ExpressionContinuation {
|
| +class PrintEK extends ExpressionContinuation {
|
| final ExpressionContinuation continuation;
|
|
|
| - PrintContinuation(this.continuation);
|
| + PrintEK(this.continuation);
|
|
|
| Configuration call(Value v) {
|
| log.info('print(${v.value.runtimeType}: ${v.value})\n');
|
| @@ -820,11 +664,11 @@ class PrintContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class PropertyGetContinuation extends ExpressionContinuation {
|
| +class PropertyGetEK extends ExpressionContinuation {
|
| final Name name;
|
| final ExpressionContinuation continuation;
|
|
|
| - PropertyGetContinuation(this.name, this.continuation);
|
| + PropertyGetEK(this.name, this.continuation);
|
|
|
| Configuration call(Value receiver) {
|
| // TODO: CPS the invocation of the getter.
|
| @@ -833,27 +677,27 @@ class PropertyGetContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class PropertySetContinuation extends ExpressionContinuation {
|
| +class PropertySetEK extends ExpressionContinuation {
|
| final Expression value;
|
| final Name setterName;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - PropertySetContinuation(
|
| + PropertySetEK(
|
| this.value, this.setterName, this.environment, this.continuation);
|
|
|
| Configuration call(Value receiver) {
|
| - var cont = new SetterContinuation(receiver, setterName, continuation);
|
| + var cont = new SetterEK(receiver, setterName, continuation);
|
| return new EvalConfiguration(value, environment, cont);
|
| }
|
| }
|
|
|
| -class SetterContinuation extends ExpressionContinuation {
|
| +class SetterEK extends ExpressionContinuation {
|
| final Value receiver;
|
| final Name name;
|
| final ExpressionContinuation continuation;
|
|
|
| - SetterContinuation(this.receiver, this.name, this.continuation);
|
| + SetterEK(this.receiver, this.name, this.continuation);
|
|
|
| Configuration call(Value v) {
|
| Setter setter = receiver.class_.lookupSetter(name);
|
| @@ -864,29 +708,29 @@ class SetterContinuation extends ExpressionContinuation {
|
|
|
| /// Represents a continuation to be called after the evaluation of an actual
|
| /// argument for function invocation.
|
| -class ExpressionListContinuation extends ExpressionContinuation {
|
| +class ExpressionListEK extends ExpressionContinuation {
|
| final InterpreterExpression currentExpression;
|
| final List<InterpreterExpression> expressions;
|
| final Environment environment;
|
| final ApplicationContinuation applicationContinuation;
|
|
|
| - ExpressionListContinuation(this.currentExpression, this.expressions,
|
| - this.environment, this.applicationContinuation);
|
| + ExpressionListEK(this.currentExpression, this.expressions, this.environment,
|
| + this.applicationContinuation);
|
|
|
| Configuration call(Value v) {
|
| - ValueApplication app = new ValueApplication(
|
| - currentExpression.assignValue(v), applicationContinuation);
|
| + ValueA app =
|
| + new ValueA(currentExpression.assignValue(v), applicationContinuation);
|
| return new EvalListConfiguration(expressions, environment, app);
|
| }
|
| }
|
|
|
| -class MethodInvocationContinuation extends ExpressionContinuation {
|
| +class MethodInvocationEK extends ExpressionContinuation {
|
| final Arguments arguments;
|
| final Name methodName;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - MethodInvocationContinuation(
|
| + MethodInvocationEK(
|
| this.arguments, this.methodName, this.environment, this.continuation);
|
|
|
| Configuration call(Value receiver) {
|
| @@ -894,22 +738,22 @@ class MethodInvocationContinuation extends ExpressionContinuation {
|
| Value returnValue = receiver.invokeMethod(methodName);
|
| return new ValuePassingConfiguration(continuation, returnValue);
|
| }
|
| - var cont = new ArgumentsContinuation(
|
| + var cont = new ArgumentsEK(
|
| receiver, methodName, arguments, environment, continuation);
|
|
|
| return new EvalConfiguration(arguments.positional.first, environment, cont);
|
| }
|
| }
|
|
|
| -class ArgumentsContinuation extends ExpressionContinuation {
|
| +class ArgumentsEK extends ExpressionContinuation {
|
| final Value receiver;
|
| final Name methodName;
|
| final Arguments arguments;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - ArgumentsContinuation(this.receiver, this.methodName, this.arguments,
|
| - this.environment, this.continuation);
|
| + ArgumentsEK(this.receiver, this.methodName, this.arguments, this.environment,
|
| + this.continuation);
|
|
|
| Configuration call(Value value) {
|
| // Currently evaluates only one argument, for simple method invocations
|
| @@ -919,12 +763,12 @@ class ArgumentsContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class VariableSetContinuation extends ExpressionContinuation {
|
| +class VariableSetEK extends ExpressionContinuation {
|
| final VariableDeclaration variable;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - VariableSetContinuation(this.variable, this.environment, this.continuation);
|
| + VariableSetEK(this.variable, this.environment, this.continuation);
|
|
|
| Configuration call(Value value) {
|
| environment.assign(variable, value);
|
| @@ -932,10 +776,10 @@ class VariableSetContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class NotContinuation extends ExpressionContinuation {
|
| +class NotEK extends ExpressionContinuation {
|
| final ExpressionContinuation continuation;
|
|
|
| - NotContinuation(this.continuation);
|
| + NotEK(this.continuation);
|
|
|
| Configuration call(Value value) {
|
| Value notValue = identical(Value.trueInstance, value)
|
| @@ -945,12 +789,12 @@ class NotContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class OrContinuation extends ExpressionContinuation {
|
| +class OrEK extends ExpressionContinuation {
|
| final Expression right;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - OrContinuation(this.right, this.environment, this.continuation);
|
| + OrEK(this.right, this.environment, this.continuation);
|
|
|
| Configuration call(Value left) {
|
| return identical(Value.trueInstance, left)
|
| @@ -959,12 +803,12 @@ class OrContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class AndContinuation extends ExpressionContinuation {
|
| +class AndEK extends ExpressionContinuation {
|
| final Expression right;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - AndContinuation(this.right, this.environment, this.continuation);
|
| + AndEK(this.right, this.environment, this.continuation);
|
|
|
| Configuration call(Value left) {
|
| return identical(Value.falseInstance, left)
|
| @@ -973,14 +817,13 @@ class AndContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class ConditionalContinuation extends ExpressionContinuation {
|
| +class ConditionalEK extends ExpressionContinuation {
|
| final Expression then;
|
| final Expression otherwise;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - ConditionalContinuation(
|
| - this.then, this.otherwise, this.environment, this.continuation);
|
| + ConditionalEK(this.then, this.otherwise, this.environment, this.continuation);
|
|
|
| Configuration call(Value value) {
|
| return identical(Value.trueInstance, value)
|
| @@ -989,89 +832,73 @@ class ConditionalContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class StringConcatenationContinuation extends ApplicationContinuation {
|
| - final ExpressionContinuation continuation;
|
| -
|
| - StringConcatenationContinuation(this.continuation);
|
| -
|
| - Configuration call(List<InterpreterValue> values) {
|
| - StringBuffer result = new StringBuffer();
|
| - for (InterpreterValue v in values.reversed) {
|
| - result.write(v.value.value);
|
| - }
|
| - return new ValuePassingConfiguration(
|
| - continuation, new StringValue(result.toString()));
|
| - }
|
| -}
|
| -
|
| -class LetContinuation extends ExpressionContinuation {
|
| +class LetEK extends ExpressionContinuation {
|
| final VariableDeclaration variable;
|
| final Expression letBody;
|
| final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - LetContinuation(
|
| - this.variable, this.letBody, this.environment, this.continuation);
|
| + LetEK(this.variable, this.letBody, this.environment, this.continuation);
|
|
|
| Configuration call(Value value) {
|
| var letEnv = new Environment(environment);
|
| - letEnv.expand(variable, value);
|
| + letEnv.extend(variable, value);
|
| return new EvalConfiguration(letBody, letEnv, continuation);
|
| }
|
| }
|
|
|
| /// Represents the continuation for the condition expression in [WhileStatement].
|
| -class WhileConditionContinuation extends ExpressionContinuation {
|
| - final WhileStatement node;
|
| +class WhileConditionEK extends ExpressionContinuation {
|
| + final Expression condition;
|
| + final Statement body;
|
| + final Environment enclosingEnv;
|
| final State state;
|
|
|
| - WhileConditionContinuation(this.node, this.state);
|
| + WhileConditionEK(this.condition, this.body, this.enclosingEnv, this.state);
|
|
|
| - ExecConfiguration call(Value v) {
|
| - if (identical(v, Value.trueInstance)) {
|
| - // Add configuration for the While statement to the linked list.
|
| - ExecConfiguration config = new ExecConfiguration(node, state);
|
| - // Configuration for the body of the loop.
|
| - return new ExecConfiguration(node.body, state.withConfiguration(config));
|
| + Configuration call(Value v) {
|
| + if (identical(v, Value.falseInstance)) {
|
| + return new ForwardConfiguration(state.continuation, enclosingEnv);
|
| }
|
| -
|
| - return state.statementConfiguration;
|
| + var cont = new WhileConditionSK(condition, body, enclosingEnv, state);
|
| + return new ExecConfiguration(
|
| + body, enclosingEnv, state.withContinuation(cont));
|
| }
|
| }
|
|
|
| /// Represents the continuation for the condition expression in [IfStatement].
|
| -class IfConditionContinuation extends ExpressionContinuation {
|
| +class IfConditionEK extends ExpressionContinuation {
|
| final Statement then;
|
| final Statement otherwise;
|
| + final Environment environment;
|
| final State state;
|
|
|
| - IfConditionContinuation(this.then, this.otherwise, this.state);
|
| + IfConditionEK(this.then, this.otherwise, this.environment, this.state);
|
|
|
| - ExecConfiguration call(Value v) {
|
| + Configuration call(Value v) {
|
| if (identical(v, Value.trueInstance)) {
|
| log.info("if-then\n");
|
| - return new ExecConfiguration(then, state);
|
| + return new ExecConfiguration(then, environment, state);
|
| } else if (otherwise != null) {
|
| log.info("if-otherwise\n");
|
| - return new ExecConfiguration(otherwise, state);
|
| + return new ExecConfiguration(otherwise, environment, state);
|
| }
|
| - return state.statementConfiguration;
|
| + return new ForwardConfiguration(state.continuation, environment);
|
| }
|
| }
|
|
|
| /// Represents the continuation for the initializer expression in
|
| /// [VariableDeclaration].
|
| -class VariableInitializerContinuation extends ExpressionContinuation {
|
| +class VariableInitializerEK extends ExpressionContinuation {
|
| final VariableDeclaration variable;
|
| final Environment environment;
|
| - final ExecConfiguration nextConfiguration;
|
| + final StatementContinuation continuation;
|
|
|
| - VariableInitializerContinuation(
|
| - this.variable, this.environment, this.nextConfiguration);
|
| + VariableInitializerEK(this.variable, this.environment, this.continuation);
|
|
|
| - ExecConfiguration call(Value v) {
|
| - environment.expand(variable, v);
|
| - return nextConfiguration;
|
| + Configuration call(Value v) {
|
| + return new ForwardConfiguration(
|
| + continuation, environment.extend(variable, v));
|
| }
|
| }
|
|
|
| @@ -1084,108 +911,117 @@ class VariableInitializerContinuation extends ExpressionContinuation {
|
| /// returned and applied
|
| /// - it returns with or without value, TBD
|
| /// - it throws, TBD
|
| -class StatementExecuter extends StatementVisitor1<Configuration, State> {
|
| +class StatementExecuter
|
| + extends StatementVisitor1<Configuration, ExecConfiguration> {
|
| Evaluator evaluator = new Evaluator();
|
|
|
| void trampolinedExecution(Configuration configuration) {
|
| while (configuration != null) {
|
| configuration = configuration.step(this);
|
| }
|
| + ;
|
| }
|
|
|
| - Configuration exec(Statement statement, State state) =>
|
| - statement.accept1(this, state);
|
| + Configuration exec(Statement statement, ExecConfiguration conf) =>
|
| + statement.accept1(this, conf);
|
| Configuration eval(Expression expression, EvalConfiguration config) =>
|
| evaluator.eval(expression, config);
|
| Configuration evalList(
|
| List<InterpreterExpression> es, Environment env, Continuation cont) =>
|
| evaluator.evalList(es, env, cont);
|
|
|
| - Configuration defaultStatement(Statement node, State state) {
|
| + Configuration defaultStatement(Statement node, ExecConfiguration conf) {
|
| throw notImplemented(
|
| m: "Execution is not implemented for statement:\n$node ");
|
| }
|
|
|
| - Configuration visitInvalidStatement(InvalidStatement node, State state) {
|
| + Configuration visitInvalidStatement(
|
| + InvalidStatement node, ExecConfiguration conf) {
|
| throw "Invalid statement at ${node.location}";
|
| }
|
|
|
| Configuration visitExpressionStatement(
|
| - ExpressionStatement node, State state) {
|
| - var cont =
|
| - new ExpressionStatementContinuation(state.statementConfiguration);
|
| - return new EvalConfiguration(node.expression, state.environment, cont);
|
| + ExpressionStatement node, ExecConfiguration conf) {
|
| + var cont = new ExpressionSK(conf.state.continuation, conf.environment);
|
| + return new EvalConfiguration(node.expression, conf.environment, cont);
|
| }
|
|
|
| - Configuration visitBlock(Block node, State state) {
|
| + Configuration visitBlock(Block node, ExecConfiguration conf) {
|
| if (node.statements.isEmpty) {
|
| - return state.statementConfiguration;
|
| + return new ForwardConfiguration(
|
| + conf.state.continuation, conf.environment);
|
| }
|
| - State blockState =
|
| - state.withEnvironment(new Environment(state.environment));
|
| - ExecConfiguration configuration = state.statementConfiguration;
|
| - for (Statement s in node.statements.reversed) {
|
| - configuration =
|
| - new ExecConfiguration(s, blockState.withConfiguration(configuration));
|
| - }
|
| - return configuration;
|
| +
|
| + var env = new Environment(conf.environment);
|
| + var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf);
|
| + return new ExecConfiguration(node.statements.first, env,
|
| + new State(conf.state.labels, conf.state.returnContinuation, cont));
|
| }
|
|
|
| - Configuration visitEmptyStatement(EmptyStatement node, State state) {
|
| - return state.statementConfiguration;
|
| + Configuration visitEmptyStatement(
|
| + EmptyStatement node, ExecConfiguration conf) {
|
| + return new ForwardConfiguration(conf.state.continuation, conf.environment);
|
| }
|
|
|
| - Configuration visitIfStatement(IfStatement node, State state) {
|
| - var cont = new IfConditionContinuation(node.then, node.otherwise, state);
|
| + Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) {
|
| + var cont = new IfConditionEK(
|
| + node.then, node.otherwise, conf.environment, conf.state);
|
|
|
| - return new EvalConfiguration(node.condition, state.environment, cont);
|
| + return new EvalConfiguration(node.condition, conf.environment, cont);
|
| }
|
|
|
| - Configuration visitLabeledStatement(LabeledStatement node, State state) {
|
| - return new ExecConfiguration(node.body, state.withBreak(node));
|
| + Configuration visitLabeledStatement(
|
| + LabeledStatement node, ExecConfiguration conf) {
|
| + var l = new Label(
|
| + node, conf.environment, conf.state.continuation, conf.state.labels);
|
| + return new ExecConfiguration(node.body, conf.environment,
|
| + new State(l, conf.state.returnContinuation, conf.state.continuation));
|
| }
|
|
|
| - Configuration visitBreakStatement(BreakStatement node, State state) {
|
| - return state.lookupLabel(node.target).configuration;
|
| + Configuration visitBreakStatement(
|
| + BreakStatement node, ExecConfiguration conf) {
|
| + Label l = conf.state.lookupLabel(node.target);
|
| + return new ForwardConfiguration(l.continuation, l.environment);
|
| }
|
|
|
| - Configuration visitWhileStatement(WhileStatement node, State state) {
|
| - var cont = new WhileConditionContinuation(node, state);
|
| + Configuration visitWhileStatement(
|
| + WhileStatement node, ExecConfiguration conf) {
|
| + var cont = new WhileConditionEK(
|
| + node.condition, node.body, conf.environment, conf.state);
|
|
|
| - return new EvalConfiguration(node.condition, state.environment, cont);
|
| + return new EvalConfiguration(node.condition, conf.environment, cont);
|
| }
|
|
|
| - Configuration visitDoStatement(DoStatement node, State state) {
|
| - WhileStatement whileStatement =
|
| - new WhileStatement(node.condition, node.body);
|
| - ExecConfiguration configuration =
|
| - new ExecConfiguration(whileStatement, state);
|
| + Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) {
|
| + var cont = new WhileConditionSK(
|
| + node.condition, node.body, conf.environment, conf.state);
|
|
|
| - return new ExecConfiguration(
|
| - node.body, state.withConfiguration(configuration));
|
| + return new ExecConfiguration(node.body, conf.environment,
|
| + new State(conf.state.labels, conf.state.returnContinuation, cont));
|
| }
|
|
|
| - Configuration visitReturnStatement(ReturnStatement node, State state) {
|
| - assert(state.returnContinuation != null);
|
| + Configuration visitReturnStatement(
|
| + ReturnStatement node, ExecConfiguration conf) {
|
| + assert(conf.state.returnContinuation != null);
|
| log.info('return\n');
|
| if (node.expression == null) {
|
| return new ValuePassingConfiguration(
|
| - state.returnContinuation, Value.nullInstance);
|
| + conf.state.returnContinuation, Value.nullInstance);
|
| }
|
|
|
| return new EvalConfiguration(
|
| - node.expression, state.environment, state.returnContinuation);
|
| + node.expression, conf.environment, conf.state.returnContinuation);
|
| }
|
|
|
| Configuration visitVariableDeclaration(
|
| - VariableDeclaration node, State state) {
|
| + VariableDeclaration node, ExecConfiguration conf) {
|
| if (node.initializer != null) {
|
| - var cont = new VariableInitializerContinuation(
|
| - node, state.environment, state.statementConfiguration);
|
| - return new EvalConfiguration(node.initializer, state.environment, cont);
|
| + var cont = new VariableInitializerEK(
|
| + node, conf.environment, conf.state.continuation);
|
| + return new EvalConfiguration(node.initializer, conf.environment, cont);
|
| }
|
| - state.environment.expand(node, Value.nullInstance);
|
| - return state.statementConfiguration;
|
| + return new ForwardConfiguration(conf.state.continuation,
|
| + conf.environment.extend(node, Value.nullInstance));
|
| }
|
| }
|
|
|
|
|