Chromium Code Reviews| 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 switch (a.kind) { |
| 147 return true; | 202 case SendStructureKind.IF_NULL: |
| 203 case SendStructureKind.LOGICAL_AND: | |
| 204 case SendStructureKind.LOGICAL_OR: | |
| 205 case SendStructureKind.NOT: | |
| 206 case SendStructureKind.INVALID_UNARY: | |
| 207 case SendStructureKind.INVALID_BINARY: | |
| 208 // No additional properties. | |
| 209 return true; | |
| 210 case SendStructureKind.IS: | |
| 211 IsStructure structure1 = a; | |
| 212 IsStructure structure2 = b; | |
| 213 return areTypesEquivalent(structure1.type, structure1.type); | |
| 214 case SendStructureKind.IS_NOT: | |
| 215 IsNotStructure structure1 = a; | |
| 216 IsNotStructure structure2 = b; | |
| 217 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.
| |
| 218 case SendStructureKind.AS: | |
| 219 AsStructure structure1 = a; | |
| 220 AsStructure structure2 = b; | |
| 221 return areTypesEquivalent(structure1.type, structure1.type); | |
| 222 case SendStructureKind.INVOKE: | |
| 223 InvokeStructure structure1 = a; | |
| 224 InvokeStructure structure2 = b; | |
| 225 return areAccessSemanticsEquivalent( | |
| 226 structure1.semantics, structure2.semantics) && | |
| 227 areSelectorsEquivalent(structure1.selector, structure2.selector); | |
| 228 case SendStructureKind.INCOMPATIBLE_INVOKE: | |
| 229 IncompatibleInvokeStructure structure1 = a; | |
| 230 IncompatibleInvokeStructure structure2 = b; | |
| 231 return areAccessSemanticsEquivalent( | |
| 232 structure1.semantics, structure2.semantics) && | |
| 233 areSelectorsEquivalent(structure1.selector, structure2.selector); | |
| 234 case SendStructureKind.GET: | |
| 235 GetStructure structure1 = a; | |
| 236 GetStructure structure2 = b; | |
| 237 return areAccessSemanticsEquivalent( | |
| 238 structure1.semantics, structure2.semantics); | |
| 239 case SendStructureKind.SET: | |
| 240 SetStructure structure1 = a; | |
| 241 SetStructure structure2 = b; | |
| 242 return areAccessSemanticsEquivalent( | |
| 243 structure1.semantics, structure2.semantics); | |
| 244 case SendStructureKind.UNARY: | |
| 245 UnaryStructure structure1 = a; | |
| 246 UnaryStructure structure2 = b; | |
| 247 return areAccessSemanticsEquivalent( | |
| 248 structure1.semantics, structure2.semantics) && | |
| 249 structure1.operator == structure2.operator; | |
| 250 case SendStructureKind.INDEX: | |
| 251 IndexStructure structure1 = a; | |
| 252 IndexStructure structure2 = b; | |
| 253 return areAccessSemanticsEquivalent( | |
| 254 structure1.semantics, structure2.semantics); | |
| 255 case SendStructureKind.EQUALS: | |
| 256 EqualsStructure structure1 = a; | |
| 257 EqualsStructure structure2 = b; | |
| 258 return areAccessSemanticsEquivalent( | |
| 259 structure1.semantics, structure2.semantics); | |
| 260 case SendStructureKind.NOT_EQUALS: | |
| 261 NotEqualsStructure structure1 = a; | |
| 262 NotEqualsStructure structure2 = b; | |
| 263 return areAccessSemanticsEquivalent( | |
| 264 structure1.semantics, structure2.semantics); | |
| 265 case SendStructureKind.BINARY: | |
| 266 BinaryStructure structure1 = a; | |
| 267 BinaryStructure structure2 = b; | |
| 268 return areAccessSemanticsEquivalent( | |
| 269 structure1.semantics, structure2.semantics) && | |
| 270 structure1.operator == structure2.operator; | |
| 271 case SendStructureKind.INDEX_SET: | |
| 272 IndexSetStructure structure1 = a; | |
| 273 IndexSetStructure structure2 = b; | |
| 274 return areAccessSemanticsEquivalent( | |
| 275 structure1.semantics, structure2.semantics); | |
| 276 case SendStructureKind.INDEX_PREFIX: | |
| 277 IndexPrefixStructure structure1 = a; | |
| 278 IndexPrefixStructure structure2 = b; | |
| 279 return areAccessSemanticsEquivalent( | |
| 280 structure1.semantics, structure2.semantics) && | |
| 281 structure1.operator == structure2.operator; | |
| 282 case SendStructureKind.INDEX_POSTFIX: | |
| 283 IndexPostfixStructure structure1 = a; | |
| 284 IndexPostfixStructure structure2 = b; | |
| 285 return areAccessSemanticsEquivalent( | |
| 286 structure1.semantics, structure2.semantics) && | |
| 287 structure1.operator == structure2.operator; | |
| 288 case SendStructureKind.COMPOUND: | |
| 289 CompoundStructure structure1 = a; | |
| 290 CompoundStructure structure2 = b; | |
| 291 return areAccessSemanticsEquivalent( | |
| 292 structure1.semantics, structure2.semantics) && | |
| 293 structure1.operator == structure2.operator; | |
| 294 case SendStructureKind.SET_IF_NULL: | |
| 295 SetIfNullStructure structure1 = a; | |
| 296 SetIfNullStructure structure2 = b; | |
| 297 return areAccessSemanticsEquivalent( | |
| 298 structure1.semantics, structure2.semantics); | |
| 299 case SendStructureKind.COMPOUND_INDEX_SET: | |
| 300 CompoundIndexSetStructure structure1 = a; | |
| 301 CompoundIndexSetStructure structure2 = b; | |
| 302 return areAccessSemanticsEquivalent( | |
| 303 structure1.semantics, structure2.semantics) && | |
| 304 structure1.operator == structure2.operator; | |
| 305 case SendStructureKind.INDEX_SET_IF_NULL: | |
| 306 IndexSetIfNullStructure structure1 = a; | |
| 307 IndexSetIfNullStructure structure2 = b; | |
| 308 return areAccessSemanticsEquivalent( | |
| 309 structure1.semantics, structure2.semantics); | |
| 310 case SendStructureKind.PREFIX: | |
| 311 PrefixStructure structure1 = a; | |
| 312 PrefixStructure structure2 = b; | |
| 313 return areAccessSemanticsEquivalent( | |
| 314 structure1.semantics, structure2.semantics) && | |
| 315 structure1.operator == structure2.operator; | |
| 316 case SendStructureKind.POSTFIX: | |
| 317 PostfixStructure structure1 = a; | |
| 318 PostfixStructure structure2 = b; | |
| 319 return areAccessSemanticsEquivalent( | |
| 320 structure1.semantics, structure2.semantics) && | |
| 321 structure1.operator == structure2.operator; | |
| 322 case SendStructureKind.DEFERRED_PREFIX: | |
| 323 DeferredPrefixStructure structure1 = a; | |
| 324 DeferredPrefixStructure structure2 = b; | |
| 325 return areElementsEquivalent(structure1.prefix, structure2.prefix) && | |
| 326 areSendStructuresEquivalent( | |
| 327 structure1.sendStructure, structure2.sendStructure); | |
| 328 } | |
| 148 } | 329 } |
| 149 | 330 |
| 150 /// Returns `true` if the new structures [a] and [b] are equivalent. | 331 /// Returns `true` if the new structures [a] and [b] are equivalent. |
| 151 bool areNewStructuresEquivalent(NewStructure a, NewStructure b) { | 332 bool areNewStructuresEquivalent(NewStructure a, NewStructure b) { |
| 152 if (identical(a, b)) return true; | 333 if (identical(a, b)) return true; |
| 153 if (a == null || b == null) return false; | 334 if (a == null || b == null) return false; |
| 154 if (a.kind != b.kind) return false; | 335 if (a.kind != b.kind) return false; |
| 155 // TODO(johnniwinther): Compute a deep equivalence. | 336 switch (a.kind) { |
| 156 return true; | 337 case NewStructureKind.NEW_INVOKE: |
| 338 NewInvokeStructure structure1 = a; | |
| 339 NewInvokeStructure structure2 = b; | |
| 340 return structure1.semantics.kind == structure2.semantics.kind && | |
| 341 areElementsEquivalent( | |
| 342 structure1.semantics.element, structure2.semantics.element) && | |
| 343 areTypesEquivalent( | |
| 344 structure1.semantics.type, structure2.semantics.type) && | |
| 345 areSelectorsEquivalent(structure1.selector, structure2.selector); | |
| 346 case NewStructureKind.CONST_INVOKE: | |
| 347 ConstInvokeStructure structure1 = a; | |
| 348 ConstInvokeStructure structure2 = b; | |
| 349 return structure1.constantInvokeKind == structure2.constantInvokeKind && | |
| 350 areConstantsEquivalent(structure1.constant, structure2.constant); | |
| 351 case NewStructureKind.LATE_CONST: | |
| 352 throw new UnsupportedError('Unsupported NewStructure kind ${a.kind}.'); | |
| 353 } | |
| 157 } | 354 } |
| 158 | 355 |
| 159 /// Strategy for testing equivalence. | 356 /// Strategy for testing equivalence. |
| 160 /// | 357 /// |
| 161 /// Use this strategy to determine equivalence without failing on inequivalence. | 358 /// Use this strategy to determine equivalence without failing on inequivalence. |
| 162 class TestStrategy { | 359 class TestStrategy { |
| 163 const TestStrategy(); | 360 const TestStrategy(); |
| 164 | 361 |
| 165 bool test(var object1, var object2, String property, var value1, var value2, | 362 bool test(var object1, var object2, String property, var value1, var value2, |
| 166 [bool equivalence(a, b) = equality]) { | 363 [bool equivalence(a, b) = equality]) { |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 798 int index = indices1.nodeIndices[node1]; | 995 int index = indices1.nodeIndices[node1]; |
| 799 RedirectingFactoryBody node2 = indices2.nodeList[index]; | 996 RedirectingFactoryBody node2 = indices2.nodeList[index]; |
| 800 success = strategy.testElements( | 997 success = strategy.testElements( |
| 801 node1, | 998 node1, |
| 802 node2, | 999 node2, |
| 803 'getRedirectingTargetConstructor($index)', | 1000 'getRedirectingTargetConstructor($index)', |
| 804 elements1.getRedirectingTargetConstructor(node1), | 1001 elements1.getRedirectingTargetConstructor(node1), |
| 805 elements2.getRedirectingTargetConstructor(node2)); | 1002 elements2.getRedirectingTargetConstructor(node2)); |
| 806 } | 1003 } |
| 807 } | 1004 } |
| OLD | NEW |