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

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

Issue 10834330: Clean-up of getCompilationUnit. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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/typechecker.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('elements'); 5 #library('elements');
6 6
7 #import('dart:uri'); 7 #import('dart:uri');
8 8
9 #import('../tree/tree.dart'); 9 #import('../tree/tree.dart');
10 #import('../scanner/scannerlib.dart'); 10 #import('../scanner/scannerlib.dart');
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 101
102 toString() => id; 102 toString() => id;
103 } 103 }
104 104
105 class Element implements Hashable { 105 class Element implements Hashable {
106 final SourceString name; 106 final SourceString name;
107 final ElementKind kind; 107 final ElementKind kind;
108 final Element enclosingElement; 108 final Element enclosingElement;
109 Link<Node> metadata = const EmptyLink<Node>(); 109 Link<Node> metadata = const EmptyLink<Node>();
110 110
111
112 Element(this.name, this.kind, this.enclosingElement) { 111 Element(this.name, this.kind, this.enclosingElement) {
113 assert(getLibrary() !== null); 112 assert(getLibrary() !== null);
114 } 113 }
115 114
116 Modifiers get modifiers() => null; 115 Modifiers get modifiers() => null;
117 116
118 Node parseNode(DiagnosticListener listener) { 117 Node parseNode(DiagnosticListener listener) {
119 listener.cancel("Internal Error: $this.parseNode", token: position()); 118 listener.cancel("Internal Error: $this.parseNode", token: position());
120 } 119 }
121 120
122 Type computeType(Compiler compiler) { 121 Type computeType(Compiler compiler) {
123 compiler.internalError("$this.computeType.", token: position()); 122 compiler.internalError("$this.computeType.", token: position());
124 } 123 }
125 124
126 void addMetadata(Node node) { 125 void addMetadata(Node node) {
127 metadata = metadata.prepend(node); 126 metadata = metadata.prepend(node);
128 } 127 }
129 128
130 bool isFunction() => kind === ElementKind.FUNCTION; 129 bool isFunction() => kind === ElementKind.FUNCTION;
131 bool isConstructor() => isFactoryConstructor() || isGenerativeConstructor(); 130 bool isConstructor() => isFactoryConstructor() || isGenerativeConstructor();
132 bool isClosure() => false; 131 bool isClosure() => false;
133 bool isMember() { 132 bool isMember() {
134 // Check that this element is defined in the scope of a Class. 133 // Check that this element is defined in the scope of a Class.
135 Element enclosing = enclosingElement; 134 Element enclosing = enclosingElement;
136 if (enclosing !== null && 135 if (enclosing !== null &&
137 enclosing.kind === ElementKind.COMPILATION_UNIT_OVERRIDE) { 136 enclosing.kind === ElementKind.COMPILATION_UNIT_OVERRIDE) {
138 enclosing = enclosing.enclosingElement; 137 enclosing = enclosing.enclosingElement;
139 } 138 }
140 // TODO(lrn): Skip any synthetic elements inserted, e.g.,
141 // a compilation unit override.
142 return enclosing !== null && enclosing.isClass(); 139 return enclosing !== null && enclosing.isClass();
143 } 140 }
144 bool isInstanceMember() => false; 141 bool isInstanceMember() => false;
145 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); 142 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory();
146 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; 143 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR;
147 bool isGenerativeConstructorBody() => 144 bool isGenerativeConstructorBody() =>
148 kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY; 145 kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY;
149 bool isCompilationUnit() { 146 bool isCompilationUnit() => kind === ElementKind.COMPILATION_UNIT;
150 return kind === ElementKind.COMPILATION_UNIT ||
151 kind === ElementKind.LIBRARY ||
152 kind === ElementKind.COMPILATION_UNIT_OVERRIDE;
153 }
154 /**
155 * Provides the compilation unit corresponding to this element.
156 * Returns non-null for elements where [isCompilationUnit] returns true,
157 * but may not return the current [Element].
158 */
159 CompilationUnitElement asCompilationUnit() => null;
160 bool isClass() => kind === ElementKind.CLASS; 147 bool isClass() => kind === ElementKind.CLASS;
161 bool isPrefix() => kind === ElementKind.PREFIX; 148 bool isPrefix() => kind === ElementKind.PREFIX;
162 bool isVariable() => kind === ElementKind.VARIABLE; 149 bool isVariable() => kind === ElementKind.VARIABLE;
163 bool isParameter() => kind === ElementKind.PARAMETER; 150 bool isParameter() => kind === ElementKind.PARAMETER;
164 bool isStatement() => kind === ElementKind.STATEMENT; 151 bool isStatement() => kind === ElementKind.STATEMENT;
165 bool isTypedef() => kind === ElementKind.TYPEDEF; 152 bool isTypedef() => kind === ElementKind.TYPEDEF;
166 bool isTypeVariable() => kind === ElementKind.TYPE_VARIABLE; 153 bool isTypeVariable() => kind === ElementKind.TYPE_VARIABLE;
167 bool isField() => kind === ElementKind.FIELD; 154 bool isField() => kind === ElementKind.FIELD;
168 bool isGetter() => kind === ElementKind.GETTER; 155 bool isGetter() => kind === ElementKind.GETTER;
169 bool isSetter() => kind === ElementKind.SETTER; 156 bool isSetter() => kind === ElementKind.SETTER;
170 bool isAccessor() => isGetter() || isSetter(); 157 bool isAccessor() => isGetter() || isSetter();
171 bool isForeign() => kind === ElementKind.FOREIGN; 158 bool isForeign() => kind === ElementKind.FOREIGN;
172 bool isLibrary() => kind === ElementKind.LIBRARY; 159 bool isLibrary() => kind === ElementKind.LIBRARY;
173 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; 160 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
174 bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0; 161 bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0;
175 162
176 // TODO(johnniwinther): This breaks for libraries (for which enclosing 163 // TODO(johnniwinther): This breaks for libraries (for which enclosing
177 // elements are null) and is invalid for top level variable declarations for 164 // elements are null) and is invalid for top level variable declarations for
178 // which the enclosing element is a VariableDeclarations and not a compilation 165 // which the enclosing element is a VariableDeclarations and not a compilation
179 // unit. 166 // unit.
180 bool isTopLevel() => enclosingElement.isCompilationUnit(); 167 bool isTopLevel() =>
168 enclosingElement !== null && enclosingElement.isCompilationUnit();
ahe 2012/08/15 10:00:19 I prefer to not use the short-hand function syntax
Lasse Reichstein Nielsen 2012/08/15 11:17:06 Done.
181 169
182 bool isAssignable() { 170 bool isAssignable() {
183 if (modifiers != null && modifiers.isFinal()) return false; 171 if (modifiers != null && modifiers.isFinal()) return false;
184 if (isFunction() || isGenerativeConstructor()) return false; 172 if (isFunction() || isGenerativeConstructor()) return false;
185 return true; 173 return true;
186 } 174 }
187 175
188 Token position() => null; 176 Token position() => null;
189 177
190 Token findMyName(Token token) { 178 Token findMyName(Token token) {
191 for (Token t = token; t.kind !== EOF_TOKEN; t = t.next) { 179 for (Token t = token; t.kind !== EOF_TOKEN; t = t.next) {
192 if (t.value == name) return t; 180 if (t.value == name) return t;
193 } 181 }
194 return token; 182 return token;
195 } 183 }
196 184
197 // TODO(kasperl): This is a very bad hash code for the element and 185 // TODO(kasperl): This is a very bad hash code for the element and
198 // there's no reason why two elements with the same name should have 186 // there's no reason why two elements with the same name should have
199 // the same hash code. Replace this with a simple id in the element? 187 // the same hash code. Replace this with a simple id in the element?
200 int hashCode() => name === null ? 0 : name.hashCode(); 188 int hashCode() => name === null ? 0 : name.hashCode();
201 189
202 Script getScript() {
203 return getCompilationUnit().script;
204 }
205
206 CompilationUnitElement getCompilationUnit() { 190 CompilationUnitElement getCompilationUnit() {
207 if (isCompilationUnit()) return this; 191 Element element = this;
208 return enclosingElement.getCompilationUnit(); 192 while (element !== null && !element.isCompilationUnit()) {
193 if (element is CompilationUnitOverrideElement) {
194 return (element as CompilationUnitOverrideElement).compilationUnit;
ahe 2012/08/15 10:00:19 Please don't use the cast operator.
Lasse Reichstein Nielsen 2012/08/15 11:17:06 Done.
195 }
196 if (element.isLibrary()) {
197 return (element as LibraryElement).entryCompilationUnit;
ahe 2012/08/15 10:00:19 Please don't use the cast operator.
Lasse Reichstein Nielsen 2012/08/15 11:17:06 Done.
198 }
199 if (element is FunctionElement &&
200 (element as FunctionElement).isPatched) {
ahe 2012/08/15 10:00:19 Please don't use cast operator.
Lasse Reichstein Nielsen 2012/08/15 11:17:06 Done.
201 element = (element as FunctionElement).patch;
Lasse Reichstein Nielsen 2012/08/15 09:09:12 This is still not sufficient to handle all cases,
ahe 2012/08/15 10:00:19 Please don't use the cast operator.
Lasse Reichstein Nielsen 2012/08/15 11:17:06 Done.
202 }
203 element = element.enclosingElement;
204 }
205 return element;
209 } 206 }
210 207
211 LibraryElement getLibrary() { 208 LibraryElement getLibrary() {
212 Element element = this; 209 Element element = this;
213 while (element.kind !== ElementKind.LIBRARY) { 210 while (element.kind !== ElementKind.LIBRARY) {
214 element = element.enclosingElement; 211 element = element.enclosingElement;
215 } 212 }
216 return element; 213 return element;
217 } 214 }
218 215
219 ClassElement getEnclosingClass() { 216 ClassElement getEnclosingClass() {
220 for (Element e = this; e !== null; e = e.enclosingElement) { 217 for (Element e = this; e !== null; e = e.enclosingElement) {
221 if (e.isClass()) return e; 218 if (e.isClass()) return e;
222 } 219 }
223 return null; 220 return null;
224 } 221 }
225 222
223 Element getEnclosingClassOrCompilationUnit() {
224 for (Element e = this; e !== null; e = e.enclosingElement) {
225 if (e.isClass() || e.isCompilationUnit()) return e;
226 }
227 return null;
228 }
229
226 Element getEnclosingMember() { 230 Element getEnclosingMember() {
227 for (Element e = this; e !== null; e = e.enclosingElement) { 231 for (Element e = this; e !== null; e = e.enclosingElement) {
228 if (e.isMember()) return e; 232 if (e.isMember()) return e;
229 } 233 }
230 return null; 234 return null;
231 } 235 }
232 236
233 Element getOutermostEnclosingMemberOrTopLevel() { 237 Element getOutermostEnclosingMemberOrTopLevel() {
234 // TODO(lrn): Why is this called "Outermost"? 238 // TODO(lrn): Why is this called "Outermost"?
235 for (Element e = this; e !== null; e = e.enclosingElement) { 239 for (Element e = this; e !== null; e = e.enclosingElement) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 listener.cancel('duplicate definition', token: element.position()); 317 listener.cancel('duplicate definition', token: element.position());
314 listener.cancel('existing definition', token: existing.position()); 318 listener.cancel('existing definition', token: existing.position());
315 } 319 }
316 } 320 }
317 } 321 }
318 322
319 Element localLookup(SourceString elementName) { 323 Element localLookup(SourceString elementName) {
320 return localScope[elementName]; 324 return localScope[elementName];
321 } 325 }
322 326
323 void addGetterOrSetter(Element element, 327 void addGetterOrSetter(FunctionElement element,
324 Element existing, 328 Element existing,
325 DiagnosticListener listener) { 329 DiagnosticListener listener) {
326 void reportError(Element other) { 330 void reportError(Element other) {
327 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. 331 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext.
328 listener.cancel('duplicate definition of ${element.name.slowToString()}', 332 listener.cancel('duplicate definition of ${element.name.slowToString()}',
329 element: element); 333 element: element);
330 listener.cancel('existing definition', element: other); 334 listener.cancel('existing definition', element: other);
331 } 335 }
332 336
333 if (existing != null) { 337 if (existing != null) {
334 if (existing.kind !== ElementKind.ABSTRACT_FIELD) { 338 if (existing.kind !== ElementKind.ABSTRACT_FIELD) {
335 reportError(existing); 339 reportError(existing);
336 } else { 340 } else {
337 AbstractFieldElement field = existing; 341 AbstractFieldElement field = existing;
338 if (element.kind == ElementKind.GETTER) { 342 if (element.kind == ElementKind.GETTER) {
339 if (field.getter != null && field.getter != element) { 343 if (field.getter != null && field.getter != element) {
340 reportError(field.getter); 344 reportError(field.getter);
341 } 345 }
342 field.getter = element; 346 field.getter = element;
343 } else { 347 } else {
344 if (field.setter != null && field.setter != element) { 348 if (field.setter != null && field.setter != element) {
345 reportError(field.setter); 349 reportError(field.setter);
346 } 350 }
347 field.setter = element; 351 field.setter = element;
348 } 352 }
349 } 353 }
350 } else { 354 } else {
351 AbstractFieldElement field = new AbstractFieldElement(element.name, this); 355 Element container = element.getEnclosingClassOrCompilationUnit();
356 AbstractFieldElement field =
357 new AbstractFieldElement(element.name, container);
352 if (element.kind == ElementKind.GETTER) { 358 if (element.kind == ElementKind.GETTER) {
353 field.getter = element; 359 field.getter = element;
354 } else { 360 } else {
355 field.setter = element; 361 field.setter = element;
356 } 362 }
357 addMember(field, listener); 363 addMember(field, listener);
358 } 364 }
359 } 365 }
360 } 366 }
361 367
(...skipping 16 matching lines...) Expand all
378 384
379 class CompilationUnitOverrideElement extends Element { 385 class CompilationUnitOverrideElement extends Element {
380 final CompilationUnitElement compilationUnit; 386 final CompilationUnitElement compilationUnit;
381 387
382 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, 388 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit,
383 Element enclosing) 389 Element enclosing)
384 : this.compilationUnit = compilationUnit, 390 : this.compilationUnit = compilationUnit,
385 super(compilationUnit.name, 391 super(compilationUnit.name,
386 ElementKind.COMPILATION_UNIT_OVERRIDE, 392 ElementKind.COMPILATION_UNIT_OVERRIDE,
387 enclosing); 393 enclosing);
388
389 CompilationUnitElement asCompilationUnit() => compilationUnit;
390
391 CompilationUnitElement getCompilationUnit() => compilationUnit;
392 } 394 }
393 395
394 class LibraryElement extends ScopeContainerElement { 396 class LibraryElement extends ScopeContainerElement {
395 CompilationUnitElement entryCompilationUnit; 397 CompilationUnitElement entryCompilationUnit;
396 Link<CompilationUnitElement> compilationUnits = 398 Link<CompilationUnitElement> compilationUnits =
397 const EmptyLink<CompilationUnitElement>(); 399 const EmptyLink<CompilationUnitElement>();
398 400
399 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); 401 Link<ScriptTag> tags = const EmptyLink<ScriptTag>();
400 ScriptTag libraryTag; 402 ScriptTag libraryTag;
401 bool canUseNative = false; 403 bool canUseNative = false;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 String getLibraryOrScriptName() { 456 String getLibraryOrScriptName() {
455 if (libraryTag !== null) { 457 if (libraryTag !== null) {
456 return libraryTag.argument.dartString.slowToString(); 458 return libraryTag.argument.dartString.slowToString();
457 } else { 459 } else {
458 // Use the file name as script name. 460 // Use the file name as script name.
459 String path = uri.path; 461 String path = uri.path;
460 return path.substring(path.lastIndexOf('/') + 1); 462 return path.substring(path.lastIndexOf('/') + 1);
461 } 463 }
462 } 464 }
463 465
464 CompilationUnitElement getCompilationUnit() => entryCompilationUnit;
465
466 Scope buildEnclosingScope() => new TopScope(this); 466 Scope buildEnclosingScope() => new TopScope(this);
467 } 467 }
468 468
469 class PrefixElement extends Element { 469 class PrefixElement extends Element {
470 Map<SourceString, Element> imported; 470 Map<SourceString, Element> imported;
471 Token firstPosition; 471 Token firstPosition;
472 472
473 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) 473 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition)
474 : imported = new Map<SourceString, Element>(), 474 : imported = new Map<SourceString, Element>(),
475 super(prefix, ElementKind.PREFIX, enclosing); 475 super(prefix, ElementKind.PREFIX, enclosing);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 692
693 Node parseNode(DiagnosticListener listener) { 693 Node parseNode(DiagnosticListener listener) {
694 throw "internal error: AbstractFieldElement has no node"; 694 throw "internal error: AbstractFieldElement has no node";
695 } 695 }
696 696
697 position() { 697 position() {
698 // The getter and setter may be defined in two different 698 // The getter and setter may be defined in two different
699 // compilation units. However, we know that one of them is 699 // compilation units. However, we know that one of them is
700 // non-null and defined in the same compilation unit as the 700 // non-null and defined in the same compilation unit as the
701 // abstract element. 701 // abstract element.
702 // TODO(lrn): No we don't know that if the element from the same
703 // compilation unit is patched.
Lasse Reichstein Nielsen 2012/08/15 09:09:12 The current way to handle patched functions will c
ahe 2012/08/15 10:00:19 Is that coming?
Lasse Reichstein Nielsen 2012/08/15 11:17:06 It's being worked on as a separate change.
702 // 704 //
703 // We need to make sure that the position returned is relative to 705 // We need to make sure that the position returned is relative to
704 // the compilation unit of the abstract element. 706 // the compilation unit of the abstract element.
705 if (getter !== null 707 if (getter !== null
706 && getter.getCompilationUnit() === getCompilationUnit()) { 708 && getter.getCompilationUnit() === getCompilationUnit()) {
707 return getter.position(); 709 return getter.position();
708 } else { 710 } else {
709 return setter.position(); 711 return setter.position();
710 } 712 }
711 } 713 }
712 714
713 Modifiers get modifiers() { 715 Modifiers get modifiers() {
714 // The resolver ensures that the flags match (ignoring abstract). 716 // The resolver ensures that the flags match (ignoring abstract).
715 if (getter !== null) { 717 if (getter !== null) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 FunctionElement.tooMuchOverloading(SourceString name, 806 FunctionElement.tooMuchOverloading(SourceString name,
805 FunctionExpression this.cachedNode, 807 FunctionExpression this.cachedNode,
806 ElementKind kind, 808 ElementKind kind,
807 Modifiers this.modifiers, 809 Modifiers this.modifiers,
808 Element enclosing, 810 Element enclosing,
809 FunctionSignature this.functionSignature) 811 FunctionSignature this.functionSignature)
810 : super(name, kind, enclosing) { 812 : super(name, kind, enclosing) {
811 defaultImplementation = this; 813 defaultImplementation = this;
812 } 814 }
813 815
814 Script getScript() {
815 if (patch !== null) return patch.getScript();
816 return super.getScript();
817 }
818
819 bool get isPatched() => patch !== null; 816 bool get isPatched() => patch !== null;
820 817
821 /** 818 /**
822 * Applies a patch function to this function. The patch function's body 819 * Applies a patch function to this function. The patch function's body
823 * is used as replacement when parsing this function's body. 820 * is used as replacement when parsing this function's body.
824 * This method must not be called after the function has been parsed, 821 * This method must not be called after the function has been parsed,
825 * and it must be called at most once. 822 * and it must be called at most once.
826 */ 823 */
827 void setPatch(FunctionElement patchElement) { 824 void setPatch(FunctionElement patchElement) {
828 // Sanity checks. The caller must check these things before calling. 825 // Sanity checks. The caller must check these things before calling.
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 Node parseNode(compiler) => cachedNode; 1446 Node parseNode(compiler) => cachedNode;
1450 1447
1451 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; 1448 String toString() => "${enclosingElement.toString()}.${name.slowToString()}";
1452 1449
1453 TypeVariableElement cloneTo(Element enclosing, DiagnosticListener listener) { 1450 TypeVariableElement cloneTo(Element enclosing, DiagnosticListener listener) {
1454 TypeVariableElement result = 1451 TypeVariableElement result =
1455 new TypeVariableElement(name, enclosing, node, type, bound); 1452 new TypeVariableElement(name, enclosing, node, type, bound);
1456 return result; 1453 return result;
1457 } 1454 }
1458 } 1455 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/typechecker.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698