Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: pkg/kernel/lib/transformations/closure/converter.dart

Issue 2981603002: Convert closures in all initializers, and share the context between them. (Closed)
Patch Set: Change name of the argument extraction pass. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698