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

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: 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') | no next file » | 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 eead9b947743bb1ceeaabe9ec24ac6aa3d5a3f88..d9b37eafe7ac3d18c725ee343412b3033391c8e2 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>(),
@@ -181,10 +184,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);
}
@@ -193,10 +194,11 @@ 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 &&
+ (element === null ||
ngeoffray 2012/02/08 12:37:58 Please add a: Elements.isUnbound(Send node, TreeE
floitsch 2012/02/08 13:17:07 Now uses isInstanceSend.
+ Elements.isInstanceField(element) ||
+ Elements.isInstanceMethod(element))) {
+ useLocal(closureData.thisElement);
}
node.visitChildren(this);
}
@@ -257,10 +259,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);
@@ -273,14 +279,30 @@ 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.
ngeoffray 2012/02/08 12:37:58 So why are we doing it?
floitsch 2012/02/08 13:17:07 updated comment.
+ if (element.isInstanceMember() ||
+ element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
+ thisElement = new VariableElement(const SourceString("this"),
ngeoffray 2012/02/08 12:37:58 new Element
floitsch 2012/02/08 13:17:07 Done.
+ null,
+ ElementKind.PARAMETER,
+ element);
+ }
+ 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') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698