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.info; | 5 library kernel.transformations.closure.info; |
6 | 6 |
7 import '../../ast.dart' | 7 import '../../ast.dart' |
8 show | 8 show |
9 Class, | 9 Class, |
10 Constructor, | 10 Constructor, |
11 Field, | 11 Field, |
12 FunctionDeclaration, | 12 FunctionDeclaration, |
13 FunctionNode, | 13 FunctionNode, |
14 Member, | 14 Member, |
15 Name, | 15 Name, |
16 Procedure, | 16 Procedure, |
17 ProcedureKind, | 17 ProcedureKind, |
18 PropertyGet, | 18 PropertyGet, |
19 ThisExpression, | 19 ThisExpression, |
20 TypeParameter, | 20 TypeParameter, |
21 TypeParameterType, | 21 TypeParameterType, |
22 VariableDeclaration, | 22 VariableDeclaration, |
23 VariableGet, | 23 VariableGet, |
24 VariableSet; | 24 VariableSet, |
| 25 visitList; |
25 | 26 |
26 import '../../visitor.dart' show RecursiveVisitor; | 27 import '../../visitor.dart' show RecursiveVisitor; |
27 | 28 |
28 class ClosureInfo extends RecursiveVisitor { | 29 class ClosureInfo extends RecursiveVisitor { |
29 FunctionNode currentFunction; | 30 FunctionNode currentFunction; |
30 final Map<VariableDeclaration, FunctionNode> function = | 31 final Map<VariableDeclaration, FunctionNode> function = |
31 <VariableDeclaration, FunctionNode>{}; | 32 <VariableDeclaration, FunctionNode>{}; |
32 | 33 |
33 final Set<VariableDeclaration> variables = new Set<VariableDeclaration>(); | 34 final Set<VariableDeclaration> variables = new Set<VariableDeclaration>(); |
34 | 35 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 /// /* Constructor body. */ | 113 /// /* Constructor body. */ |
113 /// } | 114 /// } |
114 /// } | 115 /// } |
115 /// | 116 /// |
116 /// Here the parameter shouldn't be captured into a context in the | 117 /// Here the parameter shouldn't be captured into a context in the |
117 /// initializer. However, [currentFunction] is `null` if not set, and | 118 /// initializer. However, [currentFunction] is `null` if not set, and |
118 /// `function[node.variable]` in this case points to the [FunctionNode] of | 119 /// `function[node.variable]` in this case points to the [FunctionNode] of |
119 /// the constructor (which is not `null`). It leads to `x` being treated as | 120 /// the constructor (which is not `null`). It leads to `x` being treated as |
120 /// captured, because it's seen as used outside of the function where it is | 121 /// captured, because it's seen as used outside of the function where it is |
121 /// declared. In turn, it leads to unnecessary context creation and usage. | 122 /// declared. In turn, it leads to unnecessary context creation and usage. |
| 123 /// |
| 124 /// We also need to visit the parameters to the function node before the |
| 125 /// initializer list. Since the default [visitChildren] method of |
| 126 /// [Constructor] will visit initializers first, we manually visit the |
| 127 /// parameters here. |
| 128 /// |
| 129 /// TODO(sjindel): Don't visit the parameters twice. |
| 130 /// |
122 beginMember(node, node.function); | 131 beginMember(node, node.function); |
123 saveCurrentFunction(() { | 132 saveCurrentFunction(() { |
124 currentFunction = currentMemberFunction; | 133 currentFunction = currentMemberFunction; |
| 134 visitList(node.function.positionalParameters, this); |
| 135 visitList(node.function.namedParameters, this); |
125 super.visitConstructor(node); | 136 super.visitConstructor(node); |
126 }); | 137 }); |
127 endMember(); | 138 endMember(); |
128 } | 139 } |
129 | 140 |
130 visitProcedure(Procedure node) { | 141 visitProcedure(Procedure node) { |
131 beginMember(node, node.function); | 142 beginMember(node, node.function); |
132 if (node.isInstanceMember && node.kind == ProcedureKind.Method) { | 143 if (node.isInstanceMember && node.kind == ProcedureKind.Method) { |
133 // Ignore the `length` method of [File] subclasses for now, as they | 144 // Ignore the `length` method of [File] subclasses for now, as they |
134 // will force us to rename the `length` getter (kernel issue #43). | 145 // will force us to rename the `length` getter (kernel issue #43). |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 | 247 |
237 saveCurrentFunction(void f()) { | 248 saveCurrentFunction(void f()) { |
238 var saved = currentFunction; | 249 var saved = currentFunction; |
239 try { | 250 try { |
240 f(); | 251 f(); |
241 } finally { | 252 } finally { |
242 currentFunction = saved; | 253 currentFunction = saved; |
243 } | 254 } |
244 } | 255 } |
245 } | 256 } |
OLD | NEW |