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

Side by Side Diff: dart/frog/leg/resolver.dart

Issue 9634008: Introduce element categories and move resolver towards being more compositional. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 9 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 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 } 8 }
9 9
10 class TreeElementMapping implements TreeElements { 10 class TreeElementMapping implements TreeElements {
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 526
527 527
528 class ResolverVisitor extends CommonResolverVisitor<Element> { 528 class ResolverVisitor extends CommonResolverVisitor<Element> {
529 final TreeElementMapping mapping; 529 final TreeElementMapping mapping;
530 final Element enclosingElement; 530 final Element enclosingElement;
531 bool inInstanceContext; 531 bool inInstanceContext;
532 Scope context; 532 Scope context;
533 ClassElement currentClass; 533 ClassElement currentClass;
534 bool typeRequired = false; 534 bool typeRequired = false;
535 StatementScope statementScope; 535 StatementScope statementScope;
536 int allowedCategory = ElementCategory.SLOT | ElementCategory.FUNCTION;
536 537
537 ResolverVisitor(Compiler compiler, Element element) 538 ResolverVisitor(Compiler compiler, Element element)
538 : this.mapping = new TreeElementMapping(), 539 : this.mapping = new TreeElementMapping(),
539 this.enclosingElement = element, 540 this.enclosingElement = element,
540 inInstanceContext = element.isInstanceMember() 541 inInstanceContext = element.isInstanceMember()
541 || element.isGenerativeConstructor(), 542 || element.isGenerativeConstructor(),
542 this.context = element.isMember() 543 this.context = element.isMember()
543 ? new ClassScope(element.enclosingElement, element.getLibrary()) 544 ? new ClassScope(element.enclosingElement, element.getLibrary())
544 : new TopScope(element.getLibrary()), 545 : new TopScope(element.getLibrary()),
545 this.currentClass = element.isMember() ? element.enclosingElement : null, 546 this.currentClass = element.isMember() ? element.enclosingElement : null,
(...skipping 21 matching lines...) Expand all
567 bool wasInstanceContext = inInstanceContext; 568 bool wasInstanceContext = inInstanceContext;
568 inInstanceContext = false; 569 inInstanceContext = false;
569 action(); 570 action();
570 inInstanceContext = wasInstanceContext; 571 inInstanceContext = wasInstanceContext;
571 } 572 }
572 573
573 visitInStaticContext(Node node) { 574 visitInStaticContext(Node node) {
574 inStaticContext(() => visit(node)); 575 inStaticContext(() => visit(node));
575 } 576 }
576 577
577 visitIdentifier(Identifier node) { 578 Element visitIdentifier(Identifier node) {
578 if (node.isThis()) { 579 if (node.isThis()) {
579 if (!inInstanceContext) { 580 if (!inInstanceContext) {
580 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); 581 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
581 } 582 }
582 return null; 583 return null;
583 } else if (node.isSuper()) { 584 } else if (node.isSuper()) {
584 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); 585 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC);
586 if ((ElementCategory.SUPER & allowedCategory) == 0) {
587 error(node, MessageKind.INVALID_USE_OF_SUPER);
588 }
585 return null; 589 return null;
586 } else { 590 } else {
587 Element element = lookup(node, node.source); 591 Element element = lookup(node, node.source);
588 if (element == null) { 592 if (element === null) {
589 error(node, MessageKind.CANNOT_RESOLVE, [node]); 593 if (!inInstanceContext) error(node, MessageKind.CANNOT_RESOLVE, [node]);
594 } else {
595 if ((element.kind.category & allowedCategory) == 0) {
596 // TODO(ahe): Improve error message. Need UX input.
597 error(node, MessageKind.GENERIC, ["is not an expression $element"]);
598 }
590 } 599 }
591 return useElement(node, element); 600 return useElement(node, element);
592 } 601 }
593 } 602 }
594 603
595 visitTypeAnnotation(TypeAnnotation node) { 604 visitTypeAnnotation(TypeAnnotation node) {
596 SourceString className; 605 SourceString className;
597 if (node.typeName.asSend() !== null) { 606 if (node.typeName.asSend() !== null) {
598 // In new and const expressions, the type name can be a Send to 607 // In new and const expressions, the type name can be a Send to
599 // denote named constructors or library prefixes. 608 // denote named constructors or library prefixes.
600 Send send = node.typeName.asSend(); 609 Send send = node.typeName.asSend();
601 className = send.receiver.asIdentifier().source; 610 className = send.receiver.asIdentifier().source;
602 } else { 611 } else {
603 className = node.typeName.asIdentifier().source; 612 className = node.typeName.asIdentifier().source;
604 } 613 }
605 if (className == const SourceString('var')) return null; 614 if (className == const SourceString('var')) return null;
606 if (className == const SourceString('void')) return null; 615 if (className == const SourceString('void')) return null;
607 Element element = context.lookup(className); 616 Element element = context.lookup(className);
608 if (element === null) { 617 if (element === null) {
609 if (typeRequired) { 618 if (typeRequired) {
610 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); 619 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]);
611 } else { 620 } else {
612 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); 621 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]);
613 } 622 }
614 } else if (!element.isClassOrInterfaceOrTypedef()) { 623 } else if (!element.impliesType()) {
615 if (typeRequired) { 624 if (typeRequired) {
616 error(node, MessageKind.NOT_A_TYPE, [className]); 625 error(node, MessageKind.NOT_A_TYPE, [className]);
617 } else { 626 } else {
618 warning(node, MessageKind.NOT_A_TYPE, [className]); 627 warning(node, MessageKind.NOT_A_TYPE, [className]);
619 } 628 }
620 } else { 629 } else {
621 if (element.isClass()) { 630 if (element.isClass()) {
622 // TODO(ngeoffray): Should we also resolve typedef? 631 // TODO(ngeoffray): Should we also resolve typedef?
623 ClassElement cls = element; 632 ClassElement cls = element;
624 compiler.resolver.toResolve.add(element); 633 compiler.resolver.toResolve.add(element);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 setupFunction(node, enclosingElement); 744 setupFunction(node, enclosingElement);
736 defineElement(node, enclosingElement, doAddToScope: node.name !== null); 745 defineElement(node, enclosingElement, doAddToScope: node.name !== null);
737 746
738 // Run the body in a fresh statement scope. 747 // Run the body in a fresh statement scope.
739 StatementScope oldScope = statementScope; 748 StatementScope oldScope = statementScope;
740 statementScope = new StatementScope(); 749 statementScope = new StatementScope();
741 visit(node.body); 750 visit(node.body);
742 statementScope = oldScope; 751 statementScope = oldScope;
743 752
744 context = context.parent; 753 context = context.parent;
745 return enclosingElement;
746 } 754 }
747 755
748 visitIf(If node) { 756 visitIf(If node) {
749 visit(node.condition); 757 visit(node.condition);
750 visit(node.thenPart); 758 visit(node.thenPart);
751 visit(node.elsePart); 759 visit(node.elsePart);
752 } 760 }
753 761
754 static bool isLogicalOperator(Identifier op) { 762 static bool isLogicalOperator(Identifier op) {
755 String str = op.source.stringValue; 763 String str = op.source.stringValue;
756 return (str === '&&' || str == '||' || str == '!'); 764 return (str === '&&' || str == '||' || str == '!');
757 } 765 }
758 766
759 Element resolveSend(Send node) { 767 Element resolveSend(Send node) {
768 if (node.receiver === null || node.selector.isThis()) {
769 return node.selector.accept(this);
770 }
771 var oldCategory = allowedCategory;
772 allowedCategory |=
773 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER;
760 Element resolvedReceiver = visit(node.receiver); 774 Element resolvedReceiver = visit(node.receiver);
775 allowedCategory = oldCategory;
761 776
762 Element target = null; 777 Element target;
763 if (node.selector.asIdentifier() === null) { 778 SourceString name = node.selector.asIdentifier().source;
764 // We are calling a closure returned from an expression. 779 if (node.isSuperCall) {
765 assert(node.selector.asExpression() !== null); 780 if (isUserDefinableOperator(name.stringValue)) {
766 assert(resolvedReceiver === null); 781 name = Elements.constructOperatorName(const SourceString('operator'),
767 visit(node.selector); 782 name);
768 } else { 783 }
769 SourceString name = node.selector.asIdentifier().source; 784 if (currentClass === null || !inInstanceContext) {
ngeoffray 2012/03/08 14:00:45 Shouldn't that just be '!inInstanceContext' ?
ahe 2012/03/08 18:13:40 Done.
770 if (node.receiver === null) { 785 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]);
771 target = lookup(node, name); 786 }
772 if (target === null && !inInstanceContext) { 787 target = currentClass.lookupSuperMember(name);
773 error(node, MessageKind.CANNOT_RESOLVE, [name]); 788 if (target === null) {
774 } 789 error(node.selector, MessageKind.METHOD_NOT_FOUND,
775 } else if (node.isSuperCall) { 790 [currentClass.superclass.name, name]);
776 if (currentClass !== null) { 791 }
777 ClassElement superElement = currentClass.superclass; 792 } else if (resolvedReceiver === null) {
778 if (superElement !== null) { 793 return null;
779 // TODO(ngeoffray): The lookup should continue on super 794 } else if (resolvedReceiver.kind === ElementKind.CLASS) {
ngeoffray 2012/03/08 14:00:45 You can now change it to resolvedReceiver.isClass(
ahe 2012/03/08 18:13:40 I'm not sure that I like that.
780 // classes. 795 ClassElement receiverClass = resolvedReceiver;
781 target = superElement.lookupLocalMember(name); 796 target = receiverClass.resolve(compiler).lookupLocalMember(name);
782 } 797 if (target === null) {
783 if (target === null) { 798 error(node, MessageKind.METHOD_NOT_FOUND, [receiverClass.name, name]);
784 error(node, 799 } else if (target.isInstanceMember()) {
785 MessageKind.METHOD_NOT_FOUND, 800 error(node, MessageKind.MEMBER_NOT_STATIC,
786 [superElement.name, name]); 801 [receiverClass.name, name]);
karlklose 2012/03/08 14:01:45 Would this fit into one line?
ahe 2012/03/08 18:13:40 Done.
787 } 802 }
788 } 803 } else if (resolvedReceiver.kind === ElementKind.PREFIX) {
789 } else if (resolvedReceiver === null) { 804 PrefixElement prefix = resolvedReceiver;
790 return null; 805 target = prefix.lookupLocalMember(name);
791 } else if (resolvedReceiver.kind === ElementKind.CLASS) { 806 if (target == null) {
792 ClassElement receiverClass = resolvedReceiver; 807 error(node, MessageKind.NO_SUCH_LIBRARY_MEMBER, [prefix.name, name]);
793 target = receiverClass.resolve(compiler).lookupLocalMember(name);
794 if (target === null) {
795 error(node, MessageKind.METHOD_NOT_FOUND, [receiverClass.name, name]);
796 } else if (target.isInstanceMember()) {
797 error(node, MessageKind.MEMBER_NOT_STATIC,
798 [receiverClass.name, name]);
799 }
800 } else if (resolvedReceiver.kind === ElementKind.PREFIX) {
801 PrefixElement prefix = resolvedReceiver;
802 target = prefix.library.lookupLocalMember(name);
803 if (target == null) {
804 error(node, MessageKind.NO_SUCH_LIBRARY_MEMBER,
805 [resolvedReceiver.name, name]);
806 }
807 } 808 }
808 } 809 }
809 return target; 810 return target;
810 } 811 }
811 812
812 resolveTypeTest(Node argument) { 813 resolveTypeTest(Node argument) {
813 TypeAnnotation node = argument.asTypeAnnotation(); 814 TypeAnnotation node = argument.asTypeAnnotation();
814 if (node == null) { 815 if (node == null) {
815 node = argument.asSend().receiver; 816 node = argument.asSend().receiver;
816 } 817 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 mapping.setSelector(node, Selector.GETTER); 858 mapping.setSelector(node, Selector.GETTER);
858 } else { 859 } else {
859 handleArguments(node); 860 handleArguments(node);
860 } 861 }
861 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { 862 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
862 AbstractFieldElement field = target; 863 AbstractFieldElement field = target;
863 target = field.getter; 864 target = field.getter;
864 } 865 }
865 // TODO(ngeoffray): Warn if target is null and the send is 866 // TODO(ngeoffray): Warn if target is null and the send is
866 // unqualified. 867 // unqualified.
867 return useElement(node, target); 868 useElement(node, target);
869 if (node.isPropertyAccess) return target;
868 } 870 }
869 871
870 visitSendSet(SendSet node) { 872 visitSendSet(SendSet node) {
871 Element target = resolveSend(node); 873 Element target = resolveSend(node);
872 Element setter = null; 874 Element setter = null;
873 Element getter = null; 875 Element getter = null;
874 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { 876 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) {
875 AbstractFieldElement field = target; 877 AbstractFieldElement field = target;
876 setter = field.setter; 878 setter = field.setter;
877 getter = field.getter; 879 getter = field.getter;
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 } 1194 }
1193 for (Link<Node> link = node.interfaces.nodes; 1195 for (Link<Node> link = node.interfaces.nodes;
1194 !link.isEmpty(); 1196 !link.isEmpty();
1195 link = link.tail) { 1197 link = link.tail) {
1196 element.interfaces = element.interfaces.prepend(visit(link.head)); 1198 element.interfaces = element.interfaces.prepend(visit(link.head));
1197 } 1199 }
1198 return element.computeType(compiler); 1200 return element.computeType(compiler);
1199 } 1201 }
1200 1202
1201 Type visitTypeAnnotation(TypeAnnotation node) { 1203 Type visitTypeAnnotation(TypeAnnotation node) {
1202 Identifier name = node.typeName.asIdentifier(); 1204 return visit(node.typeName);
1203 if (name === null) {
1204 unimplemented(node.typeName, "prefixes");
1205 }
1206 return visit(name);
1207 } 1205 }
1208 1206
1209 Type visitIdentifier(Identifier node) { 1207 Type visitIdentifier(Identifier node) {
1210 Element element = context.lookup(node.source); 1208 Element element = context.lookup(node.source);
1211 if (element === null) { 1209 if (element === null) {
1212 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); 1210 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
1213 } else if (!element.isClassOrInterfaceOrTypedef()) { 1211 } else if (!element.impliesType()) {
1214 error(node, MessageKind.NOT_A_TYPE, [node]); 1212 error(node, MessageKind.NOT_A_TYPE, [node]);
1215 } else { 1213 } else {
1216 if (element.isClass()) { 1214 if (element.isClass()) {
1217 compiler.resolver.toResolve.add(element); 1215 compiler.resolver.toResolve.add(element);
1218 } 1216 }
1219 // TODO(ngeoffray): Use type variables. 1217 // TODO(ngeoffray): Use type variables.
1220 return element.computeType(compiler); 1218 return element.computeType(compiler);
1221 } 1219 }
1222 return null; 1220 return null;
1223 } 1221 }
1222
1223 Type visitSend(Send node) {
1224 Identifier prefix = node.receiver.asIdentifier();
1225 if (prefix === null) {
1226 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
1227 return null;
1228 }
1229 Element element = context.lookup(prefix.source);
1230 if (element.kind === ElementKind.PREFIX) {
1231 var e = element.library.lookupLocalMember(node.selector.source);
1232 if (e === null) {
1233 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
1234 return null;
1235 }
1236 return e.computeType(compiler);
1237 }
ngeoffray 2012/03/08 14:00:45 Why don't you warn here that you resolve to someth
ahe 2012/03/08 18:13:40 Done.
1238 return null;
1239 }
1224 } 1240 }
1225 1241
1226 class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> { 1242 class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
1227 VariableDefinitions definitions; 1243 VariableDefinitions definitions;
1228 ResolverVisitor resolver; 1244 ResolverVisitor resolver;
1229 ElementKind kind; 1245 ElementKind kind;
1230 VariableListElement variables; 1246 VariableListElement variables;
1231 1247
1232 VariableDefinitionsVisitor(Compiler compiler, 1248 VariableDefinitionsVisitor(Compiler compiler,
1233 this.definitions, this.resolver, this.kind) 1249 this.definitions, this.resolver, this.kind)
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 class TopScope extends Scope { 1560 class TopScope extends Scope {
1545 LibraryElement get library() => element; 1561 LibraryElement get library() => element;
1546 1562
1547 TopScope(LibraryElement library) : super(null, library); 1563 TopScope(LibraryElement library) : super(null, library);
1548 Element lookup(SourceString name) => library.find(name); 1564 Element lookup(SourceString name) => library.find(name);
1549 1565
1550 Element add(Element element) { 1566 Element add(Element element) {
1551 throw "Cannot add an element in the top scope"; 1567 throw "Cannot add an element in the top scope";
1552 } 1568 }
1553 } 1569 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698