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 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 static final int ALIAS = 32; | 32 static final int ALIAS = 32; |
33 | 33 |
34 static final int SUPER = 64; | 34 static final int SUPER = 64; |
35 | 35 |
36 /** Type variable */ | 36 /** Type variable */ |
37 static final int TYPE_VARIABLE = 128; | 37 static final int TYPE_VARIABLE = 128; |
38 | 38 |
39 static final int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE; | 39 static final int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE; |
40 | 40 |
41 static final int IS_EXTENDABLE = CLASS | ALIAS; | 41 static final int IS_EXTENDABLE = CLASS; |
42 } | 42 } |
43 | 43 |
44 class ElementKind { | 44 class ElementKind { |
45 final String id; | 45 final String id; |
46 final int category; | 46 final int category; |
47 | 47 |
48 const ElementKind(String this.id, this.category); | 48 const ElementKind(String this.id, this.category); |
49 | 49 |
50 static final ElementKind VARIABLE = | 50 static final ElementKind VARIABLE = |
51 const ElementKind('variable', ElementCategory.VARIABLE); | 51 const ElementKind('variable', ElementCategory.VARIABLE); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 | 207 |
208 Element getOutermostEnclosingMemberOrTopLevel() { | 208 Element getOutermostEnclosingMemberOrTopLevel() { |
209 for (Element e = this; e !== null; e = e.enclosingElement) { | 209 for (Element e = this; e !== null; e = e.enclosingElement) { |
210 if (e.isMember() || e.isTopLevel()) { | 210 if (e.isMember() || e.isTopLevel()) { |
211 return e; | 211 return e; |
212 } | 212 } |
213 } | 213 } |
214 return null; | 214 return null; |
215 } | 215 } |
216 | 216 |
217 /** | |
218 * Creates the scope for this element. The scope of the | |
219 * enclosing element will be the parent scope. | |
220 */ | |
221 Scope buildScope() => buildEnclosingScope(); | |
222 | |
223 /** | |
224 * Creates the scope for the enclosing element. The scope of the | |
225 * enclosing element will be the parent scope. | |
ahe
2012/08/02 06:43:14
Could you explain what the difference between thes
| |
226 */ | |
227 Scope buildEnclosingScope() => enclosingElement.buildScope(); | |
228 | |
217 String toString() { | 229 String toString() { |
218 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an | 230 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an |
219 // invariant for all element types? | 231 // invariant for all element types? |
220 var nameText = name !== null ? name.slowToString() : '?'; | 232 var nameText = name !== null ? name.slowToString() : '?'; |
221 if (enclosingElement !== null && !isTopLevel()) { | 233 if (enclosingElement !== null && !isTopLevel()) { |
222 String holderName = enclosingElement.name !== null | 234 String holderName = enclosingElement.name !== null |
223 ? enclosingElement.name.slowToString() | 235 ? enclosingElement.name.slowToString() |
224 : '${enclosingElement.kind}?'; | 236 : '${enclosingElement.kind}?'; |
225 return '$kind($holderName#${nameText})'; | 237 return '$kind($holderName#${nameText})'; |
226 } else { | 238 } else { |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 */ | 399 */ |
388 String getLibraryOrScriptName() { | 400 String getLibraryOrScriptName() { |
389 if (libraryTag !== null) { | 401 if (libraryTag !== null) { |
390 return libraryTag.argument.dartString.slowToString(); | 402 return libraryTag.argument.dartString.slowToString(); |
391 } else { | 403 } else { |
392 // Use the file name as script name. | 404 // Use the file name as script name. |
393 var path = script.uri.path; | 405 var path = script.uri.path; |
394 return path.substring(path.lastIndexOf('/') + 1); | 406 return path.substring(path.lastIndexOf('/') + 1); |
395 } | 407 } |
396 } | 408 } |
409 | |
410 Scope buildEnclosingScope() => new TopScope(this); | |
397 } | 411 } |
398 | 412 |
399 class PrefixElement extends Element { | 413 class PrefixElement extends Element { |
400 Map<SourceString, Element> imported; | 414 Map<SourceString, Element> imported; |
401 Token firstPosition; | 415 Token firstPosition; |
402 final CompilationUnitElement patchSource; | 416 final CompilationUnitElement patchSource; |
403 | 417 |
404 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, | 418 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, |
405 [this.patchSource]) | 419 [this.patchSource]) |
406 : imported = new Map<SourceString, Element>(), | 420 : imported = new Map<SourceString, Element>(), |
407 super(prefix, ElementKind.PREFIX, enclosing); | 421 super(prefix, ElementKind.PREFIX, enclosing); |
408 | 422 |
409 CompilationUnitElement getCompilationUnit() { | 423 CompilationUnitElement getCompilationUnit() { |
410 if (patchSource !== null) return patchSource; | 424 if (patchSource !== null) return patchSource; |
411 return super.getCompilationUnit(); | 425 return super.getCompilationUnit(); |
412 } | 426 } |
413 | 427 |
414 lookupLocalMember(SourceString memberName) => imported[memberName]; | 428 lookupLocalMember(SourceString memberName) => imported[memberName]; |
415 | 429 |
416 Type computeType(Compiler compiler) => compiler.types.dynamicType; | 430 Type computeType(Compiler compiler) => compiler.types.dynamicType; |
417 | 431 |
418 Token position() => firstPosition; | 432 Token position() => firstPosition; |
419 } | 433 } |
420 | 434 |
421 class TypedefElement extends Element { | 435 class TypedefElement extends Element implements TypeDeclarationElement { |
422 Type cachedType; | 436 TypedefElement(SourceString name, Element enclosing) |
437 : super(name, ElementKind.TYPEDEF, enclosing); | |
438 | |
439 TypedefType cachedType; | |
440 Type alias; | |
423 Typedef cachedNode; | 441 Typedef cachedNode; |
424 | 442 |
425 TypedefElement(SourceString name, Element enclosing) | 443 /** |
426 : super(name, ElementKind.TYPEDEF, enclosing); | 444 * Function signature for a typedef of a function type. The signature is |
445 * kept to provide full information about parameter names through the mirror | |
446 * system. | |
447 * | |
448 * The [functionSignature] is not available until the typedef element has been | |
449 * resolved. | |
450 */ | |
451 FunctionSignature functionSignature; | |
427 | 452 |
428 Type computeType(Compiler compiler) { | 453 TypedefType computeType(Compiler compiler) { |
429 if (cachedType !== null) return cachedType; | 454 if (cachedType == null) { |
430 cachedType = compiler.computeFunctionType( | 455 Typedef node = parseNode(compiler); |
431 this, compiler.resolveTypedef(this)); | 456 Link<TypeVariableType> parameters = |
457 createTypeVariables(this, node.typeParameters); | |
ahe
2012/08/02 06:43:14
How about adding:
assert(cachedType === null);
| |
458 cachedType = new TypedefType(this, parameters); | |
459 } | |
432 return cachedType; | 460 return cachedType; |
433 } | 461 } |
462 | |
463 | |
464 Link<TypeVariableType> get typeVariables() => cachedType.typeArguments; | |
465 | |
466 Scope buildScope() => | |
467 new TypeDeclarationScope(enclosingElement.buildScope(), this); | |
434 } | 468 } |
435 | 469 |
436 class VariableElement extends Element { | 470 class VariableElement extends Element { |
437 final VariableListElement variables; | 471 final VariableListElement variables; |
438 Expression cachedNode; // The send or the identifier in the variables list. | 472 Expression cachedNode; // The send or the identifier in the variables list. |
439 | 473 |
440 Modifiers get modifiers() => variables.modifiers; | 474 Modifiers get modifiers() => variables.modifiers; |
441 | 475 |
442 VariableElement(SourceString name, | 476 VariableElement(SourceString name, |
443 VariableListElement this.variables, | 477 VariableListElement this.variables, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 // It contains the node, and the type. A [VariableElement] always | 532 // It contains the node, and the type. A [VariableElement] always |
499 // references its [VariableListElement]. It forwards its | 533 // references its [VariableListElement]. It forwards its |
500 // [computeType] and [parseNode] methods to this element. | 534 // [computeType] and [parseNode] methods to this element. |
501 class VariableListElement extends Element { | 535 class VariableListElement extends Element { |
502 VariableDefinitions cachedNode; | 536 VariableDefinitions cachedNode; |
503 Type type; | 537 Type type; |
504 final Modifiers modifiers; | 538 final Modifiers modifiers; |
505 | 539 |
506 /** | 540 /** |
507 * Function signature for a variable with a function type. The signature is | 541 * Function signature for a variable with a function type. The signature is |
508 * kept to provide full information about parameter names through the the | 542 * kept to provide full information about parameter names through the mirror |
509 * mirror system. | 543 * system. |
510 */ | 544 */ |
511 FunctionSignature functionSignature; | 545 FunctionSignature functionSignature; |
512 | 546 |
513 VariableListElement(ElementKind kind, | 547 VariableListElement(ElementKind kind, |
514 Modifiers this.modifiers, | 548 Modifiers this.modifiers, |
515 Element enclosing) | 549 Element enclosing) |
516 : super(null, kind, enclosing); | 550 : super(null, kind, enclosing); |
517 | 551 |
518 VariableListElement.node(VariableDefinitions node, | 552 VariableListElement.node(VariableDefinitions node, |
519 ElementKind kind, | 553 ElementKind kind, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 getter.modifiers.nodes, | 640 getter.modifiers.nodes, |
607 getter.modifiers.flags | Modifiers.FLAG_ABSTRACT); | 641 getter.modifiers.flags | Modifiers.FLAG_ABSTRACT); |
608 } else { | 642 } else { |
609 return new Modifiers.withFlags( | 643 return new Modifiers.withFlags( |
610 setter.modifiers.nodes, | 644 setter.modifiers.nodes, |
611 setter.modifiers.flags | Modifiers.FLAG_ABSTRACT); | 645 setter.modifiers.flags | Modifiers.FLAG_ABSTRACT); |
612 } | 646 } |
613 } | 647 } |
614 } | 648 } |
615 | 649 |
650 // TODO(johnniwinther): [FunctionSignature] should be merged with | |
651 // [FunctionType]. | |
616 class FunctionSignature { | 652 class FunctionSignature { |
617 Link<Element> requiredParameters; | 653 Link<Element> requiredParameters; |
618 Link<Element> optionalParameters; | 654 Link<Element> optionalParameters; |
619 Type returnType; | 655 Type returnType; |
620 int requiredParameterCount; | 656 int requiredParameterCount; |
621 int optionalParameterCount; | 657 int optionalParameterCount; |
622 FunctionSignature(this.requiredParameters, | 658 FunctionSignature(this.requiredParameters, |
623 this.optionalParameters, | 659 this.optionalParameters, |
624 this.requiredParameterCount, | 660 this.requiredParameterCount, |
625 this.optionalParameterCount, | 661 this.optionalParameterCount, |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
804 class VoidElement extends Element { | 840 class VoidElement extends Element { |
805 VoidElement(Element enclosing) | 841 VoidElement(Element enclosing) |
806 : super(const SourceString('void'), ElementKind.VOID, enclosing); | 842 : super(const SourceString('void'), ElementKind.VOID, enclosing); |
807 Type computeType(compiler) => compiler.types.voidType; | 843 Type computeType(compiler) => compiler.types.voidType; |
808 Node parseNode(_) { | 844 Node parseNode(_) { |
809 throw 'internal error: parseNode on void'; | 845 throw 'internal error: parseNode on void'; |
810 } | 846 } |
811 bool impliesType() => true; | 847 bool impliesType() => true; |
812 } | 848 } |
813 | 849 |
814 class ClassElement extends ContainerElement { | 850 /** |
851 * [TypeDeclarationElement] defines the common interface for class/interface | |
852 * declarations and typedefs. | |
853 */ | |
854 interface TypeDeclarationElement extends Element { | |
855 /** | |
856 * The type variables declared on this declaration. The type variables are not | |
857 * available until the type of the element has been computed through | |
858 * [computeType]. | |
859 */ | |
860 // TODO(johnniwinther): Find a (better) way to decouple [typeVariables] from | |
861 // [Compiler]. | |
862 final Link<TypeVariableType> typeVariables; | |
863 } | |
864 | |
865 /** | |
866 * Creates the type variables, their type and corresponding element, for the | |
867 * type variables declared in [parameter] on [element]. The bounds of the type | |
868 * variables are not set until [element] has been resolved. | |
869 */ | |
870 Link<TypeVariableType> createTypeVariables(TypeDeclarationElement element, | |
871 NodeList parameters) { | |
872 if (parameters === null) return const EmptyLink<TypeVariableType>(); | |
873 | |
874 // Create types and elements for type variable. | |
875 var arguments = new LinkBuilder<TypeVariableType>(); | |
876 for (Link<Node> link = parameters.nodes; !link.isEmpty(); link = link.tail) { | |
877 TypeVariable typeNode = link.head; | |
878 SourceString variableName = typeNode.name.source; | |
879 TypeVariableType variableType = new TypeVariableType(variableName); | |
880 arguments.addLast(variableType); | |
881 TypeVariableElement variableElement = | |
882 new TypeVariableElement(variableName, element, typeNode, variableType); | |
883 variableType.element = variableElement; | |
884 } | |
885 return arguments.toLink(); | |
886 } | |
887 | |
888 /** | |
889 * Looks up [name] within the type variables declared in [element]. | |
890 */ | |
891 Element lookupTypeVariable(TypeDeclarationElement element, | |
892 SourceString name) { | |
893 Link<TypeVariableType> typeVariableLink = element.typeVariables; | |
894 while (!typeVariableLink.isEmpty()) { | |
895 TypeVariableType typeVariable = typeVariableLink.head; | |
896 if (typeVariable.name == name) { | |
897 return typeVariable.element; | |
898 } | |
899 typeVariableLink = typeVariableLink.tail; | |
900 } | |
901 return null; | |
902 } | |
903 | |
ahe
2012/08/02 06:43:14
Extra line.
| |
904 | |
905 class ClassElement extends ContainerElement | |
906 implements TypeDeclarationElement { | |
815 final int id; | 907 final int id; |
816 Type type; | 908 InterfaceType type; |
817 Type supertype; | 909 InterfaceType supertype; |
ahe
2012/08/02 06:43:14
Eventually an interface may extend a typedef. So I
| |
818 Type defaultClass; | 910 InterfaceType defaultClass; |
819 Link<Element> members = const EmptyLink<Element>(); | 911 Link<Element> members = const EmptyLink<Element>(); |
820 Map<SourceString, Element> localMembers; | 912 Map<SourceString, Element> localMembers; |
821 Map<SourceString, Element> constructors; | 913 Map<SourceString, Element> constructors; |
822 Link<Type> interfaces = const EmptyLink<Type>(); | 914 Link<InterfaceType> interfaces = const EmptyLink<InterfaceType>(); |
823 LinkedHashMap<SourceString, TypeVariableElement> typeParameters; | |
824 bool isResolved = false; | 915 bool isResolved = false; |
825 bool isBeingResolved = false; | 916 bool isBeingResolved = false; |
826 // backendMembers are members that have been added by the backend to simplify | 917 // backendMembers are members that have been added by the backend to simplify |
827 // compilation. They don't have any user-side counter-part. | 918 // compilation. They don't have any user-side counter-part. |
828 Link<Element> backendMembers = const EmptyLink<Element>(); | 919 Link<Element> backendMembers = const EmptyLink<Element>(); |
829 | 920 |
830 Link<Type> allSupertypes; | 921 Link<InterfaceType> allSupertypes; |
831 ClassElement patch = null; | 922 ClassElement patch = null; |
832 Node defaultClause; // Only for interfaces. | 923 Node defaultClause; // Only for interfaces. |
833 | 924 |
834 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) | 925 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) |
835 : localMembers = new Map<SourceString, Element>(), | 926 : localMembers = new Map<SourceString, Element>(), |
836 constructors = new Map<SourceString, Element>(), | 927 constructors = new Map<SourceString, Element>(), |
837 typeParameters = new LinkedHashMap<SourceString, TypeVariableElement>(), | |
838 super(name, ElementKind.CLASS, enclosing); | 928 super(name, ElementKind.CLASS, enclosing); |
839 | 929 |
840 void addMember(Element element, DiagnosticListener listener) { | 930 void addMember(Element element, DiagnosticListener listener) { |
841 members = members.prepend(element); | 931 members = members.prepend(element); |
842 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | 932 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
843 element.modifiers.isFactory()) { | 933 element.modifiers.isFactory()) { |
844 constructors[element.name] = element; | 934 constructors[element.name] = element; |
845 } else if (element.kind == ElementKind.GETTER | 935 } else if (element.kind == ElementKind.GETTER |
846 || element.kind == ElementKind.SETTER) { | 936 || element.kind == ElementKind.SETTER) { |
847 addGetterOrSetter(element, localMembers[element.name], listener); | 937 addGetterOrSetter(element, localMembers[element.name], listener); |
848 } else { | 938 } else { |
849 localMembers[element.name] = element; | 939 localMembers[element.name] = element; |
850 } | 940 } |
851 } | 941 } |
852 | 942 |
853 Type computeType(compiler) { | 943 InterfaceType computeType(compiler) { |
854 if (type === null) { | 944 if (type == null) { |
855 type = new InterfaceType(this); | 945 ClassNode node = parseNode(compiler); |
946 Link<TypeVariableType> parameters = | |
947 createTypeVariables(this, node.typeParameters); | |
948 type = new InterfaceType(this, parameters); | |
856 } | 949 } |
857 return type; | 950 return type; |
858 } | 951 } |
859 | 952 |
953 Link<TypeVariableType> get typeVariables() => type.typeArguments; | |
ahe
2012/08/02 06:43:14
Same applies here, so I would prefer Link<Type>.
| |
954 | |
860 ClassElement ensureResolved(Compiler compiler) { | 955 ClassElement ensureResolved(Compiler compiler) { |
861 compiler.resolveClass(this); | 956 compiler.resolveClass(this); |
862 return this; | 957 return this; |
863 } | 958 } |
864 | 959 |
865 Element lookupTypeParameter(SourceString parameterName) { | |
866 Element result = typeParameters[parameterName]; | |
867 return result; | |
868 } | |
869 | |
870 Element lookupLocalMember(SourceString memberName) { | 960 Element lookupLocalMember(SourceString memberName) { |
871 return localMembers[memberName]; | 961 return localMembers[memberName]; |
872 } | 962 } |
873 | 963 |
874 Element lookupSuperMember(SourceString memberName) { | 964 Element lookupSuperMember(SourceString memberName) { |
875 for (ClassElement s = superclass; s != null; s = s.superclass) { | 965 for (ClassElement s = superclass; s != null; s = s.superclass) { |
876 Element e = s.lookupLocalMember(memberName); | 966 Element e = s.lookupLocalMember(memberName); |
877 if (e === null) continue; | 967 if (e === null) continue; |
878 // Private members from a different library are not visible. | 968 // Private members from a different library are not visible. |
879 if (memberName.isPrivate() && getLibrary() !== e.getLibrary()) continue; | 969 if (memberName.isPrivate() && getLibrary() !== e.getLibrary()) continue; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
995 for (ClassElement s = this; s != null; s = s.superclass) { | 1085 for (ClassElement s = this; s != null; s = s.superclass) { |
996 if (s === cls) return true; | 1086 if (s === cls) return true; |
997 } | 1087 } |
998 return false; | 1088 return false; |
999 } | 1089 } |
1000 | 1090 |
1001 bool isInterface() => false; | 1091 bool isInterface() => false; |
1002 bool isNative() => nativeName != null; | 1092 bool isNative() => nativeName != null; |
1003 SourceString nativeName; | 1093 SourceString nativeName; |
1004 int hashCode() => id; | 1094 int hashCode() => id; |
1095 | |
1096 Scope buildScope() => | |
1097 new ClassScope(enclosingElement.buildScope(), this); | |
1005 } | 1098 } |
1006 | 1099 |
1007 class Elements { | 1100 class Elements { |
1008 static bool isLocal(Element element) { | 1101 static bool isLocal(Element element) { |
1009 return ((element !== null) | 1102 return ((element !== null) |
1010 && !element.isInstanceMember() | 1103 && !element.isInstanceMember() |
1011 && !isStaticOrTopLevelField(element) | 1104 && !isStaticOrTopLevelField(element) |
1012 && !isStaticOrTopLevelFunction(element) | 1105 && !isStaticOrTopLevelFunction(element) |
1013 && (element.kind === ElementKind.VARIABLE || | 1106 && (element.kind === ElementKind.VARIABLE || |
1014 element.kind === ElementKind.PARAMETER || | 1107 element.kind === ElementKind.PARAMETER || |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1173 | 1266 |
1174 Node parseNode(DiagnosticListener l) => statement; | 1267 Node parseNode(DiagnosticListener l) => statement; |
1175 | 1268 |
1176 bool get isSwitch() => statement is SwitchStatement; | 1269 bool get isSwitch() => statement is SwitchStatement; |
1177 | 1270 |
1178 Token position() => statement.getBeginToken(); | 1271 Token position() => statement.getBeginToken(); |
1179 String toString() => statement.toString(); | 1272 String toString() => statement.toString(); |
1180 } | 1273 } |
1181 | 1274 |
1182 class TypeVariableElement extends Element { | 1275 class TypeVariableElement extends Element { |
1183 final Node node; | 1276 final Node cachedNode; |
1184 Type bound; | 1277 Type bound; |
1185 Type type; | 1278 TypeVariableType type; |
1186 TypeVariableElement(name, Element enclosing, this.node, this.type, | 1279 |
1280 TypeVariableElement(name, Element enclosing, this.cachedNode, this.type, | |
1187 [this.bound]) | 1281 [this.bound]) |
1188 : super(name, ElementKind.TYPE_VARIABLE, enclosing); | 1282 : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
1189 Type computeType(compiler) => type; | 1283 |
1190 Node parseNode(compiler) => node; | 1284 TypeVariableType computeType(compiler) => type; |
1191 toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1285 |
1286 Node parseNode(compiler) => cachedNode; | |
1287 | |
1288 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | |
ahe
2012/08/02 06:43:14
This change is fine, but am I the only one thinkin
| |
1192 } | 1289 } |
OLD | NEW |