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 "js_backend/js_backend.dart" show JavaScriptBackend; | 10 import "js_backend/js_backend.dart" show JavaScriptBackend; |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 | 265 |
266 /// Call method of a closure class. | 266 /// Call method of a closure class. |
267 class SynthesizedCallMethodElementX extends BaseFunctionElementX { | 267 class SynthesizedCallMethodElementX extends BaseFunctionElementX { |
268 final LocalFunctionElement expression; | 268 final LocalFunctionElement expression; |
269 | 269 |
270 SynthesizedCallMethodElementX(String name, | 270 SynthesizedCallMethodElementX(String name, |
271 LocalFunctionElementX other, | 271 LocalFunctionElementX other, |
272 ClosureClassElement enclosing) | 272 ClosureClassElement enclosing) |
273 : expression = other, | 273 : expression = other, |
274 super(name, other.kind, other.modifiers, enclosing, false) { | 274 super(name, other.kind, other.modifiers, enclosing, false) { |
275 asyncMarker = other.asyncMarker; | |
275 functionSignatureCache = other.functionSignature; | 276 functionSignatureCache = other.functionSignature; |
276 } | 277 } |
277 | 278 |
278 /// Use [closureClass] instead. | 279 /// Use [closureClass] instead. |
279 @deprecated | 280 @deprecated |
280 get enclosingElement => super.enclosingElement; | 281 get enclosingElement => super.enclosingElement; |
281 | 282 |
282 ClosureClassElement get closureClass => super.enclosingElement; | 283 ClosureClassElement get closureClass => super.enclosingElement; |
283 | 284 |
284 MemberElement get memberContext { | 285 MemberElement get memberContext { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 final Map<Local, CapturedVariable> freeVariableMap = | 341 final Map<Local, CapturedVariable> freeVariableMap = |
341 new Map<Local, CapturedVariable>(); | 342 new Map<Local, CapturedVariable>(); |
342 | 343 |
343 // Maps [Loop] and [FunctionExpression] nodes to their | 344 // Maps [Loop] and [FunctionExpression] nodes to their |
344 // [ClosureScope] which contains their box and the | 345 // [ClosureScope] which contains their box and the |
345 // captured variables that are stored in the box. | 346 // captured variables that are stored in the box. |
346 // This map will be empty if the method/closure of this [ClosureData] does not | 347 // This map will be empty if the method/closure of this [ClosureData] does not |
347 // contain any nested closure. | 348 // contain any nested closure. |
348 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); | 349 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); |
349 | 350 |
350 final Set<Local> usedVariablesInTry = new Set<Local>(); | 351 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); |
floitsch
2015/02/02 22:00:06
Add comment.
Not every variable in a generator is
sigurdm
2015/02/03 16:59:27
Done.
| |
351 | 352 |
352 ClosureClassMap(this.closureElement, | 353 ClosureClassMap(this.closureElement, |
353 this.closureClassElement, | 354 this.closureClassElement, |
354 this.callElement, | 355 this.callElement, |
355 this.thisLocal); | 356 this.thisLocal); |
356 | 357 |
357 void addFreeVariable(Local element) { | 358 void addFreeVariable(Local element) { |
358 assert(freeVariableMap[element] == null); | 359 assert(freeVariableMap[element] == null); |
359 freeVariableMap[element] = null; | 360 freeVariableMap[element] = null; |
360 } | 361 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 }); | 421 }); |
421 } | 422 } |
422 } | 423 } |
423 | 424 |
424 class ClosureTranslator extends Visitor { | 425 class ClosureTranslator extends Visitor { |
425 final Compiler compiler; | 426 final Compiler compiler; |
426 final TreeElements elements; | 427 final TreeElements elements; |
427 int closureFieldCounter = 0; | 428 int closureFieldCounter = 0; |
428 int boxedFieldCounter = 0; | 429 int boxedFieldCounter = 0; |
429 bool inTryStatement = false; | 430 bool inTryStatement = false; |
431 | |
430 final Map<Node, ClosureClassMap> closureMappingCache; | 432 final Map<Node, ClosureClassMap> closureMappingCache; |
431 | 433 |
432 // Map of captured variables. Initially they will map to `null`. If | 434 // Map of captured variables. Initially they will map to `null`. If |
433 // a variable needs to be boxed then the scope declaring the variable | 435 // a variable needs to be boxed then the scope declaring the variable |
434 // will update this to mapping to the capturing [BoxFieldElement]. | 436 // will update this to mapping to the capturing [BoxFieldElement]. |
435 Map<Local, BoxFieldElement> _capturedVariableMapping = | 437 Map<Local, BoxFieldElement> _capturedVariableMapping = |
436 new Map<Local, BoxFieldElement>(); | 438 new Map<Local, BoxFieldElement>(); |
437 | 439 |
438 // List of encountered closures. | 440 // List of encountered closures. |
439 List<Expression> closures = <Expression>[]; | 441 List<Expression> closures = <Expression>[]; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
581 } | 583 } |
582 | 584 |
583 if (insideClosure && !inCurrentContext(variable)) { | 585 if (insideClosure && !inCurrentContext(variable)) { |
584 closureData.addFreeVariable(variable); | 586 closureData.addFreeVariable(variable); |
585 } else if (inTryStatement) { | 587 } else if (inTryStatement) { |
586 // Don't mark the this-element or a self-reference. This would complicate | 588 // Don't mark the this-element or a self-reference. This would complicate |
587 // things in the builder. | 589 // things in the builder. |
588 // Note that nested (named) functions are immutable. | 590 // Note that nested (named) functions are immutable. |
589 if (variable != closureData.thisLocal && | 591 if (variable != closureData.thisLocal && |
590 variable != closureData.closureElement) { | 592 variable != closureData.closureElement) { |
591 // TODO(ngeoffray): only do this if the variable is mutated. | 593 // TODO(ngeoffray): only do this if the variable is mutated. |
floitsch
2015/02/02 22:00:06
We should have an "isEffectivelyFinal" getter on v
sigurdm
2015/02/03 16:59:27
Done.
| |
592 closureData.usedVariablesInTry.add(variable); | 594 closureData.variablesUsedInTryOrGenerator.add(variable); |
593 } | 595 } |
596 } else if (variable is LocalParameterElement && | |
597 variable.functionDeclaration.asyncMarker == AsyncMarker.SYNC_STAR) { | |
598 // Parameters in a sync* function are shared between each Iterator created | |
599 // by the Iterable returned by the function, therefore they must be boxed. | |
600 // TODO(sigurdm): only do this if the variable is mutated. | |
601 closureData.variablesUsedInTryOrGenerator.add(variable); | |
594 } | 602 } |
595 } | 603 } |
596 | 604 |
597 void useTypeVariableAsLocal(TypeVariableType typeVariable) { | 605 void useTypeVariableAsLocal(TypeVariableType typeVariable) { |
598 useLocal(new TypeVariableLocal(typeVariable, outermostElement)); | 606 useLocal(new TypeVariableLocal(typeVariable, outermostElement)); |
599 } | 607 } |
600 | 608 |
601 void declareLocal(LocalVariableElement element) { | 609 void declareLocal(LocalVariableElement element) { |
602 scopeVariables.add(element); | 610 scopeVariables.add(element); |
603 } | 611 } |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1027 | 1035 |
1028 String get name => typeVariable.name; | 1036 String get name => typeVariable.name; |
1029 | 1037 |
1030 int get hashCode => typeVariable.hashCode; | 1038 int get hashCode => typeVariable.hashCode; |
1031 | 1039 |
1032 bool operator ==(other) { | 1040 bool operator ==(other) { |
1033 if (other is! TypeVariableLocal) return false; | 1041 if (other is! TypeVariableLocal) return false; |
1034 return typeVariable == other.typeVariable; | 1042 return typeVariable == other.typeVariable; |
1035 } | 1043 } |
1036 } | 1044 } |
OLD | NEW |