Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Unified Diff: packages/analyzer/lib/src/dart/constant/value.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packages/analyzer/lib/src/dart/constant/value.dart
diff --git a/packages/analyzer/lib/src/dart/constant/value.dart b/packages/analyzer/lib/src/dart/constant/value.dart
new file mode 100644
index 0000000000000000000000000000000000000000..db4de37f8302ce08b9e49f36f2c4d778191c2976
--- /dev/null
+++ b/packages/analyzer/lib/src/dart/constant/value.dart
@@ -0,0 +1,2820 @@
+// 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.
+
+/**
+ * The implementation of the class [DartObject].
+ */
+library analyzer.src.dart.constant.value;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/utilities_general.dart';
+
+/**
+ * The state of an object representing a boolean value.
+ */
+class BoolState extends InstanceState {
+ /**
+ * An instance representing the boolean value 'false'.
+ */
+ static BoolState FALSE_STATE = new BoolState(false);
+
+ /**
+ * An instance representing the boolean value 'true'.
+ */
+ static BoolState TRUE_STATE = new BoolState(true);
+
+ /**
+ * A state that can be used to represent a boolean whose value is not known.
+ */
+ static BoolState UNKNOWN_VALUE = new BoolState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final bool value;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ BoolState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : (value ? 2 : 3);
+
+ @override
+ bool get isBool => true;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "bool";
+
+ @override
+ bool operator ==(Object object) =>
+ object is BoolState && identical(value, object.value);
+
+ @override
+ BoolState convertToBool() => this;
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value ? "true" : "false");
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is BoolState) {
+ bool rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return BoolState.from(identical(value, rightValue));
+ } else if (rightOperand is DynamicState) {
+ return UNKNOWN_VALUE;
+ }
+ return FALSE_STATE;
+ }
+
+ @override
+ BoolState logicalAnd(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return value ? rightOperand.convertToBool() : FALSE_STATE;
+ }
+
+ @override
+ BoolState logicalNot() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return value ? FALSE_STATE : TRUE_STATE;
+ }
+
+ @override
+ BoolState logicalOr(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return value ? TRUE_STATE : rightOperand.convertToBool();
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
+
+ /**
+ * Return the boolean state representing the given boolean [value].
+ */
+ static BoolState from(bool value) =>
+ value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
+}
+
+/**
+ * A representation of an instance of a Dart class.
+ */
+class DartObjectImpl implements DartObject {
+ /**
+ * An empty list of objects.
+ */
+ static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
+
+ /**
+ * The run-time type of this object.
+ */
+ @override
+ final ParameterizedType type;
+
+ /**
+ * The state of the object.
+ */
+ final InstanceState _state;
+
+ /**
+ * Initialize a newly created object to have the given [type] and [_state].
+ */
+ DartObjectImpl(this.type, this._state);
+
+ /**
+ * Create an object to represent an unknown value.
+ */
+ factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
+ if (type.element.library.isDartCore) {
+ String typeName = type.name;
+ if (typeName == "bool") {
+ return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
+ } else if (typeName == "double") {
+ return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
+ } else if (typeName == "int") {
+ return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
+ } else if (typeName == "String") {
+ return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
+ }
+ }
+ return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
+ }
+
+ HashMap<String, DartObjectImpl> get fields => _state.fields;
+
+ @override
+ int get hashCode => JenkinsSmiHash.hash2(type.hashCode, _state.hashCode);
+
+ @override
+ bool get hasKnownValue => !_state.isUnknown;
+
+ /**
+ * Return `true` if this object represents an object whose type is 'bool'.
+ */
+ bool get isBool => _state.isBool;
+
+ /**
+ * Return `true` if this object represents an object whose type is either
+ * 'bool', 'num', 'String', or 'Null'.
+ */
+ bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
+
+ @override
+ bool get isNull => _state is NullState;
+
+ /**
+ * Return `true` if this object represents an unknown value.
+ */
+ bool get isUnknown => _state.isUnknown;
+
+ /**
+ * Return `true` if this object represents an instance of a user-defined
+ * class.
+ */
+ bool get isUserDefinedObject => _state is GenericState;
+
+ @override
+ bool operator ==(Object object) {
+ if (object is DartObjectImpl) {
+ return type == object.type && _state == object._state;
+ }
+ return false;
+ }
+
+ /**
+ * Return the result of invoking the '+' operator on this object with the
+ * given [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.add(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ } else if (result is StringState) {
+ return new DartObjectImpl(typeProvider.stringType, result);
+ }
+ // We should never get here.
+ throw new StateError("add returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '&' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitAnd(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.bitAnd(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '~' operator on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitNot(TypeProvider typeProvider) =>
+ new DartObjectImpl(typeProvider.intType, _state.bitNot());
+
+ /**
+ * Return the result of invoking the '|' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitOr(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.bitOr(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '^' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitXor(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.bitXor(rightOperand._state));
+
+ /**
+ * Return the result of invoking the ' ' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl concatenate(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.stringType, _state.concatenate(rightOperand._state));
+
+ /**
+ * Return the result of applying boolean conversion to this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl convertToBool(TypeProvider typeProvider) {
+ InterfaceType boolType = typeProvider.boolType;
+ if (identical(type, boolType)) {
+ return this;
+ }
+ return new DartObjectImpl(boolType, _state.convertToBool());
+ }
+
+ /**
+ * Return the result of invoking the '/' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for
+ * an object of this kind.
+ */
+ DartObjectImpl divide(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.divide(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new StateError("divide returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '==' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl equalEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ if (type != rightOperand.type) {
+ String typeName = type.name;
+ if (!(typeName == "bool" ||
+ typeName == "double" ||
+ typeName == "int" ||
+ typeName == "num" ||
+ typeName == "String" ||
+ typeName == "Null" ||
+ type.isDynamic)) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ }
+ }
+ return new DartObjectImpl(
+ typeProvider.boolType, _state.equalEqual(rightOperand._state));
+ }
+
+ @override
+ DartObject getField(String name) {
+ InstanceState state = _state;
+ if (state is GenericState) {
+ return state.fields[name];
+ }
+ return null;
+ }
+
+ /**
+ * Return the result of invoking the '&gt;' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl greaterThan(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.greaterThan(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '&gt;=' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl greaterThanOrEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(typeProvider.boolType,
+ _state.greaterThanOrEqual(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '~/' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl integerDivide(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.integerDivide(rightOperand._state));
+
+ /**
+ * Return the result of invoking the identical function on this object with
+ * the [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ */
+ DartObjectImpl isIdentical(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ return new DartObjectImpl(
+ typeProvider.boolType, _state.isIdentical(rightOperand._state));
+ }
+
+ /**
+ * Return the result of invoking the '&lt;' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl lessThan(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.lessThan(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '&lt;=' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl lessThanOrEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '&&' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl logicalAnd(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.logicalAnd(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '!' operator on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl logicalNot(TypeProvider typeProvider) =>
+ new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
+
+ /**
+ * Return the result of invoking the '||' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl logicalOr(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.logicalOr(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '-' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.minus(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new StateError("minus returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '-' operator on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl negated(TypeProvider typeProvider) {
+ InstanceState result = _state.negated();
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new StateError("negated returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '!=' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl notEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ if (type != rightOperand.type) {
+ String typeName = type.name;
+ if (typeName != "bool" &&
+ typeName != "double" &&
+ typeName != "int" &&
+ typeName != "num" &&
+ typeName != "String") {
+ return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
+ }
+ }
+ return new DartObjectImpl(typeProvider.boolType,
+ _state.equalEqual(rightOperand._state).logicalNot());
+ }
+
+ /**
+ * Return the result of converting this object to a 'String'. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the object cannot be converted to a
+ * 'String'.
+ */
+ DartObjectImpl performToString(TypeProvider typeProvider) {
+ InterfaceType stringType = typeProvider.stringType;
+ if (identical(type, stringType)) {
+ return this;
+ }
+ return new DartObjectImpl(stringType, _state.convertToString());
+ }
+
+ /**
+ * Return the result of invoking the '%' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl remainder(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.remainder(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new StateError("remainder returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '&lt;&lt;' operator on this object with
+ * the [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl shiftLeft(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.shiftLeft(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '&gt;&gt;' operator on this object with
+ * the [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl shiftRight(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.shiftRight(rightOperand._state));
+
+ /**
+ * Return the result of invoking the 'length' getter on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl stringLength(TypeProvider typeProvider) =>
+ new DartObjectImpl(typeProvider.intType, _state.stringLength());
+
+ /**
+ * Return the result of invoking the '*' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.times(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new StateError("times returned a ${result.runtimeType}");
+ }
+
+ @override
+ bool toBoolValue() {
+ InstanceState state = _state;
+ if (state is BoolState) {
+ return state.value;
+ }
+ return null;
+ }
+
+ @override
+ double toDoubleValue() {
+ InstanceState state = _state;
+ if (state is DoubleState) {
+ return state.value;
+ }
+ return null;
+ }
+
+ @override
+ int toIntValue() {
+ InstanceState state = _state;
+ if (state is IntState) {
+ return state.value;
+ }
+ return null;
+ }
+
+ @override
+ List<DartObject> toListValue() {
+ InstanceState state = _state;
+ if (state is ListState) {
+ return state._elements;
+ }
+ return null;
+ }
+
+ @override
+ Map<DartObject, DartObject> toMapValue() {
+ InstanceState state = _state;
+ if (state is MapState) {
+ return state._entries;
+ }
+ return null;
+ }
+
+ @override
+ String toString() => "${type.displayName} ($_state)";
+
+ @override
+ String toStringValue() {
+ InstanceState state = _state;
+ if (state is StringState) {
+ return state.value;
+ }
+ return null;
+ }
+
+ @override
+ String toSymbolValue() {
+ InstanceState state = _state;
+ if (state is SymbolState) {
+ return state.value;
+ }
+ return null;
+ }
+
+ @override
+ DartType toTypeValue() {
+ InstanceState state = _state;
+ if (state is TypeState) {
+ return state._type;
+ }
+ return null;
+ }
+}
+
+/**
+ * The state of an object representing a double.
+ */
+class DoubleState extends NumState {
+ /**
+ * A state that can be used to represent a double whose value is not known.
+ */
+ static DoubleState UNKNOWN_VALUE = new DoubleState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final double value;
+
+ /**
+ * Initialize a newly created state to represent a double with the given
+ * [value].
+ */
+ DoubleState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "double";
+
+ @override
+ bool operator ==(Object object) =>
+ object is DoubleState && (value == object.value);
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value + rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value + rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value.toString());
+ }
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value / rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value / rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value > rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value > rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value >= rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value >= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ double result = value / rightValue.toDouble();
+ return new IntState(result.toInt());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ double result = value / rightValue;
+ return new IntState(result.toInt());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue.toDouble());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value < rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value < rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value <= rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value <= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value - rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value - rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState negated() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(-(value));
+ }
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value % rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value % rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value * rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value * rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : value.toString();
+}
+
+/**
+ * The state of an object representing a Dart object for which there is no type
+ * information.
+ */
+class DynamicState extends InstanceState {
+ /**
+ * The unique instance of this class.
+ */
+ static DynamicState DYNAMIC_STATE = new DynamicState();
+
+ @override
+ bool get isBool => true;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ String get typeName => "dynamic";
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState bitNot() => IntState.UNKNOWN_VALUE;
+
+ @override
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ StringState concatenate(InstanceState rightOperand) {
+ assertString(rightOperand);
+ return StringState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState logicalAnd(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
+
+ @override
+ BoolState logicalOr(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ return rightOperand.convertToBool();
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ NumState negated() => NumState.UNKNOWN_VALUE;
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ /**
+ * Return an object representing an unknown numeric value whose type is based
+ * on the type of the [rightOperand].
+ */
+ NumState _unknownNum(InstanceState rightOperand) {
+ if (rightOperand is IntState) {
+ return IntState.UNKNOWN_VALUE;
+ } else if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return NumState.UNKNOWN_VALUE;
+ }
+}
+
+/**
+ * Exception that would be thrown during the evaluation of Dart code.
+ */
+class EvaluationException {
+ /**
+ * The error code associated with the exception.
+ */
+ final ErrorCode errorCode;
+
+ /**
+ * Initialize a newly created exception to have the given [errorCode].
+ */
+ EvaluationException(this.errorCode);
+}
+
+/**
+ * The state of an object representing a function.
+ */
+class FunctionState extends InstanceState {
+ /**
+ * The element representing the function being modeled.
+ */
+ final ExecutableElement _element;
+
+ /**
+ * Initialize a newly created state to represent the function with the given
+ * [element].
+ */
+ FunctionState(this._element);
+
+ @override
+ int get hashCode => _element == null ? 0 : _element.hashCode;
+
+ @override
+ String get typeName => "Function";
+
+ @override
+ bool operator ==(Object object) =>
+ object is FunctionState && (_element == object._element);
+
+ @override
+ StringState convertToString() {
+ if (_element == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(_element.name);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (_element == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is FunctionState) {
+ ExecutableElement rightElement = rightOperand._element;
+ if (rightElement == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(_element == rightElement);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ String toString() => _element == null ? "-unknown-" : _element.name;
+}
+
+/**
+ * The state of an object representing a Dart object for which there is no more
+ * specific state.
+ */
+class GenericState extends InstanceState {
+ /**
+ * Pseudo-field that we use to represent fields in the superclass.
+ */
+ static String SUPERCLASS_FIELD = "(super)";
+
+ /**
+ * A state that can be used to represent an object whose state is not known.
+ */
+ static GenericState UNKNOWN_VALUE =
+ new GenericState(new HashMap<String, DartObjectImpl>());
+
+ /**
+ * The values of the fields of this instance.
+ */
+ final HashMap<String, DartObjectImpl> _fieldMap;
+
+ /**
+ * Initialize a newly created state to represent a newly created object. The
+ * [fieldMap] contains the values of the fields of the instance.
+ */
+ GenericState(this._fieldMap);
+
+ @override
+ HashMap<String, DartObjectImpl> get fields => _fieldMap;
+
+ @override
+ int get hashCode {
+ int hashCode = 0;
+ for (DartObjectImpl value in _fieldMap.values) {
+ hashCode += value.hashCode;
+ }
+ return hashCode;
+ }
+
+ @override
+ bool get isUnknown => identical(this, UNKNOWN_VALUE);
+
+ @override
+ String get typeName => "user defined type";
+
+ @override
+ bool operator ==(Object object) {
+ if (object is GenericState) {
+ HashSet<String> otherFields =
+ new HashSet<String>.from(object._fieldMap.keys.toSet());
+ for (String fieldName in _fieldMap.keys.toSet()) {
+ if (_fieldMap[fieldName] != object._fieldMap[fieldName]) {
+ return false;
+ }
+ otherFields.remove(fieldName);
+ }
+ for (String fieldName in otherFields) {
+ if (object._fieldMap[fieldName] != _fieldMap[fieldName]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ List<String> fieldNames = _fieldMap.keys.toList();
+ fieldNames.sort();
+ bool first = true;
+ for (String fieldName in fieldNames) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write('; ');
+ }
+ buffer.write(fieldName);
+ buffer.write(' = ');
+ buffer.write(_fieldMap[fieldName]);
+ }
+ return buffer.toString();
+ }
+}
+
+/**
+ * The state of an object representing a Dart object.
+ */
+abstract class InstanceState {
+ /**
+ * If this represents a generic dart object, return a map from its field names
+ * to their values. Otherwise return null.
+ */
+ HashMap<String, DartObjectImpl> get fields => null;
+
+ /**
+ * Return `true` if this object represents an object whose type is 'bool'.
+ */
+ bool get isBool => false;
+
+ /**
+ * Return `true` if this object represents an object whose type is either
+ * 'bool', 'num', 'String', or 'Null'.
+ */
+ bool get isBoolNumStringOrNull => false;
+
+ /**
+ * Return `true` if this object represents an unknown value.
+ */
+ bool get isUnknown => false;
+
+ /**
+ * Return the name of the type of this value.
+ */
+ String get typeName;
+
+ /**
+ * Return the result of invoking the '+' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ InstanceState add(InstanceState rightOperand) {
+ if (this is StringState && rightOperand is StringState) {
+ return concatenate(rightOperand);
+ }
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a boolean value.
+ */
+ void assertBool(InstanceState state) {
+ if (!(state is BoolState || state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a boolean,
+ * numeric, string or null value.
+ */
+ void assertBoolNumStringOrNull(InstanceState state) {
+ if (!(state is BoolState ||
+ state is DoubleState ||
+ state is IntState ||
+ state is NumState ||
+ state is StringState ||
+ state is NullState ||
+ state is DynamicState)) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent an integer or
+ * null value.
+ */
+ void assertIntOrNull(InstanceState state) {
+ if (!(state is IntState ||
+ state is NumState ||
+ state is NullState ||
+ state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a boolean,
+ * numeric, string or null value.
+ */
+ void assertNumOrNull(InstanceState state) {
+ if (!(state is DoubleState ||
+ state is IntState ||
+ state is NumState ||
+ state is NullState ||
+ state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a String value.
+ */
+ void assertString(InstanceState state) {
+ if (!(state is StringState || state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
+ }
+ }
+
+ /**
+ * Return the result of invoking the '&' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '~' operator on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitNot() {
+ assertIntOrNull(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '|' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '^' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the ' ' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ StringState concatenate(InstanceState rightOperand) {
+ assertString(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of applying boolean conversion to this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState convertToBool() => BoolState.FALSE_STATE;
+
+ /**
+ * Return the result of converting this object to a String.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ StringState convertToString();
+
+ /**
+ * Return the result of invoking the '/' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '==' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState equalEqual(InstanceState rightOperand);
+
+ /**
+ * Return the result of invoking the '&gt;' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '&gt;=' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '~/' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the identical function on this object with
+ * the [rightOperand].
+ */
+ BoolState isIdentical(InstanceState rightOperand);
+
+ /**
+ * Return the result of invoking the '&lt;' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '&lt;=' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '&&' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState logicalAnd(InstanceState rightOperand) {
+ assertBool(this);
+ assertBool(rightOperand);
+ return BoolState.FALSE_STATE;
+ }
+
+ /**
+ * Return the result of invoking the '!' operator on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState logicalNot() {
+ assertBool(this);
+ return BoolState.TRUE_STATE;
+ }
+
+ /**
+ * Return the result of invoking the '||' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState logicalOr(InstanceState rightOperand) {
+ assertBool(this);
+ assertBool(rightOperand);
+ return rightOperand.convertToBool();
+ }
+
+ /**
+ * Return the result of invoking the '-' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '-' operator on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState negated() {
+ assertNumOrNull(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '%' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '&lt;&lt;' operator on this object with
+ * the [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '&gt;&gt;' operator on this object with
+ * the [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the 'length' getter on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState stringLength() {
+ assertString(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '*' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+}
+
+/**
+ * The state of an object representing an int.
+ */
+class IntState extends NumState {
+ /**
+ * A state that can be used to represent an int whose value is not known.
+ */
+ static IntState UNKNOWN_VALUE = new IntState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final int value;
+
+ /**
+ * Initialize a newly created state to represent an int with the given
+ * [value].
+ */
+ IntState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "int";
+
+ @override
+ bool operator ==(Object object) =>
+ object is IntState && (value == object.value);
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value + rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() + rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value & rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState bitNot() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(~value);
+ }
+
+ @override
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value | rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value ^ rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value.toString());
+ }
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ } else {
+ return new DoubleState(value.toDouble() / rightValue.toDouble());
+ }
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() / rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) > 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() > rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) >= 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() >= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+ }
+ return new IntState(value ~/ rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ double result = value.toDouble() / rightValue;
+ return new IntState(result.toInt());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(rightValue == value.toDouble());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) < 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() < rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) <= 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() <= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value - rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() - rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState negated() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(-value);
+ }
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ return new DoubleState(value.toDouble() % rightValue.toDouble());
+ }
+ return new IntState(value.remainder(rightValue));
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() % rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue.bitLength > 31) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value << rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue.bitLength > 31) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value >> rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value * rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() * rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : value.toString();
+}
+
+/**
+ * The state of an object representing a list.
+ */
+class ListState extends InstanceState {
+ /**
+ * The elements of the list.
+ */
+ final List<DartObjectImpl> _elements;
+
+ /**
+ * Initialize a newly created state to represent a list with the given
+ * [elements].
+ */
+ ListState(this._elements);
+
+ @override
+ int get hashCode {
+ int value = 0;
+ int count = _elements.length;
+ for (int i = 0; i < count; i++) {
+ value = (value << 3) ^ _elements[i].hashCode;
+ }
+ return value;
+ }
+
+ @override
+ String get typeName => "List";
+
+ @override
+ bool operator ==(Object object) {
+ if (object is ListState) {
+ List<DartObjectImpl> otherElements = object._elements;
+ int count = _elements.length;
+ if (otherElements.length != count) {
+ return false;
+ } else if (count == 0) {
+ return true;
+ }
+ for (int i = 0; i < count; i++) {
+ if (_elements[i] != otherElements[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('[');
+ bool first = true;
+ _elements.forEach((DartObjectImpl element) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write(', ');
+ }
+ buffer.write(element);
+ });
+ buffer.write(']');
+ return buffer.toString();
+ }
+}
+
+/**
+ * The state of an object representing a map.
+ */
+class MapState extends InstanceState {
+ /**
+ * The entries in the map.
+ */
+ final HashMap<DartObjectImpl, DartObjectImpl> _entries;
+
+ /**
+ * Initialize a newly created state to represent a map with the given
+ * [entries].
+ */
+ MapState(this._entries);
+
+ @override
+ int get hashCode {
+ int value = 0;
+ for (DartObjectImpl key in _entries.keys.toSet()) {
+ value = (value << 3) ^ key.hashCode;
+ }
+ return value;
+ }
+
+ @override
+ String get typeName => "Map";
+
+ @override
+ bool operator ==(Object object) {
+ if (object is MapState) {
+ HashMap<DartObjectImpl, DartObjectImpl> otherElements = object._entries;
+ int count = _entries.length;
+ if (otherElements.length != count) {
+ return false;
+ } else if (count == 0) {
+ return true;
+ }
+ for (DartObjectImpl key in _entries.keys) {
+ DartObjectImpl value = _entries[key];
+ DartObjectImpl otherValue = otherElements[key];
+ if (value != otherValue) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('{');
+ bool first = true;
+ _entries.forEach((DartObjectImpl key, DartObjectImpl value) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write(', ');
+ }
+ buffer.write(key);
+ buffer.write(' = ');
+ buffer.write(value);
+ });
+ buffer.write('}');
+ return buffer.toString();
+ }
+}
+
+/**
+ * The state of an object representing the value 'null'.
+ */
+class NullState extends InstanceState {
+ /**
+ * An instance representing the boolean value 'null'.
+ */
+ static NullState NULL_STATE = new NullState();
+
+ @override
+ int get hashCode => 0;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ String get typeName => "Null";
+
+ @override
+ bool operator ==(Object object) => object is NullState;
+
+ @override
+ BoolState convertToBool() {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ StringState convertToString() => new StringState("null");
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(rightOperand is NullState);
+ }
+
+ @override
+ BoolState logicalNot() {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => "null";
+}
+
+/**
+ * The state of an object representing a number of an unknown type (a 'num').
+ */
+class NumState extends InstanceState {
+ /**
+ * A state that can be used to represent a number whose value is not known.
+ */
+ static NumState UNKNOWN_VALUE = new NumState();
+
+ @override
+ int get hashCode => 7;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => identical(this, UNKNOWN_VALUE);
+
+ @override
+ String get typeName => "num";
+
+ @override
+ bool operator ==(Object object) => object is NumState;
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return DoubleState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+ }
+ } else if (rightOperand is DynamicState) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState negated() => UNKNOWN_VALUE;
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ String toString() => "-unknown-";
+}
+
+/**
+ * The state of an object representing a string.
+ */
+class StringState extends InstanceState {
+ /**
+ * A state that can be used to represent a double whose value is not known.
+ */
+ static StringState UNKNOWN_VALUE = new StringState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final String value;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ StringState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "String";
+
+ @override
+ bool operator ==(Object object) =>
+ object is StringState && (value == object.value);
+
+ @override
+ StringState concatenate(InstanceState rightOperand) {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is StringState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new StringState("$value$rightValue");
+ } else if (rightOperand is DynamicState) {
+ return UNKNOWN_VALUE;
+ }
+ return super.concatenate(rightOperand);
+ }
+
+ @override
+ StringState convertToString() => this;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is StringState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ IntState stringLength() {
+ if (value == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ return new IntState(value.length);
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : "'$value'";
+}
+
+/**
+ * The state of an object representing a symbol.
+ */
+class SymbolState extends InstanceState {
+ /**
+ * The value of this instance.
+ */
+ final String value;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ SymbolState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ String get typeName => "Symbol";
+
+ @override
+ bool operator ==(Object object) =>
+ object is SymbolState && (value == object.value);
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is SymbolState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : "#$value";
+}
+
+/**
+ * The state of an object representing a type.
+ */
+class TypeState extends InstanceState {
+ /**
+ * The element representing the type being modeled.
+ */
+ final DartType _type;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ TypeState(this._type);
+
+ @override
+ int get hashCode => _type?.hashCode ?? 0;
+
+ @override
+ String get typeName => "Type";
+
+ @override
+ bool operator ==(Object object) =>
+ object is TypeState && (_type == object._type);
+
+ @override
+ StringState convertToString() {
+ if (_type == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(_type.displayName);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (_type == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is TypeState) {
+ DartType rightType = rightOperand._type;
+ if (rightType == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(_type == rightType);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ String toString() => _type?.toString() ?? "-unknown-";
+}
« no previous file with comments | « packages/analyzer/lib/src/dart/constant/utilities.dart ('k') | packages/analyzer/lib/src/dart/element/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698