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 part of resolution; | 5 part of resolution; |
6 | 6 |
7 abstract class TreeElements { | 7 abstract class TreeElements { |
8 Element operator[](Node node); | 8 Element operator[](Node node); |
9 Selector getSelector(Send send); | 9 Selector getSelector(Send send); |
10 DartType getType(Node node); | 10 DartType getType(Node node); |
(...skipping 1717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1728 // with the same arguments. | 1728 // with the same arguments. |
1729 Selector call = new Selector.callClosureFrom(selector); | 1729 Selector call = new Selector.callClosureFrom(selector); |
1730 world.registerDynamicInvocation(call.name, call); | 1730 world.registerDynamicInvocation(call.name, call); |
1731 } else if (target.impliesType()) { | 1731 } else if (target.impliesType()) { |
1732 // We call 'call()' on a Type instance returned from the reference to a | 1732 // We call 'call()' on a Type instance returned from the reference to a |
1733 // class or typedef literal. We do not need to register this call as a | 1733 // class or typedef literal. We do not need to register this call as a |
1734 // dynamic invocation, because we statically know what the target is. | 1734 // dynamic invocation, because we statically know what the target is. |
1735 } else if (!selector.applies(target, compiler)) { | 1735 } else if (!selector.applies(target, compiler)) { |
1736 warnArgumentMismatch(node, target); | 1736 warnArgumentMismatch(node, target); |
1737 } | 1737 } |
1738 | |
1739 if (selector.name == const SourceString('JS')) { | |
ngeoffray
2012/11/08 08:18:01
Note that the equality check must be done on the e
sra1
2012/11/15 00:09:10
Which element?
| |
1740 var argNodes = node.arguments; | |
1741 if (!argNodes.isEmpty) { | |
1742 resolveJsTypeParameter(argNodes.head, node); | |
1743 } | |
1744 } | |
1738 } | 1745 } |
1739 | 1746 |
1740 // TODO(ngeoffray): Warn if target is null and the send is | 1747 // TODO(ngeoffray): Warn if target is null and the send is |
1741 // unqualified. | 1748 // unqualified. |
1742 useElement(node, target); | 1749 useElement(node, target); |
1743 registerSend(selector, target); | 1750 registerSend(selector, target); |
1744 return node.isPropertyAccess ? target : null; | 1751 return node.isPropertyAccess ? target : null; |
1745 } | 1752 } |
1746 | 1753 |
1747 void warnArgumentMismatch(Send node, Element target) { | 1754 void warnArgumentMismatch(Send node, Element target) { |
1748 // TODO(karlklose): we can be more precise about the reason of the | 1755 // TODO(karlklose): we can be more precise about the reason of the |
1749 // mismatch. | 1756 // mismatch. |
1750 warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS, | 1757 warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS, |
1751 [target.name]); | 1758 [target.name]); |
1752 } | 1759 } |
1753 | 1760 |
1761 void resolveJsTypeParameter(Node node, Node expression) { | |
ngeoffray
2012/11/08 08:18:01
I would move this method to the native enqueuer.
sra1
2012/11/12 20:28:03
Done. I've moved everything except the lookup of
| |
1762 // Resolve 'JS' type; mark as an instantiated native type. | |
1763 // | |
1764 // The type is currently a string. We make an attempt at parsing the | |
1765 // string. | |
1766 // | |
1767 // We will need the JS form to support union types and possible some other | |
1768 // hints. We could get the parser to resolve complex types like List<int> | |
1769 // by using expressions that name classes, and a union by using a list | |
1770 // literal. | |
1771 // | |
1772 // JS(int, '#.foo', this); | |
1773 // | |
1774 // JS([List<int>, bool], '...'); // Union of types. | |
1775 // | |
1776 // JS([], '1'); // Type not expressable but harmless. | |
1777 // | |
1778 // JS(['existing', Object], ...); // Object, but not a fresh native one. | |
1779 | |
1780 LiteralString typeStringLiteral = node.asLiteralString(); | |
1781 if (typeStringLiteral != null) { | |
1782 String typeString = typeStringLiteral.dartString.slowToString(); | |
1783 if (! const {'': 1, 'var':1, 'void':1, | |
1784 //'bool':1, 'num':1, 'int':1, 'String':1 | |
1785 }.containsKey(typeString)) { | |
1786 Element element = resolveJSTypeString(typeString, node); | |
1787 if (element != null) { | |
1788 element.ensureResolved(compiler); | |
1789 DartType type = element.computeType(compiler); | |
1790 world.nativeEnqueuer.registerJSDartType(type, expression); | |
ngeoffray
2012/11/08 08:18:01
Could this just be (native)enqueuer.registerInstan
sra1
2012/11/12 20:28:03
No, the matching is much more complex (subtypes, a
| |
1791 } | |
1792 } | |
1793 // Is there some way to decorate `node` with the type? With a union? | |
1794 } | |
1795 } | |
1796 | |
1797 ClassElement resolveJSTypeString(String typeString, Node node) { | |
1798 String typeName; | |
1799 if (typeString.startsWith('new:')) { | |
1800 typeName = typeString.substring(4); | |
1801 } else { | |
1802 typeName = typeString; | |
1803 } | |
1804 Element element = scope.lookup(new SourceString(typeName)); | |
1805 if (element == null) { | |
1806 if (typeName == 'dynamic') return compiler.dynamicClass; | |
1807 int index = typeName.indexOf('<'); | |
1808 if (index > 1) { | |
1809 element = scope.lookup(new SourceString(typeName.substring(0, index))); | |
1810 } | |
1811 if (element == null) { | |
1812 compiler.cancel( | |
1813 "Type of JS expression '$typeName' not found", | |
1814 node: node); | |
1815 return; | |
1816 } | |
1817 } | |
1818 if (element is! ClassElement) { | |
1819 compiler.cancel( | |
1820 "Type of JS expression '$typeName' not a class", | |
1821 node: node); | |
1822 } else { | |
1823 return element; | |
1824 } | |
1825 } | |
1826 | |
1754 visitSendSet(SendSet node) { | 1827 visitSendSet(SendSet node) { |
1755 Element target = resolveSend(node); | 1828 Element target = resolveSend(node); |
1756 Element setter = target; | 1829 Element setter = target; |
1757 Element getter = target; | 1830 Element getter = target; |
1758 SourceString operatorName = node.assignmentOperator.source; | 1831 SourceString operatorName = node.assignmentOperator.source; |
1759 String source = operatorName.stringValue; | 1832 String source = operatorName.stringValue; |
1760 bool isComplex = !identical(source, '='); | 1833 bool isComplex = !identical(source, '='); |
1761 if (!Elements.isUnresolved(target) | 1834 if (!Elements.isUnresolved(target) |
1762 && target.kind == ElementKind.ABSTRACT_FIELD) { | 1835 && target.kind == ElementKind.ABSTRACT_FIELD) { |
1763 AbstractFieldElement field = target; | 1836 AbstractFieldElement field = target; |
(...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3070 return e; | 3143 return e; |
3071 } | 3144 } |
3072 | 3145 |
3073 /// Assumed to be called by [resolveRedirectingFactory]. | 3146 /// Assumed to be called by [resolveRedirectingFactory]. |
3074 Element visitReturn(Return node) { | 3147 Element visitReturn(Return node) { |
3075 Node expression = node.expression; | 3148 Node expression = node.expression; |
3076 return finishConstructorReference(visit(expression), | 3149 return finishConstructorReference(visit(expression), |
3077 expression, expression); | 3150 expression, expression); |
3078 } | 3151 } |
3079 } | 3152 } |
OLD | NEW |