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 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 bool inCheckContext; | 955 bool inCheckContext; |
956 Scope scope; | 956 Scope scope; |
957 ClassElement currentClass; | 957 ClassElement currentClass; |
| 958 ExpressionStatement currentExpressionStatement; |
958 bool typeRequired = false; | 959 bool typeRequired = false; |
959 StatementScope statementScope; | 960 StatementScope statementScope; |
960 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; | 961 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; |
961 | 962 |
962 ResolverVisitor(Compiler compiler, Element element) | 963 ResolverVisitor(Compiler compiler, Element element) |
963 : this.mapping = new TreeElementMapping(), | 964 : this.mapping = new TreeElementMapping(), |
964 this.enclosingElement = element, | 965 this.enclosingElement = element, |
965 // When the element is a field, we are actually resolving its | 966 // When the element is a field, we are actually resolving its |
966 // initial value, which should not have access to instance | 967 // initial value, which should not have access to instance |
967 // fields. | 968 // fields. |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 } | 1157 } |
1157 | 1158 |
1158 visitDoWhile(DoWhile node) { | 1159 visitDoWhile(DoWhile node) { |
1159 visitLoopBodyIn(node, node.body, new BlockScope(scope)); | 1160 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
1160 visit(node.condition); | 1161 visit(node.condition); |
1161 } | 1162 } |
1162 | 1163 |
1163 visitEmptyStatement(EmptyStatement node) { } | 1164 visitEmptyStatement(EmptyStatement node) { } |
1164 | 1165 |
1165 visitExpressionStatement(ExpressionStatement node) { | 1166 visitExpressionStatement(ExpressionStatement node) { |
| 1167 ExpressionStatement oldExpressionStatement = currentExpressionStatement; |
| 1168 currentExpressionStatement = node; |
1166 visit(node.expression); | 1169 visit(node.expression); |
| 1170 currentExpressionStatement = oldExpressionStatement; |
1167 } | 1171 } |
1168 | 1172 |
1169 visitFor(For node) { | 1173 visitFor(For node) { |
1170 Scope blockScope = new BlockScope(scope); | 1174 Scope blockScope = new BlockScope(scope); |
1171 visitIn(node.initializer, blockScope); | 1175 visitIn(node.initializer, blockScope); |
1172 visitIn(node.condition, blockScope); | 1176 visitIn(node.condition, blockScope); |
1173 visitIn(node.update, blockScope); | 1177 visitIn(node.update, blockScope); |
1174 visitLoopBodyIn(node, node.body, blockScope); | 1178 visitLoopBodyIn(node, node.body, blockScope); |
1175 } | 1179 } |
1176 | 1180 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 visit(node.condition); | 1214 visit(node.condition); |
1211 visit(node.thenPart); | 1215 visit(node.thenPart); |
1212 visit(node.elsePart); | 1216 visit(node.elsePart); |
1213 } | 1217 } |
1214 | 1218 |
1215 static bool isLogicalOperator(Identifier op) { | 1219 static bool isLogicalOperator(Identifier op) { |
1216 String str = op.source.stringValue; | 1220 String str = op.source.stringValue; |
1217 return (str === '&&' || str == '||' || str == '!'); | 1221 return (str === '&&' || str == '||' || str == '!'); |
1218 } | 1222 } |
1219 | 1223 |
| 1224 /** |
| 1225 * Check the lexical scope chain for a declaration with the name "assert". |
| 1226 * |
| 1227 * This is used to detect whether "assert(x)" is actually an assertion or |
| 1228 * just a call expression. |
| 1229 * It does not check fields inherited from a superclass. |
| 1230 */ |
| 1231 bool isAssertInLexicalScope() { |
| 1232 return scope.lexicalLookup(const SourceString("assert")) !== null; |
| 1233 } |
| 1234 |
| 1235 /** Check if [node] is the expression of the current expression statement. */ |
| 1236 bool isExpressionStatementExpression(Node node) { |
| 1237 return currentExpressionStatement !== null && |
| 1238 currentExpressionStatement.expression === node; |
| 1239 } |
| 1240 |
1220 Element resolveSend(Send node) { | 1241 Element resolveSend(Send node) { |
1221 Selector selector = resolveSelector(node); | 1242 Selector selector = resolveSelector(node); |
1222 | 1243 |
1223 if (node.receiver === null) { | 1244 if (node.receiver === null) { |
| 1245 // If this send is the expression of an expression statement, and is on |
| 1246 // the form "assert(expr);", and there is no declaration with name |
| 1247 // "assert" in the lexical scope, then this is actually an assertion. |
| 1248 if (isExpressionStatementExpression(node) && |
| 1249 selector.isAssertSyntax() && |
| 1250 !isAssertInLexicalScope()) { |
| 1251 return compiler.assertMethod; |
| 1252 } |
1224 return node.selector.accept(this); | 1253 return node.selector.accept(this); |
1225 } | 1254 } |
1226 | 1255 |
1227 var oldCategory = allowedCategory; | 1256 var oldCategory = allowedCategory; |
1228 allowedCategory |= | 1257 allowedCategory |= |
1229 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; | 1258 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; |
1230 Element resolvedReceiver = visit(node.receiver); | 1259 Element resolvedReceiver = visit(node.receiver); |
1231 allowedCategory = oldCategory; | 1260 allowedCategory = oldCategory; |
1232 | 1261 |
1233 Element target; | 1262 Element target; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1401 // we need to register that fact that we may be calling a closure | 1430 // we need to register that fact that we may be calling a closure |
1402 // with the same arguments. | 1431 // with the same arguments. |
1403 if (node.isCall && | 1432 if (node.isCall && |
1404 (Elements.isUnresolved(target) || | 1433 (Elements.isUnresolved(target) || |
1405 target.isGetter() || | 1434 target.isGetter() || |
1406 Elements.isClosureSend(node, target))) { | 1435 Elements.isClosureSend(node, target))) { |
1407 Selector call = new Selector.callClosureFrom(selector); | 1436 Selector call = new Selector.callClosureFrom(selector); |
1408 world.registerDynamicInvocation(call.name, call); | 1437 world.registerDynamicInvocation(call.name, call); |
1409 } | 1438 } |
1410 | 1439 |
1411 // TODO(ngeoffray): We should do the check in | |
1412 // visitExpressionStatement instead. | |
1413 if (target === compiler.assertMethod && !node.isCall) { | |
1414 // We can only use assert by calling it. | |
1415 if (!inInstanceContext) { | |
1416 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]); | |
1417 } | |
1418 target = null; | |
1419 } | |
1420 | |
1421 // TODO(ngeoffray): Warn if target is null and the send is | 1440 // TODO(ngeoffray): Warn if target is null and the send is |
1422 // unqualified. | 1441 // unqualified. |
1423 useElement(node, target); | 1442 useElement(node, target); |
1424 registerSend(selector, target); | 1443 registerSend(selector, target); |
1425 return node.isPropertyAccess ? target : null; | 1444 return node.isPropertyAccess ? target : null; |
1426 } | 1445 } |
1427 | 1446 |
1428 visitSendSet(SendSet node) { | 1447 visitSendSet(SendSet node) { |
1429 Element target = resolveSend(node); | 1448 Element target = resolveSend(node); |
1430 Element setter = target; | 1449 Element setter = target; |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1910 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH); | 1929 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH); |
1911 } | 1930 } |
1912 TypeAnnotation type = declaration.type; | 1931 TypeAnnotation type = declaration.type; |
1913 if (type !== null) { | 1932 if (type !== null) { |
1914 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); | 1933 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); |
1915 } | 1934 } |
1916 } | 1935 } |
1917 } | 1936 } |
1918 | 1937 |
1919 Scope blockScope = new BlockScope(scope); | 1938 Scope blockScope = new BlockScope(scope); |
1920 doInCheckContext(() => visitIn(node.type, blockScope)); | 1939 doInCheckContext(() => visitIn(node.type, blockScope)); |
1921 visitIn(node.formals, blockScope); | 1940 visitIn(node.formals, blockScope); |
1922 visitIn(node.block, blockScope); | 1941 visitIn(node.block, blockScope); |
1923 } | 1942 } |
1924 | 1943 |
1925 visitTypedef(Typedef node) { | 1944 visitTypedef(Typedef node) { |
1926 unimplemented(node, 'typedef'); | 1945 unimplemented(node, 'typedef'); |
1927 } | 1946 } |
1928 } | 1947 } |
1929 | 1948 |
1930 class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> { | 1949 class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> { |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2586 return e; | 2605 return e; |
2587 } | 2606 } |
2588 } | 2607 } |
2589 | 2608 |
2590 class Scope { | 2609 class Scope { |
2591 final Element element; | 2610 final Element element; |
2592 final Scope parent; | 2611 final Scope parent; |
2593 | 2612 |
2594 Scope(this.parent, this.element); | 2613 Scope(this.parent, this.element); |
2595 abstract Element add(Element element); | 2614 abstract Element add(Element element); |
2596 abstract Element lookup(SourceString name); | 2615 |
| 2616 Element lookup(SourceString name) { |
| 2617 Element result = localLookup(name); |
| 2618 if (result != null) return result; |
| 2619 return parent.lookup(name); |
| 2620 } |
| 2621 |
| 2622 Element lexicalLookup(SourceString name) { |
| 2623 Element result = localLookup(name); |
| 2624 if (result != null) return result; |
| 2625 return parent.lexicalLookup(name); |
| 2626 } |
| 2627 |
| 2628 abstract Element localLookup(SourceString name); |
2597 } | 2629 } |
2598 | 2630 |
2599 class VariableScope extends Scope { | 2631 class VariableScope extends Scope { |
2600 VariableScope(parent, element) : super(parent, element); | 2632 VariableScope(parent, element) : super(parent, element); |
2601 | 2633 |
2602 Element add(Element newElement) { | 2634 Element add(Element newElement) { |
2603 throw "Cannot add element to VariableScope"; | 2635 throw "Cannot add element to VariableScope"; |
2604 } | 2636 } |
2605 | 2637 |
2606 Element lookup(SourceString name) => parent.lookup(name); | 2638 Element lookup(SourceString name) => parent.lookup(name); |
(...skipping 13 matching lines...) Expand all Loading... |
2620 | 2652 |
2621 TypeDeclarationScope(parent, TypeDeclarationElement element) | 2653 TypeDeclarationScope(parent, TypeDeclarationElement element) |
2622 : super(parent, element) { | 2654 : super(parent, element) { |
2623 assert(parent !== null); | 2655 assert(parent !== null); |
2624 } | 2656 } |
2625 | 2657 |
2626 Element add(Element newElement) { | 2658 Element add(Element newElement) { |
2627 throw "Cannot add element to TypeDeclarationScope"; | 2659 throw "Cannot add element to TypeDeclarationScope"; |
2628 } | 2660 } |
2629 | 2661 |
2630 Element lookup(SourceString name) { | 2662 Element localLookup(SourceString name) { |
2631 Link<DartType> typeVariableLink = element.typeVariables; | 2663 Link<DartType> typeVariableLink = element.typeVariables; |
2632 while (!typeVariableLink.isEmpty()) { | 2664 while (!typeVariableLink.isEmpty()) { |
2633 TypeVariableType typeVariable = typeVariableLink.head; | 2665 TypeVariableType typeVariable = typeVariableLink.head; |
2634 if (typeVariable.name == name) { | 2666 if (typeVariable.name == name) { |
2635 return typeVariable.element; | 2667 return typeVariable.element; |
2636 } | 2668 } |
2637 typeVariableLink = typeVariableLink.tail; | 2669 typeVariableLink = typeVariableLink.tail; |
2638 } | 2670 } |
2639 | 2671 return null; |
2640 return parent.lookup(name); | |
2641 } | 2672 } |
2642 | 2673 |
2643 String toString() => | 2674 String toString() => |
2644 '$element${element.typeVariables} > $parent'; | 2675 '$element${element.typeVariables} > $parent'; |
2645 } | 2676 } |
2646 | 2677 |
2647 class MethodScope extends Scope { | 2678 class MethodScope extends Scope { |
2648 final Map<SourceString, Element> elements; | 2679 final Map<SourceString, Element> elements; |
2649 | 2680 |
2650 MethodScope(Scope parent, Element element) | 2681 MethodScope(Scope parent, Element element) |
2651 : super(parent, element), | 2682 : super(parent, element), |
2652 this.elements = new Map<SourceString, Element>() { | 2683 this.elements = new Map<SourceString, Element>() { |
2653 assert(parent !== null); | 2684 assert(parent !== null); |
2654 } | 2685 } |
2655 | 2686 |
2656 Element lookup(SourceString name) { | 2687 Element localLookup(SourceString name) => elements[name]; |
2657 Element found = elements[name]; | |
2658 if (found !== null) return found; | |
2659 return parent.lookup(name); | |
2660 } | |
2661 | 2688 |
2662 Element add(Element newElement) { | 2689 Element add(Element newElement) { |
2663 if (elements.containsKey(newElement.name)) { | 2690 if (elements.containsKey(newElement.name)) { |
2664 return elements[newElement.name]; | 2691 return elements[newElement.name]; |
2665 } | 2692 } |
2666 elements[newElement.name] = newElement; | 2693 elements[newElement.name] = newElement; |
2667 return newElement; | 2694 return newElement; |
2668 } | 2695 } |
2669 | 2696 |
2670 String toString() => '$element${elements.getKeys()} > $parent'; | 2697 String toString() => '$element${elements.getKeys()} > $parent'; |
2671 } | 2698 } |
2672 | 2699 |
2673 class BlockScope extends MethodScope { | 2700 class BlockScope extends MethodScope { |
2674 BlockScope(Scope parent) : super(parent, parent.element); | 2701 BlockScope(Scope parent) : super(parent, parent.element); |
2675 | 2702 |
2676 String toString() => 'block${elements.getKeys()} > $parent'; | 2703 String toString() => 'block${elements.getKeys()} > $parent'; |
2677 } | 2704 } |
2678 | 2705 |
2679 /** | 2706 /** |
2680 * [ClassScope] defines the inner scope of a class/interface declaration in | 2707 * [ClassScope] defines the inner scope of a class/interface declaration in |
2681 * which declared members, declared type variables, entities in the enclosing | 2708 * which declared members, declared type variables, entities in the enclosing |
2682 * scope and inherited members are available, in the given order. | 2709 * scope and inherited members are available, in the given order. |
2683 */ | 2710 */ |
2684 class ClassScope extends TypeDeclarationScope { | 2711 class ClassScope extends TypeDeclarationScope { |
2685 bool inStaticContext = false; | 2712 bool inStaticContext = false; |
2686 | 2713 |
2687 ClassScope(Scope parentScope, ClassElement element) | 2714 ClassScope(Scope parentScope, ClassElement element) |
2688 : super(parentScope, element); | 2715 : super(parentScope, element); |
2689 | 2716 |
2690 Element lookup(SourceString name) { | 2717 Element localLookup(SourceString name) { |
2691 ClassElement cls = element; | 2718 ClassElement cls = element; |
2692 Element result = cls.lookupLocalMember(name); | 2719 Element result = cls.lookupLocalMember(name); |
2693 if (result !== null) return result; | 2720 if (result !== null) return result; |
2694 if (!inStaticContext) { | 2721 if (!inStaticContext) { |
2695 // If not in a static context, we can lookup in the | 2722 // If not in a static context, we can lookup in the |
2696 // TypeDeclaration scope, which contains the type variables of | 2723 // TypeDeclaration scope, which contains the type variables of |
2697 // the class. | 2724 // the class. |
2698 result = super.lookup(name); | 2725 return super.localLookup(name); |
2699 } else { | |
2700 result = parent.lookup(name); | |
2701 } | 2726 } |
2702 if (result != null) return result; | 2727 return null; |
| 2728 } |
| 2729 |
| 2730 Element lookup(SourceString name) { |
| 2731 Element result = super.lookup(name); |
| 2732 if (result !== null) return result; |
| 2733 ClassElement cls = element; |
2703 return cls.lookupSuperMember(name); | 2734 return cls.lookupSuperMember(name); |
2704 } | 2735 } |
2705 | 2736 |
2706 Element add(Element newElement) { | 2737 Element add(Element newElement) { |
2707 throw "Cannot add an element in a class scope"; | 2738 throw "Cannot add an element in a class scope"; |
2708 } | 2739 } |
2709 | 2740 |
2710 String toString() => '$element > $parent'; | 2741 String toString() => '$element > $parent'; |
2711 } | 2742 } |
2712 | 2743 |
2713 class TopScope extends Scope { | 2744 class TopScope extends Scope { |
2714 LibraryElement get library => element; | 2745 LibraryElement get library => element; |
2715 | 2746 |
2716 TopScope(LibraryElement library) : super(null, library); | 2747 TopScope(LibraryElement library) : super(null, library); |
2717 Element lookup(SourceString name) { | 2748 |
2718 return library.find(name); | 2749 Element localLookup(SourceString name) => library.find(name); |
2719 } | 2750 Element lookup(SourceString name) => localLookup(name); |
| 2751 Element lexicalLookup(SourceString name) => localLookup(name); |
2720 | 2752 |
2721 Element add(Element newElement) { | 2753 Element add(Element newElement) { |
2722 throw "Cannot add an element in the top scope"; | 2754 throw "Cannot add an element in the top scope"; |
2723 } | 2755 } |
2724 String toString() => '$element'; | 2756 String toString() => '$element'; |
2725 } | 2757 } |
OLD | NEW |