| 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); |
| 3009 | 3011 |
| 3010 // The initializer_list is divided into two sections. The sections | 3012 // The initializer_list is divided into two sections. The sections |
| 3011 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] | 3013 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] |
| 3012 // The first fields f0 .. fn are final fields of the class that | 3014 // The first fields f0 .. fn are final fields of the class that |
| 3013 // have an initializer expression inlined in the class declaration. | 3015 // have an initializer expression inlined in the class declaration. |
| 3014 // The remaining fields are those initialized by the constructor's | 3016 // The remaining fields are those initialized by the constructor's |
| 3015 // initializing formals and initializer list | 3017 // initializing formals and initializer list |
| 3016 int initializer_idx = 0; | 3018 int initializer_idx = 0; |
| 3017 while (initializer_idx < initialized_fields->length()) { | 3019 while (initializer_idx < initialized_fields->length()) { |
| 3018 Field* initialized_field = (*initialized_fields)[initializer_idx]; | 3020 Field* initialized_field = (*initialized_fields)[initializer_idx]; |
| 3019 initializer_idx++; | 3021 initializer_idx++; |
| 3020 if (initialized_field == NULL) { | 3022 if (initialized_field == NULL) { |
| 3021 break; | 3023 break; |
| 3022 } | 3024 } |
| 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 |
| 3023 if (initialized_field->raw() == field->raw()) { | 3032 if (initialized_field->raw() == field->raw()) { |
| 3024 // This final field has been initialized by an inlined | 3033 // This final field has been initialized by an inlined |
| 3025 // initializer expression. This is a runtime error. | 3034 // initializer expression. This is a runtime error. |
| 3026 // Throw a NoSuchMethodError for the missing setter. | 3035 // Throw a NoSuchMethodError for the missing setter. |
| 3027 ASSERT(field->is_final()); | 3036 ASSERT(field->is_final()); |
| 3028 | 3037 |
| 3029 // Build a call to NoSuchMethodError::_throwNew( | 3038 // Build a call to NoSuchMethodError::_throwNew( |
| 3030 // Object receiver, | 3039 // Object receiver, |
| 3031 // String memberName, | 3040 // String memberName, |
| 3032 // int invocation_type, | 3041 // int invocation_type, |
| (...skipping 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5233 AddFormalParamsToFunction(¶ms, ctor); | 5242 AddFormalParamsToFunction(¶ms, ctor); |
| 5234 ctor.set_result_type(Object::dynamic_type()); | 5243 ctor.set_result_type(Object::dynamic_type()); |
| 5235 ResolveSignature(ctor); | 5244 ResolveSignature(ctor); |
| 5236 // The body of the constructor cannot modify the type of the constructed | 5245 // The body of the constructor cannot modify the type of the constructed |
| 5237 // instance, which is passed in as the receiver. | 5246 // instance, which is passed in as the receiver. |
| 5238 ctor.set_result_type(*receiver_type); | 5247 ctor.set_result_type(*receiver_type); |
| 5239 cls.AddFunction(ctor); | 5248 cls.AddFunction(ctor); |
| 5240 } | 5249 } |
| 5241 | 5250 |
| 5242 | 5251 |
| 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 |
| 5243 // Check for cycles in constructor redirection. | 5287 // Check for cycles in constructor redirection. |
| 5244 void Parser::CheckConstructors(ClassDesc* class_desc) { | 5288 void Parser::CheckConstructors(ClassDesc* class_desc) { |
| 5245 // Check for cycles in constructor redirection. | 5289 // Check for cycles in constructor redirection. |
| 5246 const GrowableArray<MemberDesc>& members = class_desc->members(); | 5290 const GrowableArray<MemberDesc>& members = class_desc->members(); |
| 5247 for (int i = 0; i < members.length(); i++) { | 5291 for (int i = 0; i < members.length(); i++) { |
| 5248 MemberDesc* member = &members[i]; | 5292 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 } |
| 5249 if (member->redirect_name == NULL) { | 5298 if (member->redirect_name == NULL) { |
| 5250 continue; | 5299 continue; |
| 5251 } | 5300 } |
| 5252 GrowableArray<MemberDesc*> ctors; | 5301 GrowableArray<MemberDesc*> ctors; |
| 5253 while ((member != NULL) && (member->redirect_name != NULL)) { | 5302 while ((member != NULL) && (member->redirect_name != NULL)) { |
| 5254 ASSERT(member->IsConstructor()); | 5303 ASSERT(member->IsConstructor()); |
| 5255 // Check whether we have already seen this member. | 5304 // Check whether we have already seen this member. |
| 5256 for (int i = 0; i < ctors.length(); i++) { | 5305 for (int i = 0; i < ctors.length(); i++) { |
| 5257 if (ctors[i] == member) { | 5306 if (ctors[i] == member) { |
| 5258 ReportError(member->name_pos, | 5307 ReportError(member->name_pos, |
| (...skipping 10054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15313 TokenPosition* start, | 15362 TokenPosition* start, |
| 15314 TokenPosition* end) { | 15363 TokenPosition* end) { |
| 15315 UNREACHABLE(); | 15364 UNREACHABLE(); |
| 15316 return false; | 15365 return false; |
| 15317 } | 15366 } |
| 15318 | 15367 |
| 15319 | 15368 |
| 15320 } // namespace dart | 15369 } // namespace dart |
| 15321 | 15370 |
| 15322 #endif // DART_PRECOMPILED_RUNTIME | 15371 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |