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 DartType getType(TypeAnnotation annotation); | 8 DartType getType(TypeAnnotation annotation); |
9 bool isParameterChecked(Element element); | 9 bool isParameterChecked(Element element); |
10 } | 10 } |
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
947 } | 947 } |
948 } | 948 } |
949 | 949 |
950 class ResolverVisitor extends CommonResolverVisitor<Element> { | 950 class ResolverVisitor extends CommonResolverVisitor<Element> { |
951 final TreeElementMapping mapping; | 951 final TreeElementMapping mapping; |
952 final Element enclosingElement; | 952 final Element enclosingElement; |
953 final TypeResolver typeResolver; | 953 final TypeResolver typeResolver; |
954 bool inInstanceContext; | 954 bool inInstanceContext; |
955 Scope scope; | 955 Scope scope; |
956 ClassElement currentClass; | 956 ClassElement currentClass; |
957 ExpressionStatement currentExpressionStatement; | |
957 bool typeRequired = false; | 958 bool typeRequired = false; |
958 StatementScope statementScope; | 959 StatementScope statementScope; |
959 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; | 960 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; |
960 | 961 |
961 ResolverVisitor(Compiler compiler, Element element) | 962 ResolverVisitor(Compiler compiler, Element element) |
962 : this.mapping = new TreeElementMapping(), | 963 : this.mapping = new TreeElementMapping(), |
963 this.enclosingElement = element, | 964 this.enclosingElement = element, |
964 // When the element is a field, we are actually resolving its | 965 // When the element is a field, we are actually resolving its |
965 // initial value, which should not have access to instance | 966 // initial value, which should not have access to instance |
966 // fields. | 967 // fields. |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 } | 1132 } |
1132 | 1133 |
1133 visitDoWhile(DoWhile node) { | 1134 visitDoWhile(DoWhile node) { |
1134 visitLoopBodyIn(node, node.body, new BlockScope(scope)); | 1135 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
1135 visit(node.condition); | 1136 visit(node.condition); |
1136 } | 1137 } |
1137 | 1138 |
1138 visitEmptyStatement(EmptyStatement node) { } | 1139 visitEmptyStatement(EmptyStatement node) { } |
1139 | 1140 |
1140 visitExpressionStatement(ExpressionStatement node) { | 1141 visitExpressionStatement(ExpressionStatement node) { |
1142 ExpressionStatement oldExpressionStatement = currentExpressionStatement; | |
1143 currentExpressionStatement = node; | |
1141 visit(node.expression); | 1144 visit(node.expression); |
1145 currentExpressionStatement = oldExpressionStatement; | |
1142 } | 1146 } |
1143 | 1147 |
1144 visitFor(For node) { | 1148 visitFor(For node) { |
1145 Scope blockScope = new BlockScope(scope); | 1149 Scope blockScope = new BlockScope(scope); |
1146 visitIn(node.initializer, blockScope); | 1150 visitIn(node.initializer, blockScope); |
1147 visitIn(node.condition, blockScope); | 1151 visitIn(node.condition, blockScope); |
1148 visitIn(node.update, blockScope); | 1152 visitIn(node.update, blockScope); |
1149 visitLoopBodyIn(node, node.body, blockScope); | 1153 visitLoopBodyIn(node, node.body, blockScope); |
1150 } | 1154 } |
1151 | 1155 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1185 visit(node.condition); | 1189 visit(node.condition); |
1186 visit(node.thenPart); | 1190 visit(node.thenPart); |
1187 visit(node.elsePart); | 1191 visit(node.elsePart); |
1188 } | 1192 } |
1189 | 1193 |
1190 static bool isLogicalOperator(Identifier op) { | 1194 static bool isLogicalOperator(Identifier op) { |
1191 String str = op.source.stringValue; | 1195 String str = op.source.stringValue; |
1192 return (str === '&&' || str == '||' || str == '!'); | 1196 return (str === '&&' || str == '||' || str == '!'); |
1193 } | 1197 } |
1194 | 1198 |
1199 /** | |
1200 * Check the lexical scope chain for a declaration with the name "assert". | |
1201 * | |
1202 * This is used to detect whether "assert(x)" is actually an assertion or | |
1203 * just a call expression. | |
1204 * It does not check fields inherited from a superclass. | |
1205 */ | |
1206 bool isAssertInLexicalScope() { | |
1207 return scope.lexicalLookup(const SourceString("assert")) !== null; | |
1208 } | |
1209 | |
1210 /** Check whether [node] is the body of the current expression statement. */ | |
ahe
2012/09/06 22:25:53
body -> expression.
Lasse Reichstein Nielsen
2012/09/07 10:18:57
Done.
| |
1211 bool isExpressionStatementBody(Node node) { | |
ahe
2012/09/06 22:25:53
I don't like calling this a "body". isExpressionSt
Lasse Reichstein Nielsen
2012/09/07 10:18:57
Done.
| |
1212 return currentExpressionStatement !== null && | |
1213 currentExpressionStatement.expression === node; | |
1214 } | |
1215 | |
1195 Element resolveSend(Send node) { | 1216 Element resolveSend(Send node) { |
1196 Selector selector = resolveSelector(node); | 1217 Selector selector = resolveSelector(node); |
1197 | 1218 |
1198 if (node.receiver === null) { | 1219 if (node.receiver === null) { |
1220 // If this send is the body of an expression statement, and is on the | |
ahe
2012/09/06 22:25:53
body -> expression
Lasse Reichstein Nielsen
2012/09/07 10:18:57
Done.
| |
1221 // form "assert(expr);", and there is no declaration with name "assert" | |
1222 // in the lexical scope, then this is actually an assertion. | |
1223 if (isExpressionStatementBody(node) && | |
1224 selector.isAssertSyntax() && | |
1225 !isAssertInLexicalScope()) { | |
1226 return compiler.assertMethod; | |
1227 } | |
1199 return node.selector.accept(this); | 1228 return node.selector.accept(this); |
1200 } | 1229 } |
1201 | 1230 |
1202 var oldCategory = allowedCategory; | 1231 var oldCategory = allowedCategory; |
1203 allowedCategory |= | 1232 allowedCategory |= |
1204 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; | 1233 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; |
1205 Element resolvedReceiver = visit(node.receiver); | 1234 Element resolvedReceiver = visit(node.receiver); |
1206 allowedCategory = oldCategory; | 1235 allowedCategory = oldCategory; |
1207 | 1236 |
1208 Element target; | 1237 Element target; |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1372 // we need to register that fact that we may be calling a closure | 1401 // we need to register that fact that we may be calling a closure |
1373 // with the same arguments. | 1402 // with the same arguments. |
1374 if (node.isCall && | 1403 if (node.isCall && |
1375 (Element.isInvalid(target) || | 1404 (Element.isInvalid(target) || |
1376 target.isGetter() || | 1405 target.isGetter() || |
1377 Elements.isClosureSend(node, target))) { | 1406 Elements.isClosureSend(node, target))) { |
1378 Selector call = new Selector.callClosureFrom(selector); | 1407 Selector call = new Selector.callClosureFrom(selector); |
1379 world.registerDynamicInvocation(call.name, call); | 1408 world.registerDynamicInvocation(call.name, call); |
1380 } | 1409 } |
1381 | 1410 |
1382 // TODO(ngeoffray): We should do the check in | |
1383 // visitExpressionStatement instead. | |
1384 if (target === compiler.assertMethod && !node.isCall) { | |
1385 // We can only use assert by calling it. | |
1386 if (!inInstanceContext) { | |
1387 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]); | |
1388 } | |
1389 target = null; | |
1390 } | |
1391 | |
1392 // TODO(ngeoffray): Warn if target is null and the send is | 1411 // TODO(ngeoffray): Warn if target is null and the send is |
1393 // unqualified. | 1412 // unqualified. |
1394 useElement(node, target); | 1413 useElement(node, target); |
1395 registerSend(selector, target); | 1414 registerSend(selector, target); |
1396 return node.isPropertyAccess ? target : null; | 1415 return node.isPropertyAccess ? target : null; |
1397 } | 1416 } |
1398 | 1417 |
1399 visitSendSet(SendSet node) { | 1418 visitSendSet(SendSet node) { |
1400 Element target = resolveSend(node); | 1419 Element target = resolveSend(node); |
1401 Element setter = target; | 1420 Element setter = target; |
(...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2550 return e; | 2569 return e; |
2551 } | 2570 } |
2552 } | 2571 } |
2553 | 2572 |
2554 class Scope { | 2573 class Scope { |
2555 final Element element; | 2574 final Element element; |
2556 final Scope parent; | 2575 final Scope parent; |
2557 | 2576 |
2558 Scope(this.parent, this.element); | 2577 Scope(this.parent, this.element); |
2559 abstract Element add(Element element); | 2578 abstract Element add(Element element); |
2560 abstract Element lookup(SourceString name); | 2579 |
2580 Element lookup(SourceString name) { | |
2581 Element result = localLookup(name); | |
2582 if (result != null) return result; | |
2583 return parent.lookup(name); | |
2584 } | |
2585 | |
2586 Element lexicalLookup(SourceString name) { | |
2587 Element result = localLookup(name); | |
2588 if (result != null) return result; | |
2589 return parent.lexicalLookup(name); | |
2590 } | |
2591 | |
2592 abstract Element localLookup(SourceString name); | |
2561 } | 2593 } |
2562 | 2594 |
2563 /** | 2595 /** |
2564 * [TypeDeclarationScope] defines the outer scope of a type declaration in | 2596 * [TypeDeclarationScope] defines the outer scope of a type declaration in |
2565 * which the declared type variables and the entities in the enclosing scope are | 2597 * which the declared type variables and the entities in the enclosing scope are |
2566 * available but where declared and inherited members are not available. This | 2598 * available but where declared and inherited members are not available. This |
2567 * scope is only used for class/interface declarations during resolution of the | 2599 * scope is only used for class/interface declarations during resolution of the |
2568 * class hierarchy. In all other cases [ClassScope] is used. | 2600 * class hierarchy. In all other cases [ClassScope] is used. |
2569 */ | 2601 */ |
2570 class TypeDeclarationScope extends Scope { | 2602 class TypeDeclarationScope extends Scope { |
2571 TypeDeclarationElement get element => super.element; | 2603 TypeDeclarationElement get element => super.element; |
2572 | 2604 |
2573 TypeDeclarationScope(parent, TypeDeclarationElement element) | 2605 TypeDeclarationScope(parent, TypeDeclarationElement element) |
2574 : super(parent, element) { | 2606 : super(parent, element) { |
2575 assert(parent !== null); | 2607 assert(parent !== null); |
2576 } | 2608 } |
2577 | 2609 |
2578 Element add(Element newElement) { | 2610 Element add(Element newElement) { |
2579 throw "Cannot add element to TypeDeclarationScope"; | 2611 throw "Cannot add element to TypeDeclarationScope"; |
2580 } | 2612 } |
2581 | 2613 |
2582 /** | 2614 /** |
2583 * Looks up [name] within the type variables declared in [element]. | 2615 * Looks up [name] within the type variables declared in [element]. |
2584 */ | 2616 */ |
2585 Element lookupTypeVariable(SourceString name) { | 2617 Element lookupTypeVariable(SourceString name) { |
2586 return null; | 2618 return null; |
2587 } | 2619 } |
2588 | 2620 |
2589 Element lookup(SourceString name) { | 2621 Element localLookup(SourceString name) { |
2590 Link<DartType> typeVariableLink = element.typeVariables; | 2622 Link<DartType> typeVariableLink = element.typeVariables; |
2591 while (!typeVariableLink.isEmpty()) { | 2623 while (!typeVariableLink.isEmpty()) { |
2592 TypeVariableType typeVariable = typeVariableLink.head; | 2624 TypeVariableType typeVariable = typeVariableLink.head; |
2593 if (typeVariable.name == name) { | 2625 if (typeVariable.name == name) { |
2594 return typeVariable.element; | 2626 return typeVariable.element; |
2595 } | 2627 } |
2596 typeVariableLink = typeVariableLink.tail; | 2628 typeVariableLink = typeVariableLink.tail; |
2597 } | 2629 } |
2598 | 2630 return null; |
2599 return parent.lookup(name); | |
2600 } | 2631 } |
2601 | 2632 |
2602 String toString() => | 2633 String toString() => |
2603 '$element${element.typeVariables} > $parent'; | 2634 '$element${element.typeVariables} > $parent'; |
2604 } | 2635 } |
2605 | 2636 |
2606 class MethodScope extends Scope { | 2637 class MethodScope extends Scope { |
2607 final Map<SourceString, Element> elements; | 2638 final Map<SourceString, Element> elements; |
2608 | 2639 |
2609 MethodScope(Scope parent, Element element) | 2640 MethodScope(Scope parent, Element element) |
2610 : super(parent, element), | 2641 : super(parent, element), |
2611 this.elements = new Map<SourceString, Element>() { | 2642 this.elements = new Map<SourceString, Element>() { |
2612 assert(parent !== null); | 2643 assert(parent !== null); |
2613 } | 2644 } |
2614 | 2645 |
2615 Element lookup(SourceString name) { | 2646 Element localLookup(SourceString name) => elements[name]; |
2616 Element found = elements[name]; | |
2617 if (found !== null) return found; | |
2618 return parent.lookup(name); | |
2619 } | |
2620 | 2647 |
2621 Element add(Element newElement) { | 2648 Element add(Element newElement) { |
2622 if (elements.containsKey(newElement.name)) { | 2649 if (elements.containsKey(newElement.name)) { |
2623 return elements[newElement.name]; | 2650 return elements[newElement.name]; |
2624 } | 2651 } |
2625 elements[newElement.name] = newElement; | 2652 elements[newElement.name] = newElement; |
2626 return newElement; | 2653 return newElement; |
2627 } | 2654 } |
2628 | 2655 |
2629 String toString() => '$element${elements.getKeys()} > $parent'; | 2656 String toString() => '$element${elements.getKeys()} > $parent'; |
2630 } | 2657 } |
2631 | 2658 |
2632 class BlockScope extends MethodScope { | 2659 class BlockScope extends MethodScope { |
2633 BlockScope(Scope parent) : super(parent, parent.element); | 2660 BlockScope(Scope parent) : super(parent, parent.element); |
2634 | 2661 |
2635 String toString() => 'block${elements.getKeys()} > $parent'; | 2662 String toString() => 'block${elements.getKeys()} > $parent'; |
2636 } | 2663 } |
2637 | 2664 |
2638 /** | 2665 /** |
2639 * [ClassScope] defines the inner scope of a class/interface declaration in | 2666 * [ClassScope] defines the inner scope of a class/interface declaration in |
2640 * which declared members, declared type variables, entities in the enclosing | 2667 * which declared members, declared type variables, entities in the enclosing |
2641 * scope and inherited members are available, in the given order. | 2668 * scope and inherited members are available, in the given order. |
2642 */ | 2669 */ |
2643 class ClassScope extends TypeDeclarationScope { | 2670 class ClassScope extends TypeDeclarationScope { |
2644 ClassScope(Scope parentScope, ClassElement element) | 2671 ClassScope(Scope parentScope, ClassElement element) |
2645 : super(parentScope, element); | 2672 : super(parentScope, element); |
2646 | 2673 |
2647 Element lookup(SourceString name) { | 2674 Element localLookup(SourceString name) { |
2648 ClassElement cls = element; | 2675 ClassElement cls = element; |
2649 Element result = cls.lookupLocalMember(name); | 2676 Element result = cls.lookupLocalMember(name); |
2650 if (result !== null) return result; | 2677 if (result !== null) return result; |
2651 result = super.lookup(name); | 2678 return super.localLookup(name); |
2652 if (result != null) return result; | 2679 } |
2680 | |
2681 Element lookup(SourceString name) { | |
2682 Element result = super.lookup(name); | |
2683 if (result !== null) return result; | |
2684 ClassElement cls = element; | |
2653 return cls.lookupSuperMember(name); | 2685 return cls.lookupSuperMember(name); |
2654 } | 2686 } |
2655 | 2687 |
2656 Element add(Element newElement) { | 2688 Element add(Element newElement) { |
2657 throw "Cannot add an element in a class scope"; | 2689 throw "Cannot add an element in a class scope"; |
2658 } | 2690 } |
2659 | 2691 |
2660 String toString() => '$element > $parent'; | 2692 String toString() => '$element > $parent'; |
2661 } | 2693 } |
2662 | 2694 |
2663 class TopScope extends Scope { | 2695 class TopScope extends Scope { |
2664 LibraryElement get library => element; | 2696 LibraryElement get library => element; |
2665 | 2697 |
2666 TopScope(LibraryElement library) : super(null, library); | 2698 TopScope(LibraryElement library) : super(null, library); |
2667 Element lookup(SourceString name) { | 2699 |
2668 return library.find(name); | 2700 Element localLookup(SourceString name) => library.find(name); |
2669 } | 2701 Element lookup(SourceString name) => localLookup(name); |
2702 Element lexicalLookup(SourceString name) => localLookup(name); | |
2670 | 2703 |
2671 Element add(Element newElement) { | 2704 Element add(Element newElement) { |
2672 throw "Cannot add an element in the top scope"; | 2705 throw "Cannot add an element in the top scope"; |
2673 } | 2706 } |
2674 String toString() => '$element'; | 2707 String toString() => '$element'; |
2675 } | 2708 } |
OLD | NEW |