Chromium Code Reviews| Index: frog/leg/ssa/closure.dart |
| diff --git a/frog/leg/ssa/closure.dart b/frog/leg/ssa/closure.dart |
| index eead9b947743bb1ceeaabe9ec24ac6aa3d5a3f88..0dcd92612fe2b2b045b28f40b26197a158eb5c33 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,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)) { |
|
ngeoffray
2012/02/08 13:31:24
How about isThisSend in that case? It could also c
floitsch
2012/02/08 14:36:53
I prefer keeping it the way it is.
|
| + useLocal(closureData.thisElement); |
| } |
| node.visitChildren(this); |
| } |
| @@ -257,10 +257,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 +277,29 @@ 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 13:31:24
Improve comment?
floitsch
2012/02/08 14:36:53
Done.
|
| + if (element.isInstanceMember() || |
| + element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| + thisElement = new Element(const SourceString("this"), |
| + 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); |