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

Unified Diff: sdk/lib/_internal/compiler/implementation/elements/modelx.dart

Issue 14168003: Implement implicit constructors in mixin applications. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 8 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/elements/modelx.dart
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index d9753e4081b539e36c40766abc06aab2c017ad01..6b65b31ba0c45604a97f535320062cbeb90b4f7d 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -132,6 +132,8 @@ class ElementX implements Element {
bool get isSynthesized => false;
+ bool get isForwardingConstructor => false;
+
/**
* Returns the element which defines the implementation for the entity of this
* element.
@@ -270,6 +272,8 @@ class ElementX implements Element {
bool isAbstract(Compiler compiler) => modifiers.isAbstract();
bool isForeign(Compiler compiler) => getLibrary() == compiler.foreignLibrary;
+
+ FunctionElement get targetConstructor => null;
}
/**
@@ -1263,15 +1267,29 @@ class ConstructorBodyElementX extends FunctionElementX
Token position() => constructor.position();
}
+/**
+ * A constructor that is not defined in the source code but rather implied by
+ * the language semantics.
+ *
+ * This class is used to represent default constructors and forwarding
+ * constructors for mixin applications.
+ */
class SynthesizedConstructorElementX extends FunctionElementX {
+ /// The target constructor if this synthetic constructor is a forwarding
+ /// constructor in a mixin application.
+ final FunctionElement target;
+
SynthesizedConstructorElementX(Element enclosing)
- : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
- Modifiers.EMPTY, enclosing);
+ : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
+ Modifiers.EMPTY, enclosing),
+ target = null;
SynthesizedConstructorElementX.forDefault(Element enclosing,
Compiler compiler)
- : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
- Modifiers.EMPTY, enclosing) {
+ : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
+ Modifiers.EMPTY, enclosing),
+ target = null {
+ // TODO(karlklose): get rid of the fake AST.
type = new FunctionType(this,
compiler.types.voidType,
const Link<DartType>(),
@@ -1285,9 +1303,40 @@ class SynthesizedConstructorElementX extends FunctionElementX {
null, Modifiers.EMPTY, null, null);
}
- bool get isSynthesized => true;
+ /**
+ * Create synthetic constructor that directly forwards to a constructor in the
+ * super class of a mixin application.
+ *
+ * In a mixin application `Base with M`, any constructor defined in `Base` is
+ * available as if they were a constructor defined in the mixin application
+ * with the same formal parameters that calls the constructor in the super
+ * class via a `super` initializer (see Ch. 9.1 in the specification).
+ */
+ SynthesizedConstructorElementX.forwarding(SourceString name, this.target,
+ Element enclosing)
+ : super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
+ enclosing);
Token position() => enclosingElement.position();
+
+ bool get isSynthesized => true;
+
+ bool get isForwardingConstructor => target != null;
+
+ FunctionElement get targetConstructor => target;
+
+ FunctionSignature computeSignature(compiler) {
+ if (target != null) {
+ return target.computeSignature(compiler);
+ } else {
+ assert(cachedNode != null);
+ return super.computeSignature(compiler);
+ }
+ }
+
+ get declaration => this;
+ get implementation => this;
+ get defaultImplementation => this;
}
class VoidElementX extends ElementX {
@@ -1839,7 +1888,8 @@ class MixinApplicationElementX extends BaseClassElementX
final Node node;
final Modifiers modifiers;
- FunctionElement constructor;
+ Link<FunctionElement> constructors = new Link<FunctionElement>();
+
ClassElement mixin;
// TODO(kasperl): The analyzer complains when I don't have these two
@@ -1852,15 +1902,19 @@ class MixinApplicationElementX extends BaseClassElementX
: super(name, enclosing, id, STATE_NOT_STARTED);
bool get isMixinApplication => true;
- bool get hasConstructor => constructor != null;
- bool get hasLocalScopeMembers => false;
+ bool get hasConstructor => !constructors.isEmpty;
+ bool get hasLocalScopeMembers => constructors.isEmpty;
kasperl 2013/04/25 12:13:12 So it has local scope members when there are no co
karlklose 2013/05/03 09:35:45 Done.
Token position() => node.getBeginToken();
Node parseNode(DiagnosticListener listener) => node;
Element localLookup(SourceString name) {
- if (this.name == name) return constructor;
+ for (Link<Element> link = constructors;
kasperl 2013/04/25 12:13:12 Maybe add a lookup constructor for this and call i
karlklose 2013/05/03 09:35:45 Done.
+ !link.isEmpty;
+ link = link.tail) {
+ if (link.head.name == name) return link.head;
+ }
if (mixin == null) return null;
Element mixedInElement = mixin.localLookup(name);
if (mixedInElement == null) return null;
@@ -1878,12 +1932,16 @@ class MixinApplicationElementX extends BaseClassElementX
}
void addToScope(Element element, DiagnosticListener listener) {
- throw new UnsupportedError("cannot add to scope of $this");
+ if (!element.isConstructor()) {
kasperl 2013/04/25 12:13:12 Why not keep this as is and always throw?
karlklose 2013/05/03 09:35:45 Done.
+ listener.internalError('can only add constructors to mixin application '
+ 'scope, but got $element', element: this);
+ }
+ constructors = constructors.prepend(element);
}
void setDefaultConstructor(FunctionElement constructor, Compiler compiler) {
assert(!hasConstructor);
- this.constructor = constructor;
+ addToScope(constructor, compiler);
}
kasperl 2013/04/25 12:13:12 I'd add a new method for adding a constructor and
karlklose 2013/05/03 09:35:45 Done.
Link<DartType> computeTypeParameters(Compiler compiler) {

Powered by Google App Engine
This is Rietveld 408576698