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 interface TreeElements { | 5 interface TreeElements { |
| 6 Element operator[](Node node); | 6 Element operator[](Node node); |
| 7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
| 8 Type getType(TypeAnnotation annotation); | 8 Type getType(TypeAnnotation annotation); |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 584 nestingLevel++; | 584 nestingLevel++; |
| 585 } | 585 } |
| 586 | 586 |
| 587 void exitSwitch() { | 587 void exitSwitch() { |
| 588 nestingLevel--; | 588 nestingLevel--; |
| 589 breakTargetStack = breakTargetStack.tail; | 589 breakTargetStack = breakTargetStack.tail; |
| 590 labels = labels.outer; | 590 labels = labels.outer; |
| 591 } | 591 } |
| 592 } | 592 } |
| 593 | 593 |
| 594 class TypeResolver { | |
| 595 final Compiler compiler; | |
| 596 TypeResolver(this.compiler); | |
| 597 | |
| 598 Element resolveTypeName(Scope context, TypeAnnotation node) { | |
| 599 Identifier typeName = node.typeName.asIdentifier(); | |
| 600 Send send = node.typeName.asSend(); | |
| 601 if (send !== null) { | |
| 602 typeName = send.selector; | |
| 603 } | |
| 604 if (typeName.source == Types.VOID) { | |
| 605 return compiler.types.voidType.element; | |
| 606 } else if (send !== null) { | |
| 607 Element e = context.lookup(send.receiver.asIdentifier().source); | |
| 608 if (e !== null && e.kind === ElementKind.PREFIX) { | |
| 609 // The receiver is a prefix. Lookup in the imported members. | |
| 610 PrefixElement prefix = e; | |
| 611 return prefix.lookupLocalMember(typeName.source); | |
| 612 } else if (e !== null && e.kind === ElementKind.CLASS) { | |
| 613 // The receiver is the class part of a named constructor. | |
| 614 return e; | |
| 615 } else { | |
| 616 return null; | |
| 617 } | |
| 618 } else { | |
| 619 return context.lookup(typeName.source); | |
| 620 } | |
| 621 } | |
| 622 | |
| 623 Type resolveTypeAnnotation(TypeAnnotation node, | |
| 624 [Scope inContext, ClassElement inClass, | |
| 625 onFailure(Node, MessageKind, [List arguments]), | |
| 626 whenResolved(Node, Type)]) { | |
| 627 if (onFailure === null) { | |
| 628 onFailure = (n, k, [arguments]) => {}; | |
|
ngeoffray
2012/06/06 11:12:26
Returns a map? :-)
karlklose
2012/06/06 11:43:37
Done.
| |
| 629 } | |
| 630 if (whenResolved === null) { | |
| 631 whenResolved = (n, t) => {}; | |
|
ngeoffray
2012/06/06 11:12:26
ditto
karlklose
2012/06/06 11:43:37
Done.
| |
| 632 } | |
| 633 if (inClass !== null) { | |
| 634 inContext = new ClassScope(inClass, inClass.getLibrary()); | |
| 635 } | |
| 636 if (inContext === null) { | |
| 637 compiler.internalError('resolveTypeAnnotation: no scope specified'); | |
| 638 } | |
| 639 return resolveTypeAnnotationInContext(inContext, node, onFailure, | |
| 640 whenResolved); | |
| 641 } | |
| 642 | |
| 643 Type resolveTypeAnnotationInContext(Scope context, TypeAnnotation node, | |
| 644 onFailure, whenResolved) { | |
| 645 Element element = resolveTypeName(context, node); | |
| 646 Type type; | |
| 647 if (element === null) { | |
| 648 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); | |
| 649 } else if (!element.impliesType()) { | |
| 650 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); | |
| 651 } else { | |
| 652 if (element === compiler.types.voidType.element || | |
| 653 element === compiler.types.dynamicType.element) { | |
| 654 type = element.computeType(compiler); | |
| 655 } else if (element.isClass()) { | |
| 656 ClassElement cls = element; | |
| 657 if (!cls.isResolved) compiler.resolveClass(cls); | |
| 658 LinkBuilder<Type> arguments = new LinkBuilder<Type>(); | |
| 659 if (node.typeArguments !== null) { | |
| 660 int index = 0; | |
| 661 for (Link<Node> typeArguments = node.typeArguments.nodes; | |
| 662 !typeArguments.isEmpty(); | |
| 663 typeArguments = typeArguments.tail) { | |
| 664 if (++index > cls.typeParameters.length) { | |
| 665 onFailure(typeArguments.head, | |
| 666 MessageKind.ADDITIONAL_TYPE_ARGUMENT); | |
| 667 } | |
| 668 Type argType = resolveTypeAnnotationInContext(context, | |
| 669 typeArguments.head, | |
| 670 onFailure, | |
| 671 whenResolved); | |
| 672 arguments.addLast(argType); | |
| 673 } | |
| 674 if (index < cls.typeParameters.length) { | |
| 675 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | |
| 676 } | |
| 677 } | |
| 678 if (cls.typeParameters.length == 0) { | |
| 679 // Return the canonical type if it has no type parameters. | |
| 680 type = cls.computeType(compiler); | |
| 681 } else { | |
| 682 type = new InterfaceType(cls, arguments.toLink()); | |
| 683 } | |
| 684 } else if (element.isTypedef()) { | |
| 685 type = element.computeType(compiler); | |
| 686 } else if (element.isTypeVariable()) { | |
| 687 type = element.computeType(compiler); | |
| 688 } else { | |
| 689 compiler.cancel("unexpected element kind ${element.kind}", | |
| 690 node: node); | |
| 691 } | |
| 692 } | |
| 693 whenResolved(node, type); | |
| 694 return type; | |
| 695 } | |
| 696 } | |
| 697 | |
| 594 class ResolverVisitor extends CommonResolverVisitor<Element> { | 698 class ResolverVisitor extends CommonResolverVisitor<Element> { |
| 595 final TreeElementMapping mapping; | 699 final TreeElementMapping mapping; |
| 596 final Element enclosingElement; | 700 final Element enclosingElement; |
| 701 final TypeResolver typeResolver; | |
| 597 bool inInstanceContext; | 702 bool inInstanceContext; |
| 598 Scope context; | 703 Scope context; |
| 599 ClassElement currentClass; | 704 ClassElement currentClass; |
| 600 bool typeRequired = false; | 705 bool typeRequired = false; |
| 601 StatementScope statementScope; | 706 StatementScope statementScope; |
| 602 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; | 707 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; |
| 603 | 708 |
| 604 ResolverVisitor(Compiler compiler, Element element) | 709 ResolverVisitor(Compiler compiler, Element element) |
| 605 : this.mapping = new TreeElementMapping(), | 710 : this.mapping = new TreeElementMapping(), |
| 606 this.enclosingElement = element, | 711 this.enclosingElement = element, |
| 607 inInstanceContext = element.isInstanceMember() | 712 inInstanceContext = element.isInstanceMember() |
| 608 || element.isGenerativeConstructor(), | 713 || element.isGenerativeConstructor(), |
| 609 this.currentClass = element.isMember() ? element.enclosingElement : null, | 714 this.currentClass = element.isMember() ? element.enclosingElement : null, |
| 610 this.statementScope = new StatementScope(), | 715 this.statementScope = new StatementScope(), |
| 716 typeResolver = new TypeResolver(compiler), | |
| 611 super(compiler) { | 717 super(compiler) { |
| 612 LibraryElement library = element.getLibrary(); | 718 LibraryElement library = element.getLibrary(); |
| 613 element = element.getEnclosingMember(); | 719 element = element.getEnclosingMember(); |
| 614 if (element !== null) { | 720 if (element !== null) { |
| 615 context = new ClassScope(element.enclosingElement, library); | 721 context = new ClassScope(element.enclosingElement, library); |
| 616 } else { | 722 } else { |
| 617 this.context = new TopScope(library); | 723 this.context = new TopScope(library); |
| 618 } | 724 } |
| 619 } | 725 } |
| 620 | 726 |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1089 } | 1195 } |
| 1090 | 1196 |
| 1091 Type resolveTypeRequired(TypeAnnotation node) { | 1197 Type resolveTypeRequired(TypeAnnotation node) { |
| 1092 bool old = typeRequired; | 1198 bool old = typeRequired; |
| 1093 typeRequired = true; | 1199 typeRequired = true; |
| 1094 Type result = resolveTypeAnnotation(node); | 1200 Type result = resolveTypeAnnotation(node); |
| 1095 typeRequired = old; | 1201 typeRequired = old; |
| 1096 return result; | 1202 return result; |
| 1097 } | 1203 } |
| 1098 | 1204 |
| 1099 Element resolveTypeName(TypeAnnotation node) { | |
| 1100 Identifier typeName = node.typeName.asIdentifier(); | |
| 1101 Send send = node.typeName.asSend(); | |
| 1102 if (send !== null) { | |
| 1103 typeName = send.selector; | |
| 1104 } | |
| 1105 if (typeName.source == Types.VOID) { | |
| 1106 return compiler.types.voidType.element; | |
| 1107 } else if (send !== null) { | |
| 1108 Element e = context.lookup(send.receiver.asIdentifier().source); | |
| 1109 if (e !== null && e.kind === ElementKind.PREFIX) { | |
| 1110 // The receiver is a prefix. Lookup in the imported members. | |
| 1111 PrefixElement prefix = e; | |
| 1112 return prefix.lookupLocalMember(typeName.source); | |
| 1113 } else if (e !== null && e.kind === ElementKind.CLASS) { | |
| 1114 // The receiver is the class part of a named constructor. | |
| 1115 return e; | |
| 1116 } else { | |
| 1117 return null; | |
| 1118 } | |
| 1119 } else { | |
| 1120 return context.lookup(typeName.source); | |
| 1121 } | |
| 1122 } | |
| 1123 | |
| 1124 Type resolveTypeAnnotation(TypeAnnotation node) { | 1205 Type resolveTypeAnnotation(TypeAnnotation node) { |
| 1125 Function report = typeRequired ? error : warning; | 1206 Function report = typeRequired ? error : warning; |
| 1126 Element element = resolveTypeName(node); | 1207 return typeResolver.resolveTypeAnnotation(node, inContext: context, |
| 1127 Type type; | 1208 onFailure: report, |
| 1128 if (element === null) { | 1209 whenResolved: useType); |
| 1129 report(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); | |
| 1130 } else if (!element.impliesType()) { | |
| 1131 report(node, MessageKind.NOT_A_TYPE, [node.typeName]); | |
| 1132 } else { | |
| 1133 if (element === compiler.types.voidType.element || | |
| 1134 element === compiler.types.dynamicType.element) { | |
| 1135 type = element.computeType(compiler); | |
| 1136 } else if (element.isClass()) { | |
| 1137 ClassElement cls = element; | |
| 1138 if (!cls.isResolved) compiler.resolveClass(cls); | |
| 1139 LinkBuilder<Type> arguments = new LinkBuilder<Type>(); | |
| 1140 if (node.typeArguments !== null) { | |
| 1141 int index = 0; | |
| 1142 for (Link<Node> typeArguments = node.typeArguments.nodes; | |
| 1143 !typeArguments.isEmpty(); | |
| 1144 typeArguments = typeArguments.tail) { | |
| 1145 if (++index > cls.typeParameters.length) { | |
| 1146 report(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | |
| 1147 } | |
| 1148 arguments.addLast(resolveTypeAnnotation(typeArguments.head)); | |
| 1149 } | |
| 1150 if (index < cls.typeParameters.length) { | |
| 1151 report(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | |
| 1152 } | |
| 1153 } | |
| 1154 if (cls.typeParameters.length == 0) { | |
| 1155 // Return the canonical type if it has no type parameters. | |
| 1156 type = cls.computeType(compiler); | |
| 1157 } else { | |
| 1158 type = new InterfaceType(cls, arguments.toLink()); | |
| 1159 } | |
| 1160 } else if (element.isTypedef()) { | |
| 1161 type = element.computeType(compiler); | |
| 1162 } else if (element.isTypeVariable()) { | |
| 1163 type = element.computeType(compiler); | |
| 1164 } else { | |
| 1165 compiler.cancel("unexpected element kind ${element.kind}", | |
| 1166 node: node); | |
| 1167 } | |
| 1168 } | |
| 1169 return useType(node, type); | |
| 1170 } | 1210 } |
| 1171 | 1211 |
| 1172 visitModifiers(Modifiers node) { | 1212 visitModifiers(Modifiers node) { |
| 1173 // TODO(ngeoffray): Implement this. | 1213 // TODO(ngeoffray): Implement this. |
| 1174 unimplemented(node, 'modifiers'); | 1214 unimplemented(node, 'modifiers'); |
| 1175 } | 1215 } |
| 1176 | 1216 |
| 1177 visitLiteralList(LiteralList node) { | 1217 visitLiteralList(LiteralList node) { |
| 1178 visit(node.elements); | 1218 visit(node.elements); |
| 1179 } | 1219 } |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1964 | 2004 |
| 1965 TopScope(LibraryElement library) : super(null, library); | 2005 TopScope(LibraryElement library) : super(null, library); |
| 1966 Element lookup(SourceString name) { | 2006 Element lookup(SourceString name) { |
| 1967 return library.find(name); | 2007 return library.find(name); |
| 1968 } | 2008 } |
| 1969 | 2009 |
| 1970 Element add(Element newElement) { | 2010 Element add(Element newElement) { |
| 1971 throw "Cannot add an element in the top scope"; | 2011 throw "Cannot add an element in the top scope"; |
| 1972 } | 2012 } |
| 1973 } | 2013 } |
| OLD | NEW |