| 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 library kernel.transformations.mixin_full_resolution; | 4 library kernel.transformations.mixin_full_resolution; |
| 5 | 5 |
| 6 import '../ast.dart'; | 6 import '../ast.dart'; |
| 7 import '../class_hierarchy.dart'; | 7 import '../class_hierarchy.dart'; |
| 8 import '../clone.dart'; | 8 import '../clone.dart'; |
| 9 import '../core_types.dart'; | 9 import '../core_types.dart'; |
| 10 import '../target/targets.dart' show NoneTarget, Target; | 10 import '../target/targets.dart' show Target; |
| 11 import '../type_algebra.dart'; | 11 import '../type_algebra.dart'; |
| 12 | 12 |
| 13 Program transformProgram(Program program) { | 13 void transformLibraries(Target targetInfo, List<Library> libraries) { |
| 14 new MixinFullResolution(new NoneTarget(null)).transform(program); | 14 new MixinFullResolution(targetInfo).transform(libraries); |
| 15 return program; | |
| 16 } | 15 } |
| 17 | 16 |
| 18 /// Replaces all mixin applications with regular classes, cloning all fields | 17 /// Replaces all mixin applications with regular classes, cloning all fields |
| 19 /// and procedures from the mixed-in class, cloning all constructors from the | 18 /// and procedures from the mixed-in class, cloning all constructors from the |
| 20 /// base class. | 19 /// base class. |
| 21 /// | 20 /// |
| 22 /// Super calls (as well as super initializer invocations) are also resolved | 21 /// Super calls (as well as super initializer invocations) are also resolved |
| 23 /// to their targets in this pass. | 22 /// to their targets in this pass. |
| 24 class MixinFullResolution { | 23 class MixinFullResolution { |
| 25 final Target targetInfo; | 24 final Target targetInfo; |
| 26 | 25 |
| 27 ClassHierarchy hierarchy; | 26 ClassHierarchy hierarchy; |
| 28 CoreTypes coreTypes; | 27 CoreTypes coreTypes; |
| 29 | 28 |
| 30 MixinFullResolution(this.targetInfo); | 29 MixinFullResolution(this.targetInfo); |
| 31 | 30 |
| 32 void transform(Program program) { | 31 /// Transform the given new [libraries]. It is expected that all other |
| 32 /// libraries have already been transformed. |
| 33 void transform(List<Library> libraries) { |
| 34 if (libraries.isEmpty) return; |
| 35 |
| 33 var transformedClasses = new Set<Class>(); | 36 var transformedClasses = new Set<Class>(); |
| 34 | 37 |
| 35 // Desugar all mixin application classes by copying in fields/methods from | 38 // Desugar all mixin application classes by copying in fields/methods from |
| 36 // the mixin and constructors from the base class. | 39 // the mixin and constructors from the base class. |
| 37 var processedClasses = new Set<Class>(); | 40 var processedClasses = new Set<Class>(); |
| 38 for (var library in program.libraries) { | 41 for (var library in libraries) { |
| 39 if (library.isExternal) continue; | 42 if (library.isExternal) continue; |
| 40 | 43 |
| 41 for (var class_ in library.classes) { | 44 for (var class_ in library.classes) { |
| 42 transformClass(processedClasses, transformedClasses, class_); | 45 transformClass(libraries, processedClasses, transformedClasses, class_); |
| 43 } | 46 } |
| 44 } | 47 } |
| 45 | 48 |
| 49 // TODO(scheglov) Remove "program" once we switch to creating "hierarchy" |
| 50 // and "coreTypes" outside and passing into the transformers. |
| 51 var program = libraries.first.enclosingProgram; |
| 46 hierarchy = new ClassHierarchy(program); | 52 hierarchy = new ClassHierarchy(program); |
| 47 coreTypes = new CoreTypes(program); | 53 coreTypes = new CoreTypes(program); |
| 48 | 54 |
| 49 // Resolve all super call expressions and super initializers. | 55 // Resolve all super call expressions and super initializers. |
| 50 for (var library in program.libraries) { | 56 for (var library in libraries) { |
| 51 if (library.isExternal) continue; | 57 if (library.isExternal) continue; |
| 52 | 58 |
| 53 for (var class_ in library.classes) { | 59 for (var class_ in library.classes) { |
| 54 final bool hasTransformedSuperclass = | 60 final bool hasTransformedSuperclass = |
| 55 transformedClasses.contains(class_.superclass); | 61 transformedClasses.contains(class_.superclass); |
| 56 | 62 |
| 57 for (var procedure in class_.procedures) { | 63 for (var procedure in class_.procedures) { |
| 58 if (procedure.containsSuperCalls) { | 64 if (procedure.containsSuperCalls) { |
| 59 new SuperCallResolutionTransformer( | 65 new SuperCallResolutionTransformer( |
| 60 hierarchy, coreTypes, class_.superclass, targetInfo) | 66 hierarchy, coreTypes, class_.superclass, targetInfo) |
| 61 .visit(procedure); | 67 .visit(procedure); |
| 62 } | 68 } |
| 63 } | 69 } |
| 64 for (var constructor in class_.constructors) { | 70 for (var constructor in class_.constructors) { |
| 65 if (constructor.containsSuperCalls) { | 71 if (constructor.containsSuperCalls) { |
| 66 new SuperCallResolutionTransformer( | 72 new SuperCallResolutionTransformer( |
| 67 hierarchy, coreTypes, class_.superclass, targetInfo) | 73 hierarchy, coreTypes, class_.superclass, targetInfo) |
| 68 .visit(constructor); | 74 .visit(constructor); |
| 69 } | 75 } |
| 70 if (hasTransformedSuperclass && constructor.initializers.length > 0) { | 76 if (hasTransformedSuperclass && constructor.initializers.length > 0) { |
| 71 new SuperInitializerResolutionTransformer(class_.superclass) | 77 new SuperInitializerResolutionTransformer(class_.superclass) |
| 72 .transformInitializers(constructor.initializers); | 78 .transformInitializers(constructor.initializers); |
| 73 } | 79 } |
| 74 } | 80 } |
| 75 } | 81 } |
| 76 } | 82 } |
| 77 } | 83 } |
| 78 | 84 |
| 79 transformClass(Set<Class> processedClasses, Set<Class> transformedClasses, | 85 transformClass( |
| 86 List<Library> librariesToBeTransformed, |
| 87 Set<Class> processedClasses, |
| 88 Set<Class> transformedClasses, |
| 80 Class class_) { | 89 Class class_) { |
| 81 // If this class was already handled then so were all classes up to the | 90 // If this class was already handled then so were all classes up to the |
| 82 // [Object] class. | 91 // [Object] class. |
| 83 if (!processedClasses.add(class_)) return; | 92 if (!processedClasses.add(class_)) return; |
| 84 | 93 |
| 85 // Ensure super classes have been transformed before this class. | 94 // Ensure super classes have been transformed before this class. |
| 86 if (class_.superclass != null && | 95 if (class_.superclass != null && |
| 87 class_.superclass.level.index >= ClassLevel.Mixin.index) { | 96 class_.superclass.level.index >= ClassLevel.Mixin.index) { |
| 88 transformClass(processedClasses, transformedClasses, class_.superclass); | 97 transformClass(librariesToBeTransformed, processedClasses, |
| 98 transformedClasses, class_.superclass); |
| 89 } | 99 } |
| 90 | 100 |
| 91 // If this is not a mixin application we don't need to make forwarding | 101 // If this is not a mixin application we don't need to make forwarding |
| 92 // constructors in this class. | 102 // constructors in this class. |
| 93 if (!class_.isMixinApplication) return; | 103 if (!class_.isMixinApplication) return; |
| 104 assert(librariesToBeTransformed.contains(class_.enclosingLibrary)); |
| 94 | 105 |
| 95 if (class_.mixedInClass.level.index < ClassLevel.Mixin.index) { | 106 if (class_.mixedInClass.level.index < ClassLevel.Mixin.index) { |
| 96 throw new Exception( | 107 throw new Exception( |
| 97 'Class "${class_.name}" mixes in "${class_.mixedInClass.name}" from' | 108 'Class "${class_.name}" mixes in "${class_.mixedInClass.name}" from' |
| 98 ' an external library. Did you forget --link?'); | 109 ' an external library. Did you forget --link?'); |
| 99 } | 110 } |
| 100 | 111 |
| 101 transformedClasses.add(class_); | 112 transformedClasses.add(class_); |
| 102 | 113 |
| 103 // Clone fields and methods from the mixin class. | 114 // Clone fields and methods from the mixin class. |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 return null; | 343 return null; |
| 333 } | 344 } |
| 334 } | 345 } |
| 335 | 346 |
| 336 throw new Exception( | 347 throw new Exception( |
| 337 'Could not find a generative constructor named "${constructor.name}" ' | 348 'Could not find a generative constructor named "${constructor.name}" ' |
| 338 'in lookup class "${lookupClass.name}"!'); | 349 'in lookup class "${lookupClass.name}"!'); |
| 339 } | 350 } |
| 340 } | 351 } |
| 341 } | 352 } |
| OLD | NEW |