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

/// This library implements a kernel2kernel constant evaluation transformation.
///
/// Even though it is expected that the frontend does not emit kernel AST which
/// contains compile-time errors, this transformation still performs some
/// valiation and throws a [ConstantEvaluationError] if there was a compile-time
/// errors.
///
/// Due to the lack information which is is only available in the front-end,
/// this validation is incomplete (e.g. whether an integer literal used the
/// hexadecimal syntax or not).
///
/// Furthermore due to the lowering of certain constructs in the front-end
/// (e.g. '??') we need to support a super-set of the normal constant expression
/// language.  Issue(http://dartbug.com/31799)
library kernel.transformations.constants;

import 'dart:io' as io;

import '../ast.dart';
import '../class_hierarchy.dart';
import '../core_types.dart';
import '../external_name.dart' show getExternalName;
import '../kernel.dart';
import '../type_algebra.dart';
import '../type_environment.dart';

Component transformComponent(Component component, ConstantsBackend backend,
    {bool keepFields: false,
    bool strongMode: false,
    bool enableAsserts: false,
    bool evaluateAnnotations: true,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    ErrorReporter errorReporter: const _SimpleErrorReporter()}) {
  coreTypes ??= new CoreTypes(component);
  hierarchy ??= new ClassHierarchy(component);

  final typeEnvironment =
      new TypeEnvironment(coreTypes, hierarchy, strongMode: strongMode);

  transformLibraries(component.libraries, backend, coreTypes, typeEnvironment,
      keepFields: keepFields,
      strongMode: strongMode,
      enableAsserts: enableAsserts,
      evaluateAnnotations: evaluateAnnotations,
      errorReporter: errorReporter);
  return component;
}

void transformLibraries(List<Library> libraries, ConstantsBackend backend,
    CoreTypes coreTypes, TypeEnvironment typeEnvironment,
    {bool keepFields: false,
    bool keepVariables: false,
    bool evaluateAnnotations: true,
    bool strongMode: false,
    bool enableAsserts: false,
    ErrorReporter errorReporter: const _SimpleErrorReporter()}) {
  final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
      backend,
      keepFields,
      keepVariables,
      evaluateAnnotations,
      coreTypes,
      typeEnvironment,
      strongMode,
      enableAsserts,
      errorReporter);
  for (final Library library in libraries) {
    constantsTransformer.convertLibrary(library);
  }
}

class ConstantsTransformer extends Transformer {
  final ConstantEvaluator constantEvaluator;
  final CoreTypes coreTypes;
  final TypeEnvironment typeEnvironment;

  /// Whether to preserve constant [Field]s.  All use-sites will be rewritten.
  final bool keepFields;
  final bool keepVariables;
  final bool evaluateAnnotations;

  ConstantsTransformer(
      ConstantsBackend backend,
      this.keepFields,
      this.keepVariables,
      this.evaluateAnnotations,
      this.coreTypes,
      this.typeEnvironment,
      bool strongMode,
      bool enableAsserts,
      ErrorReporter errorReporter)
      : constantEvaluator = new ConstantEvaluator(backend, typeEnvironment,
            coreTypes, strongMode, enableAsserts, errorReporter);

  // Transform the library/class members:

  void convertLibrary(Library library) {
    transformAnnotations(library.annotations, library);

    transformList(library.dependencies, this, library);
    transformList(library.parts, this, library);
    transformList(library.typedefs, this, library);
    transformList(library.classes, this, library);
    transformList(library.procedures, this, library);
    transformList(library.fields, this, library);

    if (!keepFields) {
      // The transformer API does not iterate over `Library.additionalExports`,
      // so we manually delete the references to shaken nodes.
      library.additionalExports.removeWhere((Reference reference) {
        return reference.canonicalName == null;
      });
    }
  }

  visitLibraryPart(LibraryPart node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
    });
    return node;
  }

  visitLibraryDependency(LibraryDependency node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
    });
    return node;
  }

  visitClass(Class node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformList(node.fields, this, node);
      transformList(node.typeParameters, this, node);
      transformList(node.constructors, this, node);
      transformList(node.procedures, this, node);
      transformList(node.redirectingFactoryConstructors, this, node);
    });
    return node;
  }

  visitProcedure(Procedure node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      node.function = node.function.accept(this)..parent = node;
    });
    return node;
  }

  visitConstructor(Constructor node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformList(node.initializers, this, node);
      node.function = node.function.accept(this)..parent = node;
    });
    return node;
  }

  visitTypedef(Typedef node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
    });
    return node;
  }

  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
    constantEvaluator.withNewEnvironment(() {
      transformAnnotations(node.annotations, node);
      transformList(node.typeParameters, this, node);
      transformList(node.positionalParameters, this, node);
      transformList(node.namedParameters, this, node);
    });
    return node;
  }

  visitTypeParameter(TypeParameter node) {
    transformAnnotations(node.annotations, node);
    return node;
  }

  void transformAnnotations(List<Expression> nodes, TreeNode parent) {
    if (evaluateAnnotations && nodes.length > 0) {
      transformExpressions(nodes, parent);
    }
  }

  void transformExpressions(List<Expression> nodes, TreeNode parent) {
    constantEvaluator.withNewEnvironment(() {
      for (int i = 0; i < nodes.length; ++i) {
        nodes[i] = tryEvaluateAndTransformWithContext(parent, nodes[i])
          ..parent = parent;
      }
    });
  }

  // Handle definition of constants:

  visitFunctionNode(FunctionNode node) {
    final positionalParameterCount = node.positionalParameters.length;
    for (int i = node.requiredParameterCount;
        i < positionalParameterCount;
        ++i) {
      final VariableDeclaration variable = node.positionalParameters[i];
      if (variable.initializer != null) {
        variable.initializer =
            tryEvaluateAndTransformWithContext(variable, variable.initializer)
              ..parent = node;
      }
    }
    for (final VariableDeclaration variable in node.namedParameters) {
      if (variable.initializer != null) {
        variable.initializer =
            tryEvaluateAndTransformWithContext(variable, variable.initializer)
              ..parent = node;
      }
    }
    if (node.body != null) {
      node.body = node.body.accept(this)..parent = node;
    }
    return node;
  }

  visitVariableDeclaration(VariableDeclaration node) {
    transformAnnotations(node.annotations, node);

    if (node.isConst) {
      final Constant constant = tryEvaluateWithContext(node, node.initializer);

      // If there was a constant evaluation error we will not continue and
      // simply keep the old [node].
      if (constant == null) {
        return node;
      }

      constantEvaluator.env.addVariableValue(node, constant);

      if (keepVariables) {
        // So the value of the variable is still available for debugging
        // purposes we convert the constant variable to be a final variable
        // initialized to the evaluated constant expression.
        node.initializer = new ConstantExpression(constant)..parent = node;
        node.isFinal = true;
        node.isConst = false;
      } else {
        // Since we convert all use-sites of constants, the constant
        // [VariableDeclaration] is unused and we'll therefore remove it.
        return null;
      }
    }
    if (node.initializer != null) {
      node.initializer = node.initializer.accept(this)..parent = node;
    }
    return node;
  }

  visitField(Field node) {
    return constantEvaluator.withNewEnvironment(() {
      if (node.isConst) {
        // Since we convert all use-sites of constants, the constant [Field]
        // cannot be referenced anymore.  We therefore get rid of it if
        // [keepFields] was not specified.
        if (!keepFields) {
          return null;
        }

        // Otherwise we keep the constant [Field] and convert it's initializer.
        transformAnnotations(node.annotations, node);
        if (node.initializer != null) {
          node.initializer =
              tryEvaluateAndTransformWithContext(node, node.initializer)
                ..parent = node;
        }
      } else {
        transformAnnotations(node.annotations, node);
        if (node.initializer != null) {
          node.initializer = node.initializer.accept(this)..parent = node;
        }
      }
      return node;
    });
  }

  // Handle use-sites of constants (and "inline" constant expressions):

  visitSymbolLiteral(SymbolLiteral node) {
    return new ConstantExpression(constantEvaluator.evaluate(node));
  }

  visitStaticGet(StaticGet node) {
    final Member target = node.target;
    if (target is Field && target.isConst) {
      final Constant constant =
          tryEvaluateWithContext(node, target.initializer);
      return constant != null ? new ConstantExpression(constant) : node;
    } else if (target is Procedure && target.kind == ProcedureKind.Method) {
      return tryEvaluateAndTransformWithContext(node, node);
    }
    return super.visitStaticGet(node);
  }

  visitSwitchCase(SwitchCase node) {
    transformExpressions(node.expressions, node);
    return super.visitSwitchCase(node);
  }

  visitVariableGet(VariableGet node) {
    if (node.variable.isConst) {
      return tryEvaluateAndTransformWithContext(node, node);
    }
    return super.visitVariableGet(node);
  }

  visitListLiteral(ListLiteral node) {
    if (node.isConst) {
      return tryEvaluateAndTransformWithContext(node, node);
    }
    return super.visitListLiteral(node);
  }

  visitMapLiteral(MapLiteral node) {
    if (node.isConst) {
      return tryEvaluateAndTransformWithContext(node, node);
    }
    return super.visitMapLiteral(node);
  }

  visitConstructorInvocation(ConstructorInvocation node) {
    if (node.isConst) {
      return tryEvaluateAndTransformWithContext(node, node);
    }
    return super.visitConstructorInvocation(node);
  }

  tryEvaluateAndTransformWithContext(TreeNode treeContext, Expression node) {
    final Constant constant = tryEvaluateWithContext(treeContext, node);
    return constant != null ? new ConstantExpression(constant) : node;
  }

  tryEvaluateWithContext(TreeNode treeContext, Expression node) {
    if (treeContext == node) {
      return constantEvaluator.evaluate(node);
    }

    return constantEvaluator.runInsideContext(treeContext, () {
      return constantEvaluator.evaluate(node);
    });
  }
}

class ConstantEvaluator extends RecursiveVisitor {
  final ConstantsBackend backend;
  final CoreTypes coreTypes;
  final TypeEnvironment typeEnvironment;
  final bool strongMode;
  final bool enableAsserts;
  final ErrorReporter errorReporter;

  final Map<Constant, Constant> canonicalizationCache;
  final Map<Node, Object> nodeCache;

  final NullConstant nullConstant = new NullConstant();
  final BoolConstant trueConstant = new BoolConstant(true);
  final BoolConstant falseConstant = new BoolConstant(false);

  final List<TreeNode> contextChain = [];

  InstanceBuilder instanceBuilder;
  EvaluationEnvironment env;

  ConstantEvaluator(this.backend, this.typeEnvironment, this.coreTypes,
      this.strongMode, this.enableAsserts,
      [this.errorReporter = const _SimpleErrorReporter()])
      : canonicalizationCache = <Constant, Constant>{},
        nodeCache = <Node, Constant>{};

  /// Evaluates [node] and possibly cache the evaluation result.
  /// Returns `null` if expression can't be evaluated.
  Constant evaluate(Expression node) {
    try {
      return _evaluateSubexpression(node);
    } on _AbortCurrentEvaluation catch (_) {
      return null;
    }
  }

  /// Evaluates [node] and possibly cache the evaluation result.
  /// @throws _AbortCurrentEvaluation if expression can't be evaluated.
  Constant _evaluateSubexpression(Expression node) {
    if (node == null) return nullConstant;
    if (env.isEmpty) {
      // We only try to evaluate the same [node] *once* within an empty
      // environment.
      if (nodeCache.containsKey(node)) {
        final Constant constant = nodeCache[node];
        if (constant == null) throw const _AbortCurrentEvaluation();
        return constant;
      }

      nodeCache[node] = null;
      return nodeCache[node] = node.accept(this);
    }
    return node.accept(this);
  }

  Constant runInsideContext(TreeNode node, Constant fun()) {
    try {
      pushContext(node);
      return fun();
    } finally {
      popContext(node);
    }
  }

  Constant runInsideContextIfNoContext(TreeNode node, Constant fun()) {
    if (contextChain.isEmpty) {
      return runInsideContext(node, fun);
    } else {
      return fun();
    }
  }

  pushContext(TreeNode contextNode) {
    contextChain.add(contextNode);
  }

  popContext(TreeNode contextNode) {
    assert(contextChain.last == contextNode);
    contextChain.length = contextChain.length - 1;
  }

  defaultTreeNode(Node node) {
    // Only a subset of the expression language is valid for constant
    // evaluation.
    throw 'Constant evaluation has no support for ${node.runtimeType} yet!';
  }

  visitNullLiteral(NullLiteral node) => nullConstant;

  visitBoolLiteral(BoolLiteral node) {
    return node.value ? trueConstant : falseConstant;
  }

  visitIntLiteral(IntLiteral node) {
    // The frontend will ensure the integer literals are in signed 64-bit range
    // in strong mode.
    return canonicalize(new IntConstant(node.value));
  }

  visitDoubleLiteral(DoubleLiteral node) {
    return canonicalize(new DoubleConstant(node.value));
  }

  visitStringLiteral(StringLiteral node) {
    return canonicalize(new StringConstant(node.value));
  }

  visitTypeLiteral(TypeLiteral node) {
    final DartType type = evaluateDartType(node.type);
    return canonicalize(new TypeLiteralConstant(type));
  }

  visitConstantExpression(ConstantExpression node) {
    // If there were already constants in the AST then we make sure we
    // re-canonicalize them.  After running the transformer we will therefore
    // have a fully-canonicalized constant DAG with roots coming from the
    // [ConstantExpression] nodes in the AST.
    return canonicalize(node.constant);
  }

  visitListLiteral(ListLiteral node) {
    if (!node.isConst) {
      errorReporter.nonConstLiteral(contextChain, node, 'List');
      throw const _AbortCurrentEvaluation();
    }
    final List<Constant> entries = new List<Constant>(node.expressions.length);
    for (int i = 0; i < node.expressions.length; ++i) {
      entries[i] = node.expressions[i].accept(this);
    }
    final DartType typeArgument = evaluateDartType(node.typeArgument);
    final ListConstant listConstant = new ListConstant(typeArgument, entries);
    return canonicalize(backend.lowerListConstant(listConstant));
  }

  visitMapLiteral(MapLiteral node) {
    if (!node.isConst) {
      errorReporter.nonConstLiteral(contextChain, node, 'Map');
      throw const _AbortCurrentEvaluation();
    }
    final Set<Constant> usedKeys = new Set<Constant>();
    final List<ConstantMapEntry> entries =
        new List<ConstantMapEntry>(node.entries.length);
    for (int i = 0; i < node.entries.length; ++i) {
      final key = node.entries[i].key.accept(this);
      final value = node.entries[i].value.accept(this);
      if (!usedKeys.add(key)) {
        // TODO(kustermann): We should change the context handling from just
        // capturing the `TreeNode`s to a `(TreeNode, String message)` tuple and
        // report where the first key with the same value was.
        errorReporter.duplicateKey(contextChain, node.entries[i], key);
        throw const _AbortCurrentEvaluation();
      }
      entries[i] = new ConstantMapEntry(key, value);
    }
    final DartType keyType = evaluateDartType(node.keyType);
    final DartType valueType = evaluateDartType(node.valueType);
    final MapConstant mapConstant =
        new MapConstant(keyType, valueType, entries);
    return canonicalize(backend.lowerMapConstant(mapConstant));
  }

  visitFunctionExpression(FunctionExpression node) {
    errorReporter.nonConstLiteral(contextChain, node, 'Function');
    throw const _AbortCurrentEvaluation();
  }

  visitConstructorInvocation(ConstructorInvocation node) {
    final Constructor constructor = node.target;
    final Class klass = constructor.enclosingClass;
    if (!constructor.isConst) {
      throw 'The front-end should ensure we do not encounter a '
          'constructor invocation of a non-const constructor.';
    }
    if (constructor.function.body != null &&
        constructor.function.body is! EmptyStatement) {
      throw 'Constructor "$node" has non-trivial body "${constructor.function.body.runtimeType}".';
    }
    if (klass.isAbstract) {
      throw 'Constructor "$node" belongs to abstract class "${klass}".';
    }

    final typeArguments = evaluateTypeArguments(node.arguments);
    final positionals = evaluatePositionalArguments(node.arguments);
    final named = evaluateNamedArguments(node.arguments);

    // Fill in any missing type arguments with "dynamic".
    for (int i = typeArguments.length; i < klass.typeParameters.length; i++) {
      typeArguments.add(const DynamicType());
    }

    // Start building a new instance.
    return withNewInstanceBuilder(klass, typeArguments, () {
      return runInsideContextIfNoContext(node, () {
        // "Run" the constructor (and any super constructor calls), which will
        // initialize the fields of the new instance.
        handleConstructorInvocation(
            constructor, typeArguments, positionals, named);
        return canonicalize(instanceBuilder.buildInstance());
      });
    });
  }

  handleConstructorInvocation(
      Constructor constructor,
      List<DartType> typeArguments,
      List<Constant> positionalArguments,
      Map<String, Constant> namedArguments) {
    return runInsideContext(constructor, () {
      return withNewEnvironment(() {
        final Class klass = constructor.enclosingClass;
        final FunctionNode function = constructor.function;

        // We simulate now the constructor invocation.

        // Step 1) Map type arguments and normal arguments from caller to callee.
        for (int i = 0; i < klass.typeParameters.length; i++) {
          env.addTypeParameterValue(klass.typeParameters[i], typeArguments[i]);
        }
        for (int i = 0; i < function.positionalParameters.length; i++) {
          final VariableDeclaration parameter =
              function.positionalParameters[i];
          final Constant value = (i < positionalArguments.length)
              ? positionalArguments[i]
              : _evaluateSubexpression(parameter.initializer);
          env.addVariableValue(parameter, value);
        }
        for (final VariableDeclaration parameter in function.namedParameters) {
          final Constant value = namedArguments[parameter.name] ??
              _evaluateSubexpression(parameter.initializer);
          env.addVariableValue(parameter, value);
        }

        // Step 2) Run all initializers (including super calls) with environment setup.
        for (final Field field in klass.fields) {
          if (!field.isStatic) {
            instanceBuilder.setFieldValue(
                field, _evaluateSubexpression(field.initializer));
          }
        }
        for (final Initializer init in constructor.initializers) {
          if (init is FieldInitializer) {
            instanceBuilder.setFieldValue(
                init.field, _evaluateSubexpression(init.value));
          } else if (init is LocalInitializer) {
            final VariableDeclaration variable = init.variable;
            env.addVariableValue(
                variable, _evaluateSubexpression(variable.initializer));
          } else if (init is SuperInitializer) {
            handleConstructorInvocation(
                init.target,
                evaluateSuperTypeArguments(
                    constructor.enclosingClass.supertype),
                evaluatePositionalArguments(init.arguments),
                evaluateNamedArguments(init.arguments));
          } else if (init is RedirectingInitializer) {
            // Since a redirecting constructor targets a constructor of the same
            // class, we pass the same [typeArguments].
            handleConstructorInvocation(
                init.target,
                typeArguments,
                evaluatePositionalArguments(init.arguments),
                evaluateNamedArguments(init.arguments));
          } else if (init is AssertInitializer) {
            if (enableAsserts) {
              final Constant condition = init.statement.condition.accept(this);

              if (condition is BoolConstant) {
                if (!condition.value) {
                  final Constant message = init.statement.message?.accept(this);
                  if (message == null) {
                    errorReporter.failedAssertion(
                        contextChain, init.statement.condition, null);
                    throw const _AbortCurrentEvaluation();
                  } else if (message is StringConstant) {
                    errorReporter.failedAssertion(
                        contextChain, init.statement.condition, message.value);
                    throw const _AbortCurrentEvaluation();
                  }
                  errorReporter.invalidDartType(
                      contextChain,
                      init.statement.message,
                      message,
                      typeEnvironment.stringType);
                  throw const _AbortCurrentEvaluation();
                }
              } else {
                errorReporter.invalidDartType(
                    contextChain,
                    init.statement.condition,
                    condition,
                    typeEnvironment.boolType);
                throw const _AbortCurrentEvaluation();
              }
            }
          } else {
            throw new Exception(
                'No support for handling initializer of type "${init.runtimeType}".');
          }
        }
      });
    });
  }

  visitMethodInvocation(MethodInvocation node) {
    // We have no support for generic method invocation atm.
    assert(node.arguments.named.isEmpty);

    final Constant receiver = _evaluateSubexpression(node.receiver);
    final List<Constant> arguments =
        evaluatePositionalArguments(node.arguments);

    // TODO(http://dartbug.com/31799): Ensure we only invoke ==/!= on
    // null/bool/int/double/String objects.

    // Handle == and != first (it's common between all types).
    if (arguments.length == 1 && node.name.name == '==') {
      final right = arguments[0];
      return receiver == right ? trueConstant : falseConstant;
    }
    if (arguments.length == 1 && node.name.name == '!=') {
      final right = arguments[0];
      return receiver != right ? trueConstant : falseConstant;
    }

    // This is a white-listed set of methods we need to support on constants.
    if (receiver is StringConstant) {
      if (arguments.length == 1) {
        switch (node.name.name) {
          case '+':
            final Constant other = arguments[0];
            if (other is StringConstant) {
              return canonicalize(
                  new StringConstant(receiver.value + other.value));
            }
            errorReporter.invalidBinaryOperandType(
                contextChain,
                node,
                receiver,
                '+',
                typeEnvironment.stringType,
                other.getType(typeEnvironment));
            throw const _AbortCurrentEvaluation();
        }
      }
    } else if (receiver is BoolConstant) {
      if (arguments.length == 1) {
        switch (node.name.name) {
          case '!':
            return !receiver.value ? trueConstant : falseConstant;
        }
      } else if (arguments.length == 2) {
        final right = arguments[0];
        if (right is BoolConstant) {
          switch (node.name.name) {
            case '&&':
              return (receiver.value && right.value)
                  ? trueConstant
                  : falseConstant;
            case '||':
              return (receiver.value || right.value)
                  ? trueConstant
                  : falseConstant;
          }
        }
        errorReporter.invalidBinaryOperandType(
            contextChain,
            node,
            receiver,
            '${node.name.name}',
            typeEnvironment.boolType,
            right.getType(typeEnvironment));
        throw const _AbortCurrentEvaluation();
      }
    } else if (receiver is IntConstant) {
      if (arguments.length == 0) {
        switch (node.name.name) {
          case 'unary-':
            return canonicalize(new IntConstant(-receiver.value));
          case '~':
            return canonicalize(new IntConstant(~receiver.value));
        }
      } else if (arguments.length == 1) {
        final Constant other = arguments[0];
        final op = node.name.name;
        if (other is IntConstant) {
          if ((op == '<<' || op == '>>') && other.value < 0) {
            errorReporter.negativeShift(contextChain,
                node.arguments.positional.first, receiver, op, other);
            throw const _AbortCurrentEvaluation();
          }
          switch (op) {
            case '|':
              return canonicalize(
                  new IntConstant(receiver.value | other.value));
            case '&':
              return canonicalize(
                  new IntConstant(receiver.value & other.value));
            case '^':
              return canonicalize(
                  new IntConstant(receiver.value ^ other.value));
            case '<<':
              return canonicalize(
                  new IntConstant(receiver.value << other.value));
            case '>>':
              return canonicalize(
                  new IntConstant(receiver.value >> other.value));
          }
        }

        if (other is IntConstant) {
          if (other.value == 0 && (op == '%' || op == '~/')) {
            errorReporter.zeroDivisor(
                contextChain, node.arguments.positional.first, receiver, op);
            throw const _AbortCurrentEvaluation();
          }

          return evaluateBinaryNumericOperation(
              node.name.name, receiver.value, other.value, node);
        } else if (other is DoubleConstant) {
          return evaluateBinaryNumericOperation(
              node.name.name, receiver.value, other.value, node);
        }

        errorReporter.invalidBinaryOperandType(
            contextChain,
            node,
            receiver,
            '${node.name.name}',
            typeEnvironment.numType,
            other.getType(typeEnvironment));
        throw const _AbortCurrentEvaluation();
      }
    } else if (receiver is DoubleConstant) {
      if (arguments.length == 0) {
        switch (node.name.name) {
          case 'unary-':
            return canonicalize(new DoubleConstant(-receiver.value));
        }
      } else if (arguments.length == 1) {
        final Constant other = arguments[0];

        if (other is IntConstant || other is DoubleConstant) {
          final num value = (other is IntConstant)
              ? other.value
              : (other as DoubleConstant).value;
          return evaluateBinaryNumericOperation(
              node.name.name, receiver.value, value, node);
        }
        errorReporter.invalidBinaryOperandType(
            contextChain,
            node,
            receiver,
            '${node.name.name}',
            typeEnvironment.numType,
            other.getType(typeEnvironment));
        throw const _AbortCurrentEvaluation();
      }
    }
    errorReporter.invalidMethodInvocation(
        contextChain, node, receiver, node.name.name);
    throw const _AbortCurrentEvaluation();
  }

  visitLogicalExpression(LogicalExpression node) {
    final Constant left = _evaluateSubexpression(node.left);
    switch (node.operator) {
      case '||':
        if (left is BoolConstant) {
          if (left.value) return trueConstant;

          final Constant right = _evaluateSubexpression(node.right);
          if (right is BoolConstant) {
            return right;
          }
          errorReporter.invalidBinaryOperandType(
              contextChain,
              node,
              left,
              '${node.operator}',
              typeEnvironment.boolType,
              right.getType(typeEnvironment));
          throw const _AbortCurrentEvaluation();
        }
        errorReporter.invalidMethodInvocation(
            contextChain, node, left, '${node.operator}');
        throw const _AbortCurrentEvaluation();
      case '&&':
        if (left is BoolConstant) {
          if (!left.value) return falseConstant;

          final Constant right = _evaluateSubexpression(node.right);
          if (right is BoolConstant) {
            return right;
          }
          errorReporter.invalidBinaryOperandType(
              contextChain,
              node,
              left,
              '${node.operator}',
              typeEnvironment.boolType,
              right.getType(typeEnvironment));
          throw const _AbortCurrentEvaluation();
        }
        errorReporter.invalidMethodInvocation(
            contextChain, node, left, '${node.operator}');
        throw const _AbortCurrentEvaluation();
      case '??':
        return (left is! NullConstant)
            ? left
            : _evaluateSubexpression(node.right);
      default:
        errorReporter.invalidMethodInvocation(
            contextChain, node, left, '${node.operator}');
        throw const _AbortCurrentEvaluation();
    }
  }

  visitConditionalExpression(ConditionalExpression node) {
    final Constant constant = _evaluateSubexpression(node.condition);
    if (constant == trueConstant) {
      return _evaluateSubexpression(node.then);
    } else if (constant == falseConstant) {
      return _evaluateSubexpression(node.otherwise);
    } else {
      errorReporter.invalidDartType(
          contextChain, node, constant, typeEnvironment.boolType);
      throw const _AbortCurrentEvaluation();
    }
  }

  visitPropertyGet(PropertyGet node) {
    if (node.receiver is ThisExpression) {
      // Access "this" during instance creation.
      for (final Field field in instanceBuilder.fields.keys) {
        if (field.name == node.name) {
          return instanceBuilder.fields[field];
        }
      }
      throw 'Could not evaluate field get ${node.name} on incomplete instance';
    }

    final Constant receiver = _evaluateSubexpression(node.receiver);
    if (receiver is StringConstant && node.name.name == 'length') {
      return canonicalize(new IntConstant(receiver.value.length));
    } else if (receiver is InstanceConstant) {
      for (final Reference fieldRef in receiver.fieldValues.keys) {
        if (fieldRef.asField.name == node.name) {
          return receiver.fieldValues[fieldRef];
        }
      }
    }
    throw 'Could not evaluate property get on $receiver.';
  }

  visitLet(Let node) {
    env.addVariableValue(
        node.variable, _evaluateSubexpression(node.variable.initializer));
    return node.body.accept(this);
  }

  visitVariableGet(VariableGet node) {
    // Not every variable which a [VariableGet] refers to must be marked as
    // constant.  For example function parameters as well as constructs
    // desugared to [Let] expressions are ok.
    //
    // TODO(kustermann): The heuristic of allowing all [VariableGet]s on [Let]
    // variables might allow more than it should.
    final VariableDeclaration variable = node.variable;
    if (variable.parent is Let || _isFormalParameter(variable)) {
      final Constant constant = env.lookupVariable(node.variable);
      if (constant == null) {
        errorReporter.nonConstantVariableGet(contextChain, node, variable.name);
        throw const _AbortCurrentEvaluation();
      }
      return constant;
    }
    if (variable.isConst) {
      return _evaluateSubexpression(variable.initializer);
    }
    throw new Exception('The front-end should ensure we do not encounter a '
        'variable get of a non-const variable.');
  }

  visitStaticGet(StaticGet node) {
    return withNewEnvironment(() {
      final Member target = node.target;
      if (target is Field && target.isConst) {
        return runInsideContext(target, () {
          return _evaluateSubexpression(target.initializer);
        });
      } else if (target is Procedure) {
        if (target.kind == ProcedureKind.Method) {
          return canonicalize(new TearOffConstant(target));
        }
        errorReporter.invalidStaticInvocation(contextChain, node, target);
        throw const _AbortCurrentEvaluation();
      } else {
        throw new Exception(
            'No support for ${target.runtimeType} in a static-get.');
      }
    });
  }

  visitStringConcatenation(StringConcatenation node) {
    final String value = node.expressions.map((Expression node) {
      final Constant constant = node.accept(this);

      if (constant is NullConstant) {
        return 'null';
      } else if (constant is BoolConstant) {
        return constant.value ? 'true' : 'false';
      } else if (constant is IntConstant) {
        return constant.value.toString();
      } else if (constant is DoubleConstant) {
        return constant.value.toString();
      } else if (constant is StringConstant) {
        return constant.value;
      } else {
        errorReporter.invalidStringInterpolationOperand(
            contextChain, node, constant);
        throw const _AbortCurrentEvaluation();
      }
    }).join('');
    return canonicalize(new StringConstant(value));
  }

  visitStaticInvocation(StaticInvocation node) {
    final Procedure target = node.target;
    if (target.kind == ProcedureKind.Factory) {
      final String nativeName = getExternalName(target);
      if (nativeName != null) {
        final Constant constant = backend.buildConstantForNative(
            nativeName,
            evaluateTypeArguments(node.arguments),
            evaluatePositionalArguments(node.arguments),
            evaluateNamedArguments(node.arguments));
        assert(constant != null);
        return canonicalize(constant);
      }
    } else if (target.name.name == 'identical') {
      // Ensure the "identical()" function comes from dart:core.
      final parent = target.parent;
      if (parent is Library && parent == coreTypes.coreLibrary) {
        final positionalArguments = evaluatePositionalArguments(node.arguments);
        final Constant left = positionalArguments[0];
        final Constant right = positionalArguments[1];
        // Since we canonicalize constants during the evaluation, we can use
        // identical here.
        assert(left == right);
        return identical(left, right) ? trueConstant : falseConstant;
      }
    }
    errorReporter.invalidStaticInvocation(contextChain, node, target);
    throw const _AbortCurrentEvaluation();
  }

  visitAsExpression(AsExpression node) {
    final Constant constant = node.operand.accept(this);
    ensureIsSubtype(constant, evaluateDartType(node.type), node);
    return constant;
  }

  visitNot(Not node) {
    final Constant constant = node.operand.accept(this);
    if (constant is BoolConstant) {
      return constant == trueConstant ? falseConstant : trueConstant;
    }
    errorReporter.invalidDartType(
        contextChain, node, constant, typeEnvironment.boolType);
    throw const _AbortCurrentEvaluation();
  }

  visitSymbolLiteral(SymbolLiteral node) {
    final value = canonicalize(new StringConstant(node.value));
    return canonicalize(backend.buildSymbolConstant(value));
  }

  visitInstantiation(Instantiation node) {
    final Constant constant = _evaluateSubexpression(node.expression);
    if (constant is TearOffConstant) {
      if (node.typeArguments.length ==
          constant.procedure.function.typeParameters.length) {
        return canonicalize(
            new PartialInstantiationConstant(constant, node.typeArguments));
      }
      throw new Exception(
          'The number of type arguments supplied in the partial instantiation '
          'does not match the number of type arguments of the $constant.');
    }
    throw new Exception(
        'Only tear-off constants can be partially instantiated.');
  }

  // Helper methods:

  void ensureIsSubtype(Constant constant, DartType type, TreeNode node) {
    DartType constantType;
    if (constant is NullConstant) {
      constantType = new InterfaceType(coreTypes.nullClass);
    } else if (constant is BoolConstant) {
      constantType = new InterfaceType(coreTypes.boolClass);
    } else if (constant is IntConstant) {
      constantType = new InterfaceType(coreTypes.intClass);
    } else if (constant is DoubleConstant) {
      constantType = new InterfaceType(coreTypes.doubleClass);
    } else if (constant is StringConstant) {
      constantType = new InterfaceType(coreTypes.stringClass);
    } else if (constant is MapConstant) {
      constantType = new InterfaceType(
          coreTypes.mapClass, <DartType>[constant.keyType, constant.valueType]);
    } else if (constant is ListConstant) {
      constantType = new InterfaceType(
          coreTypes.stringClass, <DartType>[constant.typeArgument]);
    } else if (constant is InstanceConstant) {
      constantType = new InterfaceType(constant.klass, constant.typeArguments);
    } else if (constant is TearOffConstant) {
      constantType = constant.procedure.function.functionType;
    } else if (constant is TypeLiteralConstant) {
      constantType = new InterfaceType(coreTypes.typeClass);
    } else {
      throw new Exception('No support for ${constant.runtimeType}.runtimeType');
    }

    if (!typeEnvironment.isSubtypeOf(constantType, type)) {
      errorReporter.invalidDartType(contextChain, node, constant, type);
      throw const _AbortCurrentEvaluation();
    }
  }

  List<DartType> evaluateTypeArguments(Arguments arguments) {
    return evaluateDartTypes(arguments.types);
  }

  List<DartType> evaluateSuperTypeArguments(Supertype type) {
    return evaluateDartTypes(type.typeArguments);
  }

  List<DartType> evaluateDartTypes(List<DartType> types) {
    if (env.isEmpty) return types;
    return types.map(evaluateDartType).toList();
  }

  DartType evaluateDartType(DartType type) {
    return env.subsituteType(type);
  }

  List<Constant> evaluatePositionalArguments(Arguments arguments) {
    return arguments.positional.map((Expression node) {
      return node.accept(this) as Constant;
    }).toList();
  }

  Map<String, Constant> evaluateNamedArguments(Arguments arguments) {
    if (arguments.named.isEmpty) return const <String, Constant>{};

    final Map<String, Constant> named = {};
    arguments.named.forEach((NamedExpression pair) {
      named[pair.name] = pair.value.accept(this);
    });
    return named;
  }

  canonicalize(Constant constant) {
    return canonicalizationCache.putIfAbsent(constant, () => constant);
  }

  withNewInstanceBuilder(Class klass, List<DartType> typeArguments, fn()) {
    InstanceBuilder old = instanceBuilder;
    try {
      instanceBuilder = new InstanceBuilder(klass, typeArguments);
      return fn();
    } finally {
      instanceBuilder = old;
    }
  }

  withNewEnvironment(fn()) {
    final EvaluationEnvironment oldEnv = env;
    try {
      env = new EvaluationEnvironment();
      return fn();
    } finally {
      env = oldEnv;
    }
  }

  evaluateBinaryNumericOperation(String op, num a, num b, TreeNode node) {
    num result;
    switch (op) {
      case '+':
        result = a + b;
        break;
      case '-':
        result = a - b;
        break;
      case '*':
        result = a * b;
        break;
      case '/':
        result = a / b;
        break;
      case '~/':
        result = a ~/ b;
        break;
      case '%':
        result = a % b;
        break;
    }

    if (result != null) {
      return canonicalize(result is int
          ? new IntConstant(_wrapAroundInteger(result))
          : new DoubleConstant(result as double));
    }

    switch (op) {
      case '<':
        return a < b ? trueConstant : falseConstant;
      case '<=':
        return a <= b ? trueConstant : falseConstant;
      case '>=':
        return a >= b ? trueConstant : falseConstant;
      case '>':
        return a > b ? trueConstant : falseConstant;
    }

    throw new Exception("Unexpected binary numeric operation '$op'.");
  }

  int _wrapAroundInteger(int value) {
    if (strongMode) {
      return value.toSigned(64);
    }
    return value;
  }
}

/// Holds the necessary information for a constant object, namely
///   * the [klass] being instantiated
///   * the [typeArguments] used for the instantiation
///   * the [fields] the instance will obtain (all fields from the
///     instantiated [klass] up to the [Object] klass).
class InstanceBuilder {
  /// The class of the new instance.
  final Class klass;

  /// The values of the type parameters of the new instance.
  final List<DartType> typeArguments;

  /// The field values of the new instance.
  final Map<Field, Constant> fields = <Field, Constant>{};

  InstanceBuilder(this.klass, this.typeArguments);

  void setFieldValue(Field field, Constant constant) {
    fields[field] = constant;
  }

  InstanceConstant buildInstance() {
    final Map<Reference, Constant> fieldValues = <Reference, Constant>{};
    fields.forEach((Field field, Constant value) {
      fieldValues[field.reference] = value;
    });
    return new InstanceConstant(klass.reference, typeArguments, fieldValues);
  }
}

/// Holds an environment of type parameters, parameters and variables.
class EvaluationEnvironment {
  /// The values of the type parameters in scope.
  final Map<TypeParameter, DartType> _typeVariables =
      <TypeParameter, DartType>{};

  /// The values of the parameters/variables in scope.
  final Map<VariableDeclaration, Constant> _variables =
      <VariableDeclaration, Constant>{};

  /// Whether the current environment is empty.
  bool get isEmpty => _typeVariables.isEmpty && _variables.isEmpty;

  void addTypeParameterValue(TypeParameter parameter, DartType value) {
    assert(!_typeVariables.containsKey(parameter));
    _typeVariables[parameter] = value;
  }

  void addVariableValue(VariableDeclaration variable, Constant value) {
    assert(!_variables.containsKey(variable));
    _variables[variable] = value;
  }

  DartType lookupParameterValue(TypeParameter parameter) {
    final DartType value = _typeVariables[parameter];
    assert(value != null);
    return value;
  }

  Constant lookupVariable(VariableDeclaration variable) {
    return _variables[variable];
  }

  DartType subsituteType(DartType type) {
    if (_typeVariables.isEmpty) return type;
    return substitute(type, _typeVariables);
  }
}

abstract class ConstantsBackend {
  Constant buildConstantForNative(
      String nativeName,
      List<DartType> typeArguments,
      List<Constant> positionalArguments,
      Map<String, Constant> namedArguments);
  Constant buildSymbolConstant(StringConstant value);

  Constant lowerListConstant(ListConstant constant);
  Constant lowerMapConstant(MapConstant constant);
}

// Used as control-flow to abort the current evaluation.
class _AbortCurrentEvaluation {
  const _AbortCurrentEvaluation();
}

abstract class ErrorReporter {
  const ErrorReporter();

  invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
      DartType expectedType);
  invalidBinaryOperandType(List<TreeNode> context, TreeNode node,
      Constant receiver, String op, DartType expectedType, DartType actualType);
  invalidMethodInvocation(
      List<TreeNode> context, TreeNode node, Constant receiver, String op);
  invalidStaticInvocation(
      List<TreeNode> context, TreeNode node, Procedure target);
  invalidStringInterpolationOperand(
      List<TreeNode> context, TreeNode node, Constant constant);
  zeroDivisor(
      List<TreeNode> context, TreeNode node, IntConstant receiver, String op);
  negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
      String op, IntConstant argument);
  nonConstLiteral(List<TreeNode> context, TreeNode node, String klass);
  duplicateKey(List<TreeNode> context, TreeNode node, Constant key);
  failedAssertion(List<TreeNode> context, TreeNode node, String message);
  nonConstantVariableGet(
      List<TreeNode> context, TreeNode node, String variableName);
}

abstract class ErrorReporterBase implements ErrorReporter {
  const ErrorReporterBase();

  report(List<TreeNode> context, String message, TreeNode node);

  getFileUri(TreeNode node) {
    while (node is! FileUriNode) {
      node = node.parent;
    }
    return (node as FileUriNode).fileUri;
  }

  getFileOffset(TreeNode node) {
    while (node.fileOffset == TreeNode.noOffset) {
      node = node.parent;
    }
    return node == null ? TreeNode.noOffset : node.fileOffset;
  }

  invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
      DartType expectedType) {
    report(
        context,
        'Expected expression to evaluate to "$expectedType" but got "$receiver.',
        node);
  }

  invalidBinaryOperandType(
      List<TreeNode> context,
      TreeNode node,
      Constant receiver,
      String op,
      DartType expectedType,
      DartType actualType) {
    report(
        context,
        'Calling "$op" on "$receiver" needs operand of type '
        '"$expectedType" (but got "$actualType")',
        node);
  }

  invalidMethodInvocation(
      List<TreeNode> context, TreeNode node, Constant receiver, String op) {
    report(context, 'Cannot call "$op" on "$receiver" in constant expression',
        node);
  }

  invalidStaticInvocation(
      List<TreeNode> context, TreeNode node, Procedure target) {
    report(
        context, 'Cannot invoke "$target" inside a constant expression', node);
  }

  invalidStringInterpolationOperand(
      List<TreeNode> context, TreeNode node, Constant constant) {
    report(
        context,
        'Only null/bool/int/double/String values are allowed as string '
        'interpolation expressions during constant evaluation (was: "$constant").',
        node);
  }

  zeroDivisor(
      List<TreeNode> context, TreeNode node, IntConstant receiver, String op) {
    report(
        context,
        "Binary operator '$op' on '${receiver.value}' requires non-zero "
        "divisor, but divisor was '0'.",
        node);
  }

  negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
      String op, IntConstant argument) {
    report(
        context,
        "Binary operator '$op' on '${receiver.value}' requires non-negative "
        "operand, but was '${argument.value}'.",
        node);
  }

  nonConstLiteral(List<TreeNode> context, TreeNode node, String klass) {
    report(
        context,
        'Cannot have a non-constant $klass literal within a const context.',
        node);
  }

  duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
    report(
        context,
        'Duplicate keys are not allowed in constant maps (found duplicate key "$key")',
        node);
  }

  failedAssertion(List<TreeNode> context, TreeNode node, String message) {
    report(
        context,
        'The assertion condition evaluated to "false" with message "$message"',
        node);
  }

  nonConstantVariableGet(
      List<TreeNode> context, TreeNode node, String variableName) {
    report(
        context,
        'The variable "$variableName" cannot be used inside a constant '
        'expression.',
        node);
  }
}

class _SimpleErrorReporter extends ErrorReporterBase {
  const _SimpleErrorReporter();

  report(List<TreeNode> context, String message, TreeNode node) {
    io.exitCode = 42;
    final Uri uri = getFileUri(node);
    final int fileOffset = getFileOffset(node);

    io.stderr.writeln('$uri:$fileOffset Constant evaluation error: $message');
  }
}

bool _isFormalParameter(VariableDeclaration variable) {
  final parent = variable.parent;
  if (parent is FunctionNode) {
    return parent.positionalParameters.contains(variable) ||
        parent.namedParameters.contains(variable);
  }
  return false;
}
