anchor.diff:      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);
     }
   }
   
  
positive.code: }
  
  /// Evaluate expressions.
  class Evaluator extends ExpressionVisitor1<Value> {
    Value eval(Expression expr, Environment env) => expr.accept1(this, env);
  
    Value defaultExpression(Expression node, env) {
      throw new NotImplemented('Evaluation for expressions of type '
          '${node.runtimeType} is not implemented.');
    }
  
    Value visitInvalidExpression1(InvalidExpression node, env) {
      throw 'Invalid expression at ${node.location.toString()}';
    }
  
    Value visitVariableGet(VariableGet node, env) {
      return env.lookup(node.variable);
    }
  
    Value visitVariableSet(VariableSet node, env) {
      return env.assign(node.variable, eval(node.value, env));
    }
  
    Value visitPropertyGet(PropertyGet node, env) {
      Value receiver = eval(node.receiver, env);
      return receiver.class_.lookupGetter(node.name)(receiver);
    }
  
    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;
    }
  
    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;
    }
  
    Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env);
    Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env);
  
    Value visitStaticInvocation(StaticInvocation node, env) {
      if ('print' == node.name.toString()) {
        // Special evaluation of print.
        var res = eval(node.arguments.positional[0], env);
        print(res.value);
        return Value.nullInstance;
      } else {
        throw new NotImplemented('Support for statement type '
            '${node.runtimeType} is not implemented');
      }
    }
  
    Value visitMethodInvocation(MethodInvocation node, env) {
      // 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);
      }
    }
  
    Value visitConstructorInvocation(ConstructorInvocation node, env) {
      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);
  
      return 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;
    }
  
    Value visitLogicalExpression(LogicalExpression node, env) {
      if ('||' == node.operator) {
        BoolValue left = eval(node.left, env).toBoolean();
        return identical(left, Value.trueInstance)
            ? Value.trueInstance
            : eval(node.right, env).toBoolean();
      } else {
        assert('&&' == node.operator);
        BoolValue left = eval(node.left, env).toBoolean();
        return identical(left, Value.falseInstance)
            ? Value.falseInstance
            : eval(node.right, env).toBoolean();
      }
    }
  
    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);
    }
  
    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());
    }
  
    // 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;
  
    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);
    }
  }
  
  /// 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) {
  
negative.code: /// returned and applied
  /// - it returns with or without value, TBD
  /// - it throws, TBD
  class StatementExecuter extends StatementVisitor1<Configuration> {
    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 eval(Expression expression, ExpressionState state) =>
        evaluator.eval(expression, state);
  
    Configuration defaultStatement(Statement node, state) {
      throw notImplemented(
          m: "Execution is not implemented for statement:\n$node ");
    }
  
    Configuration visitInvalidStatement(InvalidStatement node, state) {
      throw "Invalid statement at ${node.location}";
    }
  
    Configuration visitExpressionStatement(ExpressionStatement node, state) {
      return new ExpressionConfiguration(
          node.expression, new ExpressionState.fromStatementState(state));
    }
  
    Configuration visitBlock(Block node, state) {
      if (node.statements.isEmpty) {
        return state.statementConfiguration;
      }
      State blockState =
          state.withEnvironment(new Environment(state.environment));
      StatementConfiguration configuration = state.statementConfiguration;
      for (Statement s in node.statements.reversed) {
        configuration = new StatementConfiguration(
            s, blockState.withConfiguration(configuration));
      }
      return configuration;
    }
  
    Configuration visitEmptyStatement(EmptyStatement node, state) {
      return state.statementConfiguration;
    }
  
    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));
    }
  
    Configuration visitLabeledStatement(LabeledStatement node, state) {
      return new StatementConfiguration(node.body, state.withBreak(node));
    }
  
    Configuration visitBreakStatement(BreakStatement node, state) {
      return state.lookupLabel(node.target).configuration;
    }
  
    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));
    }
  
    Configuration visitDoStatement(DoStatement node, state) {
      WhileStatement whileStatement =
          new WhileStatement(node.condition, node.body);
      StatementConfiguration configuration =
          new StatementConfiguration(whileStatement, state);
  
      return new StatementConfiguration(
          node.body, state.withConfiguration(configuration));
    }
  
    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);
  