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

Side by Side Diff: frog/leg/ssa/closure.dart

Issue 9378040: Allow self-referencing closures. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Revert last update to CL. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 class ClosureFieldElement extends Element { 5 class ClosureFieldElement extends Element {
6 ClosureFieldElement(SourceString name, ClassElement enclosing) 6 ClosureFieldElement(SourceString name, ClassElement enclosing)
7 : super(name, ElementKind.FIELD, enclosing); 7 : super(name, ElementKind.FIELD, enclosing);
8 8
9 bool isInstanceMember() => true; 9 bool isInstanceMember() => true;
10 bool isAssignable() => false; 10 bool isAssignable() => false;
11 11
12 String toString() => "ClosureFieldElement($name)"; 12 String toString() => "ClosureFieldElement($name)";
13 } 13 }
14 14
15 // The box-element for a scope, and the captured variables that need to be 15 // The box-element for a scope, and the captured variables that need to be
16 // stored in the box. 16 // stored in the box.
17 class ClosureScope { 17 class ClosureScope {
18 Element boxElement; 18 Element boxElement;
19 Map<Element, Element> capturedVariableMapping; 19 Map<Element, Element> capturedVariableMapping;
20 20
21 ClosureScope(this.boxElement, this.capturedVariableMapping); 21 ClosureScope(this.boxElement, this.capturedVariableMapping);
22 } 22 }
23 23
24 class ClosureData { 24 class ClosureData {
25 // The closure's or method's element before any translation.
26 final FunctionElement closureElement;
ngeoffray 2012/02/13 10:13:38 Should it just be null for non-closures?
floitsch 2012/02/13 12:03:42 Done.
25 // The globalizedClosureElement will be null for methods that are not local 27 // The globalizedClosureElement will be null for methods that are not local
26 // closures. 28 // closures.
27 final ClassElement globalizedClosureElement; 29 final ClassElement globalizedClosureElement;
ngeoffray 2012/02/13 10:13:38 How about renaming it to closureClassElement?
floitsch 2012/02/13 12:03:42 Done.
28 // The callElement will be null for methods that are not local closures. 30 // The callElement will be null for methods that are not local closures.
29 final FunctionElement callElement; 31 final FunctionElement callElement;
30 // The [thisElement] makes handling 'this' easier by treating it like any 32 // The [thisElement] makes handling 'this' easier by treating it like any
31 // other argument. It is only set for instance-members. 33 // other argument. It is only set for instance-members.
32 final Element thisElement; 34 final Element thisElement;
33 35
34 // Maps free locals, arguments and function elements to their captured 36 // Maps free locals, arguments and function elements to their captured
35 // copies. 37 // copies.
36 final Map<Element, Element> freeVariableMapping; 38 final Map<Element, Element> freeVariableMapping;
37 // Maps closure-fields to their captured elements. This is somehow the inverse 39 // Maps closure-fields to their captured elements. This is somehow the inverse
38 // mapping of [freeVariableMapping], but whereas [freeVariableMapping] does 40 // mapping of [freeVariableMapping], but whereas [freeVariableMapping] does
39 // not deal with boxes, here we map instance-fields (which might represent 41 // not deal with boxes, here we map instance-fields (which might represent
40 // boxes) to their boxElement. 42 // boxes) to their boxElement.
41 final Map<Element, Element> capturedFieldMapping; 43 final Map<Element, Element> capturedFieldMapping;
42 44
43 // Maps scopes ([Loop] and [FunctionExpression] nodes) to their 45 // Maps scopes ([Loop] and [FunctionExpression] nodes) to their
44 // [ClosureScope] which contains their box and the 46 // [ClosureScope] which contains their box and the
45 // captured variables that are stored in the box. 47 // captured variables that are stored in the box.
46 // This map will be empty if the method/closure of this [ClosureData] does not 48 // This map will be empty if the method/closure of this [ClosureData] does not
47 // contain any nested closure. 49 // contain any nested closure.
48 final Map<Node, ClosureScope> capturingScopes; 50 final Map<Node, ClosureScope> capturingScopes;
49 51
50 final Set<Element> usedVariablesInTry; 52 final Set<Element> usedVariablesInTry;
51 53
52 ClosureData(this.globalizedClosureElement, this.callElement, this.thisElement) 54 ClosureData(this.closureElement,
55 this.globalizedClosureElement,
56 this.callElement,
57 this.thisElement)
53 : this.freeVariableMapping = new Map<Element, Element>(), 58 : this.freeVariableMapping = new Map<Element, Element>(),
54 this.capturedFieldMapping = new Map<Element, Element>(), 59 this.capturedFieldMapping = new Map<Element, Element>(),
55 this.capturingScopes = new Map<Node, ClosureScope>(), 60 this.capturingScopes = new Map<Node, ClosureScope>(),
56 this.usedVariablesInTry = new Set<Element>(); 61 this.usedVariablesInTry = new Set<Element>();
62
63 bool isClosure() => globalizedClosureElement !== null;
57 } 64 }
58 65
59 Map<Node, ClosureData> _closureDataCache; 66 Map<Node, ClosureData> _closureDataCache;
60 Map<Node, ClosureData> get closureDataCache() { 67 Map<Node, ClosureData> get closureDataCache() {
61 if (_closureDataCache === null) { 68 if (_closureDataCache === null) {
62 _closureDataCache = new HashMap<Node, ClosureData>(); 69 _closureDataCache = new HashMap<Node, ClosureData>();
63 } 70 }
64 return _closureDataCache; 71 return _closureDataCache;
65 } 72 }
66 73
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 globalizedElement); 266 globalizedElement);
260 globalizedElement.backendMembers = 267 globalizedElement.backendMembers =
261 const EmptyLink<Element>().prepend(callElement); 268 const EmptyLink<Element>().prepend(callElement);
262 globalizedElement.isResolved = true; 269 globalizedElement.isResolved = true;
263 ClassElement objectClass = 270 ClassElement objectClass =
264 compiler.coreLibrary.find(const SourceString('Object')); 271 compiler.coreLibrary.find(const SourceString('Object'));
265 globalizedElement.supertype = new SimpleType(Types.OBJECT, objectClass); 272 globalizedElement.supertype = new SimpleType(Types.OBJECT, objectClass);
266 // The nested function's 'this' is the same as the one for the outer 273 // The nested function's 'this' is the same as the one for the outer
267 // function. It could be [null] if we are inside a static method. 274 // function. It could be [null] if we are inside a static method.
268 Element thisElement = closureData.thisElement; 275 Element thisElement = closureData.thisElement;
269 return new ClosureData(globalizedElement, callElement, thisElement); 276 return new ClosureData(element, globalizedElement,
277 callElement, thisElement);
270 } 278 }
271 279
272 visitFunctionExpression(FunctionExpression node) { 280 visitFunctionExpression(FunctionExpression node) {
273 FunctionElement element = elements[node]; 281 FunctionElement element = elements[node];
274 bool isClosure = (closureData !== null); 282 bool isClosure = (closureData !== null);
275 283
276 if (isClosure) closures.add(node); 284 if (isClosure) closures.add(node);
277 285
278 bool oldInsideClosure = insideClosure; 286 bool oldInsideClosure = insideClosure;
279 FunctionElement oldFunctionElement = currentFunctionElement; 287 FunctionElement oldFunctionElement = currentFunctionElement;
(...skipping 16 matching lines...) Expand all
296 // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'. 304 // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'.
297 Element thisEnclosingElement = element; 305 Element thisEnclosingElement = element;
298 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { 306 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
299 ConstructorBodyElement body = element; 307 ConstructorBodyElement body = element;
300 thisEnclosingElement = body.constructor; 308 thisEnclosingElement = body.constructor;
301 } 309 }
302 thisElement = new Element(const SourceString("this"), 310 thisElement = new Element(const SourceString("this"),
303 ElementKind.PARAMETER, 311 ElementKind.PARAMETER,
304 thisEnclosingElement); 312 thisEnclosingElement);
305 } 313 }
306 closureData = new ClosureData(null, null, thisElement); 314 closureData = new ClosureData(element, null, null, thisElement);
307 } 315 }
308 scopeVariables = new List<Element>(); 316 scopeVariables = new List<Element>();
309 317
310 // TODO(floitsch): a named function is visible from inside itself. Add 318 // TODO(floitsch): a named function is visible from inside itself. Add
311 // the element to the block. 319 // the element to the block.
312 320
313 // We have to declare the implicit 'this' parameter. 321 // We have to declare the implicit 'this' parameter.
314 if (!insideClosure && closureData.thisElement !== null) { 322 if (!insideClosure && closureData.thisElement !== null) {
315 declareLocal(closureData.thisElement); 323 declareLocal(closureData.thisElement);
316 } 324 }
(...skipping 10 matching lines...) Expand all
327 // Restore old values. 335 // Restore old values.
328 scopeVariables = oldScopeVariables; 336 scopeVariables = oldScopeVariables;
329 insideClosure = oldInsideClosure; 337 insideClosure = oldInsideClosure;
330 closureData = oldClosureData; 338 closureData = oldClosureData;
331 currentFunctionElement = oldFunctionElement; 339 currentFunctionElement = oldFunctionElement;
332 340
333 // Mark all free variables as captured and use them in the outer function. 341 // Mark all free variables as captured and use them in the outer function.
334 List<Element> freeVariables = 342 List<Element> freeVariables =
335 savedClosureData.freeVariableMapping.getKeys(); 343 savedClosureData.freeVariableMapping.getKeys();
336 assert(freeVariables.isEmpty() || savedInsideClosure); 344 assert(freeVariables.isEmpty() || savedInsideClosure);
337 for (Element element in freeVariables) { 345 for (Element freeElement in freeVariables) {
338 assert(capturedVariableMapping[element] == null || 346 assert(capturedVariableMapping[freeElement] == null ||
339 capturedVariableMapping[element] == element); 347 capturedVariableMapping[freeElement] == freeElement);
340 capturedVariableMapping[element] = element; 348 capturedVariableMapping[freeElement] = freeElement;
341 useLocal(element); 349 useLocal(freeElement);
342 } 350 }
343 351
344 // If we just visited a closure we declare it. This is not always correct 352 // If we just visited a closure we declare it. This is not always correct
345 // since some closures are used as expressions and don't introduce any 353 // since some closures are used as expressions and don't introduce any
346 // name. But in this case the added local is simply not used. 354 // name. But in this case the added local is simply not used.
347 if (savedInsideClosure) { 355 if (savedInsideClosure) {
348 declareLocal(elements[node]); 356 declareLocal(element);
349 } 357 }
350 } 358 }
351 359
352 visitTryStatement(TryStatement node) { 360 visitTryStatement(TryStatement node) {
353 // TODO(ngeoffray): implement finer grain state. 361 // TODO(ngeoffray): implement finer grain state.
354 inTryCatchOrFinally = true; 362 inTryCatchOrFinally = true;
355 node.visitChildren(this); 363 node.visitChildren(this);
356 inTryCatchOrFinally = false; 364 inTryCatchOrFinally = false;
357 } 365 }
358 } 366 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698