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

Unified Diff: runtime/vm/parser.cc

Issue 19023005: Implement forwarding constructors for mixins (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 24971)
+++ runtime/vm/parser.cc (working copy)
@@ -1813,7 +1813,8 @@
void Parser::GenerateSuperConstructorCall(const Class& cls,
- LocalVariable* receiver) {
+ LocalVariable* receiver,
+ ArgumentListNode* forwarding_args) {
const intptr_t supercall_pos = TokenPos();
const Class& super_class = Class::Handle(cls.SuperClass());
// Omit the implicit super() if there is no super class (i.e.
@@ -1824,8 +1825,9 @@
Class::Handle(super_class.SuperClass()).IsObjectClass())) {
return;
}
- String& ctor_name = String::Handle(super_class.Name());
- ctor_name = String::Concat(ctor_name, Symbols::Dot());
+ String& super_ctor_name = String::Handle(super_class.Name());
+ super_ctor_name = String::Concat(super_ctor_name, Symbols::Dot());
+
ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
// Implicit 'this' parameter is the first argument.
AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
@@ -1835,8 +1837,27 @@
new LiteralNode(supercall_pos,
Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)));
arguments->Add(phase_parameter);
+
+ // If this is a super call in a forwarding constructor, add the user-
+ // defined arguments to the super call and adjust the the super
+ // constructor name to the respective named constructor if necessary.
+ if (forwarding_args != NULL) {
+ for (int i = 0; i < forwarding_args->length(); i++) {
+ arguments->Add(forwarding_args->NodeAt(i));
+ }
+ String& ctor_name = String::Handle(current_function().name());
+ String& class_name = String::Handle(cls.Name());
+ if (ctor_name.Length() > class_name.Length() + 1) {
+ // Generating a forwarding call to a named constructor 'C.n'.
+ // Add the constructor name 'n' to the super constructor.
+ ctor_name = String::SubString(ctor_name, class_name.Length() + 1);
+ super_ctor_name = String::Concat(super_ctor_name, ctor_name);
+ }
+ }
+
+ // Resolve super constructor function and check arguments.
const Function& super_ctor = Function::ZoneHandle(
- super_class.LookupConstructor(ctor_name));
+ super_class.LookupConstructor(super_ctor_name));
if (super_ctor.IsNull()) {
ErrorMsg(supercall_pos,
"unresolved implicit call to super constructor '%s()'",
@@ -2129,7 +2150,7 @@
if (!super_init_seen) {
// Generate implicit super() if we haven't seen an explicit super call
// or constructor redirection.
- GenerateSuperConstructorCall(cls, receiver);
+ GenerateSuperConstructorCall(cls, receiver, NULL);
}
CheckConstFieldsInitialized(cls);
}
@@ -2190,6 +2211,7 @@
const intptr_t ctor_pos = TokenPos();
OpenFunctionBlock(func);
const Class& cls = Class::Handle(func.Owner());
+
LocalVariable* receiver = new LocalVariable(
ctor_pos,
Symbols::This(),
@@ -2210,7 +2232,39 @@
ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
receiver->set_invisible(false);
- GenerateSuperConstructorCall(cls, receiver);
+ // If the class of this implicit constructor is a mixin application class,
+ // it is a forwarding constructor of the mixin. The forwarding
+ // constructor initializes the instance fields that have initializer
+ // expressions and then calls the respective super constructor with
+ // the same name and number of parameters.
+ ArgumentListNode* forwarding_args = NULL;
+ if (cls.mixin() != Type::null()) {
+ // At this point we don't support forwarding constructors
+ // that have optional parameters because we don't know the default
+ // values of the optional parameters. We would have to compile the super
+ // constructor to get the default values. Also, the spec is not clear
+ // whether optional parameters are even allowed in this situation.
+ // TODO(hausner): Remove this limitation if the language spec indeed
+ // allows optional parameters.
+ if (func.HasOptionalParameters()) {
+ ErrorMsg(ctor_pos,
+ "forwarding constructors must not have optional parameters");
+ }
+
+ // Prepare user-defined arguments to be forwarded to super call.
+ // The first user-defined argument is at position 2.
+ forwarding_args = new ArgumentListNode(ctor_pos);
+ for (int i = 2; i < func.NumParameters(); i++) {
+ LocalVariable* param = new LocalVariable(
+ ctor_pos,
+ String::ZoneHandle(func.ParameterNameAt(i)),
+ Type::ZoneHandle(Type::DynamicType()));
+ current_block_->scope->AddVariable(param);
+ forwarding_args->Add(new LoadLocalNode(ctor_pos, param));
+ }
+ }
+
+ GenerateSuperConstructorCall(cls, receiver, forwarding_args);
CheckConstFieldsInitialized(cls);
// Empty constructor body.
@@ -2856,7 +2910,7 @@
// Only constructors can redirect to another method.
ASSERT((method->redirect_name == NULL) || method->IsConstructor());
- intptr_t method_end_pos = method_pos;
+ intptr_t method_end_pos = TokenPos();
if ((CurrentToken() == Token::kLBRACE) ||
(CurrentToken() == Token::kARROW)) {
if (method->has_abstract) {
@@ -3571,7 +3625,8 @@
ctor_name = String::Concat(ctor_name, Symbols::Dot());
ctor_name = Symbols::New(ctor_name);
// To indicate that this is an implicit constructor, we set the
- // token position is the same as the token position of the class.
+ // token position and end token position of the function
+ // to the token position of the class.
Function& ctor = Function::Handle(
Function::New(ctor_name,
RawFunction::kConstructor,
@@ -3581,6 +3636,8 @@
/* is_external = */ false,
cls,
cls.token_pos()));
+ ctor.set_end_token_pos(ctor.token_pos());
+
ParamList params;
// Add implicit 'this' parameter. We don't care about the specific type
// and just specify dynamic.
@@ -4094,7 +4151,7 @@
mixin_application.set_mixin(Type::Cast(mixin_type));
mixin_application.set_library(library_);
mixin_application.set_is_synthesized_class();
- AddImplicitConstructor(mixin_application);
+
// Add the mixin type to the interfaces that the mixin application
// class implements. This is necessary so that type tests work.
mixin_application_interfaces = Array::New(1);
@@ -4826,7 +4883,7 @@
params->has_optional_named_parameters));
if (!Utils::IsInt(16, params->num_fixed_parameters) ||
!Utils::IsInt(16, params->num_optional_parameters)) {
- ErrorMsg("too many formal parameters");
+ ErrorMsg(func.token_pos(), "too many formal parameters");
}
func.set_num_fixed_parameters(params->num_fixed_parameters);
func.SetNumOptionalParameters(params->num_optional_parameters,

Powered by Google App Engine
This is Rietveld 408576698