Index: pkg/compiler/lib/src/serialization/equivalence.dart |
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart |
index be28121447478a00f77bd9d59506b7b5bb9cae63..760967ee4d2dd31ded7faa6343a00682cdd75ed1 100644 |
--- a/pkg/compiler/lib/src/serialization/equivalence.dart |
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart |
@@ -11,6 +11,7 @@ import '../constants/expressions.dart'; |
import '../dart_types.dart'; |
import '../elements/elements.dart'; |
import '../elements/visitor.dart'; |
+import '../resolution/access_semantics.dart'; |
import '../resolution/send_structure.dart'; |
import '../resolution/tree_elements.dart'; |
import '../tokens/token.dart'; |
@@ -138,13 +139,193 @@ bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { |
a.isEmpty == b.isEmpty; |
} |
+/// Returns `true` if the access semantics [a] and [b] are equivalent. |
+bool areAccessSemanticsEquivalent(AccessSemantics a, AccessSemantics b) { |
+ if (a.kind != b.kind) return false; |
+ switch (a.kind) { |
+ case AccessKind.EXPRESSION: |
+ case AccessKind.THIS: |
+ // No additional properties. |
+ return true; |
+ case AccessKind.THIS_PROPERTY: |
+ case AccessKind.DYNAMIC_PROPERTY: |
+ case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY: |
+ return areNamesEquivalent(a.name, b.name); |
+ case AccessKind.CLASS_TYPE_LITERAL: |
+ case AccessKind.TYPEDEF_TYPE_LITERAL: |
+ case AccessKind.DYNAMIC_TYPE_LITERAL: |
+ return areConstantsEquivalent(a.constant, b.constant); |
+ case AccessKind.LOCAL_FUNCTION: |
+ case AccessKind.LOCAL_VARIABLE: |
+ case AccessKind.FINAL_LOCAL_VARIABLE: |
+ case AccessKind.PARAMETER: |
+ case AccessKind.FINAL_PARAMETER: |
+ case AccessKind.STATIC_FIELD: |
+ case AccessKind.FINAL_STATIC_FIELD: |
+ case AccessKind.STATIC_METHOD: |
+ case AccessKind.STATIC_GETTER: |
+ case AccessKind.STATIC_SETTER: |
+ case AccessKind.TOPLEVEL_FIELD: |
+ case AccessKind.FINAL_TOPLEVEL_FIELD: |
+ case AccessKind.TOPLEVEL_METHOD: |
+ case AccessKind.TOPLEVEL_GETTER: |
+ case AccessKind.TOPLEVEL_SETTER: |
+ case AccessKind.SUPER_FIELD: |
+ case AccessKind.SUPER_FINAL_FIELD: |
+ case AccessKind.SUPER_METHOD: |
+ case AccessKind.SUPER_GETTER: |
+ case AccessKind.SUPER_SETTER: |
+ case AccessKind.TYPE_PARAMETER_TYPE_LITERAL: |
+ case AccessKind.UNRESOLVED: |
+ case AccessKind.UNRESOLVED_SUPER: |
+ case AccessKind.INVALID: |
+ return areElementsEquivalent(a.element, b.element); |
+ case AccessKind.COMPOUND: |
+ CompoundAccessSemantics compoundAccess1 = a; |
+ CompoundAccessSemantics compoundAccess2 = b; |
+ return compoundAccess1.compoundAccessKind == |
+ compoundAccess2.compoundAccessKind && |
+ areElementsEquivalent( |
+ compoundAccess1.getter, compoundAccess2.getter) && |
+ areElementsEquivalent(compoundAccess1.setter, compoundAccess2.setter); |
+ case AccessKind.CONSTANT: |
+ throw new UnsupportedError('Unsupported access kind: ${a.kind}'); |
+ } |
+} |
+ |
/// Returns `true` if the send structures [a] and [b] are equivalent. |
bool areSendStructuresEquivalent(SendStructure a, SendStructure b) { |
if (identical(a, b)) return true; |
if (a == null || b == null) return false; |
if (a.kind != b.kind) return false; |
- // TODO(johnniwinther): Compute a deep equivalence. |
- return true; |
+ switch (a.kind) { |
+ case SendStructureKind.IF_NULL: |
+ case SendStructureKind.LOGICAL_AND: |
+ case SendStructureKind.LOGICAL_OR: |
+ case SendStructureKind.NOT: |
+ case SendStructureKind.INVALID_UNARY: |
+ case SendStructureKind.INVALID_BINARY: |
+ // No additional properties. |
+ return true; |
+ case SendStructureKind.IS: |
+ IsStructure structure1 = a; |
+ IsStructure structure2 = b; |
+ return areTypesEquivalent(structure1.type, structure1.type); |
+ case SendStructureKind.IS_NOT: |
+ IsNotStructure structure1 = a; |
+ IsNotStructure structure2 = b; |
+ return areTypesEquivalent(structure1.type, structure1.type); |
Siggi Cherem (dart-lang)
2016/04/12 17:33:42
consider combining similar cases. No need to add c
Johnni Winther
2016/04/13 07:59:11
Done.
|
+ case SendStructureKind.AS: |
+ AsStructure structure1 = a; |
+ AsStructure structure2 = b; |
+ return areTypesEquivalent(structure1.type, structure1.type); |
+ case SendStructureKind.INVOKE: |
+ InvokeStructure structure1 = a; |
+ InvokeStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ areSelectorsEquivalent(structure1.selector, structure2.selector); |
+ case SendStructureKind.INCOMPATIBLE_INVOKE: |
+ IncompatibleInvokeStructure structure1 = a; |
+ IncompatibleInvokeStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ areSelectorsEquivalent(structure1.selector, structure2.selector); |
+ case SendStructureKind.GET: |
+ GetStructure structure1 = a; |
+ GetStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.SET: |
+ SetStructure structure1 = a; |
+ SetStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.UNARY: |
+ UnaryStructure structure1 = a; |
+ UnaryStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.INDEX: |
+ IndexStructure structure1 = a; |
+ IndexStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.EQUALS: |
+ EqualsStructure structure1 = a; |
+ EqualsStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.NOT_EQUALS: |
+ NotEqualsStructure structure1 = a; |
+ NotEqualsStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.BINARY: |
+ BinaryStructure structure1 = a; |
+ BinaryStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.INDEX_SET: |
+ IndexSetStructure structure1 = a; |
+ IndexSetStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.INDEX_PREFIX: |
+ IndexPrefixStructure structure1 = a; |
+ IndexPrefixStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.INDEX_POSTFIX: |
+ IndexPostfixStructure structure1 = a; |
+ IndexPostfixStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.COMPOUND: |
+ CompoundStructure structure1 = a; |
+ CompoundStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.SET_IF_NULL: |
+ SetIfNullStructure structure1 = a; |
+ SetIfNullStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.COMPOUND_INDEX_SET: |
+ CompoundIndexSetStructure structure1 = a; |
+ CompoundIndexSetStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.INDEX_SET_IF_NULL: |
+ IndexSetIfNullStructure structure1 = a; |
+ IndexSetIfNullStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics); |
+ case SendStructureKind.PREFIX: |
+ PrefixStructure structure1 = a; |
+ PrefixStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.POSTFIX: |
+ PostfixStructure structure1 = a; |
+ PostfixStructure structure2 = b; |
+ return areAccessSemanticsEquivalent( |
+ structure1.semantics, structure2.semantics) && |
+ structure1.operator == structure2.operator; |
+ case SendStructureKind.DEFERRED_PREFIX: |
+ DeferredPrefixStructure structure1 = a; |
+ DeferredPrefixStructure structure2 = b; |
+ return areElementsEquivalent(structure1.prefix, structure2.prefix) && |
+ areSendStructuresEquivalent( |
+ structure1.sendStructure, structure2.sendStructure); |
+ } |
} |
/// Returns `true` if the new structures [a] and [b] are equivalent. |
@@ -152,8 +333,24 @@ bool areNewStructuresEquivalent(NewStructure a, NewStructure b) { |
if (identical(a, b)) return true; |
if (a == null || b == null) return false; |
if (a.kind != b.kind) return false; |
- // TODO(johnniwinther): Compute a deep equivalence. |
- return true; |
+ switch (a.kind) { |
+ case NewStructureKind.NEW_INVOKE: |
+ NewInvokeStructure structure1 = a; |
+ NewInvokeStructure structure2 = b; |
+ return structure1.semantics.kind == structure2.semantics.kind && |
+ areElementsEquivalent( |
+ structure1.semantics.element, structure2.semantics.element) && |
+ areTypesEquivalent( |
+ structure1.semantics.type, structure2.semantics.type) && |
+ areSelectorsEquivalent(structure1.selector, structure2.selector); |
+ case NewStructureKind.CONST_INVOKE: |
+ ConstInvokeStructure structure1 = a; |
+ ConstInvokeStructure structure2 = b; |
+ return structure1.constantInvokeKind == structure2.constantInvokeKind && |
+ areConstantsEquivalent(structure1.constant, structure2.constant); |
+ case NewStructureKind.LATE_CONST: |
+ throw new UnsupportedError('Unsupported NewStructure kind ${a.kind}.'); |
+ } |
} |
/// Strategy for testing equivalence. |