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

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

Issue 9431029: Implement interface types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add test. Created 8 years, 8 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 Type getType(TypeAnnotation annotation);
8 } 9 }
9 10
10 class TreeElementMapping implements TreeElements { 11 class TreeElementMapping implements TreeElements {
11 Map<Node, Element> map; 12 Map<Node, Element> map;
12 Map<Send, Selector> selectors; 13 Map<Send, Selector> selectors;
14 Map<TypeAnnotation, Type> types;
15
13 TreeElementMapping() 16 TreeElementMapping()
14 : map = new LinkedHashMap<Node, Element>(), 17 : map = new LinkedHashMap<Node, Element>(),
15 selectors = new LinkedHashMap<Send, Selector>(); 18 selectors = new LinkedHashMap<Send, Selector>(),
19 types = new LinkedHashMap<TypeAnnotation, Type>();
16 20
17 operator []=(Node node, Element element) => map[node] = element; 21 operator []=(Node node, Element element) => map[node] = element;
18 operator [](Node node) => map[node]; 22 operator [](Node node) => map[node];
19 void remove(Node node) { map.remove(node); } 23 void remove(Node node) { map.remove(node); }
20 24
25 void setType(TypeAnnotation annotation, Type type) {
26 types[annotation] = type;
27 }
28
29 Type getType(TypeAnnotation annotation) => types[annotation];
30
21 void setSelector(Send send, Selector selector) { 31 void setSelector(Send send, Selector selector) {
22 selectors[send] = selector; 32 selectors[send] = selector;
23 } 33 }
24 34
25 Selector getSelector(Send send) => selectors[send]; 35 Selector getSelector(Send send) => selectors[send];
26 } 36 }
27 37
28 class ResolverTask extends CompilerTask { 38 class ResolverTask extends CompilerTask {
29 Queue<ClassElement> toResolve; 39 Queue<ClassElement> toResolve;
30 40
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 } else { 593 } else {
584 if ((element.kind.category & allowedCategory) == 0) { 594 if ((element.kind.category & allowedCategory) == 0) {
585 // TODO(ahe): Improve error message. Need UX input. 595 // TODO(ahe): Improve error message. Need UX input.
586 error(node, MessageKind.GENERIC, ["is not an expression $element"]); 596 error(node, MessageKind.GENERIC, ["is not an expression $element"]);
587 } 597 }
588 } 598 }
589 return useElement(node, element); 599 return useElement(node, element);
590 } 600 }
591 } 601 }
592 602
593 visitTypeAnnotation(TypeAnnotation node) { 603 ClassElement visitTypeAnnotation(TypeAnnotation node) {
594 Send send = node.typeName.asSend(); 604 Type type = resolveTypeAnnotation(node);
595 Element element; 605 if (type !== null) return type.element;
596 if (send !== null) { 606 return null;
597 if (typeRequired) {
598 element = resolveSend(send);
599 } else {
600 // Not calling resolveSend as it will emit an error instead of
601 // a warning if the type is bogus.
602 // TODO(ahe): Change resolveSend so it can emit a warning when needed.
603 return null;
604 }
605 } else {
606 element = context.lookup(node.typeName.asIdentifier().source);
607 }
608 if (element === null) {
609 if (typeRequired) {
610 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
611 } else {
612 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
613 }
614 } else if (!element.impliesType()) {
615 if (typeRequired) {
616 error(node, MessageKind.NOT_A_TYPE, [node.typeName]);
617 } else {
618 warning(node, MessageKind.NOT_A_TYPE, [node.typeName]);
619 }
620 } else {
621 if (element.isClass()) {
622 // TODO(ngeoffray): Should we also resolve typedef?
623 ClassElement cls = element;
624 compiler.resolver.toResolve.add(element);
625 }
626 // TODO(ahe): This should be a Type.
627 useElement(node, element);
628 }
629 return element;
630 } 607 }
631 608
632 Element defineElement(Node node, Element element, 609 Element defineElement(Node node, Element element,
633 [bool doAddToScope = true]) { 610 [bool doAddToScope = true]) {
634 compiler.ensure(element !== null); 611 compiler.ensure(element !== null);
635 mapping[node] = element; 612 mapping[node] = element;
636 if (doAddToScope) { 613 if (doAddToScope) {
637 Element existing = context.add(element); 614 Element existing = context.add(element);
638 if (existing != element) { 615 if (existing != element) {
639 error(node, MessageKind.DUPLICATE_DEFINITION, [node]); 616 error(node, MessageKind.DUPLICATE_DEFINITION, [node]);
640 } 617 }
641 } 618 }
642 return element; 619 return element;
643 } 620 }
644 621
645 Element useElement(Node node, Element element) { 622 Element useElement(Node node, Element element) {
646 if (element === null) return null; 623 if (element === null) return null;
647 return mapping[node] = element; 624 return mapping[node] = element;
648 } 625 }
649 626
627 Type useType(TypeAnnotation annotation, Type type) {
628 if (type !== null) {
629 mapping.setType(annotation, type);
630 useElement(annotation, type.element);
ahe 2012/04/12 15:05:23 Long term, could we avoid setting the element?
631 }
632 return type;
633 }
634
650 void setupFunction(FunctionExpression node, FunctionElement function) { 635 void setupFunction(FunctionExpression node, FunctionElement function) {
651 context = new MethodScope(context, function); 636 context = new MethodScope(context, function);
652 // Put the parameters in scope. 637 // Put the parameters in scope.
653 FunctionParameters functionParameters = 638 FunctionParameters functionParameters =
654 function.computeParameters(compiler); 639 function.computeParameters(compiler);
655 Link<Node> parameterNodes = node.parameters.nodes; 640 Link<Node> parameterNodes = node.parameters.nodes;
656 functionParameters.forEachParameter((Element element) { 641 functionParameters.forEachParameter((Element element) {
657 if (element == functionParameters.optionalParameters.head) { 642 if (element == functionParameters.optionalParameters.head) {
658 NodeList nodes = parameterNodes.head; 643 NodeList nodes = parameterNodes.head;
659 parameterNodes = nodes.nodes; 644 parameterNodes = nodes.nodes;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { 796 } else if (resolvedReceiver.kind === ElementKind.PREFIX) {
812 PrefixElement prefix = resolvedReceiver; 797 PrefixElement prefix = resolvedReceiver;
813 target = prefix.lookupLocalMember(name); 798 target = prefix.lookupLocalMember(name);
814 if (target == null) { 799 if (target == null) {
815 error(node, MessageKind.NO_SUCH_LIBRARY_MEMBER, [prefix.name, name]); 800 error(node, MessageKind.NO_SUCH_LIBRARY_MEMBER, [prefix.name, name]);
816 } 801 }
817 } 802 }
818 return target; 803 return target;
819 } 804 }
820 805
821 resolveTypeTest(Node argument) { 806 Type resolveTypeTest(Node argument) {
822 TypeAnnotation node = argument.asTypeAnnotation(); 807 TypeAnnotation node = argument.asTypeAnnotation();
823 if (node == null) { 808 if (node == null) {
ahe 2012/04/12 15:05:23 ===
824 node = argument.asSend().receiver; 809 // node is of the form !Type.
810 node = argument.asSend().receiver.asTypeAnnotation();
811 if (node === null) compiler.cancel("malformed send");
825 } 812 }
826 resolveTypeRequired(node); 813 return resolveTypeRequired(node);
827 } 814 }
828 815
829 void handleArguments(Send node) { 816 void handleArguments(Send node) {
830 int count = 0; 817 int count = 0;
831 List<SourceString> namedArguments = <SourceString>[]; 818 List<SourceString> namedArguments = <SourceString>[];
832 bool seenNamedArgument = false; 819 bool seenNamedArgument = false;
833 for (Link<Node> link = node.argumentsNode.nodes; 820 for (Link<Node> link = node.argumentsNode.nodes;
834 !link.isEmpty(); 821 !link.isEmpty();
835 link = link.tail) { 822 link = link.tail) {
836 count++; 823 count++;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 // TODO(karlklose): handle optional arguments. 966 // TODO(karlklose): handle optional arguments.
980 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { 967 if (node.send.argumentCount() != constructor.parameterCount(compiler)) {
981 // TODO(ngeoffray): resolution error with wrong number of 968 // TODO(ngeoffray): resolution error with wrong number of
982 // parameters. We cannot do this rigth now because of the 969 // parameters. We cannot do this rigth now because of the
983 // List constructor. 970 // List constructor.
984 } 971 }
985 useElement(node.send, constructor); 972 useElement(node.send, constructor);
986 return null; 973 return null;
987 } 974 }
988 975
976 TypeAnnotation getTypeAnnotationFromSend(Send send) {
977 if (send.selector.asTypeAnnotation() !== null) {
978 return send.selector;
979 } else if (send.selector.asSend() !== null) {
980 Send selector = send.selector;
981 if (selector.receiver.asTypeAnnotation() !== null) {
982 return selector.receiver;
983 }
984 } else {
985 compiler.internalError("malformed send in new expression");
986 }
987 }
988
989 FunctionElement resolveConstructor(NewExpression node) { 989 FunctionElement resolveConstructor(NewExpression node) {
990 FunctionElement constructor = 990 FunctionElement constructor =
991 node.accept(new ConstructorResolver(compiler, this)); 991 node.accept(new ConstructorResolver(compiler, this));
992 TypeAnnotation annotation = getTypeAnnotationFromSend(node.send);
993 Type type = resolveTypeRequired(annotation);
992 if (constructor === null) { 994 if (constructor === null) {
993 Element resolved = resolveTypeRequired(node.send.selector); 995 Element resolved = (type != null) ? type.element : null;
994 if (resolved !== null && resolved.kind === ElementKind.TYPE_VARIABLE) { 996 if (resolved !== null && resolved.kind === ElementKind.TYPE_VARIABLE) {
995 error(node, WarningKind.TYPE_VARIABLE_AS_CONSTRUCTOR); 997 error(node, MessageKind.TYPE_VARIABLE_AS_CONSTRUCTOR);
996 return null; 998 return null;
997 } else { 999 } else {
998 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); 1000 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]);
1001 return null;
999 } 1002 }
1000 } 1003 }
1001 return constructor; 1004 return constructor;
1002 } 1005 }
1003 1006
1004 Element resolveTypeRequired(Node node) { 1007 Type resolveTypeRequired(TypeAnnotation node) {
1005 bool old = typeRequired; 1008 bool old = typeRequired;
1006 typeRequired = true; 1009 typeRequired = true;
1007 Element element = visit(node); 1010 Type result = resolveTypeAnnotation(node);
1008 typeRequired = old; 1011 typeRequired = old;
1009 return element; 1012 return result;
1013 }
1014
1015 Element resolveTypeName(node) {
1016 Identifier typeName = node.typeName.asIdentifier();
1017 Send send = node.typeName.asSend();
1018 if (send !== null) {
1019 typeName = send.selector;
1020 }
1021 if (typeName.source == Types.VOID) return compiler.types.voidType.element;
1022 if (typeName.source == Types.DYNAMIC ||
1023 typeName.source.stringValue == "var") {
ahe 2012/04/12 15:05:23 Is it necessary to test for "var"? Also, it should
1024 return compiler.types.dynamicType.element;
1025 }
1026 if (send !== null) {
1027 Element e = context.lookup(send.receiver.asIdentifier().source);
1028 if (e !== null && e.kind === ElementKind.PREFIX) {
1029 // The receiver is a prefix. Lookup in the imported members.
1030 PrefixElement prefix = e;
1031 return prefix.lookupLocalMember(typeName.source);
1032 } else if (e !== null && e.kind === ElementKind.CLASS) {
1033 // The receiver is the class part of a named constructor.
1034 return e;
1035 } else {
1036 error(send.receiver, MessageKind.CANNOT_RESOLVE);
ahe 2012/04/12 15:05:23 Shouldn't this be a warning if typeRequired is fal
1037 }
1038 } else {
1039 return context.lookup(typeName.source);
1040 }
1041 }
1042
1043 Type resolveTypeAnnotation(TypeAnnotation node) {
1044 Element element = resolveTypeName(node);
1045 Type type;
1046 if (element === null) {
1047 if (typeRequired) {
1048 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
1049 } else {
1050 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
1051 }
1052 } else if (!element.impliesType()) {
1053 if (typeRequired) {
1054 error(node, MessageKind.NOT_A_TYPE, [node.typeName]);
1055 } else {
1056 warning(node, MessageKind.NOT_A_TYPE, [node.typeName]);
1057 }
1058 } else {
1059 if (element == compiler.types.voidType.element) {
ahe 2012/04/12 15:05:23 ===
1060 type = compiler.types.voidType;
ahe 2012/04/12 15:05:23 Why not just: type = element.type;
1061 } else if (element == compiler.types.dynamicType.element) {
ahe 2012/04/12 15:05:23 ===
1062 type = compiler.types.dynamicType;
1063 } else if (element.isClass()) {
1064 // TODO(ngeoffray): Should we also resolve typedef?
ahe 2012/04/12 15:05:23 I think this TODO is obsolete.
1065 ClassElement cls = element;
1066 compiler.resolver.toResolve.add(cls);
1067 LinkBuilder<Type> arguments = new LinkBuilder<Type>();
1068 if (node.typeArguments !== null) {
1069 for (Link<Node> typeArguments = node.typeArguments.nodes;
1070 !typeArguments.isEmpty();
1071 typeArguments = typeArguments.tail) {
1072 arguments.addLast(resolveTypeAnnotation(typeArguments.head));
1073 }
1074 }
ahe 2012/04/12 15:05:23 I don't think you're validating that the number of
1075 type = new InterfaceType(element.name, element, arguments.toLink());
ahe 2012/04/12 15:05:23 This means you create a new object every time you
1076 } else if (element.isTypedef()) {
1077 // TODO(karlklose): implement typedefs. We return a fake type that the
1078 // code generator can use to detect typedefs in is-checks.
1079 type = new SimpleType(element.name, element);
ahe 2012/04/12 15:05:23 Why not: type = element.type;
1080 } else {
1081 type = element.computeType(compiler);
ahe 2012/04/12 15:05:23 I'm not sure about this.
1082 }
1083 }
1084 return useType(node, type);
1010 } 1085 }
1011 1086
1012 visitModifiers(Modifiers node) { 1087 visitModifiers(Modifiers node) {
1013 // TODO(ngeoffray): Implement this. 1088 // TODO(ngeoffray): Implement this.
1014 unimplemented(node, 'modifiers'); 1089 unimplemented(node, 'modifiers');
1015 } 1090 }
1016 1091
1017 visitLiteralList(LiteralList node) { 1092 visitLiteralList(LiteralList node) {
1018 visit(node.elements); 1093 visit(node.elements);
1019 } 1094 }
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 1700
1626 // TODO(ahe): This is temporary. 1701 // TODO(ahe): This is temporary.
1627 void resolveExpression(Node node) { 1702 void resolveExpression(Node node) {
1628 if (node == null) return; 1703 if (node == null) return;
1629 node.accept(new ResolverVisitor(compiler, enclosingElement)); 1704 node.accept(new ResolverVisitor(compiler, enclosingElement));
1630 } 1705 }
1631 1706
1632 // TODO(ahe): This is temporary. 1707 // TODO(ahe): This is temporary.
1633 void resolveType(Node node) { 1708 void resolveType(Node node) {
1634 if (node == null) return; 1709 if (node == null) return;
1635 node.accept(new ResolverVisitor(compiler, enclosingElement)); 1710 // Find the correct member context to perform the lookup in.
ahe 2012/04/12 15:05:23 This method was a temporary wrapper around calling
1711 Element outer = enclosingElement;
1712 Element context = outer;
1713 while (outer !== null) {
1714 if (outer.isMember()) {
1715 context = outer;
1716 break;
1717 }
1718 outer = outer.enclosingElement;
1719 }
1720 node.accept(new ResolverVisitor(compiler, context));
1636 } 1721 }
1637 1722
1638 // TODO(ahe): This is temporary. 1723 // TODO(ahe): This is temporary.
1639 ClassElement get currentClass() { 1724 ClassElement get currentClass() {
1640 return enclosingElement.isMember() 1725 return enclosingElement.isMember()
1641 ? enclosingElement.enclosingElement : null; 1726 ? enclosingElement.enclosingElement : null;
1642 } 1727 }
1643 } 1728 }
1644 1729
1645 class ConstructorResolver extends CommonResolverVisitor<Element> { 1730 class ConstructorResolver extends CommonResolverVisitor<Element> {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 1877
1793 TopScope(LibraryElement library) : super(null, library); 1878 TopScope(LibraryElement library) : super(null, library);
1794 Element lookup(SourceString name) { 1879 Element lookup(SourceString name) {
1795 return library.find(name); 1880 return library.find(name);
1796 } 1881 }
1797 1882
1798 Element add(Element element) { 1883 Element add(Element element) {
1799 throw "Cannot add an element in the top scope"; 1884 throw "Cannot add an element in the top scope";
1800 } 1885 }
1801 } 1886 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698