Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(519)

Side by Side Diff: lib/compiler/implementation/resolver.dart

Issue 11111017: Re-land r13557 on behalf of Alexander. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 abstract class TreeElements { 5 abstract class 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 if (kind === ElementKind.PARAMETER || 80 if (kind === ElementKind.PARAMETER ||
81 kind === ElementKind.FIELD_PARAMETER) { 81 kind === ElementKind.FIELD_PARAMETER) {
82 return resolveParameter(element); 82 return resolveParameter(element);
83 } 83 }
84 84
85 compiler.unimplemented("resolve($element)", 85 compiler.unimplemented("resolve($element)",
86 node: element.parseNode(compiler)); 86 node: element.parseNode(compiler));
87 }); 87 });
88 } 88 }
89 89
90 bool isNamedConstructor(Send node) => node.receiver !== null;
91
90 SourceString getConstructorName(Send node) { 92 SourceString getConstructorName(Send node) {
91 if (node.receiver !== null) { 93 return node.selector.asIdentifier().source;
92 return node.selector.asIdentifier().source;
93 } else {
94 return const SourceString('');
95 }
96 } 94 }
97 95
98 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { 96 String constructorNameForDiagnostics(SourceString className,
97 SourceString constructorName) {
98 String classNameString = className.slowToString();
99 String constructorNameString = constructorName.slowToString();
100 return (constructorName === const SourceString(''))
101 ? classNameString
102 : "$classNameString.$constructorNameString";
103 }
104
105 FunctionElement resolveConstructorRedirection(InitializerResolver resolver,
106 FunctionElement constructor) {
99 if (constructor.isPatched) { 107 if (constructor.isPatched) {
100 checkMatchingPatchSignatures(constructor, constructor.patch); 108 checkMatchingPatchSignatures(constructor, constructor.patch);
101 constructor = constructor.patch; 109 constructor = constructor.patch;
102 } 110 }
103 FunctionExpression node = constructor.parseNode(compiler); 111 FunctionExpression node = constructor.parseNode(compiler);
104 112
105 // A synthetic constructor does not have a node. 113 // A synthetic constructor does not have a node.
106 if (node === null) return null; 114 if (node === null) return null;
107 if (node.initializers === null) return null; 115 if (node.initializers === null) return null;
108 Link<Node> initializers = node.initializers.nodes; 116 Link<Node> initializers = node.initializers.nodes;
109 if (!initializers.isEmpty() && 117 if (!initializers.isEmpty() &&
110 Initializers.isConstructorRedirect(initializers.head)) { 118 Initializers.isConstructorRedirect(initializers.head)) {
111 final ClassElement classElement = constructor.getEnclosingClass(); 119 final ClassElement classElement = constructor.getEnclosingClass();
112 final SourceString constructorName = 120 Selector selector;
113 getConstructorName(initializers.head); 121 if (isNamedConstructor(initializers.head)) {
114 final SourceString className = classElement.name; 122 SourceString constructorName = getConstructorName(initializers.head);
115 return classElement.lookupConstructor(className, constructorName); 123 selector = new Selector.callConstructor(
124 constructorName,
125 resolver.visitor.enclosingElement.getLibrary());
126 } else {
127 selector = new Selector.callDefaultConstructor(
128 resolver.visitor.enclosingElement.getLibrary());
129 }
130 return classElement.lookupConstructor(selector);
116 } 131 }
117 return null; 132 return null;
118 } 133 }
119 134
120 void resolveRedirectingConstructor(InitializerResolver resolver, 135 void resolveRedirectingConstructor(InitializerResolver resolver,
121 Node node, 136 Node node,
122 FunctionElement constructor, 137 FunctionElement constructor,
123 FunctionElement redirection) { 138 FunctionElement redirection) {
124 Set<FunctionElement> seen = new Set<FunctionElement>(); 139 Set<FunctionElement> seen = new Set<FunctionElement>();
125 seen.add(constructor); 140 seen.add(constructor);
126 while (redirection !== null) { 141 while (redirection !== null) {
127 if (seen.contains(redirection)) { 142 if (seen.contains(redirection)) {
128 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); 143 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
129 return; 144 return;
130 } 145 }
131 seen.add(redirection); 146 seen.add(redirection);
132 redirection = resolveConstructorRedirection(redirection); 147 redirection = resolveConstructorRedirection(resolver, redirection);
133 } 148 }
134 } 149 }
135 150
136 void checkMatchingPatchParameters(FunctionElement origin, 151 void checkMatchingPatchParameters(FunctionElement origin,
137 Link<Element> originParameters, 152 Link<Element> originParameters,
138 Link<Element> patchParameters) { 153 Link<Element> patchParameters) {
139 while (!originParameters.isEmpty()) { 154 while (!originParameters.isEmpty()) {
140 Element originParameter = originParameters.head; 155 Element originParameter = originParameters.head;
141 Element patchParameter = patchParameters.head; 156 Element patchParameter = patchParameters.head;
142 // Hack: Use unparser to test parameter equality. This only works because 157 // Hack: Use unparser to test parameter equality. This only works because
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 assert(defaultClass.resolutionState == STATE_DONE); 298 assert(defaultClass.resolutionState == STATE_DONE);
284 assert(defaultClass.supertypeLoadState == STATE_DONE); 299 assert(defaultClass.supertypeLoadState == STATE_DONE);
285 if (defaultClass.isInterface()) { 300 if (defaultClass.isInterface()) {
286 error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE, 301 error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE,
287 [defaultClass.name]); 302 [defaultClass.name]);
288 } 303 }
289 // We have now established the following: 304 // We have now established the following:
290 // [intrface] is an interface, let's say "MyInterface". 305 // [intrface] is an interface, let's say "MyInterface".
291 // [defaultClass] is a class, let's say "MyClass". 306 // [defaultClass] is a class, let's say "MyClass".
292 307
308 Selector selector;
293 // If the default class implements the interface then we must use the 309 // If the default class implements the interface then we must use the
294 // default class' name. Otherwise we look for a factory with the name 310 // default class' name. Otherwise we look for a factory with the name
295 // of the interface. 311 // of the interface.
296 SourceString name;
297 if (defaultClass.implementsInterface(intrface)) { 312 if (defaultClass.implementsInterface(intrface)) {
298 // TODO(ahe): Don't use string replacement here. 313 var constructorNameString = constructor.name.slowToString();
299 name = new SourceString(constructor.name.slowToString().replaceFirst( 314 // Create selector based on constructor.name but where interface
300 intrface.name.slowToString(), 315 // is replaced with default class name.
301 defaultClass.name.slowToString())); 316 // TODO(ahe): Don't use string manipulations here.
317 int classNameSeparatorIndex = constructorNameString.indexOf('\$');
318 if (classNameSeparatorIndex < 0) {
319 selector = new Selector.callDefaultConstructor(
320 defaultClass.getLibrary());
321 } else {
322 selector = new Selector.callConstructor(
323 new SourceString(
324 constructorNameString.substring(classNameSeparatorIndex + 1)),
325 defaultClass.getLibrary());
326 }
327 constructor.defaultImplementation =
328 defaultClass.lookupConstructor(selector);
302 } else { 329 } else {
303 name = constructor.name; 330 selector =
331 new Selector.callConstructor(constructor.name,
332 defaultClass.getLibrary());
333 constructor.defaultImplementation =
334 defaultClass.lookupFactoryConstructor(selector);
304 } 335 }
305 constructor.defaultImplementation = defaultClass.lookupConstructor(name);
306
307 if (constructor.defaultImplementation === null) { 336 if (constructor.defaultImplementation === null) {
308 // We failed to find a constructor named either 337 // We failed to find a constructor named either
309 // "MyInterface.name" or "MyClass.name". 338 // "MyInterface.name" or "MyClass.name".
339 // TODO(aprelev@gmail.com): Use constructorNameForDiagnostics in
340 // the error message below.
310 error(node, 341 error(node,
311 MessageKind.CANNOT_FIND_CONSTRUCTOR2, 342 MessageKind.CANNOT_FIND_CONSTRUCTOR2,
312 [name, defaultClass.name]); 343 [selector.name, defaultClass.name]);
313 } 344 }
314 } 345 }
315 346
316 TreeElements resolveField(VariableElement element) { 347 TreeElements resolveField(VariableElement element) {
317 Node tree = element.parseNode(compiler); 348 Node tree = element.parseNode(compiler);
318 if(element.modifiers.isStatic() && element.variables.isTopLevel()) { 349 if(element.modifiers.isStatic() && element.variables.isTopLevel()) {
319 error(element.modifiers.getStatic(), MessageKind.TOP_LEVEL_VARIABLE_DECLAR ED_STATIC); 350 error(element.modifiers.getStatic(), MessageKind.TOP_LEVEL_VARIABLE_DECLAR ED_STATIC);
320 } 351 }
321 ResolverVisitor visitor = new ResolverVisitor(compiler, element); 352 ResolverVisitor visitor = new ResolverVisitor(compiler, element);
322 initializerDo(tree, visitor.visit); 353 initializerDo(tree, visitor.visit);
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 } else { 706 } else {
676 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 707 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
677 } 708 }
678 visitor.useElement(init, target); 709 visitor.useElement(init, target);
679 visitor.world.registerStaticUse(target); 710 visitor.world.registerStaticUse(target);
680 checkForDuplicateInitializers(name, init); 711 checkForDuplicateInitializers(name, init);
681 // Resolve initializing value. 712 // Resolve initializing value.
682 visitor.visitInStaticContext(init.arguments.head); 713 visitor.visitInStaticContext(init.arguments.head);
683 } 714 }
684 715
716 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
717 bool isSuperCall,
718 Node diagnosticNode) {
719 ClassElement lookupTarget = constructor.getEnclosingClass();
720 if (isSuperCall) {
721 // Calculate correct lookup target and constructor name.
722 if (lookupTarget === visitor.compiler.objectClass) {
723 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
724 } else {
725 return lookupTarget.supertype.element;
726 }
727 }
728 return lookupTarget;
729 }
730
685 Element resolveSuperOrThisForSend(FunctionElement constructor, 731 Element resolveSuperOrThisForSend(FunctionElement constructor,
686 FunctionExpression functionNode, 732 FunctionExpression functionNode,
687 Send call) { 733 Send call) {
688 // Resolve the selector and the arguments. 734 // Resolve the selector and the arguments.
689 ResolverTask resolver = visitor.compiler.resolver; 735 ResolverTask resolver = visitor.compiler.resolver;
690 visitor.inStaticContext(() { 736 visitor.inStaticContext(() {
691 visitor.resolveSelector(call); 737 visitor.resolveSelector(call);
692 visitor.resolveArguments(call.argumentsNode); 738 visitor.resolveArguments(call.argumentsNode);
693 }); 739 });
694 Selector selector = visitor.mapping.getSelector(call); 740 Selector selector = visitor.mapping.getSelector(call);
695 bool isSuperCall = Initializers.isSuperConstructorCall(call); 741 bool isSuperCall = Initializers.isSuperConstructorCall(call);
696 SourceString constructorName = resolver.getConstructorName(call); 742
697 Element result = resolveSuperOrThis( 743 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
698 constructor, isSuperCall, false, constructorName, selector, call); 744 isSuperCall,
699 visitor.useElement(call, result); 745 call);
700 visitor.world.registerStaticUse(result); 746 final SourceString className = lookupTarget.name;
701 return result; 747
748 SourceString constructorName;
749 Selector lookupSelector;
750 if (resolver.isNamedConstructor(call)) {
751 constructorName = resolver.getConstructorName(call);
752 lookupSelector = new Selector.callConstructor(
753 constructorName,
754 visitor.enclosingElement.getLibrary());
755 } else {
756 constructorName = const SourceString('');
757 lookupSelector = new Selector.callDefaultConstructor(
758 visitor.enclosingElement.getLibrary());
759 }
760
761 FunctionElement lookedupConstructor =
762 lookupTarget.lookupConstructor(lookupSelector);
763
764 final bool isImplicitSuperCall = false;
765 verifyThatConstructorMatchesCall(lookedupConstructor,
766 selector,
767 isImplicitSuperCall,
768 call,
769 constructorName,
770 className);
771
772 visitor.useElement(call, lookedupConstructor);
773 visitor.world.registerStaticUse(lookedupConstructor);
774 return lookedupConstructor;
702 } 775 }
703 776
704 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 777 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
705 FunctionExpression functionNode) { 778 FunctionExpression functionNode) {
706 // If the class has a super resolve the implicit super call. 779 // If the class has a super resolve the implicit super call.
707 ClassElement classElement = constructor.getEnclosingClass(); 780 ClassElement classElement = constructor.getEnclosingClass();
708 ClassElement superClass = classElement.superclass; 781 ClassElement superClass = classElement.superclass;
709 if (classElement != visitor.compiler.objectClass) { 782 if (classElement != visitor.compiler.objectClass) {
710 assert(superClass !== null); 783 assert(superClass !== null);
711 assert(superClass.resolutionState == STATE_DONE); 784 assert(superClass.resolutionState == STATE_DONE);
712 SourceString name = const SourceString(''); 785 SourceString constructorName = const SourceString('');
713 Selector call = new Selector.call(name, classElement.getLibrary(), 0); 786 Selector callToMatch = new Selector.call(
714 var element = resolveSuperOrThis(constructor, true, true, 787 constructorName,
715 name, call, functionNode); 788 classElement.getLibrary(),
716 visitor.world.registerStaticUse(element); 789 0);
790
791 final bool isSuperCall = true;
792 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
793 isSuperCall,
794 functionNode);
795 final SourceString className = lookupTarget.name;
796 Element calledConstructor = lookupTarget.lookupConstructor(
797 new Selector.callDefaultConstructor(
798 visitor.enclosingElement.getLibrary()));
799
800 final bool isImplicitSuperCall = true;
801 verifyThatConstructorMatchesCall(calledConstructor,
802 callToMatch,
803 isImplicitSuperCall,
804 functionNode,
805 className,
806 const SourceString(''));
807
808 visitor.world.registerStaticUse(calledConstructor);
717 } 809 }
718 } 810 }
719 811
720 Element resolveSuperOrThis(FunctionElement constructor, 812 void verifyThatConstructorMatchesCall(
721 bool isSuperCall, 813 FunctionElement lookedupConstructor,
722 bool isImplicitSuperCall, 814 Selector call,
723 SourceString constructorName, 815 bool isImplicitSuperCall,
724 Selector selector, 816 Node diagnosticNode,
725 Node diagnosticNode) { 817 SourceString className,
726 ClassElement lookupTarget = constructor.getEnclosingClass(); 818 SourceString constructorName) {
727 bool validTarget = true; 819 if (lookedupConstructor === null
728 FunctionElement result; 820 || !lookedupConstructor.isGenerativeConstructor()) {
729 if (isSuperCall) { 821 var fullConstructorName =
730 // Calculate correct lookup target and constructor name. 822 visitor.compiler.resolver.constructorNameForDiagnostics(className,
731 if (lookupTarget === visitor.compiler.objectClass) { 823 constructorName);
732 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
733 } else {
734 lookupTarget = lookupTarget.supertype.element;
735 }
736 }
737
738 // Lookup constructor and try to match it to the selector.
739 ResolverTask resolver = visitor.compiler.resolver;
740 final SourceString className = lookupTarget.name;
741 result = lookupTarget.lookupConstructor(className, constructorName);
742 if (result === null || !result.isGenerativeConstructor()) {
743 String classNameString = className.slowToString();
744 String constructorNameString = constructorName.slowToString();
745 String name = (constructorName === const SourceString(''))
746 ? classNameString
747 : "$classNameString.$constructorNameString";
748 MessageKind kind = isImplicitSuperCall 824 MessageKind kind = isImplicitSuperCall
749 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 825 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
750 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 826 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
751 error(diagnosticNode, kind, [name]); 827 error(diagnosticNode, kind, [fullConstructorName]);
752 } else { 828 } else {
753 if (!selector.applies(result, visitor.compiler)) { 829 if (!call.applies(lookedupConstructor, visitor.compiler)) {
754 MessageKind kind = isImplicitSuperCall 830 MessageKind kind = isImplicitSuperCall
755 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 831 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
756 : MessageKind.NO_MATCHING_CONSTRUCTOR; 832 : MessageKind.NO_MATCHING_CONSTRUCTOR;
757 error(diagnosticNode, kind); 833 error(diagnosticNode, kind);
758 } 834 }
759 } 835 }
760 return result;
761 } 836 }
762 837
763 FunctionElement resolveRedirection(FunctionElement constructor, 838 FunctionElement resolveRedirection(FunctionElement constructor,
764 FunctionExpression functionNode) { 839 FunctionExpression functionNode) {
765 if (functionNode.initializers === null) return null; 840 if (functionNode.initializers === null) return null;
766 Link<Node> link = functionNode.initializers.nodes; 841 Link<Node> link = functionNode.initializers.nodes;
767 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) { 842 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) {
768 return resolveSuperOrThisForSend(constructor, functionNode, link.head); 843 return resolveSuperOrThisForSend(constructor, functionNode, link.head);
769 } 844 }
770 return null; 845 return null;
(...skipping 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 if (inConstContext) { 2866 if (inConstContext) {
2792 error(diagnosticNode, kind, arguments); 2867 error(diagnosticNode, kind, arguments);
2793 } else { 2868 } else {
2794 ResolutionWarning warning = new ResolutionWarning(kind, arguments); 2869 ResolutionWarning warning = new ResolutionWarning(kind, arguments);
2795 compiler.reportWarning(diagnosticNode, warning); 2870 compiler.reportWarning(diagnosticNode, warning);
2796 return new ErroneousFunctionElement(kind, arguments, targetName, 2871 return new ErroneousFunctionElement(kind, arguments, targetName,
2797 enclosing); 2872 enclosing);
2798 } 2873 }
2799 } 2874 }
2800 2875
2876 Selector createConstructorSelector(SourceString constructorName) {
2877 return constructorName == const SourceString('')
2878 ? new Selector.callDefaultConstructor(
2879 resolver.enclosingElement.getLibrary())
2880 : new Selector.callConstructor(
2881 constructorName,
2882 resolver.enclosingElement.getLibrary());
2883 }
2884
2801 // TODO(ngeoffray): method named lookup should not report errors. 2885 // TODO(ngeoffray): method named lookup should not report errors.
2802 FunctionElement lookupConstructor(ClassElement cls, 2886 FunctionElement lookupConstructor(ClassElement cls,
2803 Node diagnosticNode, 2887 Node diagnosticNode,
2804 SourceString constructorName) { 2888 SourceString constructorName) {
2805 cls.ensureResolved(compiler); 2889 cls.ensureResolved(compiler);
2806 Element result = cls.lookupConstructor(cls.name, constructorName); 2890 Selector selector = createConstructorSelector(constructorName);
2891 Element result = cls.lookupConstructor(selector);
2807 if (result === null) { 2892 if (result === null) {
2808 String fullConstructorName = cls.name.slowToString(); 2893 String fullConstructorName =
2809 if (constructorName !== const SourceString('')) { 2894 resolver.compiler.resolver.constructorNameForDiagnostics(
2810 fullConstructorName = '$fullConstructorName' 2895 cls.name,
2811 '.${constructorName.slowToString()}'; 2896 constructorName);
2812 } 2897 return failOrReturnErroneousElement(
2813 return failOrReturnErroneousElement(cls, diagnosticNode, 2898 cls,
2814 new SourceString(fullConstructorName), 2899 diagnosticNode,
2815 MessageKind.CANNOT_FIND_CONSTRUCTOR, 2900 new SourceString(fullConstructorName),
2816 [fullConstructorName]); 2901 MessageKind.CANNOT_FIND_CONSTRUCTOR,
2902 [fullConstructorName]);
2817 } else if (inConstContext && !result.modifiers.isConst()) { 2903 } else if (inConstContext && !result.modifiers.isConst()) {
2818 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 2904 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
2819 } 2905 }
2820 return result; 2906 return result;
2821 } 2907 }
2822 2908
2823 visitNewExpression(NewExpression node) { 2909 visitNewExpression(NewExpression node) {
2824 Node selector = node.send.selector; 2910 Node selector = node.send.selector;
2825 Element e = visit(selector); 2911 Element e = visit(selector);
2826 if (!Elements.isUnresolved(e) && e.kind === ElementKind.CLASS) { 2912 if (!Elements.isUnresolved(e) && e.kind === ElementKind.CLASS) {
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
3141 return result; 3227 return result;
3142 } 3228 }
3143 Element lookup(SourceString name) => localLookup(name); 3229 Element lookup(SourceString name) => localLookup(name);
3144 Element lexicalLookup(SourceString name) => localLookup(name); 3230 Element lexicalLookup(SourceString name) => localLookup(name);
3145 3231
3146 Element add(Element newElement) { 3232 Element add(Element newElement) {
3147 throw "Cannot add an element in a patch library scope"; 3233 throw "Cannot add an element in a patch library scope";
3148 } 3234 }
3149 String toString() => 'PatchLibraryScope($origin,$patch)'; 3235 String toString() => 'PatchLibraryScope($origin,$patch)';
3150 } 3236 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698