Chromium Code Reviews| 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 Procedure, | 15 Procedure, |
| 16 ThisExpression, | 16 ThisExpression, |
| 17 TypeParameter, | 17 TypeParameter, |
| 18 TypeParameterType, | 18 TypeParameterType, |
| 19 VariableDeclaration, | 19 VariableDeclaration, |
| 20 VariableGet, | 20 VariableGet, |
| 21 VariableSet, | 21 VariableSet, |
| 22 visitList; | 22 visitList; |
| 23 | 23 |
| 24 import '../../visitor.dart' show RecursiveVisitor; | 24 import '../../visitor.dart' show RecursiveVisitor; |
| 25 | 25 |
| 26 class ClosureInfo extends RecursiveVisitor { | 26 class ClosureInfo extends RecursiveVisitor { |
| 27 FunctionNode currentFunction; | 27 FunctionNode currentFunction; |
| 28 | |
| 29 static const int OUTSIDE_INITIALIZER = 1; | |
| 30 static const int INSIDE_INITIALIZER = 2; | |
| 31 | |
| 32 int captureFlags = OUTSIDE_INITIALIZER; | |
| 33 | |
| 34 final Map<VariableDeclaration, int /*captured flags*/ > variables = | |
|
Dmitry Stefantsov
2017/07/31 15:05:35
I think a more elaborate comment about the flags,
sjindel
2017/07/31 15:32:16
Done.
| |
| 35 <VariableDeclaration, int>{}; | |
| 36 | |
| 28 final Map<VariableDeclaration, FunctionNode> function = | 37 final Map<VariableDeclaration, FunctionNode> function = |
| 29 <VariableDeclaration, FunctionNode>{}; | 38 <VariableDeclaration, FunctionNode>{}; |
| 30 | 39 |
| 31 final Set<VariableDeclaration> variables = new Set<VariableDeclaration>(); | |
| 32 | |
| 33 /// Map from functions to set of type variables captured within them. | 40 /// Map from functions to set of type variables captured within them. |
| 34 final Map<FunctionNode, Set<TypeParameter>> typeVariables = | 41 final Map<FunctionNode, Set<TypeParameter>> typeVariables = |
| 35 <FunctionNode, Set<TypeParameter>>{}; | 42 <FunctionNode, Set<TypeParameter>>{}; |
| 36 | 43 |
| 37 /// Map from members to synthetic variables for accessing `this` in a local | 44 /// Map from members to synthetic variables for accessing `this` in a local |
| 38 /// function. | 45 /// function. |
| 39 final Map<FunctionNode, VariableDeclaration> thisAccess = | 46 final Map<FunctionNode, VariableDeclaration> thisAccess = |
| 40 <FunctionNode, VariableDeclaration>{}; | 47 <FunctionNode, VariableDeclaration>{}; |
| 41 | 48 |
| 42 final Set<String> currentMemberLocalNames = new Set<String>(); | 49 final Set<String> currentMemberLocalNames = new Set<String>(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 /// the parameters that may be used in the initializers. If the nodes are | 107 /// the parameters that may be used in the initializers. If the nodes are |
| 101 /// visited in another order, the encountered parameters in initializers | 108 /// visited in another order, the encountered parameters in initializers |
| 102 /// are treated as captured, because they are not yet associated with the | 109 /// are treated as captured, because they are not yet associated with the |
| 103 /// function. | 110 /// function. |
| 104 beginMember(node, node.function); | 111 beginMember(node, node.function); |
| 105 saveCurrentFunction(() { | 112 saveCurrentFunction(() { |
| 106 currentFunction = currentMemberFunction; | 113 currentFunction = currentMemberFunction; |
| 107 | 114 |
| 108 visitList(node.annotations, this); | 115 visitList(node.annotations, this); |
| 109 node.name?.accept(this); | 116 node.name?.accept(this); |
| 110 node.function?.accept(this); | 117 |
| 118 visitList(node.function.typeParameters, this); | |
| 119 visitList(node.function.positionalParameters, this); | |
| 120 visitList(node.function.namedParameters, this); | |
| 121 | |
| 122 assert(captureFlags == OUTSIDE_INITIALIZER); | |
| 123 captureFlags = INSIDE_INITIALIZER; | |
| 111 visitList(node.initializers, this); | 124 visitList(node.initializers, this); |
| 125 captureFlags = OUTSIDE_INITIALIZER; | |
| 126 | |
| 127 node.function.accept(this); | |
|
Dmitry Stefantsov
2017/07/31 15:05:35
To this point, we've already visited [typeParamete
sjindel
2017/07/31 15:32:16
Yes, but I wrote it this way so if a new field is
Dmitry Stefantsov
2017/08/01 09:36:13
I guess it's ok to leave it like this, but conside
| |
| 112 }); | 128 }); |
| 113 endMember(); | 129 endMember(); |
| 114 } | 130 } |
| 115 | 131 |
| 116 visitProcedure(Procedure node) { | 132 visitProcedure(Procedure node) { |
| 117 beginMember(node, node.function); | 133 beginMember(node, node.function); |
| 118 super.visitProcedure(node); | 134 super.visitProcedure(node); |
| 119 endMember(); | 135 endMember(); |
| 120 } | 136 } |
| 121 | 137 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 174 } | 190 } |
| 175 } | 191 } |
| 176 | 192 |
| 177 visitVariableDeclaration(VariableDeclaration node) { | 193 visitVariableDeclaration(VariableDeclaration node) { |
| 178 function[node] = currentFunction; | 194 function[node] = currentFunction; |
| 179 node.visitChildren(this); | 195 node.visitChildren(this); |
| 180 } | 196 } |
| 181 | 197 |
| 182 visitVariableGet(VariableGet node) { | 198 visitVariableGet(VariableGet node) { |
| 183 if (function[node.variable] != currentFunction) { | 199 if (function[node.variable] != currentFunction) { |
| 184 variables.add(node.variable); | 200 variables.putIfAbsent(node.variable, () => 0); |
| 201 } | |
| 202 if (variables.containsKey(node.variable)) { | |
| 203 variables[node.variable] = variables[node.variable] | captureFlags; | |
|
Dmitry Stefantsov
2017/07/31 15:05:35
How about using `|=` operation here and below?
sjindel
2017/07/31 15:32:16
Done.
| |
| 185 } | 204 } |
| 186 node.visitChildren(this); | 205 node.visitChildren(this); |
| 187 } | 206 } |
| 188 | 207 |
| 189 visitVariableSet(VariableSet node) { | 208 visitVariableSet(VariableSet node) { |
| 190 if (function[node.variable] != currentFunction) { | 209 if (function[node.variable] != currentFunction) { |
| 191 variables.add(node.variable); | 210 variables.putIfAbsent(node.variable, () => 0); |
| 211 } | |
| 212 if (variables.containsKey(node.variable)) { | |
| 213 variables[node.variable] = variables[node.variable] | captureFlags; | |
| 192 } | 214 } |
| 193 node.visitChildren(this); | 215 node.visitChildren(this); |
| 194 } | 216 } |
| 195 | 217 |
| 196 visitTypeParameterType(TypeParameterType node) { | 218 visitTypeParameterType(TypeParameterType node) { |
| 197 if (!isOuterMostContext && node.parameter.parent != currentFunction) { | 219 if (!isOuterMostContext && node.parameter.parent != currentFunction) { |
| 198 typeVariables | 220 typeVariables |
| 199 .putIfAbsent(currentFunction, () => new Set<TypeParameter>()) | 221 .putIfAbsent(currentFunction, () => new Set<TypeParameter>()) |
| 200 .add(node.parameter); | 222 .add(node.parameter); |
| 201 } | 223 } |
| 202 } | 224 } |
| 203 | 225 |
| 204 visitThisExpression(ThisExpression node) { | 226 visitThisExpression(ThisExpression node) { |
| 205 if (!isOuterMostContext) { | 227 if (!isOuterMostContext) { |
| 206 thisAccess.putIfAbsent( | 228 thisAccess.putIfAbsent( |
| 207 currentMemberFunction, () => new VariableDeclaration("#self")); | 229 currentMemberFunction, () => new VariableDeclaration("#self")); |
| 208 } | 230 } |
| 209 } | 231 } |
| 210 | 232 |
| 211 saveCurrentFunction(void f()) { | 233 saveCurrentFunction(void f()) { |
| 212 var saved = currentFunction; | 234 var saved = currentFunction; |
| 213 try { | 235 try { |
| 214 f(); | 236 f(); |
| 215 } finally { | 237 } finally { |
| 216 currentFunction = saved; | 238 currentFunction = saved; |
| 217 } | 239 } |
| 218 } | 240 } |
| 219 } | 241 } |
| OLD | NEW |