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

Side by Side 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 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 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after
1806 // No function or field exists of the specified field_name. 1806 // No function or field exists of the specified field_name.
1807 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called. 1807 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called.
1808 } 1808 }
1809 } 1809 }
1810 return new StaticGetterNode( 1810 return new StaticGetterNode(
1811 field_pos, implicit_argument, true, super_class, field_name); 1811 field_pos, implicit_argument, true, super_class, field_name);
1812 } 1812 }
1813 1813
1814 1814
1815 void Parser::GenerateSuperConstructorCall(const Class& cls, 1815 void Parser::GenerateSuperConstructorCall(const Class& cls,
1816 LocalVariable* receiver) { 1816 LocalVariable* receiver,
1817 ArgumentListNode* forwarding_args) {
1817 const intptr_t supercall_pos = TokenPos(); 1818 const intptr_t supercall_pos = TokenPos();
1818 const Class& super_class = Class::Handle(cls.SuperClass()); 1819 const Class& super_class = Class::Handle(cls.SuperClass());
1819 // Omit the implicit super() if there is no super class (i.e. 1820 // Omit the implicit super() if there is no super class (i.e.
1820 // we're not compiling class Object), or if the super class is an 1821 // we're not compiling class Object), or if the super class is an
1821 // artificially generated "wrapper class" that has no constructor. 1822 // artificially generated "wrapper class" that has no constructor.
1822 if (super_class.IsNull() || 1823 if (super_class.IsNull() ||
1823 (super_class.num_native_fields() > 0 && 1824 (super_class.num_native_fields() > 0 &&
1824 Class::Handle(super_class.SuperClass()).IsObjectClass())) { 1825 Class::Handle(super_class.SuperClass()).IsObjectClass())) {
1825 return; 1826 return;
1826 } 1827 }
1827 String& ctor_name = String::Handle(super_class.Name()); 1828 String& super_ctor_name = String::Handle(super_class.Name());
1828 ctor_name = String::Concat(ctor_name, Symbols::Dot()); 1829 super_ctor_name = String::Concat(super_ctor_name, Symbols::Dot());
1830
1829 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); 1831 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
1830 // Implicit 'this' parameter is the first argument. 1832 // Implicit 'this' parameter is the first argument.
1831 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); 1833 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
1832 arguments->Add(implicit_argument); 1834 arguments->Add(implicit_argument);
1833 // Implicit construction phase parameter is second argument. 1835 // Implicit construction phase parameter is second argument.
1834 AstNode* phase_parameter = 1836 AstNode* phase_parameter =
1835 new LiteralNode(supercall_pos, 1837 new LiteralNode(supercall_pos,
1836 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); 1838 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)));
1837 arguments->Add(phase_parameter); 1839 arguments->Add(phase_parameter);
1840
1841 // If this is a super call in a forwarding constructor, add the user-
1842 // defined arguments to the super call and adjust the the super
1843 // constructor name to the respective named constructor if necessary.
1844 if (forwarding_args != NULL) {
1845 for (int i = 0; i < forwarding_args->length(); i++) {
1846 arguments->Add(forwarding_args->NodeAt(i));
1847 }
1848 String& ctor_name = String::Handle(current_function().name());
1849 String& class_name = String::Handle(cls.Name());
1850 if (ctor_name.Length() > class_name.Length() + 1) {
1851 // Generating a forwarding call to a named constructor 'C.n'.
1852 // Add the constructor name 'n' to the super constructor.
1853 ctor_name = String::SubString(ctor_name, class_name.Length() + 1);
1854 super_ctor_name = String::Concat(super_ctor_name, ctor_name);
1855 }
1856 }
1857
1858 // Resolve super constructor function and check arguments.
1838 const Function& super_ctor = Function::ZoneHandle( 1859 const Function& super_ctor = Function::ZoneHandle(
1839 super_class.LookupConstructor(ctor_name)); 1860 super_class.LookupConstructor(super_ctor_name));
1840 if (super_ctor.IsNull()) { 1861 if (super_ctor.IsNull()) {
1841 ErrorMsg(supercall_pos, 1862 ErrorMsg(supercall_pos,
1842 "unresolved implicit call to super constructor '%s()'", 1863 "unresolved implicit call to super constructor '%s()'",
1843 String::Handle(super_class.Name()).ToCString()); 1864 String::Handle(super_class.Name()).ToCString());
1844 } 1865 }
1845 if (current_function().is_const() && !super_ctor.is_const()) { 1866 if (current_function().is_const() && !super_ctor.is_const()) {
1846 ErrorMsg(supercall_pos, "implicit call to non-const super constructor"); 1867 ErrorMsg(supercall_pos, "implicit call to non-const super constructor");
1847 } 1868 }
1848 1869
1849 String& error_message = String::Handle(); 1870 String& error_message = String::Handle();
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
2122 super_init_seen = true; 2143 super_init_seen = true;
2123 } else { 2144 } else {
2124 init_statement = ParseInitializer(cls, receiver, initialized_fields); 2145 init_statement = ParseInitializer(cls, receiver, initialized_fields);
2125 } 2146 }
2126 current_block_->statements->Add(init_statement); 2147 current_block_->statements->Add(init_statement);
2127 } while (CurrentToken() == Token::kCOMMA); 2148 } while (CurrentToken() == Token::kCOMMA);
2128 } 2149 }
2129 if (!super_init_seen) { 2150 if (!super_init_seen) {
2130 // Generate implicit super() if we haven't seen an explicit super call 2151 // Generate implicit super() if we haven't seen an explicit super call
2131 // or constructor redirection. 2152 // or constructor redirection.
2132 GenerateSuperConstructorCall(cls, receiver); 2153 GenerateSuperConstructorCall(cls, receiver, NULL);
2133 } 2154 }
2134 CheckConstFieldsInitialized(cls); 2155 CheckConstFieldsInitialized(cls);
2135 } 2156 }
2136 2157
2137 2158
2138 void Parser::ParseConstructorRedirection(const Class& cls, 2159 void Parser::ParseConstructorRedirection(const Class& cls,
2139 LocalVariable* receiver) { 2160 LocalVariable* receiver) {
2140 TRACE_PARSER("ParseConstructorRedirection"); 2161 TRACE_PARSER("ParseConstructorRedirection");
2141 ASSERT(CurrentToken() == Token::kTHIS); 2162 ASSERT(CurrentToken() == Token::kTHIS);
2142 const intptr_t call_pos = TokenPos(); 2163 const intptr_t call_pos = TokenPos();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2183 current_block_->statements->Add( 2204 current_block_->statements->Add(
2184 new StaticCallNode(call_pos, redirect_ctor, arguments)); 2205 new StaticCallNode(call_pos, redirect_ctor, arguments));
2185 } 2206 }
2186 2207
2187 2208
2188 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { 2209 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
2189 ASSERT(func.IsConstructor()); 2210 ASSERT(func.IsConstructor());
2190 const intptr_t ctor_pos = TokenPos(); 2211 const intptr_t ctor_pos = TokenPos();
2191 OpenFunctionBlock(func); 2212 OpenFunctionBlock(func);
2192 const Class& cls = Class::Handle(func.Owner()); 2213 const Class& cls = Class::Handle(func.Owner());
2214
2193 LocalVariable* receiver = new LocalVariable( 2215 LocalVariable* receiver = new LocalVariable(
2194 ctor_pos, 2216 ctor_pos,
2195 Symbols::This(), 2217 Symbols::This(),
2196 Type::ZoneHandle(Type::DynamicType())); 2218 Type::ZoneHandle(Type::DynamicType()));
2197 current_block_->scope->AddVariable(receiver); 2219 current_block_->scope->AddVariable(receiver);
2198 2220
2199 LocalVariable* phase_parameter = new LocalVariable( 2221 LocalVariable* phase_parameter = new LocalVariable(
2200 ctor_pos, 2222 ctor_pos,
2201 Symbols::PhaseParameter(), 2223 Symbols::PhaseParameter(),
2202 Type::ZoneHandle(Type::SmiType())); 2224 Type::ZoneHandle(Type::SmiType()));
2203 current_block_->scope->AddVariable(phase_parameter); 2225 current_block_->scope->AddVariable(phase_parameter);
2204 2226
2205 // Parse expressions of instance fields that have an explicit 2227 // Parse expressions of instance fields that have an explicit
2206 // initializer expression. 2228 // initializer expression.
2207 // The receiver must not be visible to field initializer expressions. 2229 // The receiver must not be visible to field initializer expressions.
2208 receiver->set_invisible(true); 2230 receiver->set_invisible(true);
2209 GrowableArray<Field*> initialized_fields; 2231 GrowableArray<Field*> initialized_fields;
2210 ParseInitializedInstanceFields(cls, receiver, &initialized_fields); 2232 ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
2211 receiver->set_invisible(false); 2233 receiver->set_invisible(false);
2212 2234
2213 GenerateSuperConstructorCall(cls, receiver); 2235 // If the class of this implicit constructor is a mixin application class,
2236 // it is a forwarding constructor of the mixin. The forwarding
2237 // constructor initializes the instance fields that have initializer
2238 // expressions and then calls the respective super constructor with
2239 // the same name and number of parameters.
2240 ArgumentListNode* forwarding_args = NULL;
2241 if (cls.mixin() != Type::null()) {
2242 // At this point we don't support forwarding constructors
2243 // that have optional parameters because we don't know the default
2244 // values of the optional parameters. We would have to compile the super
2245 // constructor to get the default values. Also, the spec is not clear
2246 // whether optional parameters are even allowed in this situation.
2247 // TODO(hausner): Remove this limitation if the language spec indeed
2248 // allows optional parameters.
2249 if (func.HasOptionalParameters()) {
2250 ErrorMsg(ctor_pos,
2251 "forwarding constructors must not have optional parameters");
2252 }
2253
2254 // Prepare user-defined arguments to be forwarded to super call.
2255 // The first user-defined argument is at position 2.
2256 forwarding_args = new ArgumentListNode(ctor_pos);
2257 for (int i = 2; i < func.NumParameters(); i++) {
2258 LocalVariable* param = new LocalVariable(
2259 ctor_pos,
2260 String::ZoneHandle(func.ParameterNameAt(i)),
2261 Type::ZoneHandle(Type::DynamicType()));
2262 current_block_->scope->AddVariable(param);
2263 forwarding_args->Add(new LoadLocalNode(ctor_pos, param));
2264 }
2265 }
2266
2267 GenerateSuperConstructorCall(cls, receiver, forwarding_args);
2214 CheckConstFieldsInitialized(cls); 2268 CheckConstFieldsInitialized(cls);
2215 2269
2216 // Empty constructor body. 2270 // Empty constructor body.
2217 SequenceNode* statements = CloseBlock(); 2271 SequenceNode* statements = CloseBlock();
2218 return statements; 2272 return statements;
2219 } 2273 }
2220 2274
2221 2275
2222 // Helper function to make the first num_variables variables in the 2276 // Helper function to make the first num_variables variables in the
2223 // given scope visible/invisible. 2277 // given scope visible/invisible.
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
2849 } 2903 }
2850 SkipToMatchingParenthesis(); 2904 SkipToMatchingParenthesis();
2851 } else { 2905 } else {
2852 SkipInitializers(); 2906 SkipInitializers();
2853 } 2907 }
2854 } 2908 }
2855 2909
2856 // Only constructors can redirect to another method. 2910 // Only constructors can redirect to another method.
2857 ASSERT((method->redirect_name == NULL) || method->IsConstructor()); 2911 ASSERT((method->redirect_name == NULL) || method->IsConstructor());
2858 2912
2859 intptr_t method_end_pos = method_pos; 2913 intptr_t method_end_pos = TokenPos();
2860 if ((CurrentToken() == Token::kLBRACE) || 2914 if ((CurrentToken() == Token::kLBRACE) ||
2861 (CurrentToken() == Token::kARROW)) { 2915 (CurrentToken() == Token::kARROW)) {
2862 if (method->has_abstract) { 2916 if (method->has_abstract) {
2863 ErrorMsg(method->name_pos, 2917 ErrorMsg(method->name_pos,
2864 "abstract method '%s' may not have a function body", 2918 "abstract method '%s' may not have a function body",
2865 method->name->ToCString()); 2919 method->name->ToCString());
2866 } else if (method->has_external) { 2920 } else if (method->has_external) {
2867 ErrorMsg(method->name_pos, 2921 ErrorMsg(method->name_pos,
2868 "external method '%s' may not have a function body", 2922 "external method '%s' may not have a function body",
2869 method->name->ToCString()); 2923 method->name->ToCString());
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
3564 } 3618 }
3565 3619
3566 3620
3567 // Add an implicit constructor to the given class. 3621 // Add an implicit constructor to the given class.
3568 void Parser::AddImplicitConstructor(const Class& cls) { 3622 void Parser::AddImplicitConstructor(const Class& cls) {
3569 // The implicit constructor is unnamed, has no explicit parameter. 3623 // The implicit constructor is unnamed, has no explicit parameter.
3570 String& ctor_name = String::ZoneHandle(cls.Name()); 3624 String& ctor_name = String::ZoneHandle(cls.Name());
3571 ctor_name = String::Concat(ctor_name, Symbols::Dot()); 3625 ctor_name = String::Concat(ctor_name, Symbols::Dot());
3572 ctor_name = Symbols::New(ctor_name); 3626 ctor_name = Symbols::New(ctor_name);
3573 // To indicate that this is an implicit constructor, we set the 3627 // To indicate that this is an implicit constructor, we set the
3574 // token position is the same as the token position of the class. 3628 // token position and end token position of the function
3629 // to the token position of the class.
3575 Function& ctor = Function::Handle( 3630 Function& ctor = Function::Handle(
3576 Function::New(ctor_name, 3631 Function::New(ctor_name,
3577 RawFunction::kConstructor, 3632 RawFunction::kConstructor,
3578 /* is_static = */ false, 3633 /* is_static = */ false,
3579 /* is_const = */ false, 3634 /* is_const = */ false,
3580 /* is_abstract = */ false, 3635 /* is_abstract = */ false,
3581 /* is_external = */ false, 3636 /* is_external = */ false,
3582 cls, 3637 cls,
3583 cls.token_pos())); 3638 cls.token_pos()));
3639 ctor.set_end_token_pos(ctor.token_pos());
3640
3584 ParamList params; 3641 ParamList params;
3585 // Add implicit 'this' parameter. We don't care about the specific type 3642 // Add implicit 'this' parameter. We don't care about the specific type
3586 // and just specify dynamic. 3643 // and just specify dynamic.
3587 const Type& receiver_type = Type::Handle(Type::DynamicType()); 3644 const Type& receiver_type = Type::Handle(Type::DynamicType());
3588 params.AddReceiver(&receiver_type, cls.token_pos()); 3645 params.AddReceiver(&receiver_type, cls.token_pos());
3589 // Add implicit parameter for construction phase. 3646 // Add implicit parameter for construction phase.
3590 params.AddFinalParameter(cls.token_pos(), 3647 params.AddFinalParameter(cls.token_pos(),
3591 &Symbols::PhaseParameter(), 3648 &Symbols::PhaseParameter(),
3592 &Type::ZoneHandle(Type::SmiType())); 3649 &Type::ZoneHandle(Type::SmiType()));
3593 3650
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
4087 mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand()); 4144 mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand());
4088 mixin_app_name = String::Concat(mixin_app_name, 4145 mixin_app_name = String::Concat(mixin_app_name,
4089 String::Handle(mixin_type.ClassName())); 4146 String::Handle(mixin_type.ClassName()));
4090 mixin_app_name = Symbols::New(mixin_app_name); 4147 mixin_app_name = Symbols::New(mixin_app_name);
4091 4148
4092 mixin_application = Class::New(mixin_app_name, script_, mixin_pos); 4149 mixin_application = Class::New(mixin_app_name, script_, mixin_pos);
4093 mixin_application.set_super_type(mixin_super_type); 4150 mixin_application.set_super_type(mixin_super_type);
4094 mixin_application.set_mixin(Type::Cast(mixin_type)); 4151 mixin_application.set_mixin(Type::Cast(mixin_type));
4095 mixin_application.set_library(library_); 4152 mixin_application.set_library(library_);
4096 mixin_application.set_is_synthesized_class(); 4153 mixin_application.set_is_synthesized_class();
4097 AddImplicitConstructor(mixin_application); 4154
4098 // Add the mixin type to the interfaces that the mixin application 4155 // Add the mixin type to the interfaces that the mixin application
4099 // class implements. This is necessary so that type tests work. 4156 // class implements. This is necessary so that type tests work.
4100 mixin_application_interfaces = Array::New(1); 4157 mixin_application_interfaces = Array::New(1);
4101 mixin_application_interfaces.SetAt(0, mixin_type); 4158 mixin_application_interfaces.SetAt(0, mixin_type);
4102 mixin_application.set_interfaces(mixin_application_interfaces); 4159 mixin_application.set_interfaces(mixin_application_interfaces);
4103 4160
4104 // For the type arguments of the mixin application type, we need 4161 // For the type arguments of the mixin application type, we need
4105 // a copy of the type arguments to the mixin type. The simplest way 4162 // a copy of the type arguments to the mixin type. The simplest way
4106 // to get the copy is to rewind the parser, parse the mixin type 4163 // to get the copy is to rewind the parser, parse the mixin type
4107 // again and steal its type arguments. 4164 // again and steal its type arguments.
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
4819 // Populate the parameter type array and parameter name array of the function 4876 // Populate the parameter type array and parameter name array of the function
4820 // with the formal parameter types and names. 4877 // with the formal parameter types and names.
4821 void Parser::AddFormalParamsToFunction(const ParamList* params, 4878 void Parser::AddFormalParamsToFunction(const ParamList* params,
4822 const Function& func) { 4879 const Function& func) {
4823 ASSERT((params != NULL) && (params->parameters != NULL)); 4880 ASSERT((params != NULL) && (params->parameters != NULL));
4824 ASSERT((params->num_optional_parameters > 0) == 4881 ASSERT((params->num_optional_parameters > 0) ==
4825 (params->has_optional_positional_parameters || 4882 (params->has_optional_positional_parameters ||
4826 params->has_optional_named_parameters)); 4883 params->has_optional_named_parameters));
4827 if (!Utils::IsInt(16, params->num_fixed_parameters) || 4884 if (!Utils::IsInt(16, params->num_fixed_parameters) ||
4828 !Utils::IsInt(16, params->num_optional_parameters)) { 4885 !Utils::IsInt(16, params->num_optional_parameters)) {
4829 ErrorMsg("too many formal parameters"); 4886 ErrorMsg(func.token_pos(), "too many formal parameters");
4830 } 4887 }
4831 func.set_num_fixed_parameters(params->num_fixed_parameters); 4888 func.set_num_fixed_parameters(params->num_fixed_parameters);
4832 func.SetNumOptionalParameters(params->num_optional_parameters, 4889 func.SetNumOptionalParameters(params->num_optional_parameters,
4833 params->has_optional_positional_parameters); 4890 params->has_optional_positional_parameters);
4834 const int num_parameters = params->parameters->length(); 4891 const int num_parameters = params->parameters->length();
4835 ASSERT(num_parameters == func.NumParameters()); 4892 ASSERT(num_parameters == func.NumParameters());
4836 func.set_parameter_types(Array::Handle(Array::New(num_parameters, 4893 func.set_parameter_types(Array::Handle(Array::New(num_parameters,
4837 Heap::kOld))); 4894 Heap::kOld)));
4838 func.set_parameter_names(Array::Handle(Array::New(num_parameters, 4895 func.set_parameter_names(Array::Handle(Array::New(num_parameters,
4839 Heap::kOld))); 4896 Heap::kOld)));
(...skipping 5237 matching lines...) Expand 10 before | Expand all | Expand 10 after
10077 void Parser::SkipQualIdent() { 10134 void Parser::SkipQualIdent() {
10078 ASSERT(IsIdentifier()); 10135 ASSERT(IsIdentifier());
10079 ConsumeToken(); 10136 ConsumeToken();
10080 if (CurrentToken() == Token::kPERIOD) { 10137 if (CurrentToken() == Token::kPERIOD) {
10081 ConsumeToken(); // Consume the kPERIOD token. 10138 ConsumeToken(); // Consume the kPERIOD token.
10082 ExpectIdentifier("identifier expected after '.'"); 10139 ExpectIdentifier("identifier expected after '.'");
10083 } 10140 }
10084 } 10141 }
10085 10142
10086 } // namespace dart 10143 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698