| Index: pkg/compiler/lib/src/constants/expressions.dart
|
| diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
|
| index 9a7ef9aa8928fa655ef8becca1493079468efa9f..1263ada4303f29dfe8727df36ec7bb1221e5be16 100644
|
| --- a/pkg/compiler/lib/src/constants/expressions.dart
|
| +++ b/pkg/compiler/lib/src/constants/expressions.dart
|
| @@ -7,6 +7,7 @@ library dart2js.constants.expressions;
|
| import '../dart2jslib.dart' show assertDebugMode;
|
| import '../dart_types.dart';
|
| import '../elements/elements.dart' show
|
| + ConstructorElement,
|
| Element,
|
| FunctionElement,
|
| VariableElement;
|
| @@ -14,6 +15,27 @@ import '../resolution/operators.dart';
|
| import '../universe/universe.dart' show CallStructure;
|
| import 'values.dart';
|
|
|
| +enum ConstantExpressionKind {
|
| + BINARY,
|
| + BOOL,
|
| + CONCATENATE,
|
| + CONDITIONAL,
|
| + CONSTRUCTED,
|
| + DOUBLE,
|
| + ERRONEOUS,
|
| + FUNCTION,
|
| + IDENTICAL,
|
| + INT,
|
| + LIST,
|
| + MAP,
|
| + NULL,
|
| + STRING,
|
| + SYMBOL,
|
| + TYPE,
|
| + UNARY,
|
| + VARIABLE,
|
| +}
|
| +
|
| /// An expression that is a compile-time constant.
|
| ///
|
| /// Whereas [ConstantValue] represent a compile-time value, a
|
| @@ -24,6 +46,10 @@ import 'values.dart';
|
| /// 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;
|
| +
|
| /// Returns the value of this constant expression.
|
| ConstantValue get value;
|
|
|
| @@ -39,6 +65,25 @@ abstract class ConstantExpression {
|
| return printer.toString();
|
| }
|
|
|
| + int _computeHashCode();
|
| +
|
| + int get hashCode {
|
| + if (_hashCode == null) {
|
| + _hashCode = _computeHashCode();
|
| + }
|
| + return _hashCode;
|
| + }
|
| +
|
| + bool _equals(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.getText() instead of '
|
| 'ConstantExpression.toString()');
|
| @@ -50,26 +95,120 @@ abstract class ConstantExpression {
|
| class ErroneousConstantExpression extends ConstantExpression {
|
| final PrimitiveConstantValue value = new NullConstantValue();
|
|
|
| - ErroneousConstantExpression();
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;
|
|
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| // Do nothing. This is an error.
|
| }
|
| +
|
| + @override
|
| + int _computeHashCode() => 13;
|
| +
|
| + @override
|
| + bool _equals(ErroneousConstantExpression other) => true;
|
| }
|
|
|
| -/// Boolean, int, double, string, or null constant.
|
| -class PrimitiveConstantExpression extends ConstantExpression {
|
| +/// A boolean, int, double, string, or null constant.
|
| +abstract class PrimitiveConstantExpression extends ConstantExpression {
|
| final PrimitiveConstantValue value;
|
|
|
| - PrimitiveConstantExpression(this.value) {
|
| - assert(value != null);
|
| - }
|
| + PrimitiveConstantExpression(this.value);
|
| +
|
| + /// The primitive value of this contant expression.
|
| + get primitiveValue;
|
|
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitPrimitive(this, context);
|
| }
|
| }
|
|
|
| +/// Boolean literal constant.
|
| +class BoolConstantExpression extends PrimitiveConstantExpression {
|
| + final bool primitiveValue;
|
| +
|
| + BoolConstantExpression(this.primitiveValue,
|
| + PrimitiveConstantValue value) : super(value);
|
| +
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;
|
| +
|
| + @override
|
| + int _computeHashCode() => 13 * primitiveValue.hashCode;
|
| +
|
| + @override
|
| + bool _equals(BoolConstantExpression other) {
|
| + return primitiveValue == other.primitiveValue;
|
| + }
|
| +}
|
| +
|
| +/// Integer literal constant.
|
| +class IntConstantExpression extends PrimitiveConstantExpression {
|
| + final int primitiveValue;
|
| +
|
| + IntConstantExpression(this.primitiveValue,
|
| + PrimitiveConstantValue value) : super(value);
|
| +
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.INT;
|
| +
|
| + @override
|
| + int _computeHashCode() => 17 * primitiveValue.hashCode;
|
| +
|
| + @override
|
| + bool _equals(IntConstantExpression other) {
|
| + return primitiveValue == other.primitiveValue;
|
| + }
|
| +}
|
| +
|
| +/// Double literal constant.
|
| +class DoubleConstantExpression extends PrimitiveConstantExpression {
|
| + final double primitiveValue;
|
| +
|
| + DoubleConstantExpression(this.primitiveValue,
|
| + PrimitiveConstantValue value) : super(value);
|
| +
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;
|
| +
|
| + @override
|
| + int _computeHashCode() => 19 * primitiveValue.hashCode;
|
| +
|
| + @override
|
| + bool _equals(DoubleConstantExpression other) {
|
| + return primitiveValue == other.primitiveValue;
|
| + }
|
| +}
|
| +
|
| +/// String literal constant.
|
| +class StringConstantExpression extends PrimitiveConstantExpression {
|
| + final String primitiveValue;
|
| +
|
| + StringConstantExpression(this.primitiveValue,
|
| + PrimitiveConstantValue value) : super(value);
|
| +
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.STRING;
|
| +
|
| + @override
|
| + int _computeHashCode() => 23 * primitiveValue.hashCode;
|
| +
|
| + @override
|
| + bool _equals(StringConstantExpression other) {
|
| + return primitiveValue == other.primitiveValue;
|
| + }
|
| +}
|
| +
|
| +/// Null literal constant.
|
| +class NullConstantExpression extends PrimitiveConstantExpression {
|
| + NullConstantExpression(PrimitiveConstantValue value) : super(value);
|
| +
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.NULL;
|
| +
|
| + get primitiveValue => null;
|
| +
|
| + @override
|
| + int _computeHashCode() => 29;
|
| +
|
| + @override
|
| + bool _equals(NullConstantExpression other) => true;
|
| +}
|
| +
|
| /// Literal list constant.
|
| class ListConstantExpression extends ConstantExpression {
|
| final ListConstantValue value;
|
| @@ -78,9 +217,30 @@ class ListConstantExpression extends ConstantExpression {
|
|
|
| ListConstantExpression(this.value, this.type, this.values);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.LIST;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitList(this, context);
|
| }
|
| +
|
| + @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;
|
| + }
|
| }
|
|
|
| /// Literal map constant.
|
| @@ -92,16 +252,38 @@ class MapConstantExpression extends ConstantExpression {
|
|
|
| MapConstantExpression(this.value, this.type, this.keys, this.values);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.MAP;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitMap(this, context);
|
| }
|
| +
|
| + @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;
|
| + }
|
| }
|
|
|
| /// Invocation of a const constructor.
|
| class ConstructedConstantExpression extends ConstantExpression {
|
| final ConstantValue value;
|
| final InterfaceType type;
|
| - final FunctionElement target;
|
| + final ConstructorElement target;
|
| final CallStructure callStructure;
|
| final List<ConstantExpression> arguments;
|
|
|
| @@ -114,22 +296,66 @@ class ConstructedConstantExpression extends ConstantExpression {
|
| assert(type.element == target.enclosingClass);
|
| }
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitConstructed(this, context);
|
| }
|
| +
|
| + @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;
|
| + }
|
| }
|
|
|
| /// String literal with juxtaposition and/or interpolations.
|
| -// TODO(johnniwinther): Do we need this?
|
| class ConcatenateConstantExpression extends ConstantExpression {
|
| final StringConstantValue value;
|
| final List<ConstantExpression> arguments;
|
|
|
| ConcatenateConstantExpression(this.value, this.arguments);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitConcatenate(this, context);
|
| }
|
| +
|
| + @override
|
| + int _computeHashCode() {
|
| + int hashCode = 17 * arguments.length;
|
| + for (ConstantExpression value in arguments) {
|
| + hashCode ^= 19 * value.hashCode;
|
| + }
|
| + return hashCode;
|
| + }
|
| +
|
| + @override
|
| + bool _equals(ConcatenateConstantExpression other) {
|
| + if (arguments.length != other.arguments.length) return false;
|
| + for (int i = 0; i < arguments.length; i++) {
|
| + if (arguments[i] != other.arguments[i]) return false;
|
| + }
|
| + return true;
|
| + }
|
| }
|
|
|
| /// Symbol literal.
|
| @@ -139,9 +365,19 @@ class SymbolConstantExpression extends ConstantExpression {
|
|
|
| SymbolConstantExpression(this.value, this.name);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitSymbol(this, context);
|
| }
|
| +
|
| + @override
|
| + int _computeHashCode() => 13 * name.hashCode;
|
| +
|
| + @override
|
| + bool _equals(SymbolConstantExpression other) {
|
| + return name == other.name;
|
| + }
|
| }
|
|
|
| /// Type literal.
|
| @@ -154,9 +390,19 @@ class TypeConstantExpression extends ConstantExpression {
|
| assert(type is GenericType || type is DynamicType);
|
| }
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitType(this, context);
|
| }
|
| +
|
| + @override
|
| + int _computeHashCode() => 13 * type.hashCode;
|
| +
|
| + @override
|
| + bool _equals(TypeConstantExpression other) {
|
| + return type == other.type;
|
| + }
|
| }
|
|
|
| /// Reference to a constant local, top-level, or static variable.
|
| @@ -166,9 +412,19 @@ class VariableConstantExpression extends ConstantExpression {
|
|
|
| VariableConstantExpression(this.value, this.element);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitVariable(this, context);
|
| }
|
| +
|
| + @override
|
| + int _computeHashCode() => 13 * element.hashCode;
|
| +
|
| + @override
|
| + bool _equals(VariableConstantExpression other) {
|
| + return element == other.element;
|
| + }
|
| }
|
|
|
| /// Reference to a top-level or static function.
|
| @@ -178,9 +434,19 @@ class FunctionConstantExpression extends ConstantExpression {
|
|
|
| FunctionConstantExpression(this.value, this.element);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitFunction(this, context);
|
| }
|
| +
|
| + @override
|
| + int _computeHashCode() => 13 * element.hashCode;
|
| +
|
| + @override
|
| + bool _equals(FunctionConstantExpression other) {
|
| + return element == other.element;
|
| + }
|
| }
|
|
|
| /// A constant binary expression like `a * b`.
|
| @@ -194,12 +460,28 @@ class BinaryConstantExpression extends ConstantExpression {
|
| assert(PRECEDENCE_MAP[operator.kind] != null);
|
| }
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitBinary(this, context);
|
| }
|
|
|
| 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;
|
| + }
|
| +
|
| static const Map<BinaryOperatorKind, int> PRECEDENCE_MAP = const {
|
| BinaryOperatorKind.EQ: 6,
|
| BinaryOperatorKind.NOT_EQ: 6,
|
| @@ -231,11 +513,25 @@ class IdenticalConstantExpression extends ConstantExpression {
|
|
|
| IdenticalConstantExpression(this.value, this.left, this.right);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitIdentical(this, context);
|
| }
|
|
|
| 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;
|
| + }
|
| }
|
|
|
| /// A unary constant expression like `-a`.
|
| @@ -248,12 +544,26 @@ class UnaryConstantExpression extends ConstantExpression {
|
| assert(PRECEDENCE_MAP[operator.kind] != null);
|
| }
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitUnary(this, context);
|
| }
|
|
|
| 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;
|
| + }
|
| +
|
| static const Map<UnaryOperatorKind, int> PRECEDENCE_MAP = const {
|
| UnaryOperatorKind.NOT: 14,
|
| UnaryOperatorKind.COMPLEMENT: 14,
|
| @@ -273,11 +583,27 @@ class ConditionalConstantExpression extends ConstantExpression {
|
| this.trueExp,
|
| this.falseExp);
|
|
|
| + ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;
|
| +
|
| accept(ConstantExpressionVisitor visitor, [context]) {
|
| return visitor.visitConditional(this, context);
|
| }
|
|
|
| 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;
|
| + }
|
| }
|
|
|
| abstract class ConstantExpressionVisitor<C, R> {
|
|
|