Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Unified Diff: frog/leg/ssa/closure.dart

Issue 9359011: Capture this. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Make this-capture work in the context of constructors. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « frog/leg/ssa/builder.dart ('k') | frog/tests/leg_only/src/ClosureCapture3Test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/leg/ssa/closure.dart
diff --git a/frog/leg/ssa/closure.dart b/frog/leg/ssa/closure.dart
index f8b6143d5019e017d1157caa41c86c5e1a8357c9..d0b8f95d44b459c8ff1b91b48dd5c624efe84925 100644
--- a/frog/leg/ssa/closure.dart
+++ b/frog/leg/ssa/closure.dart
@@ -27,6 +27,9 @@ class ClosureData {
final ClassElement globalizedClosureElement;
// The callElement will be null for methods that are not local closures.
final FunctionElement callElement;
+ // The [thisElement] makes handling 'this' easier by treating it like any
+ // other argument. It is only set for instance-members.
+ final Element thisElement;
// Maps free locals, arguments and function elements to their captured
// copies.
@@ -46,7 +49,7 @@ class ClosureData {
final Set<Element> usedVariablesInTry;
- ClosureData(this.globalizedClosureElement, this.callElement)
+ ClosureData(this.globalizedClosureElement, this.callElement, this.thisElement)
: this.freeVariableMapping = new Map<Element, Element>(),
this.capturedFieldMapping = new Map<Element, Element>(),
this.capturingScopes = new Map<Node, ClosureScope>(),
@@ -187,10 +190,8 @@ class ClosureTranslator extends AbstractVisitor {
}
visitIdentifier(Identifier node) {
- // TODO(floitsch): handle 'this'.
- if (node.isThis() && insideClosure) {
- compiler.unimplemented("ClosureAnalyzer.visitIdentifier this-capture",
- node: node);
+ if (node.isThis()) {
+ useLocal(closureData.thisElement);
}
node.visitChildren(this);
}
@@ -199,10 +200,9 @@ class ClosureTranslator extends AbstractVisitor {
Element element = elements[node];
if (Elements.isLocal(element)) {
useLocal(element);
- } else if (element === null && node.receiver === null) {
- if (insideClosure) {
- compiler.unimplemented("ClosureTranslator.visitSend this-capture");
- }
+ } else if (node.receiver === null &&
+ Elements.isInstanceSend(node, elements)) {
+ useLocal(closureData.thisElement);
}
node.visitChildren(this);
}
@@ -263,10 +263,14 @@ class ClosureTranslator extends AbstractVisitor {
ClassElement objectClass =
compiler.coreLibrary.find(const SourceString('Object'));
globalizedElement.supertype = new SimpleType(Types.OBJECT, objectClass);
- return new ClosureData(globalizedElement, callElement);
+ // The nested function's 'this' is the same as the one for the outer
+ // function. It could be [null] if we are inside a static method.
+ Element thisElement = closureData.thisElement;
+ return new ClosureData(globalizedElement, callElement, thisElement);
}
visitFunctionExpression(FunctionExpression node) {
+ FunctionElement element = elements[node];
bool isClosure = (closureData !== null);
if (isClosure) closures.add(node);
@@ -279,14 +283,38 @@ class ClosureTranslator extends AbstractVisitor {
insideClosure = isClosure;
currentFunctionElement = elements[node];
- closureData = insideClosure ?
- globalizeClosure(node) :
- new ClosureData(null, null);
+ if (insideClosure) {
+ closureData = globalizeClosure(node);
+ } else {
+ Element thisElement = null;
+ // TODO(floitsch): we should not need to look for generative constructors.
+ // At the moment we store only one ClosureData for both the factory and
+ // the body.
+ if (element.isInstanceMember() ||
+ element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
+ // TODO(floitsch): currently all variables are considered to be
+ // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'.
+ Element thisEnclosingElement = element;
+ if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
+ ConstructorBodyElement body = element;
+ thisEnclosingElement = body.constructor;
+ }
+ thisElement = new Element(const SourceString("this"),
+ ElementKind.PARAMETER,
+ thisEnclosingElement);
+ }
+ closureData = new ClosureData(null, null, thisElement);
+ }
scopeVariables = new List<Element>();
// TODO(floitsch): a named function is visible from inside itself. Add
// the element to the block.
+ // We have to declare the implicit 'this' parameter.
+ if (!insideClosure && closureData.thisElement !== null) {
+ declareLocal(closureData.thisElement);
+ }
+
node.visitChildren(this);
attachCapturedScopeVariables(node);
« no previous file with comments | « frog/leg/ssa/builder.dart ('k') | frog/tests/leg_only/src/ClosureCapture3Test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698