| 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 '../type_algebra.dart'; | 11 import '../type_algebra.dart'; |
| 11 | 12 |
| 12 Program transformProgram(Program program) { | 13 Program transformProgram(Program program) { |
| 13 new MixinFullResolution().transform(program); | 14 new MixinFullResolution(new NoneTarget(null)).transform(program); |
| 14 return program; | 15 return program; |
| 15 } | 16 } |
| 16 | 17 |
| 17 /// Replaces all mixin applications with regular classes, cloning all fields | 18 /// Replaces all mixin applications with regular classes, cloning all fields |
| 18 /// and procedures from the mixed-in class, cloning all constructors from the | 19 /// and procedures from the mixed-in class, cloning all constructors from the |
| 19 /// base class. | 20 /// base class. |
| 20 /// | 21 /// |
| 21 /// Super calls (as well as super initializer invocations) are also resolved | 22 /// Super calls (as well as super initializer invocations) are also resolved |
| 22 /// to their targets in this pass. | 23 /// to their targets in this pass. |
| 23 class MixinFullResolution { | 24 class MixinFullResolution { |
| 25 final Target targetInfo; |
| 26 |
| 24 ClassHierarchy hierarchy; | 27 ClassHierarchy hierarchy; |
| 25 CoreTypes coreTypes; | 28 CoreTypes coreTypes; |
| 26 | 29 |
| 30 MixinFullResolution(this.targetInfo); |
| 31 |
| 27 void transform(Program program) { | 32 void transform(Program program) { |
| 28 var transformedClasses = new Set<Class>(); | 33 var transformedClasses = new Set<Class>(); |
| 29 | 34 |
| 30 // Desugar all mixin application classes by copying in fields/methods from | 35 // Desugar all mixin application classes by copying in fields/methods from |
| 31 // the mixin and constructors from the base class. | 36 // the mixin and constructors from the base class. |
| 32 var processedClasses = new Set<Class>(); | 37 var processedClasses = new Set<Class>(); |
| 33 for (var library in program.libraries) { | 38 for (var library in program.libraries) { |
| 34 if (library.isExternal) continue; | 39 if (library.isExternal) continue; |
| 35 | 40 |
| 36 for (var class_ in library.classes) { | 41 for (var class_ in library.classes) { |
| 37 transformClass(processedClasses, transformedClasses, class_); | 42 transformClass(processedClasses, transformedClasses, class_); |
| 38 } | 43 } |
| 39 } | 44 } |
| 40 | 45 |
| 41 hierarchy = new ClassHierarchy(program); | 46 hierarchy = new ClassHierarchy(program); |
| 42 coreTypes = new CoreTypes(program); | 47 coreTypes = new CoreTypes(program); |
| 43 | 48 |
| 44 // Resolve all super call expressions and super initializers. | 49 // Resolve all super call expressions and super initializers. |
| 45 for (var library in program.libraries) { | 50 for (var library in program.libraries) { |
| 46 if (library.isExternal) continue; | 51 if (library.isExternal) continue; |
| 47 | 52 |
| 48 for (var class_ in library.classes) { | 53 for (var class_ in library.classes) { |
| 49 final bool hasTransformedSuperclass = | 54 final bool hasTransformedSuperclass = |
| 50 transformedClasses.contains(class_.superclass); | 55 transformedClasses.contains(class_.superclass); |
| 51 | 56 |
| 52 for (var procedure in class_.procedures) { | 57 for (var procedure in class_.procedures) { |
| 53 if (procedure.containsSuperCalls) { | 58 if (procedure.containsSuperCalls) { |
| 54 new SuperCallResolutionTransformer( | 59 new SuperCallResolutionTransformer( |
| 55 hierarchy, coreTypes, class_.superclass) | 60 hierarchy, coreTypes, class_.superclass, targetInfo) |
| 56 .visit(procedure); | 61 .visit(procedure); |
| 57 } | 62 } |
| 58 } | 63 } |
| 59 for (var constructor in class_.constructors) { | 64 for (var constructor in class_.constructors) { |
| 60 if (constructor.containsSuperCalls) { | 65 if (constructor.containsSuperCalls) { |
| 61 new SuperCallResolutionTransformer( | 66 new SuperCallResolutionTransformer( |
| 62 hierarchy, coreTypes, class_.superclass) | 67 hierarchy, coreTypes, class_.superclass, targetInfo) |
| 63 .visit(constructor); | 68 .visit(constructor); |
| 64 } | 69 } |
| 65 if (hasTransformedSuperclass && constructor.initializers.length > 0) { | 70 if (hasTransformedSuperclass && constructor.initializers.length > 0) { |
| 66 new SuperInitializerResolutionTransformer(class_.superclass) | 71 new SuperInitializerResolutionTransformer(class_.superclass) |
| 67 .transformInitializers(constructor.initializers); | 72 .transformInitializers(constructor.initializers); |
| 68 } | 73 } |
| 69 } | 74 } |
| 70 } | 75 } |
| 71 } | 76 } |
| 72 } | 77 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 return new Constructor(function, | 174 return new Constructor(function, |
| 170 name: superclassConstructor.name, | 175 name: superclassConstructor.name, |
| 171 initializers: <Initializer>[superInitializer]); | 176 initializers: <Initializer>[superInitializer]); |
| 172 } | 177 } |
| 173 } | 178 } |
| 174 | 179 |
| 175 class SuperCallResolutionTransformer extends Transformer { | 180 class SuperCallResolutionTransformer extends Transformer { |
| 176 final ClassHierarchy hierarchy; | 181 final ClassHierarchy hierarchy; |
| 177 final CoreTypes coreTypes; | 182 final CoreTypes coreTypes; |
| 178 final Class lookupClass; | 183 final Class lookupClass; |
| 184 final Target targetInfo; |
| 179 Constructor _invocationMirrorConstructor; // cached | 185 Constructor _invocationMirrorConstructor; // cached |
| 180 Procedure _listFrom; // cached | |
| 181 | 186 |
| 182 SuperCallResolutionTransformer( | 187 SuperCallResolutionTransformer( |
| 183 this.hierarchy, this.coreTypes, this.lookupClass); | 188 this.hierarchy, this.coreTypes, this.lookupClass, this.targetInfo); |
| 184 | 189 |
| 185 TreeNode visit(TreeNode node) => node.accept(this); | 190 TreeNode visit(TreeNode node) => node.accept(this); |
| 186 | 191 |
| 187 visitSuperPropertyGet(SuperPropertyGet node) { | 192 visitSuperPropertyGet(SuperPropertyGet node) { |
| 188 Member target = hierarchy.getDispatchTarget(lookupClass, node.name); | 193 Member target = hierarchy.getDispatchTarget(lookupClass, node.name); |
| 189 if (target != null) { | 194 if (target != null) { |
| 190 return new DirectPropertyGet(new ThisExpression(), target) | 195 return new DirectPropertyGet(new ThisExpression(), target) |
| 191 ..fileOffset = node.fileOffset; | 196 ..fileOffset = node.fileOffset; |
| 192 } else { | 197 } else { |
| 193 return _callNoSuchMethod(node.name.name, new Arguments.empty(), node, | 198 return _callNoSuchMethod(node.name.name, new Arguments.empty(), node, |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 } | 276 } |
| 272 | 277 |
| 273 /// Creates an "new _InvocationMirror(...)" invocation. | 278 /// Creates an "new _InvocationMirror(...)" invocation. |
| 274 ConstructorInvocation _createInvocation(String methodName, | 279 ConstructorInvocation _createInvocation(String methodName, |
| 275 Arguments callArguments, bool isSuperInvocation, Expression receiver) { | 280 Arguments callArguments, bool isSuperInvocation, Expression receiver) { |
| 276 if (_invocationMirrorConstructor == null) { | 281 if (_invocationMirrorConstructor == null) { |
| 277 Class clazz = coreTypes.getClass('dart:core', '_InvocationMirror'); | 282 Class clazz = coreTypes.getClass('dart:core', '_InvocationMirror'); |
| 278 _invocationMirrorConstructor = clazz.constructors[0]; | 283 _invocationMirrorConstructor = clazz.constructors[0]; |
| 279 } | 284 } |
| 280 | 285 |
| 281 // The _InvocationMirror constructor takes the following arguments: | 286 return targetInfo.instantiateInvocation(_invocationMirrorConstructor, |
| 282 // * Method name (a string). | 287 receiver, methodName, callArguments, -1, isSuperInvocation); |
| 283 // * An arguments descriptor - a list consisting of: | |
| 284 // - length of passed type argument vector, 0 if none passed. | |
| 285 // - number of arguments (including receiver). | |
| 286 // - number of positional arguments (including receiver). | |
| 287 // - pairs (2 entries in the list) of | |
| 288 // * named arguments name. | |
| 289 // * index of named argument in arguments list. | |
| 290 // * A list of arguments, where the first ones are the positional arguments. | |
| 291 // * Whether it's a super invocation or not. | |
| 292 | |
| 293 int typeArgsLen = 0; // TODO(regis): Type arguments of generic function. | |
| 294 int numPositionalArguments = callArguments.positional.length + 1; | |
| 295 int numArguments = numPositionalArguments + callArguments.named.length; | |
| 296 List<Expression> argumentsDescriptor = [ | |
| 297 new IntLiteral(typeArgsLen), | |
| 298 new IntLiteral(numArguments), | |
| 299 new IntLiteral(numPositionalArguments) | |
| 300 ]; | |
| 301 List<Expression> arguments = []; | |
| 302 arguments.add(receiver); | |
| 303 for (Expression pos in callArguments.positional) { | |
| 304 arguments.add(pos); | |
| 305 } | |
| 306 for (NamedExpression named in callArguments.named) { | |
| 307 argumentsDescriptor.add(new StringLiteral(named.name)); | |
| 308 argumentsDescriptor.add(new IntLiteral(arguments.length)); | |
| 309 arguments.add(named.value); | |
| 310 } | |
| 311 | |
| 312 return new ConstructorInvocation( | |
| 313 _invocationMirrorConstructor, | |
| 314 new Arguments([ | |
| 315 new StringLiteral(methodName), | |
| 316 _fixedLengthList(argumentsDescriptor), | |
| 317 _fixedLengthList(arguments), | |
| 318 new BoolLiteral(isSuperInvocation) | |
| 319 ])); | |
| 320 } | |
| 321 | |
| 322 /// Create a fixed length list containing given expressions. | |
| 323 Expression _fixedLengthList(List<Expression> list) { | |
| 324 _listFrom ??= coreTypes.getMember('dart:core', 'List', 'from'); | |
| 325 return new StaticInvocation( | |
| 326 _listFrom, | |
| 327 new Arguments([new ListLiteral(list)], | |
| 328 named: [new NamedExpression("growable", new BoolLiteral(false))], | |
| 329 types: [const DynamicType()])); | |
| 330 } | 288 } |
| 331 | 289 |
| 332 /// Check that a call to the targetFunction is legal given the arguments. | 290 /// Check that a call to the targetFunction is legal given the arguments. |
| 333 /// | 291 /// |
| 334 /// I.e. check that the number of positional parameters and the names of the | 292 /// I.e. check that the number of positional parameters and the names of the |
| 335 /// given named parameters represents a valid call to the function. | 293 /// given named parameters represents a valid call to the function. |
| 336 bool _callIsLegal(FunctionNode targetFunction, Arguments arguments) { | 294 bool _callIsLegal(FunctionNode targetFunction, Arguments arguments) { |
| 337 if ((targetFunction.requiredParameterCount > arguments.positional.length) || | 295 if ((targetFunction.requiredParameterCount > arguments.positional.length) || |
| 338 (targetFunction.positionalParameters.length < | 296 (targetFunction.positionalParameters.length < |
| 339 arguments.positional.length)) { | 297 arguments.positional.length)) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 return null; | 332 return null; |
| 375 } | 333 } |
| 376 } | 334 } |
| 377 | 335 |
| 378 throw new Exception( | 336 throw new Exception( |
| 379 'Could not find a generative constructor named "${constructor.name}" ' | 337 'Could not find a generative constructor named "${constructor.name}" ' |
| 380 'in lookup class "${lookupClass.name}"!'); | 338 'in lookup class "${lookupClass.name}"!'); |
| 381 } | 339 } |
| 382 } | 340 } |
| 383 } | 341 } |
| OLD | NEW |