| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 static final ElementKind GETTER = | 76 static final ElementKind GETTER = |
| 77 const ElementKind('getter', ElementCategory.NONE); | 77 const ElementKind('getter', ElementCategory.NONE); |
| 78 static final ElementKind SETTER = | 78 static final ElementKind SETTER = |
| 79 const ElementKind('setter', ElementCategory.NONE); | 79 const ElementKind('setter', ElementCategory.NONE); |
| 80 static final ElementKind TYPE_VARIABLE = | 80 static final ElementKind TYPE_VARIABLE = |
| 81 const ElementKind('type_variable', ElementCategory.TYPE_VARIABLE); | 81 const ElementKind('type_variable', ElementCategory.TYPE_VARIABLE); |
| 82 static final ElementKind ABSTRACT_FIELD = | 82 static final ElementKind ABSTRACT_FIELD = |
| 83 const ElementKind('abstract_field', ElementCategory.VARIABLE); | 83 const ElementKind('abstract_field', ElementCategory.VARIABLE); |
| 84 static final ElementKind LIBRARY = | 84 static final ElementKind LIBRARY = |
| 85 const ElementKind('library', ElementCategory.NONE); | 85 const ElementKind('library', ElementCategory.NONE); |
| 86 static final ElementKind COMPILATION_UNIT_OVERRIDE = |
| 87 const ElementKind('compilation_unit_override', ElementCategory.NONE); |
| 86 static final ElementKind PREFIX = | 88 static final ElementKind PREFIX = |
| 87 const ElementKind('prefix', ElementCategory.PREFIX); | 89 const ElementKind('prefix', ElementCategory.PREFIX); |
| 88 static final ElementKind TYPEDEF = | 90 static final ElementKind TYPEDEF = |
| 89 const ElementKind('typedef', ElementCategory.ALIAS); | 91 const ElementKind('typedef', ElementCategory.ALIAS); |
| 90 | 92 |
| 91 static final ElementKind STATEMENT = | 93 static final ElementKind STATEMENT = |
| 92 const ElementKind('statement', ElementCategory.NONE); | 94 const ElementKind('statement', ElementCategory.NONE); |
| 93 static final ElementKind LABEL = | 95 static final ElementKind LABEL = |
| 94 const ElementKind('label', ElementCategory.NONE); | 96 const ElementKind('label', ElementCategory.NONE); |
| 95 static final ElementKind VOID = | 97 static final ElementKind VOID = |
| 96 const ElementKind('void', ElementCategory.NONE); | 98 const ElementKind('void', ElementCategory.NONE); |
| 97 | 99 |
| 98 toString() => id; | 100 toString() => id; |
| 99 } | 101 } |
| 100 | 102 |
| 101 class Element implements Hashable { | 103 class Element implements Hashable { |
| 102 final SourceString name; | 104 final SourceString name; |
| 103 final ElementKind kind; | 105 final ElementKind kind; |
| 104 final Element enclosingElement; | 106 final Element enclosingElement; |
| 105 Link<Node> metadata = const EmptyLink<Node>(); | 107 Link<Node> metadata = const EmptyLink<Node>(); |
| 108 |
| 109 |
| 110 Element(this.name, this.kind, this.enclosingElement) { |
| 111 assert(getLibrary() !== null); |
| 112 } |
| 113 |
| 106 Modifiers get modifiers() => null; | 114 Modifiers get modifiers() => null; |
| 107 | 115 |
| 108 Node parseNode(DiagnosticListener listener) { | 116 Node parseNode(DiagnosticListener listener) { |
| 109 listener.cancel("Internal Error: $this.parseNode", token: position()); | 117 listener.cancel("Internal Error: $this.parseNode", token: position()); |
| 110 } | 118 } |
| 111 | 119 |
| 112 Type computeType(Compiler compiler) { | 120 Type computeType(Compiler compiler) { |
| 113 compiler.internalError("$this.computeType.", token: position()); | 121 compiler.internalError("$this.computeType.", token: position()); |
| 114 } | 122 } |
| 115 | 123 |
| 116 void addMetadata(Node node) { | 124 void addMetadata(Node node) { |
| 117 metadata = metadata.prepend(node); | 125 metadata = metadata.prepend(node); |
| 118 } | 126 } |
| 119 | 127 |
| 120 bool isFunction() => kind === ElementKind.FUNCTION; | 128 bool isFunction() => kind === ElementKind.FUNCTION; |
| 121 bool isConstructor() => isFactoryConstructor() || isGenerativeConstructor(); | 129 bool isConstructor() => isFactoryConstructor() || isGenerativeConstructor(); |
| 122 bool isClosure() => false; | 130 bool isClosure() => false; |
| 123 bool isMember() { | 131 bool isMember() { |
| 124 // Check that this element is defined in the scope of a Class. | 132 // Check that this element is defined in the scope of a Class. |
| 125 Element enclosing = enclosingElement; | 133 Element enclosing = enclosingElement; |
| 134 if (enclosing !== null && |
| 135 enclosing.kind === ElementKind.COMPILATION_UNIT_OVERRIDE) { |
| 136 enclosing = enclosing.enclosingElement; |
| 137 } |
| 126 // TODO(lrn): Skip any synthetic elements inserted, e.g., | 138 // TODO(lrn): Skip any synthetic elements inserted, e.g., |
| 127 // a compilation unit override. | 139 // a compilation unit override. |
| 128 return enclosing !== null && enclosing.isClass(); | 140 return enclosing !== null && enclosing.isClass(); |
| 129 } | 141 } |
| 130 bool isInstanceMember() => false; | 142 bool isInstanceMember() => false; |
| 131 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); | 143 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); |
| 132 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; | 144 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; |
| 133 bool isGenerativeConstructorBody() => | 145 bool isGenerativeConstructorBody() => |
| 134 kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY; | 146 kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY; |
| 135 bool isCompilationUnit() { | 147 bool isCompilationUnit() { |
| 136 return kind === ElementKind.COMPILATION_UNIT || | 148 return kind === ElementKind.COMPILATION_UNIT || |
| 137 kind === ElementKind.LIBRARY; | 149 kind === ElementKind.LIBRARY || |
| 150 kind === ElementKind.COMPILATION_UNIT_OVERRIDE; |
| 138 } | 151 } |
| 152 /** |
| 153 * Provides the compilation unit corresponding to this element. |
| 154 * Returns non-null for elements where [isCompilationUnit] returns true, |
| 155 * but may not return the current [Element]. |
| 156 */ |
| 157 CompilationUnitElement asCompilationUnit() => null; |
| 139 bool isClass() => kind === ElementKind.CLASS; | 158 bool isClass() => kind === ElementKind.CLASS; |
| 140 bool isPrefix() => kind === ElementKind.PREFIX; | 159 bool isPrefix() => kind === ElementKind.PREFIX; |
| 141 bool isVariable() => kind === ElementKind.VARIABLE; | 160 bool isVariable() => kind === ElementKind.VARIABLE; |
| 142 bool isParameter() => kind === ElementKind.PARAMETER; | 161 bool isParameter() => kind === ElementKind.PARAMETER; |
| 143 bool isStatement() => kind === ElementKind.STATEMENT; | 162 bool isStatement() => kind === ElementKind.STATEMENT; |
| 144 bool isTypedef() => kind === ElementKind.TYPEDEF; | 163 bool isTypedef() => kind === ElementKind.TYPEDEF; |
| 145 bool isTypeVariable() => kind === ElementKind.TYPE_VARIABLE; | 164 bool isTypeVariable() => kind === ElementKind.TYPE_VARIABLE; |
| 146 bool isField() => kind === ElementKind.FIELD; | 165 bool isField() => kind === ElementKind.FIELD; |
| 147 bool isGetter() => kind === ElementKind.GETTER; | 166 bool isGetter() => kind === ElementKind.GETTER; |
| 148 bool isSetter() => kind === ElementKind.SETTER; | 167 bool isSetter() => kind === ElementKind.SETTER; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 166 | 185 |
| 167 Token position() => null; | 186 Token position() => null; |
| 168 | 187 |
| 169 Token findMyName(Token token) { | 188 Token findMyName(Token token) { |
| 170 for (Token t = token; t.kind !== EOF_TOKEN; t = t.next) { | 189 for (Token t = token; t.kind !== EOF_TOKEN; t = t.next) { |
| 171 if (t.value == name) return t; | 190 if (t.value == name) return t; |
| 172 } | 191 } |
| 173 return token; | 192 return token; |
| 174 } | 193 } |
| 175 | 194 |
| 176 Element(this.name, this.kind, this.enclosingElement) { | |
| 177 assert(getLibrary() !== null); | |
| 178 } | |
| 179 | |
| 180 // TODO(kasperl): This is a very bad hash code for the element and | 195 // TODO(kasperl): This is a very bad hash code for the element and |
| 181 // there's no reason why two elements with the same name should have | 196 // there's no reason why two elements with the same name should have |
| 182 // the same hash code. Replace this with a simple id in the element? | 197 // the same hash code. Replace this with a simple id in the element? |
| 183 int hashCode() => name === null ? 0 : name.hashCode(); | 198 int hashCode() => name === null ? 0 : name.hashCode(); |
| 184 | 199 |
| 200 Script getScript() { |
| 201 return getCompilationUnit().script; |
| 202 } |
| 203 |
| 185 CompilationUnitElement getCompilationUnit() { | 204 CompilationUnitElement getCompilationUnit() { |
| 186 Element element = this; | 205 Element element = this; |
| 187 while (element !== null && !element.isCompilationUnit()) { | 206 while (element !== null && !element.isCompilationUnit()) { |
| 188 element = element.enclosingElement; | 207 element = element.enclosingElement; |
| 189 } | 208 } |
| 190 return element; | 209 return element.asCompilationUnit(); |
| 191 } | 210 } |
| 192 | 211 |
| 193 LibraryElement getLibrary() { | 212 LibraryElement getLibrary() { |
| 194 Element element = this; | 213 Element element = this; |
| 195 while (element.kind !== ElementKind.LIBRARY) { | 214 while (element.kind !== ElementKind.LIBRARY) { |
| 196 element = element.enclosingElement; | 215 element = element.enclosingElement; |
| 197 } | 216 } |
| 198 return element; | 217 return element; |
| 199 } | 218 } |
| 200 | 219 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 } else { | 264 } else { |
| 246 return '$kind(${nameText})'; | 265 return '$kind(${nameText})'; |
| 247 } | 266 } |
| 248 } | 267 } |
| 249 | 268 |
| 250 bool _isNative = false; | 269 bool _isNative = false; |
| 251 void setNative() { _isNative = true; } | 270 void setNative() { _isNative = true; } |
| 252 bool isNative() => _isNative; | 271 bool isNative() => _isNative; |
| 253 | 272 |
| 254 FunctionElement asFunctionElement() => null; | 273 FunctionElement asFunctionElement() => null; |
| 274 |
| 275 Element cloneTo(Element enclosing, DiagnosticListener listener) { |
| 276 listener.cancel("Unimplemented cloneTo", element: this); |
| 277 } |
| 255 } | 278 } |
| 256 | 279 |
| 257 class ContainerElement extends Element { | 280 class ContainerElement extends Element { |
| 258 ContainerElement(name, kind, enclosingElement) : | 281 ContainerElement(name, kind, enclosingElement) : |
| 259 super(name, kind, enclosingElement); | 282 super(name, kind, enclosingElement); |
| 260 | 283 |
| 261 abstract void addMember(Element element, DiagnosticListener listener); | 284 abstract void addMember(Element element, DiagnosticListener listener); |
| 262 | 285 |
| 263 void addGetterOrSetter(Element element, | 286 void addGetterOrSetter(Element element, |
| 264 Element existing, | 287 Element existing, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 CompilationUnitElement(Script script, Element enclosing) | 328 CompilationUnitElement(Script script, Element enclosing) |
| 306 : this.script = script, | 329 : this.script = script, |
| 307 super(new SourceString(script.name), | 330 super(new SourceString(script.name), |
| 308 ElementKind.COMPILATION_UNIT, | 331 ElementKind.COMPILATION_UNIT, |
| 309 enclosing); | 332 enclosing); |
| 310 | 333 |
| 311 CompilationUnitElement.library(Script script) | 334 CompilationUnitElement.library(Script script) |
| 312 : this.script = script, | 335 : this.script = script, |
| 313 super(new SourceString(script.name), ElementKind.LIBRARY, null); | 336 super(new SourceString(script.name), ElementKind.LIBRARY, null); |
| 314 | 337 |
| 338 CompilationUnitElement asCompilationUnit() => this; |
| 339 |
| 315 void addMember(Element element, DiagnosticListener listener) { | 340 void addMember(Element element, DiagnosticListener listener) { |
| 316 LibraryElement library = enclosingElement; | 341 LibraryElement library = enclosingElement; |
| 317 library.addMember(element, listener); | 342 library.addMember(element, listener); |
| 318 topLevelElements = topLevelElements.prepend(element); | 343 topLevelElements = topLevelElements.prepend(element); |
| 319 } | 344 } |
| 320 | 345 |
| 321 void define(Element element, DiagnosticListener listener) { | 346 void define(Element element, DiagnosticListener listener) { |
| 322 LibraryElement library = enclosingElement; | 347 LibraryElement library = enclosingElement; |
| 323 library.define(element, listener); | 348 library.define(element, listener); |
| 324 } | 349 } |
| 325 | 350 |
| 326 void addTag(ScriptTag tag, DiagnosticListener listener) { | 351 void addTag(ScriptTag tag, DiagnosticListener listener) { |
| 327 listener.cancel("script tags not allowed here", node: tag); | 352 listener.cancel("script tags not allowed here", node: tag); |
| 328 } | 353 } |
| 329 } | 354 } |
| 330 | 355 |
| 356 class CompilationUnitOverrideElement extends Element { |
| 357 final CompilationUnitElement compilationUnit; |
| 358 |
| 359 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, |
| 360 Element enclosing) |
| 361 : this.compilationUnit = compilationUnit, |
| 362 super(compilationUnit.name, |
| 363 ElementKind.COMPILATION_UNIT_OVERRIDE, |
| 364 enclosing); |
| 365 |
| 366 CompilationUnitElement asCompilationUnit() => compilationUnit; |
| 367 } |
| 368 |
| 331 class LibraryElement extends CompilationUnitElement { | 369 class LibraryElement extends CompilationUnitElement { |
| 332 // TODO(ahe): Library element should not be a subclass of | 370 // TODO(ahe): Library element should not be a subclass of |
| 333 // CompilationUnitElement. | 371 // CompilationUnitElement. |
| 334 | 372 |
| 335 Link<CompilationUnitElement> compilationUnits = | 373 Link<CompilationUnitElement> compilationUnits = |
| 336 const EmptyLink<CompilationUnitElement>(); | 374 const EmptyLink<CompilationUnitElement>(); |
| 337 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); | 375 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); |
| 338 ScriptTag libraryTag; | 376 ScriptTag libraryTag; |
| 339 Map<SourceString, Element> elements; | 377 Map<SourceString, Element> elements; |
| 340 bool canUseNative = false; | 378 bool canUseNative = false; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 return path.substring(path.lastIndexOf('/') + 1); | 451 return path.substring(path.lastIndexOf('/') + 1); |
| 414 } | 452 } |
| 415 } | 453 } |
| 416 | 454 |
| 417 Scope buildEnclosingScope() => new TopScope(this); | 455 Scope buildEnclosingScope() => new TopScope(this); |
| 418 } | 456 } |
| 419 | 457 |
| 420 class PrefixElement extends Element { | 458 class PrefixElement extends Element { |
| 421 Map<SourceString, Element> imported; | 459 Map<SourceString, Element> imported; |
| 422 Token firstPosition; | 460 Token firstPosition; |
| 423 final CompilationUnitElement patchSource; | |
| 424 | 461 |
| 425 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, | 462 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) |
| 426 [this.patchSource]) | 463 : imported = new Map<SourceString, Element>(), |
| 427 : imported = new Map<SourceString, Element>(), | 464 super(prefix, ElementKind.PREFIX, enclosing); |
| 428 super(prefix, ElementKind.PREFIX, enclosing); | |
| 429 | |
| 430 CompilationUnitElement getCompilationUnit() { | |
| 431 if (patchSource !== null) return patchSource; | |
| 432 return super.getCompilationUnit(); | |
| 433 } | |
| 434 | 465 |
| 435 lookupLocalMember(SourceString memberName) => imported[memberName]; | 466 lookupLocalMember(SourceString memberName) => imported[memberName]; |
| 436 | 467 |
| 437 Type computeType(Compiler compiler) => compiler.types.dynamicType; | 468 Type computeType(Compiler compiler) => compiler.types.dynamicType; |
| 438 | 469 |
| 439 Token position() => firstPosition; | 470 Token position() => firstPosition; |
| 471 |
| 472 PrefixElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 473 return new PrefixElement(name, enclosing, firstPosition); |
| 474 } |
| 440 } | 475 } |
| 441 | 476 |
| 442 class TypedefElement extends Element implements TypeDeclarationElement { | 477 class TypedefElement extends Element implements TypeDeclarationElement { |
| 443 Type cachedType; | 478 Type cachedType; |
| 444 Typedef cachedNode; | 479 Typedef cachedNode; |
| 445 | 480 |
| 446 TypedefElement(SourceString name, Element enclosing) | 481 TypedefElement(SourceString name, Element enclosing) |
| 447 : super(name, ElementKind.TYPEDEF, enclosing); | 482 : super(name, ElementKind.TYPEDEF, enclosing); |
| 448 | 483 |
| 449 Type computeType(Compiler compiler) { | 484 Type computeType(Compiler compiler) { |
| 450 if (cachedType !== null) return cachedType; | 485 if (cachedType !== null) return cachedType; |
| 451 cachedType = compiler.computeFunctionType( | 486 cachedType = compiler.computeFunctionType( |
| 452 this, compiler.resolveTypedef(this)); | 487 this, compiler.resolveTypedef(this)); |
| 453 return cachedType; | 488 return cachedType; |
| 454 } | 489 } |
| 455 | 490 |
| 456 Link<Type> get typeVariables() => const EmptyLink<Type>(); | 491 Link<Type> get typeVariables() => const EmptyLink<Type>(); |
| 457 | 492 |
| 458 Scope buildScope() => | 493 Scope buildScope() => |
| 459 new TypeDeclarationScope(enclosingElement.buildScope(), this); | 494 new TypeDeclarationScope(enclosingElement.buildScope(), this); |
| 495 |
| 496 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 497 TypedefElement result = new TypedefElement(name, enclosing); |
| 498 return result; |
| 499 } |
| 460 } | 500 } |
| 461 | 501 |
| 462 class VariableElement extends Element { | 502 class VariableElement extends Element { |
| 463 final VariableListElement variables; | 503 final VariableListElement variables; |
| 464 Expression cachedNode; // The send or the identifier in the variables list. | 504 Expression cachedNode; // The send or the identifier in the variables list. |
| 465 | 505 |
| 466 Modifiers get modifiers() => variables.modifiers; | 506 Modifiers get modifiers() => variables.modifiers; |
| 467 | 507 |
| 468 VariableElement(SourceString name, | 508 VariableElement(SourceString name, |
| 469 VariableListElement this.variables, | 509 VariableListElement this.variables, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 496 | 536 |
| 497 Type get type() => variables.type; | 537 Type get type() => variables.type; |
| 498 | 538 |
| 499 bool isInstanceMember() { | 539 bool isInstanceMember() { |
| 500 return isMember() && !modifiers.isStatic(); | 540 return isMember() && !modifiers.isStatic(); |
| 501 } | 541 } |
| 502 | 542 |
| 503 // Note: cachedNode.getBeginToken() will not be correct in all | 543 // Note: cachedNode.getBeginToken() will not be correct in all |
| 504 // cases, for example, for function typed parameters. | 544 // cases, for example, for function typed parameters. |
| 505 Token position() => findMyName(variables.position()); | 545 Token position() => findMyName(variables.position()); |
| 546 |
| 547 VariableElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 548 VariableListElement clonedVariables = |
| 549 variables.cloneTo(enclosing, listener); |
| 550 VariableElement result = new VariableElement( |
| 551 name, clonedVariables, kind, enclosing, cachedNode); |
| 552 return result; |
| 553 } |
| 506 } | 554 } |
| 507 | 555 |
| 508 /** | 556 /** |
| 509 * Parameters in constructors that directly initialize fields. For example: | 557 * Parameters in constructors that directly initialize fields. For example: |
| 510 * [:A(this.field):]. | 558 * [:A(this.field):]. |
| 511 */ | 559 */ |
| 512 class FieldParameterElement extends VariableElement { | 560 class FieldParameterElement extends VariableElement { |
| 513 VariableElement fieldElement; | 561 VariableElement fieldElement; |
| 514 | 562 |
| 515 FieldParameterElement(SourceString name, | 563 FieldParameterElement(SourceString name, |
| 516 this.fieldElement, | 564 this.fieldElement, |
| 517 VariableListElement variables, | 565 VariableListElement variables, |
| 518 Element enclosing, | 566 Element enclosing, |
| 519 Node node) | 567 Node node) |
| 520 : super(name, variables, ElementKind.FIELD_PARAMETER, enclosing, node); | 568 : super(name, variables, ElementKind.FIELD_PARAMETER, enclosing, node); |
| 569 |
| 570 FieldParameterElement cloneTo(Element enclosing, |
| 571 DiagnosticListener listener) { |
| 572 FieldParameterElement result = |
| 573 new FieldParameterElement(name, fieldElement, |
| 574 variables.cloneTo(enclosing, listener), |
| 575 enclosing, cachedNode); |
| 576 return result; |
| 577 } |
| 521 } | 578 } |
| 522 | 579 |
| 523 // This element represents a list of variable or field declaration. | 580 // This element represents a list of variable or field declaration. |
| 524 // It contains the node, and the type. A [VariableElement] always | 581 // It contains the node, and the type. A [VariableElement] always |
| 525 // references its [VariableListElement]. It forwards its | 582 // references its [VariableListElement]. It forwards its |
| 526 // [computeType] and [parseNode] methods to this element. | 583 // [computeType] and [parseNode] methods to this element. |
| 527 class VariableListElement extends Element { | 584 class VariableListElement extends Element { |
| 528 VariableDefinitions cachedNode; | 585 VariableDefinitions cachedNode; |
| 529 Type type; | 586 Type type; |
| 530 final Modifiers modifiers; | 587 final Modifiers modifiers; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 functionSignature); | 630 functionSignature); |
| 574 } else { | 631 } else { |
| 575 type = compiler.types.dynamicType; | 632 type = compiler.types.dynamicType; |
| 576 } | 633 } |
| 577 } | 634 } |
| 578 assert(type != null); | 635 assert(type != null); |
| 579 return type; | 636 return type; |
| 580 } | 637 } |
| 581 | 638 |
| 582 Token position() => cachedNode.getBeginToken(); | 639 Token position() => cachedNode.getBeginToken(); |
| 640 |
| 641 VariableListElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 642 VariableListElement result; |
| 643 if (cachedNode !== null) { |
| 644 result = new VariableListElement(cachedNode, kind, enclosing); |
| 645 } else { |
| 646 result = new VariableListElement(kind, modifiers, enclosing); |
| 647 } |
| 648 return result; |
| 649 } |
| 583 } | 650 } |
| 584 | 651 |
| 585 class ForeignElement extends Element { | 652 class ForeignElement extends Element { |
| 586 ForeignElement(SourceString name, ContainerElement enclosingElement) | 653 ForeignElement(SourceString name, ContainerElement enclosingElement) |
| 587 : super(name, ElementKind.FOREIGN, enclosingElement); | 654 : super(name, ElementKind.FOREIGN, enclosingElement); |
| 588 | 655 |
| 589 Type computeType(Compiler compiler) { | 656 Type computeType(Compiler compiler) { |
| 590 return compiler.types.dynamicType; | 657 return compiler.types.dynamicType; |
| 591 } | 658 } |
| 592 | 659 |
| 593 parseNode(DiagnosticListener listener) { | 660 parseNode(DiagnosticListener listener) { |
| 594 throw "internal error: ForeignElement has no node"; | 661 throw "internal error: ForeignElement has no node"; |
| 595 } | 662 } |
| 663 |
| 664 ForeignElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 665 ForeignElement result = new ForeignElement(name, kind, enclosing); |
| 666 return result; |
| 667 } |
| 596 } | 668 } |
| 597 | 669 |
| 598 class AbstractFieldElement extends Element { | 670 class AbstractFieldElement extends Element { |
| 599 FunctionElement getter; | 671 FunctionElement getter; |
| 600 FunctionElement setter; | 672 FunctionElement setter; |
| 601 | 673 |
| 602 AbstractFieldElement(SourceString name, Element enclosing) | 674 AbstractFieldElement(SourceString name, Element enclosing) |
| 603 : super(name, ElementKind.ABSTRACT_FIELD, enclosing); | 675 : super(name, ElementKind.ABSTRACT_FIELD, enclosing); |
| 604 | 676 |
| 605 Type computeType(Compiler compiler) { | 677 Type computeType(Compiler compiler) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 630 if (getter !== null) { | 702 if (getter !== null) { |
| 631 return new Modifiers.withFlags( | 703 return new Modifiers.withFlags( |
| 632 getter.modifiers.nodes, | 704 getter.modifiers.nodes, |
| 633 getter.modifiers.flags | Modifiers.FLAG_ABSTRACT); | 705 getter.modifiers.flags | Modifiers.FLAG_ABSTRACT); |
| 634 } else { | 706 } else { |
| 635 return new Modifiers.withFlags( | 707 return new Modifiers.withFlags( |
| 636 setter.modifiers.nodes, | 708 setter.modifiers.nodes, |
| 637 setter.modifiers.flags | Modifiers.FLAG_ABSTRACT); | 709 setter.modifiers.flags | Modifiers.FLAG_ABSTRACT); |
| 638 } | 710 } |
| 639 } | 711 } |
| 712 |
| 713 AbstractFieldElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 714 listener.cancel("Cannot clone synthetic AbstractFieldElement", |
| 715 element: this); |
| 716 } |
| 640 } | 717 } |
| 641 | 718 |
| 642 // TODO(johnniwinther): [FunctionSignature] should be merged with | 719 // TODO(johnniwinther): [FunctionSignature] should be merged with |
| 643 // [FunctionType]. | 720 // [FunctionType]. |
| 644 class FunctionSignature { | 721 class FunctionSignature { |
| 645 Link<Element> requiredParameters; | 722 Link<Element> requiredParameters; |
| 646 Link<Element> optionalParameters; | 723 Link<Element> optionalParameters; |
| 647 Type returnType; | 724 Type returnType; |
| 648 int requiredParameterCount; | 725 int requiredParameterCount; |
| 649 int optionalParameterCount; | 726 int optionalParameterCount; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 FunctionElement.tooMuchOverloading(SourceString name, | 791 FunctionElement.tooMuchOverloading(SourceString name, |
| 715 FunctionExpression this.cachedNode, | 792 FunctionExpression this.cachedNode, |
| 716 ElementKind kind, | 793 ElementKind kind, |
| 717 Modifiers this.modifiers, | 794 Modifiers this.modifiers, |
| 718 Element enclosing, | 795 Element enclosing, |
| 719 FunctionSignature this.functionSignature) | 796 FunctionSignature this.functionSignature) |
| 720 : super(name, kind, enclosing) { | 797 : super(name, kind, enclosing) { |
| 721 defaultImplementation = this; | 798 defaultImplementation = this; |
| 722 } | 799 } |
| 723 | 800 |
| 724 CompilationUnitElement getCompilationUnit() { | 801 Script getScript() { |
| 725 if (patch !== null) return patch.getCompilationUnit(); | 802 if (patch !== null) return patch.getScript(); |
| 726 return super.getCompilationUnit(); | 803 return super.getScript(); |
| 727 } | 804 } |
| 728 | 805 |
| 729 bool get isPatched() => patch !== null; | 806 bool get isPatched() => patch !== null; |
| 730 | 807 |
| 731 /** | 808 /** |
| 732 * Applies a patch function to this function. The patch function's body | 809 * Applies a patch function to this function. The patch function's body |
| 733 * is used as replacement when parsing this function's body. | 810 * is used as replacement when parsing this function's body. |
| 734 * This method must not be called after the function has been parsed, | 811 * This method must not be called after the function has been parsed, |
| 735 * and it must be called at most once. | 812 * and it must be called at most once. |
| 736 */ | 813 */ |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 } | 861 } |
| 785 return null; | 862 return null; |
| 786 } | 863 } |
| 787 cachedNode = patch.parseNode(listener); | 864 cachedNode = patch.parseNode(listener); |
| 788 return cachedNode; | 865 return cachedNode; |
| 789 } | 866 } |
| 790 | 867 |
| 791 Token position() => cachedNode.getBeginToken(); | 868 Token position() => cachedNode.getBeginToken(); |
| 792 | 869 |
| 793 FunctionElement asFunctionElement() => this; | 870 FunctionElement asFunctionElement() => this; |
| 871 |
| 872 FunctionElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 873 FunctionElement result = new FunctionElement.tooMuchOverloading( |
| 874 name, cachedNode, kind, modifiers, enclosing, functionSignature); |
| 875 result.defaultImplementation = defaultImplementation; |
| 876 result.type = type; |
| 877 return result; |
| 878 } |
| 794 } | 879 } |
| 795 | 880 |
| 881 |
| 796 class ConstructorBodyElement extends FunctionElement { | 882 class ConstructorBodyElement extends FunctionElement { |
| 797 FunctionElement constructor; | 883 FunctionElement constructor; |
| 798 | 884 |
| 799 ConstructorBodyElement(FunctionElement constructor) | 885 ConstructorBodyElement(FunctionElement constructor) |
| 800 : this.constructor = constructor, | 886 : this.constructor = constructor, |
| 801 super(constructor.name, | 887 super(constructor.name, |
| 802 ElementKind.GENERATIVE_CONSTRUCTOR_BODY, | 888 ElementKind.GENERATIVE_CONSTRUCTOR_BODY, |
| 803 null, | 889 null, |
| 804 constructor.enclosingElement) { | 890 constructor.enclosingElement) { |
| 805 functionSignature = constructor.functionSignature; | 891 functionSignature = constructor.functionSignature; |
| 806 } | 892 } |
| 807 | 893 |
| 808 bool isInstanceMember() => true; | 894 bool isInstanceMember() => true; |
| 809 | 895 |
| 810 FunctionType computeType(Compiler compiler) { | 896 FunctionType computeType(Compiler compiler) { |
| 811 compiler.reportFatalError('Internal error: $this.computeType', this); | 897 compiler.reportFatalError('Internal error: $this.computeType', this); |
| 812 } | 898 } |
| 813 | 899 |
| 814 Node parseNode(DiagnosticListener listener) { | 900 Node parseNode(DiagnosticListener listener) { |
| 815 if (cachedNode !== null) return cachedNode; | 901 if (cachedNode !== null) return cachedNode; |
| 816 cachedNode = constructor.parseNode(listener); | 902 cachedNode = constructor.parseNode(listener); |
| 817 assert(cachedNode !== null); | 903 assert(cachedNode !== null); |
| 818 return cachedNode; | 904 return cachedNode; |
| 819 } | 905 } |
| 820 | 906 |
| 821 Token position() => constructor.position(); | 907 Token position() => constructor.position(); |
| 908 |
| 909 ConstructorBodyElement cloneTo(Element enclosing, |
| 910 DiagnosticListener listener) { |
| 911 ConstructorBodyElement result = |
| 912 new ConstructorBodyElement(constructor.cloneTo(enclosing, listener)); |
| 913 return result; |
| 914 } |
| 822 } | 915 } |
| 823 | 916 |
| 824 class SynthesizedConstructorElement extends FunctionElement { | 917 class SynthesizedConstructorElement extends FunctionElement { |
| 825 SynthesizedConstructorElement(Element enclosing) | 918 SynthesizedConstructorElement(Element enclosing) |
| 826 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, | 919 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, |
| 827 null, enclosing); | 920 null, enclosing); |
| 828 | 921 |
| 829 Token position() => enclosingElement.position(); | 922 Token position() => enclosingElement.position(); |
| 923 |
| 924 SynthesizedConstructorElement cloneTo(Element enclosing, |
| 925 DiagnosticListener listener) { |
| 926 return new SynthesizedConstructorElement(enclosing); |
| 927 } |
| 830 } | 928 } |
| 831 | 929 |
| 832 class VoidElement extends Element { | 930 class VoidElement extends Element { |
| 833 VoidElement(Element enclosing) | 931 VoidElement(Element enclosing) |
| 834 : super(const SourceString('void'), ElementKind.VOID, enclosing); | 932 : super(const SourceString('void'), ElementKind.VOID, enclosing); |
| 835 Type computeType(compiler) => compiler.types.voidType; | 933 Type computeType(compiler) => compiler.types.voidType; |
| 836 Node parseNode(_) { | 934 Node parseNode(_) { |
| 837 throw 'internal error: parseNode on void'; | 935 throw 'internal error: parseNode on void'; |
| 838 } | 936 } |
| 839 bool impliesType() => true; | 937 bool impliesType() => true; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 class ClassElement extends ContainerElement | 980 class ClassElement extends ContainerElement |
| 883 implements TypeDeclarationElement { | 981 implements TypeDeclarationElement { |
| 884 final int id; | 982 final int id; |
| 885 InterfaceType type; | 983 InterfaceType type; |
| 886 Type supertype; | 984 Type supertype; |
| 887 Type defaultClass; | 985 Type defaultClass; |
| 888 Link<Element> members = const EmptyLink<Element>(); | 986 Link<Element> members = const EmptyLink<Element>(); |
| 889 Map<SourceString, Element> localMembers; | 987 Map<SourceString, Element> localMembers; |
| 890 Map<SourceString, Element> constructors; | 988 Map<SourceString, Element> constructors; |
| 891 Link<Type> interfaces = const EmptyLink<Type>(); | 989 Link<Type> interfaces = const EmptyLink<Type>(); |
| 990 |
| 991 LinkedHashMap<SourceString, TypeVariableElement> typeParameters; |
| 992 SourceString nativeName; |
| 993 |
| 892 bool isResolved = false; | 994 bool isResolved = false; |
| 893 bool isBeingResolved = false; | 995 bool isBeingResolved = false; |
| 894 // backendMembers are members that have been added by the backend to simplify | 996 // backendMembers are members that have been added by the backend to simplify |
| 895 // compilation. They don't have any user-side counter-part. | 997 // compilation. They don't have any user-side counter-part. |
| 896 Link<Element> backendMembers = const EmptyLink<Element>(); | 998 Link<Element> backendMembers = const EmptyLink<Element>(); |
| 897 | 999 |
| 898 Link<Type> allSupertypes; | 1000 Link<Type> allSupertypes; |
| 899 ClassElement patch = null; | |
| 900 | 1001 |
| 901 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) | 1002 ClassElement(SourceString name, Element enclosing, this.id) |
| 902 : localMembers = new Map<SourceString, Element>(), | 1003 : localMembers = new Map<SourceString, Element>(), |
| 903 constructors = new Map<SourceString, Element>(), | 1004 constructors = new Map<SourceString, Element>(), |
| 904 super(name, ElementKind.CLASS, enclosing); | 1005 super(name, ElementKind.CLASS, enclosing); |
| 905 | 1006 |
| 906 void addMember(Element element, DiagnosticListener listener) { | 1007 void addMember(Element element, DiagnosticListener listener) { |
| 907 members = members.prepend(element); | 1008 members = members.prepend(element); |
| 908 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | 1009 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
| 909 element.modifiers.isFactory()) { | 1010 element.modifiers.isFactory()) { |
| 910 constructors[element.name] = element; | 1011 constructors[element.name] = element; |
| 911 } else if (element.kind == ElementKind.GETTER | 1012 } else if (element.kind == ElementKind.GETTER |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 // lookupMember will work. | 1080 // lookupMember will work. |
| 980 while (lookupClass.getLibrary() != memberLibrary) { | 1081 while (lookupClass.getLibrary() != memberLibrary) { |
| 981 lookupClass = lookupClass.superclass; | 1082 lookupClass = lookupClass.superclass; |
| 982 } | 1083 } |
| 983 } | 1084 } |
| 984 SourceString fieldName = fieldMember.name; | 1085 SourceString fieldName = fieldMember.name; |
| 985 while (true) { | 1086 while (true) { |
| 986 Element foundMember = lookupClass.lookupMember(fieldName); | 1087 Element foundMember = lookupClass.lookupMember(fieldName); |
| 987 if (foundMember == fieldMember) return false; | 1088 if (foundMember == fieldMember) return false; |
| 988 if (foundMember.isField()) return true; | 1089 if (foundMember.isField()) return true; |
| 989 lookupClass = (foundMember.enclosingElement as ClassElement).superclass; | 1090 lookupClass = foundMember.getEnclosingClass().superclass; |
| 990 } | 1091 } |
| 991 } | 1092 } |
| 992 | 1093 |
| 993 Element lookupConstructor(SourceString className, | 1094 Element lookupConstructor(SourceString className, |
| 994 [SourceString constructorName = | 1095 [SourceString constructorName = |
| 995 const SourceString(''), | 1096 const SourceString(''), |
| 996 Element noMatch(Element)]) { | 1097 Element noMatch(Element)]) { |
| 997 // TODO(karlklose): have a map from class names to a map of constructors | 1098 // TODO(karlklose): have a map from class names to a map of constructors |
| 998 // instead of creating the name here? | 1099 // instead of creating the name here? |
| 999 SourceString normalizedName; | 1100 SourceString normalizedName; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 */ | 1189 */ |
| 1089 bool isSubclassOf(ClassElement cls) { | 1190 bool isSubclassOf(ClassElement cls) { |
| 1090 for (ClassElement s = this; s != null; s = s.superclass) { | 1191 for (ClassElement s = this; s != null; s = s.superclass) { |
| 1091 if (s === cls) return true; | 1192 if (s === cls) return true; |
| 1092 } | 1193 } |
| 1093 return false; | 1194 return false; |
| 1094 } | 1195 } |
| 1095 | 1196 |
| 1096 bool isInterface() => false; | 1197 bool isInterface() => false; |
| 1097 bool isNative() => nativeName != null; | 1198 bool isNative() => nativeName != null; |
| 1098 SourceString nativeName; | |
| 1099 int hashCode() => id; | 1199 int hashCode() => id; |
| 1100 | 1200 |
| 1101 Scope buildScope() => | 1201 Scope buildScope() => |
| 1102 new ClassScope(enclosingElement.buildScope(), this); | 1202 new ClassScope(enclosingElement.buildScope(), this); |
| 1203 |
| 1204 void cloneMembersTo(Element target, DiagnosticListener listener) { |
| 1205 target.type = type; |
| 1206 target.supertype = supertype; |
| 1207 target.defaultClass = defaultClass; |
| 1208 target.interfaces = interfaces; |
| 1209 if (typeParameters !== null) { |
| 1210 target.typeParameters = |
| 1211 new LinkedHashMap<SourceString, TypeVariableElement>(); |
| 1212 typeParameters.forEach((SourceString name, TypeVariableElement type) { |
| 1213 target.typeParameters[name] = type.cloneTo(target, listener); |
| 1214 }); |
| 1215 } |
| 1216 target.nativeName = nativeName; |
| 1217 target.isResolved = isResolved; |
| 1218 target.isBeingResolved = isBeingResolved; |
| 1219 target.allSupertypes = allSupertypes; |
| 1220 if (!backendMembers.isEmpty()) { |
| 1221 listener.cancel("Cloning backend-modified class.", element: this); |
| 1222 } |
| 1223 |
| 1224 Link<Element> elementList = this.members; |
| 1225 while (!elementList.isEmpty()) { |
| 1226 target.addMember(elementList.head.cloneTo(target, listener), listener); |
| 1227 elementList = elementList.tail; |
| 1228 } |
| 1229 } |
| 1230 |
| 1231 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1232 // TODO(lrn): Is copying id acceptable? |
| 1233 ClassElement result = new ClassElement(name, enclosing, id); |
| 1234 cloneMembersTo(result, listener); |
| 1235 return result; |
| 1236 } |
| 1103 } | 1237 } |
| 1104 | 1238 |
| 1105 class Elements { | 1239 class Elements { |
| 1106 static bool isLocal(Element element) { | 1240 static bool isLocal(Element element) { |
| 1107 return ((element !== null) | 1241 return ((element !== null) |
| 1108 && !element.isInstanceMember() | 1242 && !element.isInstanceMember() |
| 1109 && !isStaticOrTopLevelField(element) | 1243 && !isStaticOrTopLevelField(element) |
| 1110 && !isStaticOrTopLevelFunction(element) | 1244 && !isStaticOrTopLevelFunction(element) |
| 1111 && (element.kind === ElementKind.VARIABLE || | 1245 && (element.kind === ElementKind.VARIABLE || |
| 1112 element.kind === ElementKind.PARAMETER || | 1246 element.kind === ElementKind.PARAMETER || |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 || (element == coreLibrary.find(const SourceString('Pattern'))); | 1346 || (element == coreLibrary.find(const SourceString('Pattern'))); |
| 1213 } | 1347 } |
| 1214 | 1348 |
| 1215 static bool isListSupertype(Element element, Compiler compiler) { | 1349 static bool isListSupertype(Element element, Compiler compiler) { |
| 1216 LibraryElement coreLibrary = compiler.coreLibrary; | 1350 LibraryElement coreLibrary = compiler.coreLibrary; |
| 1217 return (element == coreLibrary.find(const SourceString('Collection'))) | 1351 return (element == coreLibrary.find(const SourceString('Collection'))) |
| 1218 || (element == coreLibrary.find(const SourceString('Iterable'))); | 1352 || (element == coreLibrary.find(const SourceString('Iterable'))); |
| 1219 } | 1353 } |
| 1220 } | 1354 } |
| 1221 | 1355 |
| 1222 | |
| 1223 class LabelElement extends Element { | 1356 class LabelElement extends Element { |
| 1224 // We store the original label here so it can be returned by [parseNode]. | 1357 // We store the original label here so it can be returned by [parseNode]. |
| 1225 final Label label; | 1358 final Label label; |
| 1226 final String labelName; | 1359 final String labelName; |
| 1227 final TargetElement target; | 1360 final TargetElement target; |
| 1228 bool isBreakTarget = false; | 1361 bool isBreakTarget = false; |
| 1229 bool isContinueTarget = false; | 1362 bool isContinueTarget = false; |
| 1230 LabelElement(Label label, this.labelName, this.target, | 1363 LabelElement(Label label, this.labelName, this.target, |
| 1231 Element enclosingElement) | 1364 Element enclosingElement) |
| 1232 : this.label = label, | 1365 : this.label = label, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 | 1416 |
| 1284 TypeVariableElement(name, Element enclosing, this.cachedNode, | 1417 TypeVariableElement(name, Element enclosing, this.cachedNode, |
| 1285 [this.type, this.bound]) | 1418 [this.type, this.bound]) |
| 1286 : super(name, ElementKind.TYPE_VARIABLE, enclosing); | 1419 : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
| 1287 | 1420 |
| 1288 TypeVariableType computeType(compiler) => type; | 1421 TypeVariableType computeType(compiler) => type; |
| 1289 | 1422 |
| 1290 Node parseNode(compiler) => cachedNode; | 1423 Node parseNode(compiler) => cachedNode; |
| 1291 | 1424 |
| 1292 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1425 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; |
| 1426 |
| 1427 TypeVariableElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1428 TypeVariableElement result = |
| 1429 new TypeVariableElement(name, enclosing, node, type, bound); |
| 1430 return result; |
| 1431 } |
| 1293 } | 1432 } |
| OLD | NEW |