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 '../common/resolution.dart'; | 9 import '../common/resolution.dart'; |
10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
13 import '../elements/visitor.dart'; | 13 import '../elements/visitor.dart'; |
| 14 import '../resolution/access_semantics.dart'; |
14 import '../resolution/send_structure.dart'; | 15 import '../resolution/send_structure.dart'; |
15 import '../resolution/tree_elements.dart'; | 16 import '../resolution/tree_elements.dart'; |
16 import '../tokens/token.dart'; | 17 import '../tokens/token.dart'; |
17 import '../tree/nodes.dart'; | 18 import '../tree/nodes.dart'; |
18 import '../universe/selector.dart'; | 19 import '../universe/selector.dart'; |
19 import '../universe/use.dart'; | 20 import '../universe/use.dart'; |
20 import 'resolved_ast_serialization.dart'; | 21 import 'resolved_ast_serialization.dart'; |
21 | 22 |
22 /// Equality based equivalence function. | 23 /// Equality based equivalence function. |
23 bool equality(a, b) => a == b; | 24 bool equality(a, b) => a == b; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 a.isEmpty == b.isEmpty; | 132 a.isEmpty == b.isEmpty; |
132 } | 133 } |
133 | 134 |
134 /// Returns `true` if the map literal uses [a] and [b] are equivalent. | 135 /// Returns `true` if the map literal uses [a] and [b] are equivalent. |
135 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { | 136 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { |
136 return areTypesEquivalent(a.type, b.type) && | 137 return areTypesEquivalent(a.type, b.type) && |
137 a.isConstant == b.isConstant && | 138 a.isConstant == b.isConstant && |
138 a.isEmpty == b.isEmpty; | 139 a.isEmpty == b.isEmpty; |
139 } | 140 } |
140 | 141 |
| 142 /// Returns `true` if the access semantics [a] and [b] are equivalent. |
| 143 bool areAccessSemanticsEquivalent(AccessSemantics a, AccessSemantics b) { |
| 144 if (a.kind != b.kind) return false; |
| 145 switch (a.kind) { |
| 146 case AccessKind.EXPRESSION: |
| 147 case AccessKind.THIS: |
| 148 // No additional properties. |
| 149 return true; |
| 150 case AccessKind.THIS_PROPERTY: |
| 151 case AccessKind.DYNAMIC_PROPERTY: |
| 152 case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY: |
| 153 return areNamesEquivalent(a.name, b.name); |
| 154 case AccessKind.CLASS_TYPE_LITERAL: |
| 155 case AccessKind.TYPEDEF_TYPE_LITERAL: |
| 156 case AccessKind.DYNAMIC_TYPE_LITERAL: |
| 157 return areConstantsEquivalent(a.constant, b.constant); |
| 158 case AccessKind.LOCAL_FUNCTION: |
| 159 case AccessKind.LOCAL_VARIABLE: |
| 160 case AccessKind.FINAL_LOCAL_VARIABLE: |
| 161 case AccessKind.PARAMETER: |
| 162 case AccessKind.FINAL_PARAMETER: |
| 163 case AccessKind.STATIC_FIELD: |
| 164 case AccessKind.FINAL_STATIC_FIELD: |
| 165 case AccessKind.STATIC_METHOD: |
| 166 case AccessKind.STATIC_GETTER: |
| 167 case AccessKind.STATIC_SETTER: |
| 168 case AccessKind.TOPLEVEL_FIELD: |
| 169 case AccessKind.FINAL_TOPLEVEL_FIELD: |
| 170 case AccessKind.TOPLEVEL_METHOD: |
| 171 case AccessKind.TOPLEVEL_GETTER: |
| 172 case AccessKind.TOPLEVEL_SETTER: |
| 173 case AccessKind.SUPER_FIELD: |
| 174 case AccessKind.SUPER_FINAL_FIELD: |
| 175 case AccessKind.SUPER_METHOD: |
| 176 case AccessKind.SUPER_GETTER: |
| 177 case AccessKind.SUPER_SETTER: |
| 178 case AccessKind.TYPE_PARAMETER_TYPE_LITERAL: |
| 179 case AccessKind.UNRESOLVED: |
| 180 case AccessKind.UNRESOLVED_SUPER: |
| 181 case AccessKind.INVALID: |
| 182 return areElementsEquivalent(a.element, b.element); |
| 183 case AccessKind.COMPOUND: |
| 184 CompoundAccessSemantics compoundAccess1 = a; |
| 185 CompoundAccessSemantics compoundAccess2 = b; |
| 186 return compoundAccess1.compoundAccessKind == |
| 187 compoundAccess2.compoundAccessKind && |
| 188 areElementsEquivalent( |
| 189 compoundAccess1.getter, compoundAccess2.getter) && |
| 190 areElementsEquivalent(compoundAccess1.setter, compoundAccess2.setter); |
| 191 case AccessKind.CONSTANT: |
| 192 throw new UnsupportedError('Unsupported access kind: ${a.kind}'); |
| 193 } |
| 194 } |
| 195 |
141 /// Returns `true` if the send structures [a] and [b] are equivalent. | 196 /// Returns `true` if the send structures [a] and [b] are equivalent. |
142 bool areSendStructuresEquivalent(SendStructure a, SendStructure b) { | 197 bool areSendStructuresEquivalent(SendStructure a, SendStructure b) { |
143 if (identical(a, b)) return true; | 198 if (identical(a, b)) return true; |
144 if (a == null || b == null) return false; | 199 if (a == null || b == null) return false; |
145 if (a.kind != b.kind) return false; | 200 if (a.kind != b.kind) return false; |
146 // TODO(johnniwinther): Compute a deep equivalence. | 201 |
147 return true; | 202 var ad = a; |
| 203 var bd = b; |
| 204 switch (a.kind) { |
| 205 case SendStructureKind.IF_NULL: |
| 206 case SendStructureKind.LOGICAL_AND: |
| 207 case SendStructureKind.LOGICAL_OR: |
| 208 case SendStructureKind.NOT: |
| 209 case SendStructureKind.INVALID_UNARY: |
| 210 case SendStructureKind.INVALID_BINARY: |
| 211 // No additional properties. |
| 212 return true; |
| 213 |
| 214 case SendStructureKind.IS: |
| 215 case SendStructureKind.IS_NOT: |
| 216 case SendStructureKind.AS: |
| 217 return areTypesEquivalent(ad.type, bd.type); |
| 218 |
| 219 case SendStructureKind.INVOKE: |
| 220 case SendStructureKind.INCOMPATIBLE_INVOKE: |
| 221 if (!areSelectorsEquivalent(ad.selector, bd.selector)) return false; |
| 222 continue semantics; |
| 223 |
| 224 case SendStructureKind.UNARY: |
| 225 case SendStructureKind.BINARY: |
| 226 case SendStructureKind.PREFIX: |
| 227 case SendStructureKind.POSTFIX: |
| 228 case SendStructureKind.INDEX_PREFIX: |
| 229 case SendStructureKind.INDEX_POSTFIX: |
| 230 case SendStructureKind.COMPOUND: |
| 231 case SendStructureKind.COMPOUND_INDEX_SET: |
| 232 if (ad.operator != bd.operator) return false; |
| 233 continue semantics; |
| 234 |
| 235 case SendStructureKind.DEFERRED_PREFIX: |
| 236 return areElementsEquivalent(ad.prefix, bd.prefix) && |
| 237 areSendStructuresEquivalent(ad.sendStructure, bd.sendStructure); |
| 238 |
| 239 semantics: case SendStructureKind.GET: |
| 240 case SendStructureKind.SET: |
| 241 case SendStructureKind.INDEX: |
| 242 case SendStructureKind.INDEX_SET: |
| 243 case SendStructureKind.EQUALS: |
| 244 case SendStructureKind.NOT_EQUALS: |
| 245 case SendStructureKind.SET_IF_NULL: |
| 246 case SendStructureKind.INDEX_SET_IF_NULL: |
| 247 return areAccessSemanticsEquivalent(ad.semantics, bd.semantics); |
| 248 } |
| 249 throw new UnsupportedError('Unexpected send structures $a vs $b'); |
148 } | 250 } |
149 | 251 |
150 /// Returns `true` if the new structures [a] and [b] are equivalent. | 252 /// Returns `true` if the new structures [a] and [b] are equivalent. |
151 bool areNewStructuresEquivalent(NewStructure a, NewStructure b) { | 253 bool areNewStructuresEquivalent(NewStructure a, NewStructure b) { |
152 if (identical(a, b)) return true; | 254 if (identical(a, b)) return true; |
153 if (a == null || b == null) return false; | 255 if (a == null || b == null) return false; |
154 if (a.kind != b.kind) return false; | 256 if (a.kind != b.kind) return false; |
155 // TODO(johnniwinther): Compute a deep equivalence. | 257 |
156 return true; | 258 var ad = a; |
| 259 var bd = b; |
| 260 switch (a.kind) { |
| 261 case NewStructureKind.NEW_INVOKE: |
| 262 return ad.semantics.kind == bd.semantics.kind && |
| 263 areElementsEquivalent(ad.semantics.element, bd.semantics.element) && |
| 264 areTypesEquivalent(ad.semantics.type, bd.semantics.type) && |
| 265 areSelectorsEquivalent(ad.selector, bd.selector); |
| 266 case NewStructureKind.CONST_INVOKE: |
| 267 return ad.constantInvokeKind == bd.constantInvokeKind && |
| 268 areConstantsEquivalent(ad.constant, bd.constant); |
| 269 case NewStructureKind.LATE_CONST: |
| 270 throw new UnsupportedError('Unsupported NewStructure kind ${a.kind}.'); |
| 271 } |
157 } | 272 } |
158 | 273 |
159 /// Strategy for testing equivalence. | 274 /// Strategy for testing equivalence. |
160 /// | 275 /// |
161 /// Use this strategy to determine equivalence without failing on inequivalence. | 276 /// Use this strategy to determine equivalence without failing on inequivalence. |
162 class TestStrategy { | 277 class TestStrategy { |
163 const TestStrategy(); | 278 const TestStrategy(); |
164 | 279 |
165 bool test(var object1, var object2, String property, var value1, var value2, | 280 bool test(var object1, var object2, String property, var value1, var value2, |
166 [bool equivalence(a, b) = equality]) { | 281 [bool equivalence(a, b) = equality]) { |
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 int index = indices1.nodeIndices[node1]; | 913 int index = indices1.nodeIndices[node1]; |
799 RedirectingFactoryBody node2 = indices2.nodeList[index]; | 914 RedirectingFactoryBody node2 = indices2.nodeList[index]; |
800 success = strategy.testElements( | 915 success = strategy.testElements( |
801 node1, | 916 node1, |
802 node2, | 917 node2, |
803 'getRedirectingTargetConstructor($index)', | 918 'getRedirectingTargetConstructor($index)', |
804 elements1.getRedirectingTargetConstructor(node1), | 919 elements1.getRedirectingTargetConstructor(node1), |
805 elements2.getRedirectingTargetConstructor(node2)); | 920 elements2.getRedirectingTargetConstructor(node2)); |
806 } | 921 } |
807 } | 922 } |
OLD | NEW |