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

Unified Diff: pkg/compiler/lib/src/constants/expressions.dart

Issue 1050133006: Add structural equality to ConstantExpression. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 5 years, 8 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
« no previous file with comments | « pkg/compiler/lib/src/compile_time_constants.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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> {
« no previous file with comments | « pkg/compiler/lib/src/compile_time_constants.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698