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 } | 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 |