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

Side by Side Diff: lib/compiler/implementation/closure.dart

Issue 10918078: Revert r11881. metadata_test fails for yet to be discover reasons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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
« no previous file with comments | « no previous file | lib/compiler/implementation/elements/elements.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #library("closureToClassMapper"); 5 #library("closureToClassMapper");
6 6
7 #import("elements/elements.dart"); 7 #import("elements/elements.dart");
8 #import("leg.dart"); 8 #import("leg.dart");
9 #import("scanner/scannerlib.dart"); 9 #import("scanner/scannerlib.dart");
10 #import("tree/tree.dart"); 10 #import("tree/tree.dart");
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 // List of encountered closures. 172 // List of encountered closures.
173 List<FunctionExpression> closures; 173 List<FunctionExpression> closures;
174 174
175 // The variables that have been declared in the current scope. 175 // The variables that have been declared in the current scope.
176 List<Element> scopeVariables; 176 List<Element> scopeVariables;
177 177
178 // Keep track of the mutated variables so that we don't need to box 178 // Keep track of the mutated variables so that we don't need to box
179 // non-mutated variables. 179 // non-mutated variables.
180 Set<Element> mutatedVariables; 180 Set<Element> mutatedVariables;
181 181
182 FunctionElement outermostFunctionElement;
183 FunctionElement currentFunctionElement; 182 FunctionElement currentFunctionElement;
184
185 // The closureData of the currentFunctionElement. 183 // The closureData of the currentFunctionElement.
186 ClosureClassMap closureData; 184 ClosureClassMap closureData;
187 185
188 bool insideClosure = false; 186 bool insideClosure = false;
189 187
190 ClosureTranslator(this.compiler, this.elements, this.closureMappingCache) 188 ClosureTranslator(this.compiler, this.elements, this.closureMappingCache)
191 : capturedVariableMapping = new Map<Element, Element>(), 189 : capturedVariableMapping = new Map<Element, Element>(),
192 closures = <FunctionExpression>[], 190 closures = <FunctionExpression>[],
193 mutatedVariables = new Set<Element>(); 191 mutatedVariables = new Set<Element>();
194 192
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 Element fieldElement = new ClosureFieldElement(name, closureElement); 243 Element fieldElement = new ClosureFieldElement(name, closureElement);
246 closureElement.backendMembers = 244 closureElement.backendMembers =
247 closureElement.backendMembers.prepend(fieldElement); 245 closureElement.backendMembers.prepend(fieldElement);
248 data.capturedFieldMapping[fieldElement] = capturedElement; 246 data.capturedFieldMapping[fieldElement] = capturedElement;
249 freeVariableMapping[capturedElement] = fieldElement; 247 freeVariableMapping[capturedElement] = fieldElement;
250 } 248 }
251 } 249 }
252 } 250 }
253 251
254 void useLocal(Element element) { 252 void useLocal(Element element) {
253 // TODO(floitsch): replace this with a general solution.
254 Element functionElement = currentFunctionElement;
255 if (functionElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
256 ConstructorBodyElement body = functionElement;
257 functionElement = body.constructor;
258 }
255 // If the element is not declared in the current function and the element 259 // If the element is not declared in the current function and the element
256 // is not the closure itself we need to mark the element as free variable. 260 // is not the closure itself we need to mark the element as free variable.
257 // Note that the check on [insideClosure] is not just an 261 if (element.enclosingElement != functionElement &&
258 // optimization: factories have type parameters as function 262 element != functionElement) {
259 // parameters, and type parameters are declared in the class, not
260 // the factory.
261 if (insideClosure &&
262 element.enclosingElement != currentFunctionElement &&
263 element != currentFunctionElement) {
264 assert(closureData.freeVariableMapping[element] == null || 263 assert(closureData.freeVariableMapping[element] == null ||
265 closureData.freeVariableMapping[element] == element); 264 closureData.freeVariableMapping[element] == element);
266 closureData.freeVariableMapping[element] = element; 265 closureData.freeVariableMapping[element] = element;
267 } else if (inTryStatement) { 266 } else if (inTryStatement) {
268 // Don't mark the this-element. This would complicate things in the 267 // Don't mark the this-element. This would complicate things in the
269 // builder. 268 // builder.
270 if (element != closureData.thisElement) { 269 if (element != closureData.thisElement) {
271 // TODO(ngeoffray): only do this if the variable is mutated. 270 // TODO(ngeoffray): only do this if the variable is mutated.
272 closureData.usedVariablesInTry.add(element); 271 closureData.usedVariablesInTry.add(element);
273 } 272 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 339
341 visitSendSet(SendSet node) { 340 visitSendSet(SendSet node) {
342 Element element = elements[node]; 341 Element element = elements[node];
343 if (Elements.isLocal(element)) { 342 if (Elements.isLocal(element)) {
344 mutatedVariables.add(element); 343 mutatedVariables.add(element);
345 } 344 }
346 super.visitSendSet(node); 345 super.visitSendSet(node);
347 } 346 }
348 347
349 visitNewExpression(NewExpression node) { 348 visitNewExpression(NewExpression node) {
350 TypeAnnotation annotation = node.send.getTypeAnnotation();
351 DartType type = elements.getType(annotation);
352
353 bool hasTypeVariable(DartType type) { 349 bool hasTypeVariable(DartType type) {
354 if (type is TypeVariableType) { 350 if (type is TypeVariableType) {
355 return true; 351 return true;
356 } else if (type is InterfaceType) { 352 } else if (type is InterfaceType) {
357 InterfaceType ifcType = type; 353 InterfaceType ifcType = type;
358 for (DartType argument in ifcType.arguments) { 354 for (DartType argument in ifcType.arguments) {
359 if (hasTypeVariable(argument)) { 355 if (hasTypeVariable(argument)) {
360 return true; 356 return true;
361 } 357 }
362 } 358 }
363 } 359 }
364 return false; 360 return false;
365 } 361 }
366 362 TypeAnnotation annotation = node.send.getTypeAnnotation();
367 void analyzeTypeVariables(DartType type) { 363 DartType type = elements.getType(annotation);
368 if (type is TypeVariableType) { 364 if (hasTypeVariable(type)) {
369 useLocal(type.element); 365 // Factories do not use [this] to get the type variables.
370 } else if (type is InterfaceType) { 366 if (closureData.thisElement !== null) {
371 InterfaceType ifcType = type; 367 useLocal(closureData.thisElement);
372 for (DartType argument in ifcType.arguments) {
373 analyzeTypeVariables(argument);
374 }
375 } 368 }
376 } 369 }
377
378 if (outermostFunctionElement.isInstanceMember()
379 || outermostFunctionElement.isGenerativeConstructor()) {
380 if (hasTypeVariable(type)) useLocal(closureData.thisElement);
381 } else if (outermostFunctionElement.isFactoryConstructor()) {
382 analyzeTypeVariables(type);
383 }
384
385 node.visitChildren(this); 370 node.visitChildren(this);
386 } 371 }
387 372
388 // If variables that are declared in the [node] scope are captured and need 373 // If variables that are declared in the [node] scope are captured and need
389 // to be boxed create a box-element and update the [capturingScopes] in the 374 // to be boxed create a box-element and update the [capturingScopes] in the
390 // current [closureData]. 375 // current [closureData].
391 // The boxed variables are updated in the [capturedVariableMapping]. 376 // The boxed variables are updated in the [capturedVariableMapping].
392 void attachCapturedScopeVariables(Node node) { 377 void attachCapturedScopeVariables(Node node) {
393 Element box = null; 378 Element box = null;
394 Map<Element, Element> scopeMapping = new Map<Element, Element>(); 379 Map<Element, Element> scopeMapping = new Map<Element, Element>();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 const EmptyLink<Element>().prepend(callElement); 457 const EmptyLink<Element>().prepend(callElement);
473 // The nested function's 'this' is the same as the one for the outer 458 // The nested function's 'this' is the same as the one for the outer
474 // function. It could be [null] if we are inside a static method. 459 // function. It could be [null] if we are inside a static method.
475 Element thisElement = closureData.thisElement; 460 Element thisElement = closureData.thisElement;
476 return new ClosureClassMap(element, globalizedElement, 461 return new ClosureClassMap(element, globalizedElement,
477 callElement, thisElement); 462 callElement, thisElement);
478 } 463 }
479 464
480 visitFunctionExpression(FunctionExpression node) { 465 visitFunctionExpression(FunctionExpression node) {
481 Element element = elements[node]; 466 Element element = elements[node];
482 if (element.isParameter()) { 467 if (element.kind === ElementKind.PARAMETER) {
483 // TODO(ahe): This is a hack. This method should *not* call 468 // TODO(ahe): This is a hack. This method should *not* call
484 // visitChildren. 469 // visitChildren.
485 return node.name.accept(this); 470 return node.name.accept(this);
486 } 471 }
472 bool isClosure = (closureData !== null);
473
474 if (isClosure) closures.add(node);
487 475
488 bool oldInsideClosure = insideClosure; 476 bool oldInsideClosure = insideClosure;
489 FunctionElement oldFunctionElement = currentFunctionElement; 477 FunctionElement oldFunctionElement = currentFunctionElement;
490 ClosureClassMap oldClosureData = closureData; 478 ClosureClassMap oldClosureData = closureData;
491 479
492 insideClosure = outermostFunctionElement != null; 480 insideClosure = isClosure;
493 currentFunctionElement = element; 481 currentFunctionElement = elements[node];
494 if (insideClosure) { 482 if (insideClosure) {
495 closures.add(node);
496 closureData = globalizeClosure(node, element); 483 closureData = globalizeClosure(node, element);
497 } else { 484 } else {
498 outermostFunctionElement = element;
499 Element thisElement = null; 485 Element thisElement = null;
500 if (element.isInstanceMember() || element.isGenerativeConstructor()) { 486 // TODO(floitsch): we should not need to look for generative constructors.
501 thisElement = new ThisElement(element); 487 // At the moment we store only one ClosureData for both the factory and
488 // the body.
489 if (element.isInstanceMember() ||
490 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
491 // TODO(floitsch): currently all variables are considered to be
492 // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'.
493 Element thisEnclosingElement = element;
494 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
495 ConstructorBodyElement body = element;
496 thisEnclosingElement = body.constructor;
497 }
498 thisElement = new ThisElement(thisEnclosingElement);
502 } 499 }
503 closureData = new ClosureClassMap(null, null, null, thisElement); 500 closureData = new ClosureClassMap(null, null, null, thisElement);
504 } 501 }
505 closureMappingCache[node] = closureData; 502 closureMappingCache[node] = closureData;
506 503
507 inNewScope(node, () { 504 inNewScope(node, () {
508 // We have to declare the implicit 'this' parameter. 505 // We have to declare the implicit 'this' parameter.
509 if (!insideClosure && closureData.thisElement !== null) { 506 if (!insideClosure && closureData.thisElement !== null) {
510 declareLocal(closureData.thisElement); 507 declareLocal(closureData.thisElement);
511 } 508 }
512 // If we are inside a named closure we have to declare ourselve. For 509 // If we are inside a named closure we have to declare ourselve. For
513 // simplicity we declare the local even if the closure does not have a 510 // simplicity we declare the local even if the closure does not have a
514 // name. 511 // name.
515 // It will simply not be used. 512 // It will simply not be used.
516 if (insideClosure) { 513 if (insideClosure) {
517 declareLocal(element); 514 declareLocal(element);
518 } 515 }
519
520 if (currentFunctionElement.isFactoryConstructor()) {
521 // Declare the type parameters in the scope. Generative
522 // constructors just use 'this'.
523 ClassElement cls = currentFunctionElement.enclosingElement;
524 cls.typeVariables.forEach((TypeVariableType typeVariable) {
525 declareLocal(typeVariable.element);
526 });
527 }
528 516
529 // TODO(ahe): This is problematic. The backend should not repeat 517 // TODO(ahe): This is problematic. The backend should not repeat
530 // the work of the resolver. It is the resolver's job to create 518 // the work of the resolver. It is the resolver's job to create
531 // parameters, etc. Other phases should only visit statements. 519 // parameters, etc. Other phases should only visit statements.
532 // TODO(floitsch): we avoid visiting the initializers on purpose so that 520 // TODO(floitsch): we avoid visiting the initializers on purpose so that
533 // we get an error-message later in the builder. 521 // we get an error-message later in the builder.
534 if (node.parameters !== null) node.parameters.accept(this); 522 if (node.parameters !== null) node.parameters.accept(this);
535 if (node.body !== null) node.body.accept(this); 523 if (node.body !== null) node.body.accept(this);
536 }); 524 });
537 525
(...skipping 26 matching lines...) Expand all
564 } 552 }
565 553
566 visitTryStatement(TryStatement node) { 554 visitTryStatement(TryStatement node) {
567 // TODO(ngeoffray): implement finer grain state. 555 // TODO(ngeoffray): implement finer grain state.
568 bool oldInTryStatement = inTryStatement; 556 bool oldInTryStatement = inTryStatement;
569 inTryStatement = true; 557 inTryStatement = true;
570 node.visitChildren(this); 558 node.visitChildren(this);
571 inTryStatement = oldInTryStatement; 559 inTryStatement = oldInTryStatement;
572 } 560 }
573 } 561 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/elements/elements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698