| 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, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 import '../../core_types.dart' show CoreTypes; | 63 import '../../core_types.dart' show CoreTypes; |
| 64 | 64 |
| 65 import '../../type_algebra.dart' show substitute; | 65 import '../../type_algebra.dart' show substitute; |
| 66 | 66 |
| 67 import 'clone_without_body.dart' show CloneWithoutBody; | 67 import 'clone_without_body.dart' show CloneWithoutBody; |
| 68 | 68 |
| 69 import 'context.dart' show Context, NoContext; | 69 import 'context.dart' show Context, NoContext; |
| 70 | 70 |
| 71 import 'info.dart' show ClosureInfo; | 71 import 'info.dart' show ClosureInfo; |
| 72 | 72 |
| 73 import 'rewriter.dart' show AstRewriter, BlockRewriter, InitializerRewriter; | 73 import 'rewriter.dart' |
| 74 show |
| 75 AstRewriter, |
| 76 BlockRewriter, |
| 77 InitializerRewriter, |
| 78 FieldInitializerRewriter, |
| 79 LocalInitializerRewriter; |
| 74 | 80 |
| 75 class ClosureConverter extends Transformer { | 81 class ClosureConverter extends Transformer { |
| 76 final CoreTypes coreTypes; | 82 final CoreTypes coreTypes; |
| 77 final Set<VariableDeclaration> capturedVariables; | 83 final Set<VariableDeclaration> capturedVariables; |
| 78 final Map<FunctionNode, Set<TypeParameter>> capturedTypeVariables; | 84 final Map<FunctionNode, Set<TypeParameter>> capturedTypeVariables; |
| 79 final Map<FunctionNode, VariableDeclaration> thisAccess; | 85 final Map<FunctionNode, VariableDeclaration> thisAccess; |
| 80 final Map<FunctionNode, String> localNames; | 86 final Map<FunctionNode, String> localNames; |
| 81 | 87 |
| 82 /// Records place-holders for cloning contexts. See [visitForStatement]. | 88 /// Records place-holders for cloning contexts. See [visitForStatement]. |
| 83 final Set<InvalidExpression> contextClonePlaceHolders = | 89 final Set<InvalidExpression> contextClonePlaceHolders = |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 newClassMembers.forEach(node.addMember); | 194 newClassMembers.forEach(node.addMember); |
| 189 newClassMembers.clear(); | 195 newClassMembers.clear(); |
| 190 currentClass = null; | 196 currentClass = null; |
| 191 return node; | 197 return node; |
| 192 } | 198 } |
| 193 | 199 |
| 194 void extendContextWith(VariableDeclaration parameter) { | 200 void extendContextWith(VariableDeclaration parameter) { |
| 195 context.extend(parameter, new VariableGet(parameter)); | 201 context.extend(parameter, new VariableGet(parameter)); |
| 196 } | 202 } |
| 197 | 203 |
| 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 |
| 198 TreeNode visitConstructor(Constructor node) { | 229 TreeNode visitConstructor(Constructor node) { |
| 199 assert(isEmptyContext); | 230 assert(isEmptyContext); |
| 200 currentMember = node; | 231 currentMember = node; |
| 201 // Transform initializers. | 232 // Transform initializers. |
| 202 for (Initializer initializer in node.initializers) { | 233 for (Initializer initializer in node.initializers) { |
| 203 if (initializer is FieldInitializer) { | 234 if (initializer is FieldInitializer || initializer is LocalInitializer) { |
| 204 // Create a rewriter and a context for the initializer expression. | 235 // Create a rewriter and a context for the initializer expression. |
| 205 rewriter = new InitializerRewriter(initializer.value); | 236 InitializerRewriter initializerRewriter = |
| 237 getRewriterForInitializer(initializer); |
| 238 rewriter = initializerRewriter; |
| 206 context = new NoContext(this); | 239 context = new NoContext(this); |
| 207 // Save the expression to visit it in the extended context, since the | 240 // Save the expression to visit it in the extended context, since the |
| 208 // rewriter will modify `initializer.value`. | 241 // rewriter will modify `initializer.value` (for [FieldInitializer]) or |
| 209 Expression initializerExpression = initializer.value; | 242 // `initializer.variable.initializer` (for [LocalInitializer]). |
| 243 Expression initializerExpression = |
| 244 getInitializerExpression(initializer); |
| 210 // Extend the context with all captured parameters of the constructor. | 245 // Extend the context with all captured parameters of the constructor. |
| 211 // TODO(karlklose): add a fine-grained analysis of captured parameters. | 246 // TODO(karlklose): add a fine-grained analysis of captured parameters. |
| 212 node.function.positionalParameters | 247 node.function.positionalParameters |
| 213 .where(capturedVariables.contains) | 248 .where(capturedVariables.contains) |
| 214 .forEach(extendContextWith); | 249 .forEach(extendContextWith); |
| 215 node.function.namedParameters | 250 node.function.namedParameters |
| 216 .where(capturedVariables.contains) | 251 .where(capturedVariables.contains) |
| 217 .forEach(extendContextWith); | 252 .forEach(extendContextWith); |
| 218 // Transform the initializer expression. | 253 // Transform the initializer expression. |
| 219 var parent = initializerExpression.parent; | 254 var parent = initializerExpression.parent; |
| 220 initializerExpression = initializerExpression.accept(this); | 255 initializerExpression = initializerExpression.accept(this); |
| 221 initializerExpression.parent = parent; | 256 initializerExpression.parent = parent; |
| 222 if (parent is Let) { | 257 if (parent is Let) { |
| 223 parent.body = initializerExpression; | 258 parent.body = initializerExpression; |
| 224 } else if (parent is FieldInitializer) { | 259 } else if (parent is FieldInitializer) { |
| 225 parent.value = initializerExpression; | 260 parent.value = initializerExpression; |
| 261 } else if (parent is LocalInitializer) { |
| 262 parent.variable.initializer = initializerExpression; |
| 226 } else { | 263 } else { |
| 227 throw "Found unexpected node '${node.runtimeType}, expected a 'Let' " | 264 throw "Found unexpected node '${node.runtimeType}, expected a 'Let' " |
| 228 "or a 'FieldInitializer'."; | 265 ",a 'FieldInitializer', or a 'LocalInitializer'."; |
| 229 } | 266 } |
| 230 } | 267 } |
| 231 } | 268 } |
| 232 rewriter = null; | 269 rewriter = null; |
| 233 // Transform constructor body. | 270 // Transform constructor body. |
| 234 FunctionNode function = node.function; | 271 FunctionNode function = node.function; |
| 235 if (function.body != null && function.body is! EmptyStatement) { | 272 if (function.body != null && function.body is! EmptyStatement) { |
| 236 setupContextForFunctionBody(function); | 273 setupContextForFunctionBody(function); |
| 237 VariableDeclaration self = thisAccess[currentMemberFunction]; | 274 VariableDeclaration self = thisAccess[currentMemberFunction]; |
| 238 if (self != null) { | 275 if (self != null) { |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 newClassMembers.add(tearOffMethod); | 913 newClassMembers.add(tearOffMethod); |
| 877 | 914 |
| 878 resetContext(); | 915 resetContext(); |
| 879 }); | 916 }); |
| 880 } finally { | 917 } finally { |
| 881 currentMember = oldCurrentMember; | 918 currentMember = oldCurrentMember; |
| 882 currentMemberFunction = oldCurrentMemberFunction; | 919 currentMemberFunction = oldCurrentMemberFunction; |
| 883 } | 920 } |
| 884 } | 921 } |
| 885 } | 922 } |
| OLD | NEW |