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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 } | 60 } |
61 return nestedClosureData; | 61 return nestedClosureData; |
62 }); | 62 }); |
63 } | 63 } |
64 } | 64 } |
65 | 65 |
66 // TODO(ahe): These classes continuously cause problems. We need to | 66 // TODO(ahe): These classes continuously cause problems. We need to |
67 // move these classes to elements/modelx.dart or see if we can find a | 67 // move these classes to elements/modelx.dart or see if we can find a |
68 // more general solution. | 68 // more general solution. |
69 class ClosureFieldElement extends ElementX { | 69 class ClosureFieldElement extends ElementX { |
70 ClosureFieldElement(SourceString name, ClassElement enclosing) | 70 ClosureFieldElement(SourceString name, |
| 71 this.variableElement, |
| 72 ClassElement enclosing) |
71 : super(name, ElementKind.FIELD, enclosing); | 73 : super(name, ElementKind.FIELD, enclosing); |
72 | 74 |
73 bool isInstanceMember() => true; | 75 bool isInstanceMember() => true; |
74 bool isAssignable() => false; | 76 bool isAssignable() => false; |
75 // The names of closure variables don't need renaming, since their use is very | 77 // The names of closure variables don't need renaming, since their use is very |
76 // simple and they have 1-character names in the minified mode. | 78 // simple and they have 1-character names in the minified mode. |
77 bool hasFixedBackendName() => true; | 79 bool hasFixedBackendName() => true; |
78 String fixedBackendName() => name.slowToString(); | 80 String fixedBackendName() => name.slowToString(); |
79 | 81 |
80 DartType computeType(Compiler compiler) => compiler.types.dynamicType; | 82 DartType computeType(Compiler compiler) { |
| 83 return variableElement.computeType(compiler); |
| 84 } |
81 | 85 |
82 String toString() => "ClosureFieldElement($name)"; | 86 String toString() => "ClosureFieldElement($name)"; |
| 87 |
| 88 /** |
| 89 * The source variable this element refers to. |
| 90 */ |
| 91 final Element variableElement; |
83 } | 92 } |
84 | 93 |
85 // TODO(ahe): These classes continuously cause problems. We need to | 94 // TODO(ahe): These classes continuously cause problems. We need to |
86 // move these classes to elements/modelx.dart or see if we can find a | 95 // move these classes to elements/modelx.dart or see if we can find a |
87 // more general solution. | 96 // more general solution. |
88 class ClosureClassElement extends ClassElementX { | 97 class ClosureClassElement extends ClassElementX { |
89 DartType rawType; | 98 DartType rawType; |
90 DartType thisType; | 99 DartType thisType; |
91 /// Node that corresponds to this closure, used for source position. | 100 /// Node that corresponds to this closure, used for source position. |
92 final FunctionExpression node; | 101 final FunctionExpression node; |
(...skipping 19 matching lines...) Expand all Loading... |
112 | 121 |
113 bool isClosure() => true; | 122 bool isClosure() => true; |
114 | 123 |
115 Token position() => node.getBeginToken(); | 124 Token position() => node.getBeginToken(); |
116 | 125 |
117 Node parseNode(DiagnosticListener listener) => node; | 126 Node parseNode(DiagnosticListener listener) => node; |
118 | 127 |
119 /** | 128 /** |
120 * The most outer method this closure is declared into. | 129 * The most outer method this closure is declared into. |
121 */ | 130 */ |
122 Element methodElement; | 131 final Element methodElement; |
123 } | 132 } |
124 | 133 |
125 // TODO(ahe): These classes continuously cause problems. We need to | 134 // TODO(ahe): These classes continuously cause problems. We need to |
126 // move these classes to elements/modelx.dart or see if we can find a | 135 // move these classes to elements/modelx.dart or see if we can find a |
127 // more general solution. | 136 // more general solution. |
128 class BoxElement extends ElementX { | 137 class BoxElement extends ElementX { |
129 BoxElement(SourceString name, Element enclosingElement) | 138 BoxElement(SourceString name, Element enclosingElement) |
130 : super(name, ElementKind.VARIABLE, enclosingElement); | 139 : super(name, ElementKind.VARIABLE, enclosingElement); |
| 140 |
| 141 DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
| 142 } |
| 143 |
| 144 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to |
| 145 // move these classes to elements/modelx.dart or see if we can find a |
| 146 // more general solution. |
| 147 class BoxFieldElement extends ElementX { |
| 148 BoxFieldElement(SourceString name, |
| 149 this.variableElement, |
| 150 BoxElement enclosingBox) |
| 151 : super(name, ElementKind.FIELD, enclosingBox); |
| 152 |
| 153 DartType computeType(Compiler compiler) { |
| 154 return variableElement.computeType(compiler); |
| 155 } |
| 156 |
| 157 final Element variableElement; |
131 } | 158 } |
132 | 159 |
133 // TODO(ahe): These classes continuously cause problems. We need to | 160 // TODO(ahe): These classes continuously cause problems. We need to |
134 // move these classes to elements/modelx.dart or see if we can find a | 161 // move these classes to elements/modelx.dart or see if we can find a |
135 // more general solution. | 162 // more general solution. |
136 class ThisElement extends ElementX { | 163 class ThisElement extends ElementX { |
137 ThisElement(Element enclosing) | 164 ThisElement(Element enclosing) |
138 : super(const SourceString('this'), ElementKind.PARAMETER, enclosing); | 165 : super(const SourceString('this'), ElementKind.PARAMETER, enclosing); |
139 | 166 |
140 bool isAssignable() => false; | 167 bool isAssignable() => false; |
141 | 168 |
| 169 DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
| 170 |
142 // Since there is no declaration corresponding to 'this', use the position of | 171 // Since there is no declaration corresponding to 'this', use the position of |
143 // the enclosing method. | 172 // the enclosing method. |
144 Token position() => enclosingElement.position(); | 173 Token position() => enclosingElement.position(); |
145 } | 174 } |
146 | 175 |
147 // TODO(ahe): These classes continuously cause problems. We need to | 176 // TODO(ahe): These classes continuously cause problems. We need to |
148 // move these classes to elements/modelx.dart or see if we can find a | 177 // move these classes to elements/modelx.dart or see if we can find a |
149 // more general solution. | 178 // more general solution. |
150 class CheckVariableElement extends ElementX { | 179 class CheckVariableElement extends ElementX { |
151 Element parameter; | 180 Element parameter; |
152 CheckVariableElement(SourceString name, this.parameter, Element enclosing) | 181 CheckVariableElement(SourceString name, this.parameter, Element enclosing) |
153 : super(name, ElementKind.VARIABLE, enclosing); | 182 : super(name, ElementKind.VARIABLE, enclosing); |
154 | 183 |
| 184 DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
| 185 |
155 // Since there is no declaration for the synthetic 'check' variable, use | 186 // Since there is no declaration for the synthetic 'check' variable, use |
156 // parameter. | 187 // parameter. |
157 Token position() => parameter.position(); | 188 Token position() => parameter.position(); |
158 } | 189 } |
159 | 190 |
160 // The box-element for a scope, and the captured variables that need to be | 191 // The box-element for a scope, and the captured variables that need to be |
161 // stored in the box. | 192 // stored in the box. |
162 class ClosureScope { | 193 class ClosureScope { |
163 Element boxElement; | 194 Element boxElement; |
164 Map<Element, Element> capturedVariableMapping; | 195 Map<Element, Element> capturedVariableMapping; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 | 252 |
222 bool isVariableCaptured(Element element) { | 253 bool isVariableCaptured(Element element) { |
223 freeVariableMapping.containsKey(element); | 254 freeVariableMapping.containsKey(element); |
224 } | 255 } |
225 | 256 |
226 bool isVariableBoxed(Element element) { | 257 bool isVariableBoxed(Element element) { |
227 Element copy = freeVariableMapping[element]; | 258 Element copy = freeVariableMapping[element]; |
228 return copy != null && !copy.isMember(); | 259 return copy != null && !copy.isMember(); |
229 } | 260 } |
230 | 261 |
231 void forEachCapturedVariable(void f(Element element)) { | 262 void forEachCapturedVariable(void f(Element local, Element field)) { |
232 freeVariableMapping.forEach((variable, _) { | 263 freeVariableMapping.forEach((variable, copy) { |
233 if (variable is BoxElement) return; | 264 if (variable is BoxElement) return; |
234 f(variable); | 265 f(variable, copy); |
235 }); | 266 }); |
236 } | 267 } |
237 | 268 |
238 void forEachBoxedVariable(void f(Element element)) { | 269 void forEachBoxedVariable(void f(Element local, Element field)) { |
239 freeVariableMapping.forEach((variable, copy) { | 270 freeVariableMapping.forEach((variable, copy) { |
240 if (!isVariableBoxed(variable)) return; | 271 if (!isVariableBoxed(variable)) return; |
241 f(variable); | 272 f(variable, copy); |
242 }); | 273 }); |
243 } | 274 } |
244 | 275 |
245 void forEachNonBoxedCapturedVariable(void f(Element element)) { | 276 void forEachNonBoxedCapturedVariable(void f(Element local, Element field)) { |
246 freeVariableMapping.forEach((variable, copy) { | 277 freeVariableMapping.forEach((variable, copy) { |
247 if (variable is BoxElement) return; | 278 if (variable is BoxElement) return; |
248 if (isVariableBoxed(variable)) return; | 279 if (isVariableBoxed(variable)) return; |
249 f(variable); | 280 f(variable, copy); |
250 }); | 281 }); |
251 } | 282 } |
252 } | 283 } |
253 | 284 |
254 class ClosureTranslator extends Visitor { | 285 class ClosureTranslator extends Visitor { |
255 final Compiler compiler; | 286 final Compiler compiler; |
256 final TreeElements elements; | 287 final TreeElements elements; |
257 int closureFieldCounter = 0; | 288 int closureFieldCounter = 0; |
258 int boxedFieldCounter = 0; | 289 int boxedFieldCounter = 0; |
259 bool inTryStatement = false; | 290 bool inTryStatement = false; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 freeVariableMapping[fromElement] = updatedElement; | 368 freeVariableMapping[fromElement] = updatedElement; |
338 Element boxElement = updatedElement.enclosingElement; | 369 Element boxElement = updatedElement.enclosingElement; |
339 assert(boxElement.kind == ElementKind.VARIABLE); | 370 assert(boxElement.kind == ElementKind.VARIABLE); |
340 boxes.add(boxElement); | 371 boxes.add(boxElement); |
341 } | 372 } |
342 }); | 373 }); |
343 ClassElement closureElement = data.closureClassElement; | 374 ClassElement closureElement = data.closureClassElement; |
344 assert(closureElement != null || | 375 assert(closureElement != null || |
345 (fieldCaptures.isEmpty && boxes.isEmpty)); | 376 (fieldCaptures.isEmpty && boxes.isEmpty)); |
346 void addElement(Element element, SourceString name) { | 377 void addElement(Element element, SourceString name) { |
347 Element fieldElement = new ClosureFieldElement(name, closureElement); | 378 Element fieldElement = new ClosureFieldElement( |
| 379 name, element, closureElement); |
348 closureElement.addMember(fieldElement, compiler); | 380 closureElement.addMember(fieldElement, compiler); |
349 data.capturedFieldMapping[fieldElement] = element; | 381 data.capturedFieldMapping[fieldElement] = element; |
350 freeVariableMapping[element] = fieldElement; | 382 freeVariableMapping[element] = fieldElement; |
351 } | 383 } |
352 // Add the box elements first so we get the same ordering. | 384 // Add the box elements first so we get the same ordering. |
353 // TODO(sra): What is the canonical order of multiple boxes? | 385 // TODO(sra): What is the canonical order of multiple boxes? |
354 for (Element capturedElement in boxes) { | 386 for (Element capturedElement in boxes) { |
355 addElement(capturedElement, capturedElement.name); | 387 addElement(capturedElement, capturedElement.name); |
356 } | 388 } |
357 for (Element capturedElement in | 389 for (Element capturedElement in |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 SourceString boxName = | 595 SourceString boxName = |
564 namer.getClosureVariableName(const SourceString('box'), | 596 namer.getClosureVariableName(const SourceString('box'), |
565 closureFieldCounter++); | 597 closureFieldCounter++); |
566 box = new BoxElement(boxName, currentElement); | 598 box = new BoxElement(boxName, currentElement); |
567 } | 599 } |
568 String elementName = element.name.slowToString(); | 600 String elementName = element.name.slowToString(); |
569 SourceString boxedName = | 601 SourceString boxedName = |
570 namer.getClosureVariableName(new SourceString(elementName), | 602 namer.getClosureVariableName(new SourceString(elementName), |
571 boxedFieldCounter++); | 603 boxedFieldCounter++); |
572 // TODO(kasperl): Should this be a FieldElement instead? | 604 // TODO(kasperl): Should this be a FieldElement instead? |
573 Element boxed = new ElementX(boxedName, ElementKind.FIELD, box); | 605 Element boxed = new BoxFieldElement(boxedName, element, box); |
574 // No need to rename the fields of a box, so we give them a native name | 606 // No need to rename the fields of a box, so we give them a native name |
575 // right now. | 607 // right now. |
576 boxed.setFixedBackendName(boxedName.slowToString()); | 608 boxed.setFixedBackendName(boxedName.slowToString()); |
577 scopeMapping[element] = boxed; | 609 scopeMapping[element] = boxed; |
578 capturedVariableMapping[element] = boxed; | 610 capturedVariableMapping[element] = boxed; |
579 } | 611 } |
580 } | 612 } |
581 if (!scopeMapping.isEmpty) { | 613 if (!scopeMapping.isEmpty) { |
582 ClosureScope scope = new ClosureScope(box, scopeMapping); | 614 ClosureScope scope = new ClosureScope(box, scopeMapping); |
583 closureData.capturingScopes[node] = scope; | 615 closureData.capturingScopes[node] = scope; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 } | 799 } |
768 | 800 |
769 visitTryStatement(TryStatement node) { | 801 visitTryStatement(TryStatement node) { |
770 // TODO(ngeoffray): implement finer grain state. | 802 // TODO(ngeoffray): implement finer grain state. |
771 bool oldInTryStatement = inTryStatement; | 803 bool oldInTryStatement = inTryStatement; |
772 inTryStatement = true; | 804 inTryStatement = true; |
773 node.visitChildren(this); | 805 node.visitChildren(this); |
774 inTryStatement = oldInTryStatement; | 806 inTryStatement = oldInTryStatement; |
775 } | 807 } |
776 } | 808 } |
OLD | NEW |