Chromium Code Reviews| 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. |