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

Side by Side Diff: pkg/compiler/lib/src/closure.dart

Issue 1428853004: Use better names for captured variables in closures. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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
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 'common.dart'; 7 import 'common.dart';
8 import 'common/names.dart' show 8 import 'common/names.dart' show
9 Identifiers; 9 Identifiers;
10 import 'common/resolution.dart' show 10 import 'common/resolution.dart' show
11 Parsing, 11 Parsing,
12 Resolution; 12 Resolution;
13 import 'common/tasks.dart' show 13 import 'common/tasks.dart' show
14 CompilerTask; 14 CompilerTask;
15 import 'compiler.dart' show 15 import 'compiler.dart' show
16 Compiler; 16 Compiler;
17 import 'constants/expressions.dart'; 17 import 'constants/expressions.dart';
18 import 'dart_types.dart'; 18 import 'dart_types.dart';
19 import 'elements/elements.dart'; 19 import 'elements/elements.dart';
20 import 'elements/modelx.dart' show 20 import 'elements/modelx.dart' show
21 BaseFunctionElementX, 21 BaseFunctionElementX,
22 ClassElementX, 22 ClassElementX,
23 ElementX, 23 ElementX,
24 LocalFunctionElementX; 24 LocalFunctionElementX;
25 import 'elements/visitor.dart' show ElementVisitor; 25 import 'elements/visitor.dart' show ElementVisitor;
26 import 'js_backend/js_backend.dart' show JavaScriptBackend; 26 import 'js_backend/js_backend.dart' show
27 JavaScriptBackend,
28 NamingScope,
29 NameProposingEntity,
30 ScopeBearingEntity;
27 import 'resolution/tree_elements.dart' show TreeElements; 31 import 'resolution/tree_elements.dart' show TreeElements;
28 import 'tokens/token.dart' show Token; 32 import 'tokens/token.dart' show Token;
29 import 'tree/tree.dart'; 33 import 'tree/tree.dart';
30 import 'util/util.dart'; 34 import 'util/util.dart';
31 import 'universe/universe.dart' show 35 import 'universe/universe.dart' show
32 Universe; 36 Universe;
33 37
34 class ClosureTask extends CompilerTask { 38 class ClosureTask extends CompilerTask {
35 Map<Node, ClosureClassMap> closureMappingCache; 39 Map<Node, ClosureClassMap> closureMappingCache;
36 ClosureTask(Compiler compiler) 40 ClosureTask(Compiler compiler)
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 } 100 }
97 } 101 }
98 102
99 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as 103 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as
100 /// non-elements. 104 /// non-elements.
101 abstract class CapturedVariable implements Element {} 105 abstract class CapturedVariable implements Element {}
102 106
103 // TODO(ahe): These classes continuously cause problems. We need to 107 // TODO(ahe): These classes continuously cause problems. We need to
104 // find a more general solution. 108 // find a more general solution.
105 class ClosureFieldElement extends ElementX 109 class ClosureFieldElement extends ElementX
106 implements FieldElement, CapturedVariable { 110 implements FieldElement, CapturedVariable, ScopeBearingEntity,
111 NameProposingEntity {
sra1 2015/11/04 02:27:48 I'm a bit concerned that such an early phase depen
herhut 2015/11/04 15:25:47 I have renamed NameProposingEntity to JsEntity wit
107 /// The [BoxLocal] or [LocalElement] being accessed through the field. 112 /// The [BoxLocal] or [LocalElement] being accessed through the field.
108 final Local local; 113 final Local local;
109 114
110 ClosureFieldElement(String name, 115 ClosureFieldElement(String name,
111 this.local, 116 this.local,
112 ClosureClassElement enclosing) 117 ClosureClassElement enclosing)
113 : super(name, ElementKind.FIELD, enclosing); 118 : super(name, ElementKind.FIELD, enclosing);
114 119
115 /// Use [closureClass] instead. 120 /// Use [closureClass] instead.
116 @deprecated 121 @deprecated
117 get enclosingElement => super.enclosingElement; 122 get enclosingElement => super.enclosingElement;
118 123
119 ClosureClassElement get closureClass => super.enclosingElement; 124 ClosureClassElement get closureClass => super.enclosingElement;
120 125
121 MemberElement get memberContext => closureClass.methodElement.memberContext; 126 MemberElement get memberContext => closureClass.methodElement.memberContext;
122 127
128 String proposeName() => local.name;
sra1 2015/11/04 04:09:25 Can this propose that the boxes are named nicely?
herhut 2015/11/04 15:25:47 No, this is just responsible for the name of the f
sra1 2015/11/04 17:59:22 The field is named after the BoxLocal. I tried it
herhut 2015/11/05 10:33:47 Oh yeah, you are right. But it would be nice to gi
129 NamingScope get namingScope => closureClass.fieldScope;
130
123 bool get hasNode => false; 131 bool get hasNode => false;
124 132
125 Node get node { 133 Node get node {
126 throw new SpannableAssertionFailure(local, 134 throw new SpannableAssertionFailure(local,
127 'Should not access node of ClosureFieldElement.'); 135 'Should not access node of ClosureFieldElement.');
128 } 136 }
129 137
130 bool get hasResolvedAst => hasTreeElements; 138 bool get hasResolvedAst => hasTreeElements;
131 139
132 ResolvedAst get resolvedAst { 140 ResolvedAst get resolvedAst {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 FunctionType callType; 182 FunctionType callType;
175 /// Node that corresponds to this closure, used for source position. 183 /// Node that corresponds to this closure, used for source position.
176 final FunctionExpression node; 184 final FunctionExpression node;
177 185
178 /** 186 /**
179 * The element for the declaration of the function expression. 187 * The element for the declaration of the function expression.
180 */ 188 */
181 final LocalFunctionElement methodElement; 189 final LocalFunctionElement methodElement;
182 190
183 final List<ClosureFieldElement> _closureFields = <ClosureFieldElement>[]; 191 final List<ClosureFieldElement> _closureFields = <ClosureFieldElement>[];
192 final NamingScope fieldScope = new NamingScope();
184 193
185 ClosureClassElement(this.node, 194 ClosureClassElement(this.node,
186 String name, 195 String name,
187 Compiler compiler, 196 Compiler compiler,
188 LocalFunctionElement closure) 197 LocalFunctionElement closure)
189 : this.methodElement = closure, 198 : this.methodElement = closure,
190 super(name, 199 super(name,
191 closure.compilationUnit, 200 closure.compilationUnit,
192 // By assigning a fresh class-id we make sure that the hashcode 201 // By assigning a fresh class-id we make sure that the hashcode
193 // is unique, but also emit closure classes after all other 202 // is unique, but also emit closure classes after all other
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 accept(ElementVisitor visitor, arg) { 241 accept(ElementVisitor visitor, arg) {
233 return visitor.visitClosureClassElement(this, arg); 242 return visitor.visitClosureClassElement(this, arg);
234 } 243 }
235 } 244 }
236 245
237 /// A local variable that contains the box object holding the [BoxFieldElement] 246 /// A local variable that contains the box object holding the [BoxFieldElement]
238 /// fields. 247 /// fields.
239 class BoxLocal extends Local { 248 class BoxLocal extends Local {
240 final String name; 249 final String name;
241 final ExecutableElement executableContext; 250 final ExecutableElement executableContext;
251 final NamingScope boxScope = new NamingScope();
sra1 2015/11/04 02:27:48 Is it possible to make this data emphemeral to the
herhut 2015/11/04 15:25:47 I have now changed the interface, so that all Fiel
242 252
243 BoxLocal(this.name, this.executableContext); 253 BoxLocal(this.name, this.executableContext);
244 } 254 }
245 255
246 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to 256 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to
247 // find a more general solution. 257 // find a more general solution.
248 class BoxFieldElement extends ElementX 258 class BoxFieldElement extends ElementX
249 implements TypedElement, CapturedVariable, FieldElement { 259 implements TypedElement, CapturedVariable, FieldElement,
260 NameProposingEntity, ScopeBearingEntity {
250 final BoxLocal box; 261 final BoxLocal box;
251 262
252 BoxFieldElement(String name, this.variableElement, BoxLocal box) 263 BoxFieldElement(String name, this.variableElement,
264 BoxLocal box)
253 : this.box = box, 265 : this.box = box,
254 super(name, ElementKind.FIELD, box.executableContext); 266 super(name, ElementKind.FIELD, box.executableContext);
255 267
256 DartType computeType(Resolution resolution) => type; 268 DartType computeType(Resolution resolution) => type;
257 269
258 DartType get type => variableElement.type; 270 DartType get type => variableElement.type;
259 271
272 String proposeName() => variableElement.name;
Siggi Cherem (dart-lang) 2015/11/03 17:21:34 totally up to you: it seems that all these cases f
herhut 2015/11/04 15:25:47 Done.
273 NamingScope get namingScope => box.boxScope;
274
260 final VariableElement variableElement; 275 final VariableElement variableElement;
261 276
262 accept(ElementVisitor visitor, arg) { 277 accept(ElementVisitor visitor, arg) {
263 return visitor.visitBoxFieldElement(this, arg); 278 return visitor.visitBoxFieldElement(this, arg);
264 } 279 }
265 280
266 @override 281 @override
267 bool get hasNode => false; 282 bool get hasNode => false;
268 283
269 @override 284 @override
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 /// Generate a unique name for the [id]th closure field, with proposed name 528 /// Generate a unique name for the [id]th closure field, with proposed name
514 /// [name]. 529 /// [name].
515 /// 530 ///
516 /// The result is used as the name of [ClosureFieldElement]s, and must 531 /// The result is used as the name of [ClosureFieldElement]s, and must
517 /// therefore be unique to avoid breaking an invariant in the element model 532 /// therefore be unique to avoid breaking an invariant in the element model
518 /// (classes cannot declare multiple fields with the same name). 533 /// (classes cannot declare multiple fields with the same name).
519 /// 534 ///
520 /// Also, the names should be distinct from real field names to prevent 535 /// Also, the names should be distinct from real field names to prevent
521 /// clashes with selectors for those fields. 536 /// clashes with selectors for those fields.
522 String getClosureVariableName(String name, int id) { 537 String getClosureVariableName(String name, int id) {
523 return "_captured_${name}_$id"; 538 return "_captured_${name}_$id";
sra1 2015/11/04 02:27:48 Why do we still need this if we have a scope? If
herhut 2015/11/04 15:25:47 This is the name of the element, which has to obey
524 } 539 }
525 540
526 /// Generate a unique name for the [id]th box field, with proposed name 541 /// Generate a unique name for the [id]th box field, with proposed name
527 /// [name]. 542 /// [name].
528 /// 543 ///
529 /// The result is used as the name of [BoxFieldElement]s, and must 544 /// The result is used as the name of [BoxFieldElement]s, and must
530 /// therefore be unique to avoid breaking an invariant in the element model 545 /// therefore be unique to avoid breaking an invariant in the element model
531 /// (classes cannot declare multiple fields with the same name). 546 /// (classes cannot declare multiple fields with the same name).
532 /// 547 ///
533 /// Also, the names should be distinct from real field names to prevent 548 /// Also, the names should be distinct from real field names to prevent
534 /// clashes with selectors for those fields. 549 /// clashes with selectors for those fields.
550 ///
551 /// These names are not used in generated code, just as element name.
535 String getBoxFieldName(int id) { 552 String getBoxFieldName(int id) {
536 return "_box_$id"; 553 return "_box_$id";
537 } 554 }
538 555
539 bool isCapturedVariable(Local element) { 556 bool isCapturedVariable(Local element) {
540 return _capturedVariableMapping.containsKey(element); 557 return _capturedVariableMapping.containsKey(element);
541 } 558 }
542 559
543 void addCapturedVariable(Node node, Local variable) { 560 void addCapturedVariable(Node node, Local variable) {
544 if (_capturedVariableMapping[variable] != null) { 561 if (_capturedVariableMapping[variable] != null) {
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 1144
1128 String get name => typeVariable.name; 1145 String get name => typeVariable.name;
1129 1146
1130 int get hashCode => typeVariable.hashCode; 1147 int get hashCode => typeVariable.hashCode;
1131 1148
1132 bool operator ==(other) { 1149 bool operator ==(other) {
1133 if (other is! TypeVariableLocal) return false; 1150 if (other is! TypeVariableLocal) return false;
1134 return typeVariable == other.typeVariable; 1151 return typeVariable == other.typeVariable;
1135 } 1152 }
1136 } 1153 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_backend/field_naming_mixin.dart » ('j') | pkg/compiler/lib/src/js_backend/namer.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698