// 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) {
      try {
        return constantEvaluator.evaluate(node);
      } on _AbortCurrentEvaluation catch (_) {
        return null;
      }
    }

    return constantEvaluator.runInsideContext(treeContext, () {
      try {
        return constantEvaluator.evaluate(node);
      } on _AbortCurrentEvaluation catch (_) {
        return null;
      }
    });
  }
}

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.
  Constant evaluate(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]
              : evaluate(parameter.initializer);
          env.addVariableValue(parameter, value);
        }
        for (final VariableDeclaration parameter in function.namedParameters) {
          final Constant value =
              namedArguments[parameter.name] ?? evaluate(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, evaluate(field.initializer));
          }
        }
        for (final Initializer init in constructor.initializers) {
          if (init is FieldInitializer) {
            instanceBuilder.setFieldValue(init.field, evaluate(init.value));
          } else if (init is LocalInitializer) {
            final VariableDeclaration variable = init.variable;
            env.addVariableValue(variable, evaluate(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 = evaluate(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 = evaluate(node.left);
    switch (node.operator) {
      case '||':
        if (left is BoolConstant) {
          if (left.value) return trueConstant;

          final Constant right = evaluate(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 = evaluate(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 : evaluate(node.right);
      default:
        errorReporter.invalidMethodInvocation(
            contextChain, node, left, '${node.operator}');
        throw const _AbortCurrentEvaluation();
    }
  }

  visitConditionalExpression(ConditionalExpression node) {
    final Constant constant = evaluate(node.condition);
    if (constant == trueConstant) {
      return evaluate(node.then);
    } else if (constant == falseConstant) {
      return evaluate(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 = evaluate(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, evaluate(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 evaluate(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 evaluate(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 = evaluate(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;
}
