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.closure.converter; | 5 library kernel.transformations.closure.converter; |
6 | 6 |
7 import '../../ast.dart' | 7 import '../../ast.dart' |
8 show | 8 show |
9 Arguments, | 9 Arguments, |
10 Block, | 10 Block, |
11 Catch, | 11 Catch, |
12 Class, | 12 Class, |
13 ClosureCreation, | 13 ClosureCreation, |
14 Constructor, | 14 Constructor, |
15 DartType, | 15 DartType, |
16 DynamicType, | 16 DynamicType, |
17 EmptyStatement, | 17 EmptyStatement, |
18 Expression, | 18 Expression, |
19 ExpressionStatement, | 19 ExpressionStatement, |
20 Field, | 20 Field, |
21 FieldInitializer, | |
22 ForInStatement, | 21 ForInStatement, |
23 ForStatement, | 22 ForStatement, |
24 FunctionDeclaration, | 23 FunctionDeclaration, |
25 FunctionExpression, | 24 FunctionExpression, |
26 FunctionNode, | 25 FunctionNode, |
27 FunctionType, | 26 FunctionType, |
28 Initializer, | |
29 InterfaceType, | 27 InterfaceType, |
30 InvalidExpression, | 28 InvalidExpression, |
31 InvocationExpression, | 29 InvocationExpression, |
32 Let, | |
33 Library, | 30 Library, |
34 LocalInitializer, | 31 LocalInitializer, |
35 Member, | 32 Member, |
36 MethodInvocation, | 33 MethodInvocation, |
37 Name, | 34 Name, |
38 NamedExpression, | 35 NamedExpression, |
39 NamedType, | 36 NamedType, |
40 NullLiteral, | 37 NullLiteral, |
41 Procedure, | 38 Procedure, |
42 ProcedureKind, | 39 ProcedureKind, |
(...skipping 20 matching lines...) Expand all Loading... |
63 import '../../core_types.dart' show CoreTypes; | 60 import '../../core_types.dart' show CoreTypes; |
64 | 61 |
65 import '../../type_algebra.dart' show substitute; | 62 import '../../type_algebra.dart' show substitute; |
66 | 63 |
67 import 'clone_without_body.dart' show CloneWithoutBody; | 64 import 'clone_without_body.dart' show CloneWithoutBody; |
68 | 65 |
69 import 'context.dart' show Context, NoContext; | 66 import 'context.dart' show Context, NoContext; |
70 | 67 |
71 import 'info.dart' show ClosureInfo; | 68 import 'info.dart' show ClosureInfo; |
72 | 69 |
73 import 'rewriter.dart' | 70 import 'rewriter.dart' show AstRewriter, BlockRewriter, InitializerListRewriter; |
74 show | |
75 AstRewriter, | |
76 BlockRewriter, | |
77 InitializerRewriter, | |
78 FieldInitializerRewriter, | |
79 LocalInitializerRewriter; | |
80 | 71 |
81 class ClosureConverter extends Transformer { | 72 class ClosureConverter extends Transformer { |
82 final CoreTypes coreTypes; | 73 final CoreTypes coreTypes; |
83 final Set<VariableDeclaration> capturedVariables; | 74 final Set<VariableDeclaration> capturedVariables; |
84 final Map<FunctionNode, Set<TypeParameter>> capturedTypeVariables; | 75 final Map<FunctionNode, Set<TypeParameter>> capturedTypeVariables; |
85 final Map<FunctionNode, VariableDeclaration> thisAccess; | 76 final Map<FunctionNode, VariableDeclaration> thisAccess; |
86 final Map<FunctionNode, String> localNames; | 77 final Map<FunctionNode, String> localNames; |
87 | 78 |
88 /// Records place-holders for cloning contexts. See [visitForStatement]. | 79 /// Records place-holders for cloning contexts. See [visitForStatement]. |
89 final Set<InvalidExpression> contextClonePlaceHolders = | 80 final Set<InvalidExpression> contextClonePlaceHolders = |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 newClassMembers.forEach(node.addMember); | 185 newClassMembers.forEach(node.addMember); |
195 newClassMembers.clear(); | 186 newClassMembers.clear(); |
196 currentClass = null; | 187 currentClass = null; |
197 return node; | 188 return node; |
198 } | 189 } |
199 | 190 |
200 void extendContextWith(VariableDeclaration parameter) { | 191 void extendContextWith(VariableDeclaration parameter) { |
201 context.extend(parameter, new VariableGet(parameter)); | 192 context.extend(parameter, new VariableGet(parameter)); |
202 } | 193 } |
203 | 194 |
204 static InitializerRewriter getRewriterForInitializer( | |
205 Initializer initializer) { | |
206 if (initializer is FieldInitializer) { | |
207 return new FieldInitializerRewriter(initializer.value); | |
208 } | |
209 if (initializer is LocalInitializer) { | |
210 return new LocalInitializerRewriter(initializer.variable.initializer); | |
211 } | |
212 throw "Trying to extract an initializer expression from " | |
213 "${initializer.runtimeType}, but only FieldInitializer and " | |
214 "LocalInitializer are supported."; | |
215 } | |
216 | |
217 static Expression getInitializerExpression(Initializer initializer) { | |
218 if (initializer is FieldInitializer) { | |
219 return initializer.value; | |
220 } | |
221 if (initializer is LocalInitializer) { | |
222 return initializer.variable.initializer; | |
223 } | |
224 throw "Trying to get initializing expressino from " | |
225 "${initializer.runtimeType}, but only Field Initializer and " | |
226 "LocalInitializer are supported."; | |
227 } | |
228 | |
229 TreeNode visitConstructor(Constructor node) { | 195 TreeNode visitConstructor(Constructor node) { |
230 assert(isEmptyContext); | 196 assert(isEmptyContext); |
231 currentMember = node; | 197 currentMember = node; |
| 198 |
232 // Transform initializers. | 199 // Transform initializers. |
233 for (Initializer initializer in node.initializers) { | 200 if (node.initializers.length > 0) { |
234 if (initializer is FieldInitializer || initializer is LocalInitializer) { | 201 var initRewriter = new InitializerListRewriter(node); |
235 // Create a rewriter and a context for the initializer expression. | 202 rewriter = initRewriter; |
236 InitializerRewriter initializerRewriter = | 203 context = new NoContext(this); |
237 getRewriterForInitializer(initializer); | 204 |
238 rewriter = initializerRewriter; | 205 // TODO(karlklose): add a fine-grained analysis of captured parameters. |
239 context = new NoContext(this); | 206 node.function.positionalParameters |
240 // Save the expression to visit it in the extended context, since the | 207 .where(capturedVariables.contains) |
241 // rewriter will modify `initializer.value` (for [FieldInitializer]) or | 208 .forEach(extendContextWith); |
242 // `initializer.variable.initializer` (for [LocalInitializer]). | 209 node.function.namedParameters |
243 Expression initializerExpression = | 210 .where(capturedVariables.contains) |
244 getInitializerExpression(initializer); | 211 .forEach(extendContextWith); |
245 // Extend the context with all captured parameters of the constructor. | 212 |
246 // TODO(karlklose): add a fine-grained analysis of captured parameters. | 213 transformList(node.initializers, this, node); |
247 node.function.positionalParameters | 214 node.initializers.insertAll(0, initRewriter.prefix); |
248 .where(capturedVariables.contains) | 215 context = rewriter = null; |
249 .forEach(extendContextWith); | |
250 node.function.namedParameters | |
251 .where(capturedVariables.contains) | |
252 .forEach(extendContextWith); | |
253 // Transform the initializer expression. | |
254 var parent = initializerExpression.parent; | |
255 initializerExpression = initializerExpression.accept(this); | |
256 initializerExpression.parent = parent; | |
257 if (parent is Let) { | |
258 parent.body = initializerExpression; | |
259 } else if (parent is FieldInitializer) { | |
260 parent.value = initializerExpression; | |
261 } else if (parent is LocalInitializer) { | |
262 parent.variable.initializer = initializerExpression; | |
263 } else { | |
264 throw "Found unexpected node '${node.runtimeType}, expected a 'Let' " | |
265 ",a 'FieldInitializer', or a 'LocalInitializer'."; | |
266 } | |
267 } | |
268 } | 216 } |
269 rewriter = null; | 217 |
270 // Transform constructor body. | 218 // Transform constructor body. |
271 FunctionNode function = node.function; | 219 FunctionNode function = node.function; |
272 if (function.body != null && function.body is! EmptyStatement) { | 220 if (function.body != null && function.body is! EmptyStatement) { |
273 setupContextForFunctionBody(function); | 221 setupContextForFunctionBody(function); |
274 VariableDeclaration self = thisAccess[currentMemberFunction]; | 222 VariableDeclaration self = thisAccess[currentMemberFunction]; |
275 if (self != null) { | 223 if (self != null) { |
276 context.extend(self, new ThisExpression()); | 224 context.extend(self, new ThisExpression()); |
277 } | 225 } |
278 node.function.accept(this); | 226 node.function.accept(this); |
279 resetContext(); | 227 resetContext(); |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 // initializer, just use this variable name to put it into the context. | 482 // initializer, just use this variable name to put it into the context. |
535 context.extend(node, new VariableGet(node)); | 483 context.extend(node, new VariableGet(node)); |
536 } else { | 484 } else { |
537 context.extend(node, node.initializer ?? new NullLiteral()); | 485 context.extend(node, node.initializer ?? new NullLiteral()); |
538 } | 486 } |
539 | 487 |
540 if (node.parent == currentFunction) { | 488 if (node.parent == currentFunction) { |
541 return node; | 489 return node; |
542 } else { | 490 } else { |
543 assert(node.parent is Block); | 491 assert(node.parent is Block); |
544 // When returning null, the parent block will remove this node from its | 492 // When returning null, the parent block will remove |
545 // list of statements. | 493 // this node from its list of statements. |
546 return null; | 494 return null; |
547 } | 495 } |
548 } | 496 } |
549 | 497 |
550 TreeNode visitVariableGet(VariableGet node) { | 498 TreeNode visitVariableGet(VariableGet node) { |
551 return capturedVariables.contains(node.variable) | 499 return capturedVariables.contains(node.variable) |
552 ? context.lookup(node.variable) | 500 ? context.lookup(node.variable) |
553 : node; | 501 : node; |
554 } | 502 } |
555 | 503 |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
913 newClassMembers.add(tearOffMethod); | 861 newClassMembers.add(tearOffMethod); |
914 | 862 |
915 resetContext(); | 863 resetContext(); |
916 }); | 864 }); |
917 } finally { | 865 } finally { |
918 currentMember = oldCurrentMember; | 866 currentMember = oldCurrentMember; |
919 currentMemberFunction = oldCurrentMemberFunction; | 867 currentMemberFunction = oldCurrentMemberFunction; |
920 } | 868 } |
921 } | 869 } |
922 } | 870 } |
OLD | NEW |