// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library kernel.interpreter;

import '../ast.dart';
import '../ast.dart' as ast show Class;

import '../log.dart';
export '../log.dart';

class NotImplemented {
  String message;

  NotImplemented(this.message);

  String toString() => message;
}

class Interpreter {
  Program program;
  StatementExecuter visitor = new StatementExecuter();

  // The execution of the program starts with empty main environment.
  static MainEnvironment mainEnvironment =
      new MainEnvironment(<Member, Location>{});

  Interpreter(this.program);

  void run() {
    assert(program.libraries.isEmpty);
    Procedure mainMethod = program.mainMethod;

    if (mainMethod == null) return;

    Statement statementBlock = mainMethod.function.body;
    ExecConfiguration configuration = new ExecConfiguration(
        statementBlock, new Environment.empty(), new State.initial());
    visitor.trampolinedExecution(configuration);
  }
}

class Location {
  Value value;

  Location.empty();
  Location(this.value);
}

class Binding {
  final VariableDeclaration variable;
  final Location location;

  Binding(this.variable, this.location);
}

/// Represents the top level environment that binds previously accessed or set
/// static fields to the location that stores their value.
class MainEnvironment {
  final Map<Member, Location> _staticFields;

  MainEnvironment(this._staticFields);

  bool contains(Member member) => _staticFields[member] != null;

  Value lookup(Member member) {
    assert(contains(member));
    return _staticFields[member].value;
  }

  void updateStore(Member member, Value value) {
    assert(contains(member));
    _staticFields[member].value = value;
  }

  MainEnvironment extend(Member member, Value value) {
    var newMap = new Map<Member, Location>.from(_staticFields);
    newMap[member] = new Location(value);
    return new MainEnvironment(newMap);
  }
}

class Environment {
  final List<Binding> bindings = <Binding>[];
  final Environment parent;

  Value get thisInstance {
    return containsThis()
        ? lookupThis().value
        : throw "Invalid reference to 'this' expression";
  }

  Environment.empty() : parent = null;
  Environment(this.parent);

  bool contains(VariableDeclaration variable) {
    for (Binding b in bindings) {
      if (identical(b.variable, variable)) return true;
    }
    return parent?.contains(variable) ?? false;
  }

  bool containsThis() {
    for (Binding b in bindings) {
      if (identical(b.variable.name, 'this')) return true;
    }
    return parent?.containsThis() ?? false;
  }

  Binding lookupBinding(VariableDeclaration variable) {
    assert(contains(variable));
    for (Binding b in bindings) {
      if (identical(b.variable, variable)) return b;
    }
    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;
  }

  void updateStore(VariableDeclaration variable, Value value) {
    assert(contains(variable));
    lookupBinding(variable).location.value = value;
  }

  Environment extend(VariableDeclaration variable, Value value) {
    assert(!contains(variable));
    return new Environment(this)
      ..bindings.add(new Binding(variable, new Location(value)));
  }

  Environment extendWithThis(ObjectValue v) {
    assert(!containsThis());
    return extend(new VariableDeclaration('this'), v);
  }
}

/// Evaluate expressions.
class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
  Configuration eval(Expression expr, EvalConfiguration config) =>
      expr.accept1(this, config);

  Configuration evalList(List<InterpreterExpression> list, Environment env,
      ExceptionComponents exceptionComponents, ApplicationContinuation cont) {
    if (list.isNotEmpty) {
      return new EvalConfiguration(
          list.first.expression,
          env,
          exceptionComponents,
          new ExpressionListEK(
              list.first, list.skip(1), env, exceptionComponents, cont));
    }
    return new ApplicationConfiguration(cont, <InterpreterValue>[]);
  }

  Configuration defaultExpression(Expression node, EvalConfiguration config) {
    throw new NotImplemented('Evaluation for expressions of type '
        '${node.runtimeType} is not implemented.');
  }

  Configuration visitInvalidExpression1(
      InvalidExpression node, EvalConfiguration config) {
    throw 'Invalid expression at ${node.location.toString()}';
  }

  Configuration visitVariableGet(VariableGet node, EvalConfiguration config) {
    Value value = config.environment.lookup(node.variable);
    return new ValuePassingConfiguration(config.continuation, value);
  }

  Configuration visitVariableSet(VariableSet node, EvalConfiguration config) {
    var cont = new VariableSetEK(
        node.variable, config.environment, config.continuation);
    return new EvalConfiguration(
        node.value, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) {
    var cont = new PropertyGetEK(
        node.name, config.exceptionComponents, config.continuation);
    return new EvalConfiguration(
        node.receiver, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitPropertySet(PropertySet node, EvalConfiguration config) {
    var cont = new PropertySetEK(node.value, node.name, config.environment,
        config.exceptionComponents, config.continuation);
    return new EvalConfiguration(
        node.receiver, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitStaticGet(StaticGet node, EvalConfiguration config) {
    Member member = node.target;

    if (member is Procedure && !member.isAccessor) {
      // Create a closure for the method tear off.
      var v = new FunctionValue(member.function, new Environment.empty());
      return new ValuePassingConfiguration(config.continuation, v);
    }

    if (member is Procedure && member.isGetter) {
      // Execute the body of the getter.
      var state = new State.initial()
          .withReturnContinuation(config.continuation)
          .withContinuation(new ExitSK(config.continuation, Value.nullInstance))
          .withException(config.exceptionComponents);
      return new ExecConfiguration(
          member.function.body, new Environment.empty(), state);
    }

    assert(member is Field);
    if (Interpreter.mainEnvironment.contains(member)) {
      // Read the value for the member in the main environment.
      return new ValuePassingConfiguration(
          config.continuation, Interpreter.mainEnvironment.lookup(member));
    }

    // Otherwise, the static field is accessed for the first time.
    // We extend the main environment with a new binding.
    Interpreter.mainEnvironment =
        Interpreter.mainEnvironment.extend(member, Value.nullInstance);

    if ((member as Field).initializer == null) {
      return new ValuePassingConfiguration(
          config.continuation, Value.nullInstance);
    }

    // The initializer expression is evaluated otherwise.
    var cont = new StaticSetEK(member, config.continuation);
    return new EvalConfiguration((member as Field).initializer,
        new Environment.empty(), config.exceptionComponents, cont);
  }

  Configuration visitStaticSet(StaticSet node, EvalConfiguration config) {
    Member member = node.target;
    ExpressionContinuation cont;

    if (member is Procedure) {
      assert(member.isSetter);
      cont = new StaticSetterEK(
          member.function, config.exceptionComponents, config.continuation);
    } else {
      assert(member is Field);
      cont = new StaticSetEK(member, config.continuation);
    }

    return new EvalConfiguration(
        node.value, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitStaticInvocation(
      StaticInvocation node, EvalConfiguration config) {
    if ('print' == node.name.toString()) {
      var cont = new PrintEK(config.continuation);
      return new EvalConfiguration(node.arguments.positional.first,
          config.environment, config.exceptionComponents, cont);
    } else {
      log.info('static-invocation-${node.target.name.toString()}\n');

      List<InterpreterExpression> args =
          _getArgumentExpressions(node.arguments, node.target.function);
      ApplicationContinuation cont = new StaticInvocationA(node.target.function,
          config.exceptionComponents, config.continuation);
      return new EvalListConfiguration(
          args, config.environment, config.exceptionComponents, cont);
    }
  }

  Configuration visitMethodInvocation(
      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 MethodInvocationEK(node.arguments, node.name,
        config.environment, config.exceptionComponents, config.continuation);

    return new EvalConfiguration(
        node.receiver, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitConstructorInvocation(
      ConstructorInvocation node, EvalConfiguration config) {
    ApplicationContinuation cont = new ConstructorInvocationA(
        node.target, config.exceptionComponents, config.continuation);
    var args = _getArgumentExpressions(node.arguments, node.target.function);

    return new EvalListConfiguration(
        args, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitNot(Not node, EvalConfiguration config) {
    return new EvalConfiguration(node.operand, config.environment,
        config.exceptionComponents, new NotEK(config.continuation));
  }

  Configuration visitLogicalExpression(
      LogicalExpression node, EvalConfiguration config) {
    if ('||' == node.operator) {
      var cont = new OrEK(node.right, config.environment,
          config.exceptionComponents, config.continuation);
      return new EvalConfiguration(
          node.left, config.environment, config.exceptionComponents, cont);
    } else {
      assert('&&' == node.operator);
      var cont = new AndEK(node.right, config.environment,
          config.exceptionComponents, config.continuation);
      return new EvalConfiguration(
          node.left, config.environment, config.exceptionComponents, cont);
    }
  }

  Configuration visitConditionalExpression(
      ConditionalExpression node, EvalConfiguration config) {
    var cont = new ConditionalEK(node.then, node.otherwise, config.environment,
        config.exceptionComponents, config.continuation);
    return new EvalConfiguration(
        node.condition, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitStringConcatenation(
      StringConcatenation node, EvalConfiguration config) {
    var cont = new StringConcatenationA(config.continuation);
    var expressions = node.expressions
        .map((Expression e) => new PositionalExpression(e))
        .toList();
    return new EvalListConfiguration(
        expressions, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitThisExpression(
      ThisExpression node, EvalConfiguration config) {
    return new ValuePassingConfiguration(
        config.continuation, config.environment.thisInstance);
  }

  Configuration visitThrow(Throw node, EvalConfiguration config) {
    var cont = new ThrowEK(config.exceptionComponents);

    return new EvalConfiguration(
        node.expression, config.environment, config.exceptionComponents, cont);
  }

  Configuration visitFunctionExpression(
      FunctionExpression node, EvalConfiguration config) {
    var val = new FunctionValue(node.function, config.environment);
    return new ValuePassingConfiguration(config.continuation, val);
  }

  // Evaluation of BasicLiterals.
  Configuration visitStringLiteral(
      StringLiteral node, EvalConfiguration config) {
    return new ValuePassingConfiguration(
        config.continuation, new StringValue(node.value));
  }

  Configuration visitIntLiteral(IntLiteral node, EvalConfiguration config) {
    return new ValuePassingConfiguration(
        config.continuation, new IntValue(node.value));
  }

  Configuration visitDoubleLiteral(
      DoubleLiteral node, EvalConfiguration config) {
    return new ValuePassingConfiguration(
        config.continuation, new DoubleValue(node.value));
  }

  Configuration visitBoolLiteral(BoolLiteral node, EvalConfiguration config) {
    Value value = node.value ? Value.trueInstance : Value.falseInstance;
    return new ValuePassingConfiguration(config.continuation, value);
  }

  Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) {
    return new ValuePassingConfiguration(
        config.continuation, Value.nullInstance);
  }

  Configuration visitLet(Let node, EvalConfiguration config) {
    var letCont = new LetEK(node.variable, node.body, config.environment,
        config.exceptionComponents, config.continuation);
    return new EvalConfiguration(node.variable.initializer, config.environment,
        config.exceptionComponents, letCont);
  }
}

/// Represents a state for statement execution.
class State {
  final Label labels;
  // TODO: Add switch labels.
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation returnContinuation;
  final StatementContinuation continuation;

  State(this.labels, this.exceptionComponents, this.returnContinuation,
      this.continuation);

  State.initial()
      : labels = null,
        exceptionComponents = new ExceptionComponents.initial(),
        returnContinuation = null,
        continuation = null;

  State withBreak(Statement stmt, Environment env) {
    var cont = new BreakBK(continuation, env);
    Label breakLabels = new Label(stmt, cont, labels);
    return new State(
        breakLabels, exceptionComponents, returnContinuation, continuation);
  }

  State withReturnContinuation(ExpressionContinuation returnCont) {
    return new State(labels, exceptionComponents, returnCont, continuation);
  }

  State withContinuation(StatementContinuation cont) {
    return new State(labels, exceptionComponents, returnContinuation, cont);
  }

  State withException(ExceptionComponents ecs) {
    return new State(labels, ecs, returnContinuation, continuation);
  }

  Label lookupLabel(LabeledStatement s) {
    assert(labels != null);
    return labels.lookupLabel(s);
  }
}

/// Represents a labeled statement, the corresponding continuation and the
/// enclosing label.
class Label {
  final LabeledStatement statement;
  final BreakContinuation 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);
  }

  // Recursively install finally break to all labels.
  Label withFinalizer(Statement finalizer, Environment env, State state) {
    var label = enclosingLabel?.withFinalizer(finalizer, env, state);
    var finallyCont = new FinallyBK(finalizer, env, state, continuation);
    return new Label(statement, finallyCont, label);
  }
}

// ------------------------------------------------------------------------
//                           Configurations
// ------------------------------------------------------------------------

abstract class Configuration {
  /// Executes the current and returns the next configuration.
  Configuration step(StatementExecuter executer);
}

/// Configuration for evaluating an [Expression].
class EvalConfiguration extends Configuration {
  final Expression expression;

  /// Environment in which the expression is evaluated.
  final Environment environment;

  /// Exception components.
  final ExceptionComponents exceptionComponents;

  /// Next continuation to be applied.
  final Continuation continuation;

  EvalConfiguration(this.expression, this.environment, this.exceptionComponents,
      this.continuation);

  Configuration step(StatementExecuter executer) =>
      executer.eval(expression, this);
}

/// Configuration for evaluating a `List<InterpreterExpression>`.
class EvalListConfiguration extends Configuration {
  final List<InterpreterExpression> expressions;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ApplicationContinuation continuation;

  EvalListConfiguration(this.expressions, this.environment,
      this.exceptionComponents, this.continuation);

  Configuration step(StatementExecuter executer) => executer.evalList(
      expressions, environment, exceptionComponents, continuation);
}

/// Configuration for execution of a [Statement].
class ExecConfiguration extends Configuration {
  final Statement currentStatement;
  final Environment environment;
  final State state;

  ExecConfiguration(this.currentStatement, this.environment, this.state);

  Configuration step(StatementExecuter executer) {
    return 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);
}

/// Configuration for applying [ExpressionContinuation] to a [Value].
class ValuePassingConfiguration extends Configuration {
  final ExpressionContinuation continuation;
  final Value value;

  ValuePassingConfiguration(this.continuation, this.value);

  Configuration step(StatementExecuter _) => continuation(value);
}

/// Configuration for applying an [ApplicationContinuation] to a
/// `List<InterpreterValue>`.
class ApplicationConfiguration extends Configuration {
  final ApplicationContinuation continuation;
  final List<InterpreterValue> values;

  ApplicationConfiguration(this.continuation, this.values);

  Configuration step(StatementExecuter _) => continuation(values);
}

/// Configuration for applying an [ExceptionHandler] to an exception and a
/// stack trace.
class ThrowConfiguration extends Configuration {
  final ExceptionHandler handler;
  final Value exception;
  final StackTrace stacktrace;

  ThrowConfiguration(this.handler, this.exception, this.stacktrace);

  Configuration step(StatementExecuter _) => handler(exception, stacktrace);
}

class BreakConfiguration extends Configuration {
  final BreakContinuation continuation;

  BreakConfiguration(this.continuation);

  Configuration step(StatementExecuter _) => continuation();
}

abstract class BreakContinuation extends Continuation {
  Configuration call();
}

class BreakBK extends BreakContinuation {
  final StatementContinuation continuation;
  final Environment environment;

  BreakBK(this.continuation, this.environment);

  Configuration call() => new ForwardConfiguration(continuation, environment);
}

class FinallyBK extends BreakContinuation {
  final Statement finalizer;
  final Environment environment;
  final State state;
  final BreakContinuation continuation;

  FinallyBK(this.finalizer, this.environment, this.state, this.continuation);

  Configuration call() {
    var cont = new BreakSK(continuation);
    return new ExecConfiguration(
        finalizer, environment, state.withContinuation(cont));
  }
}

class BreakSK extends StatementContinuation {
  final BreakContinuation continuation;

  BreakSK(this.continuation);

  Configuration call(Environment _) => new BreakConfiguration(continuation);
}

// ------------------------------------------------------------------------
//            Interpreter Expressions and Values
// ------------------------------------------------------------------------

abstract class InterpreterExpression {
  Expression get expression;

  InterpreterValue assignValue(Value v);
}

class PositionalExpression extends InterpreterExpression {
  final Expression expression;

  PositionalExpression(this.expression);

  InterpreterValue assignValue(Value v) => new PositionalValue(v);
}

class NamedExpression extends InterpreterExpression {
  final String name;
  final Expression expression;

  NamedExpression(this.name, this.expression);
  InterpreterValue assignValue(Value v) => new NamedValue(name, v);
}

class FieldInitializerExpression extends InterpreterExpression {
  final Field field;
  final Expression expression;

  FieldInitializerExpression(this.field, this.expression);

  InterpreterValue assignValue(Value v) => new FieldInitializerValue(field, v);
}

abstract class InterpreterValue {
  Value get value;
}

class PositionalValue extends InterpreterValue {
  final Value value;

  PositionalValue(this.value);
}

class NamedValue extends InterpreterValue {
  final String name;
  final Value value;

  NamedValue(this.name, this.value);
}

class FieldInitializerValue extends InterpreterValue {
  final Field field;
  final Value value;

  FieldInitializerValue(this.field, this.value);
}

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 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, state.exceptionComponents, cont);
  }
}

/// Applies the expression continuation to the provided value.
class NewSK extends StatementContinuation {
  final ExpressionContinuation continuation;
  final Location location;

  NewSK(this.continuation, this.location);

  Configuration call(Environment _) =>
      new ValuePassingConfiguration(continuation, location.value);
}

class ConstructorBodySK extends StatementContinuation {
  final Statement body;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final StatementContinuation continuation;

  ConstructorBodySK(
      this.body, this.environment, this.exceptionComponents, this.continuation);

  Configuration call(Environment _) {
    return new ExecConfiguration(body, environment,
        new State(null, exceptionComponents, null, continuation));
  }
}

/// Represents the statement continuation for execution of the finalizer
/// statement.
class FinallySK extends StatementContinuation {
  final Statement finallyStatement;
  final Environment environment;
  final State state;

  FinallySK(this.finallyStatement, this.environment, this.state);
  Configuration call(Environment _) {
    return new ExecConfiguration(finallyStatement, environment, state);
  }
}

/// Represents the statement continuation that applies the captured handler to
/// the current exception.
///
/// It is used as next statement continuation for the execution of the finalizer
/// statement in [TryFinally] to ensure the finalizer is executed before
/// applying the next handler to the current exception.
class RethrowSK extends StatementContinuation {
  final ExceptionHandler handler;
  final Value exception;
  final StackTrace stackTrace;

  RethrowSK(this.handler, this.exception, this.stackTrace);

  Configuration call(Environment _) {
    return new ThrowConfiguration(handler, exception, stackTrace);
  }
}

// ------------------------------------------------------------------------
//                       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);

  /// Binds actual argument values to formal parameters of the function in a
  /// new environment or in the provided initial environment.
  /// TODO: Add checks for validation of arguments according to spec.
  static Environment createEnvironment(
      FunctionNode function, List<InterpreterValue> args,
      [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 =
          newEnv.extend(function.positionalParameters[i], positional[i].value);
    }

    Map<String, Value> named = new Map.fromIterable(
        args.where((InterpreterValue av) => av is NamedValue),
        key: (NamedValue av) => av.name,
        value: (NamedValue av) => av.value);

    // Add named parameters.
    for (VariableDeclaration v in function.namedParameters) {
      newEnv = newEnv.extend(v, named[v.name.toString()]);
    }

    return newEnv;
  }
}

/// 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;

  ValueA(this.value, this.applicationContinuation);

  Configuration call(List<InterpreterValue> args) {
    args.add(value);
    return new ApplicationConfiguration(applicationContinuation, args);
  }
}

class StringConcatenationA extends ApplicationContinuation {
  final ExpressionContinuation continuation;

  StringConcatenationA(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()));
  }
}

/// Represents the application continuation for static invocation.
class StaticInvocationA extends ApplicationContinuation {
  final FunctionNode function;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  StaticInvocationA(this.function, this.exceptionComponents, this.continuation);

  Configuration call(List<InterpreterValue> argValues) {
    Environment functionEnv =
        ApplicationContinuation.createEnvironment(function, argValues);
    State bodyState = new State(null, exceptionComponents, continuation,
        new ExitSK(continuation, Value.nullInstance));

    return new ExecConfiguration(function.body, functionEnv, bodyState);
  }
}

/// Represents the application continuation for constructor invocation applied
/// on the list of evaluated arguments when a constructor is invoked with new.
///
/// It creates the newly allocated object instance.
class ConstructorInvocationA extends ApplicationContinuation {
  final Constructor constructor;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  ConstructorInvocationA(
      this.constructor, this.exceptionComponents, 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_);
    var cont = new InitializationEK(constructor, ctrEnv, exceptionComponents,
        new NewSK(continuation, new Location(newObject)));

    return new ValuePassingConfiguration(cont, newObject);
  }
}

/// Represents the application continuation for constructor invocation applied
/// on the list of evaluated arguments when a constructor is invoked in a
/// constructor initializer list with a [RedirectingInitializer] or
/// [SuperInitializer].
class ConstructorInitializerA extends ApplicationContinuation {
  final Constructor constructor;
  final Location location;
  final ExceptionComponents exceptionComponents;
  final ConstructorBodySK continuation;

  ConstructorInitializerA(this.constructor, this.location,
      this.exceptionComponents, this.continuation);

  Configuration call(List<InterpreterValue> vs) {
    Environment ctrEnv =
        ApplicationContinuation.createEnvironment(constructor.function, vs);
    var cont = new InitializationEK(
        constructor, ctrEnv, exceptionComponents, continuation);

    return new ValuePassingConfiguration(cont, location.value);
  }
}

/// Represents the application continuation applied on the list of evaluated
/// field initializer expressions.
class InstanceFieldsA extends ApplicationContinuation {
  final Constructor constructor;
  final Location location;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ConstructorBodySK continuation;

  final Class _currentClass;

  InstanceFieldsA(this.constructor, this.location, this.environment,
      this.exceptionComponents, this.continuation)
      : _currentClass = new Class(constructor.enclosingClass.reference);

  Configuration call(List<InterpreterValue> fieldValues) {
    for (FieldInitializerValue f in fieldValues) {
      // Directly set the field with the corresponding implicit setter.
      _currentClass.implicitSetters[f.field.name](location.value, f.value);
    }

    if (constructor.initializers.length == 0) {
      // This can happen when initializing fields of a constructor with an empty
      // initializer list.
      return new ForwardConfiguration(continuation, environment);
    }

    if (constructor.initializers.first is SuperInitializer) {
      // Target constructor is from the superclass `object`.
      if (_currentClass.superclass.superclass == null) {
        // TODO(zhivkag): Execute the constructor when support for
        // native/external functions is added.
        _initializeNullFields(_currentClass, location.value);
        return new ForwardConfiguration(continuation, environment);
      }

      return _createEvalListConfig(constructor.initializers.first);
    }

    // Otherwise, the next expression from Field or Local initializers will be
    // evaluated.
    return _createEvalConfig(constructor.initializers.first);
  }

  Configuration _createEvalListConfig(SuperInitializer initializer) {
    List<InterpreterExpression> args = _getArgumentExpressions(
        initializer.arguments, initializer.target.function);
    var cont = new ConstructorInitializerA(
        initializer.target, location, exceptionComponents, continuation);

    return new EvalListConfiguration(
        args, environment, exceptionComponents, cont);
  }

  EvalConfiguration _createEvalConfig(Initializer initializer) {
    Expression expr = (initializer is FieldInitializer)
        ? initializer.value
        : (initializer as LocalInitializer).variable.initializer;

    // We start with index = 0 since we are evaluating the expression for the
    // first initializer in the initializer list.
    var cont = new InitializerListEK(constructor, 0, location, environment,
        exceptionComponents, continuation);
    return new EvalConfiguration(expr, environment, exceptionComponents, cont);
  }
}

class FunctionValueA extends ApplicationContinuation {
  final FunctionValue receiver;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation returnContinuation;

  FunctionValueA(
      this.receiver, this.exceptionComponents, this.returnContinuation);

  Configuration call(List<InterpreterValue> vs) {
    Environment env = ApplicationContinuation.createEnvironment(
        receiver.function, vs, receiver.environment);
    var scont = new ExitSK(returnContinuation, Value.nullInstance);
    var state = new State(null, exceptionComponents, returnContinuation, scont);
    return new ExecConfiguration(receiver.function.body, env, state);
  }
}

// ------------------------------------------------------------------------
//                           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 ExpressionEK extends ExpressionContinuation {
  final StatementContinuation continuation;
  final Environment environment;

  ExpressionEK(this.continuation, this.environment);

  Configuration call(Value _) {
    return new ForwardConfiguration(continuation, environment);
  }
}

class PrintEK extends ExpressionContinuation {
  final ExpressionContinuation continuation;

  PrintEK(this.continuation);

  Configuration call(Value v) {
    log.info('print(${v.value.runtimeType}: ${v.value})\n');
    print(v.value);
    return new ValuePassingConfiguration(continuation, Value.nullInstance);
  }
}

class PropertyGetEK extends ExpressionContinuation {
  final Name name;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  PropertyGetEK(this.name, this.exceptionComponents, this.continuation);

  Configuration call(Value receiver) {
    if (receiver.class_.isMethod(name)) {
      var method = receiver.class_.lookup(name);
      // Return the function value with this bound to receiver.
      var env = new Environment.empty().extendWithThis(receiver);
      return new ValuePassingConfiguration(
          continuation, new FunctionValue(method, env));
    }

    if (receiver.class_.isGetter(name)) {
      var getter = receiver.class_.lookup(name);
      var state = new State.initial()
          .withReturnContinuation(continuation)
          .withContinuation(new ExitSK(continuation, Value.nullInstance))
          .withException(exceptionComponents);
      return new ExecConfiguration(
          getter.body, new Environment.empty().extendWithThis(receiver), state);
    }

    Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver);
    return new ValuePassingConfiguration(continuation, propertyValue);
  }
}

class PropertySetEK extends ExpressionContinuation {
  final Expression value;
  final Name setterName;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  PropertySetEK(this.value, this.setterName, this.environment,
      this.exceptionComponents, this.continuation);

  Configuration call(Value receiver) {
    var cont =
        new SetterEK(receiver, setterName, exceptionComponents, continuation);
    return new EvalConfiguration(value, environment, exceptionComponents, cont);
  }
}

class SetterEK extends ExpressionContinuation {
  final Value receiver;
  final Name name;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  SetterEK(
      this.receiver, this.name, this.exceptionComponents, this.continuation);

  Configuration call(Value v) {
    if (receiver.class_.isSetter(name)) {
      var setter = receiver.class_.lookup(name);
      var env = new Environment.empty()
          .extendWithThis(receiver)
          .extend(setter.positionalParameters.first, v);
      var state = new State.initial()
          .withReturnContinuation(continuation)
          .withContinuation(new ExitSK(continuation, Value.nullInstance))
          .withException(exceptionComponents);
      return new ExecConfiguration(setter.body, env, state);
    }

    Setter setter = receiver.class_.lookupImplicitSetter(name);
    setter(receiver, v);
    return new ValuePassingConfiguration(continuation, v);
  }
}

class StaticSetEK extends ExpressionContinuation {
  final Member member;
  final ExpressionContinuation continuation;

  StaticSetEK(this.member, this.continuation);

  Configuration call(Value v) {
    if (Interpreter.mainEnvironment.contains(member)) {
      Interpreter.mainEnvironment.updateStore(member, v);
    } else {
      Interpreter.mainEnvironment =
          Interpreter.mainEnvironment.extend(member, v);
    }
    return new ValuePassingConfiguration(continuation, v);
  }
}

class StaticSetterEK extends ExpressionContinuation {
  final FunctionNode setter;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation expressionContinuation;

  StaticSetterEK(
      this.setter, this.exceptionComponents, this.expressionContinuation);

  Configuration call(Value v) {
    VariableDeclaration arg = setter.positionalParameters.first;
    var env = new Environment.empty().extend(arg, v);
    var state = new State.initial()
        .withException(exceptionComponents)
        .withReturnContinuation(expressionContinuation)
        .withContinuation(
            new ExitSK(expressionContinuation, Value.nullInstance));

    return new ExecConfiguration(setter.body, env, state);
  }
}

/// Represents a continuation to be called after the evaluation of an actual
/// argument for function invocation.
class ExpressionListEK extends ExpressionContinuation {
  final InterpreterExpression currentExpression;
  final List<InterpreterExpression> expressions;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ApplicationContinuation applicationContinuation;

  ExpressionListEK(this.currentExpression, this.expressions, this.environment,
      this.exceptionComponents, this.applicationContinuation);

  Configuration call(Value v) {
    ValueA app =
        new ValueA(currentExpression.assignValue(v), applicationContinuation);
    return new EvalListConfiguration(
        expressions, environment, exceptionComponents, app);
  }
}

class MethodInvocationEK extends ExpressionContinuation {
  final Arguments arguments;
  final Name methodName;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  MethodInvocationEK(this.arguments, this.methodName, this.environment,
      this.exceptionComponents, this.continuation);

  Configuration call(Value receiver) {
    if (receiver is LiteralValue) {
      // TODO(zhivkag): CPS method invocation for literals
      if (arguments.positional.isEmpty) {
        Value returnValue = receiver.invokeMethod(methodName);
        return new ValuePassingConfiguration(continuation, returnValue);
      }
      var cont = new ArgumentsEK(
          receiver, methodName, arguments, environment, continuation);

      return new EvalConfiguration(
          arguments.positional.first, environment, exceptionComponents, cont);
    }

    FunctionValue fun;
    if (receiver is FunctionValue) {
      // TODO(zhivkag): Throw an exception when method is not call.
      assert(methodName.toString() == "call");
      fun = receiver;
    } else {
      assert(receiver.class_.isMethod(methodName));
      fun = new FunctionValue(receiver.class_.lookup(methodName),
          new Environment.empty().extendWithThis(receiver));
    }

    var args = _getArgumentExpressions(arguments, fun.function);
    var acont = new FunctionValueA(receiver, exceptionComponents, continuation);
    return new EvalListConfiguration(
        args, environment, exceptionComponents, acont);
  }
}

class ArgumentsEK extends ExpressionContinuation {
  final Value receiver;
  final Name methodName;
  final Arguments arguments;
  final Environment environment;
  final ExpressionContinuation 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
    // with 1 argument.
    Value returnValue = receiver.invokeMethod(methodName, value);
    return new ValuePassingConfiguration(continuation, returnValue);
  }
}

class VariableSetEK extends ExpressionContinuation {
  final VariableDeclaration variable;
  final Environment environment;
  final ExpressionContinuation continuation;

  VariableSetEK(this.variable, this.environment, this.continuation);

  Configuration call(Value value) {
    environment.updateStore(variable, value);
    return new ValuePassingConfiguration(continuation, value);
  }
}

class NotEK extends ExpressionContinuation {
  final ExpressionContinuation continuation;

  NotEK(this.continuation);

  Configuration call(Value value) {
    Value notValue = identical(Value.trueInstance, value)
        ? Value.falseInstance
        : Value.trueInstance;
    return new ValuePassingConfiguration(continuation, notValue);
  }
}

class OrEK extends ExpressionContinuation {
  final Expression right;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  OrEK(this.right, this.environment, this.exceptionComponents,
      this.continuation);

  Configuration call(Value left) {
    return identical(Value.trueInstance, left)
        ? new ValuePassingConfiguration(continuation, Value.trueInstance)
        : new EvalConfiguration(
            right, environment, exceptionComponents, continuation);
  }
}

class AndEK extends ExpressionContinuation {
  final Expression right;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  AndEK(this.right, this.environment, this.exceptionComponents,
      this.continuation);

  Configuration call(Value left) {
    return identical(Value.falseInstance, left)
        ? new ValuePassingConfiguration(continuation, Value.falseInstance)
        : new EvalConfiguration(
            right, environment, exceptionComponents, continuation);
  }
}

class ConditionalEK extends ExpressionContinuation {
  final Expression then;
  final Expression otherwise;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  ConditionalEK(this.then, this.otherwise, this.environment,
      this.exceptionComponents, this.continuation);

  Configuration call(Value value) {
    return identical(Value.trueInstance, value)
        ? new EvalConfiguration(
            then, environment, exceptionComponents, continuation)
        : new EvalConfiguration(
            otherwise, environment, exceptionComponents, continuation);
  }
}

class LetEK extends ExpressionContinuation {
  final VariableDeclaration variable;
  final Expression letBody;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ExpressionContinuation continuation;

  LetEK(this.variable, this.letBody, this.environment, this.exceptionComponents,
      this.continuation);

  Configuration call(Value value) {
    var letEnv = environment.extend(variable, value);
    return new EvalConfiguration(
        letBody, letEnv, exceptionComponents, continuation);
  }
}

/// Represents the continuation for the condition expression in [WhileStatement].
class WhileConditionEK extends ExpressionContinuation {
  final Expression condition;
  final Statement body;
  final Environment enclosingEnv;
  final State state;

  WhileConditionEK(this.condition, this.body, this.enclosingEnv, this.state);

  Configuration call(Value v) {
    if (identical(v, Value.falseInstance)) {
      return new ForwardConfiguration(state.continuation, enclosingEnv);
    }
    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 IfConditionEK extends ExpressionContinuation {
  final Statement then;
  final Statement otherwise;
  final Environment environment;
  final State state;

  IfConditionEK(this.then, this.otherwise, this.environment, this.state);

  Configuration call(Value v) {
    if (identical(v, Value.trueInstance)) {
      log.info("if-then\n");
      return new ExecConfiguration(then, environment, state);
    } else if (otherwise != null) {
      log.info("if-otherwise\n");
      return new ExecConfiguration(otherwise, environment, state);
    }
    return new ForwardConfiguration(state.continuation, environment);
  }
}

/// Represents the continuation for the initializer expression in
/// [VariableDeclaration].
class VariableInitializerEK extends ExpressionContinuation {
  final VariableDeclaration variable;
  final Environment environment;
  final StatementContinuation continuation;
  VariableInitializerEK(this.variable, this.environment, this.continuation);

  Configuration call(Value v) {
    return new ForwardConfiguration(
        continuation, environment.extend(variable, v));
  }
}

/// Expression continuation that further initializes the newly allocated object
/// instance with running the constructor.
class InitializationEK extends ExpressionContinuation {
  final Constructor constructor;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final StatementContinuation continuation;

  InitializationEK(this.constructor, this.environment, this.exceptionComponents,
      this.continuation);

  Configuration call(Value value) {
    Location location = new Location(value);

    if (constructor.initializers.isNotEmpty &&
        constructor.initializers.last is RedirectingInitializer) {
      return _createRedirectingInitializerConfig(
          constructor.initializers.first, location);
    }
    // The statement body is captured by the next statement continuation and
    // expressions for field initialization are evaluated.
    var ctrEnv = environment.extendWithThis(value);
    var bodyCont = new ConstructorBodySK(
        constructor.function.body, ctrEnv, exceptionComponents, continuation);
    var initializers = _getFieldInitializers(constructor.enclosingClass);
    var fieldsCont = new InstanceFieldsA(
        constructor, location, ctrEnv, exceptionComponents, bodyCont);
    return new EvalListConfiguration(
        initializers, new Environment.empty(), exceptionComponents, fieldsCont);
  }

  /// Creates the next configuration to further initializer the value for
  /// redirecting constructors.
  Configuration _createRedirectingInitializerConfig(
      Initializer initializer, Location location) {
    Initializer current = constructor.initializers.first;
    if (current is RedirectingInitializer) {
      // Evaluate the list of arguments for invoking the target constructor in
      // the current environment.
      List<InterpreterExpression> exprs =
          _getArgumentExpressions(current.arguments, current.target.function);
      var cont = new ConstructorInitializerA(
          current.target, location, exceptionComponents, continuation);
      return new EvalListConfiguration(
          exprs, environment, exceptionComponents, cont);
    }
    Expression expr = (current is FieldInitializer)
        ? current.value
        : (current as LocalInitializer).variable.initializer;

    // The index is set to 0 since we are evaluating the expression for the
    // first initializer in the initializer list.
    var cont = new InitializerListEK(constructor, 0, location, environment,
        exceptionComponents, continuation);
    return new EvalConfiguration(expr, environment, exceptionComponents, cont);
  }
}

class InitializerListEK extends ExpressionContinuation {
  final Constructor constructor;
  final int initializerIndex;
  final Location location;
  final Environment environment;
  final ExceptionComponents exceptionComponents;
  final ConstructorBodySK continuation;

  final Class _currentClass;

  InitializerListEK(this.constructor, this.initializerIndex, this.location,
      this.environment, this.exceptionComponents, this.continuation)
      : _currentClass = new Class(constructor.enclosingClass.reference);

  /// Creates a continuation for the evaluation of the initializer at position
  /// [index].
  InitializerListEK withInitializerIndex(int index) {
    return new InitializerListEK(constructor, index, location, environment,
        exceptionComponents, continuation);
  }

  Configuration call(Value value) {
    Initializer current = constructor.initializers[initializerIndex];
    if (current is FieldInitializer) {
      _currentClass.lookupImplicitSetter(current.field.name)(
          location.value, value);
      return _createNextConfiguration(environment);
    }
    if (current is LocalInitializer) {
      Environment newEnv = environment.extend(current.variable, value);
      return _createNextConfiguration(newEnv);
    }
    throw "Value can't be applied to initalizer of type ${current.runtimeType}";
  }

  Configuration _createNextConfiguration(Environment env) {
    assert(initializerIndex + 1 < constructor.initializers.length);
    Initializer next = constructor.initializers[initializerIndex + 1];
    if (next is SuperInitializer) {
      // TODO(zhivkag): Execute constructor of "object" class when support for
      // native/external functions is added.
      if (_currentClass.superclass.superclass == null) {
        _initializeNullFields(_currentClass, location.value);
        return new ForwardConfiguration(continuation, environment);
      }
      return _createEvalListConfig(next.arguments, next.target, env);
    }

    if (next is RedirectingInitializer) {
      return _createEvalListConfig(next.arguments, next.target, env);
    }

    Expression nextExpr = (next is FieldInitializer)
        ? next.value
        : (next as LocalInitializer).variable.initializer;

    var cont = withInitializerIndex(initializerIndex + 1);
    return new EvalConfiguration(nextExpr, env, exceptionComponents, cont);
  }

  Configuration _createEvalListConfig(
      Arguments args, Constructor ctr, Environment env) {
    List<InterpreterExpression> exprs =
        _getArgumentExpressions(args, ctr.function);
    var cont = new ConstructorInitializerA(
        ctr, location, exceptionComponents, continuation);
    return new EvalListConfiguration(exprs, env, exceptionComponents, cont);
  }
}

class ThrowEK extends ExpressionContinuation {
  final ExceptionComponents exceptionComponents;

  ThrowEK(this.exceptionComponents);

  Configuration call(Value value) {
    return new ThrowConfiguration(
        exceptionComponents.handler, value, exceptionComponents.stackTrace);
  }
}

/// Represents the expression continuation that ensures the finalizer of a
/// [TryFinally] node is executed before applying the return continuation to
/// the given value.
///
/// It executes the captured finalizer statement and adds a statement
/// continuation that will apply the return continuation to the given value
/// when/if reached.
class FinallyReturnEK extends ExpressionContinuation {
  final Statement statement;
  final Environment environment;
  final State state;

  FinallyReturnEK(this.statement, this.environment, this.state);

  Configuration call(Value value) {
    return new ExecConfiguration(statement, environment,
        state.withContinuation(new ExitSK(state.returnContinuation, value)));
  }
}

// ------------------------------------------------------------------------
//                        Exceptions Handlers
// ------------------------------------------------------------------------

abstract class ExceptionHandler extends Continuation {
  Configuration call(Value exception, StackTrace stacktrace);

  static String errorMessage(Value exception, StackTrace stacktrace) {
    return 'Uncaught exception '
        '"${exception.value.runtimeType} : ${exception.value}"\n'
        '${stacktrace.toString()}';
  }
}

/// Handler for showing an exception to the user and returning a halting the
/// execution of the program when an exception is not handled.
class MainHandler extends ExceptionHandler {
  Configuration call(Value exception, StackTrace stacktrace) {
    var message = ExceptionHandler.errorMessage(exception, stacktrace);
    log.info(message);
    print(message);
    return null;
  }
}

/// Represents the handler that either executes a matching catch clause or
/// applies the next handler to the given exception.
class CatchHandler extends ExceptionHandler {
  final List<Catch> catches;
  final Environment environment;
  final State state;

  CatchHandler(this.catches, this.environment, this.state);

  Configuration call(Value exception, StackTrace stackTrace) {
    // TODO(zhivkag): Check if there is a matching catch clause instead.
    return new ThrowConfiguration(
        state.exceptionComponents.handler, exception, stackTrace);
  }
}

/// Represents the handler that executes the corresponding finalizer before
/// applying the next handler to the given exception.
///
/// Applying the next handler to the given exception is supported with adding
/// [RethrowSK] as next statement continuation.
class FinallyHandler extends ExceptionHandler {
  final Statement finallyStatement;
  final Environment environment;
  final State state;

  FinallyHandler(this.finallyStatement, this.environment, this.state);
  Configuration call(Value exception, StackTrace stackTrace) {
    // A finally handler can't handle an exception, only execute the
    // corresponding finally statement and rethrow.
    var cont =
        new RethrowSK(state.exceptionComponents.handler, exception, stackTrace);
    var newState = state.withContinuation(cont);
    return new ExecConfiguration(finallyStatement, environment, newState);
  }
}

// ------------------------------------------------------------------------
//                        Exceptions
// ------------------------------------------------------------------------
/// Represents the components for Exception handling.
///
/// It contains the current of exception handler, a stack trace and optional
/// components, current stacktrace and exception.
class ExceptionComponents {
  final ExceptionHandler handler;
  final StackTrace stackTrace;

  /// Current exception and stack trace.
  ///
  /// Components enabling support for `rethrow` expressions and set only in
  /// catch clauses.
  final StackTrace currentStackTrace;
  final Value currentException;

  ExceptionComponents(this.handler, this.stackTrace, this.currentStackTrace,
      this.currentException);

  ExceptionComponents.initial()
      : handler = new MainHandler(),
        stackTrace = new StackTrace(null, null),
        currentStackTrace = null,
        currentException = null;
}

class StackTrace {
  final Expression expression;
  final StackTrace stackTrace;

  StackTrace(this.expression, this.stackTrace);

  String toString() {
    var buffer = new StringBuffer('in main()');
    var current = this;
    while (current.expression != null) {
      buffer.write('at ${current.expression.toString()}\n');
      current = current.stackTrace;
    }
    return buffer.toString();
  }
}

/// Executes statements.
///
/// 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, in which case the return continuation is
/// returned and applied accordingly.
/// - It throws, in which case the handler is returned and applied accordingly.
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, ExecConfiguration conf) =>
      statement.accept1(this, conf);
  Configuration eval(Expression expression, EvalConfiguration config) =>
      evaluator.eval(expression, config);
  Configuration evalList(List<InterpreterExpression> es, Environment env,
          ExceptionComponents ecs, Continuation cont) =>
      evaluator.evalList(es, env, ecs, cont);

  Configuration defaultStatement(Statement node, ExecConfiguration conf) {
    throw notImplemented(
        m: "Execution is not implemented for statement:\n$node ");
  }

  Configuration visitInvalidStatement(
      InvalidStatement node, ExecConfiguration conf) {
    throw "Invalid statement at ${node.location}";
  }

  Configuration visitExpressionStatement(
      ExpressionStatement node, ExecConfiguration conf) {
    var cont = new ExpressionEK(conf.state.continuation, conf.environment);
    return new EvalConfiguration(node.expression, conf.environment,
        conf.state.exceptionComponents, cont);
  }

  Configuration visitBlock(Block node, ExecConfiguration conf) {
    if (node.statements.isEmpty) {
      return new ForwardConfiguration(
          conf.state.continuation, conf.environment);
    }

    var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf);
    return new ExecConfiguration(node.statements.first, conf.environment,
        conf.state.withContinuation(cont));
  }

  Configuration visitEmptyStatement(
      EmptyStatement node, ExecConfiguration conf) {
    return new ForwardConfiguration(conf.state.continuation, conf.environment);
  }

  Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) {
    var cont = new IfConditionEK(
        node.then, node.otherwise, conf.environment, conf.state);

    return new EvalConfiguration(
        node.condition, conf.environment, conf.state.exceptionComponents, cont);
  }

  Configuration visitLabeledStatement(
      LabeledStatement node, ExecConfiguration conf) {
    return new ExecConfiguration(node.body, conf.environment,
        conf.state.withBreak(node, conf.environment));
  }

  Configuration visitBreakStatement(
      BreakStatement node, ExecConfiguration conf) {
    Label l = conf.state.lookupLabel(node.target);
    return new BreakConfiguration(l.continuation);
  }

  Configuration visitWhileStatement(
      WhileStatement node, ExecConfiguration conf) {
    var cont = new WhileConditionEK(
        node.condition, node.body, conf.environment, conf.state);

    return new EvalConfiguration(
        node.condition, conf.environment, conf.state.exceptionComponents, cont);
  }

  Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) {
    var cont = new WhileConditionSK(
        node.condition, node.body, conf.environment, conf.state);

    return new ExecConfiguration(
        node.body, conf.environment, conf.state.withContinuation(cont));
  }

  Configuration visitReturnStatement(
      ReturnStatement node, ExecConfiguration conf) {
    assert(conf.state.returnContinuation != null);
    log.info('return\n');
    if (node.expression == null) {
      return new ValuePassingConfiguration(
          conf.state.returnContinuation, Value.nullInstance);
    }
    return new EvalConfiguration(node.expression, conf.environment,
        conf.state.exceptionComponents, conf.state.returnContinuation);
  }

  Configuration visitTryCatch(TryCatch node, ExecConfiguration conf) {
    var handler = new CatchHandler(node.catches, conf.environment, conf.state);
    var exceptionComponents = new ExceptionComponents(
        handler,
        conf.state.exceptionComponents.stackTrace,
        conf.state.exceptionComponents.currentStackTrace,
        conf.state.exceptionComponents.currentException);
    var state = conf.state.withException(exceptionComponents);
    return new ExecConfiguration(node.body, conf.environment, state);
  }

  Configuration visitTryFinally(TryFinally node, ExecConfiguration conf) {
    var cont = new FinallySK(node.finalizer, conf.environment, conf.state);
    var returnCont =
        new FinallyReturnEK(node.finalizer, conf.environment, conf.state);
    var labels = conf.state.labels
        ?.withFinalizer(node.finalizer, conf.environment, conf.state);
    var handler =
        new FinallyHandler(node.finalizer, conf.environment, conf.state);
    var exceptionComponents = new ExceptionComponents(
        handler,
        conf.state.exceptionComponents.stackTrace,
        conf.state.exceptionComponents.currentStackTrace,
        conf.state.exceptionComponents.currentException);
    var state = new State(labels, exceptionComponents, returnCont, cont);
    return new ExecConfiguration(node.body, conf.environment, state);
  }

  Configuration visitVariableDeclaration(
      VariableDeclaration node, ExecConfiguration conf) {
    if (node.initializer != null) {
      var cont = new VariableInitializerEK(
          node, conf.environment, conf.state.continuation);
      return new EvalConfiguration(node.initializer, conf.environment,
          conf.state.exceptionComponents, cont);
    }
    return new ForwardConfiguration(conf.state.continuation,
        conf.environment.extend(node, Value.nullInstance));
  }

  Configuration visitFunctionDeclaration(
      FunctionDeclaration node, ExecConfiguration conf) {
    var newEnv = conf.environment.extend(node.variable, Value.nullInstance);
    var fun = new FunctionValue(node.function, newEnv);
    newEnv.updateStore(node.variable, fun);
    return new ForwardConfiguration(conf.state.continuation, newEnv);
  }
}

// ------------------------------------------------------------------------
//                                VALUES
// ------------------------------------------------------------------------

typedef Value Getter(Value receiver);
typedef void Setter(Value receiver, Value value);

class Class {
  static final Map<Reference, Class> _classes = <Reference, Class>{};

  /// The immediate superclass, or `null` if this is the root class object.
  Class superclass;

  /// The class definitions from the `implements` clause.
  final List<Supertype> interfaces = <Supertype>[];

  /// Implicit getters for instance fields.
  Map<Name, Getter> implicitGetters = <Name, Getter>{};

  /// Implicit setters for non final instance fields.
  Map<Name, Setter> implicitSetters = <Name, Setter>{};

  /// Instance methods, explicit getters and setters.
  Map<Name, Procedure> methods = <Name, Procedure>{};

  int get instanceSize => implicitGetters.length;

  factory Class(Reference classRef) {
    return _classes.putIfAbsent(
        classRef, () => new Class._internal(classRef.asClass));
  }

  Class._internal(ast.Class currentClass) {
    if (currentClass.superclass != null) {
      superclass = new Class(currentClass.superclass.reference);
    }

    _populateImplicitGettersAndSetters(currentClass);
    _populateInstanceMethods(currentClass);
  }

  Getter lookupImplicitGetter(Name name) {
    Getter getter = implicitGetters[name];
    if (getter != null) return getter;
    if (superclass != null) return superclass.lookupImplicitGetter(name);
    return (Value receiver) => notImplemented(obj: name);
  }

  Setter lookupImplicitSetter(Name name) {
    Setter setter = implicitSetters[name];
    if (setter != null) return setter;
    if (superclass != null) return superclass.lookupImplicitSetter(name);
    // TODO(zhivkag): Throw NoSuchInstance error instead.
    return (Value receiver, Value value) => notImplemented(obj: name);
  }

  FunctionNode lookup(Name name) => methods[name]?.function;

  bool isGetter(Name name) => methods[name]?.isGetter ?? false;
  bool isSetter(Name name) => methods[name]?.isSetter ?? false;
  bool isMethod(Name name) => !(methods[name]?.isAccessor ?? true);

  /// Populates implicit getters and setters for the current class and its
  /// superclass recursively.
  _populateImplicitGettersAndSetters(ast.Class class_) {
    if (class_.superclass != null) {
      _populateImplicitGettersAndSetters(class_.superclass);
    }

    for (Field f in class_.fields) {
      if (f.isStatic) continue;
      assert(f.hasImplicitGetter);

      int currentFieldIndex = implicitGetters.length;
      // Shadowing an inherited getter with the same name.
      implicitGetters[f.name] =
          (Value receiver) => receiver.fields[currentFieldIndex].value;
      if (f.hasImplicitSetter) {
        // Shadowing an inherited setter with the same name.
        implicitSetters[f.name] = (Value receiver, Value value) =>
            receiver.fields[currentFieldIndex].value = value;
      }
    }
  }

  /// Populates instance methods, getters and setters for the current class and
  /// its super class recursively.
  _populateInstanceMethods(ast.Class class_) {
    if (class_.superclass != null) {
      _populateInstanceMethods(class_.superclass);
    }

    for (Member m in class_.members) {
      if (m is Procedure) {
        // Shadowing an inherited method, getter or setter with the same name.
        methods[m.name] = m;
      }
    }
  }
}

abstract class Value {
  Class get class_;
  List<Location> get fields;
  Object get value;

  static final NullValue nullInstance = const NullValue();
  static final BoolValue trueInstance = const BoolValue(true);
  static final BoolValue falseInstance = const BoolValue(false);

  const Value();

  BoolValue toBoolean() {
    return identical(this, Value.trueInstance)
        ? Value.trueInstance
        : Value.falseInstance;
  }

  BoolValue equals(Value other) =>
      value == other?.value ? Value.trueInstance : Value.falseInstance;

  Value invokeMethod(Name name, [Value arg]) {
    if (name.toString() == "==") return equals(arg);
    throw notImplemented(obj: name);
  }
}

class ObjectValue extends Value {
  final Class class_;
  final List<Location> fields;
  Object get value => this;

  ObjectValue(this.class_) : fields = new List<Location>(class_.instanceSize) {
    for (int i = 0; i < fields.length; i++) {
      // Create fresh locations for each field.
      fields[i] = new Location.empty();
    }
  }
}

class FunctionValue extends Value {
  Class get class_ => throw 'Class for FunctionValue is not defined';
  List<Location> get fields => throw 'FunctionValue has no fields.';

  FunctionValue get value => this;

  final FunctionNode function;
  final Environment environment;

  FunctionValue(this.function, this.environment);
}

abstract class LiteralValue extends Value {
  Class get class_ =>
      notImplemented(m: "Loading class for literal is not implemented.");
  List<Location> get fields =>
      notImplemented(m: "Literal value does not have fields");

  const LiteralValue();
}

class StringValue extends LiteralValue {
  final String value;

  static final operators = <String, Function>{
    '[]': (StringValue v1, Value v2) => v1[v2],
    '==': (StringValue v1, Value v2) => v1.equals(v2)
  };

  StringValue(this.value);

  Value invokeMethod(Name name, [Value arg]) {
    if (!operators.containsKey(name.name)) {
      return notImplemented(obj: name);
    }
    return operators[name.name](this, arg);
  }

  // Operators
  Value operator [](Value index) => new StringValue(value[index.value]);
}

abstract class NumValue extends LiteralValue {
  num get value;

  NumValue();

  factory NumValue.fromValue(num value) {
    if (value is int) {
      return new IntValue(value);
    } else {
      assert(value is double);
      return new DoubleValue(value);
    }
  }

  static final operators = <String, Function>{
    '+': (NumValue v1, Value v2) => v1 + v2,
    '-': (NumValue v1, Value v2) => v1 - v2,
    '>': (NumValue v1, Value v2) => v1 > v2,
    '<': (NumValue v1, Value v2) => v1 < v2,
    '==': (NumValue v1, Value v2) => v1.equals(v2),
    'unary-': (NumValue v1) => -v1,
  };

  Value invokeMethod(Name name, [Value arg]) {
    if (!operators.containsKey(name.name)) return notImplemented(obj: name);
    if (arg == null) return operators[name.name](this);
    return operators[name.name](this, arg);
  }

  // Operators
  NumValue operator +(Value other) =>
      new NumValue.fromValue(value + other.value);
  NumValue operator -(Value other) =>
      new NumValue.fromValue(value - other.value);
  NumValue operator -() => new NumValue.fromValue(-value);

  BoolValue operator >(Value other) =>
      value > other.value ? Value.trueInstance : Value.falseInstance;
  BoolValue operator <(Value other) =>
      value < other.value ? Value.trueInstance : Value.falseInstance;
}

class IntValue extends NumValue {
  final int value;

  IntValue(this.value);
}

class DoubleValue extends NumValue {
  final double value;

  DoubleValue(this.value);
}

class BoolValue extends LiteralValue {
  final bool value;

  const BoolValue(this.value);
}

class NullValue extends LiteralValue {
  Object get value => null;

  const NullValue();
}

notImplemented({String m, Object obj}) {
  throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
}

// ------------------------------------------------------------------------
//                             INTERNAL FUNCTIONS
// ------------------------------------------------------------------------

/// Creates a list of all argument expressions to be evaluated for the
/// invocation of the provided [FunctionNode] containing the actual arguments
/// and the optional argument initializers.
List<InterpreterExpression> _getArgumentExpressions(
    Arguments providedArgs, FunctionNode fun) {
  List<InterpreterExpression> args = <InterpreterExpression>[];
  // Add positional arguments expressions.
  args.addAll(providedArgs.positional
      .map((Expression e) => new PositionalExpression(e)));

  // Add optional positional argument initializers.
  for (int i = providedArgs.positional.length;
      i < fun.positionalParameters.length;
      i++) {
    args.add(new PositionalExpression(fun.positionalParameters[i].initializer));
  }

  Map<String, NamedExpression> namedFormals = new Map.fromIterable(
      fun.namedParameters,
      key: (VariableDeclaration vd) => vd.name,
      value: (VariableDeclaration vd) =>
          new NamedExpression(vd.name, vd.initializer));

  // Add named expressions.
  for (int i = 0; i < providedArgs.named.length; i++) {
    var current = providedArgs.named[i];
    args.add(new NamedExpression(current.name, current.value));
    namedFormals.remove(current.name);
  }

  // Add missing optional named initializers.
  args.addAll(namedFormals.values);

  return args;
}

/// Creates a list of all field expressions to be evaluated.
///
/// A field expression is an initializer expression for a given field defined
/// when the field was created.
List<InterpreterExpression> _getFieldInitializers(ast.Class class_) {
  var fieldInitializers = new List<InterpreterExpression>();

  for (Field f in class_.fields) {
    if (!f.isStatic && f.initializer != null) {
      fieldInitializers.add(new FieldInitializerExpression(f, f.initializer));
    }
  }

  return fieldInitializers;
}

/// Initializes all non initialized fields from the provided class to
/// `Value.nullInstance` in the provided value.
void _initializeNullFields(Class class_, Value value) {
  int startIndex = class_.superclass?.instanceSize ?? 0;
  for (int i = startIndex; i < class_.instanceSize; i++) {
    if (value.fields[i].value == null) {
      value.fields[i].value = Value.nullInstance;
    }
  }
}
