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

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

Issue 266913017: Convert property methods into getters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 6 years, 7 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 | sdk/lib/_internal/compiler/implementation/compile_time_constants.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 "dart2jslib.dart"; 8 import "dart2jslib.dart";
9 import "dart_types.dart"; 9 import "dart_types.dart";
10 import "scanner/scannerlib.dart" show Token; 10 import "scanner/scannerlib.dart" show Token;
(...skipping 29 matching lines...) Expand all
40 new ClosureTranslator(compiler, elements, closureMappingCache, namer); 40 new ClosureTranslator(compiler, elements, closureMappingCache, namer);
41 41
42 // The translator will store the computed closure-mappings inside the 42 // The translator will store the computed closure-mappings inside the
43 // cache. One for given node and one for each nested closure. 43 // cache. One for given node and one for each nested closure.
44 if (node is FunctionExpression) { 44 if (node is FunctionExpression) {
45 translator.translateFunction(element, node); 45 translator.translateFunction(element, node);
46 } else if (element.isSynthesized) { 46 } else if (element.isSynthesized) {
47 return new ClosureClassMap(null, null, null, 47 return new ClosureClassMap(null, null, null,
48 new ThisElement(element, compiler.types.dynamicType)); 48 new ThisElement(element, compiler.types.dynamicType));
49 } else { 49 } else {
50 assert(element.isField()); 50 assert(element.isField);
51 VariableElement field = element; 51 VariableElement field = element;
52 if (field.initializer != null) { 52 if (field.initializer != null) {
53 // The lazy initializer of a static. 53 // The lazy initializer of a static.
54 translator.translateLazyInitializer(element, node, field.initializer); 54 translator.translateLazyInitializer(element, node, field.initializer);
55 } else { 55 } else {
56 assert(element.isInstanceMember()); 56 assert(element.isInstanceMember);
57 closureMappingCache[node] = 57 closureMappingCache[node] =
58 new ClosureClassMap(null, null, null, 58 new ClosureClassMap(null, null, null,
59 new ThisElement(element, compiler.types.dynamicType)); 59 new ThisElement(element, compiler.types.dynamicType));
60 } 60 }
61 } 61 }
62 assert(closureMappingCache[node] != null); 62 assert(closureMappingCache[node] != null);
63 return closureMappingCache[node]; 63 return closureMappingCache[node];
64 }); 64 });
65 } 65 }
66 66
(...skipping 19 matching lines...) Expand all
86 this.variableElement, 86 this.variableElement,
87 ClassElement enclosing) 87 ClassElement enclosing)
88 : super(name, ElementKind.FIELD, enclosing); 88 : super(name, ElementKind.FIELD, enclosing);
89 89
90 Expression get initializer { 90 Expression get initializer {
91 throw new SpannableAssertionFailure( 91 throw new SpannableAssertionFailure(
92 variableElement, 92 variableElement,
93 'Should not access initializer of ClosureFieldElement.'); 93 'Should not access initializer of ClosureFieldElement.');
94 } 94 }
95 95
96 bool isInstanceMember() => true; 96 bool get isInstanceMember => true;
97 bool isAssignable() => false; 97 bool get isAssignable => false;
98 98
99 DartType computeType(Compiler compiler) { 99 DartType computeType(Compiler compiler) {
100 return variableElement.type; 100 return variableElement.type;
101 } 101 }
102 102
103 DartType get type => variableElement.type; 103 DartType get type => variableElement.type;
104 104
105 String toString() => "ClosureFieldElement($name)"; 105 String toString() => "ClosureFieldElement($name)";
106 106
107 accept(ElementVisitor visitor) => visitor.visitClosureFieldElement(this); 107 accept(ElementVisitor visitor) => visitor.visitClosureFieldElement(this);
(...skipping 14 matching lines...) Expand all
122 Compiler compiler, 122 Compiler compiler,
123 this.methodElement, 123 this.methodElement,
124 Element enclosingElement) 124 Element enclosingElement)
125 : super(name, 125 : super(name,
126 enclosingElement, 126 enclosingElement,
127 // By assigning a fresh class-id we make sure that the hashcode 127 // By assigning a fresh class-id we make sure that the hashcode
128 // is unique, but also emit closure classes after all other 128 // is unique, but also emit closure classes after all other
129 // classes (since the emitter sorts classes by their id). 129 // classes (since the emitter sorts classes by their id).
130 compiler.getNextFreeClassId(), 130 compiler.getNextFreeClassId(),
131 STATE_DONE) { 131 STATE_DONE) {
132 ClassElement superclass = methodElement.isInstanceMember() 132 ClassElement superclass = methodElement.isInstanceMember
133 ? compiler.boundClosureClass 133 ? compiler.boundClosureClass
134 : compiler.closureClass; 134 : compiler.closureClass;
135 superclass.ensureResolved(compiler); 135 superclass.ensureResolved(compiler);
136 supertype = superclass.thisType; 136 supertype = superclass.thisType;
137 interfaces = const Link<DartType>(); 137 interfaces = const Link<DartType>();
138 thisType = rawType = new InterfaceType(this); 138 thisType = rawType = new InterfaceType(this);
139 allSupertypesAndSelf = 139 allSupertypesAndSelf =
140 superclass.allSupertypesAndSelf.extendClass(thisType); 140 superclass.allSupertypesAndSelf.extendClass(thisType);
141 callType = methodElement.type; 141 callType = methodElement.type;
142 } 142 }
143 143
144 bool isClosure() => true; 144 bool get isClosure => true;
145 145
146 Token position() => node.getBeginToken(); 146 Token get position => node.getBeginToken();
147 147
148 Node parseNode(DiagnosticListener listener) => node; 148 Node parseNode(DiagnosticListener listener) => node;
149 149
150 /** 150 /**
151 * The element for the declaration of the function expression. 151 * The element for the declaration of the function expression.
152 */ 152 */
153 final TypedElement methodElement; 153 final TypedElement methodElement;
154 154
155 // A [ClosureClassElement] is nested inside a function or initializer in terms 155 // A [ClosureClassElement] is nested inside a function or initializer in terms
156 // of [enclosingElement], but still has to be treated as a top-level 156 // of [enclosingElement], but still has to be treated as a top-level
157 // element. 157 // element.
158 bool isTopLevel() => true; 158 bool get isTopLevel => true;
159 159
160 get enclosingElement => methodElement; 160 get enclosingElement => methodElement;
161 161
162 accept(ElementVisitor visitor) => visitor.visitClosureClassElement(this); 162 accept(ElementVisitor visitor) => visitor.visitClosureClassElement(this);
163 } 163 }
164 164
165 // TODO(ahe): These classes continuously cause problems. We need to 165 // TODO(ahe): These classes continuously cause problems. We need to
166 // move these classes to elements/modelx.dart or see if we can find a 166 // move these classes to elements/modelx.dart or see if we can find a
167 // more general solution. 167 // more general solution.
168 class BoxElement extends ElementX implements TypedElement { 168 class BoxElement extends ElementX implements TypedElement {
(...skipping 27 matching lines...) Expand all
196 196
197 // TODO(ahe): These classes continuously cause problems. We need to 197 // TODO(ahe): These classes continuously cause problems. We need to
198 // move these classes to elements/modelx.dart or see if we can find a 198 // move these classes to elements/modelx.dart or see if we can find a
199 // more general solution. 199 // more general solution.
200 class ThisElement extends ElementX implements TypedElement { 200 class ThisElement extends ElementX implements TypedElement {
201 final DartType type; 201 final DartType type;
202 202
203 ThisElement(Element enclosing, this.type) 203 ThisElement(Element enclosing, this.type)
204 : super('this', ElementKind.PARAMETER, enclosing); 204 : super('this', ElementKind.PARAMETER, enclosing);
205 205
206 bool isAssignable() => false; 206 bool get isAssignable => false;
207 207
208 DartType computeType(Compiler compiler) => compiler.types.dynamicType; 208 DartType computeType(Compiler compiler) => compiler.types.dynamicType;
209 209
210 // Since there is no declaration corresponding to 'this', use the position of 210 // Since there is no declaration corresponding to 'this', use the position of
211 // the enclosing method. 211 // the enclosing method.
212 Token position() => enclosingElement.position(); 212 Token get position => enclosingElement.position;
213 213
214 accept(ElementVisitor visitor) => visitor.visitThisElement(this); 214 accept(ElementVisitor visitor) => visitor.visitThisElement(this);
215 } 215 }
216 216
217 // The box-element for a scope, and the captured variables that need to be 217 // The box-element for a scope, and the captured variables that need to be
218 // stored in the box. 218 // stored in the box.
219 class ClosureScope { 219 class ClosureScope {
220 Element boxElement; 220 Element boxElement;
221 Map<Element, Element> capturedVariableMapping; 221 Map<Element, Element> capturedVariableMapping;
222 // If the scope is attached to a [For] contains the variables that are 222 // If the scope is attached to a [For] contains the variables that are
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 262
263 ClosureClassMap(this.closureElement, 263 ClosureClassMap(this.closureElement,
264 this.closureClassElement, 264 this.closureClassElement,
265 this.callElement, 265 this.callElement,
266 this.thisElement) 266 this.thisElement)
267 : this.freeVariableMapping = new Map<Element, Element>(), 267 : this.freeVariableMapping = new Map<Element, Element>(),
268 this.capturedFieldMapping = new Map<Element, Element>(), 268 this.capturedFieldMapping = new Map<Element, Element>(),
269 this.capturingScopes = new Map<Node, ClosureScope>(), 269 this.capturingScopes = new Map<Node, ClosureScope>(),
270 this.usedVariablesInTry = new Set<Element>(); 270 this.usedVariablesInTry = new Set<Element>();
271 271
272 bool isClosure() => closureElement != null; 272 bool get isClosure => closureElement != null;
273 273
274 bool capturingScopesBox(Element element) { 274 bool capturingScopesBox(Element element) {
275 return capturingScopes.values.any((scope) { 275 return capturingScopes.values.any((scope) {
276 return scope.boxedLoopVariables.contains(element); 276 return scope.boxedLoopVariables.contains(element);
277 }); 277 });
278 } 278 }
279 279
280 bool isVariableBoxed(Element element) { 280 bool isVariableBoxed(Element element) {
281 Element copy = freeVariableMapping[element]; 281 Element copy = freeVariableMapping[element];
282 if (copy != null && !copy.isMember()) return true; 282 if (copy != null && !copy.isMember) return true;
283 return capturingScopesBox(element); 283 return capturingScopesBox(element);
284 } 284 }
285 285
286 void forEachCapturedVariable(void f(Element local, Element field)) { 286 void forEachCapturedVariable(void f(Element local, Element field)) {
287 freeVariableMapping.forEach((variable, copy) { 287 freeVariableMapping.forEach((variable, copy) {
288 if (variable is BoxElement) return; 288 if (variable is BoxElement) return;
289 f(variable, copy); 289 f(variable, copy);
290 }); 290 });
291 capturingScopes.values.forEach((scope) { 291 capturingScopes.values.forEach((scope) {
292 scope.capturedVariableMapping.forEach(f); 292 scope.capturedVariableMapping.forEach(f);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 Map<Element, Element> freeVariableMapping = data.freeVariableMapping; 375 Map<Element, Element> freeVariableMapping = data.freeVariableMapping;
376 // We get a copy of the keys and iterate over it, to avoid modifications 376 // We get a copy of the keys and iterate over it, to avoid modifications
377 // to the map while iterating over it. 377 // to the map while iterating over it.
378 freeVariableMapping.keys.toList().forEach((Element fromElement) { 378 freeVariableMapping.keys.toList().forEach((Element fromElement) {
379 assert(fromElement == freeVariableMapping[fromElement]); 379 assert(fromElement == freeVariableMapping[fromElement]);
380 Element updatedElement = capturedVariableMapping[fromElement]; 380 Element updatedElement = capturedVariableMapping[fromElement];
381 assert(updatedElement != null); 381 assert(updatedElement != null);
382 if (fromElement == updatedElement) { 382 if (fromElement == updatedElement) {
383 assert(freeVariableMapping[fromElement] == updatedElement); 383 assert(freeVariableMapping[fromElement] == updatedElement);
384 assert(Elements.isLocal(updatedElement) 384 assert(Elements.isLocal(updatedElement)
385 || updatedElement.isTypeVariable()); 385 || updatedElement.isTypeVariable);
386 // The variable has not been boxed. 386 // The variable has not been boxed.
387 fieldCaptures.add(updatedElement); 387 fieldCaptures.add(updatedElement);
388 } else { 388 } else {
389 // A boxed element. 389 // A boxed element.
390 freeVariableMapping[fromElement] = updatedElement; 390 freeVariableMapping[fromElement] = updatedElement;
391 Element boxElement = updatedElement.enclosingElement; 391 Element boxElement = updatedElement.enclosingElement;
392 assert(boxElement is BoxElement); 392 assert(boxElement is BoxElement);
393 boxes.add(boxElement); 393 boxes.add(boxElement);
394 } 394 }
395 }); 395 });
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 if (arguments != null) { 475 if (arguments != null) {
476 visit(arguments); 476 visit(arguments);
477 } 477 }
478 } else { 478 } else {
479 visit(definition); 479 visit(definition);
480 } 480 }
481 } 481 }
482 } 482 }
483 483
484 visitTypeAnnotation(TypeAnnotation node) { 484 visitTypeAnnotation(TypeAnnotation node) {
485 Element member = currentElement.getEnclosingMember(); 485 Element member = currentElement.enclosingMember;
486 DartType type = elements.getType(node); 486 DartType type = elements.getType(node);
487 // TODO(karlklose,johnniwinther): if the type is null, the annotation is 487 // TODO(karlklose,johnniwinther): if the type is null, the annotation is
488 // from a parameter which has been analyzed before the method has been 488 // from a parameter which has been analyzed before the method has been
489 // resolved and the result has been thrown away. 489 // resolved and the result has been thrown away.
490 if (compiler.enableTypeAssertions && type != null && 490 if (compiler.enableTypeAssertions && type != null &&
491 type.containsTypeVariables) { 491 type.containsTypeVariables) {
492 if (insideClosure && member.isFactoryConstructor()) { 492 if (insideClosure && member.isFactoryConstructor) {
493 // This is a closure in a factory constructor. Since there is no 493 // This is a closure in a factory constructor. Since there is no
494 // [:this:], we have to mark the type arguments as free variables to 494 // [:this:], we have to mark the type arguments as free variables to
495 // capture them in the closure. 495 // capture them in the closure.
496 type.forEachTypeVariable((variable) => useLocal(variable.element)); 496 type.forEachTypeVariable((variable) => useLocal(variable.element));
497 } 497 }
498 if (member.isInstanceMember() && !member.isField()) { 498 if (member.isInstanceMember && !member.isField) {
499 // In checked mode, using a type variable in a type annotation may lead 499 // In checked mode, using a type variable in a type annotation may lead
500 // to a runtime type check that needs to access the type argument and 500 // to a runtime type check that needs to access the type argument and
501 // therefore the closure needs a this-element, if it is not in a field 501 // therefore the closure needs a this-element, if it is not in a field
502 // initializer; field initatializers are evaluated in a context where 502 // initializer; field initatializers are evaluated in a context where
503 // the type arguments are available in locals. 503 // the type arguments are available in locals.
504 registerNeedsThis(); 504 registerNeedsThis();
505 } 505 }
506 } 506 }
507 } 507 }
508 508
509 visitIdentifier(Identifier node) { 509 visitIdentifier(Identifier node) {
510 if (node.isThis()) { 510 if (node.isThis()) {
511 registerNeedsThis(); 511 registerNeedsThis();
512 } else { 512 } else {
513 Element element = elements[node]; 513 Element element = elements[node];
514 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { 514 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) {
515 if (outermostElement.isConstructor()) { 515 if (outermostElement.isConstructor) {
516 useLocal(element); 516 useLocal(element);
517 } else { 517 } else {
518 registerNeedsThis(); 518 registerNeedsThis();
519 } 519 }
520 } 520 }
521 } 521 }
522 node.visitChildren(this); 522 node.visitChildren(this);
523 } 523 }
524 524
525 visitSend(Send node) { 525 visitSend(Send node) {
526 Element element = elements[node]; 526 Element element = elements[node];
527 if (Elements.isLocal(element)) { 527 if (Elements.isLocal(element)) {
528 useLocal(element); 528 useLocal(element);
529 } else if (element != null && element.isTypeVariable()) { 529 } else if (element != null && element.isTypeVariable) {
530 TypeVariableElement variable = element; 530 TypeVariableElement variable = element;
531 analyzeType(variable.type); 531 analyzeType(variable.type);
532 } else if (node.receiver == null && 532 } else if (node.receiver == null &&
533 Elements.isInstanceSend(node, elements)) { 533 Elements.isInstanceSend(node, elements)) {
534 registerNeedsThis(); 534 registerNeedsThis();
535 } else if (node.isSuperCall) { 535 } else if (node.isSuperCall) {
536 registerNeedsThis(); 536 registerNeedsThis();
537 } else if (node.isTypeTest || node.isTypeCast) { 537 } else if (node.isTypeTest || node.isTypeCast) {
538 TypeAnnotation annotation = node.typeAnnotationFromIsCheckOrCast; 538 TypeAnnotation annotation = node.typeAnnotationFromIsCheckOrCast;
539 DartType type = elements.getType(annotation); 539 DartType type = elements.getType(annotation);
(...skipping 26 matching lines...) Expand all
566 visitNewExpression(NewExpression node) { 566 visitNewExpression(NewExpression node) {
567 DartType type = elements.getType(node); 567 DartType type = elements.getType(node);
568 analyzeType(type); 568 analyzeType(type);
569 node.visitChildren(this); 569 node.visitChildren(this);
570 } 570 }
571 571
572 void analyzeTypeVariables(DartType type) { 572 void analyzeTypeVariables(DartType type) {
573 type.forEachTypeVariable((TypeVariableType typeVariable) { 573 type.forEachTypeVariable((TypeVariableType typeVariable) {
574 // Field initializers are inlined and access the type variable as 574 // Field initializers are inlined and access the type variable as
575 // normal parameters. 575 // normal parameters.
576 if (!outermostElement.isField() && 576 if (!outermostElement.isField &&
577 !outermostElement.isConstructor()) { 577 !outermostElement.isConstructor) {
578 registerNeedsThis(); 578 registerNeedsThis();
579 } else { 579 } else {
580 useLocal(typeVariable.element); 580 useLocal(typeVariable.element);
581 } 581 }
582 }); 582 });
583 } 583 }
584 584
585 void analyzeType(DartType type) { 585 void analyzeType(DartType type) {
586 // TODO(johnniwinther): Find out why this can be null. 586 // TODO(johnniwinther): Find out why this can be null.
587 if (type == null) return; 587 if (type == null) return;
588 if (outermostElement.isMember() && 588 if (outermostElement.isMember &&
589 compiler.backend.classNeedsRti(outermostElement.getEnclosingClass())) { 589 compiler.backend.classNeedsRti(outermostElement.enclosingClass)) {
590 if (outermostElement.isConstructor() || 590 if (outermostElement.isConstructor ||
591 outermostElement.isField()) { 591 outermostElement.isField) {
592 analyzeTypeVariables(type); 592 analyzeTypeVariables(type);
593 } else if (outermostElement.isInstanceMember()) { 593 } else if (outermostElement.isInstanceMember) {
594 if (type.containsTypeVariables) { 594 if (type.containsTypeVariables) {
595 registerNeedsThis(); 595 registerNeedsThis();
596 } 596 }
597 } 597 }
598 } 598 }
599 } 599 }
600 600
601 // If variables that are declared in the [node] scope are captured and need 601 // If variables that are declared in the [node] scope are captured and need
602 // to be boxed create a box-element and update the [capturingScopes] in the 602 // to be boxed create a box-element and update the [capturingScopes] in the
603 // current [closureData]. 603 // current [closureData].
604 // The boxed variables are updated in the [capturedVariableMapping]. 604 // The boxed variables are updated in the [capturedVariableMapping].
605 void attachCapturedScopeVariables(Node node) { 605 void attachCapturedScopeVariables(Node node) {
606 Element box = null; 606 Element box = null;
607 Map<Element, Element> scopeMapping = new Map<Element, Element>(); 607 Map<Element, Element> scopeMapping = new Map<Element, Element>();
608 for (Element element in scopeVariables) { 608 for (Element element in scopeVariables) {
609 // No need to box non-assignable elements. 609 // No need to box non-assignable elements.
610 if (!element.isAssignable()) continue; 610 if (!element.isAssignable) continue;
611 if (!mutatedVariables.contains(element)) continue; 611 if (!mutatedVariables.contains(element)) continue;
612 if (capturedVariableMapping.containsKey(element)) { 612 if (capturedVariableMapping.containsKey(element)) {
613 if (box == null) { 613 if (box == null) {
614 // TODO(floitsch): construct better box names. 614 // TODO(floitsch): construct better box names.
615 String boxName = 615 String boxName =
616 namer.getClosureVariableName('box', closureFieldCounter++); 616 namer.getClosureVariableName('box', closureFieldCounter++);
617 box = new BoxElement( 617 box = new BoxElement(
618 boxName, currentElement, compiler.types.dynamicType); 618 boxName, currentElement, compiler.types.dynamicType);
619 } 619 }
620 String elementName = element.name; 620 String elementName = element.name;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 for (Element enclosingElement = element.enclosingElement; 685 for (Element enclosingElement = element.enclosingElement;
686 enclosingElement != null && 686 enclosingElement != null &&
687 (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY 687 (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY
688 || enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR 688 || enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR
689 || enclosingElement.kind == ElementKind.CLASS 689 || enclosingElement.kind == ElementKind.CLASS
690 || enclosingElement.kind == ElementKind.FUNCTION 690 || enclosingElement.kind == ElementKind.FUNCTION
691 || enclosingElement.kind == ElementKind.GETTER 691 || enclosingElement.kind == ElementKind.GETTER
692 || enclosingElement.kind == ElementKind.SETTER); 692 || enclosingElement.kind == ElementKind.SETTER);
693 enclosingElement = enclosingElement.enclosingElement) { 693 enclosingElement = enclosingElement.enclosingElement) {
694 // TODO(johnniwinther): Simplify computed names. 694 // TODO(johnniwinther): Simplify computed names.
695 if (enclosingElement.isGenerativeConstructor() || 695 if (enclosingElement.isGenerativeConstructor ||
696 enclosingElement.isGenerativeConstructorBody() || 696 enclosingElement.isGenerativeConstructorBody ||
697 enclosingElement.isFactoryConstructor()) { 697 enclosingElement.isFactoryConstructor) {
698 parts = parts.prepend( 698 parts = parts.prepend(
699 Elements.reconstructConstructorName(enclosingElement)); 699 Elements.reconstructConstructorName(enclosingElement));
700 } else { 700 } else {
701 String surroundingName = 701 String surroundingName =
702 Elements.operatorNameToIdentifier(enclosingElement.name); 702 Elements.operatorNameToIdentifier(enclosingElement.name);
703 parts = parts.prepend(surroundingName); 703 parts = parts.prepend(surroundingName);
704 } 704 }
705 // A generative constructors's parent is the class; the class name is 705 // A generative constructors's parent is the class; the class name is
706 // already part of the generative constructor's name. 706 // already part of the generative constructor's name.
707 if (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR) break; 707 if (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR) break;
708 } 708 }
709 StringBuffer sb = new StringBuffer(); 709 StringBuffer sb = new StringBuffer();
710 parts.printOn(sb, '_'); 710 parts.printOn(sb, '_');
711 return sb.toString(); 711 return sb.toString();
712 } 712 }
713 713
714 ClosureClassMap globalizeClosure(FunctionExpression node, 714 ClosureClassMap globalizeClosure(FunctionExpression node,
715 TypedElement element) { 715 TypedElement element) {
716 String closureName = computeClosureName(element); 716 String closureName = computeClosureName(element);
717 ClassElement globalizedElement = new ClosureClassElement( 717 ClassElement globalizedElement = new ClosureClassElement(
718 node, closureName, compiler, element, element.getCompilationUnit()); 718 node, closureName, compiler, element, element.compilationUnit);
719 FunctionElement callElement = 719 FunctionElement callElement =
720 new SynthesizedCallMethodElementX(Compiler.CALL_OPERATOR_NAME, 720 new SynthesizedCallMethodElementX(Compiler.CALL_OPERATOR_NAME,
721 element, 721 element,
722 globalizedElement); 722 globalizedElement);
723 ClosureContainer enclosing = element.enclosingElement; 723 ClosureContainer enclosing = element.enclosingElement;
724 enclosing.nestedClosures.add(callElement); 724 enclosing.nestedClosures.add(callElement);
725 globalizedElement.addMember(callElement, compiler); 725 globalizedElement.addMember(callElement, compiler);
726 // The nested function's 'this' is the same as the one for the outer 726 // The nested function's 'this' is the same as the one for the outer
727 // function. It could be [null] if we are inside a static method. 727 // function. It could be [null] if we are inside a static method.
728 Element thisElement = closureData.thisElement; 728 Element thisElement = closureData.thisElement;
729 return new ClosureClassMap(element, globalizedElement, 729 return new ClosureClassMap(element, globalizedElement,
730 callElement, thisElement); 730 callElement, thisElement);
731 } 731 }
732 732
733 void visitInvokable(TypedElement element, Node node, void visitChildren()) { 733 void visitInvokable(TypedElement element, Node node, void visitChildren()) {
734 bool oldInsideClosure = insideClosure; 734 bool oldInsideClosure = insideClosure;
735 Element oldFunctionElement = currentElement; 735 Element oldFunctionElement = currentElement;
736 ClosureClassMap oldClosureData = closureData; 736 ClosureClassMap oldClosureData = closureData;
737 737
738 insideClosure = outermostElement != null; 738 insideClosure = outermostElement != null;
739 currentElement = element; 739 currentElement = element;
740 if (insideClosure) { 740 if (insideClosure) {
741 closures.add(node); 741 closures.add(node);
742 closureData = globalizeClosure(node, element); 742 closureData = globalizeClosure(node, element);
743 } else { 743 } else {
744 outermostElement = element; 744 outermostElement = element;
745 Element thisElement = null; 745 Element thisElement = null;
746 if (element.isInstanceMember() || element.isGenerativeConstructor()) { 746 if (element.isInstanceMember || element.isGenerativeConstructor) {
747 thisElement = new ThisElement(element, compiler.types.dynamicType); 747 thisElement = new ThisElement(element, compiler.types.dynamicType);
748 } 748 }
749 closureData = new ClosureClassMap(null, null, null, thisElement); 749 closureData = new ClosureClassMap(null, null, null, thisElement);
750 } 750 }
751 closureMappingCache[node] = closureData; 751 closureMappingCache[node] = closureData;
752 752
753 inNewScope(node, () { 753 inNewScope(node, () {
754 // We have to declare the implicit 'this' parameter. 754 // We have to declare the implicit 'this' parameter.
755 if (!insideClosure && closureData.thisElement != null) { 755 if (!insideClosure && closureData.thisElement != null) {
756 declareLocal(closureData.thisElement); 756 declareLocal(closureData.thisElement);
757 } 757 }
758 // If we are inside a named closure we have to declare ourselve. For 758 // If we are inside a named closure we have to declare ourselve. For
759 // simplicity we declare the local even if the closure does not have a 759 // simplicity we declare the local even if the closure does not have a
760 // name. 760 // name.
761 // It will simply not be used. 761 // It will simply not be used.
762 if (insideClosure) { 762 if (insideClosure) {
763 declareLocal(element); 763 declareLocal(element);
764 } 764 }
765 765
766 if (currentElement.isFactoryConstructor() && 766 if (currentElement.isFactoryConstructor &&
767 compiler.backend.classNeedsRti(currentElement.enclosingElement)) { 767 compiler.backend.classNeedsRti(currentElement.enclosingElement)) {
768 // Declare the type parameters in the scope. Generative 768 // Declare the type parameters in the scope. Generative
769 // constructors just use 'this'. 769 // constructors just use 'this'.
770 ClassElement cls = currentElement.enclosingElement; 770 ClassElement cls = currentElement.enclosingElement;
771 cls.typeVariables.forEach((TypeVariableType typeVariable) { 771 cls.typeVariables.forEach((TypeVariableType typeVariable) {
772 declareLocal(typeVariable.element); 772 declareLocal(typeVariable.element);
773 }); 773 });
774 } 774 }
775 775
776 DartType type = element.computeType(compiler); 776 DartType type = element.computeType(compiler);
(...skipping 26 matching lines...) Expand all
803 compiler.internalError(node, 'In closure analyzer.'); 803 compiler.internalError(node, 'In closure analyzer.');
804 } 804 }
805 capturedVariableMapping[freeElement] = freeElement; 805 capturedVariableMapping[freeElement] = freeElement;
806 useLocal(freeElement); 806 useLocal(freeElement);
807 } 807 }
808 } 808 }
809 809
810 visitFunctionExpression(FunctionExpression node) { 810 visitFunctionExpression(FunctionExpression node) {
811 Element element = elements[node]; 811 Element element = elements[node];
812 812
813 if (element.isParameter()) { 813 if (element.isParameter) {
814 // TODO(ahe): This is a hack. This method should *not* call 814 // TODO(ahe): This is a hack. This method should *not* call
815 // visitChildren. 815 // visitChildren.
816 return node.name.accept(this); 816 return node.name.accept(this);
817 } 817 }
818 818
819 visitInvokable(element, node, () { 819 visitInvokable(element, node, () {
820 // TODO(ahe): This is problematic. The backend should not repeat 820 // TODO(ahe): This is problematic. The backend should not repeat
821 // the work of the resolver. It is the resolver's job to create 821 // the work of the resolver. It is the resolver's job to create
822 // parameters, etc. Other phases should only visit statements. 822 // parameters, etc. Other phases should only visit statements.
823 if (node.parameters != null) node.parameters.accept(this); 823 if (node.parameters != null) node.parameters.accept(this);
824 if (node.initializers != null) node.initializers.accept(this); 824 if (node.initializers != null) node.initializers.accept(this);
825 if (node.body != null) node.body.accept(this); 825 if (node.body != null) node.body.accept(this);
826 }); 826 });
827 } 827 }
828 828
829 visitFunctionDeclaration(FunctionDeclaration node) { 829 visitFunctionDeclaration(FunctionDeclaration node) {
830 node.visitChildren(this); 830 node.visitChildren(this);
831 declareLocal(elements[node]); 831 declareLocal(elements[node]);
832 } 832 }
833 833
834 visitTryStatement(TryStatement node) { 834 visitTryStatement(TryStatement node) {
835 // TODO(ngeoffray): implement finer grain state. 835 // TODO(ngeoffray): implement finer grain state.
836 bool oldInTryStatement = inTryStatement; 836 bool oldInTryStatement = inTryStatement;
837 inTryStatement = true; 837 inTryStatement = true;
838 node.visitChildren(this); 838 node.visitChildren(this);
839 inTryStatement = oldInTryStatement; 839 inTryStatement = oldInTryStatement;
840 } 840 }
841 } 841 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/compile_time_constants.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698