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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 6f573b0463d6ed5aea15a3f04a7f5ccc10bc8f34..2733dde49c70f573fcea0ae685834526d10da7ff 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -386,7 +386,7 @@ class ResolverTask extends CompilerTask {
* Warning: do not call this method directly. It should only be
* called by [resolveClass] and [ClassSupertypeResolver].
*/
- void loadSupertypes(ClassElement cls, Node from) {
+ void loadSupertypes(ClassElement cls, Spannable from) {
compiler.withCurrentElement(cls, () => measure(() {
if (cls.supertypeLoadState == STATE_DONE) return;
if (cls.supertypeLoadState == STATE_STARTED) {
@@ -404,8 +404,8 @@ class ResolverTask extends CompilerTask {
cls.supertypeLoadState = STATE_STARTED;
compiler.withCurrentElement(cls, () {
// TODO(ahe): Cache the node in cls.
- cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler,
- cls));
+ cls.parseNode(compiler).accept(
+ new ClassSupertypeResolver(compiler, cls));
if (cls.supertypeLoadState != STATE_DONE) {
cls.supertypeLoadState = STATE_DONE;
}
@@ -418,17 +418,6 @@ class ResolverTask extends CompilerTask {
ClassElement currentlyResolvedClass;
Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
- void resolveMixinApplication(MixinApplicationElement element) {
- // TODO(kasperl): Implement this.
- assert(element.resolutionState == STATE_NOT_STARTED);
- element.resolutionState = STATE_STARTED;
- compiler.reportMessage(
- compiler.spanFromSpannable(element.cachedNode),
- MessageKind.GENERIC.error(['unimplemented mixin application']),
- Diagnostic.ERROR);
- element.resolutionState = STATE_DONE;
- }
-
/**
* Resolve the class [element].
*
@@ -465,7 +454,7 @@ class ResolverTask extends CompilerTask {
compiler.withCurrentElement(element, () => measure(() {
assert(element.resolutionState == STATE_NOT_STARTED);
element.resolutionState = STATE_STARTED;
- ClassNode tree = element.parseNode(compiler);
+ Node tree = element.parseNode(compiler);
loadSupertypes(element, tree);
ClassResolverVisitor visitor =
@@ -2748,24 +2737,8 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
// resolve this class again.
resolveTypeVariableBounds(node.typeParameters);
- // Find super type.
- DartType supertype = null;
- if (node.superclass != null) {
- supertype = typeResolver.resolveTypeAnnotation(node.superclass, scope,
- element, onFailure: error);
- }
- if (supertype != null) {
- if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
- // Error has already been reported.
- } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
- // TODO(johnniwinther): Handle dynamic.
- error(node.superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
- } else if (isBlackListed(supertype)) {
- error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
- } else {
- element.supertype = supertype;
- }
- }
+ // Resolve super type and deal with the Object class nicely.
+ element.supertype = resolveSupertype(element, node.superclass);
final objectElement = compiler.objectClass;
if (!identical(element, objectElement) && element.supertype == null) {
if (objectElement == null) {
@@ -2776,6 +2749,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
}
element.supertype = objectElement.computeType(compiler);
}
+
assert(element.interfaces == null);
Link<DartType> interfaces = const Link<DartType>();
for (Link<Node> link = node.interfaces.nodes;
@@ -2820,10 +2794,66 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
if (node.defaultClause != null) {
element.defaultClass = visit(node.defaultClause);
}
- addDefaultConstructorIfNeeded(element);
+ element.addDefaultConstructorIfNeeded(compiler);
+ return element.computeType(compiler);
+ }
+
+ DartType visitMixinApplication(MixinApplication node) {
+ compiler.ensure(element != null);
+ compiler.ensure(element.resolutionState == STATE_STARTED);
+
+ // Generate anonymous mixin application elements for the
+ // intermediate mixin applications (excluding the last).
+ DartType supertype = resolveSupertype(element, node.superclass);
+ Link<Node> link = node.mixins.nodes;
+ while (!link.tail.isEmpty) {
+ supertype = applyMixin(supertype, visit(link.head));
+ link = link.tail;
+ }
+ doApplyMixinTo(element, supertype, visit(link.head));
return element.computeType(compiler);
}
+ DartType applyMixin(DartType supertype, DartType mixinType) {
+ String superName = supertype.name.slowToString();
+ String mixinName = mixinType.name.slowToString();
+ // TODO(kasperl): This is a little bit weird. Maybe we should
+ // restructure the parsed nodes for mixin applications to better
+ // match the nesting implied by the list of mixins so that each
+ // mixin application element could get it's own proper node.
+ MixinApplication fakeTree = element.parseNode(compiler);
+ ClassElement mixinApplication = new MixinApplicationElementX(
+ new SourceString("${superName}_${mixinName}"),
ahe 2013/01/18 12:40:12 I'm really concerned about this. We did something
+ element.getCompilationUnit(),
+ compiler.getNextFreeClassId(),
+ fakeTree);
+ doApplyMixinTo(mixinApplication, supertype, mixinType);
+ mixinApplication.resolutionState = STATE_DONE;
+ mixinApplication.supertypeLoadState = STATE_DONE;
+ return mixinApplication.computeType(compiler);
+ }
+
+ void doApplyMixinTo(ClassElement mixinApplication,
+ DartType supertype,
+ DartType mixinType) {
+ assert(mixinApplication.supertype == null);
+ mixinApplication.supertype = supertype;
+
+ // The class that is the result of a mixin application implements
+ // the interface of the class that was mixed in.
+ Link<DartType> interfaces = const Link<DartType>();
+ interfaces = interfaces.prepend(mixinType);
+ assert(mixinApplication.interfaces == null);
+ mixinApplication.interfaces = interfaces;
+
+ assert(element.mixin == null);
+ mixinApplication.mixin = mixinType.element;
+ mixinApplication.mixin.ensureResolved(compiler);
+ mixinApplication.addDefaultConstructorIfNeeded(compiler);
+ calculateAllSupertypes(mixinApplication);
+ }
+
+
// TODO(johnniwinther): Remove when default class is no longer supported.
DartType visitTypeAnnotation(TypeAnnotation node) {
return visit(node.typeName);
@@ -2874,9 +2904,30 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
return e.computeType(compiler);
}
+ DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) {
+ DartType supertype;
+ if (superclass != null) {
+ supertype = typeResolver.resolveTypeAnnotation(
+ superclass, scope, cls, onFailure: error);
+ }
+ if (supertype != null) {
+ if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
+ // Error has already been reported.
+ } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
+ // TODO(johnniwinther): Handle dynamic.
+ error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
+ return null;
+ } else if (isBlackListed(supertype)) {
+ error(superclass, MessageKind.CANNOT_EXTEND, [supertype]);
+ return null;
+ }
+ }
+ return supertype;
+ }
+
void calculateAllSupertypes(ClassElement cls) {
- // TODO(karlklose): check if type arguments match, if a classelement occurs
- // more than once in the supertypes.
+ // TODO(karlklose): Check if type arguments match, if a class
+ // element occurs more than once in the supertypes.
if (cls.allSupertypes != null) return;
final DartType supertype = cls.supertype;
if (supertype != null) {
@@ -2914,17 +2965,6 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
}
}
- /**
- * Add a synthetic nullary constructor if there are no other
- * constructors.
- */
- void addDefaultConstructorIfNeeded(ClassElement element) {
- if (element.hasConstructor) return;
- FunctionElement constructor =
- new SynthesizedConstructorElementX.forDefault(element, compiler);
- element.addToScope(constructor, compiler);
- }
-
isBlackListed(DartType type) {
LibraryElement lib = element.getLibrary();
return
@@ -2956,6 +2996,12 @@ class ClassSupertypeResolver extends CommonResolverVisitor {
element.ensureResolved(compiler);
}
+ void visitNodeList(NodeList node) {
+ for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
+ link.head.accept(this);
+ }
+ }
+
void visitClassNode(ClassNode node) {
if (node.superclass == null) {
if (!identical(classElement, compiler.objectClass)) {
@@ -2964,11 +3010,12 @@ class ClassSupertypeResolver extends CommonResolverVisitor {
} else {
node.superclass.accept(this);
}
- for (Link<Node> link = node.interfaces.nodes;
- !link.isEmpty;
- link = link.tail) {
- link.head.accept(this);
- }
+ visitNodeList(node.interfaces);
ahe 2013/01/18 12:40:12 Generally, I don't like calling the visitor method
+ }
+
+ void visitMixinApplication(MixinApplication node) {
+ node.superclass.accept(this);
+ visitNodeList(node.mixins);
ahe 2013/01/18 12:40:12 Ditto.
}
void visitTypeAnnotation(TypeAnnotation node) {

Powered by Google App Engine
This is Rietveld 408576698