| 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 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
| (...skipping 2175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 SetAllowFunctionLiterals(saved_mode); | 2186 SetAllowFunctionLiterals(saved_mode); |
| 2187 if (current_function().is_const() && !init_expr->IsPotentiallyConst()) { | 2187 if (current_function().is_const() && !init_expr->IsPotentiallyConst()) { |
| 2188 ReportError(field_pos, | 2188 ReportError(field_pos, |
| 2189 "initializer expression must be compile time constant."); | 2189 "initializer expression must be compile time constant."); |
| 2190 } | 2190 } |
| 2191 Field& field = Field::ZoneHandle(I, cls.LookupInstanceField(field_name)); | 2191 Field& field = Field::ZoneHandle(I, cls.LookupInstanceField(field_name)); |
| 2192 if (field.IsNull()) { | 2192 if (field.IsNull()) { |
| 2193 ReportError(field_pos, "unresolved reference to instance field '%s'", | 2193 ReportError(field_pos, "unresolved reference to instance field '%s'", |
| 2194 field_name.ToCString()); | 2194 field_name.ToCString()); |
| 2195 } | 2195 } |
| 2196 CheckDuplicateFieldInit(field_pos, initialized_fields, &field); | |
| 2197 AstNode* instance = new LoadLocalNode(field_pos, receiver); | |
| 2198 EnsureExpressionTemp(); | 2196 EnsureExpressionTemp(); |
| 2199 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); | 2197 AstNode* instance = new(I) LoadLocalNode(field_pos, receiver); |
| 2198 AstNode* initializer = CheckDuplicateFieldInit(field_pos, |
| 2199 initialized_fields, instance, &field, init_expr); |
| 2200 if (initializer == NULL) { |
| 2201 initializer = |
| 2202 new(I) StoreInstanceFieldNode(field_pos, instance, field, init_expr); |
| 2203 } |
| 2204 return initializer; |
| 2200 } | 2205 } |
| 2201 | 2206 |
| 2202 | 2207 |
| 2203 void Parser::CheckFieldsInitialized(const Class& cls) { | 2208 void Parser::CheckFieldsInitialized(const Class& cls) { |
| 2204 const Array& fields = Array::Handle(I, cls.fields()); | 2209 const Array& fields = Array::Handle(I, cls.fields()); |
| 2205 Field& field = Field::Handle(I); | 2210 Field& field = Field::Handle(I); |
| 2206 SequenceNode* initializers = current_block_->statements; | 2211 SequenceNode* initializers = current_block_->statements; |
| 2207 for (int field_num = 0; field_num < fields.Length(); field_num++) { | 2212 for (int field_num = 0; field_num < fields.Length(); field_num++) { |
| 2208 field ^= fields.At(field_num); | 2213 field ^= fields.At(field_num); |
| 2209 if (field.is_static()) { | 2214 if (field.is_static()) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver); | 2315 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver); |
| 2311 EnsureExpressionTemp(); | 2316 EnsureExpressionTemp(); |
| 2312 AstNode* field_init = | 2317 AstNode* field_init = |
| 2313 new StoreInstanceFieldNode(field.token_pos(), | 2318 new StoreInstanceFieldNode(field.token_pos(), |
| 2314 instance, | 2319 instance, |
| 2315 field, | 2320 field, |
| 2316 init_expr); | 2321 init_expr); |
| 2317 current_block_->statements->Add(field_init); | 2322 current_block_->statements->Add(field_init); |
| 2318 } | 2323 } |
| 2319 } | 2324 } |
| 2325 initialized_fields->Add(NULL); // End of inline initializers. |
| 2320 SetPosition(saved_pos); | 2326 SetPosition(saved_pos); |
| 2321 } | 2327 } |
| 2322 | 2328 |
| 2323 | 2329 |
| 2324 void Parser::CheckDuplicateFieldInit(intptr_t init_pos, | 2330 AstNode* Parser::CheckDuplicateFieldInit( |
| 2325 GrowableArray<Field*>* initialized_fields, | 2331 intptr_t init_pos, |
| 2326 Field* field) { | 2332 GrowableArray<Field*>* initialized_fields, |
| 2333 AstNode* instance, |
| 2334 Field* field, |
| 2335 AstNode* init_value) { |
| 2327 ASSERT(!field->is_static()); | 2336 ASSERT(!field->is_static()); |
| 2328 for (int i = 0; i < initialized_fields->length(); i++) { | 2337 AstNode* result = NULL; |
| 2329 Field* initialized_field = (*initialized_fields)[i]; | 2338 |
| 2339 // The initializer_list is divided into two sections. The sections |
| 2340 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] |
| 2341 // The first fields f0 .. fn are final fields of the class that |
| 2342 // have an initializer expression inlined in the class declaration. |
| 2343 // The remaining fields are those initialized by the constructor's |
| 2344 // initializing formals and initializer list |
| 2345 int initializer_idx = 0; |
| 2346 while (initializer_idx < initialized_fields->length()) { |
| 2347 Field* initialized_field = (*initialized_fields)[initializer_idx]; |
| 2348 initializer_idx++; |
| 2349 if (initialized_field == NULL) { |
| 2350 break; |
| 2351 } |
| 2352 if (initialized_field->raw() == field->raw()) { |
| 2353 // This final field has been initialized by an inlined |
| 2354 // initializer expression. This is a runtime error. |
| 2355 // Throw a NoSuchMethodError for the missing setter. |
| 2356 ASSERT(field->is_final()); |
| 2357 |
| 2358 // Build a call to NoSuchMethodError::_throwNew( |
| 2359 // Object receiver, |
| 2360 // String memberName, |
| 2361 // int invocation_type, |
| 2362 // List arguments, |
| 2363 // List argumentNames, |
| 2364 // List existingArgumentNames); |
| 2365 |
| 2366 ArgumentListNode* nsm_args = new(I) ArgumentListNode(init_pos); |
| 2367 // Object receiver. |
| 2368 nsm_args->Add(instance); |
| 2369 |
| 2370 // String memberName. |
| 2371 String& setter_name = String::ZoneHandle(field->name()); |
| 2372 setter_name = Field::SetterSymbol(setter_name); |
| 2373 nsm_args->Add(new(I) LiteralNode(init_pos, setter_name)); |
| 2374 |
| 2375 // Smi invocation_type. |
| 2376 const int invocation_type = |
| 2377 InvocationMirror::EncodeType(InvocationMirror::kDynamic, |
| 2378 InvocationMirror::kSetter); |
| 2379 nsm_args->Add(new(I) LiteralNode( |
| 2380 init_pos, Smi::ZoneHandle(I, Smi::New(invocation_type)))); |
| 2381 |
| 2382 // List arguments. |
| 2383 GrowableArray<AstNode*> setter_args; |
| 2384 setter_args.Add(init_value); |
| 2385 ArrayNode* setter_args_array = new(I) ArrayNode( |
| 2386 init_pos, |
| 2387 Type::ZoneHandle(I, Type::ArrayType()), |
| 2388 setter_args); |
| 2389 nsm_args->Add(setter_args_array); |
| 2390 |
| 2391 // List argumentNames. |
| 2392 // The missing implicit setter of the field has no argument names. |
| 2393 nsm_args->Add(new(I) LiteralNode(init_pos, Array::ZoneHandle(I))); |
| 2394 |
| 2395 // List existingArgumentNames. |
| 2396 // There is no setter for the final field, thus there are |
| 2397 // no existing names. |
| 2398 nsm_args->Add(new(I) LiteralNode(init_pos, Array::ZoneHandle(I))); |
| 2399 |
| 2400 AstNode* nsm_call = |
| 2401 MakeStaticCall(Symbols::NoSuchMethodError(), |
| 2402 Library::PrivateCoreLibName(Symbols::ThrowNew()), |
| 2403 nsm_args); |
| 2404 |
| 2405 LetNode* let = new(I) LetNode(init_pos); |
| 2406 let->AddNode(init_value); |
| 2407 let->AddNode(nsm_call); |
| 2408 result = let; |
| 2409 } |
| 2410 } |
| 2411 // The remaining elements in initialized_fields are fields that |
| 2412 // are initialized through initializing formal parameters, or |
| 2413 // in the constructor's initializer list. If there is a duplicate, |
| 2414 // it is a compile time error. |
| 2415 while (initializer_idx < initialized_fields->length()) { |
| 2416 Field* initialized_field = (*initialized_fields)[initializer_idx]; |
| 2417 initializer_idx++; |
| 2330 if (initialized_field->raw() == field->raw()) { | 2418 if (initialized_field->raw() == field->raw()) { |
| 2331 ReportError(init_pos, | 2419 ReportError(init_pos, |
| 2332 "duplicate initialization for field %s", | 2420 "duplicate initializer for field %s", |
| 2333 String::Handle(I, field->name()).ToCString()); | 2421 String::Handle(I, field->name()).ToCString()); |
| 2334 } | 2422 } |
| 2335 } | 2423 } |
| 2336 initialized_fields->Add(field); | 2424 initialized_fields->Add(field); |
| 2425 return result; |
| 2337 } | 2426 } |
| 2338 | 2427 |
| 2339 | 2428 |
| 2340 void Parser::ParseInitializers(const Class& cls, | 2429 void Parser::ParseInitializers(const Class& cls, |
| 2341 LocalVariable* receiver, | 2430 LocalVariable* receiver, |
| 2342 GrowableArray<Field*>* initialized_fields) { | 2431 GrowableArray<Field*>* initialized_fields) { |
| 2343 TRACE_PARSER("ParseInitializers"); | 2432 TRACE_PARSER("ParseInitializers"); |
| 2344 bool super_init_seen = false; | 2433 bool super_init_seen = false; |
| 2345 if (CurrentToken() == Token::kCOLON) { | 2434 if (CurrentToken() == Token::kCOLON) { |
| 2346 do { | 2435 do { |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2603 if (field.IsNull()) { | 2692 if (field.IsNull()) { |
| 2604 ReportError(param.name_pos, | 2693 ReportError(param.name_pos, |
| 2605 "unresolved reference to instance field '%s'", | 2694 "unresolved reference to instance field '%s'", |
| 2606 field_name.ToCString()); | 2695 field_name.ToCString()); |
| 2607 } | 2696 } |
| 2608 if (is_redirecting_constructor) { | 2697 if (is_redirecting_constructor) { |
| 2609 ReportError(param.name_pos, | 2698 ReportError(param.name_pos, |
| 2610 "redirecting constructors may not have " | 2699 "redirecting constructors may not have " |
| 2611 "initializing formal parameters"); | 2700 "initializing formal parameters"); |
| 2612 } | 2701 } |
| 2613 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); | |
| 2614 | 2702 |
| 2615 if (!param.has_explicit_type) { | 2703 if (!param.has_explicit_type) { |
| 2616 const AbstractType& field_type = | 2704 const AbstractType& field_type = |
| 2617 AbstractType::ZoneHandle(I, field.type()); | 2705 AbstractType::ZoneHandle(I, field.type()); |
| 2618 param.type = &field_type; | 2706 param.type = &field_type; |
| 2619 // Parameter type was already set to dynamic when parsing the class | 2707 // Parameter type was already set to dynamic when parsing the class |
| 2620 // declaration: fix it. | 2708 // declaration: fix it. |
| 2621 func.SetParameterTypeAt(i, field_type); | 2709 func.SetParameterTypeAt(i, field_type); |
| 2622 } | 2710 } |
| 2623 | 2711 |
| 2624 AstNode* instance = new LoadLocalNode(param.name_pos, receiver); | 2712 AstNode* instance = new LoadLocalNode(param.name_pos, receiver); |
| 2625 // Initializing formals cannot be used in the explicit initializer | 2713 // Initializing formals cannot be used in the explicit initializer |
| 2626 // list, nor can they be used in the constructor body. | 2714 // list, nor can they be used in the constructor body. |
| 2627 // Thus, they are set to be invisible when added to the scope. | 2715 // Thus, they are set to be invisible when added to the scope. |
| 2628 LocalVariable* p = param.var; | 2716 LocalVariable* p = param.var; |
| 2629 ASSERT(p != NULL); | 2717 ASSERT(p != NULL); |
| 2630 ASSERT(p->is_invisible()); | 2718 ASSERT(p->is_invisible()); |
| 2631 AstNode* value = new LoadLocalNode(param.name_pos, p); | 2719 AstNode* value = new LoadLocalNode(param.name_pos, p); |
| 2632 EnsureExpressionTemp(); | 2720 EnsureExpressionTemp(); |
| 2633 AstNode* initializer = new StoreInstanceFieldNode( | 2721 AstNode* initializer = |
| 2634 param.name_pos, instance, field, value); | 2722 CheckDuplicateFieldInit(param.name_pos, |
| 2723 &initialized_fields, |
| 2724 instance, |
| 2725 &field, |
| 2726 value); |
| 2727 if (initializer == NULL) { |
| 2728 initializer = new(I) StoreInstanceFieldNode( |
| 2729 param.name_pos, instance, field, value); |
| 2730 } |
| 2635 current_block_->statements->Add(initializer); | 2731 current_block_->statements->Add(initializer); |
| 2636 } | 2732 } |
| 2637 } | 2733 } |
| 2638 } | 2734 } |
| 2639 | 2735 |
| 2640 if (is_redirecting_constructor) { | 2736 if (is_redirecting_constructor) { |
| 2641 ParseConstructorRedirection(cls, receiver); | 2737 ParseConstructorRedirection(cls, receiver); |
| 2642 } else { | 2738 } else { |
| 2643 ParseInitializers(cls, receiver, &initialized_fields); | 2739 ParseInitializers(cls, receiver, &initialized_fields); |
| 2644 } | 2740 } |
| (...skipping 8742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11387 void Parser::SkipQualIdent() { | 11483 void Parser::SkipQualIdent() { |
| 11388 ASSERT(IsIdentifier()); | 11484 ASSERT(IsIdentifier()); |
| 11389 ConsumeToken(); | 11485 ConsumeToken(); |
| 11390 if (CurrentToken() == Token::kPERIOD) { | 11486 if (CurrentToken() == Token::kPERIOD) { |
| 11391 ConsumeToken(); // Consume the kPERIOD token. | 11487 ConsumeToken(); // Consume the kPERIOD token. |
| 11392 ExpectIdentifier("identifier expected after '.'"); | 11488 ExpectIdentifier("identifier expected after '.'"); |
| 11393 } | 11489 } |
| 11394 } | 11490 } |
| 11395 | 11491 |
| 11396 } // namespace dart | 11492 } // namespace dart |
| OLD | NEW |