| Index: pkg/kernel/lib/interpreter/interpreter.dart
|
| diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
|
| index 857d065f61b08c16c298c3f500c05fbfe5bcb072..9b0babf4994b503e8bc8ddffe852322cc8faa082 100644
|
| --- a/pkg/kernel/lib/interpreter/interpreter.dart
|
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart
|
| @@ -24,8 +24,9 @@ class Interpreter {
|
| assert(program.libraries.isEmpty);
|
| Procedure mainMethod = program.mainMethod;
|
| Statement statementBlock = mainMethod.function.body;
|
| - Continuation cont = new Continuation(statementBlock, new State.initial());
|
| - visitor.trampolinedExecution(cont);
|
| + StatementConfiguration configuration =
|
| + new StatementConfiguration(statementBlock, new State.initial());
|
| + visitor.trampolinedExecution(configuration);
|
| }
|
| }
|
|
|
| @@ -74,168 +75,181 @@ class Environment {
|
| }
|
|
|
| /// Evaluate expressions.
|
| -class Evaluator extends ExpressionVisitor1<Value> {
|
| - Value eval(Expression expr, Environment env) => expr.accept1(this, env);
|
| +class Evaluator extends ExpressionVisitor1<Configuration> {
|
| + Configuration eval(Expression expr, ExpressionState state) =>
|
| + expr.accept1(this, state);
|
|
|
| - Value defaultExpression(Expression node, env) {
|
| + Configuration defaultExpression(Expression node, state) {
|
| throw new NotImplemented('Evaluation for expressions of type '
|
| '${node.runtimeType} is not implemented.');
|
| }
|
|
|
| - Value visitInvalidExpression1(InvalidExpression node, env) {
|
| + Configuration visitInvalidExpression1(InvalidExpression node, state) {
|
| throw 'Invalid expression at ${node.location.toString()}';
|
| }
|
|
|
| - Value visitVariableGet(VariableGet node, env) {
|
| - return env.lookup(node.variable);
|
| + Configuration visitVariableGet(VariableGet node, state) {
|
| + Value value = state.environment.lookup(node.variable);
|
| + return new ContinuationConfiguration(state.continuation, value);
|
| }
|
|
|
| - Value visitVariableSet(VariableSet node, env) {
|
| - return env.assign(node.variable, eval(node.value, env));
|
| + Configuration visitVariableSet(VariableSet node, state) {
|
| + var cont = new VariableSetContinuation(state, node.variable);
|
| + return new ExpressionConfiguration(
|
| + node.value, state.withContinuation(cont));
|
| }
|
|
|
| - Value visitPropertyGet(PropertyGet node, env) {
|
| - Value receiver = eval(node.receiver, env);
|
| - return receiver.class_.lookupGetter(node.name)(receiver);
|
| + Configuration visitPropertyGet(PropertyGet node, state) {
|
| + var cont = new PropertyGetContinuation(node.name, state);
|
| + return new ExpressionConfiguration(
|
| + node.receiver, state.withContinuation(cont));
|
| }
|
|
|
| - Value visitPropertySet(PropertySet node, env) {
|
| - Value receiver = eval(node.receiver, env);
|
| - Value value = eval(node.value, env);
|
| - receiver.class_.lookupSetter(node.name)(receiver, value);
|
| - return value;
|
| + Configuration visitPropertySet(PropertySet node, state) {
|
| + var cont = new PropertySetContinuation(node.value, node.name, state);
|
| + return new ExpressionConfiguration(
|
| + node.receiver, state.withContinuation(cont));
|
| }
|
|
|
| - Value visitDirectPropertyGet(DirectPropertyGet node, env) {
|
| - Value receiver = eval(node.receiver, env);
|
| - return receiver.class_.getProperty(receiver, node.target);
|
| - }
|
| -
|
| - Value visitDirectPropertySet(DirectPropertySet node, env) {
|
| - Value receiver = eval(node.receiver, env);
|
| - Value value = eval(node.value, env);
|
| - receiver.class_.setProperty(receiver, node.target, value);
|
| - return value;
|
| - }
|
| + Configuration visitStaticGet(StaticGet node, state) =>
|
| + defaultExpression(node, state);
|
| + Configuration visitStaticSet(StaticSet node, state) =>
|
| + defaultExpression(node, state);
|
|
|
| - Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env);
|
| - Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env);
|
| -
|
| - Value visitStaticInvocation(StaticInvocation node, env) {
|
| + Configuration visitStaticInvocation(StaticInvocation node, state) {
|
| if ('print' == node.name.toString()) {
|
| - // Special evaluation of print.
|
| - var res = eval(node.arguments.positional[0], env);
|
| - print(res.value);
|
| - return Value.nullInstance;
|
| + return new ExpressionConfiguration(node.arguments.positional.first,
|
| + state.withContinuation(new PrintContinuation(state)));
|
| } else {
|
| - throw new NotImplemented('Support for statement type '
|
| - '${node.runtimeType} is not implemented');
|
| + // Currently supports only static invocations with no arguments.
|
| + if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) {
|
| + State statementState = new State.initial()
|
| + .withExpressionContinuation(state.continuation)
|
| + .withConfiguration(new ExitConfiguration(state.continuation));
|
| +
|
| + return new StatementConfiguration(
|
| + node.target.function.body, statementState);
|
| + }
|
| + throw new NotImplemented(
|
| + 'Support for static invocation with arguments is not implemented');
|
| }
|
| }
|
|
|
| - Value visitMethodInvocation(MethodInvocation node, env) {
|
| + Configuration visitMethodInvocation(MethodInvocation node, state) {
|
| // Currently supports only method invocation with <2 arguments and is used
|
| // to evaluate implemented operators for int, double and String values.
|
| - var receiver = eval(node.receiver, env);
|
| - if (node.arguments.positional.isNotEmpty) {
|
| - var argValue = eval(node.arguments.positional.first, env);
|
| - return receiver.invokeMethod(node.name, argValue);
|
| - } else {
|
| - return receiver.invokeMethod(node.name);
|
| - }
|
| + var cont =
|
| + new MethodInvocationContinuation(node.arguments, node.name, state);
|
| +
|
| + return new ExpressionConfiguration(
|
| + node.receiver, state.withContinuation(cont));
|
| }
|
|
|
| - Value visitConstructorInvocation(ConstructorInvocation node, env) {
|
| + Configuration visitConstructorInvocation(ConstructorInvocation node, state) {
|
| Class class_ = new Class(node.target.enclosingClass.reference);
|
|
|
| - Environment emptyEnv = new Environment.empty();
|
| // Currently we don't support initializers.
|
| // TODO: Modify to respect dart semantics for initialization.
|
| // 1. Init fields and eval initializers, repeat the same with super.
|
| // 2. Eval the Function body of the constructor.
|
| - List<Value> fields = class_.instanceFields
|
| - .map((Field f) => eval(f.initializer ?? new NullLiteral(), emptyEnv))
|
| - .toList(growable: false);
|
| + List<Value> fields = <Value>[];
|
|
|
| - return new ObjectValue(class_, fields);
|
| + return new ContinuationConfiguration(
|
| + state.continuation, new ObjectValue(class_, fields));
|
| }
|
|
|
| - Value visitNot(Not node, env) {
|
| - Value operand = eval(node.operand, env).toBoolean();
|
| - return identical(operand, Value.trueInstance)
|
| - ? Value.falseInstance
|
| - : Value.trueInstance;
|
| + Configuration visitNot(Not node, state) {
|
| + return new ExpressionConfiguration(
|
| + node.operand, state.withContinuation(new NotContinuation(state)));
|
| }
|
|
|
| - Value visitLogicalExpression(LogicalExpression node, env) {
|
| + Configuration visitLogicalExpression(LogicalExpression node, state) {
|
| if ('||' == node.operator) {
|
| - BoolValue left = eval(node.left, env).toBoolean();
|
| - return identical(left, Value.trueInstance)
|
| - ? Value.trueInstance
|
| - : eval(node.right, env).toBoolean();
|
| + var cont = new OrContinuation(node.right, state);
|
| + return new ExpressionConfiguration(
|
| + node.left, state.withContinuation(cont));
|
| } else {
|
| assert('&&' == node.operator);
|
| - BoolValue left = eval(node.left, env).toBoolean();
|
| - return identical(left, Value.falseInstance)
|
| - ? Value.falseInstance
|
| - : eval(node.right, env).toBoolean();
|
| + var cont = new AndContinuation(node.right, state);
|
| + return new ExpressionConfiguration(
|
| + node.left, state.withContinuation(cont));
|
| }
|
| }
|
|
|
| - Value visitConditionalExpression(ConditionalExpression node, env) {
|
| - var condition = eval(node.condition, env).toBoolean();
|
| - return identical(condition, Value.trueInstance)
|
| - ? eval(node.then, env)
|
| - : eval(node.otherwise, env);
|
| + Configuration visitConditionalExpression(ConditionalExpression node, state) {
|
| + var cont = new ConditionalContinuation(node.then, node.otherwise, state);
|
| + return new ExpressionConfiguration(
|
| + node.condition, state.withContinuation(cont));
|
| }
|
|
|
| - Value visitStringConcatenation(StringConcatenation node, env) {
|
| - StringBuffer res = new StringBuffer();
|
| - for (Expression e in node.expressions) {
|
| - res.write(eval(e, env).value);
|
| - }
|
| - return new StringValue(res.toString());
|
| + Configuration visitStringConcatenation(StringConcatenation node, state) {
|
| + var cont = new StringConcatenationContinuation(node.expressions, state);
|
| + return new ExpressionConfiguration(
|
| + node.expressions.first, state.withContinuation(cont));
|
| }
|
|
|
| // Evaluation of BasicLiterals.
|
| - Value visitStringLiteral(StringLiteral node, env) =>
|
| - new StringValue(node.value);
|
| - Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value);
|
| - Value visitDoubleLiteral(DoubleLiteral node, env) =>
|
| - new DoubleValue(node.value);
|
| - Value visitBoolLiteral(BoolLiteral node, env) =>
|
| - node.value ? Value.trueInstance : Value.falseInstance;
|
| - Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance;
|
| + Configuration visitStringLiteral(StringLiteral node, state) {
|
| + return new ContinuationConfiguration(
|
| + state.continuation, new StringValue(node.value));
|
| + }
|
| +
|
| + Configuration visitIntLiteral(IntLiteral node, state) {
|
| + return new ContinuationConfiguration(
|
| + state.continuation, new IntValue(node.value));
|
| + }
|
| +
|
| + Configuration visitDoubleLiteral(DoubleLiteral node, state) {
|
| + return new ContinuationConfiguration(
|
| + state.continuation, new DoubleValue(node.value));
|
| + }
|
|
|
| - Value visitLet(Let node, env) {
|
| - var value = eval(node.variable.initializer, env);
|
| - var letEnv = new Environment(env);
|
| - letEnv.expand(node.variable, value);
|
| - return eval(node.body, letEnv);
|
| + Configuration visitBoolLiteral(BoolLiteral node, state) {
|
| + Value value = node.value ? Value.trueInstance : Value.falseInstance;
|
| + return new ContinuationConfiguration(state.continuation, value);
|
| + }
|
| +
|
| + Configuration visitNullLiteral(NullLiteral node, state) {
|
| + return new ContinuationConfiguration(
|
| + state.continuation, Value.nullInstance);
|
| + }
|
| +
|
| + Configuration visitLet(Let node, state) {
|
| + var letCont = new LetContinuation(node.variable, node.body, state);
|
| + return new ExpressionConfiguration(
|
| + node.variable.initializer, state.withContinuation(letCont));
|
| }
|
| }
|
|
|
| -/// Represents a state which consists of current environment, continuation to be
|
| -/// applied and the current label.
|
| +/// Represents a state for statement execution.
|
| class State {
|
| final Environment environment;
|
| final Label labels;
|
| - final Continuation continuation;
|
| + final StatementConfiguration statementConfiguration;
|
| +
|
| + final ExpressionContinuation returnContinuation;
|
|
|
| - State(this.environment, this.labels, this.continuation);
|
| - State.initial() : this(new Environment.empty(), null, null);
|
| + State(this.environment, this.labels, this.statementConfiguration,
|
| + this.returnContinuation);
|
| +
|
| + State.initial() : this(new Environment.empty(), null, null, null);
|
|
|
| State withEnvironment(Environment env) {
|
| - return new State(env, labels, continuation);
|
| + return new State(env, labels, statementConfiguration, returnContinuation);
|
| }
|
|
|
| State withBreak(Statement stmt) {
|
| + Label breakLabels = new Label(stmt, statementConfiguration, labels);
|
| return new State(
|
| - environment, new Label(stmt, continuation, labels), continuation);
|
| + environment, breakLabels, statementConfiguration, returnContinuation);
|
| + }
|
| +
|
| + State withConfiguration(Configuration config) {
|
| + return new State(environment, labels, config, returnContinuation);
|
| }
|
|
|
| - State withContinuation(Continuation cont) {
|
| - return new State(environment, labels, cont);
|
| + State withExpressionContinuation(ExpressionContinuation cont) {
|
| + return new State(environment, labels, statementConfiguration, cont);
|
| }
|
|
|
| Label lookupLabel(LabeledStatement s) {
|
| @@ -244,22 +258,37 @@ class State {
|
| }
|
| }
|
|
|
| -/// Represent the continuation for execution of statement.
|
| -class Continuation {
|
| - final Statement statement;
|
| - final State state;
|
| +/// Represents a state for expression evaluation.
|
| +class ExpressionState {
|
| + /// Environment in which the expression is evaluated.
|
| + final Environment environment;
|
| +
|
| + /// Next continuation to be applied.
|
| + final ExpressionContinuation continuation;
|
| +
|
| + ExpressionState(this.environment, this.continuation);
|
| +
|
| + ExpressionState.fromStatementState(State state)
|
| + : this(state.environment,
|
| + new ExpressionStatementContinuation(state.statementConfiguration));
|
| +
|
| + ExpressionState withEnvironment(Environment env) {
|
| + return new ExpressionState(env, continuation);
|
| + }
|
|
|
| - Continuation(this.statement, this.state);
|
| + ExpressionState withContinuation(ExpressionContinuation cont) {
|
| + return new ExpressionState(environment, cont);
|
| + }
|
| }
|
|
|
| /// Represents a labeled statement, the corresponding continuation and the
|
| /// enclosing label.
|
| class Label {
|
| final LabeledStatement statement;
|
| - final Continuation continuation;
|
| + final StatementConfiguration configuration;
|
| final Label enclosingLabel;
|
|
|
| - Label(this.statement, this.continuation, this.enclosingLabel);
|
| + Label(this.statement, this.configuration, this.enclosingLabel);
|
|
|
| Label lookupLabel(LabeledStatement s) {
|
| if (identical(s, statement)) return this;
|
| @@ -268,6 +297,328 @@ class Label {
|
| }
|
| }
|
|
|
| +abstract class Configuration {
|
| + /// Executes the current and returns the next configuration.
|
| + Configuration step(StatementExecuter executer);
|
| +}
|
| +
|
| +/// Represents the configuration for execution of statement.
|
| +class StatementConfiguration extends Configuration {
|
| + final Statement statement;
|
| + final State state;
|
| +
|
| + StatementConfiguration(this.statement, this.state);
|
| +
|
| + Configuration step(StatementExecuter executer) =>
|
| + executer.exec(statement, state);
|
| +}
|
| +
|
| +class ExitConfiguration extends StatementConfiguration {
|
| + final ExpressionContinuation returnContinuation;
|
| +
|
| + ExitConfiguration(this.returnContinuation) : super(null, null);
|
| +
|
| + Configuration step(StatementExecuter executer) {
|
| + return returnContinuation(Value.nullInstance);
|
| + }
|
| +}
|
| +
|
| +/// Represents the configuration for applying an [ExpressionContinuation].
|
| +class ContinuationConfiguration extends Configuration {
|
| + final ExpressionContinuation continuation;
|
| + final Value value;
|
| +
|
| + ContinuationConfiguration(this.continuation, this.value);
|
| +
|
| + Configuration step(StatementExecuter executer) => continuation(value);
|
| +}
|
| +
|
| +/// Represents the configuration for evaluating an [Expression].
|
| +class ExpressionConfiguration extends Configuration {
|
| + final Expression expression;
|
| + final ExpressionState state;
|
| +
|
| + ExpressionConfiguration(this.expression, this.state);
|
| +
|
| + Configuration step(StatementExecuter executer) =>
|
| + executer.eval(expression, state);
|
| +}
|
| +
|
| +/// Represents an expression continuation.
|
| +abstract class ExpressionContinuation {
|
| + Configuration call(Value v);
|
| +}
|
| +
|
| +/// Represents a continuation that returns the next [StatementConfiguration]
|
| +/// to be executed.
|
| +class ExpressionStatementContinuation extends ExpressionContinuation {
|
| + final StatementConfiguration configuration;
|
| +
|
| + ExpressionStatementContinuation(this.configuration);
|
| +
|
| + Configuration call(Value _) {
|
| + return configuration;
|
| + }
|
| +}
|
| +
|
| +class PrintContinuation extends ExpressionContinuation {
|
| + final ExpressionState state;
|
| +
|
| + PrintContinuation(this.state);
|
| +
|
| + Configuration call(Value v) {
|
| + print(v.value);
|
| + return new ContinuationConfiguration(
|
| + state.continuation, Value.nullInstance);
|
| + }
|
| +}
|
| +
|
| +class PropertyGetContinuation extends ExpressionContinuation {
|
| + final Name name;
|
| + final ExpressionState state;
|
| +
|
| + PropertyGetContinuation(this.name, this.state);
|
| +
|
| + Configuration call(Value receiver) {
|
| + // TODO: CPS the invocation of the getter.
|
| + Value propertyValue = receiver.class_.lookupGetter(name)(receiver);
|
| + return new ContinuationConfiguration(state.continuation, propertyValue);
|
| + }
|
| +}
|
| +
|
| +class PropertySetContinuation extends ExpressionContinuation {
|
| + final Expression value;
|
| + final Name setterName;
|
| + final ExpressionState state;
|
| +
|
| + PropertySetContinuation(this.value, this.setterName, this.state);
|
| +
|
| + Configuration call(Value receiver) {
|
| + var cont = new SetterContinuation(receiver, setterName, state);
|
| + return new ExpressionConfiguration(value, state.withContinuation(cont));
|
| + }
|
| +}
|
| +
|
| +class SetterContinuation extends ExpressionContinuation {
|
| + final Value receiver;
|
| + final Name name;
|
| + final ExpressionState state;
|
| +
|
| + SetterContinuation(this.receiver, this.name, this.state);
|
| +
|
| + Configuration call(Value v) {
|
| + Setter setter = receiver.class_.lookupSetter(name);
|
| + setter(receiver, v);
|
| + return new ContinuationConfiguration(state.continuation, v);
|
| + }
|
| +}
|
| +
|
| +class StaticInvocationContinuation extends ExpressionContinuation {
|
| + final ExpressionState state;
|
| +
|
| + StaticInvocationContinuation(this.state);
|
| +
|
| + Configuration call(Value v) {
|
| + return new ContinuationConfiguration(state.continuation, v);
|
| + }
|
| +}
|
| +
|
| +class MethodInvocationContinuation extends ExpressionContinuation {
|
| + final Arguments arguments;
|
| + final Name methodName;
|
| + final ExpressionState state;
|
| +
|
| + MethodInvocationContinuation(this.arguments, this.methodName, this.state);
|
| +
|
| + Configuration call(Value receiver) {
|
| + if (arguments.positional.isEmpty) {
|
| + Value returnValue = receiver.invokeMethod(methodName);
|
| + return new ContinuationConfiguration(state.continuation, returnValue);
|
| + }
|
| + var cont =
|
| + new ArgumentsContinuation(receiver, methodName, arguments, state);
|
| +
|
| + return new ExpressionConfiguration(
|
| + arguments.positional.first, state.withContinuation(cont));
|
| + }
|
| +}
|
| +
|
| +class ArgumentsContinuation extends ExpressionContinuation {
|
| + final Value receiver;
|
| + final Name methodName;
|
| + final Arguments arguments;
|
| + final ExpressionState state;
|
| +
|
| + ArgumentsContinuation(
|
| + this.receiver, this.methodName, this.arguments, this.state);
|
| +
|
| + Configuration call(Value value) {
|
| + // Currently evaluates only one argument, for simple method invocations
|
| + // with 1 argument.
|
| + Value returnValue = receiver.invokeMethod(methodName, value);
|
| + return new ContinuationConfiguration(state.continuation, returnValue);
|
| + }
|
| +}
|
| +
|
| +class VariableSetContinuation extends ExpressionContinuation {
|
| + final ExpressionState state;
|
| + final VariableDeclaration variable;
|
| +
|
| + VariableSetContinuation(this.state, this.variable);
|
| +
|
| + Configuration call(Value value) {
|
| + state.environment.assign(variable, value);
|
| + return new ContinuationConfiguration(state.continuation, value);
|
| + }
|
| +}
|
| +
|
| +class NotContinuation extends ExpressionContinuation {
|
| + final ExpressionState state;
|
| +
|
| + NotContinuation(this.state);
|
| +
|
| + Configuration call(Value value) {
|
| + Value notValue = identical(Value.trueInstance, value)
|
| + ? Value.falseInstance
|
| + : Value.trueInstance;
|
| + return new ContinuationConfiguration(state.continuation, notValue);
|
| + }
|
| +}
|
| +
|
| +class OrContinuation extends ExpressionContinuation {
|
| + final Expression right;
|
| + final ExpressionState state;
|
| +
|
| + OrContinuation(this.right, this.state);
|
| +
|
| + Configuration call(Value left) {
|
| + return identical(Value.trueInstance, left)
|
| + ? new ContinuationConfiguration(state.continuation, Value.trueInstance)
|
| + : new ExpressionConfiguration(right, state);
|
| + }
|
| +}
|
| +
|
| +class AndContinuation extends ExpressionContinuation {
|
| + final Expression right;
|
| + final ExpressionState state;
|
| +
|
| + AndContinuation(this.right, this.state);
|
| +
|
| + Configuration call(Value left) {
|
| + return identical(Value.falseInstance, left)
|
| + ? new ContinuationConfiguration(state.continuation, Value.falseInstance)
|
| + : new ExpressionConfiguration(right, state);
|
| + }
|
| +}
|
| +
|
| +class ConditionalContinuation extends ExpressionContinuation {
|
| + final Expression then;
|
| + final Expression otherwise;
|
| + final ExpressionState state;
|
| +
|
| + ConditionalContinuation(this.then, this.otherwise, this.state);
|
| +
|
| + Configuration call(Value value) {
|
| + return identical(Value.trueInstance, value)
|
| + ? new ExpressionConfiguration(then, state)
|
| + : new ExpressionConfiguration(otherwise, state);
|
| + }
|
| +}
|
| +
|
| +class StringConcatenationContinuation extends ExpressionContinuation {
|
| + final List<Expression> expressions;
|
| + final ExpressionState state;
|
| +
|
| + int _currentPosition = 0;
|
| + final List<Value> _values = <Value>[];
|
| +
|
| + StringConcatenationContinuation(this.expressions, this.state);
|
| +
|
| + Configuration call(Value value) {
|
| + _values.add(value);
|
| + if (_values.length == expressions.length) {
|
| + StringBuffer res = new StringBuffer();
|
| +
|
| + for (int i = 0; i < expressions.length; i++) {
|
| + res.write(_values[i].value);
|
| + }
|
| +
|
| + Value value = new StringValue(res.toString());
|
| + return new ContinuationConfiguration(state.continuation, value);
|
| + }
|
| + return new ExpressionConfiguration(
|
| + expressions[++_currentPosition], state.withContinuation(this));
|
| + }
|
| +}
|
| +
|
| +class LetContinuation extends ExpressionContinuation {
|
| + final VariableDeclaration variable;
|
| + final Expression letBody;
|
| + final ExpressionState state;
|
| +
|
| + LetContinuation(this.variable, this.letBody, this.state);
|
| +
|
| + Configuration call(Value value) {
|
| + var letState = state.withEnvironment(new Environment(state.environment));
|
| + letState.environment.expand(variable, value);
|
| + return new ExpressionConfiguration(letBody, letState);
|
| + }
|
| +}
|
| +
|
| +/// Represents the continuation for the condition expression in [WhileStatement].
|
| +class WhileConditionContinuation extends ExpressionContinuation {
|
| + final WhileStatement node;
|
| + final State state;
|
| +
|
| + WhileConditionContinuation(this.node, this.state);
|
| +
|
| + StatementConfiguration call(Value v) {
|
| + if (identical(v, Value.trueInstance)) {
|
| + // Add configuration for the While statement to the linked list.
|
| + StatementConfiguration config = new StatementConfiguration(node, state);
|
| + // Configuration for the body of the loop.
|
| + return new StatementConfiguration(
|
| + node.body, state.withConfiguration(config));
|
| + }
|
| +
|
| + return state.statementConfiguration;
|
| + }
|
| +}
|
| +
|
| +/// Represents the continuation for the condition expression in [IfStatement].
|
| +class IfConditionContinuation extends ExpressionContinuation {
|
| + final Statement then;
|
| + final Statement otherwise;
|
| + final State state;
|
| +
|
| + IfConditionContinuation(this.then, this.otherwise, this.state);
|
| +
|
| + StatementConfiguration call(Value v) {
|
| + if (identical(v, Value.trueInstance)) {
|
| + return new StatementConfiguration(then, state);
|
| + } else if (otherwise != null) {
|
| + return new StatementConfiguration(otherwise, state);
|
| + }
|
| + return state.statementConfiguration;
|
| + }
|
| +}
|
| +
|
| +/// Represents the continuation for the initializer expression in
|
| +/// [VariableDeclaration].
|
| +class VariableInitializerContinuation extends ExpressionContinuation {
|
| + final VariableDeclaration variable;
|
| + final Environment environment;
|
| + final StatementConfiguration nextConfiguration;
|
| +
|
| + VariableInitializerContinuation(
|
| + this.variable, this.environment, this.nextConfiguration);
|
| +
|
| + StatementConfiguration call(Value v) {
|
| + environment.expand(variable, v);
|
| + return nextConfiguration;
|
| + }
|
| +}
|
| +
|
| /// Executes statements.
|
| ///
|
| /// Execution of a statement completes in one of the following ways:
|
| @@ -277,95 +628,111 @@ class Label {
|
| /// returned and applied
|
| /// - it returns with or without value, TBD
|
| /// - it throws, TBD
|
| -class StatementExecuter extends StatementVisitor1<Continuation> {
|
| +class StatementExecuter extends StatementVisitor1<Configuration> {
|
| Evaluator evaluator = new Evaluator();
|
|
|
| - void trampolinedExecution(Continuation continuation) {
|
| - while (continuation != null) {
|
| - continuation = exec(continuation.statement, continuation.state);
|
| + void trampolinedExecution(Configuration configuration) {
|
| + while (configuration != null) {
|
| + configuration = configuration.step(this);
|
| }
|
| }
|
|
|
| - Continuation exec(Statement statement, state) =>
|
| + Configuration exec(Statement statement, State state) =>
|
| statement.accept1(this, state);
|
| - Value eval(Expression expression, env) => evaluator.eval(expression, env);
|
| + Configuration eval(Expression expression, ExpressionState state) =>
|
| + evaluator.eval(expression, state);
|
|
|
| - Continuation defaultStatement(Statement node, state) {
|
| + Configuration defaultStatement(Statement node, state) {
|
| throw notImplemented(
|
| m: "Execution is not implemented for statement:\n$node ");
|
| }
|
|
|
| - Continuation visitInvalidStatement(InvalidStatement node, state) {
|
| + Configuration visitInvalidStatement(InvalidStatement node, state) {
|
| throw "Invalid statement at ${node.location}";
|
| }
|
|
|
| - Continuation visitExpressionStatement(ExpressionStatement node, state) {
|
| - eval(node.expression, state.environment);
|
| - return state.continuation;
|
| + Configuration visitExpressionStatement(ExpressionStatement node, state) {
|
| + return new ExpressionConfiguration(
|
| + node.expression, new ExpressionState.fromStatementState(state));
|
| }
|
|
|
| - Continuation visitBlock(Block node, state) {
|
| + Configuration visitBlock(Block node, state) {
|
| if (node.statements.isEmpty) {
|
| - return state.continuation;
|
| + return state.statementConfiguration;
|
| }
|
| State blockState =
|
| state.withEnvironment(new Environment(state.environment));
|
| - Continuation cont = state.continuation;
|
| + StatementConfiguration configuration = state.statementConfiguration;
|
| for (Statement s in node.statements.reversed) {
|
| - cont = new Continuation(s, blockState.withContinuation(cont));
|
| + configuration = new StatementConfiguration(
|
| + s, blockState.withConfiguration(configuration));
|
| }
|
| - return cont;
|
| + return configuration;
|
| }
|
|
|
| - Continuation visitEmptyStatement(EmptyStatement node, state) {
|
| - return state.continuation;
|
| + Configuration visitEmptyStatement(EmptyStatement node, state) {
|
| + return state.statementConfiguration;
|
| }
|
|
|
| - Continuation visitIfStatement(IfStatement node, state) {
|
| - Value cond = eval(node.condition, state.environment).toBoolean();
|
| - if (identical(Value.trueInstance, cond)) {
|
| - return new Continuation(node.then, state);
|
| - } else if (node.otherwise != null) {
|
| - return new Continuation(node.otherwise, state);
|
| - }
|
| - return state.continuation;
|
| + Configuration visitIfStatement(IfStatement node, state) {
|
| + var expState = new ExpressionState.fromStatementState(state);
|
| + var cont = new IfConditionContinuation(node.then, node.otherwise, state);
|
| + return new ExpressionConfiguration(
|
| + node.condition, expState.withContinuation(cont));
|
| }
|
|
|
| - Continuation visitLabeledStatement(LabeledStatement node, state) {
|
| - return new Continuation(node.body, state.withBreak(node));
|
| + Configuration visitLabeledStatement(LabeledStatement node, state) {
|
| + return new StatementConfiguration(node.body, state.withBreak(node));
|
| }
|
|
|
| - Continuation visitBreakStatement(BreakStatement node, state) {
|
| - return state.lookupLabel(node.target).continuation;
|
| + Configuration visitBreakStatement(BreakStatement node, state) {
|
| + return state.lookupLabel(node.target).configuration;
|
| }
|
|
|
| - Continuation visitWhileStatement(WhileStatement node, state) {
|
| - Value cond = eval(node.condition, state.environment).toBoolean();
|
| - if (identical(Value.trueInstance, cond)) {
|
| - // Add continuation for the While statement to the linked list.
|
| - Continuation cont = new Continuation(node, state);
|
| - // Continuation for the body of the loop.
|
| - return new Continuation(node.body, state.withContinuation(cont));
|
| - }
|
| - return state.continuation;
|
| + Configuration visitWhileStatement(WhileStatement node, state) {
|
| + var expState = new ExpressionState.fromStatementState(state);
|
| + var cont = new WhileConditionContinuation(node, state);
|
| +
|
| + return new ExpressionConfiguration(
|
| + node.condition, expState.withContinuation(cont));
|
| }
|
|
|
| - Continuation visitDoStatement(DoStatement node, state) {
|
| + Configuration visitDoStatement(DoStatement node, state) {
|
| WhileStatement whileStatement =
|
| new WhileStatement(node.condition, node.body);
|
| - Continuation cont = new Continuation(whileStatement, state);
|
| - return new Continuation(node.body, state.withContinuation(cont));
|
| + StatementConfiguration configuration =
|
| + new StatementConfiguration(whileStatement, state);
|
| +
|
| + return new StatementConfiguration(
|
| + node.body, state.withConfiguration(configuration));
|
| }
|
|
|
| - Continuation visitVariableDeclaration(VariableDeclaration node, state) {
|
| - Value value = node.initializer != null
|
| - ? eval(node.initializer, state.environment)
|
| - : Value.nullInstance;
|
| - state.environment.expand(node, value);
|
| - return state.continuation;
|
| + Configuration visitReturnStatement(ReturnStatement node, state) {
|
| + assert(state.returnContinuation != null);
|
| + // The new ExpressionState contains the next expression continuation.
|
| + var expState = new ExpressionState.fromStatementState(state)
|
| + .withContinuation(state.returnContinuation);
|
| + return new ExpressionConfiguration(
|
| + node.expression ?? new NullLiteral(), expState);
|
| + }
|
| +
|
| + Configuration visitVariableDeclaration(VariableDeclaration node, state) {
|
| + if (node.initializer != null) {
|
| + var expState = new ExpressionState.fromStatementState(state);
|
| + var cont = new VariableInitializerContinuation(
|
| + node, state.environment, state.statementConfiguration);
|
| + return new ExpressionConfiguration(
|
| + node.initializer, expState.withContinuation(cont));
|
| + }
|
| + state.environment.expand(node, Value.nullInstance);
|
| + return state.statementConfiguration;
|
| }
|
| }
|
|
|
| +// ------------------------------------------------------------------------
|
| +// VALUES
|
| +// ------------------------------------------------------------------------
|
| +
|
| typedef Value Getter(Value receiver);
|
| typedef void Setter(Value receiver, Value value);
|
|
|
|
|