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

class NotImplemented {
  String message;

  NotImplemented(this.message);

  String toString() => message;
}

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

  Interpreter(this.program);

  void run() {
    assert(program.libraries.isEmpty);
    Procedure mainMethod = program.mainMethod;
    Statement statementBlock = mainMethod.function.body;
    StatementConfiguration configuration =
        new StatementConfiguration(statementBlock, new State.initial());
    visitor.trampolinedExecution(configuration);
  }
}

class Binding {
  final VariableDeclaration variable;
  Value value;

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

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

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

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

  Binding lookupBinding(VariableDeclaration variable) {
    assert(contains(variable));
    for (Binding b in bindings) {
      if (identical(b.variable, variable)) return b;
    }
    return parent.lookupBinding(variable);
  }

  Value lookup(VariableDeclaration variable) {
    return lookupBinding(variable).value;
  }

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

  void expand(VariableDeclaration variable, Value value) {
    assert(!contains(variable));
    bindings.add(new Binding(variable, value));
  }
}

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

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

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

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

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

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

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

  Configuration visitStaticGet(
          StaticGet node, ExpressionConfiguration config) =>
      defaultExpression(node, config);
  Configuration visitStaticSet(
          StaticSet node, ExpressionConfiguration config) =>
      defaultExpression(node, config);

  Configuration visitStaticInvocation(
      StaticInvocation node, ExpressionConfiguration config) {
    if ('print' == node.name.toString()) {
      var cont = new PrintContinuation(config.continuation);
      return new ExpressionConfiguration(
          node.arguments.positional.first, config.environment, cont);
    } else {
      // Currently supports only static invocations with no arguments.
      if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) {
        State statementState = new State.initial()
            .withExpressionContinuation(config.continuation)
            .withConfiguration(new ExitConfiguration(config.continuation));

        return new StatementConfiguration(
            node.target.function.body, statementState);
      }
      throw new NotImplemented(
          'Support for static invocation with arguments is not implemented');
    }
  }

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

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

  Configuration visitConstructorInvocation(
      ConstructorInvocation node, ExpressionConfiguration config) {
    Class class_ = new Class(node.target.enclosingClass.reference);

    // 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 = <Value>[];

    return new ContinuationConfiguration(
        config.continuation, new ObjectValue(class_, fields));
  }

  Configuration visitNot(Not node, ExpressionConfiguration config) {
    return new ExpressionConfiguration(node.operand, config.environment,
        new NotContinuation(config.continuation));
  }

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

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

  Configuration visitStringConcatenation(
      StringConcatenation node, ExpressionConfiguration config) {
    var cont = new StringConcatenationContinuation(
        node.expressions, config.environment, config.continuation);
    return new ExpressionConfiguration(
        node.expressions.first, config.environment, cont);
  }

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

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

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

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

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

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

/// Represents a state for statement execution.
class State {
  final Environment environment;
  final Label labels;
  final StatementConfiguration statementConfiguration;

  final ExpressionContinuation returnContinuation;

  State(this.environment, this.labels, this.statementConfiguration,
      this.returnContinuation);

  State.initial() : this(new Environment.empty(), null, null, null);

  State withEnvironment(Environment env) {
    return new State(env, labels, statementConfiguration, returnContinuation);
  }

  State withBreak(Statement stmt) {
    Label breakLabels = new Label(stmt, statementConfiguration, labels);
    return new State(
        environment, breakLabels, statementConfiguration, returnContinuation);
  }

  State withConfiguration(Configuration config) {
    return new State(environment, labels, config, returnContinuation);
  }

  State withExpressionContinuation(ExpressionContinuation cont) {
    return new State(environment, labels, statementConfiguration, cont);
  }

  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 StatementConfiguration configuration;
  final Label enclosingLabel;

  Label(this.statement, this.configuration, this.enclosingLabel);

  Label lookupLabel(LabeledStatement s) {
    if (identical(s, statement)) return this;
    assert(enclosingLabel != null);
    return enclosingLabel.lookupLabel(s);
  }
}

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

/// Represents the configuration for execution of statement.
class StatementConfiguration extends Configuration {
  final Statement statement;
  final State state;

  StatementConfiguration(this.statement, this.state);

  Configuration step(StatementExecuter executer) =>
      executer.exec(statement, state);
}

class ExitConfiguration extends StatementConfiguration {
  final ExpressionContinuation returnContinuation;

  ExitConfiguration(this.returnContinuation) : super(null, null);

  Configuration step(StatementExecuter executer) {
    return returnContinuation(Value.nullInstance);
  }
}

/// Represents the configuration for applying an [ExpressionContinuation].
class ContinuationConfiguration extends Configuration {
  final ExpressionContinuation continuation;
  final Value value;

  ContinuationConfiguration(this.continuation, this.value);

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

/// Represents the configuration for evaluating an [Expression].
class ExpressionConfiguration extends Configuration {
  final Expression expression;

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

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

  ExpressionConfiguration(this.expression, this.environment, this.continuation);

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

/// Represents an expression continuation.
abstract class ExpressionContinuation {
  Configuration call(Value v);
}

/// Represents a continuation that returns the next [StatementConfiguration]
/// to be executed.
class ExpressionStatementContinuation extends ExpressionContinuation {
  final StatementConfiguration configuration;

  ExpressionStatementContinuation(this.configuration);

  Configuration call(Value _) {
    return configuration;
  }
}

class PrintContinuation extends ExpressionContinuation {
  final ExpressionContinuation continuation;

  PrintContinuation(this.continuation);

  Configuration call(Value v) {
    print(v.value);
    return new ContinuationConfiguration(continuation, Value.nullInstance);
  }
}

class PropertyGetContinuation extends ExpressionContinuation {
  final Name name;
  final ExpressionContinuation continuation;

  PropertyGetContinuation(this.name, this.continuation);

  Configuration call(Value receiver) {
    // TODO: CPS the invocation of the getter.
    Value propertyValue = receiver.class_.lookupGetter(name)(receiver);
    return new ContinuationConfiguration(continuation, propertyValue);
  }
}

class PropertySetContinuation extends ExpressionContinuation {
  final Expression value;
  final Name setterName;
  final Environment environment;
  final ExpressionContinuation continuation;

  PropertySetContinuation(
      this.value, this.setterName, this.environment, this.continuation);

  Configuration call(Value receiver) {
    var cont = new SetterContinuation(receiver, setterName, continuation);
    return new ExpressionConfiguration(value, environment, cont);
  }
}

class SetterContinuation extends ExpressionContinuation {
  final Value receiver;
  final Name name;
  final ExpressionContinuation continuation;

  SetterContinuation(this.receiver, this.name, this.continuation);

  Configuration call(Value v) {
    Setter setter = receiver.class_.lookupSetter(name);
    setter(receiver, v);
    return new ContinuationConfiguration(continuation, v);
  }
}

class StaticInvocationContinuation extends ExpressionContinuation {
  final ExpressionContinuation continuation;

  StaticInvocationContinuation(this.continuation);

  Configuration call(Value v) {
    return new ContinuationConfiguration(continuation, v);
  }
}

class MethodInvocationContinuation extends ExpressionContinuation {
  final Arguments arguments;
  final Name methodName;
  final Environment environment;
  final ExpressionContinuation continuation;

  MethodInvocationContinuation(
      this.arguments, this.methodName, this.environment, this.continuation);

  Configuration call(Value receiver) {
    if (arguments.positional.isEmpty) {
      Value returnValue = receiver.invokeMethod(methodName);
      return new ContinuationConfiguration(continuation, returnValue);
    }
    var cont = new ArgumentsContinuation(
        receiver, methodName, arguments, environment, continuation);

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

class ArgumentsContinuation extends ExpressionContinuation {
  final Value receiver;
  final Name methodName;
  final Arguments arguments;
  final Environment environment;
  final ExpressionContinuation continuation;

  ArgumentsContinuation(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 ContinuationConfiguration(continuation, returnValue);
  }
}

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

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

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

class NotContinuation extends ExpressionContinuation {
  final ExpressionContinuation continuation;

  NotContinuation(this.continuation);

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

class OrContinuation extends ExpressionContinuation {
  final Expression right;
  final Environment environment;
  final ExpressionContinuation continuation;

  OrContinuation(this.right, this.environment, this.continuation);

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

class AndContinuation extends ExpressionContinuation {
  final Expression right;
  final Environment environment;
  final ExpressionContinuation continuation;

  AndContinuation(this.right, this.environment, this.continuation);

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

class ConditionalContinuation extends ExpressionContinuation {
  final Expression then;
  final Expression otherwise;
  final Environment environment;
  final ExpressionContinuation continuation;

  ConditionalContinuation(
      this.then, this.otherwise, this.environment, this.continuation);

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

class StringConcatenationContinuation extends ExpressionContinuation {
  final List<Expression> expressions;
  final Environment environment;
  final ExpressionContinuation continuation;

  int _currentPosition = 0;
  final List<Value> _values = <Value>[];

  StringConcatenationContinuation(
      this.expressions, this.environment, this.continuation);

  Configuration call(Value value) {
    _values.add(value);
    if (_values.length == expressions.length) {
      StringBuffer res = new StringBuffer();

      for (int i = 0; i < expressions.length; i++) {
        res.write(_values[i].value);
      }

      Value value = new StringValue(res.toString());
      return new ContinuationConfiguration(continuation, value);
    }
    return new ExpressionConfiguration(
        expressions[++_currentPosition], environment, this);
  }
}

class LetContinuation extends ExpressionContinuation {
  final VariableDeclaration variable;
  final Expression letBody;
  final Environment environment;
  final ExpressionContinuation continuation;

  LetContinuation(
      this.variable, this.letBody, this.environment, this.continuation);

  Configuration call(Value value) {
    var letEnv = new Environment(environment);
    letEnv.expand(variable, value);
    return new ExpressionConfiguration(letBody, letEnv, continuation);
  }
}

/// Represents the continuation for the condition expression in [WhileStatement].
class WhileConditionContinuation extends ExpressionContinuation {
  final WhileStatement node;
  final State state;

  WhileConditionContinuation(this.node, this.state);

  StatementConfiguration call(Value v) {
    if (identical(v, Value.trueInstance)) {
      // Add configuration for the While statement to the linked list.
      StatementConfiguration config = new StatementConfiguration(node, state);
      // Configuration for the body of the loop.
      return new StatementConfiguration(
          node.body, state.withConfiguration(config));
    }

    return state.statementConfiguration;
  }
}

/// Represents the continuation for the condition expression in [IfStatement].
class IfConditionContinuation extends ExpressionContinuation {
  final Statement then;
  final Statement otherwise;
  final State state;

  IfConditionContinuation(this.then, this.otherwise, this.state);

  StatementConfiguration call(Value v) {
    if (identical(v, Value.trueInstance)) {
      return new StatementConfiguration(then, state);
    } else if (otherwise != null) {
      return new StatementConfiguration(otherwise, state);
    }
    return state.statementConfiguration;
  }
}

/// Represents the continuation for the initializer expression in
/// [VariableDeclaration].
class VariableInitializerContinuation extends ExpressionContinuation {
  final VariableDeclaration variable;
  final Environment environment;
  final StatementConfiguration nextConfiguration;

  VariableInitializerContinuation(
      this.variable, this.environment, this.nextConfiguration);

  StatementConfiguration call(Value v) {
    environment.expand(variable, v);
    return nextConfiguration;
  }
}

/// Executes statements.
///
/// Execution of a statement completes in one of the following ways:
/// - 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<Configuration, State> {
  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, ExpressionConfiguration config) =>
      evaluator.eval(expression, config);

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

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

  Configuration visitExpressionStatement(
      ExpressionStatement node, State state) {
    var cont =
        new ExpressionStatementContinuation(state.statementConfiguration);
    return new ExpressionConfiguration(
        node.expression, state.environment, cont);
  }

  Configuration visitBlock(Block node, State 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 state) {
    return state.statementConfiguration;
  }

  Configuration visitIfStatement(IfStatement node, State state) {
    var cont = new IfConditionContinuation(node.then, node.otherwise, state);

    return new ExpressionConfiguration(node.condition, state.environment, cont);
  }

  Configuration visitLabeledStatement(LabeledStatement node, State state) {
    return new StatementConfiguration(node.body, state.withBreak(node));
  }

  Configuration visitBreakStatement(BreakStatement node, State state) {
    return state.lookupLabel(node.target).configuration;
  }

  Configuration visitWhileStatement(WhileStatement node, State state) {
    var cont = new WhileConditionContinuation(node, state);

    return new ExpressionConfiguration(node.condition, state.environment, cont);
  }

  Configuration visitDoStatement(DoStatement node, State 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 state) {
    assert(state.returnContinuation != null);
    if (node.expression == null) {
      return new ContinuationConfiguration(
          state.returnContinuation, Value.nullInstance);
    }

    return new ExpressionConfiguration(
        node.expression, state.environment, state.returnContinuation);
  }

  Configuration visitVariableDeclaration(
      VariableDeclaration node, State state) {
    if (node.initializer != null) {
      var cont = new VariableInitializerContinuation(
          node, state.environment, state.statementConfiguration);
      return new ExpressionConfiguration(
          node.initializer, state.environment, cont);
    }
    state.environment.expand(node, Value.nullInstance);
    return state.statementConfiguration;
  }
}

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

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

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

  Class superclass;
  List<Field> instanceFields = <Field>[];
  List<Field> staticFields = <Field>[];
  // Implicit getters and setters for instance Fields.
  Map<Name, Getter> getters = <Name, Getter>{};
  Map<Name, Setter> setters = <Name, Setter>{};
  // The initializers of static fields are evaluated the first time the field
  // is accessed.
  List<Value> staticFieldValues = <Value>[];

  List<Procedure> methods = <Procedure>[];

  int get instanceSize => instanceFields.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);
    }

    _populateInstanceFields(currentClass);
    // TODO: Populate methods.
  }

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

  Setter lookupSetter(Name name) {
    Setter setter = setters[name];
    if (setter != null) return setter;
    if (superclass != null) return superclass.lookupSetter(name);
    return (Value receiver, Value value) => notImplemented(obj: name);
  }

  Value getProperty(ObjectValue object, Member member) {
    if (member is Field) {
      int index = instanceFields.indexOf(member);
      // TODO: throw NoSuchMethodError instead.
      if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}');
      return object.fields[index];
    }
    return notImplemented(obj: member);
  }

  Value setProperty(ObjectValue object, Member member, Value value) {
    if (member is Field) {
      int index = instanceFields.indexOf(member);
      // TODO: throw NoSuchMethodError instead.
      if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}');
      object.fields[index] = value;
      return Value.nullInstance;
    }
    return notImplemented(obj: member);
  }

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

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

      int currentFieldIndex = instanceFields.length - 1;

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

abstract class Value {
  Class get class_;
  List<Value> 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]) {
    throw notImplemented(obj: name);
  }
}

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

  ObjectValue(this.class_, this.fields);
}

abstract class LiteralValue extends Value {
  Class get class_ =>
      notImplemented(m: "Loading class for literal is not implemented.");
  List<Value> 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');
}
