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 Selector getGetterSelectorInComplexSendSet(SendSet node); | |
| 11 Selector getOperatorSelectorInComplexSendSet(SendSet node); | |
| 12 Selector getIteratorSelector(ForIn node); | |
| 13 Selector getMoveNextSelector(ForIn node); | |
| 14 Selector getCurrentSelector(ForIn node); | |
| 10 DartType getType(Node node); | 15 DartType getType(Node node); |
| 11 bool isParameterChecked(Element element); | 16 bool isParameterChecked(Element element); |
| 12 Set<Node> get superUses; | 17 Set<Node> get superUses; |
| 13 } | 18 } |
| 14 | 19 |
| 15 class TreeElementMapping implements TreeElements { | 20 class TreeElementMapping implements TreeElements { |
| 16 final Element currentElement; | 21 final Element currentElement; |
| 17 final Map<Node, Selector> selectors = new LinkedHashMap<Node, Selector>(); | 22 final Map<Spannable, Selector> selectors = |
| 23 new LinkedHashMap<Spannable, Selector>(); | |
| 18 final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>(); | 24 final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>(); |
| 19 final Set<Element> checkedParameters = new Set<Element>(); | 25 final Set<Element> checkedParameters = new Set<Element>(); |
| 20 final Set<Node> superUses = new Set<Node>(); | 26 final Set<Node> superUses = new Set<Node>(); |
| 21 | 27 |
| 22 TreeElementMapping(this.currentElement); | 28 TreeElementMapping(this.currentElement); |
| 23 | 29 |
| 24 operator []=(Node node, Element element) { | 30 operator []=(Node node, Element element) { |
| 25 assert(invariant(node, () { | 31 assert(invariant(node, () { |
| 26 if (node is FunctionExpression) { | 32 if (node is FunctionExpression) { |
| 27 return !node.modifiers.isExternal(); | 33 return !node.modifiers.isExternal(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 54 void setType(Node node, DartType type) { | 60 void setType(Node node, DartType type) { |
| 55 types[node] = type; | 61 types[node] = type; |
| 56 } | 62 } |
| 57 | 63 |
| 58 DartType getType(Node node) => types[node]; | 64 DartType getType(Node node) => types[node]; |
| 59 | 65 |
| 60 void setSelector(Node node, Selector selector) { | 66 void setSelector(Node node, Selector selector) { |
| 61 selectors[node] = selector; | 67 selectors[node] = selector; |
| 62 } | 68 } |
| 63 | 69 |
| 64 Selector getSelector(Node node) => selectors[node]; | 70 Selector getSelector(Node node) { |
| 71 return selectors[node]; | |
| 72 } | |
| 73 | |
| 74 void setGetterSelectorInComplexSendSet(SendSet node, Selector selector) { | |
| 75 selectors[node.selector] = selector; | |
| 76 } | |
| 77 | |
| 78 Selector getGetterSelectorInComplexSendSet(SendSet node) { | |
| 79 return selectors[node.selector]; | |
| 80 } | |
| 81 | |
| 82 void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector) { | |
| 83 selectors[node.assignmentOperator] = selector; | |
| 84 } | |
| 85 | |
| 86 Selector getOperatorSelectorInComplexSendSet(SendSet node) { | |
| 87 return selectors[node.assignmentOperator]; | |
| 88 } | |
| 89 | |
| 90 // The following methods set selectors on the "for in" node. Since | |
| 91 // we're using three selectors, we need to use children of the node, | |
| 92 // and we arbritraly choose which ones. | |
|
kasperl
2013/02/27 10:11:28
arbitrarily
ngeoffray
2013/02/27 12:23:59
Done.
| |
| 93 | |
| 94 Selector setIteratorSelector(ForIn node, Selector selector) { | |
| 95 selectors[node] = selector; | |
| 96 } | |
| 97 | |
| 98 Selector getIteratorSelector(ForIn node) { | |
| 99 return selectors[node]; | |
| 100 } | |
| 101 | |
| 102 Selector setMoveNextSelector(ForIn node, Selector selector) { | |
| 103 selectors[node.forToken] = selector; | |
| 104 } | |
| 105 | |
| 106 Selector getMoveNextSelector(ForIn node) { | |
| 107 return selectors[node.forToken]; | |
| 108 } | |
| 109 | |
| 110 Selector setCurrentSelector(ForIn node, Selector selector) { | |
| 111 selectors[node.inToken] = selector; | |
| 112 } | |
| 113 | |
| 114 Selector getCurrentSelector(ForIn node) { | |
| 115 return selectors[node.inToken]; | |
| 116 } | |
| 65 | 117 |
| 66 bool isParameterChecked(Element element) { | 118 bool isParameterChecked(Element element) { |
| 67 return checkedParameters.contains(element); | 119 return checkedParameters.contains(element); |
| 68 } | 120 } |
| 69 } | 121 } |
| 70 | 122 |
| 71 class ResolverTask extends CompilerTask { | 123 class ResolverTask extends CompilerTask { |
| 72 ResolverTask(Compiler compiler) : super(compiler); | 124 ResolverTask(Compiler compiler) : super(compiler); |
| 73 | 125 |
| 74 String get name => 'Resolver'; | 126 String get name => 'Resolver'; |
| (...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1948 // for a real error message. | 2000 // for a real error message. |
| 1949 error(node.receiver, MessageKind.GENERIC, | 2001 error(node.receiver, MessageKind.GENERIC, |
| 1950 {'text': "Object has no superclass"}); | 2002 {'text': "Object has no superclass"}); |
| 1951 } | 2003 } |
| 1952 // TODO(johnniwinther): Ensure correct behavior if currentClass is a | 2004 // TODO(johnniwinther): Ensure correct behavior if currentClass is a |
| 1953 // patch. | 2005 // patch. |
| 1954 target = currentClass.lookupSuperMember(name); | 2006 target = currentClass.lookupSuperMember(name); |
| 1955 // [target] may be null which means invoking noSuchMethod on | 2007 // [target] may be null which means invoking noSuchMethod on |
| 1956 // super. | 2008 // super. |
| 1957 if (target == null) { | 2009 if (target == null) { |
| 2010 target = warnAndCreateErroneousElement( | |
| 2011 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, | |
| 2012 {'className': currentClass, 'memberName': name}); | |
| 2013 // We still need to register the invocation, because we might | |
| 2014 // call [:super.noSuchMethod:] that does a | |
| 2015 // [:InvocationMirror.invokeOn:]. | |
| 2016 world.registerDynamicInvocation(selector.name, selector); | |
| 1958 compiler.backend.registerSuperNoSuchMethod(); | 2017 compiler.backend.registerSuperNoSuchMethod(); |
| 1959 } | 2018 } |
| 1960 } else if (Elements.isUnresolved(resolvedReceiver)) { | 2019 } else if (Elements.isUnresolved(resolvedReceiver)) { |
| 1961 return null; | 2020 return null; |
| 1962 } else if (resolvedReceiver.isClass()) { | 2021 } else if (resolvedReceiver.isClass()) { |
| 1963 ClassElement receiverClass = resolvedReceiver; | 2022 ClassElement receiverClass = resolvedReceiver; |
| 1964 receiverClass.ensureResolved(compiler); | 2023 receiverClass.ensureResolved(compiler); |
| 1965 if (node.isOperator) { | 2024 if (node.isOperator) { |
| 1966 // When the resolved receiver is a class, we can have two cases: | 2025 // When the resolved receiver is a class, we can have two cases: |
| 1967 // 1) a static send: C.foo, or | 2026 // 1) a static send: C.foo, or |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2227 MessageKind.CANNOT_RESOLVE_GETTER); | 2286 MessageKind.CANNOT_RESOLVE_GETTER); |
| 2228 compiler.backend.registerThrowNoSuchMethod(); | 2287 compiler.backend.registerThrowNoSuchMethod(); |
| 2229 } | 2288 } |
| 2230 } else if (target.impliesType()) { | 2289 } else if (target.impliesType()) { |
| 2231 compiler.backend.registerThrowNoSuchMethod(); | 2290 compiler.backend.registerThrowNoSuchMethod(); |
| 2232 } else if (target.modifiers.isFinal() || target.modifiers.isConst()) { | 2291 } else if (target.modifiers.isFinal() || target.modifiers.isConst()) { |
| 2233 setter = | 2292 setter = |
| 2234 warnAndCreateErroneousElement(node.selector, target.name, | 2293 warnAndCreateErroneousElement(node.selector, target.name, |
| 2235 MessageKind.CANNOT_RESOLVE_SETTER); | 2294 MessageKind.CANNOT_RESOLVE_SETTER); |
| 2236 compiler.backend.registerThrowNoSuchMethod(); | 2295 compiler.backend.registerThrowNoSuchMethod(); |
| 2296 } else if (isComplex && target.name == const SourceString('[]=')) { | |
| 2297 getter = | |
| 2298 setter.getEnclosingClass().lookupMember(const SourceString('[]')); | |
|
kasperl
2013/02/27 10:11:28
Seems more logical to use the enclosing class of t
ngeoffray
2013/02/27 12:23:59
Yes, it's the same. Replaced to use target.
| |
| 2299 if (getter == null) { | |
| 2300 getter = | |
| 2301 warnAndCreateErroneousElement(node, setter.name, | |
|
kasperl
2013/02/27 10:11:28
Move the warnAnd...( part to the previous line (li
ngeoffray
2013/02/27 12:23:59
Done.
| |
| 2302 MessageKind.CANNOT_RESOLVE_INDEX); | |
| 2303 compiler.backend.registerThrowNoSuchMethod(); | |
| 2304 } | |
| 2237 } | 2305 } |
| 2238 } | 2306 } |
| 2239 | 2307 |
| 2240 visit(node.argumentsNode); | 2308 visit(node.argumentsNode); |
| 2241 | 2309 |
| 2242 // TODO(ngeoffray): Check if the target can be assigned. | 2310 // TODO(ngeoffray): Check if the target can be assigned. |
| 2243 // TODO(ngeoffray): Warn if target is null and the send is | 2311 // TODO(ngeoffray): Warn if target is null and the send is |
| 2244 // unqualified. | 2312 // unqualified. |
| 2245 | 2313 |
| 2246 Selector selector = mapping.getSelector(node); | 2314 Selector selector = mapping.getSelector(node); |
| 2247 if (isComplex) { | 2315 if (isComplex) { |
| 2316 Selector getterSelector; | |
| 2248 if (selector.isSetter()) { | 2317 if (selector.isSetter()) { |
| 2249 // TODO(kasperl): We're registering the getter selector for | 2318 getterSelector = new Selector.getterFrom(selector); |
| 2250 // compound assignments on the AST selector node. In the code | |
| 2251 // generator, we then fetch it from there when generating the | |
| 2252 // getter for a SendSet node. | |
| 2253 Selector getterSelector = new Selector.getterFrom(selector); | |
| 2254 registerSend(getterSelector, getter); | |
| 2255 mapping.setSelector(node.selector, getterSelector); | |
| 2256 useElement(node.selector, getter); | |
| 2257 } else { | 2319 } else { |
| 2258 // TODO(kasperl): If [getter] is resolved, it will actually | |
| 2259 // refer to the []= operator which isn't the one we want to | |
| 2260 // register here. We should consider using some notion of | |
| 2261 // abstract indexable element that we can resolve to so we can | |
| 2262 // distinguish the two. | |
| 2263 assert(selector.isIndexSet()); | 2320 assert(selector.isIndexSet()); |
| 2264 registerSend(new Selector.index(), null); | 2321 getterSelector = new Selector.index(); |
| 2265 } | 2322 } |
| 2323 registerSend(getterSelector, getter); | |
| 2324 mapping.setGetterSelectorInComplexSendSet(node, getterSelector); | |
| 2325 useElement(node.selector, getter); | |
| 2266 | 2326 |
| 2267 // Make sure we include the + and - operators if we are using | 2327 // Make sure we include the + and - operators if we are using |
| 2268 // the ++ and -- ones. Also, if op= form is used, include op itself. | 2328 // the ++ and -- ones. Also, if op= form is used, include op itself. |
| 2269 void registerBinaryOperator(SourceString name) { | 2329 void registerBinaryOperator(SourceString name) { |
| 2270 Selector binop = new Selector.binaryOperator(name); | 2330 Selector binop = new Selector.binaryOperator(name); |
| 2271 world.registerDynamicInvocation(binop.name, binop); | 2331 world.registerDynamicInvocation(binop.name, binop); |
| 2332 mapping.setOperatorSelectorInComplexSendSet(node, binop); | |
| 2272 } | 2333 } |
| 2273 if (identical(source, '++')) registerBinaryOperator(const SourceString('+' )); | 2334 if (identical(source, '++')) { |
| 2274 if (identical(source, '--')) registerBinaryOperator(const SourceString('-' )); | 2335 registerBinaryOperator(const SourceString('+')); |
| 2275 if (source.endsWith('=')) { | 2336 } else if (identical(source, '--')) { |
| 2337 registerBinaryOperator(const SourceString('-')); | |
| 2338 } else if (source.endsWith('=')) { | |
| 2276 registerBinaryOperator(Elements.mapToUserOperator(operatorName)); | 2339 registerBinaryOperator(Elements.mapToUserOperator(operatorName)); |
| 2277 } | 2340 } |
| 2278 } | 2341 } |
| 2279 | 2342 |
| 2280 registerSend(selector, setter); | 2343 registerSend(selector, setter); |
| 2281 return useElement(node, setter); | 2344 return useElement(node, setter); |
| 2282 } | 2345 } |
| 2283 | 2346 |
| 2284 void registerSend(Selector selector, Element target) { | 2347 void registerSend(Selector selector, Element target) { |
| 2285 if (target == null || target.isInstanceMember()) { | 2348 if (target == null || target.isInstanceMember()) { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2624 mapping[node.target] = label; | 2687 mapping[node.target] = label; |
| 2625 } | 2688 } |
| 2626 mapping[node] = target; | 2689 mapping[node] = target; |
| 2627 } | 2690 } |
| 2628 | 2691 |
| 2629 registerImplicitInvocation(SourceString name, int arity) { | 2692 registerImplicitInvocation(SourceString name, int arity) { |
| 2630 Selector selector = new Selector.call(name, null, arity); | 2693 Selector selector = new Selector.call(name, null, arity); |
| 2631 world.registerDynamicInvocation(name, selector); | 2694 world.registerDynamicInvocation(name, selector); |
| 2632 } | 2695 } |
| 2633 | 2696 |
| 2634 registerImplicitFieldGet(SourceString name) { | 2697 visitForIn(ForIn node) { |
| 2635 Selector selector = new Selector.getter(name, null); | 2698 LibraryElement library = enclosingElement.getLibrary(); |
| 2636 world.registerDynamicGetter(name, selector); | 2699 Selector iteratorSelector = |
| 2637 } | 2700 new Selector.getter(const SourceString('iterator'), library); |
| 2701 world.registerDynamicGetter(iteratorSelector.name, iteratorSelector); | |
| 2702 mapping.setIteratorSelector(node, iteratorSelector); | |
| 2638 | 2703 |
| 2639 visitForIn(ForIn node) { | 2704 Selector currentSelector = |
| 2640 for (final name in const [ | 2705 new Selector.getter(const SourceString('current'), library); |
| 2641 const SourceString('iterator'), | 2706 world.registerDynamicGetter(currentSelector.name, currentSelector); |
| 2642 const SourceString('current')]) { | 2707 mapping.setCurrentSelector(node, currentSelector); |
| 2643 registerImplicitFieldGet(name); | 2708 |
| 2644 } | 2709 Selector moveNextSelector = |
| 2645 registerImplicitInvocation(const SourceString('moveNext'), 0); | 2710 new Selector.call(const SourceString('moveNext'), library, 0); |
| 2711 world.registerDynamicInvocation(moveNextSelector.name, moveNextSelector); | |
| 2712 mapping.setMoveNextSelector(node, moveNextSelector); | |
| 2713 | |
| 2646 visit(node.expression); | 2714 visit(node.expression); |
| 2647 Scope blockScope = new BlockScope(scope); | 2715 Scope blockScope = new BlockScope(scope); |
| 2648 Node declaration = node.declaredIdentifier; | 2716 Node declaration = node.declaredIdentifier; |
| 2649 visitIn(declaration, blockScope); | 2717 visitIn(declaration, blockScope); |
| 2650 visitLoopBodyIn(node, node.body, blockScope); | 2718 visitLoopBodyIn(node, node.body, blockScope); |
| 2651 | 2719 |
| 2652 // TODO(lrn): Also allow a single identifier. | 2720 // TODO(lrn): Also allow a single identifier. |
| 2653 if ((declaration is !Send || declaration.asSend().selector is !Identifier | 2721 if ((declaration is !Send || declaration.asSend().selector is !Identifier |
| 2654 || declaration.asSend().receiver != null) | 2722 || declaration.asSend().receiver != null) |
| 2655 && (declaration is !VariableDefinitions || | 2723 && (declaration is !VariableDefinitions || |
| (...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3739 return e; | 3807 return e; |
| 3740 } | 3808 } |
| 3741 | 3809 |
| 3742 /// Assumed to be called by [resolveRedirectingFactory]. | 3810 /// Assumed to be called by [resolveRedirectingFactory]. |
| 3743 Element visitReturn(Return node) { | 3811 Element visitReturn(Return node) { |
| 3744 Node expression = node.expression; | 3812 Node expression = node.expression; |
| 3745 return finishConstructorReference(visit(expression), | 3813 return finishConstructorReference(visit(expression), |
| 3746 expression, expression); | 3814 expression, expression); |
| 3747 } | 3815 } |
| 3748 } | 3816 } |
| OLD | NEW |