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