Chromium Code Reviews| 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..38d5c6996993fb8635d54c24b8c16eea79801b9a 100644 |
| --- a/pkg/kernel/lib/interpreter/interpreter.dart |
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart |
| @@ -16,7 +16,7 @@ class NotImplemented { |
| class Interpreter { |
| Program program; |
| - StatementExecuter visitor = new StatementExecuter(); |
| + static StatementExecuter visitor = new StatementExecuter(); |
|
Dmitry Stefantsov
2017/04/10 14:05:53
Why is it made static?
zhivkag
2017/04/11 11:37:39
This is a remainder from some initial experiments
|
| Interpreter(this.program); |
| @@ -24,7 +24,8 @@ class Interpreter { |
| assert(program.libraries.isEmpty); |
| Procedure mainMethod = program.mainMethod; |
| Statement statementBlock = mainMethod.function.body; |
| - Continuation cont = new Continuation(statementBlock, new State.initial()); |
| + StatementConfiguration cont = |
| + new StatementConfiguration(statementBlock, new State.initial()); |
| visitor.trampolinedExecution(cont); |
| } |
| } |
| @@ -74,168 +75,171 @@ 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 ExpressionConfiguration(value, state.continuation); |
| } |
| - 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 eval(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 eval(node.receiver, state.continuation(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, this); |
| + return eval(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 eval(node.arguments.positional.first, |
| + state.withContinuation(new PrintContinuation(state.statementState))); |
| } 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) { |
| + var cont = new StaticInvocationContinuation(state); |
| + return new StatementConfiguration(node.target.function.body, |
| + state.statementState.withExpressionContinuation(cont)); |
| + } |
| + 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, this); |
| + |
| + return eval(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 ExpressionConfiguration( |
| + new ObjectValue(class_, fields), state.continuation); |
| } |
| - 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 eval(node.operand, |
| + state.withContinuation(new NotContinuation(state.continuation))); |
| } |
| - 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(state, node.right, this); |
| + return eval(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(state, node.right, this); |
| + return eval(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, this); |
| + return eval(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, this); |
| + return eval(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 ExpressionConfiguration( |
| + new StringValue(node.value), state.continuation); |
| + } |
| + |
| + Configuration visitIntLiteral(IntLiteral node, state) { |
| + return new ExpressionConfiguration( |
| + new IntValue(node.value), state.continuation); |
| + } |
| + |
| + Configuration visitDoubleLiteral(DoubleLiteral node, state) { |
| + return new ExpressionConfiguration( |
| + new DoubleValue(node.value), state.continuation); |
| + } |
| + |
| + Configuration visitBoolLiteral(BoolLiteral node, state) { |
| + Value value = node.value ? Value.trueInstance : Value.falseInstance; |
| + return new ExpressionConfiguration(value, state.continuation); |
| + } |
| + |
| + Configuration visitNullLiteral(NullLiteral node, state) { |
| + return new ExpressionConfiguration(Value.nullInstance, state.continuation); |
| + } |
| - 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 visitLet(Let node, state) { |
| + var value = eval(node.variable.initializer, state); |
| + var letState = state.withEnvironment(new Environment(state.environment)); |
| + letState.environment.expand(node.variable, value); |
| + return eval(node.body, letState); |
| } |
| } |
| -/// 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 Configuration configuration; |
| - State(this.environment, this.labels, this.continuation); |
| - State.initial() : this(new Environment.empty(), null, null); |
| + final ExpressionContinuation expressionContinuation; |
| + |
| + State(this.environment, this.labels, this.configuration, |
| + this.expressionContinuation); |
| + State.initial() : this(new Environment.empty(), null, null, null); |
| State withEnvironment(Environment env) { |
| - return new State(env, labels, continuation); |
| + return new State(env, labels, configuration, expressionContinuation); |
| } |
| State withBreak(Statement stmt) { |
| + Label breakLabels = new Label(stmt, configuration, labels); |
| return new State( |
| - environment, new Label(stmt, continuation, labels), continuation); |
| + environment, breakLabels, configuration, expressionContinuation); |
| } |
| - State withContinuation(Continuation cont) { |
| - return new State(environment, labels, cont); |
| + State withConfiguration(Configuration cont) { |
|
Dmitry Stefantsov
2017/04/10 14:05:53
Maybe "cont" ==> "configuration"? We may use forms
zhivkag
2017/04/11 11:37:38
Done.
|
| + return new State(environment, labels, cont, expressionContinuation); |
| + } |
| + |
| + State withExpressionContinuation(ExpressionContinuation cont) { |
| + return new State(environment, labels, configuration, cont); |
| } |
| Label lookupLabel(LabeledStatement s) { |
| @@ -244,19 +248,36 @@ 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 { |
| + /// Enclosing statement state. |
| + final State statementState; |
| + |
| + /// Environment in which the expression is evaluated. |
| + final Environment environment; |
| + |
| + /// Next continuation to be evaluated. |
| + final ExpressionContinuation continuation; |
| + |
| + ExpressionState(this.statementState, this.environment, this.continuation); |
| - Continuation(this.statement, this.state); |
| + ExpressionState.withStatementState(State state) |
|
Dmitry Stefantsov
2017/04/10 14:05:53
Maybe rename it to "fromStatementState", because "
zhivkag
2017/04/11 11:37:38
Done.
|
| + : this(state, state.environment, state.expressionContinuation); |
| + |
| + ExpressionState withEnvironment(Environment env) { |
| + return new ExpressionState(statementState, env, continuation); |
| + } |
| + |
| + ExpressionState withContinuation(ExpressionContinuation cont) { |
| + return new ExpressionState(statementState, environment, cont); |
| + } |
| } |
| /// Represents a labeled statement, the corresponding continuation and the |
| /// enclosing label. |
| class Label { |
| final LabeledStatement statement; |
| - final Continuation continuation; |
| + final StatementConfiguration continuation; |
|
Dmitry Stefantsov
2017/04/10 14:05:53
"continuation" ==> "configuration"
zhivkag
2017/04/11 11:37:38
Done.
|
| final Label enclosingLabel; |
| Label(this.statement, this.continuation, this.enclosingLabel); |
| @@ -268,6 +289,264 @@ 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); |
| +} |
| + |
| +/// Represents the configuration for applying an Expression continuation. |
| +class ExpressionConfiguration extends Configuration { |
| + final Value value; |
| + final ExpressionContinuation continuation; |
| + |
| + ExpressionConfiguration(this.value, this.continuation); |
| + |
| + Configuration step(StatementExecuter executer) => continuation(value); |
| +} |
| + |
| +/// Represents an expression continuation. |
| +abstract class ExpressionContinuation { |
| + Configuration call(Value v); |
| +} |
| + |
| +class PrintContinuation extends ExpressionContinuation { |
| + final State state; |
|
Dmitry Stefantsov
2017/04/10 14:05:53
I think it's better to have ExpressionState rather
zhivkag
2017/04/11 11:37:39
Done.
|
| + |
| + PrintContinuation(this.state); |
| + |
| + Configuration call(Value v) { |
| + print(v.value); |
| + return state.configuration; |
| + } |
| +} |
| + |
| +class PropertyGetContinuation extends ExpressionContinuation { |
| + final Name name; |
| + final ExpressionState state; |
| + |
| + PropertyGetContinuation(this.name, this.state); |
| + |
| + Configuration call(Value value) { |
| + Value propertyValue = value.class_.lookupGetter(name)(value); |
| + return new ExpressionConfiguration(propertyValue, state.continuation); |
| + } |
| +} |
| + |
| +class PropertySetContinuation extends ExpressionContinuation { |
| + final Expression value; |
| + final Name setterName; |
| + final ExpressionState state; |
| + final Evaluator evaluator; |
|
Dmitry Stefantsov
2017/04/10 14:05:53
I don't think we want to have an Evaluator in a fi
zhivkag
2017/04/11 11:37:39
As we discussed offline, we couldn't see an obviou
|
| + |
| + PropertySetContinuation( |
| + this.value, this.setterName, this.state, this.evaluator); |
| + |
| + Configuration call(Value receiver) { |
| + Setter setter = receiver.class_.lookupSetter(setterName); |
| + var cont = new SetterContinuation(setter, receiver, state); |
| + return evaluator.eval(value, state.withContinuation(cont)); |
| + } |
| +} |
| + |
| +class SetterContinuation extends ExpressionContinuation { |
| + final Setter setter; |
| + final Value receiver; |
| + final ExpressionState state; |
| + |
| + SetterContinuation(this.setter, this.receiver, this.state); |
| + |
| + Configuration call(Value value) { |
| + setter(receiver, value); |
| + if (state.continuation != null) { |
|
Dmitry Stefantsov
2017/04/10 14:05:53
I think we may write lines 371-374 as a method "Co
zhivkag
2017/04/11 11:37:38
Done.
|
| + return new ExpressionConfiguration(value, state.continuation); |
| + } |
| + return state.statementState.configuration; |
| + } |
| +} |
| + |
| +class StaticInvocationContinuation extends ExpressionContinuation { |
|
Dmitry Stefantsov
2017/04/10 14:05:53
Shouldn't this class have a reference to the metho
zhivkag
2017/04/11 11:37:38
With the current implementation we only support ca
|
| + final ExpressionState state; |
| + |
| + StaticInvocationContinuation(this.state); |
| + |
| + Configuration call(Value value) { |
| + if (state.continuation != null) { |
| + return new ExpressionConfiguration(value, state.continuation); |
| + } |
| + return state.statementState.configuration; |
| + } |
| +} |
| + |
| +class MethodInvocationContinuation extends ExpressionContinuation { |
| + final Arguments arguments; |
| + final Name methodName; |
| + final ExpressionState state; |
| + final Evaluator evaluator; |
| + |
| + MethodInvocationContinuation( |
| + this.arguments, this.methodName, this.state, this.evaluator); |
| + |
| + Configuration call(Value value) { |
| + if (arguments.positional.isEmpty) { |
|
Dmitry Stefantsov
2017/04/10 14:05:53
I think we may turn this if-statement into a case
zhivkag
2017/04/11 11:37:38
Acknowledged.
|
| + Value returnValue = value.invokeMethod(methodName); |
| + return new ExpressionConfiguration(returnValue, state.continuation); |
| + } |
| + var cont = new ArgumentsContinuation(value, methodName, state); |
| + return evaluator.eval( |
| + arguments.positional.first, state.withContinuation(cont)); |
| + } |
| +} |
| + |
| +// Currently evaluates only one argument, for simple method invocations with 1 |
| +// argument. |
| +class ArgumentsContinuation extends ExpressionContinuation { |
| + final Value receiver; |
| + final Name methodName; |
| + final ExpressionState state; |
| + //final Evaluator evaluator; |
| + |
| + ArgumentsContinuation(this.receiver, this.methodName, this.state); |
| + |
| + Configuration call(Value value) { |
| + Value returnValue = receiver.invokeMethod(methodName, value); |
| + return new ExpressionConfiguration(returnValue, state.continuation); |
| + } |
| +} |
| + |
| +class VariableDeclarationContinuation extends ExpressionContinuation { |
|
Dmitry Stefantsov
2017/04/10 14:05:53
I think variable declaration is not an expression,
zhivkag
2017/04/11 11:37:38
Done.
|
| + final VariableDeclaration variable; |
| + final State state; |
| + |
| + VariableDeclarationContinuation(this.variable, this.state); |
| + |
| + Configuration call(Value value) { |
| + state.environment.expand(variable, value); |
| + return state.configuration; |
| + } |
| +} |
| + |
| +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 ExpressionConfiguration(value, state.continuation); |
| + } |
| +} |
| + |
| +class NotContinuation extends ExpressionContinuation { |
| + final ExpressionContinuation continuation; |
| + |
| + NotContinuation(this.continuation); |
| + |
| + Configuration call(Value value) { |
| + Value notValue = identical(Value.trueInstance, value) |
| + ? Value.falseInstance |
| + : Value.trueInstance; |
| + return new ExpressionConfiguration(notValue, continuation); |
| + } |
| +} |
| + |
| +class OrContinuation extends ExpressionContinuation { |
| + final ExpressionState state; |
| + final Expression right; |
| + final Evaluator evaluator; |
| + |
| + OrContinuation(this.state, this.right, this.evaluator); |
| + |
| + Configuration call(Value left) { |
| + return identical(Value.trueInstance, left) |
| + ? new ExpressionConfiguration(Value.trueInstance, state.continuation) |
| + : evaluator.eval(right, state); |
| + } |
| +} |
| + |
| +class AndContinuation extends ExpressionContinuation { |
| + final ExpressionState state; |
| + final Expression right; |
| + final Evaluator evaluator; // wth?? |
| + |
| + AndContinuation(this.state, this.right, this.evaluator); |
| + |
| + Configuration call(Value left) { |
| + return identical(Value.falseInstance, left) |
| + ? new ExpressionConfiguration(Value.falseInstance, state.continuation) |
| + : evaluator.eval(right, state); |
| + } |
| +} |
| + |
| +class ConditionalContinuation extends ExpressionContinuation { |
| + final Expression then; |
| + final Expression otherwise; |
| + final ExpressionState state; |
| + final Evaluator evaluator; |
| + |
| + ConditionalContinuation( |
| + this.then, this.otherwise, this.state, this.evaluator); |
| + |
| + Configuration call(Value value) { |
| + return identical(Value.trueInstance, value) |
| + ? evaluator.eval(then, state) |
| + : evaluator.eval(otherwise, state); |
| + } |
| +} |
| + |
| +class StringConcatenationContinuation extends ExpressionContinuation { |
| + final List<Expression> expressions; |
| + final ExpressionState state; |
| + final Evaluator evaluator; |
| + |
| + int _currentPosition = 0; |
| + final List<Value> _values = <Value>[]; |
| + |
| + StringConcatenationContinuation(this.expressions, this.state, this.evaluator); |
| + |
| + 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 ExpressionConfiguration(value, state.continuation); |
| + } |
| + return evaluator.eval( |
| + expressions[++_currentPosition], state.withContinuation(this)); |
| + } |
| +} |
| + |
| +class LetContinuation extends ExpressionContinuation { |
| + final VariableDeclaration variable; |
| + final Expression letBody; |
| + final ExpressionState state; |
| + final Evaluator evaluator; |
| + |
| + LetContinuation(this.variable, this.letBody, this.state, this.evaluator); |
| + |
| + Configuration call(Value value) { |
| + var letState = state.withEnvironment(new Environment(state.environment)); |
| + letState.environment.expand(variable, value); |
| + return evaluator.eval(letBody, letState); |
| + } |
| +} |
| + |
| /// Executes statements. |
| /// |
| /// Execution of a statement completes in one of the following ways: |
| @@ -277,95 +556,112 @@ 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) { |
| + void trampolinedExecution(Configuration continuation) { |
|
Dmitry Stefantsov
2017/04/10 14:05:53
"continuation" ==> "configuration"
zhivkag
2017/04/11 11:37:38
Done.
|
| while (continuation != null) { |
| - continuation = exec(continuation.statement, continuation.state); |
| + continuation = continuation.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 eval(node.expression, new ExpressionState.withStatementState(state)); |
| } |
| - Continuation visitBlock(Block node, state) { |
| + Configuration visitBlock(Block node, state) { |
| if (node.statements.isEmpty) { |
| - return state.continuation; |
| + return state.configuration; |
| } |
| State blockState = |
| state.withEnvironment(new Environment(state.environment)); |
| - Continuation cont = state.continuation; |
| + StatementConfiguration cont = state.configuration; |
|
Dmitry Stefantsov
2017/04/10 14:05:53
"cont" ==> "configuration"
zhivkag
2017/04/11 11:37:39
Done.
|
| for (Statement s in node.statements.reversed) { |
| - cont = new Continuation(s, blockState.withContinuation(cont)); |
| + cont = new StatementConfiguration(s, blockState.withConfiguration(cont)); |
| } |
| return cont; |
| } |
| - Continuation visitEmptyStatement(EmptyStatement node, state) { |
| - return state.continuation; |
| + Configuration visitEmptyStatement(EmptyStatement node, state) { |
| + return state.configuration; |
| } |
| - Continuation visitIfStatement(IfStatement node, state) { |
| - Value cond = eval(node.condition, state.environment).toBoolean(); |
| - if (identical(Value.trueInstance, cond)) { |
| - return new Continuation(node.then, state); |
| + Configuration visitIfStatement(IfStatement node, state) { |
| + // shortcutting |
| + ExpressionConfiguration cont = eval(node.condition, state); |
|
Dmitry Stefantsov
2017/04/10 14:05:53
The variable "state" here is most likely a State,
Dmitry Stefantsov
2017/04/10 14:05:53
"cont" ==> "configuration"
zhivkag
2017/04/11 11:37:38
Here and below are some calls to eval that I misse
zhivkag
2017/04/11 11:37:39
Done.
|
| + if (identical(Value.trueInstance, cont.value)) { |
| + return new StatementConfiguration(node.then, state); |
| } else if (node.otherwise != null) { |
| - return new Continuation(node.otherwise, state); |
| + return new StatementConfiguration(node.otherwise, state); |
| } |
| - return state.continuation; |
| + return state.configuration; |
| } |
| - 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)) { |
| + Configuration visitWhileStatement(WhileStatement node, state) { |
| + // shortcutting |
| + ExpressionConfiguration cont = eval(node.condition, state.environment); |
|
Dmitry Stefantsov
2017/04/10 14:05:53
Does "eval" accepts an Environment as the second a
Dmitry Stefantsov
2017/04/10 14:05:53
"cont" ==> "configuration"
zhivkag
2017/04/11 11:37:38
eval takes an Expression and an ExpressionState, i
zhivkag
2017/04/11 11:37:38
Done.
|
| + if (identical(Value.trueInstance, cont.value)) { |
| // Add continuation for the While statement to the linked list. |
| - Continuation cont = new Continuation(node, state); |
| + StatementConfiguration cont = new StatementConfiguration(node, state); |
| // Continuation for the body of the loop. |
| - return new Continuation(node.body, state.withContinuation(cont)); |
| + return new StatementConfiguration( |
| + node.body, state.withConfiguration(cont)); |
| } |
| - return state.continuation; |
| + return state.configuration; |
| } |
| - 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 cont = |
| + new StatementConfiguration(whileStatement, state); |
| + return new StatementConfiguration(node.body, state.withConfiguration(cont)); |
| + } |
| + |
| + Configuration visitReturnStatement(ReturnStatement node, state) { |
| + assert(state.expressionContinuation != null); |
| + var expState = new ExpressionState.withStatementState(state); |
| + return eval(node.expression, expState); |
| } |
| - 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 visitVariableDeclaration(VariableDeclaration node, state) { |
| + if (node.initializer != null) { |
| + var cont = new VariableDeclarationContinuation(node, state); |
|
Dmitry Stefantsov
2017/04/10 14:05:53
I don't think we should have "VariableDeclarationC
zhivkag
2017/04/11 11:37:38
Done.
|
| + return eval(node.initializer, |
| + new ExpressionState.withStatementState(state).withContinuation(cont)); |
| + } else { |
| + state.environment.expand(node, Value.nullInstance); |
| + return state.configuration; |
| + } |
| } |
| } |
| +// ------------------------------------------------------------------------ |
| +// VALUES |
| +// ------------------------------------------------------------------------ |
| + |
| typedef Value Getter(Value receiver); |
| typedef void Setter(Value receiver, Value value); |