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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/resolution/members.dart

Issue 11886097: Get the most basic mixin applications working. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix checked mode. Created 7 years, 11 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 part of resolution; 5 part of resolution;
6 6
7 abstract class TreeElements { 7 abstract class TreeElements {
8 Element operator[](Node node); 8 Element operator[](Node node);
9 Selector getSelector(Send send); 9 Selector getSelector(Send send);
10 DartType getType(Node node); 10 DartType getType(Node node);
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 } 379 }
380 return result; 380 return result;
381 } 381 }
382 382
383 /** 383 /**
384 * Load and resolve the supertypes of [cls]. 384 * Load and resolve the supertypes of [cls].
385 * 385 *
386 * Warning: do not call this method directly. It should only be 386 * Warning: do not call this method directly. It should only be
387 * called by [resolveClass] and [ClassSupertypeResolver]. 387 * called by [resolveClass] and [ClassSupertypeResolver].
388 */ 388 */
389 void loadSupertypes(ClassElement cls, Node from) { 389 void loadSupertypes(ClassElement cls, Spannable from) {
390 compiler.withCurrentElement(cls, () => measure(() { 390 compiler.withCurrentElement(cls, () => measure(() {
391 if (cls.supertypeLoadState == STATE_DONE) return; 391 if (cls.supertypeLoadState == STATE_DONE) return;
392 if (cls.supertypeLoadState == STATE_STARTED) { 392 if (cls.supertypeLoadState == STATE_STARTED) {
393 compiler.reportMessage( 393 compiler.reportMessage(
394 compiler.spanFromSpannable(from), 394 compiler.spanFromSpannable(from),
395 MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]), 395 MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]),
396 Diagnostic.ERROR); 396 Diagnostic.ERROR);
397 cls.supertypeLoadState = STATE_DONE; 397 cls.supertypeLoadState = STATE_DONE;
398 cls.allSupertypes = const Link<DartType>().prepend( 398 cls.allSupertypes = const Link<DartType>().prepend(
399 compiler.objectClass.computeType(compiler)); 399 compiler.objectClass.computeType(compiler));
400 // TODO(ahe): We should also set cls.supertype here to avoid 400 // TODO(ahe): We should also set cls.supertype here to avoid
401 // creating a malformed class hierarchy. 401 // creating a malformed class hierarchy.
402 return; 402 return;
403 } 403 }
404 cls.supertypeLoadState = STATE_STARTED; 404 cls.supertypeLoadState = STATE_STARTED;
405 compiler.withCurrentElement(cls, () { 405 compiler.withCurrentElement(cls, () {
406 // TODO(ahe): Cache the node in cls. 406 // TODO(ahe): Cache the node in cls.
407 cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler, 407 cls.parseNode(compiler).accept(
408 cls)); 408 new ClassSupertypeResolver(compiler, cls));
409 if (cls.supertypeLoadState != STATE_DONE) { 409 if (cls.supertypeLoadState != STATE_DONE) {
410 cls.supertypeLoadState = STATE_DONE; 410 cls.supertypeLoadState = STATE_DONE;
411 } 411 }
412 }); 412 });
413 })); 413 }));
414 } 414 }
415 415
416 // TODO(johnniwinther): Remove this queue when resolution has been split into 416 // TODO(johnniwinther): Remove this queue when resolution has been split into
417 // syntax and semantic resolution. 417 // syntax and semantic resolution.
418 ClassElement currentlyResolvedClass; 418 ClassElement currentlyResolvedClass;
419 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); 419 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
420 420
421 void resolveMixinApplication(MixinApplicationElement element) {
422 // TODO(kasperl): Implement this.
423 assert(element.resolutionState == STATE_NOT_STARTED);
424 element.resolutionState = STATE_STARTED;
425 compiler.reportMessage(
426 compiler.spanFromSpannable(element.cachedNode),
427 MessageKind.GENERIC.error(['unimplemented mixin application']),
428 Diagnostic.ERROR);
429 element.resolutionState = STATE_DONE;
430 }
431
432 /** 421 /**
433 * Resolve the class [element]. 422 * Resolve the class [element].
434 * 423 *
435 * Before calling this method, [element] was constructed by the 424 * Before calling this method, [element] was constructed by the
436 * scanner and most fields are null or empty. This method fills in 425 * scanner and most fields are null or empty. This method fills in
437 * these fields and also ensure that the supertypes of [element] are 426 * these fields and also ensure that the supertypes of [element] are
438 * resolved. 427 * resolved.
439 * 428 *
440 * Warning: Do not call this method directly. Instead use 429 * Warning: Do not call this method directly. Instead use
441 * [:element.ensureResolved(compiler):]. 430 * [:element.ensureResolved(compiler):].
(...skipping 16 matching lines...) Expand all
458 } else { 447 } else {
459 pendingClassesToBeResolved.add(element); 448 pendingClassesToBeResolved.add(element);
460 } 449 }
461 } 450 }
462 451
463 void resolveClassInternal(ClassElement element) { 452 void resolveClassInternal(ClassElement element) {
464 if (!element.isPatch) { 453 if (!element.isPatch) {
465 compiler.withCurrentElement(element, () => measure(() { 454 compiler.withCurrentElement(element, () => measure(() {
466 assert(element.resolutionState == STATE_NOT_STARTED); 455 assert(element.resolutionState == STATE_NOT_STARTED);
467 element.resolutionState = STATE_STARTED; 456 element.resolutionState = STATE_STARTED;
468 ClassNode tree = element.parseNode(compiler); 457 Node tree = element.parseNode(compiler);
469 loadSupertypes(element, tree); 458 loadSupertypes(element, tree);
470 459
471 ClassResolverVisitor visitor = 460 ClassResolverVisitor visitor =
472 new ClassResolverVisitor(compiler, element); 461 new ClassResolverVisitor(compiler, element);
473 visitor.visit(tree); 462 visitor.visit(tree);
474 element.resolutionState = STATE_DONE; 463 element.resolutionState = STATE_DONE;
475 })); 464 }));
476 if (element.isPatched) { 465 if (element.isPatched) {
477 // Ensure handling patch after origin. 466 // Ensure handling patch after origin.
478 element.patch.ensureResolved(compiler); 467 element.patch.ensureResolved(compiler);
(...skipping 2262 matching lines...) Expand 10 before | Expand all | Expand 10 after
2741 compiler.ensure(element != null); 2730 compiler.ensure(element != null);
2742 compiler.ensure(element.resolutionState == STATE_STARTED); 2731 compiler.ensure(element.resolutionState == STATE_STARTED);
2743 2732
2744 InterfaceType type = element.computeType(compiler); 2733 InterfaceType type = element.computeType(compiler);
2745 scope = new TypeDeclarationScope(scope, element); 2734 scope = new TypeDeclarationScope(scope, element);
2746 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. 2735 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet.
2747 // As a side-effect, this may get us back here trying to 2736 // As a side-effect, this may get us back here trying to
2748 // resolve this class again. 2737 // resolve this class again.
2749 resolveTypeVariableBounds(node.typeParameters); 2738 resolveTypeVariableBounds(node.typeParameters);
2750 2739
2751 // Find super type. 2740 // Resolve super type and deal with the Object class nicely.
2752 DartType supertype = null; 2741 element.supertype = resolveSupertype(element, node.superclass);
2753 if (node.superclass != null) {
2754 supertype = typeResolver.resolveTypeAnnotation(node.superclass, scope,
2755 element, onFailure: error);
2756 }
2757 if (supertype != null) {
2758 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
2759 // Error has already been reported.
2760 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
2761 // TODO(johnniwinther): Handle dynamic.
2762 error(node.superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
2763 } else if (isBlackListed(supertype)) {
2764 error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
2765 } else {
2766 element.supertype = supertype;
2767 }
2768 }
2769 final objectElement = compiler.objectClass; 2742 final objectElement = compiler.objectClass;
2770 if (!identical(element, objectElement) && element.supertype == null) { 2743 if (!identical(element, objectElement) && element.supertype == null) {
2771 if (objectElement == null) { 2744 if (objectElement == null) {
2772 compiler.internalError("Internal error: cannot resolve Object", 2745 compiler.internalError("Internal error: cannot resolve Object",
2773 node: node); 2746 node: node);
2774 } else { 2747 } else {
2775 objectElement.ensureResolved(compiler); 2748 objectElement.ensureResolved(compiler);
2776 } 2749 }
2777 element.supertype = objectElement.computeType(compiler); 2750 element.supertype = objectElement.computeType(compiler);
2778 } 2751 }
2752
2779 assert(element.interfaces == null); 2753 assert(element.interfaces == null);
2780 Link<DartType> interfaces = const Link<DartType>(); 2754 Link<DartType> interfaces = const Link<DartType>();
2781 for (Link<Node> link = node.interfaces.nodes; 2755 for (Link<Node> link = node.interfaces.nodes;
2782 !link.isEmpty; 2756 !link.isEmpty;
2783 link = link.tail) { 2757 link = link.tail) {
2784 DartType interfaceType = typeResolver.resolveTypeAnnotation( 2758 DartType interfaceType = typeResolver.resolveTypeAnnotation(
2785 link.head, scope, element, onFailure: error); 2759 link.head, scope, element, onFailure: error);
2786 if (interfaceType != null) { 2760 if (interfaceType != null) {
2787 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { 2761 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) {
2788 // Error has already been reported. 2762 // Error has already been reported.
(...skipping 24 matching lines...) Expand all
2813 } 2787 }
2814 } 2788 }
2815 } 2789 }
2816 } 2790 }
2817 element.interfaces = interfaces; 2791 element.interfaces = interfaces;
2818 calculateAllSupertypes(element); 2792 calculateAllSupertypes(element);
2819 2793
2820 if (node.defaultClause != null) { 2794 if (node.defaultClause != null) {
2821 element.defaultClass = visit(node.defaultClause); 2795 element.defaultClass = visit(node.defaultClause);
2822 } 2796 }
2823 addDefaultConstructorIfNeeded(element); 2797 element.addDefaultConstructorIfNeeded(compiler);
2824 return element.computeType(compiler); 2798 return element.computeType(compiler);
2825 } 2799 }
2826 2800
2801 DartType visitMixinApplication(MixinApplication node) {
2802 compiler.ensure(element != null);
2803 compiler.ensure(element.resolutionState == STATE_STARTED);
2804
2805 // Generate anonymous mixin application elements for the
2806 // intermediate mixin applications (excluding the last).
2807 DartType supertype = resolveSupertype(element, node.superclass);
2808 Link<Node> link = node.mixins.nodes;
2809 while (!link.tail.isEmpty) {
2810 supertype = applyMixin(supertype, visit(link.head));
2811 link = link.tail;
2812 }
2813 doApplyMixinTo(element, supertype, visit(link.head));
2814 return element.computeType(compiler);
2815 }
2816
2817 DartType applyMixin(DartType supertype, DartType mixinType) {
2818 String superName = supertype.name.slowToString();
2819 String mixinName = mixinType.name.slowToString();
2820 // TODO(kasperl): This is a little bit weird. Maybe we should
2821 // restructure the parsed nodes for mixin applications to better
2822 // match the nesting implied by the list of mixins so that each
2823 // mixin application element could get it's own proper node.
2824 MixinApplication fakeTree = element.parseNode(compiler);
2825 ClassElement mixinApplication = new MixinApplicationElementX(
2826 new SourceString("${superName}_${mixinName}"),
ahe 2013/01/18 12:40:12 I'm really concerned about this. We did something
2827 element.getCompilationUnit(),
2828 compiler.getNextFreeClassId(),
2829 fakeTree);
2830 doApplyMixinTo(mixinApplication, supertype, mixinType);
2831 mixinApplication.resolutionState = STATE_DONE;
2832 mixinApplication.supertypeLoadState = STATE_DONE;
2833 return mixinApplication.computeType(compiler);
2834 }
2835
2836 void doApplyMixinTo(ClassElement mixinApplication,
2837 DartType supertype,
2838 DartType mixinType) {
2839 assert(mixinApplication.supertype == null);
2840 mixinApplication.supertype = supertype;
2841
2842 // The class that is the result of a mixin application implements
2843 // the interface of the class that was mixed in.
2844 Link<DartType> interfaces = const Link<DartType>();
2845 interfaces = interfaces.prepend(mixinType);
2846 assert(mixinApplication.interfaces == null);
2847 mixinApplication.interfaces = interfaces;
2848
2849 assert(element.mixin == null);
2850 mixinApplication.mixin = mixinType.element;
2851 mixinApplication.mixin.ensureResolved(compiler);
2852 mixinApplication.addDefaultConstructorIfNeeded(compiler);
2853 calculateAllSupertypes(mixinApplication);
2854 }
2855
2856
2827 // TODO(johnniwinther): Remove when default class is no longer supported. 2857 // TODO(johnniwinther): Remove when default class is no longer supported.
2828 DartType visitTypeAnnotation(TypeAnnotation node) { 2858 DartType visitTypeAnnotation(TypeAnnotation node) {
2829 return visit(node.typeName); 2859 return visit(node.typeName);
2830 } 2860 }
2831 2861
2832 // TODO(johnniwinther): Remove when default class is no longer supported. 2862 // TODO(johnniwinther): Remove when default class is no longer supported.
2833 DartType visitIdentifier(Identifier node) { 2863 DartType visitIdentifier(Identifier node) {
2834 Element element = scope.lookup(node.source); 2864 Element element = scope.lookup(node.source);
2835 if (element == null) { 2865 if (element == null) {
2836 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); 2866 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
(...skipping 30 matching lines...) Expand all
2867 PrefixElement prefixElement = element; 2897 PrefixElement prefixElement = element;
2868 Identifier selector = node.selector.asIdentifier(); 2898 Identifier selector = node.selector.asIdentifier();
2869 var e = prefixElement.lookupLocalMember(selector.source); 2899 var e = prefixElement.lookupLocalMember(selector.source);
2870 if (e == null || !e.impliesType()) { 2900 if (e == null || !e.impliesType()) {
2871 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]); 2901 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
2872 return null; 2902 return null;
2873 } 2903 }
2874 return e.computeType(compiler); 2904 return e.computeType(compiler);
2875 } 2905 }
2876 2906
2907 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) {
2908 DartType supertype;
2909 if (superclass != null) {
2910 supertype = typeResolver.resolveTypeAnnotation(
2911 superclass, scope, cls, onFailure: error);
2912 }
2913 if (supertype != null) {
2914 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
2915 // Error has already been reported.
2916 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
2917 // TODO(johnniwinther): Handle dynamic.
2918 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
2919 return null;
2920 } else if (isBlackListed(supertype)) {
2921 error(superclass, MessageKind.CANNOT_EXTEND, [supertype]);
2922 return null;
2923 }
2924 }
2925 return supertype;
2926 }
2927
2877 void calculateAllSupertypes(ClassElement cls) { 2928 void calculateAllSupertypes(ClassElement cls) {
2878 // TODO(karlklose): check if type arguments match, if a classelement occurs 2929 // TODO(karlklose): Check if type arguments match, if a class
2879 // more than once in the supertypes. 2930 // element occurs more than once in the supertypes.
2880 if (cls.allSupertypes != null) return; 2931 if (cls.allSupertypes != null) return;
2881 final DartType supertype = cls.supertype; 2932 final DartType supertype = cls.supertype;
2882 if (supertype != null) { 2933 if (supertype != null) {
2883 var allSupertypes = new LinkBuilder<DartType>(); 2934 var allSupertypes = new LinkBuilder<DartType>();
2884 addAllSupertypes(allSupertypes, supertype); 2935 addAllSupertypes(allSupertypes, supertype);
2885 for (Link<DartType> interfaces = cls.interfaces; 2936 for (Link<DartType> interfaces = cls.interfaces;
2886 !interfaces.isEmpty; 2937 !interfaces.isEmpty;
2887 interfaces = interfaces.tail) { 2938 interfaces = interfaces.tail) {
2888 addAllSupertypes(allSupertypes, interfaces.head); 2939 addAllSupertypes(allSupertypes, interfaces.head);
2889 } 2940 }
(...skipping 17 matching lines...) Expand all
2907 assert(invariant(element, supertypes != null, 2958 assert(invariant(element, supertypes != null,
2908 message: "Supertypes not computed on $classElement " 2959 message: "Supertypes not computed on $classElement "
2909 "during resolution of $element")); 2960 "during resolution of $element"));
2910 while (!supertypes.isEmpty) { 2961 while (!supertypes.isEmpty) {
2911 DartType supertype = supertypes.head; 2962 DartType supertype = supertypes.head;
2912 builder.addLast(supertype.subst(typeArguments, typeVariables)); 2963 builder.addLast(supertype.subst(typeArguments, typeVariables));
2913 supertypes = supertypes.tail; 2964 supertypes = supertypes.tail;
2914 } 2965 }
2915 } 2966 }
2916 2967
2917 /**
2918 * Add a synthetic nullary constructor if there are no other
2919 * constructors.
2920 */
2921 void addDefaultConstructorIfNeeded(ClassElement element) {
2922 if (element.hasConstructor) return;
2923 FunctionElement constructor =
2924 new SynthesizedConstructorElementX.forDefault(element, compiler);
2925 element.addToScope(constructor, compiler);
2926 }
2927
2928 isBlackListed(DartType type) { 2968 isBlackListed(DartType type) {
2929 LibraryElement lib = element.getLibrary(); 2969 LibraryElement lib = element.getLibrary();
2930 return 2970 return
2931 !identical(lib, compiler.coreLibrary) && 2971 !identical(lib, compiler.coreLibrary) &&
2932 !identical(lib, compiler.jsHelperLibrary) && 2972 !identical(lib, compiler.jsHelperLibrary) &&
2933 !identical(lib, compiler.interceptorsLibrary) && 2973 !identical(lib, compiler.interceptorsLibrary) &&
2934 (identical(type.element, compiler.dynamicClass) || 2974 (identical(type.element, compiler.dynamicClass) ||
2935 identical(type.element, compiler.boolClass) || 2975 identical(type.element, compiler.boolClass) ||
2936 identical(type.element, compiler.numClass) || 2976 identical(type.element, compiler.numClass) ||
2937 identical(type.element, compiler.intClass) || 2977 identical(type.element, compiler.intClass) ||
(...skipping 11 matching lines...) Expand all
2949 ClassSupertypeResolver(Compiler compiler, ClassElement cls) 2989 ClassSupertypeResolver(Compiler compiler, ClassElement cls)
2950 : context = Scope.buildEnclosingScope(cls), 2990 : context = Scope.buildEnclosingScope(cls),
2951 this.classElement = cls, 2991 this.classElement = cls,
2952 super(compiler); 2992 super(compiler);
2953 2993
2954 void loadSupertype(ClassElement element, Node from) { 2994 void loadSupertype(ClassElement element, Node from) {
2955 compiler.resolver.loadSupertypes(element, from); 2995 compiler.resolver.loadSupertypes(element, from);
2956 element.ensureResolved(compiler); 2996 element.ensureResolved(compiler);
2957 } 2997 }
2958 2998
2999 void visitNodeList(NodeList node) {
3000 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
3001 link.head.accept(this);
3002 }
3003 }
3004
2959 void visitClassNode(ClassNode node) { 3005 void visitClassNode(ClassNode node) {
2960 if (node.superclass == null) { 3006 if (node.superclass == null) {
2961 if (!identical(classElement, compiler.objectClass)) { 3007 if (!identical(classElement, compiler.objectClass)) {
2962 loadSupertype(compiler.objectClass, node); 3008 loadSupertype(compiler.objectClass, node);
2963 } 3009 }
2964 } else { 3010 } else {
2965 node.superclass.accept(this); 3011 node.superclass.accept(this);
2966 } 3012 }
2967 for (Link<Node> link = node.interfaces.nodes; 3013 visitNodeList(node.interfaces);
ahe 2013/01/18 12:40:12 Generally, I don't like calling the visitor method
2968 !link.isEmpty; 3014 }
2969 link = link.tail) { 3015
2970 link.head.accept(this); 3016 void visitMixinApplication(MixinApplication node) {
2971 } 3017 node.superclass.accept(this);
3018 visitNodeList(node.mixins);
ahe 2013/01/18 12:40:12 Ditto.
2972 } 3019 }
2973 3020
2974 void visitTypeAnnotation(TypeAnnotation node) { 3021 void visitTypeAnnotation(TypeAnnotation node) {
2975 node.typeName.accept(this); 3022 node.typeName.accept(this);
2976 } 3023 }
2977 3024
2978 void visitIdentifier(Identifier node) { 3025 void visitIdentifier(Identifier node) {
2979 Element element = context.lookup(node.source); 3026 Element element = context.lookup(node.source);
2980 if (element == null) { 3027 if (element == null) {
2981 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); 3028 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
3414 return e; 3461 return e;
3415 } 3462 }
3416 3463
3417 /// Assumed to be called by [resolveRedirectingFactory]. 3464 /// Assumed to be called by [resolveRedirectingFactory].
3418 Element visitReturn(Return node) { 3465 Element visitReturn(Return node) {
3419 Node expression = node.expression; 3466 Node expression = node.expression;
3420 return finishConstructorReference(visit(expression), 3467 return finishConstructorReference(visit(expression),
3421 expression, expression); 3468 expression, expression);
3422 } 3469 }
3423 } 3470 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698