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 library kernel.transformations.reify.transformation.transformer; | 5 library kernel.transformations.reify.transformation.transformer; |
6 | 6 |
7 import '../analysis/program_analysis.dart'; | 7 import '../analysis/program_analysis.dart'; |
8 import 'package:kernel/ast.dart'; | 8 import 'package:kernel/ast.dart'; |
9 import 'binding.dart' show RuntimeLibrary; | 9 import 'binding.dart' show RuntimeLibrary; |
10 import 'builder.dart' show RuntimeTypeSupportBuilder; | 10 import 'builder.dart' show RuntimeTypeSupportBuilder; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 ReifyVisitor(this.rtiLibrary, this.builder, this.knowledge, | 96 ReifyVisitor(this.rtiLibrary, this.builder, this.knowledge, |
97 [this.libraryToTransform]); | 97 [this.libraryToTransform]); |
98 | 98 |
99 /// If not null, the transformation will only be applied to classes declared | 99 /// If not null, the transformation will only be applied to classes declared |
100 /// in this library. | 100 /// in this library. |
101 final Library libraryToTransform; | 101 final Library libraryToTransform; |
102 | 102 |
103 // TODO(karlklose): find a way to get rid of this state in the visitor. | 103 // TODO(karlklose): find a way to get rid of this state in the visitor. |
104 TransformationContext context; | 104 TransformationContext context; |
105 | 105 |
| 106 static const String genericMethodTypeParametersName = r"$typeParameters"; |
| 107 |
106 bool libraryShouldBeTransformed(Library library) { | 108 bool libraryShouldBeTransformed(Library library) { |
107 return libraryToTransform == null || libraryToTransform == library; | 109 return libraryToTransform == null || libraryToTransform == library; |
108 } | 110 } |
109 | 111 |
110 bool needsTypeInformation(Class cls) { | 112 bool needsTypeInformation(Class cls) { |
111 return !isObject(cls) && | 113 return !isObject(cls) && |
112 !rtiLibrary.contains(cls) && | 114 !rtiLibrary.contains(cls) && |
113 libraryShouldBeTransformed(cls.enclosingLibrary); | 115 libraryShouldBeTransformed(cls.enclosingLibrary); |
114 } | 116 } |
115 | 117 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 | 175 |
174 Procedure target = invocation.target; | 176 Procedure target = invocation.target; |
175 if (target == rtiLibrary.reifyFunction) { | 177 if (target == rtiLibrary.reifyFunction) { |
176 /// Rewrite calls to reify(TypeLiteral) to a reified type. | 178 /// Rewrite calls to reify(TypeLiteral) to a reified type. |
177 TypeLiteral literal = invocation.arguments.positional.single; | 179 TypeLiteral literal = invocation.arguments.positional.single; |
178 return createRuntimeType(literal.type); | 180 return createRuntimeType(literal.type); |
179 } else if (target.kind == ProcedureKind.Factory) { | 181 } else if (target.kind == ProcedureKind.Factory) { |
180 // Intercept calls to factories of classes we do not transform | 182 // Intercept calls to factories of classes we do not transform |
181 return interceptInstantiation(invocation, target); | 183 return interceptInstantiation(invocation, target); |
182 } | 184 } |
| 185 |
| 186 addTypeArgumentToGenericInvocation(invocation); |
| 187 |
183 return invocation; | 188 return invocation; |
184 } | 189 } |
185 | 190 |
186 Library visitLibrary(Library library) { | 191 Library visitLibrary(Library library) { |
187 trace(library); | 192 trace(library); |
188 | 193 |
189 if (libraryShouldBeTransformed(library)) { | 194 if (libraryShouldBeTransformed(library)) { |
190 library.transformChildren(this); | 195 library.transformChildren(this); |
191 } | 196 } |
192 return library; | 197 return library; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 | 417 |
413 RuntimeTypeStorage access = context.runtimeTypeStorage; | 418 RuntimeTypeStorage access = context.runtimeTypeStorage; |
414 assert(access != RuntimeTypeStorage.none); | 419 assert(access != RuntimeTypeStorage.none); |
415 return access == RuntimeTypeStorage.field || | 420 return access == RuntimeTypeStorage.field || |
416 access == RuntimeTypeStorage.inheritedField; | 421 access == RuntimeTypeStorage.inheritedField; |
417 } | 422 } |
418 | 423 |
419 FunctionNode visitFunctionNode(FunctionNode node) { | 424 FunctionNode visitFunctionNode(FunctionNode node) { |
420 trace(node); | 425 trace(node); |
421 | 426 |
| 427 addTypeArgumentToGenericDeclaration(node); |
| 428 |
422 // If we have a [TransformationContext] with a runtime type field and we | 429 // If we have a [TransformationContext] with a runtime type field and we |
423 // translate a constructor or factory, we need a parameter that the code of | 430 // translate a constructor or factory, we need a parameter that the code of |
424 // initializers or the factory body can use to access type arguments. | 431 // initializers or the factory body can use to access type arguments. |
425 // The parameter field in the context will be reset in the visit-method of | 432 // The parameter field in the context will be reset in the visit-method of |
426 // the parent. | 433 // the parent. |
427 if (context != null && needsParameterForRuntimeType(node.parent)) { | 434 if (context != null && needsParameterForRuntimeType(node.parent)) { |
428 assert(context.parameter == null); | 435 assert(context.parameter == null); |
429 // Create the parameter and insert it as the function's first parameter. | 436 // Create the parameter and insert it as the function's first parameter. |
430 context.parameter = new VariableDeclaration( | 437 context.parameter = new VariableDeclaration( |
431 rtiLibrary.runtimeTypeName.name, | 438 rtiLibrary.runtimeTypeName.name, |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 } | 572 } |
566 | 573 |
567 Expression visitMapLiteral(MapLiteral node) { | 574 Expression visitMapLiteral(MapLiteral node) { |
568 trace(node); | 575 trace(node); |
569 node.transformChildren(this); | 576 node.transformChildren(this); |
570 return builder.callAttachType( | 577 return builder.callAttachType( |
571 node, | 578 node, |
572 new InterfaceType(builder.coreTypes.mapClass, | 579 new InterfaceType(builder.coreTypes.mapClass, |
573 <DartType>[node.keyType, node.valueType])); | 580 <DartType>[node.keyType, node.valueType])); |
574 } | 581 } |
| 582 |
| 583 Expression visitMethodInvocation(MethodInvocation node) { |
| 584 node.transformChildren(this); |
| 585 addTypeArgumentToGenericInvocation(node); |
| 586 return node; |
| 587 } |
| 588 |
| 589 bool isGenericMethod(FunctionNode node) { |
| 590 if (node.parent is Member) { |
| 591 Member member = node.parent; |
| 592 if (member is Constructor || |
| 593 member is Procedure && member.kind == ProcedureKind.Factory) { |
| 594 return member.enclosingClass.typeParameters.length < |
| 595 node.typeParameters.length; |
| 596 } |
| 597 } |
| 598 return node.typeParameters.isNotEmpty; |
| 599 } |
| 600 |
| 601 void addTypeArgumentToGenericInvocation(InvocationExpression expression) { |
| 602 if (expression.arguments.types.length > 0) { |
| 603 ListLiteral genericMethodTypeParameters = new ListLiteral( |
| 604 expression.arguments.types |
| 605 .map(createRuntimeType) |
| 606 .toList(growable: false), |
| 607 typeArgument: rtiLibrary.typeType); |
| 608 expression.arguments.named.add(new NamedExpression( |
| 609 genericMethodTypeParametersName, genericMethodTypeParameters) |
| 610 ..parent = expression.arguments); |
| 611 } |
| 612 } |
| 613 |
| 614 void addTypeArgumentToGenericDeclaration(FunctionNode node) { |
| 615 if (isGenericMethod(node)) { |
| 616 VariableDeclaration genericMethodTypeParameters = new VariableDeclaration( |
| 617 genericMethodTypeParametersName, |
| 618 type: new InterfaceType( |
| 619 builder.coreTypes.listClass, <DartType>[rtiLibrary.typeType])); |
| 620 genericMethodTypeParameters.parent = node; |
| 621 node.namedParameters.insert(0, genericMethodTypeParameters); |
| 622 } |
| 623 } |
575 } | 624 } |
OLD | NEW |