| OLD | NEW |
| 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 25 matching lines...) Expand all Loading... |
| 36 if (cached != null) return cached; | 36 if (cached != null) return cached; |
| 37 | 37 |
| 38 ClosureTranslator translator = | 38 ClosureTranslator translator = |
| 39 new ClosureTranslator(compiler, elements, closureMappingCache, namer); | 39 new ClosureTranslator(compiler, elements, closureMappingCache, namer); |
| 40 | 40 |
| 41 // The translator will store the computed closure-mappings inside the | 41 // The translator will store the computed closure-mappings inside the |
| 42 // cache. One for given node and one for each nested closure. | 42 // cache. One for given node and one for each nested closure. |
| 43 if (node is FunctionExpression) { | 43 if (node is FunctionExpression) { |
| 44 translator.translateFunction(element, node); | 44 translator.translateFunction(element, node); |
| 45 } else if (element.isSynthesized) { | 45 } else if (element.isSynthesized) { |
| 46 return new ClosureClassMap(null, null, null, | 46 return new ClosureClassMap(null, null, null, new ThisElement(element)); |
| 47 new ThisElement(element, compiler.types.dynamicType)); | |
| 48 } else { | 47 } else { |
| 49 assert(element.isField); | 48 assert(element.isField); |
| 50 VariableElement field = element; | 49 VariableElement field = element; |
| 51 if (field.initializer != null) { | 50 if (field.initializer != null) { |
| 52 // The lazy initializer of a static. | 51 // The lazy initializer of a static. |
| 53 translator.translateLazyInitializer(element, node, field.initializer); | 52 translator.translateLazyInitializer(element, node, field.initializer); |
| 54 } else { | 53 } else { |
| 55 assert(element.isInstanceMember); | 54 assert(element.isInstanceMember); |
| 56 closureMappingCache[node] = | 55 closureMappingCache[node] = |
| 57 new ClosureClassMap(null, null, null, | 56 new ClosureClassMap(null, null, null, new ThisElement(element)); |
| 58 new ThisElement(element, compiler.types.dynamicType)); | |
| 59 } | 57 } |
| 60 } | 58 } |
| 61 assert(closureMappingCache[node] != null); | 59 assert(closureMappingCache[node] != null); |
| 62 return closureMappingCache[node]; | 60 return closureMappingCache[node]; |
| 63 }); | 61 }); |
| 64 } | 62 } |
| 65 | 63 |
| 66 ClosureClassMap getMappingForNestedFunction(FunctionExpression node) { | 64 ClosureClassMap getMappingForNestedFunction(FunctionExpression node) { |
| 67 return measure(() { | 65 return measure(() { |
| 68 ClosureClassMap nestedClosureData = closureMappingCache[node]; | 66 ClosureClassMap nestedClosureData = closureMappingCache[node]; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 162 |
| 165 get enclosingElement => methodElement; | 163 get enclosingElement => methodElement; |
| 166 | 164 |
| 167 accept(ElementVisitor visitor) => visitor.visitClosureClassElement(this); | 165 accept(ElementVisitor visitor) => visitor.visitClosureClassElement(this); |
| 168 } | 166 } |
| 169 | 167 |
| 170 // TODO(ahe): These classes continuously cause problems. We need to | 168 // TODO(ahe): These classes continuously cause problems. We need to |
| 171 // move these classes to elements/modelx.dart or see if we can find a | 169 // move these classes to elements/modelx.dart or see if we can find a |
| 172 // more general solution. | 170 // more general solution. |
| 173 class BoxElement extends ElementX implements TypedElement { | 171 class BoxElement extends ElementX implements TypedElement { |
| 174 final DartType type; | 172 BoxElement(String name, Element enclosingElement) |
| 175 | |
| 176 BoxElement(String name, Element enclosingElement, this.type) | |
| 177 : super(name, ElementKind.VARIABLE_LIST, enclosingElement); | 173 : super(name, ElementKind.VARIABLE_LIST, enclosingElement); |
| 178 | 174 |
| 179 DartType computeType(Compiler compiler) => type; | 175 DartType computeType(Compiler compiler) => type; |
| 180 | 176 |
| 177 DartType get type => const DynamicType(); |
| 178 |
| 181 accept(ElementVisitor visitor) => visitor.visitBoxElement(this); | 179 accept(ElementVisitor visitor) => visitor.visitBoxElement(this); |
| 182 } | 180 } |
| 183 | 181 |
| 184 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to | 182 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to |
| 185 // move these classes to elements/modelx.dart or see if we can find a | 183 // move these classes to elements/modelx.dart or see if we can find a |
| 186 // more general solution. | 184 // more general solution. |
| 187 class BoxFieldElement extends ElementX implements TypedElement { | 185 class BoxFieldElement extends ElementX implements TypedElement { |
| 188 BoxFieldElement(String name, | 186 BoxFieldElement(String name, |
| 189 this.variableElement, | 187 this.variableElement, |
| 190 BoxElement enclosingBox) | 188 BoxElement enclosingBox) |
| 191 : super(name, ElementKind.FIELD, enclosingBox); | 189 : super(name, ElementKind.FIELD, enclosingBox); |
| 192 | 190 |
| 193 DartType computeType(Compiler compiler) => type; | 191 DartType computeType(Compiler compiler) => type; |
| 194 | 192 |
| 195 DartType get type => variableElement.type; | 193 DartType get type => variableElement.type; |
| 196 | 194 |
| 197 final VariableElement variableElement; | 195 final VariableElement variableElement; |
| 198 | 196 |
| 199 accept(ElementVisitor visitor) => visitor.visitBoxFieldElement(this); | 197 accept(ElementVisitor visitor) => visitor.visitBoxFieldElement(this); |
| 200 } | 198 } |
| 201 | 199 |
| 202 // TODO(ahe): These classes continuously cause problems. We need to | 200 // TODO(ahe): These classes continuously cause problems. We need to |
| 203 // move these classes to elements/modelx.dart or see if we can find a | 201 // move these classes to elements/modelx.dart or see if we can find a |
| 204 // more general solution. | 202 // more general solution. |
| 205 class ThisElement extends ElementX implements TypedElement { | 203 class ThisElement extends ElementX implements TypedElement { |
| 206 final DartType type; | 204 ThisElement(Element enclosing) |
| 207 | |
| 208 ThisElement(Element enclosing, this.type) | |
| 209 : super('this', ElementKind.PARAMETER, enclosing); | 205 : super('this', ElementKind.PARAMETER, enclosing); |
| 210 | 206 |
| 211 bool get isAssignable => false; | 207 bool get isAssignable => false; |
| 212 | 208 |
| 213 DartType computeType(Compiler compiler) => compiler.types.dynamicType; | 209 DartType computeType(Compiler compiler) => type; |
| 210 |
| 211 DartType get type => const DynamicType(); |
| 214 | 212 |
| 215 // Since there is no declaration corresponding to 'this', use the position of | 213 // Since there is no declaration corresponding to 'this', use the position of |
| 216 // the enclosing method. | 214 // the enclosing method. |
| 217 Token get position => enclosingElement.position; | 215 Token get position => enclosingElement.position; |
| 218 | 216 |
| 219 accept(ElementVisitor visitor) => visitor.visitThisElement(this); | 217 accept(ElementVisitor visitor) => visitor.visitThisElement(this); |
| 220 } | 218 } |
| 221 | 219 |
| 222 /// Call method of a closure class. | 220 /// Call method of a closure class. |
| 223 class SynthesizedCallMethodElementX extends FunctionElementX { | 221 class SynthesizedCallMethodElementX extends FunctionElementX { |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 for (Element element in scopeVariables) { | 628 for (Element element in scopeVariables) { |
| 631 // No need to box non-assignable elements. | 629 // No need to box non-assignable elements. |
| 632 if (!element.isAssignable) continue; | 630 if (!element.isAssignable) continue; |
| 633 if (!mutatedVariables.contains(element)) continue; | 631 if (!mutatedVariables.contains(element)) continue; |
| 634 if (capturedVariableMapping.containsKey(element)) { | 632 if (capturedVariableMapping.containsKey(element)) { |
| 635 if (box == null) { | 633 if (box == null) { |
| 636 // TODO(floitsch): construct better box names. | 634 // TODO(floitsch): construct better box names. |
| 637 String boxName = | 635 String boxName = |
| 638 namer.getClosureVariableName('box', closureFieldCounter++); | 636 namer.getClosureVariableName('box', closureFieldCounter++); |
| 639 box = new BoxElement( | 637 box = new BoxElement( |
| 640 boxName, currentElement, compiler.types.dynamicType); | 638 boxName, currentElement); |
| 641 } | 639 } |
| 642 String elementName = element.name; | 640 String elementName = element.name; |
| 643 String boxedName = | 641 String boxedName = |
| 644 namer.getClosureVariableName(elementName, boxedFieldCounter++); | 642 namer.getClosureVariableName(elementName, boxedFieldCounter++); |
| 645 // TODO(kasperl): Should this be a FieldElement instead? | 643 // TODO(kasperl): Should this be a FieldElement instead? |
| 646 Element boxed = new BoxFieldElement(boxedName, element, box); | 644 Element boxed = new BoxFieldElement(boxedName, element, box); |
| 647 // No need to rename the fields of a box, so we give them a native name | 645 // No need to rename the fields of a box, so we give them a native name |
| 648 // right now. | 646 // right now. |
| 649 boxed.setFixedBackendName(boxedName); | 647 boxed.setFixedBackendName(boxedName); |
| 650 scopeMapping[element] = boxed; | 648 scopeMapping[element] = boxed; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 | 757 |
| 760 insideClosure = outermostElement != null; | 758 insideClosure = outermostElement != null; |
| 761 currentElement = element; | 759 currentElement = element; |
| 762 if (insideClosure) { | 760 if (insideClosure) { |
| 763 closures.add(node); | 761 closures.add(node); |
| 764 closureData = globalizeClosure(node, element); | 762 closureData = globalizeClosure(node, element); |
| 765 } else { | 763 } else { |
| 766 outermostElement = element; | 764 outermostElement = element; |
| 767 Element thisElement = null; | 765 Element thisElement = null; |
| 768 if (element.isInstanceMember || element.isGenerativeConstructor) { | 766 if (element.isInstanceMember || element.isGenerativeConstructor) { |
| 769 thisElement = new ThisElement(element, compiler.types.dynamicType); | 767 thisElement = new ThisElement(element); |
| 770 } | 768 } |
| 771 closureData = new ClosureClassMap(null, null, null, thisElement); | 769 closureData = new ClosureClassMap(null, null, null, thisElement); |
| 772 } | 770 } |
| 773 closureMappingCache[node] = closureData; | 771 closureMappingCache[node] = closureData; |
| 774 | 772 |
| 775 inNewScope(node, () { | 773 inNewScope(node, () { |
| 776 // We have to declare the implicit 'this' parameter. | 774 // We have to declare the implicit 'this' parameter. |
| 777 if (!insideClosure && closureData.thisElement != null) { | 775 if (!insideClosure && closureData.thisElement != null) { |
| 778 declareLocal(closureData.thisElement); | 776 declareLocal(closureData.thisElement); |
| 779 } | 777 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 } | 852 } |
| 855 | 853 |
| 856 visitTryStatement(TryStatement node) { | 854 visitTryStatement(TryStatement node) { |
| 857 // TODO(ngeoffray): implement finer grain state. | 855 // TODO(ngeoffray): implement finer grain state. |
| 858 bool oldInTryStatement = inTryStatement; | 856 bool oldInTryStatement = inTryStatement; |
| 859 inTryStatement = true; | 857 inTryStatement = true; |
| 860 node.visitChildren(this); | 858 node.visitChildren(this); |
| 861 inTryStatement = oldInTryStatement; | 859 inTryStatement = oldInTryStatement; |
| 862 } | 860 } |
| 863 } | 861 } |
| OLD | NEW |