| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 closureToClassMapper; | 5 library closureToClassMapper; |
| 6 | 6 |
| 7 import "elements/elements.dart"; | 7 import "elements/elements.dart"; |
| 8 import "dart2jslib.dart"; | 8 import "dart2jslib.dart"; |
| 9 import "dart_types.dart"; | 9 import "dart_types.dart"; |
| 10 import "scanner/scannerlib.dart" show Token; | 10 import "scanner/scannerlib.dart" show Token; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 190 |
| 191 DartType computeType(Compiler compiler) => compiler.types.dynamicType; | 191 DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
| 192 | 192 |
| 193 // Since there is no declaration corresponding to 'this', use the position of | 193 // Since there is no declaration corresponding to 'this', use the position of |
| 194 // the enclosing method. | 194 // the enclosing method. |
| 195 Token position() => enclosingElement.position(); | 195 Token position() => enclosingElement.position(); |
| 196 | 196 |
| 197 accept(ElementVisitor visitor) => visitor.visitThisElement(this); | 197 accept(ElementVisitor visitor) => visitor.visitThisElement(this); |
| 198 } | 198 } |
| 199 | 199 |
| 200 // TODO(ahe): These classes continuously cause problems. We need to | |
| 201 // move these classes to elements/modelx.dart or see if we can find a | |
| 202 // more general solution. | |
| 203 class CheckVariableElement extends ElementX { | |
| 204 Element parameter; | |
| 205 CheckVariableElement(String name, this.parameter, Element enclosing) | |
| 206 : super(name, ElementKind.VARIABLE, enclosing); | |
| 207 | |
| 208 DartType computeType(Compiler compiler) => compiler.types.dynamicType; | |
| 209 | |
| 210 // Since there is no declaration for the synthetic 'check' variable, use | |
| 211 // parameter. | |
| 212 Token position() => parameter.position(); | |
| 213 | |
| 214 accept(ElementVisitor visitor) => visitor.visitCheckVariableElement(this); | |
| 215 } | |
| 216 | |
| 217 // The box-element for a scope, and the captured variables that need to be | 200 // The box-element for a scope, and the captured variables that need to be |
| 218 // stored in the box. | 201 // stored in the box. |
| 219 class ClosureScope { | 202 class ClosureScope { |
| 220 Element boxElement; | 203 Element boxElement; |
| 221 Map<Element, Element> capturedVariableMapping; | 204 Map<Element, Element> capturedVariableMapping; |
| 222 // If the scope is attached to a [For] contains the variables that are | 205 // If the scope is attached to a [For] contains the variables that are |
| 223 // declared in the initializer of the [For] and that need to be boxed. | 206 // declared in the initializer of the [For] and that need to be boxed. |
| 224 // Otherwise contains the empty List. | 207 // Otherwise contains the empty List. |
| 225 List<Element> boxedLoopVariables; | 208 List<Element> boxedLoopVariables; |
| 226 | 209 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 this.closureClassElement, | 247 this.closureClassElement, |
| 265 this.callElement, | 248 this.callElement, |
| 266 this.thisElement) | 249 this.thisElement) |
| 267 : this.freeVariableMapping = new Map<Element, Element>(), | 250 : this.freeVariableMapping = new Map<Element, Element>(), |
| 268 this.capturedFieldMapping = new Map<Element, Element>(), | 251 this.capturedFieldMapping = new Map<Element, Element>(), |
| 269 this.capturingScopes = new Map<Node, ClosureScope>(), | 252 this.capturingScopes = new Map<Node, ClosureScope>(), |
| 270 this.usedVariablesInTry = new Set<Element>(); | 253 this.usedVariablesInTry = new Set<Element>(); |
| 271 | 254 |
| 272 bool isClosure() => closureElement != null; | 255 bool isClosure() => closureElement != null; |
| 273 | 256 |
| 274 bool isVariableCaptured(Element element) { | |
| 275 return freeVariableMapping.containsKey(element) | |
| 276 || capturingScopesBox(element); | |
| 277 } | |
| 278 | |
| 279 bool capturingScopesBox(Element element) { | 257 bool capturingScopesBox(Element element) { |
| 280 return capturingScopes.values.any((scope) { | 258 return capturingScopes.values.any((scope) { |
| 281 return scope.boxedLoopVariables.contains(element); | 259 return scope.boxedLoopVariables.contains(element); |
| 282 }); | 260 }); |
| 283 } | 261 } |
| 284 | 262 |
| 285 bool isVariableBoxed(Element element) { | 263 bool isVariableBoxed(Element element) { |
| 286 Element copy = freeVariableMapping[element]; | 264 Element copy = freeVariableMapping[element]; |
| 287 if (copy != null && !copy.isMember()) return true; | 265 if (copy != null && !copy.isMember()) return true; |
| 288 return capturingScopesBox(element); | 266 return capturingScopesBox(element); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 300 | 278 |
| 301 void forEachBoxedVariable(void f(Element local, Element field)) { | 279 void forEachBoxedVariable(void f(Element local, Element field)) { |
| 302 freeVariableMapping.forEach((variable, copy) { | 280 freeVariableMapping.forEach((variable, copy) { |
| 303 if (!isVariableBoxed(variable)) return; | 281 if (!isVariableBoxed(variable)) return; |
| 304 f(variable, copy); | 282 f(variable, copy); |
| 305 }); | 283 }); |
| 306 capturingScopes.values.forEach((scope) { | 284 capturingScopes.values.forEach((scope) { |
| 307 scope.capturedVariableMapping.forEach(f); | 285 scope.capturedVariableMapping.forEach(f); |
| 308 }); | 286 }); |
| 309 } | 287 } |
| 310 | |
| 311 void forEachNonBoxedCapturedVariable(void f(Element local, Element field)) { | |
| 312 freeVariableMapping.forEach((variable, copy) { | |
| 313 if (variable is BoxElement) return; | |
| 314 if (isVariableBoxed(variable)) return; | |
| 315 f(variable, copy); | |
| 316 }); | |
| 317 } | |
| 318 } | 288 } |
| 319 | 289 |
| 320 class ClosureTranslator extends Visitor { | 290 class ClosureTranslator extends Visitor { |
| 321 final Compiler compiler; | 291 final Compiler compiler; |
| 322 final TreeElements elements; | 292 final TreeElements elements; |
| 323 int closureFieldCounter = 0; | 293 int closureFieldCounter = 0; |
| 324 int boxedFieldCounter = 0; | 294 int boxedFieldCounter = 0; |
| 325 bool inTryStatement = false; | 295 bool inTryStatement = false; |
| 326 final Map<Node, ClosureClassMap> closureMappingCache; | 296 final Map<Node, ClosureClassMap> closureMappingCache; |
| 327 | 297 |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 840 } | 810 } |
| 841 | 811 |
| 842 visitTryStatement(TryStatement node) { | 812 visitTryStatement(TryStatement node) { |
| 843 // TODO(ngeoffray): implement finer grain state. | 813 // TODO(ngeoffray): implement finer grain state. |
| 844 bool oldInTryStatement = inTryStatement; | 814 bool oldInTryStatement = inTryStatement; |
| 845 inTryStatement = true; | 815 inTryStatement = true; |
| 846 node.visitChildren(this); | 816 node.visitChildren(this); |
| 847 inTryStatement = oldInTryStatement; | 817 inTryStatement = oldInTryStatement; |
| 848 } | 818 } |
| 849 } | 819 } |
| OLD | NEW |