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