| 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 Type getType(TypeAnnotation annotation); | 8 Type getType(TypeAnnotation annotation); |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 224 } |
| 225 return result; | 225 return result; |
| 226 } | 226 } |
| 227 | 227 |
| 228 void resolveClass(ClassElement element) { | 228 void resolveClass(ClassElement element) { |
| 229 if (element.isResolved || element.isBeingResolved) return; | 229 if (element.isResolved || element.isBeingResolved) return; |
| 230 element.isBeingResolved = true; | 230 element.isBeingResolved = true; |
| 231 measure(() { | 231 measure(() { |
| 232 ClassNode tree = element.parseNode(compiler); | 232 ClassNode tree = element.parseNode(compiler); |
| 233 ClassResolverVisitor visitor = | 233 ClassResolverVisitor visitor = |
| 234 new ClassResolverVisitor(compiler, element.getLibrary(), element); | 234 new ClassResolverVisitor(compiler, element); |
| 235 visitor.visit(tree); | 235 visitor.visit(tree); |
| 236 element.isBeingResolved = false; | 236 element.isBeingResolved = false; |
| 237 element.isResolved = true; | 237 element.isResolved = true; |
| 238 | 238 |
| 239 while (!toResolve.isEmpty()) { | 239 while (!toResolve.isEmpty()) { |
| 240 ClassElement classElement = toResolve.removeFirst(); | 240 ClassElement classElement = toResolve.removeFirst(); |
| 241 classElement.ensureResolved(compiler); | 241 classElement.ensureResolved(compiler); |
| 242 } | 242 } |
| 243 | 243 |
| 244 checkMembers(element); | 244 checkMembers(element); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 return null; // If there was no redirection always return null. | 562 return null; // If there was no redirection always return null. |
| 563 } | 563 } |
| 564 } | 564 } |
| 565 | 565 |
| 566 class CommonResolverVisitor<R> extends AbstractVisitor<R> { | 566 class CommonResolverVisitor<R> extends AbstractVisitor<R> { |
| 567 final Compiler compiler; | 567 final Compiler compiler; |
| 568 | 568 |
| 569 CommonResolverVisitor(Compiler this.compiler); | 569 CommonResolverVisitor(Compiler this.compiler); |
| 570 | 570 |
| 571 R visitNode(Node node) { | 571 R visitNode(Node node) { |
| 572 cancel(node, 'internal error'); | 572 cancel(node, |
| 573 'internal error: Unhandled node: ${node.getObjectDescription()}'); |
| 573 } | 574 } |
| 574 | 575 |
| 575 R visitEmptyStatement(Node node) => null; | 576 R visitEmptyStatement(Node node) => null; |
| 576 | 577 |
| 577 /** Convenience method for visiting nodes that may be null. */ | 578 /** Convenience method for visiting nodes that may be null. */ |
| 578 R visit(Node node) => (node == null) ? null : node.accept(this); | 579 R visit(Node node) => (node == null) ? null : node.accept(this); |
| 579 | 580 |
| 580 void error(Node node, MessageKind kind, [arguments = const []]) { | 581 void error(Node node, MessageKind kind, [arguments = const []]) { |
| 581 ResolutionError message = new ResolutionError(kind, arguments); | 582 ResolutionError message = new ResolutionError(kind, arguments); |
| 582 compiler.reportError(node, message); | 583 compiler.reportError(node, message); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 int nestingLevel = 0; | 647 int nestingLevel = 0; |
| 647 | 648 |
| 648 StatementScope() | 649 StatementScope() |
| 649 : labels = const EmptyLabelScope(), | 650 : labels = const EmptyLabelScope(), |
| 650 breakTargetStack = const EmptyLink<TargetElement>(), | 651 breakTargetStack = const EmptyLink<TargetElement>(), |
| 651 continueTargetStack = const EmptyLink<TargetElement>(); | 652 continueTargetStack = const EmptyLink<TargetElement>(); |
| 652 | 653 |
| 653 LabelElement lookupLabel(String label) { | 654 LabelElement lookupLabel(String label) { |
| 654 return labels.lookup(label); | 655 return labels.lookup(label); |
| 655 } | 656 } |
| 657 |
| 656 TargetElement currentBreakTarget() => | 658 TargetElement currentBreakTarget() => |
| 657 breakTargetStack.isEmpty() ? null : breakTargetStack.head; | 659 breakTargetStack.isEmpty() ? null : breakTargetStack.head; |
| 658 | 660 |
| 659 TargetElement currentContinueTarget() => | 661 TargetElement currentContinueTarget() => |
| 660 continueTargetStack.isEmpty() ? null : continueTargetStack.head; | 662 continueTargetStack.isEmpty() ? null : continueTargetStack.head; |
| 661 | 663 |
| 662 void enterLabelScope(Map<String, LabelElement> elements) { | 664 void enterLabelScope(Map<String, LabelElement> elements) { |
| 663 labels = new LabeledStatementLabelScope(labels, elements); | 665 labels = new LabeledStatementLabelScope(labels, elements); |
| 664 nestingLevel++; | 666 nestingLevel++; |
| 665 } | 667 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 690 | 692 |
| 691 void exitSwitch() { | 693 void exitSwitch() { |
| 692 nestingLevel--; | 694 nestingLevel--; |
| 693 breakTargetStack = breakTargetStack.tail; | 695 breakTargetStack = breakTargetStack.tail; |
| 694 labels = labels.outer; | 696 labels = labels.outer; |
| 695 } | 697 } |
| 696 } | 698 } |
| 697 | 699 |
| 698 class TypeResolver { | 700 class TypeResolver { |
| 699 final Compiler compiler; | 701 final Compiler compiler; |
| 702 |
| 700 TypeResolver(this.compiler); | 703 TypeResolver(this.compiler); |
| 701 | 704 |
| 702 Element resolveTypeName(Scope context, TypeAnnotation node) { | 705 Element resolveTypeName(Scope scope, TypeAnnotation node) { |
| 703 Identifier typeName = node.typeName.asIdentifier(); | 706 Identifier typeName = node.typeName.asIdentifier(); |
| 704 Send send = node.typeName.asSend(); | 707 Send send = node.typeName.asSend(); |
| 708 return resolveTypeNameInternal(scope, typeName, send); |
| 709 } |
| 710 |
| 711 Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) { |
| 705 if (send !== null) { | 712 if (send !== null) { |
| 706 typeName = send.selector; | 713 typeName = send.selector; |
| 707 } | 714 } |
| 708 if (typeName.source.stringValue === 'void') { | 715 if (typeName.source.stringValue === 'void') { |
| 709 return compiler.types.voidType.element; | 716 return compiler.types.voidType.element; |
| 710 } else if (send !== null) { | 717 } else if (send !== null) { |
| 711 Element e = context.lookup(send.receiver.asIdentifier().source); | 718 Element e = scope.lookup(send.receiver.asIdentifier().source); |
| 712 if (e !== null && e.kind === ElementKind.PREFIX) { | 719 if (e !== null && e.kind === ElementKind.PREFIX) { |
| 713 // The receiver is a prefix. Lookup in the imported members. | 720 // The receiver is a prefix. Lookup in the imported members. |
| 714 PrefixElement prefix = e; | 721 PrefixElement prefix = e; |
| 715 return prefix.lookupLocalMember(typeName.source); | 722 return prefix.lookupLocalMember(typeName.source); |
| 716 } else if (e !== null && e.kind === ElementKind.CLASS) { | 723 } else if (e !== null && e.kind === ElementKind.CLASS) { |
| 717 // The receiver is the class part of a named constructor. | 724 // The receiver is the class part of a named constructor. |
| 718 return e; | 725 return e; |
| 719 } else { | 726 } else { |
| 720 return null; | 727 return null; |
| 721 } | 728 } |
| 722 } else { | 729 } else { |
| 723 return context.lookup(typeName.source); | 730 return scope.lookup(typeName.source); |
| 724 } | 731 } |
| 725 } | 732 } |
| 726 | 733 |
| 734 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean |
| 735 // flags instead of closures. |
| 727 Type resolveTypeAnnotation(TypeAnnotation node, | 736 Type resolveTypeAnnotation(TypeAnnotation node, |
| 728 [Scope inContext, ClassElement inClass, | 737 [Scope inScope, ClassElement inClass, |
| 729 onFailure(Node, MessageKind, [List arguments]), | 738 onFailure(Node, MessageKind, [List arguments]), |
| 730 whenResolved(Node, Type)]) { | 739 whenResolved(Node, Type)]) { |
| 731 if (onFailure === null) { | 740 if (onFailure === null) { |
| 732 onFailure = (n, k, [arguments]) {}; | 741 onFailure = (n, k, [arguments]) {}; |
| 733 } | 742 } |
| 734 if (whenResolved === null) { | 743 if (whenResolved === null) { |
| 735 whenResolved = (n, t) {}; | 744 whenResolved = (n, t) {}; |
| 736 } | 745 } |
| 737 if (inClass !== null) { | 746 if (inClass !== null) { |
| 738 inContext = new ClassScope(inClass, inClass.getLibrary()); | 747 inScope = inClass.buildScope(); |
| 739 } | 748 } |
| 740 if (inContext === null) { | 749 if (inScope === null) { |
| 741 compiler.internalError('resolveTypeAnnotation: no scope specified'); | 750 compiler.internalError('resolveTypeAnnotation: no scope specified'); |
| 742 } | 751 } |
| 743 return resolveTypeAnnotationInContext(inContext, node, onFailure, | 752 return resolveTypeAnnotationInContext(inScope, node, onFailure, |
| 744 whenResolved); | 753 whenResolved); |
| 745 } | 754 } |
| 746 | 755 |
| 747 Type resolveTypeAnnotationInContext(Scope context, TypeAnnotation node, | 756 Type resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, |
| 748 onFailure, whenResolved) { | 757 onFailure, whenResolved) { |
| 749 Element element = resolveTypeName(context, node); | 758 Element element = resolveTypeName(scope, node); |
| 750 Type type; | 759 Type type; |
| 751 if (element === null) { | 760 if (element === null) { |
| 752 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); | 761 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); |
| 753 } else if (!element.impliesType()) { | 762 } else if (!element.impliesType()) { |
| 754 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); | 763 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); |
| 755 } else { | 764 } else { |
| 756 if (element === compiler.types.voidType.element || | 765 if (element === compiler.types.voidType.element || |
| 757 element === compiler.types.dynamicType.element) { | 766 element === compiler.types.dynamicType.element) { |
| 758 type = element.computeType(compiler); | 767 type = element.computeType(compiler); |
| 759 } else if (element.isClass()) { | 768 } else if (element.isClass()) { |
| 760 ClassElement cls = element; | 769 ClassElement cls = element; |
| 761 if (!cls.isResolved) compiler.resolveClass(cls); | 770 if (!cls.isResolved) compiler.resolveClass(cls); |
| 762 LinkBuilder<Type> arguments = new LinkBuilder<Type>(); | 771 LinkBuilder<Type> arguments = new LinkBuilder<Type>(); |
| 763 if (node.typeArguments !== null) { | 772 if (node.typeArguments !== null) { |
| 764 int index = 0; | 773 int index = 0; |
| 765 for (Link<Node> typeArguments = node.typeArguments.nodes; | 774 for (Link<Node> typeArguments = node.typeArguments.nodes; |
| 766 !typeArguments.isEmpty(); | 775 !typeArguments.isEmpty(); |
| 767 typeArguments = typeArguments.tail) { | 776 typeArguments = typeArguments.tail) { |
| 768 if (++index > cls.typeParameters.length) { | 777 if (++index > cls.typeParameters.length) { |
| 769 onFailure(typeArguments.head, | 778 onFailure(typeArguments.head, |
| 770 MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 779 MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
| 771 } | 780 } |
| 772 Type argType = resolveTypeAnnotationInContext(context, | 781 Type argType = resolveTypeAnnotationInContext(scope, |
| 773 typeArguments.head, | 782 typeArguments.head, |
| 774 onFailure, | 783 onFailure, |
| 775 whenResolved); | 784 whenResolved); |
| 776 arguments.addLast(argType); | 785 arguments.addLast(argType); |
| 777 } | 786 } |
| 778 if (index < cls.typeParameters.length) { | 787 if (index < cls.typeParameters.length) { |
| 779 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | 788 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
| 780 } | 789 } |
| 781 } | 790 } |
| 782 if (cls.typeParameters.length == 0) { | 791 if (cls.typeParameters.length == 0) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 797 whenResolved(node, type); | 806 whenResolved(node, type); |
| 798 return type; | 807 return type; |
| 799 } | 808 } |
| 800 } | 809 } |
| 801 | 810 |
| 802 class ResolverVisitor extends CommonResolverVisitor<Element> { | 811 class ResolverVisitor extends CommonResolverVisitor<Element> { |
| 803 final TreeElementMapping mapping; | 812 final TreeElementMapping mapping; |
| 804 final Element enclosingElement; | 813 final Element enclosingElement; |
| 805 final TypeResolver typeResolver; | 814 final TypeResolver typeResolver; |
| 806 bool inInstanceContext; | 815 bool inInstanceContext; |
| 807 Scope context; | 816 Scope scope; |
| 808 ClassElement currentClass; | 817 ClassElement currentClass; |
| 809 bool typeRequired = false; | 818 bool typeRequired = false; |
| 810 StatementScope statementScope; | 819 StatementScope statementScope; |
| 811 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; | 820 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; |
| 812 | 821 |
| 813 ResolverVisitor(Compiler compiler, Element element) | 822 ResolverVisitor(Compiler compiler, Element element) |
| 814 : this.mapping = new TreeElementMapping(), | 823 : this.mapping = new TreeElementMapping(), |
| 815 this.enclosingElement = element, | 824 this.enclosingElement = element, |
| 816 inInstanceContext = element.isInstanceMember() | 825 inInstanceContext = element.isInstanceMember() |
| 817 || element.isGenerativeConstructor(), | 826 || element.isGenerativeConstructor(), |
| 818 this.currentClass = element.isMember() ? element.enclosingElement : null, | 827 this.currentClass = element.isMember() ? element.enclosingElement : null, |
| 819 this.statementScope = new StatementScope(), | 828 this.statementScope = new StatementScope(), |
| 820 typeResolver = new TypeResolver(compiler), | 829 typeResolver = new TypeResolver(compiler), |
| 830 scope = element.buildEnclosingScope(), |
| 821 super(compiler) { | 831 super(compiler) { |
| 822 LibraryElement library = element.getLibrary(); | |
| 823 element = element.getEnclosingMember(); | |
| 824 if (element !== null) { | |
| 825 context = new ClassScope(element.enclosingElement, library); | |
| 826 } else { | |
| 827 this.context = new TopScope(library); | |
| 828 } | |
| 829 } | 832 } |
| 830 | 833 |
| 831 Enqueuer get world() => compiler.enqueuer.resolution; | 834 Enqueuer get world() => compiler.enqueuer.resolution; |
| 832 | 835 |
| 833 Element lookup(Node node, SourceString name) { | 836 Element lookup(Node node, SourceString name) { |
| 834 Element result = context.lookup(name); | 837 Element result = scope.lookup(name); |
| 835 if (!inInstanceContext && result != null && result.isInstanceMember()) { | 838 if (!inInstanceContext && result != null && result.isInstanceMember()) { |
| 836 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); | 839 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 837 } | 840 } |
| 838 return result; | 841 return result; |
| 839 } | 842 } |
| 840 | 843 |
| 841 // Create, or reuse an already created, statement element for a statement. | 844 // Create, or reuse an already created, statement element for a statement. |
| 842 TargetElement getOrCreateTargetElement(Node statement) { | 845 TargetElement getOrCreateTargetElement(Node statement) { |
| 843 TargetElement element = mapping[statement]; | 846 TargetElement element = mapping[statement]; |
| 844 if (element === null) { | 847 if (element === null) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 Type type = resolveTypeAnnotation(node); | 895 Type type = resolveTypeAnnotation(node); |
| 893 if (type !== null) return type.element; | 896 if (type !== null) return type.element; |
| 894 return null; | 897 return null; |
| 895 } | 898 } |
| 896 | 899 |
| 897 Element defineElement(Node node, Element element, | 900 Element defineElement(Node node, Element element, |
| 898 [bool doAddToScope = true]) { | 901 [bool doAddToScope = true]) { |
| 899 compiler.ensure(element !== null); | 902 compiler.ensure(element !== null); |
| 900 mapping[node] = element; | 903 mapping[node] = element; |
| 901 if (doAddToScope) { | 904 if (doAddToScope) { |
| 902 Element existing = context.add(element); | 905 Element existing = scope.add(element); |
| 903 if (existing != element) { | 906 if (existing != element) { |
| 904 error(node, MessageKind.DUPLICATE_DEFINITION, [node]); | 907 error(node, MessageKind.DUPLICATE_DEFINITION, [node]); |
| 905 } | 908 } |
| 906 } | 909 } |
| 907 return element; | 910 return element; |
| 908 } | 911 } |
| 909 | 912 |
| 910 Element useElement(Node node, Element element) { | 913 Element useElement(Node node, Element element) { |
| 911 if (element === null) return null; | 914 if (element === null) return null; |
| 912 mapping[node] = element; | 915 mapping[node] = element; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 933 | 936 |
| 934 Type useType(TypeAnnotation annotation, Type type) { | 937 Type useType(TypeAnnotation annotation, Type type) { |
| 935 if (type !== null) { | 938 if (type !== null) { |
| 936 mapping.setType(annotation, type); | 939 mapping.setType(annotation, type); |
| 937 useElement(annotation, type.element); | 940 useElement(annotation, type.element); |
| 938 } | 941 } |
| 939 return type; | 942 return type; |
| 940 } | 943 } |
| 941 | 944 |
| 942 void setupFunction(FunctionExpression node, FunctionElement function) { | 945 void setupFunction(FunctionExpression node, FunctionElement function) { |
| 943 context = new MethodScope(context, function); | 946 scope = new MethodScope(scope, function); |
| 944 // Put the parameters in scope. | 947 // Put the parameters in scope. |
| 945 FunctionSignature functionParameters = | 948 FunctionSignature functionParameters = |
| 946 function.computeSignature(compiler); | 949 function.computeSignature(compiler); |
| 947 Link<Node> parameterNodes = node.parameters.nodes; | 950 Link<Node> parameterNodes = node.parameters.nodes; |
| 948 functionParameters.forEachParameter((Element element) { | 951 functionParameters.forEachParameter((Element element) { |
| 949 if (element == functionParameters.optionalParameters.head) { | 952 if (element == functionParameters.optionalParameters.head) { |
| 950 NodeList nodes = parameterNodes.head; | 953 NodeList nodes = parameterNodes.head; |
| 951 parameterNodes = nodes.nodes; | 954 parameterNodes = nodes.nodes; |
| 952 } | 955 } |
| 953 VariableDefinitions variableDefinitions = parameterNodes.head; | 956 VariableDefinitions variableDefinitions = parameterNodes.head; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 969 } | 972 } |
| 970 | 973 |
| 971 visitCascadeReceiver(CascadeReceiver node) { | 974 visitCascadeReceiver(CascadeReceiver node) { |
| 972 visit(node.expression); | 975 visit(node.expression); |
| 973 } | 976 } |
| 974 | 977 |
| 975 Element visitClassNode(ClassNode node) { | 978 Element visitClassNode(ClassNode node) { |
| 976 cancel(node, "shouldn't be called"); | 979 cancel(node, "shouldn't be called"); |
| 977 } | 980 } |
| 978 | 981 |
| 979 visitIn(Node node, Scope scope) { | 982 visitIn(Node node, Scope nestedScope) { |
| 980 context = scope; | 983 scope = nestedScope; |
| 981 Element element = visit(node); | 984 Element element = visit(node); |
| 982 context = context.parent; | 985 scope = scope.parent; |
| 983 return element; | 986 return element; |
| 984 } | 987 } |
| 985 | 988 |
| 986 /** | 989 /** |
| 987 * Introduces new default targets for break and continue | 990 * Introduces new default targets for break and continue |
| 988 * before visiting the body of the loop | 991 * before visiting the body of the loop |
| 989 */ | 992 */ |
| 990 visitLoopBodyIn(Node loop, Node body, Scope scope) { | 993 visitLoopBodyIn(Node loop, Node body, Scope bodyScope) { |
| 991 TargetElement element = getOrCreateTargetElement(loop); | 994 TargetElement element = getOrCreateTargetElement(loop); |
| 992 statementScope.enterLoop(element); | 995 statementScope.enterLoop(element); |
| 993 visitIn(body, scope); | 996 visitIn(body, bodyScope); |
| 994 statementScope.exitLoop(); | 997 statementScope.exitLoop(); |
| 995 if (!element.isTarget) { | 998 if (!element.isTarget) { |
| 996 mapping.remove(loop); | 999 mapping.remove(loop); |
| 997 } | 1000 } |
| 998 } | 1001 } |
| 999 | 1002 |
| 1000 visitBlock(Block node) { | 1003 visitBlock(Block node) { |
| 1001 visitIn(node.statements, new BlockScope(context)); | 1004 visitIn(node.statements, new BlockScope(scope)); |
| 1002 } | 1005 } |
| 1003 | 1006 |
| 1004 visitDoWhile(DoWhile node) { | 1007 visitDoWhile(DoWhile node) { |
| 1005 visitLoopBodyIn(node, node.body, new BlockScope(context)); | 1008 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
| 1006 visit(node.condition); | 1009 visit(node.condition); |
| 1007 } | 1010 } |
| 1008 | 1011 |
| 1009 visitEmptyStatement(EmptyStatement node) { } | 1012 visitEmptyStatement(EmptyStatement node) { } |
| 1010 | 1013 |
| 1011 visitExpressionStatement(ExpressionStatement node) { | 1014 visitExpressionStatement(ExpressionStatement node) { |
| 1012 visit(node.expression); | 1015 visit(node.expression); |
| 1013 } | 1016 } |
| 1014 | 1017 |
| 1015 visitFor(For node) { | 1018 visitFor(For node) { |
| 1016 Scope scope = new BlockScope(context); | 1019 Scope blockScope = new BlockScope(scope); |
| 1017 visitIn(node.initializer, scope); | 1020 visitIn(node.initializer, blockScope); |
| 1018 visitIn(node.condition, scope); | 1021 visitIn(node.condition, blockScope); |
| 1019 visitIn(node.update, scope); | 1022 visitIn(node.update, blockScope); |
| 1020 visitLoopBodyIn(node, node.body, scope); | 1023 visitLoopBodyIn(node, node.body, blockScope); |
| 1021 } | 1024 } |
| 1022 | 1025 |
| 1023 visitFunctionDeclaration(FunctionDeclaration node) { | 1026 visitFunctionDeclaration(FunctionDeclaration node) { |
| 1024 assert(node.function.name !== null); | 1027 assert(node.function.name !== null); |
| 1025 visit(node.function); | 1028 visit(node.function); |
| 1026 FunctionElement functionElement = mapping[node.function]; | 1029 FunctionElement functionElement = mapping[node.function]; |
| 1027 // TODO(floitsch): this might lead to two errors complaining about | 1030 // TODO(floitsch): this might lead to two errors complaining about |
| 1028 // shadowing. | 1031 // shadowing. |
| 1029 defineElement(node, functionElement); | 1032 defineElement(node, functionElement); |
| 1030 } | 1033 } |
| 1031 | 1034 |
| 1032 visitFunctionExpression(FunctionExpression node) { | 1035 visitFunctionExpression(FunctionExpression node) { |
| 1033 visit(node.returnType); | 1036 visit(node.returnType); |
| 1034 SourceString name; | 1037 SourceString name; |
| 1035 if (node.name === null) { | 1038 if (node.name === null) { |
| 1036 name = const SourceString(""); | 1039 name = const SourceString(""); |
| 1037 } else { | 1040 } else { |
| 1038 name = node.name.asIdentifier().source; | 1041 name = node.name.asIdentifier().source; |
| 1039 } | 1042 } |
| 1040 FunctionElement enclosing = new FunctionElement.node( | 1043 FunctionElement enclosing = new FunctionElement.node( |
| 1041 name, node, ElementKind.FUNCTION, new Modifiers.empty(), | 1044 name, node, ElementKind.FUNCTION, new Modifiers.empty(), |
| 1042 context.element); | 1045 scope.element); |
| 1043 setupFunction(node, enclosing); | 1046 setupFunction(node, enclosing); |
| 1044 defineElement(node, enclosing, doAddToScope: node.name !== null); | 1047 defineElement(node, enclosing, doAddToScope: node.name !== null); |
| 1045 | 1048 |
| 1046 // Run the body in a fresh statement scope. | 1049 // Run the body in a fresh statement scope. |
| 1047 StatementScope oldScope = statementScope; | 1050 StatementScope oldScope = statementScope; |
| 1048 statementScope = new StatementScope(); | 1051 statementScope = new StatementScope(); |
| 1049 visit(node.body); | 1052 visit(node.body); |
| 1050 statementScope = oldScope; | 1053 statementScope = oldScope; |
| 1051 | 1054 |
| 1052 context = context.parent; | 1055 scope = scope.parent; |
| 1053 } | 1056 } |
| 1054 | 1057 |
| 1055 visitIf(If node) { | 1058 visitIf(If node) { |
| 1056 visit(node.condition); | 1059 visit(node.condition); |
| 1057 visit(node.thenPart); | 1060 visit(node.thenPart); |
| 1058 visit(node.elsePart); | 1061 visit(node.elsePart); |
| 1059 } | 1062 } |
| 1060 | 1063 |
| 1061 static bool isLogicalOperator(Identifier op) { | 1064 static bool isLogicalOperator(Identifier op) { |
| 1062 String str = op.source.stringValue; | 1065 String str = op.source.stringValue; |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1312 visitVariableDefinitions(VariableDefinitions node) { | 1315 visitVariableDefinitions(VariableDefinitions node) { |
| 1313 visit(node.type); | 1316 visit(node.type); |
| 1314 VariableDefinitionsVisitor visitor = | 1317 VariableDefinitionsVisitor visitor = |
| 1315 new VariableDefinitionsVisitor(compiler, node, this, | 1318 new VariableDefinitionsVisitor(compiler, node, this, |
| 1316 ElementKind.VARIABLE); | 1319 ElementKind.VARIABLE); |
| 1317 visitor.visit(node.definitions); | 1320 visitor.visit(node.definitions); |
| 1318 } | 1321 } |
| 1319 | 1322 |
| 1320 visitWhile(While node) { | 1323 visitWhile(While node) { |
| 1321 visit(node.condition); | 1324 visit(node.condition); |
| 1322 visitLoopBodyIn(node, node.body, new BlockScope(context)); | 1325 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
| 1323 } | 1326 } |
| 1324 | 1327 |
| 1325 visitParenthesizedExpression(ParenthesizedExpression node) { | 1328 visitParenthesizedExpression(ParenthesizedExpression node) { |
| 1326 visit(node.expression); | 1329 visit(node.expression); |
| 1327 } | 1330 } |
| 1328 | 1331 |
| 1329 visitNewExpression(NewExpression node) { | 1332 visitNewExpression(NewExpression node) { |
| 1330 Node selector = node.send.selector; | 1333 Node selector = node.send.selector; |
| 1331 | 1334 |
| 1332 FunctionElement constructor = resolveConstructor(node); | 1335 FunctionElement constructor = resolveConstructor(node); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 Type resolveTypeRequired(TypeAnnotation node) { | 1392 Type resolveTypeRequired(TypeAnnotation node) { |
| 1390 bool old = typeRequired; | 1393 bool old = typeRequired; |
| 1391 typeRequired = true; | 1394 typeRequired = true; |
| 1392 Type result = resolveTypeAnnotation(node); | 1395 Type result = resolveTypeAnnotation(node); |
| 1393 typeRequired = old; | 1396 typeRequired = old; |
| 1394 return result; | 1397 return result; |
| 1395 } | 1398 } |
| 1396 | 1399 |
| 1397 Type resolveTypeAnnotation(TypeAnnotation node) { | 1400 Type resolveTypeAnnotation(TypeAnnotation node) { |
| 1398 Function report = typeRequired ? error : warning; | 1401 Function report = typeRequired ? error : warning; |
| 1399 return typeResolver.resolveTypeAnnotation(node, inContext: context, | 1402 return typeResolver.resolveTypeAnnotation(node, inScope: scope, |
| 1400 onFailure: report, | 1403 onFailure: report, |
| 1401 whenResolved: useType); | 1404 whenResolved: useType); |
| 1402 } | 1405 } |
| 1403 | 1406 |
| 1404 visitModifiers(Modifiers node) { | 1407 visitModifiers(Modifiers node) { |
| 1405 // TODO(ngeoffray): Implement this. | 1408 // TODO(ngeoffray): Implement this. |
| 1406 unimplemented(node, 'modifiers'); | 1409 unimplemented(node, 'modifiers'); |
| 1407 } | 1410 } |
| 1408 | 1411 |
| 1409 visitLiteralList(LiteralList node) { | 1412 visitLiteralList(LiteralList node) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 unimplemented(node, "continue to switch case"); | 1477 unimplemented(node, "continue to switch case"); |
| 1475 } | 1478 } |
| 1476 label.setContinueTarget(); | 1479 label.setContinueTarget(); |
| 1477 mapping[node.target] = label; | 1480 mapping[node.target] = label; |
| 1478 } | 1481 } |
| 1479 mapping[node] = target; | 1482 mapping[node] = target; |
| 1480 } | 1483 } |
| 1481 | 1484 |
| 1482 visitForIn(ForIn node) { | 1485 visitForIn(ForIn node) { |
| 1483 visit(node.expression); | 1486 visit(node.expression); |
| 1484 Scope scope = new BlockScope(context); | 1487 Scope blockScope = new BlockScope(scope); |
| 1485 Node declaration = node.declaredIdentifier; | 1488 Node declaration = node.declaredIdentifier; |
| 1486 visitIn(declaration, scope); | 1489 visitIn(declaration, blockScope); |
| 1487 visitLoopBodyIn(node, node.body, scope); | 1490 visitLoopBodyIn(node, node.body, blockScope); |
| 1488 | 1491 |
| 1489 // TODO(lrn): Also allow a single identifier. | 1492 // TODO(lrn): Also allow a single identifier. |
| 1490 if ((declaration is !Send || declaration.asSend().selector is !Identifier) | 1493 if ((declaration is !Send || declaration.asSend().selector is !Identifier) |
| 1491 && (declaration is !VariableDefinitions || | 1494 && (declaration is !VariableDefinitions || |
| 1492 !declaration.asVariableDefinitions().definitions.nodes.tail.isEmpty())) | 1495 !declaration.asVariableDefinitions().definitions.nodes.tail.isEmpty())) |
| 1493 { | 1496 { |
| 1494 // The variable declaration is either not an identifier, not a | 1497 // The variable declaration is either not an identifier, not a |
| 1495 // declaration, or it's declaring more than one variable. | 1498 // declaration, or it's declaring more than one variable. |
| 1496 error(node.declaredIdentifier, MessageKind.INVALID_FOR_IN, []); | 1499 error(node.declaredIdentifier, MessageKind.INVALID_FOR_IN, []); |
| 1497 } | 1500 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 TargetElement targetElement = label.target; | 1600 TargetElement targetElement = label.target; |
| 1598 SwitchCase switchCase = targetElement.statement; | 1601 SwitchCase switchCase = targetElement.statement; |
| 1599 mapping.remove(switchCase); | 1602 mapping.remove(switchCase); |
| 1600 mapping.remove(label.label); | 1603 mapping.remove(label.label); |
| 1601 } | 1604 } |
| 1602 }); | 1605 }); |
| 1603 } | 1606 } |
| 1604 | 1607 |
| 1605 visitSwitchCase(SwitchCase node) { | 1608 visitSwitchCase(SwitchCase node) { |
| 1606 node.labelsAndCases.accept(this); | 1609 node.labelsAndCases.accept(this); |
| 1607 visitIn(node.statements, new BlockScope(context)); | 1610 visitIn(node.statements, new BlockScope(scope)); |
| 1608 } | 1611 } |
| 1609 | 1612 |
| 1610 visitCaseMatch(CaseMatch node) { | 1613 visitCaseMatch(CaseMatch node) { |
| 1611 visit(node.expression); | 1614 visit(node.expression); |
| 1612 } | 1615 } |
| 1613 | 1616 |
| 1614 visitTryStatement(TryStatement node) { | 1617 visitTryStatement(TryStatement node) { |
| 1615 visit(node.tryBlock); | 1618 visit(node.tryBlock); |
| 1616 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) { | 1619 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) { |
| 1617 // TODO(ngeoffray): The precise location is | 1620 // TODO(ngeoffray): The precise location is |
| 1618 // node.getEndtoken.next. Adjust when issue #1581 is fixed. | 1621 // node.getEndtoken.next. Adjust when issue #1581 is fixed. |
| 1619 error(node, MessageKind.NO_CATCH_NOR_FINALLY); | 1622 error(node, MessageKind.NO_CATCH_NOR_FINALLY); |
| 1620 } | 1623 } |
| 1621 visit(node.catchBlocks); | 1624 visit(node.catchBlocks); |
| 1622 visit(node.finallyBlock); | 1625 visit(node.finallyBlock); |
| 1623 } | 1626 } |
| 1624 | 1627 |
| 1625 visitCatchBlock(CatchBlock node) { | 1628 visitCatchBlock(CatchBlock node) { |
| 1626 Scope scope = new BlockScope(context); | 1629 Scope blockScope = new BlockScope(scope); |
| 1627 if (node.formals.isEmpty()) { | 1630 if (node.formals.isEmpty()) { |
| 1628 error(node, MessageKind.EMPTY_CATCH_DECLARATION); | 1631 error(node, MessageKind.EMPTY_CATCH_DECLARATION); |
| 1629 } else if (!node.formals.nodes.tail.isEmpty() | 1632 } else if (!node.formals.nodes.tail.isEmpty() |
| 1630 && !node.formals.nodes.tail.tail.isEmpty()) { | 1633 && !node.formals.nodes.tail.tail.isEmpty()) { |
| 1631 for (Node extra in node.formals.nodes.tail.tail) { | 1634 for (Node extra in node.formals.nodes.tail.tail) { |
| 1632 error(extra, MessageKind.EXTRA_CATCH_DECLARATION); | 1635 error(extra, MessageKind.EXTRA_CATCH_DECLARATION); |
| 1633 } | 1636 } |
| 1634 } | 1637 } |
| 1635 visitIn(node.formals, scope); | 1638 visitIn(node.formals, blockScope); |
| 1636 visitIn(node.block, scope); | 1639 visitIn(node.block, blockScope); |
| 1637 } | 1640 } |
| 1638 | 1641 |
| 1639 visitTypedef(Typedef node) { | 1642 visitTypedef(Typedef node) { |
| 1640 unimplemented(node, 'typedef'); | 1643 unimplemented(node, 'typedef'); |
| 1641 } | 1644 } |
| 1642 } | 1645 } |
| 1643 | 1646 |
| 1644 class ClassResolverVisitor extends CommonResolverVisitor<Type> { | 1647 class ClassResolverVisitor extends CommonResolverVisitor<Type> { |
| 1645 Scope context; | 1648 Scope scope; |
| 1646 ClassElement classElement; | 1649 ClassElement classElement; |
| 1647 | 1650 |
| 1648 ClassResolverVisitor(Compiler compiler, LibraryElement library, | 1651 ClassResolverVisitor(Compiler compiler, |
| 1649 ClassElement this.classElement) | 1652 ClassElement classElement) |
| 1650 : context = new TopScope(library), | 1653 : this.classElement = classElement, |
| 1651 super(compiler); | 1654 scope = classElement.buildEnclosingScope(), |
| 1655 super(compiler); |
| 1652 | 1656 |
| 1653 Type visitClassNode(ClassNode node) { | 1657 Type visitClassNode(ClassNode node) { |
| 1654 compiler.ensure(classElement !== null); | 1658 compiler.ensure(classElement !== null); |
| 1655 compiler.ensure(!classElement.isResolved); | 1659 compiler.ensure(!classElement.isResolved); |
| 1656 final Link<Node> parameters = | 1660 final Link<Node> parameters = |
| 1657 node.typeParameters !== null ? node.typeParameters.nodes | 1661 node.typeParameters !== null ? node.typeParameters.nodes |
| 1658 : const EmptyLink<TypeVariable>(); | 1662 : const EmptyLink<TypeVariable>(); |
| 1659 // Create types and elements for type variable. | 1663 // Create types and elements for type variable. |
| 1660 for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) { | 1664 for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) { |
| 1661 TypeVariable typeNode = link.head; | 1665 TypeVariable typeNode = link.head; |
| 1662 SourceString variableName = typeNode.name.source; | 1666 SourceString variableName = typeNode.name.source; |
| 1663 TypeVariableType variableType = new TypeVariableType(variableName); | 1667 TypeVariableType variableType = new TypeVariableType(variableName); |
| 1664 TypeVariableElement variableElement = | 1668 TypeVariableElement variableElement = |
| 1665 new TypeVariableElement(variableName, classElement, node, | 1669 new TypeVariableElement(variableName, classElement, node, |
| 1666 variableType); | 1670 variableType); |
| 1667 variableType.element = variableElement; | 1671 variableType.element = variableElement; |
| 1668 classElement.typeParameters[variableName] = variableElement; | 1672 classElement.typeParameters[variableName] = variableElement; |
| 1669 context = new TypeVariablesScope(context, classElement); | 1673 scope = new TypeDeclarationScope(scope, classElement); |
| 1670 } | 1674 } |
| 1671 // Resolve the bounds of type variables. | 1675 // Resolve the bounds of type variables. |
| 1672 for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) { | 1676 for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) { |
| 1673 TypeVariable typeNode = link.head; | 1677 TypeVariable typeNode = link.head; |
| 1674 SourceString variableName = typeNode.name.source; | 1678 SourceString variableName = typeNode.name.source; |
| 1675 TypeVariableElement variableElement = | 1679 TypeVariableElement variableElement = |
| 1676 classElement.typeParameters[variableName]; | 1680 classElement.typeParameters[variableName]; |
| 1677 if (typeNode.bound !== null) { | 1681 if (typeNode.bound !== null) { |
| 1678 Type boundType = visit(typeNode.bound); | 1682 Type boundType = visit(typeNode.bound); |
| 1679 if (boundType !== null && boundType.element == variableElement) { | 1683 if (boundType !== null && boundType.element == variableElement) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 calculateAllSupertypes(classElement, new Set<ClassElement>()); | 1730 calculateAllSupertypes(classElement, new Set<ClassElement>()); |
| 1727 addDefaultConstructorIfNeeded(classElement); | 1731 addDefaultConstructorIfNeeded(classElement); |
| 1728 return classElement.computeType(compiler); | 1732 return classElement.computeType(compiler); |
| 1729 } | 1733 } |
| 1730 | 1734 |
| 1731 Type visitTypeAnnotation(TypeAnnotation node) { | 1735 Type visitTypeAnnotation(TypeAnnotation node) { |
| 1732 return visit(node.typeName); | 1736 return visit(node.typeName); |
| 1733 } | 1737 } |
| 1734 | 1738 |
| 1735 Type visitIdentifier(Identifier node) { | 1739 Type visitIdentifier(Identifier node) { |
| 1736 Element element = context.lookup(node.source); | 1740 Element element = scope.lookup(node.source); |
| 1737 if (element === null) { | 1741 if (element === null) { |
| 1738 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); | 1742 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); |
| 1739 return null; | 1743 return null; |
| 1740 } else if (!element.impliesType() && !element.isTypeVariable()) { | 1744 } else if (!element.impliesType() && !element.isTypeVariable()) { |
| 1741 error(node, MessageKind.NOT_A_TYPE, [node]); | 1745 error(node, MessageKind.NOT_A_TYPE, [node]); |
| 1742 return null; | 1746 return null; |
| 1743 } else { | 1747 } else { |
| 1744 if (element.isClass()) { | 1748 if (element.isClass()) { |
| 1745 compiler.resolver.toResolve.add(element); | 1749 compiler.resolver.toResolve.add(element); |
| 1746 } | 1750 } |
| 1747 if (element.isTypeVariable()) { | 1751 if (element.isTypeVariable()) { |
| 1748 TypeVariableElement variableElement = element; | 1752 TypeVariableElement variableElement = element; |
| 1749 return variableElement.type; | 1753 return variableElement.type; |
| 1750 } else if (element.isTypedef()) { | 1754 } else if (element.isTypedef()) { |
| 1751 compiler.unimplemented('visitIdentifier for typedefs', node: node); | 1755 compiler.unimplemented('visitIdentifier for typedefs', node: node); |
| 1752 } else { | 1756 } else { |
| 1753 // TODO(ngeoffray): Use type variables. | 1757 // TODO(ngeoffray): Use type variables. |
| 1754 return element.computeType(compiler); | 1758 return element.computeType(compiler); |
| 1755 } | 1759 } |
| 1756 } | 1760 } |
| 1757 return null; | 1761 return null; |
| 1758 } | 1762 } |
| 1759 | 1763 |
| 1760 Type visitSend(Send node) { | 1764 Type visitSend(Send node) { |
| 1761 Identifier prefix = node.receiver.asIdentifier(); | 1765 Identifier prefix = node.receiver.asIdentifier(); |
| 1762 if (prefix === null) { | 1766 if (prefix === null) { |
| 1763 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); | 1767 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); |
| 1764 return null; | 1768 return null; |
| 1765 } | 1769 } |
| 1766 Element element = context.lookup(prefix.source); | 1770 Element element = scope.lookup(prefix.source); |
| 1767 if (element === null || element.kind !== ElementKind.PREFIX) { | 1771 if (element === null || element.kind !== ElementKind.PREFIX) { |
| 1768 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); | 1772 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); |
| 1769 return null; | 1773 return null; |
| 1770 } | 1774 } |
| 1771 PrefixElement prefixElement = element; | 1775 PrefixElement prefixElement = element; |
| 1772 Identifier selector = node.selector.asIdentifier(); | 1776 Identifier selector = node.selector.asIdentifier(); |
| 1773 var e = prefixElement.lookupLocalMember(selector.source); | 1777 var e = prefixElement.lookupLocalMember(selector.source); |
| 1774 if (e === null || !e.impliesType()) { | 1778 if (e === null || !e.impliesType()) { |
| 1775 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]); | 1779 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]); |
| 1776 return null; | 1780 return null; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1869 VariableDefinitions definitions; | 1873 VariableDefinitions definitions; |
| 1870 ResolverVisitor resolver; | 1874 ResolverVisitor resolver; |
| 1871 ElementKind kind; | 1875 ElementKind kind; |
| 1872 VariableListElement variables; | 1876 VariableListElement variables; |
| 1873 | 1877 |
| 1874 VariableDefinitionsVisitor(Compiler compiler, | 1878 VariableDefinitionsVisitor(Compiler compiler, |
| 1875 this.definitions, this.resolver, this.kind) | 1879 this.definitions, this.resolver, this.kind) |
| 1876 : super(compiler) | 1880 : super(compiler) |
| 1877 { | 1881 { |
| 1878 variables = new VariableListElement.node( | 1882 variables = new VariableListElement.node( |
| 1879 definitions, ElementKind.VARIABLE_LIST, resolver.context.element); | 1883 definitions, ElementKind.VARIABLE_LIST, resolver.scope.element); |
| 1880 } | 1884 } |
| 1881 | 1885 |
| 1882 SourceString visitSendSet(SendSet node) { | 1886 SourceString visitSendSet(SendSet node) { |
| 1883 assert(node.arguments.tail.isEmpty()); // Sanity check | 1887 assert(node.arguments.tail.isEmpty()); // Sanity check |
| 1884 resolver.visit(node.arguments.head); | 1888 resolver.visit(node.arguments.head); |
| 1885 return visit(node.selector); | 1889 return visit(node.selector); |
| 1886 } | 1890 } |
| 1887 | 1891 |
| 1888 SourceString visitIdentifier(Identifier node) => node.source; | 1892 SourceString visitIdentifier(Identifier node) => node.source; |
| 1889 | 1893 |
| 1890 visitNodeList(NodeList node) { | 1894 visitNodeList(NodeList node) { |
| 1891 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 1895 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 1892 SourceString name = visit(link.head); | 1896 SourceString name = visit(link.head); |
| 1893 VariableElement element = new VariableElement( | 1897 VariableElement element = new VariableElement( |
| 1894 name, variables, kind, resolver.context.element, node: link.head); | 1898 name, variables, kind, resolver.scope.element, node: link.head); |
| 1895 resolver.defineElement(link.head, element); | 1899 resolver.defineElement(link.head, element); |
| 1896 } | 1900 } |
| 1897 } | 1901 } |
| 1898 } | 1902 } |
| 1899 | 1903 |
| 1904 /** |
| 1905 * [SignatureResolver] resolves function signatures. |
| 1906 */ |
| 1900 class SignatureResolver extends CommonResolverVisitor<Element> { | 1907 class SignatureResolver extends CommonResolverVisitor<Element> { |
| 1901 final Element enclosingElement; | 1908 final Element enclosingElement; |
| 1902 Link<Element> optionalParameters = const EmptyLink<Element>(); | 1909 Link<Element> optionalParameters = const EmptyLink<Element>(); |
| 1903 int optionalParameterCount = 0; | 1910 int optionalParameterCount = 0; |
| 1904 Node currentDefinitions; | 1911 VariableDefinitions currentDefinitions; |
| 1905 | 1912 |
| 1906 SignatureResolver(Compiler compiler, this.enclosingElement) : super(compiler); | 1913 SignatureResolver(Compiler compiler, this.enclosingElement) : super(compiler); |
| 1907 | 1914 |
| 1908 Element visitNodeList(NodeList node) { | 1915 Element visitNodeList(NodeList node) { |
| 1909 // This must be a list of optional arguments. | 1916 // This must be a list of optional arguments. |
| 1910 if (node.beginToken.stringValue !== '[') { | 1917 if (node.beginToken.stringValue !== '[') { |
| 1911 internalError(node, "expected optional parameters"); | 1918 internalError(node, "expected optional parameters"); |
| 1912 } | 1919 } |
| 1913 LinkBuilder<Element> elements = analyzeNodes(node.nodes); | 1920 LinkBuilder<Element> elements = analyzeNodes(node.nodes); |
| 1914 optionalParameterCount = elements.length; | 1921 optionalParameterCount = elements.length; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2022 // If parameter is null, the current node should be the last, | 2029 // If parameter is null, the current node should be the last, |
| 2023 // and a list of optional named parameters. | 2030 // and a list of optional named parameters. |
| 2024 if (!link.tail.isEmpty() || (link.head is !NodeList)) { | 2031 if (!link.tail.isEmpty() || (link.head is !NodeList)) { |
| 2025 internalError(link.head, "expected optional parameters"); | 2032 internalError(link.head, "expected optional parameters"); |
| 2026 } | 2033 } |
| 2027 } | 2034 } |
| 2028 } | 2035 } |
| 2029 return elements; | 2036 return elements; |
| 2030 } | 2037 } |
| 2031 | 2038 |
| 2039 /** |
| 2040 * Resolves formal parameters and return type to a [FunctionSignature]. |
| 2041 */ |
| 2032 static FunctionSignature analyze(Compiler compiler, | 2042 static FunctionSignature analyze(Compiler compiler, |
| 2033 NodeList formalParameters, | 2043 NodeList formalParameters, |
| 2034 Node returnNode, | 2044 Node returnNode, |
| 2035 Element element) { | 2045 Element element) { |
| 2036 SignatureResolver visitor = new SignatureResolver(compiler, element); | 2046 SignatureResolver visitor = new SignatureResolver(compiler, element); |
| 2037 LinkBuilder<Element> parametersBuilder = | 2047 LinkBuilder<Element> parametersBuilder = |
| 2038 visitor.analyzeNodes(formalParameters.nodes); | 2048 visitor.analyzeNodes(formalParameters.nodes); |
| 2039 Link<Element> parameters = parametersBuilder.toLink(); | 2049 Link<Element> parameters = parametersBuilder.toLink(); |
| 2040 Type returnType = | 2050 Type returnType = |
| 2041 compiler.resolveTypeAnnotation(element, returnNode); | 2051 compiler.resolveTypeAnnotation(element, returnNode); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2141 | 2151 |
| 2142 class Scope { | 2152 class Scope { |
| 2143 final Element element; | 2153 final Element element; |
| 2144 final Scope parent; | 2154 final Scope parent; |
| 2145 | 2155 |
| 2146 Scope(this.parent, this.element); | 2156 Scope(this.parent, this.element); |
| 2147 abstract Element add(Element element); | 2157 abstract Element add(Element element); |
| 2148 abstract Element lookup(SourceString name); | 2158 abstract Element lookup(SourceString name); |
| 2149 } | 2159 } |
| 2150 | 2160 |
| 2151 class TypeVariablesScope extends Scope { | 2161 /** |
| 2152 TypeVariablesScope(parent, ClassElement element) : super(parent, element); | 2162 * [TypeDeclarationScope] defines the outer scope of a type declaration in |
| 2163 * which the declared type variables and the entities in the enclosing scope are |
| 2164 * available but where declared and inherited members are not available. This |
| 2165 * scope is only used for class/interface declarations during resolution of the |
| 2166 * class hierarchy. In all other cases [ClassScope] is used. |
| 2167 */ |
| 2168 class TypeDeclarationScope extends Scope { |
| 2169 ClassElement get element() => super.element; |
| 2170 |
| 2171 TypeDeclarationScope(Scope parent, ClassElement element) |
| 2172 : super(parent, element); |
| 2173 |
| 2153 Element add(Element newElement) { | 2174 Element add(Element newElement) { |
| 2154 throw "Cannot add element to TypeVariableScope"; | 2175 throw "Cannot add element to TypeDeclarationScope"; |
| 2155 } | 2176 } |
| 2177 |
| 2156 Element lookup(SourceString name) { | 2178 Element lookup(SourceString name) { |
| 2157 ClassElement cls = element; | 2179 Element result = element.lookupTypeParameter(name); |
| 2158 Element result = cls.lookupTypeParameter(name); | |
| 2159 if (result !== null) return result; | 2180 if (result !== null) return result; |
| 2160 if (parent !== null) return parent.lookup(name); | 2181 if (parent !== null) return parent.lookup(name); |
| 2161 } | 2182 } |
| 2183 |
| 2184 String toString() => |
| 2185 '$element${element.typeParameters.getKeys()} > $parent'; |
| 2162 } | 2186 } |
| 2163 | 2187 |
| 2164 class MethodScope extends Scope { | 2188 class MethodScope extends Scope { |
| 2165 final Map<SourceString, Element> elements; | 2189 final Map<SourceString, Element> elements; |
| 2166 | 2190 |
| 2167 MethodScope(Scope parent, Element element) | 2191 MethodScope(Scope parent, Element element) |
| 2168 : super(parent, element), this.elements = new Map<SourceString, Element>(); | 2192 : super(parent, element), this.elements = new Map<SourceString, Element>(); |
| 2169 | 2193 |
| 2170 Element lookup(SourceString name) { | 2194 Element lookup(SourceString name) { |
| 2171 Element found = elements[name]; | 2195 Element found = elements[name]; |
| 2172 if (found !== null) return found; | 2196 if (found !== null) return found; |
| 2173 return parent.lookup(name); | 2197 return parent.lookup(name); |
| 2174 } | 2198 } |
| 2175 | 2199 |
| 2176 Element add(Element newElement) { | 2200 Element add(Element newElement) { |
| 2177 if (elements.containsKey(newElement.name)) { | 2201 if (elements.containsKey(newElement.name)) { |
| 2178 return elements[newElement.name]; | 2202 return elements[newElement.name]; |
| 2179 } | 2203 } |
| 2180 elements[newElement.name] = newElement; | 2204 elements[newElement.name] = newElement; |
| 2181 return newElement; | 2205 return newElement; |
| 2182 } | 2206 } |
| 2207 |
| 2208 String toString() => '$element${elements.getKeys()} > $parent'; |
| 2183 } | 2209 } |
| 2184 | 2210 |
| 2185 class BlockScope extends MethodScope { | 2211 class BlockScope extends MethodScope { |
| 2186 BlockScope(Scope parent) : super(parent, parent.element); | 2212 BlockScope(Scope parent) : super(parent, parent.element); |
| 2213 |
| 2214 String toString() => 'block${elements.getKeys()} > $parent'; |
| 2187 } | 2215 } |
| 2188 | 2216 |
| 2189 class ClassScope extends Scope { | 2217 /** |
| 2190 ClassScope(ClassElement element, LibraryElement library) | 2218 * [ClassScope] defines the inner scope of a class/interface declaration in |
| 2191 : super(new TopScope(library), element); | 2219 * which declared members, declared type variables, entities in the enclosing |
| 2220 * scope and inherited members are available, in the given order. |
| 2221 */ |
| 2222 class ClassScope extends TypeDeclarationScope { |
| 2223 ClassScope(Scope parentScope, ClassElement element) |
| 2224 : super(parentScope, element); |
| 2192 | 2225 |
| 2193 Element lookup(SourceString name) { | 2226 Element lookup(SourceString name) { |
| 2194 ClassElement cls = element; | 2227 ClassElement cls = element; |
| 2195 Element result = cls.lookupLocalMember(name); | 2228 Element result = cls.lookupLocalMember(name); |
| 2196 if (result !== null) return result; | 2229 if (result !== null) return result; |
| 2197 result = cls.lookupTypeParameter(name); | 2230 result = super.lookup(name); |
| 2198 if (result !== null) return result; | |
| 2199 result = parent.lookup(name); | |
| 2200 if (result != null) return result; | 2231 if (result != null) return result; |
| 2201 return cls.lookupSuperMember(name); | 2232 return cls.lookupSuperMember(name); |
| 2202 } | 2233 } |
| 2203 | 2234 |
| 2204 Element add(Element newElement) { | 2235 Element add(Element newElement) { |
| 2205 throw "Cannot add an element in a class scope"; | 2236 throw "Cannot add an element in a class scope"; |
| 2206 } | 2237 } |
| 2238 |
| 2239 String toString() => '$element > $parent'; |
| 2207 } | 2240 } |
| 2208 | 2241 |
| 2209 class TopScope extends Scope { | 2242 class TopScope extends Scope { |
| 2210 LibraryElement get library() => element; | 2243 LibraryElement get library() => element; |
| 2211 | 2244 |
| 2212 TopScope(LibraryElement library) : super(null, library); | 2245 TopScope(LibraryElement library) : super(null, library); |
| 2213 Element lookup(SourceString name) { | 2246 Element lookup(SourceString name) { |
| 2214 return library.find(name); | 2247 return library.find(name); |
| 2215 } | 2248 } |
| 2216 | 2249 |
| 2217 Element add(Element newElement) { | 2250 Element add(Element newElement) { |
| 2218 throw "Cannot add an element in the top scope"; | 2251 throw "Cannot add an element in the top scope"; |
| 2219 } | 2252 } |
| 2253 String toString() => '$element'; |
| 2220 } | 2254 } |
| OLD | NEW |