| Index: pkg/kernel/lib/interpreter/interpreter.dart
|
| diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
|
| index a64fe581f12f7be928f4f34308138c6a63545c48..c319a88afc26eb2302034c316b2089b6514519bd 100644
|
| --- a/pkg/kernel/lib/interpreter/interpreter.dart
|
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart
|
| @@ -17,7 +17,6 @@ class NotImplemented {
|
| class Interpreter {
|
| Program program;
|
| StatementExecuter visitor = new StatementExecuter();
|
| - Environment env = new Environment.empty();
|
|
|
| Interpreter(this.program);
|
|
|
| @@ -25,19 +24,11 @@ class Interpreter {
|
| assert(program.libraries.isEmpty);
|
| Procedure mainMethod = program.mainMethod;
|
| Statement statementBlock = mainMethod.function.body;
|
| - visitor.exec(statementBlock, env);
|
| + Continuation cont = new Continuation(statementBlock, new State.initial());
|
| + visitor.trampolinedExecution(cont);
|
| }
|
| }
|
|
|
| -class InvalidExpressionError {
|
| - InvalidExpression expression;
|
| -
|
| - InvalidExpressionError(this.expression);
|
| -
|
| - String toString() =>
|
| - 'Invalid expression at ${expression.location.toString()}';
|
| -}
|
| -
|
| class Binding {
|
| final VariableDeclaration variable;
|
| Value value;
|
| @@ -82,6 +73,7 @@ class Environment {
|
| }
|
| }
|
|
|
| +/// Evaluate expressions.
|
| class Evaluator extends ExpressionVisitor1<Value> {
|
| Value eval(Expression expr, Environment env) => expr.accept1(this, env);
|
|
|
| @@ -91,7 +83,7 @@ class Evaluator extends ExpressionVisitor1<Value> {
|
| }
|
|
|
| Value visitInvalidExpression1(InvalidExpression node, env) {
|
| - throw new InvalidExpressionError(node);
|
| + throw 'Invalid expression at ${node.location.toString()}';
|
| }
|
|
|
| Value visitVariableGet(VariableGet node, env) {
|
| @@ -223,57 +215,160 @@ class Evaluator extends ExpressionVisitor1<Value> {
|
| }
|
| }
|
|
|
| +/// Represents a state which consists of current environment, continuation to be
|
| +/// applied and the current label.
|
| +class State {
|
| + final Environment environment;
|
| + final Label labels;
|
| + final Continuation continuation;
|
| +
|
| + State(this.environment, this.labels, this.continuation);
|
| + State.initial() : this(new Environment.empty(), null, null);
|
| +
|
| + State withEnvironment(Environment env) {
|
| + return new State(env, labels, continuation);
|
| + }
|
| +
|
| + State withBreak(Statement stmt) {
|
| + return new State(
|
| + environment, new Label(stmt, continuation, labels), continuation);
|
| + }
|
| +
|
| + State withContinuation(Continuation cont) {
|
| + return new State(environment, labels, cont);
|
| + }
|
| +
|
| + Label lookupLabel(LabeledStatement s) {
|
| + assert(labels != null);
|
| + return labels.lookupLabel(s);
|
| + }
|
| +}
|
| +
|
| +/// Represent the continuation for execution of statement.
|
| +class Continuation {
|
| + final Statement statement;
|
| + final State state;
|
| +
|
| + Continuation(this.statement, this.state);
|
| +}
|
| +
|
| +/// Represents a labeled statement, the corresponding continuation and the
|
| +/// enclosing label.
|
| +class Label {
|
| + final LabeledStatement statement;
|
| + final Continuation continuation;
|
| + final Label enclosingLabel;
|
| +
|
| + Label(this.statement, this.continuation, this.enclosingLabel);
|
| +
|
| + Label lookupLabel(LabeledStatement s) {
|
| + if (identical(s, statement)) return this;
|
| + assert(enclosingLabel != null);
|
| + return enclosingLabel.lookupLabel(s);
|
| + }
|
| +}
|
| +
|
| /// Executes statements.
|
| -class StatementExecuter extends StatementVisitor1 {
|
| +///
|
| +/// Execution of a statement completes in one of the following ways:
|
| +/// - it completes normally, in which case the execution proceeds to applying
|
| +/// the next continuation
|
| +/// - it breaks with a label, in which case the corresponding continuation is
|
| +/// returned and applied
|
| +/// - it returns with or without value, TBD
|
| +/// - it throws, TBD
|
| +class StatementExecuter extends StatementVisitor1<Continuation> {
|
| Evaluator evaluator = new Evaluator();
|
|
|
| - exec(Statement statement, env) => statement.accept1(this, env);
|
| - eval(Expression expression, env) => evaluator.eval(expression, env);
|
| + void trampolinedExecution(Continuation continuation) {
|
| + while (continuation != null) {
|
| + continuation = exec(continuation.statement, continuation.state);
|
| + }
|
| + }
|
| +
|
| + Continuation exec(Statement statement, state) =>
|
| + statement.accept1(this, state);
|
| + Value eval(Expression expression, env) => evaluator.eval(expression, env);
|
|
|
| - defaultStatement(Statement node, env) {
|
| + Continuation defaultStatement(Statement node, state) {
|
| throw notImplemented(
|
| m: "Execution is not implemented for statement:\n$node ");
|
| }
|
|
|
| - visitInvalidStatement(InvalidStatement node, env) {
|
| + Continuation visitInvalidStatement(InvalidStatement node, state) {
|
| throw "Invalid statement at ${node.location}";
|
| }
|
|
|
| - visitExpressionStatement(ExpressionStatement node, env) {
|
| - return eval(node.expression, env);
|
| + Continuation visitExpressionStatement(ExpressionStatement node, state) {
|
| + eval(node.expression, state.environment);
|
| + return state.continuation;
|
| }
|
|
|
| - visitBlock(Block node, env) {
|
| - Environment blockEnv = new Environment(env);
|
| - for (Statement s in node.statements) {
|
| - exec(s, blockEnv);
|
| + Continuation visitBlock(Block node, state) {
|
| + if (node.statements.isEmpty) {
|
| + return state.continuation;
|
| + }
|
| + State blockState =
|
| + state.withEnvironment(new Environment(state.environment));
|
| + Continuation cont = state.continuation;
|
| + for (Statement s in node.statements.reversed) {
|
| + cont = new Continuation(s, blockState.withContinuation(cont));
|
| }
|
| + return cont;
|
| }
|
|
|
| - visitEmptyStatement(EmptyStatement node, env) {}
|
| + Continuation visitEmptyStatement(EmptyStatement node, state) {
|
| + return state.continuation;
|
| + }
|
|
|
| - visitIfStatement(IfStatement node, env) {
|
| - Value condition = eval(node.condition, env).toBoolean();
|
| - if (identical(Value.trueInstance, condition)) {
|
| - exec(node.then, env);
|
| - } else {
|
| - exec(node.otherwise, env);
|
| + 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;
|
| + }
|
| +
|
| + Continuation visitLabeledStatement(LabeledStatement node, state) {
|
| + return new Continuation(node.body, state.withBreak(node));
|
| + }
|
| +
|
| + Continuation visitBreakStatement(BreakStatement node, state) {
|
| + return state.lookupLabel(node.target).continuation;
|
| + }
|
| +
|
| + 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;
|
| + }
|
| +
|
| + Continuation 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));
|
| }
|
|
|
| - visitVariableDeclaration(VariableDeclaration node, env) {
|
| + Continuation visitVariableDeclaration(VariableDeclaration node, state) {
|
| Value value = node.initializer != null
|
| - ? eval(node.initializer, env)
|
| + ? eval(node.initializer, state.environment)
|
| : Value.nullInstance;
|
| - env.expand(node, value);
|
| + state.environment.expand(node, value);
|
| + return state.continuation;
|
| }
|
| }
|
|
|
| typedef Value Getter(Value receiver);
|
| typedef void Setter(Value receiver, Value value);
|
|
|
| -// TODO(zhivkag): Change misleading name.
|
| -// This is representation of a class in the interpreter, not a declaration.
|
| class Class {
|
| static final Map<Reference, Class> _classes = <Reference, Class>{};
|
|
|
|
|