OLD | NEW |
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 #include "vm/flags.h" | 6 #include "vm/flags.h" |
7 | 7 |
8 #ifndef DART_PRECOMPILED_RUNTIME | 8 #ifndef DART_PRECOMPILED_RUNTIME |
9 | 9 |
10 #include "lib/invocation_mirror.h" | 10 #include "lib/invocation_mirror.h" |
(...skipping 2988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2999 | 2999 |
3000 | 3000 |
3001 AstNode* Parser::CheckDuplicateFieldInit( | 3001 AstNode* Parser::CheckDuplicateFieldInit( |
3002 TokenPosition init_pos, | 3002 TokenPosition init_pos, |
3003 GrowableArray<Field*>* initialized_fields, | 3003 GrowableArray<Field*>* initialized_fields, |
3004 AstNode* instance, | 3004 AstNode* instance, |
3005 Field* field, | 3005 Field* field, |
3006 AstNode* init_value) { | 3006 AstNode* init_value) { |
3007 ASSERT(!field->is_static()); | 3007 ASSERT(!field->is_static()); |
3008 AstNode* result = NULL; | 3008 AstNode* result = NULL; |
3009 const String& field_name = String::Handle(field->name()); | |
3010 String& initialized_name = String::Handle(Z); | |
3011 | 3009 |
3012 // The initializer_list is divided into two sections. The sections | 3010 // The initializer_list is divided into two sections. The sections |
3013 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] | 3011 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] |
3014 // The first fields f0 .. fn are final fields of the class that | 3012 // The first fields f0 .. fn are final fields of the class that |
3015 // have an initializer expression inlined in the class declaration. | 3013 // have an initializer expression inlined in the class declaration. |
3016 // The remaining fields are those initialized by the constructor's | 3014 // The remaining fields are those initialized by the constructor's |
3017 // initializing formals and initializer list | 3015 // initializing formals and initializer list |
3018 int initializer_idx = 0; | 3016 int initializer_idx = 0; |
3019 while (initializer_idx < initialized_fields->length()) { | 3017 while (initializer_idx < initialized_fields->length()) { |
3020 Field* initialized_field = (*initialized_fields)[initializer_idx]; | 3018 Field* initialized_field = (*initialized_fields)[initializer_idx]; |
3021 initializer_idx++; | 3019 initializer_idx++; |
3022 if (initialized_field == NULL) { | 3020 if (initialized_field == NULL) { |
3023 break; | 3021 break; |
3024 } | 3022 } |
3025 | |
3026 initialized_name ^= initialized_field->name(); | |
3027 if (initialized_name.Equals(field_name) && field->has_initializer()) { | |
3028 ReportError(init_pos, "final field '%s' is already initialized.", | |
3029 field_name.ToCString()); | |
3030 } | |
3031 | |
3032 if (initialized_field->raw() == field->raw()) { | 3023 if (initialized_field->raw() == field->raw()) { |
3033 // This final field has been initialized by an inlined | 3024 // This final field has been initialized by an inlined |
3034 // initializer expression. This is a runtime error. | 3025 // initializer expression. This is a runtime error. |
3035 // Throw a NoSuchMethodError for the missing setter. | 3026 // Throw a NoSuchMethodError for the missing setter. |
3036 ASSERT(field->is_final()); | 3027 ASSERT(field->is_final()); |
3037 | 3028 |
3038 // Build a call to NoSuchMethodError::_throwNew( | 3029 // Build a call to NoSuchMethodError::_throwNew( |
3039 // Object receiver, | 3030 // Object receiver, |
3040 // String memberName, | 3031 // String memberName, |
3041 // int invocation_type, | 3032 // int invocation_type, |
(...skipping 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5242 AddFormalParamsToFunction(¶ms, ctor); | 5233 AddFormalParamsToFunction(¶ms, ctor); |
5243 ctor.set_result_type(Object::dynamic_type()); | 5234 ctor.set_result_type(Object::dynamic_type()); |
5244 ResolveSignature(ctor); | 5235 ResolveSignature(ctor); |
5245 // The body of the constructor cannot modify the type of the constructed | 5236 // The body of the constructor cannot modify the type of the constructed |
5246 // instance, which is passed in as the receiver. | 5237 // instance, which is passed in as the receiver. |
5247 ctor.set_result_type(*receiver_type); | 5238 ctor.set_result_type(*receiver_type); |
5248 cls.AddFunction(ctor); | 5239 cls.AddFunction(ctor); |
5249 } | 5240 } |
5250 | 5241 |
5251 | 5242 |
5252 void Parser::CheckFinalInitializationConflicts(const ClassDesc* class_desc, | |
5253 const MemberDesc* member) { | |
5254 const ParamList* params = &member->params; | |
5255 if (!params->has_field_initializer) { | |
5256 return; | |
5257 } | |
5258 | |
5259 const ZoneGrowableArray<ParamDesc>& parameters = *params->parameters; | |
5260 const GrowableArray<const Field*>& fields = class_desc->fields(); | |
5261 String& field_name = String::Handle(Z); | |
5262 | |
5263 for (intptr_t p = 0; p < parameters.length(); p++) { | |
5264 const ParamDesc& current_param = parameters[p]; | |
5265 if (!current_param.is_field_initializer) { | |
5266 continue; | |
5267 } | |
5268 | |
5269 const String& param_name = *current_param.name; | |
5270 for (intptr_t i = 0; i < fields.length(); i++) { | |
5271 const Field* current_field = fields.At(i); | |
5272 if (!current_field->is_final() || !current_field->has_initializer()) { | |
5273 continue; | |
5274 } | |
5275 | |
5276 field_name ^= current_field->name(); | |
5277 if (param_name.Equals(field_name)) { | |
5278 ReportError(current_param.name_pos, | |
5279 "final field '%s' is already initialized.", | |
5280 param_name.ToCString()); | |
5281 } | |
5282 } | |
5283 } | |
5284 } | |
5285 | |
5286 | |
5287 // Check for cycles in constructor redirection. | 5243 // Check for cycles in constructor redirection. |
5288 void Parser::CheckConstructors(ClassDesc* class_desc) { | 5244 void Parser::CheckConstructors(ClassDesc* class_desc) { |
5289 // Check for cycles in constructor redirection. | 5245 // Check for cycles in constructor redirection. |
5290 const GrowableArray<MemberDesc>& members = class_desc->members(); | 5246 const GrowableArray<MemberDesc>& members = class_desc->members(); |
5291 for (int i = 0; i < members.length(); i++) { | 5247 for (int i = 0; i < members.length(); i++) { |
5292 MemberDesc* member = &members[i]; | 5248 MemberDesc* member = &members[i]; |
5293 if (member->IsConstructor()) { | |
5294 // Check that our constructors don't try and reinitialize an initialized | |
5295 // final variable. | |
5296 CheckFinalInitializationConflicts(class_desc, member); | |
5297 } | |
5298 if (member->redirect_name == NULL) { | 5249 if (member->redirect_name == NULL) { |
5299 continue; | 5250 continue; |
5300 } | 5251 } |
5301 GrowableArray<MemberDesc*> ctors; | 5252 GrowableArray<MemberDesc*> ctors; |
5302 while ((member != NULL) && (member->redirect_name != NULL)) { | 5253 while ((member != NULL) && (member->redirect_name != NULL)) { |
5303 ASSERT(member->IsConstructor()); | 5254 ASSERT(member->IsConstructor()); |
5304 // Check whether we have already seen this member. | 5255 // Check whether we have already seen this member. |
5305 for (int i = 0; i < ctors.length(); i++) { | 5256 for (int i = 0; i < ctors.length(); i++) { |
5306 if (ctors[i] == member) { | 5257 if (ctors[i] == member) { |
5307 ReportError(member->name_pos, | 5258 ReportError(member->name_pos, |
(...skipping 10054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15362 TokenPosition* start, | 15313 TokenPosition* start, |
15363 TokenPosition* end) { | 15314 TokenPosition* end) { |
15364 UNREACHABLE(); | 15315 UNREACHABLE(); |
15365 return false; | 15316 return false; |
15366 } | 15317 } |
15367 | 15318 |
15368 | 15319 |
15369 } // namespace dart | 15320 } // namespace dart |
15370 | 15321 |
15371 #endif // DART_PRECOMPILED_RUNTIME | 15322 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |