// 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 '../common.dart';
import '../constants/constant_system.dart';
import '../common_elements.dart';
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,
  DEFERRED,
  DOUBLE,
  ERRONEOUS,
  FUNCTION,
  FIELD,
  IDENTICAL,
  INT,
  INT_FROM_ENVIRONMENT,
  LIST,
  MAP,
  NULL,
  STRING,
  STRING_FROM_ENVIRONMENT,
  STRING_LENGTH,
  SYMBOL,
  SYNTHETIC,
  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]
  /// and the [constantSystem].
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem);

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

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

  bool _equals(covariant ConstantExpression other);

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

  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 {
  ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    // 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;
}

// TODO(johnniwinther): Avoid the need for this class.
class SyntheticConstantExpression extends ConstantExpression {
  final SyntheticConstantValue value;

  SyntheticConstantExpression(this.value);

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return value;
  }

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

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

  accept(ConstantExpressionVisitor visitor, [context]) {
    throw "unsupported";
  }

  @override
  bool _equals(SyntheticConstantExpression other) {
    return value == other.value;
  }

  ConstantExpressionKind get kind => ConstantExpressionKind.SYNTHETIC;

  @override
  bool get isImplicit => false;
}

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

  BoolConstantExpression(this.boolValue);

  ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.INT;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.STRING;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return constantSystem.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();

  ConstantExpressionKind get kind => ConstantExpressionKind.NULL;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.LIST;

  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, ConstantSystem constantSystem) {
    return constantSystem.createList(type,
        values.map((v) => v.evaluate(environment, constantSystem)).toList());
  }

  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 map constant.
class MapConstantExpression extends ConstantExpression {
  final InterfaceType type;
  final List<ConstantExpression> keys;
  final List<ConstantExpression> values;

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

  ConstantExpressionKind get kind => ConstantExpressionKind.MAP;

  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, ConstantSystem constantSystem) {
    Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
    for (int i = 0; i < keys.length; i++) {
      ConstantValue key = keys[i].evaluate(environment, constantSystem);
      if (!key.isConstant) {
        return new NonConstantValue();
      }
      ConstantValue value = values[i].evaluate(environment, constantSystem);
      if (!value.isConstant) {
        return new NonConstantValue();
      }
      if (map.containsKey(key)) {
        environment.reportWarning(keys[i], MessageKind.EQUAL_MAP_ENTRY_KEY, {});
      }
      map[key] = value;
    }
    return constantSystem.createMap(environment.commonElements, type,
        map.keys.toList(), map.values.toList());
  }

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

  ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    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, constantSystem);
        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, constantSystem).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);

  ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    bool isValid = true;
    StringBuffer sb = new StringBuffer();
    for (ConstantExpression expression in expressions) {
      ConstantValue value = expression.evaluate(environment, constantSystem);
      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 constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;

  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, ConstantSystem constantSystem) {
    return constantSystem.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");
  }

  ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.AS;

  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, ConstantSystem constantSystem) {
    // 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, constantSystem);

    // 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 (!constantSystem.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);

  ConstantExpressionKind get kind => ConstantExpressionKind.FIELD;

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

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

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

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

  ConstantExpressionKind get kind => ConstantExpressionKind.LOCAL_VARIABLE;

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

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

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

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

  ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;

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

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    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;

  ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;

  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, ConstantSystem constantSystem) {
    ConstantValue leftValue = left.evaluate(environment, constantSystem);
    ConstantValue rightValue = right.evaluate(environment, constantSystem);
    if (!leftValue.isConstant || !rightValue.isConstant) {
      return new NonConstantValue();
    }
    bool isValid = true;
    switch (operator.kind) {
      case BinaryOperatorKind.EQ:
      case BinaryOperatorKind.NOT_EQ:
        if (!leftValue.isPrimitive) {
          environment.reportError(
              left, MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE, {
            'constant': left,
            'type': leftValue.getType(environment.commonElements),
            'operator': operator
          });
          isValid = false;
        }
        if (!rightValue.isPrimitive) {
          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.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)) {
          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 =
              constantSystem.equal.fold(leftValue, rightValue);
          return equals.negate();
        default:
          ConstantValue value =
              constantSystem.lookupBinary(operator).fold(leftValue, rightValue);
          if (value != null) {
            return value;
          }
          environment
              .reportError(this, MessageKind.NOT_A_COMPILE_TIME_CONSTANT, {});
      }
    }
    return new NonConstantValue();
  }

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

  // 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.SHR:
      case BinaryOperatorKind.SHL:
        return commonElements.intType;
      case BinaryOperatorKind.IF_NULL:
      case BinaryOperatorKind.INDEX:
        throw new UnsupportedError(
            'Unexpected constant binary operator: $operator');
    }
  }

  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.SHR: 11,
    BinaryOperatorKind.SHL: 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);

  ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;

  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, ConstantSystem constantSystem) {
    ConstantValue leftValue = left.evaluate(environment, constantSystem);
    ConstantValue rightValue = right.evaluate(environment, constantSystem);
    if (leftValue.isConstant && rightValue.isConstant) {
      return constantSystem.identity.fold(leftValue, rightValue);
    }
    return new NonConstantValue();
  }

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

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

  ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;

  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, ConstantSystem constantSystem) {
    ConstantValue expressionValue =
        expression.evaluate(environment, constantSystem);
    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 =
          constantSystem.lookupUnary(operator).fold(expressionValue);
      if (value != null) {
        return value;
      }
    }
    return new NonConstantValue();
  }

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

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

  ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;

  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, ConstantSystem constantSystem) {
    ConstantValue value = expression.evaluate(environment, constantSystem);
    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 constantSystem
          .createInt(new BigInt.from(stringValue.stringValue.length));
    }
  }

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

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

  ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;

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

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

  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, ConstantSystem constantSystem) {
    ConstantValue conditionValue =
        condition.evaluate(environment, constantSystem);
    ConstantValue trueValue = trueExp.evaluate(environment, constantSystem);
    ConstantValue falseValue = falseExp.evaluate(environment, constantSystem);
    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);

  ConstantExpressionKind get kind {
    return ConstantExpressionKind.POSITIONAL_REFERENCE;
  }

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

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

  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, ConstantSystem constantSystem) {
    throw new UnsupportedError('PositionalArgumentReference.evaluate');
  }

  @override
  bool get isPotential => true;
}

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

  NamedArgumentReference(this.name);

  ConstantExpressionKind get kind {
    return ConstantExpressionKind.NAMED_REFERENCE;
  }

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

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

  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, ConstantSystem constantSystem) {
    throw new UnsupportedError('NamedArgumentReference.evaluate');
  }

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

  ConstantExpressionKind get kind {
    return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
  }

  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, ConstantSystem constantSystem) {
    ConstantValue nameConstantValue =
        name.evaluate(environment, constantSystem);
    ConstantValue defaultConstantValue;
    if (defaultValue != null) {
      defaultConstantValue = defaultValue.evaluate(environment, constantSystem);
    } else {
      defaultConstantValue = constantSystem.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 constantSystem.createBool(true);
      } else if (text == 'false') {
        return constantSystem.createBool(false);
      } else {
        return defaultConstantValue;
      }
    }
    return new NonConstantValue();
  }

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

  ConstantExpressionKind get kind {
    return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
  }

  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, ConstantSystem constantSystem) {
    ConstantValue nameConstantValue =
        name.evaluate(environment, constantSystem);
    ConstantValue defaultConstantValue;
    if (defaultValue != null) {
      defaultConstantValue = defaultValue.evaluate(environment, constantSystem);
    } else {
      defaultConstantValue = constantSystem.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 constantSystem.createInt(value);
      }
    }
    return new NonConstantValue();
  }

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

  ConstantExpressionKind get kind {
    return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
  }

  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, ConstantSystem constantSystem) {
    ConstantValue nameConstantValue =
        name.evaluate(environment, constantSystem);
    ConstantValue defaultConstantValue;
    if (defaultValue != null) {
      defaultConstantValue = defaultValue.evaluate(environment, constantSystem);
    } else {
      defaultConstantValue = constantSystem.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 constantSystem.createString(text);
      }
    }
    return new NonConstantValue();
  }

  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, ConstantSystem constantSystem) {
    ConstantValue conditionValue =
        condition.evaluate(environment, constantSystem);
    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, constantSystem);
        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);
  }

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

/// A constant expression referenced with a deferred prefix.
/// For example `lib.C`.
class DeferredConstantExpression extends ConstantExpression {
  final ConstantExpression expression;
  final ImportEntity import;

  DeferredConstantExpression(this.expression, this.import);

  ConstantExpressionKind get kind => ConstantExpressionKind.DEFERRED;

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

  @override
  ConstantValue evaluate(
      EvaluationEnvironment environment, ConstantSystem constantSystem) {
    return new DeferredConstantValue(
        expression.evaluate(environment, constantSystem), import);
  }

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

  ConstantExpression apply(NormalizedArguments arguments) {
    return new DeferredConstantExpression(expression.apply(arguments), import);
  }

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

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

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

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

  InstantiationConstantExpression(this.typeArguments, this.expression);

  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, ConstantSystem constantSystem) {
    List<DartType> typeArgumentsInContext =
        typeArguments.map(environment.getTypeInContext).toList();
    return new InstantiationConstantValue(typeArgumentsInContext,
        expression.evaluate(environment, constantSystem));
  }

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

  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 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 visitDeferred(DeferredConstantExpression 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 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 visitDeferred(DeferredConstantExpression exp, context) {
    sb.write(exp.import.name);
    sb.write('.');
    write(exp, exp.expression);
  }

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

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