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

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

Issue 10834061: Resolve typedefs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated scope handling and type resolution 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
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('../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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698