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

library dart2js.constants.expressions;

import 'dart:collection';

import '../common.dart';
import '../common_elements.dart';
import '../constants/constant_system.dart' as constant_system;
import '../elements/entities.dart';
import '../elements/operators.dart';
import '../elements/types.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../util/util.dart';
import 'constructors.dart';
import 'evaluation.dart';
import 'values.dart';

enum ConstantExpressionKind {
  AS,
  BINARY,
  BOOL,
  BOOL_FROM_ENVIRONMENT,
  CONCATENATE,
  CONDITIONAL,
  CONSTRUCTED,
  DOUBLE,
  ERRONEOUS,
  FUNCTION,
  FIELD,
  IDENTICAL,
  INT,
  INT_FROM_ENVIRONMENT,
  LIST,
  SET,
  MAP,
  NULL,
  STRING,
  STRING_FROM_ENVIRONMENT,
  STRING_LENGTH,
  SYMBOL,
  TYPE,
  UNARY,
  LOCAL_VARIABLE,
  POSITIONAL_REFERENCE,
  NAMED_REFERENCE,
  ASSERT,
  INSTANTIATION,
}

/// An expression that is a compile-time constant.
///
/// Whereas [ConstantValue] represent a compile-time value, a
/// [ConstantExpression] represents an expression for creating a constant.
///
/// There is no one-to-one mapping between [ConstantExpression] and
/// [ConstantValue], because different expressions can denote the same constant.
/// For instance, multiple `const` constructors may be used to create the same
/// object, and different `const` variables may hold the same value.
abstract class ConstantExpression {
  int _hashCode;

  ConstantExpressionKind get kind;

  // TODO(johnniwinther): Unify precedence handled between constants, front-end
  // and back-end.
  int get precedence => 16;

  accept(ConstantExpressionVisitor visitor, [context]);

  /// Substitute free variables using arguments.
  ConstantExpression apply(NormalizedArguments arguments) => this;

  /// Compute the [ConstantValue] for this expression using the [environment].
  ConstantValue evaluate(EvaluationEnvironment environment);

  /// Returns the type of this constant expression, if it is independent of the
  /// environment values.
  DartType getKnownType(CommonElements commonElements) => null;

  /// Returns a text string resembling the Dart code creating this constant.
  String toDartText() {
    ConstExpPrinter printer = new ConstExpPrinter();
    accept(printer);
    return printer.toString();
  }

  /// Returns a text string showing the structure of this constant.
  String toStructuredText() {
    StringBuffer sb = new StringBuffer();
    _createStructuredText(sb);
    return sb.toString();
  }

  /// Writes the structure of the constant into [sb].
  void _createStructuredText(StringBuffer sb);

  int _computeHashCode();

  @override
  int get hashCode => _hashCode ??= _computeHashCode();

  bool _equals(covariant ConstantExpression other);

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! ConstantExpression) return false;
    if (kind != other.kind) return false;
    if (hashCode != other.hashCode) return false;
    return _equals(other);
  }

  @override
  String toString() {
    assertDebugMode('Use ConstantExpression.toDartText() or '
        'ConstantExpression.toStructuredText() instead of '
        'ConstantExpression.toString()');
    return toDartText();
  }

  /// Returns `true` if this expression is implicitly constant, that is, that
  /// it doesn't declare its constness with the 'const' keyword.
  ///
  /// Implicit constants are simple literals, like bool, int and string
  /// literals, constant references and compositions of implicit constants.
  /// Explicit constants are constructor constants, and constant map and list
  /// literals.
  bool get isImplicit => true;

  /// Returns `true` if this expression is only potentially constant, that is,
  /// if it contains positional or named references, used to define constant
  /// constructors.
  // TODO(johnniwinther): Maybe make this final if we use it outside assertions.
  bool get isPotential => false;
}

/// A synthetic constant used to recover from errors.
class ErroneousConstantExpression extends ConstantExpression {
  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    // Do nothing. This is an error.
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    // TODO(johnniwinther): Use non-constant values for errors.
    return new NonConstantValue();
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Erroneous()');
  }

  @override
  int _computeHashCode() => 13;

  @override
  bool _equals(ErroneousConstantExpression other) => true;
}

/// Boolean literal constant.
class BoolConstantExpression extends ConstantExpression {
  final bool boolValue;

  BoolConstantExpression(this.boolValue);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitBool(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Bool(value=${boolValue})');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createBool(boolValue);
  }

  @override
  int _computeHashCode() => 13 * boolValue.hashCode;

  @override
  bool _equals(BoolConstantExpression other) {
    return boolValue == other.boolValue;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.boolType;
}

/// Integer literal constant.
class IntConstantExpression extends ConstantExpression {
  final BigInt intValue;

  IntConstantExpression(this.intValue);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.INT;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitInt(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Int(value=${intValue})');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createInt(intValue);
  }

  @override
  int _computeHashCode() => 17 * intValue.hashCode;

  @override
  bool _equals(IntConstantExpression other) {
    return intValue == other.intValue;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.intType;
}

/// Double literal constant.
class DoubleConstantExpression extends ConstantExpression {
  final double doubleValue;

  DoubleConstantExpression(this.doubleValue);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitDouble(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Double(value=${doubleValue})');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createDouble(doubleValue);
  }

  @override
  int _computeHashCode() => 19 * doubleValue.hashCode;

  @override
  bool _equals(DoubleConstantExpression other) {
    return doubleValue == other.doubleValue;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.doubleType;
}

/// String literal constant.
class StringConstantExpression extends ConstantExpression {
  final String stringValue;

  StringConstantExpression(this.stringValue);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.STRING;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitString(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('String(value=${stringValue})');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createString(stringValue);
  }

  @override
  int _computeHashCode() => 23 * stringValue.hashCode;

  @override
  bool _equals(StringConstantExpression other) {
    return stringValue == other.stringValue;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.stringType;
}

/// Null literal constant.
class NullConstantExpression extends ConstantExpression {
  NullConstantExpression();

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.NULL;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitNull(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Null()');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createNull();
  }

  @override
  int _computeHashCode() => 29;

  @override
  bool _equals(NullConstantExpression other) => true;

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.nullType;
}

/// Literal list constant.
class ListConstantExpression extends ConstantExpression {
  final InterfaceType type;
  final List<ConstantExpression> values;

  ListConstantExpression(this.type, this.values);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.LIST;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitList(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('List(type=$type,values=[');
    String delimiter = '';
    for (ConstantExpression value in values) {
      sb.write(delimiter);
      value._createStructuredText(sb);
      delimiter = ',';
    }
    sb.write('])');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createList(environment.commonElements, type,
        values.map((v) => v.evaluate(environment)).toList());
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new ListConstantExpression(
        type, values.map((v) => v.apply(arguments)).toList());
  }

  @override
  int _computeHashCode() {
    int hashCode = 13 * type.hashCode + 17 * values.length;
    for (ConstantExpression value in values) {
      hashCode ^= 19 * value.hashCode;
    }
    return hashCode;
  }

  @override
  bool _equals(ListConstantExpression other) {
    if (type != other.type) return false;
    if (values.length != other.values.length) return false;
    for (int i = 0; i < values.length; i++) {
      if (values[i] != other.values[i]) return false;
    }
    return true;
  }

  @override
  DartType getKnownType(CommonElements commonElements) => type;

  @override
  bool get isImplicit => false;

  @override
  bool get isPotential => values.any((e) => e.isPotential);
}

/// Literal set constant.
class SetConstantExpression extends ConstantExpression {
  final InterfaceType type;
  final List<ConstantExpression> values;

  SetConstantExpression(this.type, this.values);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.SET;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitSet(this, context);
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) =>
      new SetConstantExpression(
          type, values.map((v) => v.apply(arguments)).toList());

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    // TODO(fishythefish): Delete once the CFE provides these error messages.
    Set<ConstantValue> set = new LinkedHashSet<ConstantValue>();
    for (int i = 0; i < values.length; i++) {
      ConstantValue value = values[i].evaluate(environment);
      if (!value.isConstant) return new NonConstantValue();
      if (!set.add(value)) {
        environment.reportError(values[i], MessageKind.EQUAL_SET_ENTRY, {});
      }
    }

    return constant_system.createSet(
        environment.commonElements, type, set.toList());
  }

  @override
  DartType getKnownType(CommonElements commonElements) => type;

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Set(type=$type,values=[');
    String delimiter = '';
    for (ConstantExpression value in values) {
      sb.write(delimiter);
      value._createStructuredText(sb);
      delimiter = ',';
    }
    sb.write('])');
  }

  @override
  int _computeHashCode() => Hashing.listHash(values, Hashing.objectHash(type));

  @override
  bool _equals(SetConstantExpression other) {
    if (type != other.type) return false;
    if (values.length != other.values.length) return false;
    for (int i = 0; i < values.length; i++) {
      if (values[i] != other.values[i]) return false;
    }
    return true;
  }

  @override
  bool get isImplicit => false;

  @override
  bool get isPotential => values.any((v) => v.isPotential);
}

/// Literal map constant.
class MapConstantExpression extends ConstantExpression {
  final InterfaceType type;
  final List<ConstantExpression> keys;
  final List<ConstantExpression> values;

  MapConstantExpression(this.type, this.keys, this.values);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.MAP;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitMap(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Map(type=$type,entries=[');
    for (int index = 0; index < keys.length; index++) {
      if (index > 0) {
        sb.write(',');
      }
      keys[index]._createStructuredText(sb);
      sb.write('->');
      values[index]._createStructuredText(sb);
    }
    sb.write('])');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    // TODO(sigmund): delete once the CFE provides these error messages.
    return environment.evaluateMapBody(() {
      Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
      for (int i = 0; i < keys.length; i++) {
        ConstantValue key = keys[i].evaluate(environment);
        if (!key.isConstant) {
          return new NonConstantValue();
        }
        ConstantValue value = values[i].evaluate(environment);
        if (!value.isConstant) {
          return new NonConstantValue();
        }
        if (map.containsKey(key)) {
          environment.reportError(keys[i], MessageKind.EQUAL_MAP_ENTRY_KEY, {});
        }
        map[key] = value;
      }
      return constant_system.createMap(environment.commonElements, type,
          map.keys.toList(), map.values.toList());
    });
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new MapConstantExpression(
        type,
        keys.map((k) => k.apply(arguments)).toList(),
        values.map((v) => v.apply(arguments)).toList());
  }

  @override
  int _computeHashCode() {
    int hashCode = 13 * type.hashCode + 17 * values.length;
    for (ConstantExpression value in values) {
      hashCode ^= 19 * value.hashCode;
    }
    return hashCode;
  }

  @override
  bool _equals(MapConstantExpression other) {
    if (type != other.type) return false;
    if (values.length != other.values.length) return false;
    for (int i = 0; i < values.length; i++) {
      if (keys[i] != other.keys[i]) return false;
      if (values[i] != other.values[i]) return false;
    }
    return true;
  }

  @override
  DartType getKnownType(CommonElements commonElements) => type;

  @override
  bool get isImplicit => false;

  @override
  bool get isPotential {
    return keys.any((e) => e.isPotential) || values.any((e) => e.isPotential);
  }
}

/// Invocation of a const constructor.
class ConstructedConstantExpression extends ConstantExpression {
  final InterfaceType type;
  final ConstructorEntity target;
  final CallStructure callStructure;
  final List<ConstantExpression> arguments;

  ConstructedConstantExpression(
      this.type, this.target, this.callStructure, this.arguments) {
    assert(type.element == target.enclosingClass);
    assert(!arguments.contains(null));
  }

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitConstructed(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Constructed(type=$type,constructor=$target,'
        'callStructure=$callStructure,arguments=[');
    String delimiter = '';
    for (ConstantExpression value in arguments) {
      sb.write(delimiter);
      value._createStructuredText(sb);
      delimiter = ',';
    }
    sb.write('])');
  }

  InstanceData computeInstanceData(EvaluationEnvironment environment) {
    ConstantConstructor constantConstructor =
        environment.getConstructorConstant(target);
    assert(constantConstructor != null,
        failedAt(target, "No constant constructor computed for $target."));
    return constantConstructor.computeInstanceData(
        environment, arguments, callStructure);
  }

  InterfaceType computeInstanceType(EvaluationEnvironment environment) {
    return environment
        .getConstructorConstant(target)
        .computeInstanceType(environment, type);
  }

  @override
  ConstructedConstantExpression apply(NormalizedArguments arguments) {
    return new ConstructedConstantExpression(type, target, callStructure,
        this.arguments.map((a) => a.apply(arguments)).toList());
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    InterfaceType instanceType = computeInstanceType(environment);
    return environment.evaluateConstructor(target, instanceType, () {
      InstanceData instanceData = computeInstanceData(environment);
      if (instanceData == null) {
        return new NonConstantValue();
      }
      bool isValidAsConstant = true;
      Map<FieldEntity, ConstantValue> fieldValues =
          <FieldEntity, ConstantValue>{};
      instanceData.fieldMap
          .forEach((FieldEntity field, ConstantExpression constant) {
        ConstantValue value = constant.evaluate(environment);
        assert(
            value != null,
            failedAt(CURRENT_ELEMENT_SPANNABLE,
                "No value computed for ${constant.toStructuredText()}."));
        if (value.isConstant) {
          fieldValues[field] = value;
        } else {
          isValidAsConstant = false;
        }
      });
      for (AssertConstantExpression assertion in instanceData.assertions) {
        if (!assertion.evaluate(environment).isConstant) {
          isValidAsConstant = false;
        }
      }
      if (isValidAsConstant) {
        return new ConstructedConstantValue(instanceType, fieldValues);
      } else {
        return new NonConstantValue();
      }
    });
  }

  @override
  int _computeHashCode() {
    int hashCode =
        13 * type.hashCode + 17 * target.hashCode + 19 * callStructure.hashCode;
    for (ConstantExpression value in arguments) {
      hashCode ^= 23 * value.hashCode;
    }
    return hashCode;
  }

  @override
  bool _equals(ConstructedConstantExpression other) {
    if (type != other.type) return false;
    if (target != other.target) return false;
    if (callStructure != other.callStructure) return false;
    for (int i = 0; i < arguments.length; i++) {
      if (arguments[i] != other.arguments[i]) return false;
    }
    return true;
  }

  @override
  bool get isImplicit => false;

  @override
  bool get isPotential {
    return arguments.any((e) => e.isPotential);
  }
}

/// String literal with juxtaposition and/or interpolations.
class ConcatenateConstantExpression extends ConstantExpression {
  final List<ConstantExpression> expressions;

  ConcatenateConstantExpression(this.expressions);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitConcatenate(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Concatenate(expressions=[');
    String delimiter = '';
    for (ConstantExpression value in expressions) {
      sb.write(delimiter);
      value._createStructuredText(sb);
      delimiter = ',';
    }
    sb.write('])');
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new ConcatenateConstantExpression(
        expressions.map((a) => a.apply(arguments)).toList());
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    bool isValid = true;
    StringBuffer sb = new StringBuffer();
    for (ConstantExpression expression in expressions) {
      ConstantValue value = expression.evaluate(environment);
      if (!value.isConstant) {
        isValid = false;
        // Use `continue` instead of `return` here to report all errors in the
        // expression and not just the first.
        continue;
      }
      if (value.isPrimitive) {
        if (value is StringConstantValue) {
          sb.write(value.stringValue);
        } else if (value is IntConstantValue) {
          sb.write(value.intValue);
        } else if (value is DoubleConstantValue) {
          sb.write(value.doubleValue);
        } else if (value is BoolConstantValue) {
          sb.write(value.boolValue);
        } else if (value is NullConstantValue) {
          sb.write(null);
        }
      } else {
        environment.reportError(
            expression, MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE, {
          'constant': expression,
          'type': value.getType(environment.commonElements)
        });
        isValid = false;
        // Use `continue` instead of `return` here to report all errors in the
        // expression and not just the first.
        continue;
      }
    }
    if (isValid) {
      return constant_system.createString(sb.toString());
    }
    return new NonConstantValue();
  }

  @override
  int _computeHashCode() {
    int hashCode = 17 * expressions.length;
    for (ConstantExpression value in expressions) {
      hashCode ^= 19 * value.hashCode;
    }
    return hashCode;
  }

  @override
  bool _equals(ConcatenateConstantExpression other) {
    if (expressions.length != other.expressions.length) return false;
    for (int i = 0; i < expressions.length; i++) {
      if (expressions[i] != other.expressions[i]) return false;
    }
    return true;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.stringType;

  @override
  bool get isPotential {
    return expressions.any((e) => e.isPotential);
  }
}

/// Symbol literal.
class SymbolConstantExpression extends ConstantExpression {
  final String name;

  SymbolConstantExpression(this.name);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitSymbol(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Symbol(name=$name)');
  }

  @override
  int _computeHashCode() => 13 * name.hashCode;

  @override
  bool _equals(SymbolConstantExpression other) {
    return name == other.name;
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createSymbol(environment.commonElements, name);
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.symbolType;
}

/// Type literal.
class TypeConstantExpression extends ConstantExpression {
  /// Either [DynamicType] or a raw [GenericType].
  final DartType type;
  final String name;

  TypeConstantExpression(this.type, this.name) {
    assert(type.isInterfaceType || type.isTypedef || type.isDynamic,
        "Unexpected type constant type: $type");
  }

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitType(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Type(type=$type)');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return constant_system.createType(environment.commonElements, type);
  }

  @override
  int _computeHashCode() => 13 * type.hashCode;

  @override
  bool _equals(TypeConstantExpression other) {
    return type == other.type;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.typeType;
}

/// Cast expressions: these may be from either explicit or implicit `as`
/// checks.
class AsConstantExpression extends ConstantExpression {
  final ConstantExpression expression;
  final DartType type;

  AsConstantExpression(this.expression, this.type);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.AS;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitAs(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('As(value=');
    expression._createStructuredText(sb);
    sb.write(',type=$type)');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    // Running example for comments:
    //
    //     class A<T> {
    //       final T t;
    //       const A(dynamic t) : this.t = t; // implicitly `t as A.T`
    //     }
    //     class B<S> extends A<S> {
    //       const B(dynamic s) : super(s);
    //     }
    //     main() => const B<num>(0);
    //
    // We visit `t as A.T` while evaluating `const B<num>(0)`.

    // The expression value is `0`.
    ConstantValue expressionValue = expression.evaluate(environment);

    if (!environment.checkCasts) return expressionValue;

    // The expression type is `int`.
    DartType expressionType =
        expressionValue.getType(environment.commonElements);

    // The `as` type `A.T` in the context of `B<num>` is `num`.
    DartType typeInContext = environment.getTypeInContext(type);

    // Check that the expression type, `int`, is a subtype of the type in
    // context, `num`.
    if (!constant_system.isSubtype(
        environment.types, expressionType, typeInContext)) {
      // TODO(sigmund): consider reporting different messages and error
      // locations for implicit vs explicit casts.
      environment.reportError(expression, MessageKind.INVALID_CONSTANT_CAST,
          {'constant': expression, 'type': expressionType, 'castType': type});
      return new NonConstantValue();
    }
    return expressionValue;
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new AsConstantExpression(expression.apply(arguments), type);
  }

  @override
  int _computeHashCode() => 13 * type.hashCode + 17 * expression.hashCode;

  @override
  bool _equals(AsConstantExpression other) {
    return expression == other.expression && type == other.type;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      expression.getKnownType(commonElements);
}

/// Reference to a constant top-level or static field.
class FieldConstantExpression extends ConstantExpression {
  final FieldEntity element;

  FieldConstantExpression(this.element);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.FIELD;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitField(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Field(element=$element)');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return environment.evaluateField(element, () {
      ConstantExpression constant = environment.getFieldConstant(element);
      return constant.evaluate(environment);
    });
  }

  @override
  int _computeHashCode() => 13 * element.hashCode;

  @override
  bool _equals(FieldConstantExpression other) {
    return element == other.element;
  }
}

/// Reference to a constant local variable.
class LocalVariableConstantExpression extends ConstantExpression {
  final Local element;

  LocalVariableConstantExpression(this.element);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.LOCAL_VARIABLE;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitLocalVariable(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('LocalVariable(element=$element)');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantExpression constant = environment.getLocalConstant(element);
    return constant.evaluate(environment);
  }

  @override
  int _computeHashCode() => 13 * element.hashCode;

  @override
  bool _equals(LocalVariableConstantExpression other) {
    return element == other.element;
  }
}

/// Reference to a top-level or static function.
class FunctionConstantExpression extends ConstantExpression {
  final FunctionEntity element;
  final FunctionType type;

  FunctionConstantExpression(this.element, this.type);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitFunction(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Function(element=$element)');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return new FunctionConstantValue(element, type);
  }

  @override
  int _computeHashCode() => 13 * element.hashCode;

  @override
  bool _equals(FunctionConstantExpression other) {
    return element == other.element;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.functionType;
}

/// A constant binary expression like `a * b`.
class BinaryConstantExpression extends ConstantExpression {
  final ConstantExpression left;
  final BinaryOperator operator;
  final ConstantExpression right;

  BinaryConstantExpression(this.left, this.operator, this.right) {
    assert(PRECEDENCE_MAP[operator.kind] != null,
        "Missing precendence for binary operator: '$operator'.");
  }

  static bool potentialOperator(BinaryOperator operator) =>
      PRECEDENCE_MAP[operator.kind] != null;

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitBinary(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Binary(left=');
    left._createStructuredText(sb);
    sb.write(',op=$operator,right=');
    right._createStructuredText(sb);
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue leftValue = left.evaluate(environment);
    if (!leftValue.isConstant) return new NonConstantValue();
    ConstantValue rightValue;
    // Short-circuit && and || operators.
    switch (operator.kind) {
      case BinaryOperatorKind.LOGICAL_AND:
        if (leftValue.isBool && leftValue.isFalse) {
          rightValue = new FalseConstantValue();
        } else {
          rightValue = right.evaluate(environment);
        }
        break;

      case BinaryOperatorKind.LOGICAL_OR:
        if (leftValue.isBool && leftValue.isTrue) {
          rightValue = new TrueConstantValue();
        } else {
          rightValue = right.evaluate(environment);
        }
        break;
      default:
        rightValue = right.evaluate(environment);
    }

    if (!rightValue.isConstant) return new NonConstantValue();
    bool isValid = true;
    switch (operator.kind) {
      case BinaryOperatorKind.EQ:
      case BinaryOperatorKind.NOT_EQ:
        if (!leftValue.isPrimitive) {
          if (!rightValue.isNull) {
            environment.reportError(
                left, MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE, {
              'constant': left,
              'type': leftValue.getType(environment.commonElements),
              'operator': operator
            });
            isValid = false;
          }
        }
        if (!rightValue.isPrimitive) {
          if (!leftValue.isNull) {
            environment.reportError(
                right, MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE, {
              'constant': right,
              'type': rightValue.getType(environment.commonElements),
              'operator': operator
            });
            isValid = false;
          }
        }
        break;
      case BinaryOperatorKind.ADD:
        if (leftValue.isString) {
          if (!rightValue.isString) {
            environment.reportError(
                right, MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE, {
              'constant': right,
              'type': rightValue.getType(environment.commonElements)
            });
            isValid = false;
          }
        } else if (leftValue.isNum) {
          if (!rightValue.isNum) {
            environment.reportError(
                right, MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE, {
              'constant': right,
              'type': rightValue.getType(environment.commonElements)
            });
            isValid = false;
          }
        } else if (rightValue.isString) {
          if (!leftValue.isString) {
            environment.reportError(
                left, MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE, {
              'constant': left,
              'type': leftValue.getType(environment.commonElements)
            });
            isValid = false;
          }
        } else if (rightValue.isNum) {
          if (!leftValue.isNum) {
            environment.reportError(
                left, MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE, {
              'constant': left,
              'type': leftValue.getType(environment.commonElements)
            });
            isValid = false;
          }
        } else {
          environment
              .reportError(this, MessageKind.INVALID_CONSTANT_ADD_TYPES, {
            'leftConstant': left,
            'leftType': leftValue.getType(environment.commonElements),
            'rightConstant': right,
            'rightType': rightValue.getType(environment.commonElements)
          });
          isValid = false;
        }
        break;
      case BinaryOperatorKind.SUB:
      case BinaryOperatorKind.MUL:
      case BinaryOperatorKind.DIV:
      case BinaryOperatorKind.IDIV:
      case BinaryOperatorKind.MOD:
      case BinaryOperatorKind.GTEQ:
      case BinaryOperatorKind.GT:
      case BinaryOperatorKind.LTEQ:
      case BinaryOperatorKind.LT:
        if (!leftValue.isNum) {
          environment
              .reportError(left, MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE, {
            'constant': left,
            'type': leftValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (!rightValue.isNum) {
          environment.reportError(
              right, MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE, {
            'constant': right,
            'type': rightValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (isValid &&
            (operator.kind == BinaryOperatorKind.IDIV ||
                operator.kind == BinaryOperatorKind.MOD)) {
          if (rightValue.isZero) {
            environment.reportError(right, MessageKind.INVALID_CONSTANT_DIV,
                {'left': left, 'right': right, 'operator': operator});
            isValid = false;
          }
        }
        break;
      case BinaryOperatorKind.SHL:
      case BinaryOperatorKind.SHR:
      case BinaryOperatorKind.SHRU:
      case BinaryOperatorKind.AND:
      case BinaryOperatorKind.OR:
      case BinaryOperatorKind.XOR:
        if (!leftValue.isInt) {
          environment
              .reportError(left, MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE, {
            'constant': left,
            'type': leftValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (!rightValue.isInt) {
          environment.reportError(
              right, MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE, {
            'constant': right,
            'type': rightValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (isValid &&
            (operator.kind == BinaryOperatorKind.SHL ||
                operator.kind == BinaryOperatorKind.SHR ||
                operator.kind == BinaryOperatorKind.SHRU)) {
          IntConstantValue shift = rightValue;
          if (shift.intValue < BigInt.zero) {
            environment.reportError(right, MessageKind.INVALID_CONSTANT_SHIFT,
                {'left': left, 'right': right, 'operator': operator});
            isValid = false;
          }
        }
        break;
      case BinaryOperatorKind.LOGICAL_AND:
        if (!leftValue.isBool) {
          environment
              .reportError(left, MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE, {
            'constant': left,
            'type': leftValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (!rightValue.isBool) {
          environment.reportError(
              right, MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE, {
            'constant': right,
            'type': rightValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        break;
      case BinaryOperatorKind.LOGICAL_OR:
        if (!leftValue.isBool) {
          environment
              .reportError(left, MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE, {
            'constant': left,
            'type': leftValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (!rightValue.isBool) {
          environment
              .reportError(right, MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE, {
            'constant': right,
            'type': rightValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        break;
      case BinaryOperatorKind.INDEX:
        environment.reportError(this, MessageKind.INVALID_CONSTANT_INDEX, {});
        isValid = false;
        break;
      case BinaryOperatorKind.IF_NULL:
        // Valid since [leftValue] and [rightValue] are constants.
        break;
    }
    if (isValid) {
      switch (operator.kind) {
        case BinaryOperatorKind.NOT_EQ:
          BoolConstantValue equals =
              constant_system.equal.fold(leftValue, rightValue);
          return equals.negate();
        default:
          ConstantValue value = constant_system
              .lookupBinary(operator)
              .fold(leftValue, rightValue);
          if (value != null) {
            return value;
          }
          environment
              .reportError(this, MessageKind.NOT_A_COMPILE_TIME_CONSTANT, {});
      }
    }
    return new NonConstantValue();
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new BinaryConstantExpression(
        left.apply(arguments), operator, right.apply(arguments));
  }

  @override
  // ignore: MISSING_RETURN
  InterfaceType getKnownType(CommonElements commonElements) {
    DartType knownLeftType = left.getKnownType(commonElements);
    DartType knownRightType = right.getKnownType(commonElements);
    switch (operator.kind) {
      case BinaryOperatorKind.EQ:
      case BinaryOperatorKind.NOT_EQ:
      case BinaryOperatorKind.LOGICAL_AND:
      case BinaryOperatorKind.LOGICAL_OR:
      case BinaryOperatorKind.GT:
      case BinaryOperatorKind.LT:
      case BinaryOperatorKind.GTEQ:
      case BinaryOperatorKind.LTEQ:
        return commonElements.boolType;
      case BinaryOperatorKind.ADD:
        if (knownLeftType == commonElements.stringType) {
          assert(knownRightType == commonElements.stringType);
          return commonElements.stringType;
        } else if (knownLeftType == commonElements.intType &&
            knownRightType == commonElements.intType) {
          return commonElements.intType;
        }
        assert(knownLeftType == commonElements.doubleType ||
            knownRightType == commonElements.doubleType);
        return commonElements.doubleType;
      case BinaryOperatorKind.SUB:
      case BinaryOperatorKind.MUL:
      case BinaryOperatorKind.MOD:
        if (knownLeftType == commonElements.intType &&
            knownRightType == commonElements.intType) {
          return commonElements.intType;
        }
        assert(knownLeftType == commonElements.doubleType ||
            knownRightType == commonElements.doubleType);
        return commonElements.doubleType;
      case BinaryOperatorKind.DIV:
        return commonElements.doubleType;
      case BinaryOperatorKind.IDIV:
        return commonElements.intType;
      case BinaryOperatorKind.AND:
      case BinaryOperatorKind.OR:
      case BinaryOperatorKind.XOR:
      case BinaryOperatorKind.SHL:
      case BinaryOperatorKind.SHR:
      case BinaryOperatorKind.SHRU:
        return commonElements.intType;
      case BinaryOperatorKind.IF_NULL:
      case BinaryOperatorKind.INDEX:
        throw new UnsupportedError(
            'Unexpected constant binary operator: $operator');
    }
  }

  @override
  int get precedence => PRECEDENCE_MAP[operator.kind];

  @override
  int _computeHashCode() {
    return 13 * operator.hashCode + 17 * left.hashCode + 19 * right.hashCode;
  }

  @override
  bool _equals(BinaryConstantExpression other) {
    return operator == other.operator &&
        left == other.left &&
        right == other.right;
  }

  @override
  bool get isPotential {
    return left.isPotential || right.isPotential;
  }

  static const Map<BinaryOperatorKind, int> PRECEDENCE_MAP = const {
    BinaryOperatorKind.EQ: 6,
    BinaryOperatorKind.NOT_EQ: 6,
    BinaryOperatorKind.LOGICAL_AND: 5,
    BinaryOperatorKind.LOGICAL_OR: 4,
    BinaryOperatorKind.XOR: 9,
    BinaryOperatorKind.AND: 10,
    BinaryOperatorKind.OR: 8,
    BinaryOperatorKind.SHL: 11,
    BinaryOperatorKind.SHR: 11,
    BinaryOperatorKind.SHRU: 11,
    BinaryOperatorKind.ADD: 12,
    BinaryOperatorKind.SUB: 12,
    BinaryOperatorKind.MUL: 13,
    BinaryOperatorKind.DIV: 13,
    BinaryOperatorKind.IDIV: 13,
    BinaryOperatorKind.GT: 7,
    BinaryOperatorKind.LT: 7,
    BinaryOperatorKind.GTEQ: 7,
    BinaryOperatorKind.LTEQ: 7,
    BinaryOperatorKind.MOD: 13,
    BinaryOperatorKind.IF_NULL: 3,
    BinaryOperatorKind.INDEX: 3,
  };
}

/// A constant identical invocation like `identical(a, b)`.
class IdenticalConstantExpression extends ConstantExpression {
  final ConstantExpression left;
  final ConstantExpression right;

  IdenticalConstantExpression(this.left, this.right);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitIdentical(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Identical(left=');
    left._createStructuredText(sb);
    sb.write(',right=');
    right._createStructuredText(sb);
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue leftValue = left.evaluate(environment);
    ConstantValue rightValue = right.evaluate(environment);
    if (leftValue.isConstant && rightValue.isConstant) {
      return constant_system.identity.fold(leftValue, rightValue);
    }
    return new NonConstantValue();
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new IdenticalConstantExpression(
        left.apply(arguments), right.apply(arguments));
  }

  @override
  int get precedence => 15;

  @override
  int _computeHashCode() {
    return 17 * left.hashCode + 19 * right.hashCode;
  }

  @override
  bool _equals(IdenticalConstantExpression other) {
    return left == other.left && right == other.right;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.boolType;

  @override
  bool get isPotential {
    return left.isPotential || right.isPotential;
  }
}

/// A unary constant expression like `-a`.
class UnaryConstantExpression extends ConstantExpression {
  final UnaryOperator operator;
  final ConstantExpression expression;

  UnaryConstantExpression(this.operator, this.expression) {
    assert(PRECEDENCE_MAP[operator.kind] != null);
  }

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitUnary(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Unary(op=$operator,expression=');
    expression._createStructuredText(sb);
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue expressionValue = expression.evaluate(environment);
    bool isValid = true;
    switch (operator.kind) {
      case UnaryOperatorKind.NOT:
        if (!expressionValue.isBool) {
          environment
              .reportError(expression, MessageKind.INVALID_CONSTANT_NOT_TYPE, {
            'constant': expression,
            'type': expressionValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        break;
      case UnaryOperatorKind.NEGATE:
        if (!expressionValue.isNum) {
          environment.reportError(
              expression, MessageKind.INVALID_CONSTANT_NEGATE_TYPE, {
            'constant': expression,
            'type': expressionValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        break;
      case UnaryOperatorKind.COMPLEMENT:
        if (!expressionValue.isInt) {
          environment.reportError(
              expression, MessageKind.INVALID_CONSTANT_COMPLEMENT_TYPE, {
            'constant': expression,
            'type': expressionValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        break;
    }
    if (isValid) {
      ConstantValue value =
          constant_system.lookupUnary(operator).fold(expressionValue);
      if (value != null) {
        return value;
      }
    }
    return new NonConstantValue();
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new UnaryConstantExpression(operator, expression.apply(arguments));
  }

  @override
  int get precedence => PRECEDENCE_MAP[operator.kind];

  @override
  int _computeHashCode() {
    return 13 * operator.hashCode + 17 * expression.hashCode;
  }

  @override
  bool _equals(UnaryConstantExpression other) {
    return operator == other.operator && expression == other.expression;
  }

  @override
  DartType getKnownType(CommonElements commonElements) {
    return expression.getKnownType(commonElements);
  }

  @override
  bool get isPotential {
    return expression.isPotential;
  }

  static const Map<UnaryOperatorKind, int> PRECEDENCE_MAP = const {
    UnaryOperatorKind.NOT: 14,
    UnaryOperatorKind.COMPLEMENT: 14,
    UnaryOperatorKind.NEGATE: 14,
  };
}

/// A string length constant expression like `a.length`.
class StringLengthConstantExpression extends ConstantExpression {
  final ConstantExpression expression;

  StringLengthConstantExpression(this.expression);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitStringLength(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('StringLength(expression=');
    expression._createStructuredText(sb);
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue value = expression.evaluate(environment);
    if (!value.isString) {
      environment.reportError(
          expression, MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE, {
        'constant': expression,
        'type': value.getType(environment.commonElements)
      });
      return new NonConstantValue();
    } else {
      StringConstantValue stringValue = value;
      return constant_system
          .createInt(new BigInt.from(stringValue.stringValue.length));
    }
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new StringLengthConstantExpression(expression.apply(arguments));
  }

  @override
  int get precedence => 15;

  @override
  int _computeHashCode() {
    return 23 * expression.hashCode;
  }

  @override
  bool _equals(StringLengthConstantExpression other) {
    return expression == other.expression;
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.intType;

  @override
  bool get isPotential {
    return expression.isPotential;
  }
}

/// A constant conditional expression like `a ? b : c`.
class ConditionalConstantExpression extends ConstantExpression {
  final ConstantExpression condition;
  final ConstantExpression trueExp;
  final ConstantExpression falseExp;

  ConditionalConstantExpression(this.condition, this.trueExp, this.falseExp);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitConditional(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Conditional(condition=');
    condition._createStructuredText(sb);
    sb.write(',true=');
    trueExp._createStructuredText(sb);
    sb.write(',false=');
    falseExp._createStructuredText(sb);
    sb.write(')');
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new ConditionalConstantExpression(condition.apply(arguments),
        trueExp.apply(arguments), falseExp.apply(arguments));
  }

  @override
  int get precedence => 3;

  @override
  int _computeHashCode() {
    return 13 * condition.hashCode +
        17 * trueExp.hashCode +
        19 * falseExp.hashCode;
  }

  @override
  bool _equals(ConditionalConstantExpression other) {
    return condition == other.condition &&
        trueExp == other.trueExp &&
        falseExp == other.falseExp;
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue conditionValue = condition.evaluate(environment);
    ConstantValue trueValue = trueExp.evaluate(environment);
    ConstantValue falseValue = falseExp.evaluate(environment);
    bool isValid = true;
    if (!conditionValue.isBool) {
      environment.reportError(
          condition, MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE, {
        'constant': condition,
        'type': conditionValue.getType(environment.commonElements)
      });
      isValid = false;
    }
    if (isValid) {
      if (conditionValue.isTrue) {
        return trueValue;
      } else if (conditionValue.isFalse) {
        return falseValue;
      }
    }
    return new NonConstantValue();
  }

  @override
  DartType getKnownType(CommonElements commonElements) {
    DartType trueType = trueExp.getKnownType(commonElements);
    DartType falseType = falseExp.getKnownType(commonElements);
    if (trueType == falseType) {
      return trueType;
    }
    return null;
  }

  @override
  bool get isPotential {
    return condition.isPotential || trueExp.isPotential || falseExp.isPotential;
  }
}

/// A reference to a position parameter.
class PositionalArgumentReference extends ConstantExpression {
  final int index;

  PositionalArgumentReference(this.index);

  @override
  ConstantExpressionKind get kind {
    return ConstantExpressionKind.POSITIONAL_REFERENCE;
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitPositional(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Positional(index=$index)');
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return arguments.getPositionalArgument(index);
  }

  @override
  int _computeHashCode() => 13 * index.hashCode;

  @override
  bool _equals(PositionalArgumentReference other) => index == other.index;

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return new NonConstantValue();
  }

  @override
  bool get isPotential => true;
}

/// A reference to a named parameter.
class NamedArgumentReference extends ConstantExpression {
  final String name;

  NamedArgumentReference(this.name);

  @override
  ConstantExpressionKind get kind {
    return ConstantExpressionKind.NAMED_REFERENCE;
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitNamed(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Named(name=$name)');
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return arguments.getNamedArgument(name);
  }

  @override
  int _computeHashCode() => 13 * name.hashCode;

  @override
  bool _equals(NamedArgumentReference other) => name == other.name;

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    return new NonConstantValue();
  }

  @override
  bool get isPotential => true;
}

abstract class FromEnvironmentConstantExpression extends ConstantExpression {
  final ConstantExpression name;
  final ConstantExpression defaultValue;

  FromEnvironmentConstantExpression(this.name, this.defaultValue);

  bool _checkNameFromEnvironment(EvaluationEnvironment environment,
      ConstantExpression name, ConstantValue nameValue) {
    if (!nameValue.isString) {
      environment.reportError(
          name, MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE, {
        'constant': name,
        'type': nameValue.getType(environment.commonElements)
      });
      return false;
    }
    return true;
  }

  @override
  int _computeHashCode() {
    return 13 * name.hashCode + 17 * defaultValue.hashCode;
  }

  @override
  bool _equals(FromEnvironmentConstantExpression other) {
    return name == other.name && defaultValue == other.defaultValue;
  }

  @override
  bool get isImplicit {
    return false;
  }

  @override
  bool get isPotential {
    return name.isPotential ||
        (defaultValue != null && defaultValue.isPotential);
  }
}

/// A `const bool.fromEnvironment` constant.
class BoolFromEnvironmentConstantExpression
    extends FromEnvironmentConstantExpression {
  BoolFromEnvironmentConstantExpression(
      ConstantExpression name, ConstantExpression defaultValue)
      : super(name, defaultValue);

  @override
  ConstantExpressionKind get kind {
    return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitBoolFromEnvironment(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('bool.fromEnvironment(name=');
    name._createStructuredText(sb);
    sb.write(',defaultValue=');
    if (defaultValue != null) {
      defaultValue._createStructuredText(sb);
    } else {
      sb.write('null');
    }
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue nameConstantValue = name.evaluate(environment);
    ConstantValue defaultConstantValue;
    if (defaultValue != null) {
      defaultConstantValue = defaultValue.evaluate(environment);
    } else {
      defaultConstantValue = constant_system.createBool(false);
    }
    if (!nameConstantValue.isConstant || !defaultConstantValue.isConstant) {
      return new NonConstantValue();
    }
    bool isValid =
        _checkNameFromEnvironment(environment, name, nameConstantValue);
    if (defaultValue != null) {
      if (!defaultConstantValue.isBool && !defaultConstantValue.isNull) {
        environment.reportError(defaultValue,
            MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE, {
          'constant': defaultValue,
          'type': defaultConstantValue.getType(environment.commonElements)
        });
        isValid = false;
      }
    }
    if (isValid) {
      StringConstantValue nameStringConstantValue = nameConstantValue;
      String text =
          environment.readFromEnvironment(nameStringConstantValue.stringValue);
      if (text == 'true') {
        return constant_system.createBool(true);
      } else if (text == 'false') {
        return constant_system.createBool(false);
      } else {
        return defaultConstantValue;
      }
    }
    return new NonConstantValue();
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new BoolFromEnvironmentConstantExpression(name.apply(arguments),
        defaultValue != null ? defaultValue.apply(arguments) : null);
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.boolType;
}

/// A `const int.fromEnvironment` constant.
class IntFromEnvironmentConstantExpression
    extends FromEnvironmentConstantExpression {
  IntFromEnvironmentConstantExpression(
      ConstantExpression name, ConstantExpression defaultValue)
      : super(name, defaultValue);

  @override
  ConstantExpressionKind get kind {
    return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitIntFromEnvironment(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('int.fromEnvironment(name=');
    name._createStructuredText(sb);
    sb.write(',defaultValue=');
    if (defaultValue != null) {
      defaultValue._createStructuredText(sb);
    } else {
      sb.write('null');
    }
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue nameConstantValue = name.evaluate(environment);
    ConstantValue defaultConstantValue;
    if (defaultValue != null) {
      defaultConstantValue = defaultValue.evaluate(environment);
    } else {
      defaultConstantValue = constant_system.createNull();
    }
    if (!nameConstantValue.isConstant || !defaultConstantValue.isConstant) {
      return new NonConstantValue();
    }
    bool isValid =
        _checkNameFromEnvironment(environment, name, nameConstantValue);
    if (defaultValue != null) {
      if (!defaultConstantValue.isInt && !defaultConstantValue.isNull) {
        environment.reportError(defaultValue,
            MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE, {
          'constant': defaultValue,
          'type': defaultConstantValue.getType(environment.commonElements)
        });
        isValid = false;
      }
    }
    if (isValid) {
      StringConstantValue nameStringConstantValue = nameConstantValue;
      String text =
          environment.readFromEnvironment(nameStringConstantValue.stringValue);
      BigInt value;
      if (text != null) {
        value = BigInt.tryParse(text);
      }
      if (value == null) {
        return defaultConstantValue;
      } else {
        return constant_system.createInt(value);
      }
    }
    return new NonConstantValue();
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new IntFromEnvironmentConstantExpression(name.apply(arguments),
        defaultValue != null ? defaultValue.apply(arguments) : null);
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.intType;
}

/// A `const String.fromEnvironment` constant.
class StringFromEnvironmentConstantExpression
    extends FromEnvironmentConstantExpression {
  StringFromEnvironmentConstantExpression(
      ConstantExpression name, ConstantExpression defaultValue)
      : super(name, defaultValue);

  @override
  ConstantExpressionKind get kind {
    return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitStringFromEnvironment(this, context);
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('String.fromEnvironment(name=');
    name._createStructuredText(sb);
    sb.write(',defaultValue=');
    if (defaultValue != null) {
      defaultValue._createStructuredText(sb);
    } else {
      sb.write('null');
    }
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue nameConstantValue = name.evaluate(environment);
    ConstantValue defaultConstantValue;
    if (defaultValue != null) {
      defaultConstantValue = defaultValue.evaluate(environment);
    } else {
      defaultConstantValue = constant_system.createNull();
    }
    if (!nameConstantValue.isConstant || !defaultConstantValue.isConstant) {
      return new NonConstantValue();
    }
    bool isValid =
        _checkNameFromEnvironment(environment, name, nameConstantValue);
    if (defaultValue != null) {
      if (!defaultConstantValue.isString && !defaultConstantValue.isNull) {
        environment.reportError(defaultValue,
            MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE, {
          'constant': defaultValue,
          'type': defaultConstantValue.getType(environment.commonElements)
        });
        isValid = false;
      }
    }
    if (isValid) {
      StringConstantValue nameStringConstantValue = nameConstantValue;
      String text =
          environment.readFromEnvironment(nameStringConstantValue.stringValue);
      if (text == null) {
        return defaultConstantValue;
      } else {
        return constant_system.createString(text);
      }
    }
    return new NonConstantValue();
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new StringFromEnvironmentConstantExpression(name.apply(arguments),
        defaultValue != null ? defaultValue.apply(arguments) : null);
  }

  @override
  InterfaceType getKnownType(CommonElements commonElements) =>
      commonElements.stringType;
}

class AssertConstantExpression extends ConstantExpression {
  final ConstantExpression condition;
  final ConstantExpression message;

  AssertConstantExpression(this.condition, this.message);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.ASSERT;

  @override
  bool _equals(AssertConstantExpression other) {
    return condition == other.condition && message == other.message;
  }

  @override
  int _computeHashCode() {
    return 13 * condition.hashCode + 17 * message.hashCode;
  }

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('assert(');
    condition._createStructuredText(sb);
    sb.write(',message=');
    if (message != null) {
      message._createStructuredText(sb);
    } else {
      sb.write('null');
    }
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    ConstantValue conditionValue = condition.evaluate(environment);
    bool validAssert;
    if (environment.enableAssertions) {
      // Boolean conversion:
      validAssert =
          conditionValue is BoolConstantValue && conditionValue.boolValue;
    } else {
      validAssert = true;
    }
    if (!validAssert) {
      if (message != null) {
        ConstantValue value = message.evaluate(environment);
        if (value is StringConstantValue) {
          String text = '${value.stringValue}';
          environment.reportError(this,
              MessageKind.INVALID_ASSERT_VALUE_MESSAGE, {'message': text});
        } else {
          environment.reportError(this, MessageKind.INVALID_ASSERT_VALUE,
              {'assertion': condition.toDartText()});
          // TODO(johnniwinther): Report invalid constant message?
        }
      } else {
        environment.reportError(this, MessageKind.INVALID_ASSERT_VALUE,
            {'assertion': condition.toDartText()});
      }
      return new NonConstantValue();
    }

    // Return a valid constant value to signal that assertion didn't fail.
    return new NullConstantValue();
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitAssert(this, context);
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new AssertConstantExpression(
        condition.apply(arguments), message?.apply(arguments));
  }
}

class InstantiationConstantExpression extends ConstantExpression {
  final List<DartType> typeArguments;
  final ConstantExpression expression;

  InstantiationConstantExpression(this.typeArguments, this.expression);

  @override
  ConstantExpressionKind get kind => ConstantExpressionKind.INSTANTIATION;

  @override
  void _createStructuredText(StringBuffer sb) {
    sb.write('Instantiation(typeArguments=$typeArguments,expression=');
    expression._createStructuredText(sb);
    sb.write(')');
  }

  @override
  ConstantValue evaluate(EvaluationEnvironment environment) {
    List<DartType> typeArgumentsInContext =
        typeArguments.map(environment.getTypeInContext).toList();
    return new InstantiationConstantValue(
        typeArgumentsInContext, expression.evaluate(environment));
  }

  @override
  int _computeHashCode() {
    return Hashing.objectHash(expression, Hashing.listHash(typeArguments));
  }

  @override
  ConstantExpression apply(NormalizedArguments arguments) {
    return new InstantiationConstantExpression(
        typeArguments, expression.apply(arguments));
  }

  @override
  bool _equals(InstantiationConstantExpression other) {
    return equalElements(typeArguments, other.typeArguments) &&
        expression == other.expression;
  }

  @override
  accept(ConstantExpressionVisitor visitor, [context]) {
    return visitor.visitInstantiation(this, context);
  }

  @override
  bool get isPotential {
    return expression.isPotential;
  }
}

abstract class ConstantExpressionVisitor<R, A> {
  const ConstantExpressionVisitor();

  R visit(ConstantExpression constant, A context) {
    return constant.accept(this, context);
  }

  R visitAs(AsConstantExpression exp, A context);
  R visitBool(BoolConstantExpression exp, A context);
  R visitInt(IntConstantExpression exp, A context);
  R visitDouble(DoubleConstantExpression exp, A context);
  R visitString(StringConstantExpression exp, A context);
  R visitNull(NullConstantExpression exp, A context);
  R visitList(ListConstantExpression exp, A context);
  R visitSet(SetConstantExpression exp, A context);
  R visitMap(MapConstantExpression exp, A context);
  R visitConstructed(ConstructedConstantExpression exp, A context);
  R visitConcatenate(ConcatenateConstantExpression exp, A context);
  R visitSymbol(SymbolConstantExpression exp, A context);
  R visitType(TypeConstantExpression exp, A context);
  R visitLocalVariable(LocalVariableConstantExpression exp, A context);
  R visitField(FieldConstantExpression exp, A context);
  R visitFunction(FunctionConstantExpression exp, A context);
  R visitBinary(BinaryConstantExpression exp, A context);
  R visitIdentical(IdenticalConstantExpression exp, A context);
  R visitUnary(UnaryConstantExpression exp, A context);
  R visitStringLength(StringLengthConstantExpression exp, A context);
  R visitConditional(ConditionalConstantExpression exp, A context);
  R visitBoolFromEnvironment(
      BoolFromEnvironmentConstantExpression exp, A context);
  R visitIntFromEnvironment(
      IntFromEnvironmentConstantExpression exp, A context);
  R visitStringFromEnvironment(
      StringFromEnvironmentConstantExpression exp, A context);
  R visitAssert(AssertConstantExpression exp, A context);
  R visitInstantiation(InstantiationConstantExpression exp, A context);

  R visitPositional(PositionalArgumentReference exp, A context);
  R visitNamed(NamedArgumentReference exp, A context);
}

class ConstExpPrinter extends ConstantExpressionVisitor {
  final StringBuffer sb = new StringBuffer();

  void write(ConstantExpression parent, ConstantExpression child,
      {bool leftAssociative: true}) {
    if (child.precedence < parent.precedence ||
        !leftAssociative && child.precedence == parent.precedence) {
      sb.write('(');
      child.accept(this);
      sb.write(')');
    } else {
      child.accept(this);
    }
  }

  void writeTypeArguments(InterfaceType type) {
    if (type.treatAsRaw) return;
    sb.write('<');
    bool needsComma = false;
    for (DartType value in type.typeArguments) {
      if (needsComma) {
        sb.write(', ');
      }
      sb.write(value);
      needsComma = true;
    }
    sb.write('>');
  }

  @override
  void visit(ConstantExpression constant, [_]) {
    return constant.accept(this, null);
  }

  @override
  void visitAs(AsConstantExpression exp, [_]) {
    visit(exp.expression);
    sb.write(' as ');
    sb.write(exp.type);
  }

  @override
  void visitBool(BoolConstantExpression exp, [_]) {
    sb.write(exp.boolValue);
  }

  @override
  void visitDouble(DoubleConstantExpression exp, [_]) {
    sb.write(exp.doubleValue);
  }

  @override
  void visitInt(IntConstantExpression exp, [_]) {
    sb.write(exp.intValue);
  }

  @override
  void visitNull(NullConstantExpression exp, [_]) {
    sb.write(null);
  }

  @override
  void visitString(StringConstantExpression exp, [_]) {
    // TODO(johnniwinther): Ensure correct escaping.
    sb.write('"${exp.stringValue}"');
  }

  @override
  void visitList(ListConstantExpression exp, [_]) {
    sb.write('const ');
    writeTypeArguments(exp.type);
    sb.write('[');
    bool needsComma = false;
    for (ConstantExpression value in exp.values) {
      if (needsComma) {
        sb.write(', ');
      }
      visit(value);
      needsComma = true;
    }
    sb.write(']');
  }

  @override
  void visitSet(SetConstantExpression exp, [_]) {
    sb.write('const ');
    writeTypeArguments(exp.type);
    sb.write('{');
    sb.writeAll(exp.values, ', ');
    sb.write('}');
  }

  @override
  void visitMap(MapConstantExpression exp, [_]) {
    sb.write('const ');
    writeTypeArguments(exp.type);
    sb.write('{');
    for (int index = 0; index < exp.keys.length; index++) {
      if (index > 0) {
        sb.write(', ');
      }
      visit(exp.keys[index]);
      sb.write(': ');
      visit(exp.values[index]);
    }
    sb.write('}');
  }

  @override
  void visitConstructed(ConstructedConstantExpression exp, [_]) {
    sb.write('const ');
    sb.write(exp.target.enclosingClass.name);
    writeTypeArguments(exp.type);
    if (exp.target.name != '') {
      sb.write('.');
      sb.write(exp.target.name);
    }
    sb.write('(');
    bool needsComma = false;

    int namedOffset = exp.callStructure.positionalArgumentCount;
    for (int index = 0; index < namedOffset; index++) {
      if (needsComma) {
        sb.write(', ');
      }
      visit(exp.arguments[index]);
      needsComma = true;
    }
    for (int index = 0; index < exp.callStructure.namedArgumentCount; index++) {
      if (needsComma) {
        sb.write(', ');
      }
      sb.write(exp.callStructure.namedArguments[index]);
      sb.write(': ');
      visit(exp.arguments[namedOffset + index]);
      needsComma = true;
    }
    sb.write(')');
  }

  @override
  void visitConcatenate(ConcatenateConstantExpression exp, [_]) {
    sb.write('"');
    for (ConstantExpression expression in exp.expressions) {
      if (expression.kind == ConstantExpressionKind.STRING) {
        StringConstantExpression string = expression;
        // TODO(johnniwinther): Ensure correct escaping.
        sb.write('${string.stringValue}');
      } else {
        sb.write(r"${");
        visit(expression);
        sb.write("}");
      }
    }
    sb.write('"');
  }

  @override
  void visitSymbol(SymbolConstantExpression exp, [_]) {
    sb.write('#');
    sb.write(exp.name);
  }

  @override
  void visitType(TypeConstantExpression exp, [_]) {
    sb.write(exp.name);
  }

  @override
  void visitField(FieldConstantExpression exp, [_]) {
    if (exp.element.isStatic) {
      sb.write(exp.element.enclosingClass.name);
      sb.write('.');
    }
    sb.write(exp.element.name);
  }

  @override
  void visitLocalVariable(LocalVariableConstantExpression exp, [_]) {
    sb.write(exp.element.name);
  }

  @override
  void visitFunction(FunctionConstantExpression exp, [_]) {
    if (exp.element.isStatic) {
      sb.write(exp.element.enclosingClass.name);
      sb.write('.');
    }
    sb.write(exp.element.name);
  }

  @override
  void visitBinary(BinaryConstantExpression exp, [_]) {
    write(exp, exp.left);
    sb.write(' ');
    sb.write(exp.operator.name);
    sb.write(' ');
    write(exp, exp.right);
  }

  @override
  void visitIdentical(IdenticalConstantExpression exp, [_]) {
    sb.write('identical(');
    visit(exp.left);
    sb.write(', ');
    visit(exp.right);
    sb.write(')');
  }

  @override
  void visitUnary(UnaryConstantExpression exp, [_]) {
    sb.write(exp.operator);
    write(exp, exp.expression);
  }

  @override
  void visitStringLength(StringLengthConstantExpression exp, [_]) {
    write(exp, exp.expression, leftAssociative: false);
    sb.write('.length');
  }

  @override
  void visitConditional(ConditionalConstantExpression exp, [_]) {
    write(exp, exp.condition, leftAssociative: false);
    sb.write(' ? ');
    write(exp, exp.trueExp);
    sb.write(' : ');
    write(exp, exp.falseExp);
  }

  @override
  void visitPositional(PositionalArgumentReference exp, [_]) {
    // TODO(johnniwinther): Maybe this should throw.
    sb.write('args[${exp.index}]');
  }

  @override
  void visitNamed(NamedArgumentReference exp, [_]) {
    // TODO(johnniwinther): Maybe this should throw.
    sb.write('args[${exp.name}]');
  }

  @override
  void visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
      [_]) {
    sb.write('const bool.fromEnvironment(');
    visit(exp.name);
    if (exp.defaultValue != null) {
      sb.write(', defaultValue: ');
      visit(exp.defaultValue);
    }
    sb.write(')');
  }

  @override
  void visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp, [_]) {
    sb.write('const int.fromEnvironment(');
    visit(exp.name);
    if (exp.defaultValue != null) {
      sb.write(', defaultValue: ');
      visit(exp.defaultValue);
    }
    sb.write(')');
  }

  @override
  void visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp,
      [_]) {
    sb.write('const String.fromEnvironment(');
    visit(exp.name);
    if (exp.defaultValue != null) {
      sb.write(', defaultValue: ');
      visit(exp.defaultValue);
    }
    sb.write(')');
  }

  @override
  void visitAssert(AssertConstantExpression exp, [_]) {
    sb.write('assert(');
    visit(exp.condition);
    if (exp.message != null) {
      sb.write(', ');
      visit(exp.message);
    }
    sb.write(')');
  }

  @override
  void visitInstantiation(InstantiationConstantExpression exp, [_]) {
    sb.write('<');
    sb.write(exp.typeArguments.join(', '));
    sb.write('>(');
    visit(exp.expression);
    sb.write(')');
  }

  @override
  String toString() => sb.toString();
}
