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 } | 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |