Chromium Code Reviews| 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('elements'); | 5 #library('elements'); |
| 6 | 6 |
| 7 #import('../tree/tree.dart'); | 7 #import('../tree/tree.dart'); |
| 8 #import('../scanner/scannerlib.dart'); | 8 #import('../scanner/scannerlib.dart'); |
| 9 #import('../leg.dart'); // TODO(karlklose): we only need type. | 9 #import('../leg.dart'); // TODO(karlklose): we only need type. |
| 10 #import('../util/util.dart'); | 10 #import('../util/util.dart'); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 toString() => id; | 85 toString() => id; |
| 86 } | 86 } |
| 87 | 87 |
| 88 class Element implements Hashable { | 88 class Element implements Hashable { |
| 89 final SourceString name; | 89 final SourceString name; |
| 90 final ElementKind kind; | 90 final ElementKind kind; |
| 91 final Element enclosingElement; | 91 final Element enclosingElement; |
| 92 Modifiers get modifiers() => null; | 92 Modifiers get modifiers() => null; |
| 93 | 93 |
| 94 Node parseNode(DiagnosticListener listener) { | 94 Node parseNode(DiagnosticListener listener) { |
| 95 listener.cancel("Internal Error: Element.parseNode"); | 95 listener.cancel("Internal Error: $this.parseNode", token: position()); |
| 96 } | 96 } |
| 97 | 97 |
| 98 Type computeType(Compiler compiler) { | 98 Type computeType(Compiler compiler) { |
| 99 compiler.internalError("Element.computeType."); | 99 compiler.internalError("$this.computeType.", token: position()); |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool isFunction() => kind === ElementKind.FUNCTION; | 102 bool isFunction() => kind === ElementKind.FUNCTION; |
| 103 bool isMember() => | 103 bool isMember() => |
| 104 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS; | 104 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS; |
| 105 bool isInstanceMember() => false; | 105 bool isInstanceMember() => false; |
| 106 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); | 106 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); |
| 107 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; | 107 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; |
| 108 bool isCompilationUnit() { | 108 bool isCompilationUnit() { |
| 109 return kind === ElementKind.COMPILATION_UNIT || | 109 return kind === ElementKind.COMPILATION_UNIT || |
| 110 kind === ElementKind.LIBRARY; | 110 kind === ElementKind.LIBRARY; |
| 111 } | 111 } |
| 112 bool isClass() => kind === ElementKind.CLASS; | 112 bool isClass() => kind === ElementKind.CLASS; |
| 113 bool isVariable() => kind === ElementKind.VARIABLE; | 113 bool isVariable() => kind === ElementKind.VARIABLE; |
| 114 bool isParameter() => kind === ElementKind.PARAMETER; | 114 bool isParameter() => kind === ElementKind.PARAMETER; |
| 115 bool isStatement() => kind === ElementKind.STATEMENT; | 115 bool isStatement() => kind === ElementKind.STATEMENT; |
| 116 bool isTypedef() => kind === ElementKind.TYPEDEF; | 116 bool isTypedef() => kind === ElementKind.TYPEDEF; |
| 117 bool isGetter() => kind === ElementKind.GETTER; | 117 bool isGetter() => kind === ElementKind.GETTER; |
| 118 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; | 118 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; |
| 119 | 119 |
| 120 bool isAssignable() { | 120 bool isAssignable() { |
| 121 if (modifiers != null && modifiers.isFinal()) return false; | 121 if (modifiers != null && modifiers.isFinal()) return false; |
| 122 if (isFunction() || isGenerativeConstructor()) return false; | 122 if (isFunction() || isGenerativeConstructor()) return false; |
| 123 return true; | 123 return true; |
| 124 } | 124 } |
| 125 | 125 |
| 126 Token position() => null; | 126 Token position() => null; |
| 127 | 127 |
| 128 Token findMyName(Token token) { | |
| 129 for (Token t = token; t !== EOF_TOKEN; t = t.next) { | |
| 130 if (t.value == name) return t; | |
| 131 } | |
| 132 return token; | |
| 133 } | |
| 134 | |
| 128 const Element(this.name, this.kind, this.enclosingElement); | 135 const Element(this.name, this.kind, this.enclosingElement); |
| 129 | 136 |
| 130 // TODO(kasperl): This is a very bad hash code for the element and | 137 // TODO(kasperl): This is a very bad hash code for the element and |
| 131 // there's no reason why two elements with the same name should have | 138 // there's no reason why two elements with the same name should have |
| 132 // the same hash code. Replace this with a simple id in the element? | 139 // the same hash code. Replace this with a simple id in the element? |
| 133 int hashCode() => name.hashCode(); | 140 int hashCode() => name.hashCode(); |
| 134 | 141 |
| 135 CompilationUnitElement getCompilationUnit() { | 142 CompilationUnitElement getCompilationUnit() { |
| 136 Element element = this; | 143 Element element = this; |
| 137 while (element !== null && !element.isCompilationUnit()) { | 144 while (element !== null && !element.isCompilationUnit()) { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 define(element, listener); | 260 define(element, listener); |
| 254 } | 261 } |
| 255 | 262 |
| 256 void define(Element element, DiagnosticListener listener) { | 263 void define(Element element, DiagnosticListener listener) { |
| 257 if (element.kind == ElementKind.GETTER | 264 if (element.kind == ElementKind.GETTER |
| 258 || element.kind == ElementKind.SETTER) { | 265 || element.kind == ElementKind.SETTER) { |
| 259 addGetterOrSetter(element, elements[element.name], listener); | 266 addGetterOrSetter(element, elements[element.name], listener); |
| 260 } else { | 267 } else { |
| 261 Element existing = elements.putIfAbsent(element.name, () => element); | 268 Element existing = elements.putIfAbsent(element.name, () => element); |
| 262 if (existing !== element) { | 269 if (existing !== element) { |
| 263 listener.cancel('duplicate definition', token: element.position()); | 270 listener.cancel('duplicate definition $element', token: element.position ()); |
|
ngeoffray
2012/03/10 22:36:51
line too long
ngeoffray
2012/03/10 22:36:51
definition 'of' ?
ahe
2012/03/11 13:01:50
Done.
ahe
2012/03/11 13:01:50
Debug code.
| |
| 264 listener.cancel('existing definition', token: existing.position()); | 271 listener.cancel('existing definition', token: existing.position()); |
| 265 } | 272 } |
| 266 } | 273 } |
| 267 } | 274 } |
| 268 | 275 |
| 269 Element find(SourceString name) { | 276 Element find(SourceString name) { |
| 270 return elements[name]; | 277 return elements[name]; |
| 271 } | 278 } |
| 272 | 279 |
| 273 Element lookupLocalMember(SourceString name) { | |
| 274 Element element = find(name); | |
| 275 if (element === null) return null; | |
| 276 return (this === element.getLibrary()) ? element : null; | |
| 277 } | |
| 278 | |
| 279 void forEachExport(f(Element element)) { | 280 void forEachExport(f(Element element)) { |
| 280 elements.forEach((SourceString _, Element e) { | 281 elements.forEach((SourceString _, Element e) { |
| 281 if (this === e.getLibrary() | 282 if (this === e.getLibrary() |
| 282 && e.kind !== ElementKind.PREFIX | 283 && e.kind !== ElementKind.PREFIX |
| 283 && e.kind !== ElementKind.FOREIGN) { | 284 && e.kind !== ElementKind.FOREIGN) { |
| 284 f(e); | 285 f(e); |
| 285 } | 286 } |
| 286 }); | 287 }); |
| 287 } | 288 } |
| 288 } | 289 } |
| 289 | 290 |
| 290 class PrefixElement extends Element { | 291 class PrefixElement extends Element { |
| 291 final LiteralString prefix; | 292 Map<SourceString, Element> imported; |
| 292 final LibraryElement library; | |
| 293 | 293 |
| 294 PrefixElement(LiteralString prefix, | 294 PrefixElement(SourceString prefix, Element enclosing) |
| 295 LibraryElement this.library, | 295 : imported = new Map<SourceString, Element>(), |
| 296 Element enclosing) | 296 super(prefix, ElementKind.PREFIX, enclosing); |
| 297 : this.prefix = prefix, | |
| 298 super(prefix.dartString.source, ElementKind.PREFIX, enclosing); | |
| 299 | 297 |
| 300 lookupLocalMember(SourceString name) => library.lookupLocalMember(name); | 298 lookupLocalMember(SourceString name) => imported[name]; |
| 299 | |
| 300 Type computeType(Compiler compiler) => compiler.types.dynamicType; | |
| 301 } | 301 } |
| 302 | 302 |
| 303 class TypedefElement extends Element { | 303 class TypedefElement extends Element { |
| 304 TypedefElement(SourceString name, Element enclosing) | 304 TypedefElement(SourceString name, Element enclosing) |
| 305 : super(name, ElementKind.TYPEDEF, enclosing); | 305 : super(name, ElementKind.TYPEDEF, enclosing); |
| 306 } | 306 } |
| 307 | 307 |
| 308 class VariableElement extends Element { | 308 class VariableElement extends Element { |
| 309 final VariableListElement variables; | 309 final VariableListElement variables; |
| 310 Expression cachedNode; // The send or the identifier in the variables list. | 310 Expression cachedNode; // The send or the identifier in the variables list. |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 339 Type computeType(Compiler compiler) { | 339 Type computeType(Compiler compiler) { |
| 340 return variables.computeType(compiler); | 340 return variables.computeType(compiler); |
| 341 } | 341 } |
| 342 | 342 |
| 343 Type get type() => variables.type; | 343 Type get type() => variables.type; |
| 344 | 344 |
| 345 bool isInstanceMember() { | 345 bool isInstanceMember() { |
| 346 return isMember() && !modifiers.isStatic(); | 346 return isMember() && !modifiers.isStatic(); |
| 347 } | 347 } |
| 348 | 348 |
| 349 Token position() { | 349 Token position() => findMyName(variables.position()); |
|
ngeoffray
2012/03/10 22:36:51
Why don't you check cachedNode first before going
ahe
2012/03/10 23:07:18
Wouldn't be correct for function typed parameters.
ngeoffray
2012/03/10 23:11:27
Could you please add that as a comment?
ahe
2012/03/11 13:01:50
Done.
| |
| 350 // TODO(ahe): Record the token corresponding to name instead of | |
| 351 // returning different values at different points in time. | |
| 352 return (cachedNode !== null) | |
| 353 ? cachedNode.getBeginToken() : variables.position(); | |
| 354 } | |
| 355 } | 350 } |
| 356 | 351 |
| 357 // This element represents a list of variable or field declaration. | 352 // This element represents a list of variable or field declaration. |
| 358 // It contains the node, and the type. A [VariableElement] always | 353 // It contains the node, and the type. A [VariableElement] always |
| 359 // references its [VariableListElement]. It forwards its | 354 // references its [VariableListElement]. It forwards its |
| 360 // [computeType] and [parseNode] methods to this element. | 355 // [computeType] and [parseNode] methods to this element. |
| 361 class VariableListElement extends Element { | 356 class VariableListElement extends Element { |
| 362 VariableDefinitions cachedNode; | 357 VariableDefinitions cachedNode; |
| 363 Type type; | 358 Type type; |
| 364 final Modifiers modifiers; | 359 final Modifiers modifiers; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 : super(name, ElementKind.ABSTRACT_FIELD, enclosing), | 405 : super(name, ElementKind.ABSTRACT_FIELD, enclosing), |
| 411 modifiers = new Modifiers.empty(); | 406 modifiers = new Modifiers.empty(); |
| 412 | 407 |
| 413 Type computeType(Compiler compiler) { | 408 Type computeType(Compiler compiler) { |
| 414 throw "internal error: AbstractFieldElement has no type"; | 409 throw "internal error: AbstractFieldElement has no type"; |
| 415 } | 410 } |
| 416 | 411 |
| 417 Node parseNode(DiagnosticListener listener) { | 412 Node parseNode(DiagnosticListener listener) { |
| 418 throw "internal error: AbstractFieldElement has no node"; | 413 throw "internal error: AbstractFieldElement has no node"; |
| 419 } | 414 } |
| 415 | |
| 416 position() { | |
| 417 if (getter !== null && getter.enclosingElement === enclosingElement) { | |
|
ngeoffray
2012/03/10 22:36:51
I don't understand the second check.
ahe
2012/03/10 23:07:18
I'll add a comment explaining this.
The getter an
ngeoffray
2012/03/10 23:11:27
I see, thanks for the comment!
| |
| 418 return getter.position(); | |
| 419 } else { | |
| 420 return setter.position(); | |
|
ngeoffray
2012/03/10 22:36:51
setter could be null
ahe
2012/03/10 23:07:18
No. See my comment above.
| |
| 421 } | |
| 422 } | |
| 420 } | 423 } |
| 421 | 424 |
| 422 /** DEPRECATED. */ | 425 /** DEPRECATED. */ |
| 423 Type getType(TypeAnnotation typeAnnotation, | 426 Type getType(TypeAnnotation typeAnnotation, |
| 424 Compiler compiler, | 427 Compiler compiler, |
| 425 LibraryElement library) { | 428 LibraryElement library) { |
| 426 // TODO(karlklose,ngeoffray): This method should be removed and the | 429 // TODO(karlklose,ngeoffray): This method should be removed and the |
| 427 // information should be computed by the resolver. | 430 // information should be computed by the resolver. |
| 428 | 431 |
| 429 if (typeAnnotation == null || typeAnnotation.typeName == null) { | 432 if (typeAnnotation == null || typeAnnotation.typeName == null) { |
| 430 return compiler.types.dynamicType; | 433 return compiler.types.dynamicType; |
| 431 } | 434 } |
| 432 Identifier identifier = typeAnnotation.typeName.asIdentifier(); | 435 Identifier identifier = typeAnnotation.typeName.asIdentifier(); |
| 433 if (identifier === null) { | 436 if (identifier === null) { |
| 434 compiler.cancel('library prefixes not handled', | 437 compiler.reportWarning(typeAnnotation.typeName, |
| 435 node: typeAnnotation.typeName); | 438 'library prefixes not handled'); |
| 439 return compiler.types.dynamicType; | |
| 436 } | 440 } |
| 437 SourceString name = identifier.source; | 441 SourceString name = identifier.source; |
| 438 Element element = library.find(name); | 442 Element element = library.find(name); |
| 439 if (element !== null) { | 443 if (element !== null) { |
| 440 if (element.isTypedef()) { | 444 if (element.isTypedef()) { |
| 441 // TODO(ngeoffray): This is a hack to help us get support for the | 445 // TODO(ngeoffray): This is a hack to help us get support for the |
| 442 // DOM library. | 446 // DOM library. |
| 443 // TODO(ngeoffray): The list of types for the argument is wrong. | 447 // TODO(ngeoffray): The list of types for the argument is wrong. |
| 444 return new FunctionType(compiler.types.dynamicType, | 448 return new FunctionType(compiler.types.dynamicType, |
| 445 const EmptyLink<Type>(), | 449 const EmptyLink<Type>(), |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 | 854 |
| 851 LabelElement addLabel(Identifier label, String labelName) { | 855 LabelElement addLabel(Identifier label, String labelName) { |
| 852 LabelElement result = new LabelElement(label, labelName, this, | 856 LabelElement result = new LabelElement(label, labelName, this, |
| 853 enclosingElement); | 857 enclosingElement); |
| 854 labels = labels.prepend(result); | 858 labels = labels.prepend(result); |
| 855 return result; | 859 return result; |
| 856 } | 860 } |
| 857 | 861 |
| 858 Node parseNode(DiagnosticListener l) => statement; | 862 Node parseNode(DiagnosticListener l) => statement; |
| 859 } | 863 } |
| OLD | NEW |