OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Functions for asserting equivalence across serialization. | 5 /// Functions for asserting equivalence across serialization. |
6 | 6 |
7 library dart2js.serialization.equivalence; | 7 library dart2js.serialization.equivalence; |
8 | 8 |
9 import '../closure.dart'; | 9 import '../closure.dart'; |
10 import '../common.dart'; | 10 import '../common.dart'; |
11 import '../common/resolution.dart'; | 11 import '../common/resolution.dart'; |
12 import '../constants/expressions.dart'; | 12 import '../constants/expressions.dart'; |
13 import '../constants/values.dart'; | |
13 import '../dart_types.dart'; | 14 import '../dart_types.dart'; |
14 import '../elements/elements.dart'; | 15 import '../elements/elements.dart'; |
15 import '../elements/visitor.dart'; | 16 import '../elements/visitor.dart'; |
16 import '../js_backend/backend_serialization.dart' | 17 import '../js_backend/backend_serialization.dart' |
17 show NativeBehaviorSerialization; | 18 show NativeBehaviorSerialization; |
18 import '../native/native.dart' show NativeBehavior; | 19 import '../native/native.dart' show NativeBehavior; |
19 import '../resolution/access_semantics.dart'; | 20 import '../resolution/access_semantics.dart'; |
20 import '../resolution/send_structure.dart'; | 21 import '../resolution/send_structure.dart'; |
21 import '../resolution/tree_elements.dart'; | 22 import '../resolution/tree_elements.dart'; |
22 import '../tokens/token.dart'; | 23 import '../tokens/token.dart'; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 break; | 57 break; |
57 } | 58 } |
58 } | 59 } |
59 if (!found) { | 60 if (!found) { |
60 return false; | 61 return false; |
61 } | 62 } |
62 } | 63 } |
63 return remaining.isEmpty; | 64 return remaining.isEmpty; |
64 } | 65 } |
65 | 66 |
67 /// Returns `true` if the content of [map1] and [map2] is equivalent using | |
68 /// [keyEquivalence] and [valueEquivalence] to determine key/value equivalence. | |
69 bool areMapsEquivalent(Map map1, Map map2, | |
70 [bool keyEquivalence(a, b) = equality, | |
71 bool valueEquivalence(a, b) = equality]) { | |
72 Set remaining = map2.keys.toSet(); | |
73 for (var key1 in map1.keys) { | |
74 bool found = false; | |
75 for (var key2 in map2.keys) { | |
76 if (keyEquivalence(key2, key2)) { | |
77 found = true; | |
78 remaining.remove(key2); | |
79 if (!valueEquivalence(map1[key1], map2[key2])) { | |
80 return false; | |
81 } | |
82 break; | |
83 } | |
84 } | |
85 if (!found) { | |
86 return false; | |
87 } | |
88 } | |
89 return remaining.isEmpty; | |
90 } | |
91 | |
66 /// Returns `true` if elements [a] and [b] are equivalent. | 92 /// Returns `true` if elements [a] and [b] are equivalent. |
67 bool areElementsEquivalent(Element a, Element b) { | 93 bool areElementsEquivalent(Element a, Element b) { |
68 if (identical(a, b)) return true; | 94 if (identical(a, b)) return true; |
69 if (a == null || b == null) return false; | 95 if (a == null || b == null) return false; |
70 return const ElementIdentityEquivalence().visit(a, b); | 96 return const ElementIdentityEquivalence().visit(a, b); |
71 } | 97 } |
72 | 98 |
73 /// Returns `true` if types [a] and [b] are equivalent. | 99 /// Returns `true` if types [a] and [b] are equivalent. |
74 bool areTypesEquivalent(DartType a, DartType b) { | 100 bool areTypesEquivalent(DartType a, DartType b) { |
75 if (identical(a, b)) return true; | 101 if (identical(a, b)) return true; |
76 if (a == null || b == null) return false; | 102 if (a == null || b == null) return false; |
77 return const TypeEquivalence().visit(a, b); | 103 return const TypeEquivalence().visit(a, b); |
78 } | 104 } |
79 | 105 |
80 /// Returns `true` if constants [a] and [b] are equivalent. | 106 /// Returns `true` if constants [exp1] and [exp2] are equivalent. |
81 bool areConstantsEquivalent(ConstantExpression exp1, ConstantExpression exp2) { | 107 bool areConstantsEquivalent(ConstantExpression exp1, ConstantExpression exp2) { |
82 if (identical(exp1, exp2)) return true; | 108 if (identical(exp1, exp2)) return true; |
83 if (exp1 == null || exp2 == null) return false; | 109 if (exp1 == null || exp2 == null) return false; |
84 return const ConstantEquivalence().visit(exp1, exp2); | 110 return const ConstantEquivalence().visit(exp1, exp2); |
85 } | 111 } |
86 | 112 |
113 /// Returns `true` if constant values [value1] and [value2] are equivalent. | |
114 bool areConstantValuesEquivalent(ConstantValue value1, ConstantValue value2) { | |
115 if (identical(value1, value2)) return true; | |
116 if (value1 == null || value2 == null) return false; | |
117 return const ConstantValueEquivalence().visit(value1, value2); | |
118 } | |
119 | |
87 /// Returns `true` if the lists of elements, [a] and [b], are equivalent. | 120 /// Returns `true` if the lists of elements, [a] and [b], are equivalent. |
88 bool areElementListsEquivalent(List<Element> a, List<Element> b) { | 121 bool areElementListsEquivalent(List<Element> a, List<Element> b) { |
89 return areListsEquivalent(a, b, areElementsEquivalent); | 122 return areListsEquivalent(a, b, areElementsEquivalent); |
90 } | 123 } |
91 | 124 |
92 /// Returns `true` if the lists of types, [a] and [b], are equivalent. | 125 /// Returns `true` if the lists of types, [a] and [b], are equivalent. |
93 bool areTypeListsEquivalent(List<DartType> a, List<DartType> b) { | 126 bool areTypeListsEquivalent(List<DartType> a, List<DartType> b) { |
94 return areListsEquivalent(a, b, areTypesEquivalent); | 127 return areListsEquivalent(a, b, areTypesEquivalent); |
95 } | 128 } |
96 | 129 |
97 /// Returns `true` if the lists of constants, [a] and [b], are equivalent. | 130 /// Returns `true` if the lists of constants, [a] and [b], are equivalent. |
98 bool areConstantListsEquivalent( | 131 bool areConstantListsEquivalent( |
99 List<ConstantExpression> a, List<ConstantExpression> b) { | 132 List<ConstantExpression> a, List<ConstantExpression> b) { |
100 return areListsEquivalent(a, b, areConstantsEquivalent); | 133 return areListsEquivalent(a, b, areConstantsEquivalent); |
101 } | 134 } |
102 | 135 |
136 /// Returns `true` if the lists of constant values, [a] and [b], are equivalent. | |
137 bool areConstantValueListsEquivalent( | |
138 List<ConstantValue> a, List<ConstantValue> b) { | |
139 return areListsEquivalent(a, b, areConstantValuesEquivalent); | |
140 } | |
141 | |
103 /// Returns `true` if the selectors [a] and [b] are equivalent. | 142 /// Returns `true` if the selectors [a] and [b] are equivalent. |
104 bool areSelectorsEquivalent(Selector a, Selector b) { | 143 bool areSelectorsEquivalent(Selector a, Selector b) { |
105 if (identical(a, b)) return true; | 144 if (identical(a, b)) return true; |
106 if (a == null || b == null) return false; | 145 if (a == null || b == null) return false; |
107 return a.kind == b.kind && | 146 return a.kind == b.kind && |
108 a.callStructure == b.callStructure && | 147 a.callStructure == b.callStructure && |
109 areNamesEquivalent(a.memberName, b.memberName); | 148 areNamesEquivalent(a.memberName, b.memberName); |
110 } | 149 } |
111 | 150 |
112 /// Returns `true` if the names [a] and [b] are equivalent. | 151 /// Returns `true` if the names [a] and [b] are equivalent. |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 [bool elementEquivalence(a, b) = equality]) { | 339 [bool elementEquivalence(a, b) = equality]) { |
301 return areListsEquivalent(list1, list2, elementEquivalence); | 340 return areListsEquivalent(list1, list2, elementEquivalence); |
302 } | 341 } |
303 | 342 |
304 bool testSets( | 343 bool testSets( |
305 var object1, var object2, String property, Iterable set1, Iterable set2, | 344 var object1, var object2, String property, Iterable set1, Iterable set2, |
306 [bool elementEquivalence(a, b) = equality]) { | 345 [bool elementEquivalence(a, b) = equality]) { |
307 return areSetsEquivalent(set1, set2, elementEquivalence); | 346 return areSetsEquivalent(set1, set2, elementEquivalence); |
308 } | 347 } |
309 | 348 |
349 bool testMaps(var object1, var object2, String property, Map map1, Map map2, | |
350 [bool keyEquivalence(a, b) = equality, | |
351 bool valueEquivalence(a, b) = equality]) { | |
352 return areMapsEquivalent(map1, map2, keyEquivalence, valueEquivalence); | |
353 } | |
354 | |
310 bool testElements(Object object1, Object object2, String property, | 355 bool testElements(Object object1, Object object2, String property, |
311 Element element1, Element element2) { | 356 Element element1, Element element2) { |
312 return areElementsEquivalent(element1, element2); | 357 return areElementsEquivalent(element1, element2); |
313 } | 358 } |
314 | 359 |
315 bool testTypes(Object object1, Object object2, String property, | 360 bool testTypes(Object object1, Object object2, String property, |
316 DartType type1, DartType type2) { | 361 DartType type1, DartType type2) { |
317 return areTypesEquivalent(type1, type2); | 362 return areTypesEquivalent(type1, type2); |
318 } | 363 } |
319 | 364 |
320 bool testConstants(Object object1, Object object2, String property, | 365 bool testConstants(Object object1, Object object2, String property, |
321 ConstantExpression exp1, ConstantExpression exp2) { | 366 ConstantExpression exp1, ConstantExpression exp2) { |
322 return areConstantsEquivalent(exp1, exp2); | 367 return areConstantsEquivalent(exp1, exp2); |
323 } | 368 } |
324 | 369 |
370 bool testConstantValues(Object object1, Object object2, String property, | |
371 ConstantValue value1, ConstantValue value2) { | |
372 return areConstantValuesEquivalent(value1, value2); | |
373 } | |
374 | |
325 bool testTypeLists(Object object1, Object object2, String property, | 375 bool testTypeLists(Object object1, Object object2, String property, |
326 List<DartType> list1, List<DartType> list2) { | 376 List<DartType> list1, List<DartType> list2) { |
327 return areTypeListsEquivalent(list1, list2); | 377 return areTypeListsEquivalent(list1, list2); |
328 } | 378 } |
329 | 379 |
330 bool testConstantLists(Object object1, Object object2, String property, | 380 bool testConstantLists(Object object1, Object object2, String property, |
331 List<ConstantExpression> list1, List<ConstantExpression> list2) { | 381 List<ConstantExpression> list1, List<ConstantExpression> list2) { |
332 return areConstantListsEquivalent(list1, list2); | 382 return areConstantListsEquivalent(list1, list2); |
333 } | 383 } |
334 | 384 |
385 bool testConstantValueLists(Object object1, Object object2, String property, | |
386 List<ConstantValue> list1, List<ConstantValue> list2) { | |
387 return areConstantValueListsEquivalent(list1, list2); | |
388 } | |
389 | |
335 bool testNodes( | 390 bool testNodes( |
336 Object object1, Object object2, String property, Node node1, Node node2) { | 391 Object object1, Object object2, String property, Node node1, Node node2) { |
337 return areNodesEquivalent(node1, node2); | 392 return areNodesEquivalent(node1, node2); |
338 } | 393 } |
339 } | 394 } |
340 | 395 |
341 /// Visitor that checks for equivalence of [Element]s. | 396 /// Visitor that checks for equivalence of [Element]s. |
342 class ElementIdentityEquivalence extends BaseElementVisitor<bool, Element> { | 397 class ElementIdentityEquivalence extends BaseElementVisitor<bool, Element> { |
343 final TestStrategy strategy; | 398 final TestStrategy strategy; |
344 | 399 |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
773 @override | 828 @override |
774 bool visitStringLength(StringLengthConstantExpression exp1, | 829 bool visitStringLength(StringLengthConstantExpression exp1, |
775 StringLengthConstantExpression exp2) { | 830 StringLengthConstantExpression exp2) { |
776 return strategy.testConstants( | 831 return strategy.testConstants( |
777 exp1, exp2, 'expression', exp1.expression, exp2.expression); | 832 exp1, exp2, 'expression', exp1.expression, exp2.expression); |
778 } | 833 } |
779 | 834 |
780 @override | 835 @override |
781 bool visitDeferred( | 836 bool visitDeferred( |
782 DeferredConstantExpression exp1, DeferredConstantExpression exp2) { | 837 DeferredConstantExpression exp1, DeferredConstantExpression exp2) { |
783 // TODO(johnniwinther): Implement this. | 838 return strategy.testElements( |
839 exp1, exp2, 'prefix', exp1.prefix, exp2.prefix) && | |
840 strategy.testConstants( | |
841 exp1, exp2, 'expression', exp1.expression, exp2.expression); | |
842 } | |
843 } | |
844 | |
845 /// Visitor that checks for structural equivalence of [ConstantValue]s. | |
846 class ConstantValueEquivalence | |
847 implements ConstantValueVisitor<bool, ConstantValue> { | |
848 final TestStrategy strategy; | |
849 | |
850 const ConstantValueEquivalence([this.strategy = const TestStrategy()]); | |
851 | |
852 bool visit(ConstantValue value1, ConstantValue value2) { | |
853 if (identical(value1, value2)) return true; | |
854 return strategy.test(value1, value2, 'kind', value1.kind, value2.kind) && | |
855 value1.accept(this, value2); | |
856 } | |
857 | |
858 @override | |
859 bool visitConstructed( | |
860 ConstructedConstantValue value1, ConstructedConstantValue value2) { | |
861 return strategy.testTypes( | |
862 value1, value2, 'type', value1.type, value2.type) && | |
863 strategy.testMaps( | |
864 value1, | |
865 value2, | |
866 'fields', | |
867 value1.fields, | |
868 value2.fields, | |
869 areElementsEquivalent, | |
870 (a, b) => strategy.testConstantValues( | |
871 value1, value2, 'fields.values', a, b)); | |
872 } | |
873 | |
874 @override | |
875 bool visitFunction( | |
876 FunctionConstantValue value1, FunctionConstantValue value2) { | |
877 return strategy.testElements( | |
878 value1, value2, 'element', value1.element, value2.element); | |
879 } | |
880 | |
881 @override | |
882 bool visitList(ListConstantValue value1, ListConstantValue value2) { | |
883 return strategy.testTypes( | |
884 value1, value2, 'type', value1.type, value2.type) && | |
885 strategy.testConstantValueLists( | |
886 value1, value2, 'entries', value1.entries, value2.entries); | |
887 } | |
888 | |
889 @override | |
890 bool visitMap(MapConstantValue value1, MapConstantValue value2) { | |
891 return strategy.testTypes( | |
892 value1, value2, 'type', value1.type, value2.type) && | |
893 strategy.testConstantValueLists( | |
894 value1, value2, 'keys', value1.keys, value2.keys) && | |
895 strategy.testConstantValueLists( | |
896 value1, value2, 'values', value1.values, value2.values); | |
897 } | |
898 | |
899 @override | |
900 bool visitType(TypeConstantValue value1, TypeConstantValue value2) { | |
901 return strategy.testTypes(value1, value2, 'type', value1.type, value2.type); | |
902 } | |
903 | |
904 @override | |
905 bool visitBool(BoolConstantValue value1, BoolConstantValue value2) { | |
906 return strategy.test(value1, value2, 'primitiveValue', | |
907 value1.primitiveValue, value2.primitiveValue); | |
908 } | |
909 | |
910 @override | |
911 bool visitDouble(DoubleConstantValue value1, DoubleConstantValue value2) { | |
912 return strategy.test(value1, value2, 'primitiveValue', | |
913 value1.primitiveValue, value2.primitiveValue); | |
914 } | |
915 | |
916 @override | |
917 bool visitInt(IntConstantValue value1, IntConstantValue value2) { | |
918 return strategy.test(value1, value2, 'primitiveValue', | |
919 value1.primitiveValue, value2.primitiveValue); | |
920 } | |
921 | |
922 @override | |
923 bool visitNull(NullConstantValue value1, NullConstantValue value2) { | |
784 return true; | 924 return true; |
785 } | 925 } |
926 | |
927 @override | |
928 bool visitString(StringConstantValue value1, StringConstantValue value2) { | |
929 return strategy.test(value1, value2, 'primitiveValue', | |
930 value1.primitiveValue, value2.primitiveValue); | |
931 } | |
932 | |
933 @override | |
934 bool visitDeferred( | |
935 DeferredConstantValue value1, DeferredConstantValue value2) { | |
936 return strategy.testElements( | |
937 value1, value2, 'prefix', value1.prefix, value2.prefix) && | |
938 strategy.testConstantValues( | |
939 value1, value2, 'referenced', value1.referenced, value2.referenced); | |
940 } | |
941 | |
942 @override | |
943 bool visitNonConstant(NonConstantValue value1, NonConstantValue value2) { | |
944 return true; | |
945 } | |
946 | |
947 @override | |
948 bool visitSynthetic( | |
949 SyntheticConstantValue value1, SyntheticConstantValue value2) { | |
950 return strategy.test( | |
951 value1, value2, 'payload', value1.payload, value2.payload) && | |
952 strategy.test( | |
953 value1, value2, 'valueKind', value1.valueKind, value2.valueKind); | |
954 } | |
955 | |
956 @override | |
957 bool visitInterceptor( | |
958 InterceptorConstantValue value1, InterceptorConstantValue value2) { | |
959 return strategy.testTypes(value1, value2, 'payload', value1.dispatchedType, | |
Harry Terkelsen
2016/08/01 17:42:23
payload -> dispatchedType
Johnni Winther
2016/08/08 11:38:33
Done.
| |
960 value2.dispatchedType); | |
961 } | |
786 } | 962 } |
787 | 963 |
788 /// Tests the equivalence of [impact1] and [impact2] using [strategy]. | 964 /// Tests the equivalence of [impact1] and [impact2] using [strategy]. |
789 bool testResolutionImpactEquivalence( | 965 bool testResolutionImpactEquivalence( |
790 ResolutionImpact impact1, ResolutionImpact impact2, | 966 ResolutionImpact impact1, ResolutionImpact impact2, |
791 [TestStrategy strategy = const TestStrategy()]) { | 967 [TestStrategy strategy = const TestStrategy()]) { |
792 return strategy.testSets(impact1, impact2, 'constSymbolNames', | 968 return strategy.testSets(impact1, impact2, 'constSymbolNames', |
793 impact1.constSymbolNames, impact2.constSymbolNames) && | 969 impact1.constSymbolNames, impact2.constSymbolNames) && |
794 strategy.testSets( | 970 strategy.testSets( |
795 impact1, | 971 impact1, |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1850 } | 2026 } |
1851 | 2027 |
1852 bool areMetadataAnnotationsEquivalent( | 2028 bool areMetadataAnnotationsEquivalent( |
1853 MetadataAnnotation metadata1, MetadataAnnotation metadata2) { | 2029 MetadataAnnotation metadata1, MetadataAnnotation metadata2) { |
1854 if (metadata1 == metadata2) return true; | 2030 if (metadata1 == metadata2) return true; |
1855 if (metadata1 == null || metadata2 == null) return false; | 2031 if (metadata1 == null || metadata2 == null) return false; |
1856 return areElementsEquivalent( | 2032 return areElementsEquivalent( |
1857 metadata1.annotatedElement, metadata2.annotatedElement) && | 2033 metadata1.annotatedElement, metadata2.annotatedElement) && |
1858 areConstantsEquivalent(metadata1.constant, metadata2.constant); | 2034 areConstantsEquivalent(metadata1.constant, metadata2.constant); |
1859 } | 2035 } |
OLD | NEW |