| 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 |