Index: lib/compiler/implementation/closure.dart |
=================================================================== |
--- lib/compiler/implementation/closure.dart (revision 11792) |
+++ lib/compiler/implementation/closure.dart (working copy) |
@@ -19,7 +19,7 @@ |
String get name => "Closure Simplifier"; |
ClosureClassMap computeClosureToClassMapping(FunctionExpression node, |
- TreeElements elements) { |
+ TreeElements elements) { |
return measure(() { |
ClosureClassMap cached = closureMappingCache[node]; |
if (cached !== null) return cached; |
@@ -141,6 +141,10 @@ |
final Set<Element> usedVariablesInTry; |
+ // A map from the parameter element to the variable element that |
+ // holds the sentinel check. |
+ final Map<Element, Element> parametersWithSentinel; |
+ |
ClosureClassMap(this.closureElement, |
this.closureClassElement, |
this.callElement, |
@@ -148,7 +152,8 @@ |
: this.freeVariableMapping = new Map<Element, Element>(), |
this.capturedFieldMapping = new Map<Element, Element>(), |
this.capturingScopes = new Map<Node, ClosureScope>(), |
- this.usedVariablesInTry = new Set<Element>(); |
+ this.usedVariablesInTry = new Set<Element>(), |
+ this.parametersWithSentinel = new Map<Element, Element>(); |
bool isClosure() => closureElement !== null; |
} |
@@ -312,6 +317,26 @@ |
useLocal(closureData.thisElement); |
} else if (node.isSuperCall) { |
useLocal(closureData.thisElement); |
+ } else if (node.isOperator |
+ && node.argumentsNode is Prefix |
+ && node.selector.source.stringValue == '?') { |
+ Element parameter = elements[node.receiver]; |
+ FunctionElement enclosing = parameter.enclosingElement; |
+ if (currentFunctionElement != enclosing) { |
+ // If the parameter is from an outer function, we need to put |
+ // the check in a field of the closure class. |
+ FunctionExpression node = enclosing.parseNode(compiler); |
+ ClosureClassMap cached = closureMappingCache[node]; |
+ if (!cached.parametersWithSentinel.containsKey(parameter)) { |
+ SourceString parameterName = parameter.name; |
+ String name = '${parameterName.slowToString()}_check'; |
kasperl
2012/09/04 10:50:08
Is it a problem if this conflicts with other param
ngeoffray
2012/09/04 10:53:44
No, the namer will disambiguate the elements.
|
+ Element newElement = new Element(new SourceString(name), |
+ ElementKind.VARIABLE, |
+ enclosing); |
+ useLocal(newElement); |
+ cached.parametersWithSentinel[parameter] = newElement; |
+ } |
+ } |
} |
node.visitChildren(this); |
} |
@@ -478,6 +503,7 @@ |
} |
closureData = new ClosureClassMap(null, null, null, thisElement); |
} |
+ closureMappingCache[node] = closureData; |
inNewScope(node, () { |
// We have to declare the implicit 'this' parameter. |
@@ -501,7 +527,6 @@ |
if (node.body !== null) node.body.accept(this); |
}); |
- closureMappingCache[node] = closureData; |
ClosureClassMap savedClosureData = closureData; |
bool savedInsideClosure = insideClosure; |