| 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 "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 2331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2342 initialized_fields->Add(field); | 2342 initialized_fields->Add(field); |
| 2343 } | 2343 } |
| 2344 | 2344 |
| 2345 | 2345 |
| 2346 void Parser::ParseInitializers(const Class& cls, | 2346 void Parser::ParseInitializers(const Class& cls, |
| 2347 LocalVariable* receiver, | 2347 LocalVariable* receiver, |
| 2348 GrowableArray<Field*>* initialized_fields) { | 2348 GrowableArray<Field*>* initialized_fields) { |
| 2349 TRACE_PARSER("ParseInitializers"); | 2349 TRACE_PARSER("ParseInitializers"); |
| 2350 bool super_init_seen = false; | 2350 bool super_init_seen = false; |
| 2351 if (CurrentToken() == Token::kCOLON) { | 2351 if (CurrentToken() == Token::kCOLON) { |
| 2352 if ((LookaheadToken(1) == Token::kTHIS) && | |
| 2353 ((LookaheadToken(2) == Token::kLPAREN) || | |
| 2354 ((LookaheadToken(2) == Token::kPERIOD) && | |
| 2355 (LookaheadToken(4) == Token::kLPAREN)))) { | |
| 2356 // Either we see this(...) or this.xxx(...) which is a | |
| 2357 // redirected constructor. We don't need to check whether | |
| 2358 // const fields are initialized. The other constructor will | |
| 2359 // guarantee that. | |
| 2360 ConsumeToken(); // Colon. | |
| 2361 ParseConstructorRedirection(cls, receiver); | |
| 2362 return; | |
| 2363 } | |
| 2364 do { | 2352 do { |
| 2365 ConsumeToken(); // Colon or comma. | 2353 ConsumeToken(); // Colon or comma. |
| 2366 AstNode* init_statement; | 2354 AstNode* init_statement; |
| 2367 if (CurrentToken() == Token::kSUPER) { | 2355 if (CurrentToken() == Token::kSUPER) { |
| 2368 if (super_init_seen) { | 2356 if (super_init_seen) { |
| 2369 ErrorMsg("duplicate call to super constructor"); | 2357 ErrorMsg("duplicate call to super constructor"); |
| 2370 } | 2358 } |
| 2371 init_statement = ParseSuperInitializer(cls, receiver); | 2359 init_statement = ParseSuperInitializer(cls, receiver); |
| 2372 super_init_seen = true; | 2360 super_init_seen = true; |
| 2373 } else { | 2361 } else { |
| 2374 init_statement = ParseInitializer(cls, receiver, initialized_fields); | 2362 init_statement = ParseInitializer(cls, receiver, initialized_fields); |
| 2375 } | 2363 } |
| 2376 current_block_->statements->Add(init_statement); | 2364 current_block_->statements->Add(init_statement); |
| 2377 } while (CurrentToken() == Token::kCOMMA); | 2365 } while (CurrentToken() == Token::kCOMMA); |
| 2378 } | 2366 } |
| 2379 if (!super_init_seen) { | 2367 if (!super_init_seen) { |
| 2380 // Generate implicit super() if we haven't seen an explicit super call | 2368 // Generate implicit super() if we haven't seen an explicit super call |
| 2381 // or constructor redirection. | 2369 // or constructor redirection. |
| 2382 GenerateSuperConstructorCall(cls, receiver, NULL); | 2370 GenerateSuperConstructorCall(cls, receiver, NULL); |
| 2383 } | 2371 } |
| 2384 CheckConstFieldsInitialized(cls); | 2372 CheckConstFieldsInitialized(cls); |
| 2385 } | 2373 } |
| 2386 | 2374 |
| 2387 | 2375 |
| 2388 void Parser::ParseConstructorRedirection(const Class& cls, | 2376 void Parser::ParseConstructorRedirection(const Class& cls, |
| 2389 LocalVariable* receiver) { | 2377 LocalVariable* receiver) { |
| 2390 TRACE_PARSER("ParseConstructorRedirection"); | 2378 TRACE_PARSER("ParseConstructorRedirection"); |
| 2379 ExpectToken(Token::kCOLON); |
| 2391 ASSERT(CurrentToken() == Token::kTHIS); | 2380 ASSERT(CurrentToken() == Token::kTHIS); |
| 2392 const intptr_t call_pos = TokenPos(); | 2381 const intptr_t call_pos = TokenPos(); |
| 2393 ConsumeToken(); | 2382 ConsumeToken(); |
| 2394 String& ctor_name = String::Handle(cls.Name()); | 2383 String& ctor_name = String::Handle(cls.Name()); |
| 2395 | 2384 |
| 2396 ctor_name = String::Concat(ctor_name, Symbols::Dot()); | 2385 ctor_name = String::Concat(ctor_name, Symbols::Dot()); |
| 2397 if (CurrentToken() == Token::kPERIOD) { | 2386 if (CurrentToken() == Token::kPERIOD) { |
| 2398 ConsumeToken(); | 2387 ConsumeToken(); |
| 2399 ctor_name = String::Concat(ctor_name, | 2388 ctor_name = String::Concat(ctor_name, |
| 2400 *ExpectIdentifier("constructor name expected")); | 2389 *ExpectIdentifier("constructor name expected")); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2561 } | 2550 } |
| 2562 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); | 2551 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
| 2563 | 2552 |
| 2564 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); | 2553 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); |
| 2565 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 2554 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 2566 ASSERT(func.NumParameters() == params.parameters->length()); | 2555 ASSERT(func.NumParameters() == params.parameters->length()); |
| 2567 | 2556 |
| 2568 // Now populate function scope with the formal parameters. | 2557 // Now populate function scope with the formal parameters. |
| 2569 AddFormalParamsToScope(¶ms, current_block_->scope); | 2558 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 2570 | 2559 |
| 2571 // Initialize instance fields that have an explicit initializer expression. | 2560 const bool is_redirecting_constructor = |
| 2572 // The formal parameter names must not be visible to the instance | 2561 (CurrentToken() == Token::kCOLON) && |
| 2573 // field initializer expressions, yet the parameters must be added to | 2562 ((LookaheadToken(1) == Token::kTHIS) && |
| 2574 // the scope so the expressions use the correct offsets for 'this' when | 2563 ((LookaheadToken(2) == Token::kLPAREN) || |
| 2575 // storing values. We make the formal parameters temporarily invisible | 2564 ((LookaheadToken(2) == Token::kPERIOD) && |
| 2576 // while parsing the instance field initializer expressions. | 2565 (LookaheadToken(4) == Token::kLPAREN)))); |
| 2577 params.SetInvisible(true); | 2566 |
| 2578 GrowableArray<Field*> initialized_fields; | 2567 GrowableArray<Field*> initialized_fields; |
| 2579 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 2568 LocalVariable* receiver = (*params.parameters)[0].var; |
| 2580 OpenBlock(); | 2569 OpenBlock(); |
| 2581 ParseInitializedInstanceFields(cls, receiver, &initialized_fields); | |
| 2582 // Make the parameters (which are in the outer scope) visible again. | |
| 2583 params.SetInvisible(false); | |
| 2584 | 2570 |
| 2585 // Turn formal field parameters into field initializers or report error | 2571 // If this is not a redirecting constructor, initialize |
| 2586 // if the function is not a constructor. | 2572 // instance fields that have an explicit initializer expression. |
| 2573 if (!is_redirecting_constructor) { |
| 2574 // The formal parameter names must not be visible to the instance |
| 2575 // field initializer expressions, yet the parameters must be added to |
| 2576 // the scope so the expressions use the correct offsets for 'this' when |
| 2577 // storing values. We make the formal parameters temporarily invisible |
| 2578 // while parsing the instance field initializer expressions. |
| 2579 params.SetInvisible(true); |
| 2580 ParseInitializedInstanceFields(cls, receiver, &initialized_fields); |
| 2581 // Make the parameters (which are in the outer scope) visible again. |
| 2582 params.SetInvisible(false); |
| 2583 } |
| 2584 |
| 2585 // Turn formal field parameters into field initializers. |
| 2587 if (params.has_field_initializer) { | 2586 if (params.has_field_initializer) { |
| 2588 for (int i = 0; i < params.parameters->length(); i++) { | 2587 // First two parameters are implicit receiver and phase. |
| 2588 ASSERT(params.parameters->length() >= 2); |
| 2589 for (int i = 2; i < params.parameters->length(); i++) { |
| 2589 ParamDesc& param = (*params.parameters)[i]; | 2590 ParamDesc& param = (*params.parameters)[i]; |
| 2590 if (param.is_field_initializer) { | 2591 if (param.is_field_initializer) { |
| 2591 const String& field_name = *param.name; | 2592 const String& field_name = *param.name; |
| 2592 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 2593 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 2593 if (field.IsNull()) { | 2594 if (field.IsNull()) { |
| 2594 ErrorMsg(param.name_pos, | 2595 ErrorMsg(param.name_pos, |
| 2595 "unresolved reference to instance field '%s'", | 2596 "unresolved reference to instance field '%s'", |
| 2596 field_name.ToCString()); | 2597 field_name.ToCString()); |
| 2597 } | 2598 } |
| 2599 if (is_redirecting_constructor) { |
| 2600 ErrorMsg(param.name_pos, |
| 2601 "redirecting constructors may not have " |
| 2602 "initializing formal parameters"); |
| 2603 } |
| 2598 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); | 2604 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); |
| 2599 AstNode* instance = new LoadLocalNode(param.name_pos, receiver); | 2605 AstNode* instance = new LoadLocalNode(param.name_pos, receiver); |
| 2600 // Initializing formals cannot be used in the explicit initializer | 2606 // Initializing formals cannot be used in the explicit initializer |
| 2601 // list, nor can they be used in the constructor body. | 2607 // list, nor can they be used in the constructor body. |
| 2602 // Thus, they are set to be invisible when added to the scope. | 2608 // Thus, they are set to be invisible when added to the scope. |
| 2603 LocalVariable* p = param.var; | 2609 LocalVariable* p = param.var; |
| 2604 ASSERT(p != NULL); | 2610 ASSERT(p != NULL); |
| 2605 ASSERT(p->is_invisible()); | 2611 ASSERT(p->is_invisible()); |
| 2606 AstNode* value = new LoadLocalNode(param.name_pos, p); | 2612 AstNode* value = new LoadLocalNode(param.name_pos, p); |
| 2607 EnsureExpressionTemp(); | 2613 EnsureExpressionTemp(); |
| 2608 AstNode* initializer = new StoreInstanceFieldNode( | 2614 AstNode* initializer = new StoreInstanceFieldNode( |
| 2609 param.name_pos, instance, field, value); | 2615 param.name_pos, instance, field, value); |
| 2610 current_block_->statements->Add(initializer); | 2616 current_block_->statements->Add(initializer); |
| 2611 } | 2617 } |
| 2612 } | 2618 } |
| 2613 } | 2619 } |
| 2614 | 2620 |
| 2615 // Now parse the explicit initializer list or constructor redirection. | 2621 if (is_redirecting_constructor) { |
| 2616 ParseInitializers(cls, receiver, &initialized_fields); | 2622 ParseConstructorRedirection(cls, receiver); |
| 2623 } else { |
| 2624 ParseInitializers(cls, receiver, &initialized_fields); |
| 2625 } |
| 2617 | 2626 |
| 2618 SequenceNode* init_statements = CloseBlock(); | 2627 SequenceNode* init_statements = CloseBlock(); |
| 2619 if (init_statements->length() > 0) { | 2628 if (init_statements->length() > 0) { |
| 2620 // Generate guard around the initializer code. | 2629 // Generate guard around the initializer code. |
| 2621 LocalVariable* phase_param = LookupPhaseParameter(); | 2630 LocalVariable* phase_param = LookupPhaseParameter(); |
| 2622 AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param); | 2631 AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param); |
| 2623 AstNode* phase_check = new BinaryOpNode( | 2632 AstNode* phase_check = new BinaryOpNode( |
| 2624 TokenPos(), Token::kBIT_AND, phase_value, | 2633 TokenPos(), Token::kBIT_AND, phase_value, |
| 2625 new LiteralNode(TokenPos(), | 2634 new LiteralNode(TokenPos(), |
| 2626 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); | 2635 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2653 break; | 2662 break; |
| 2654 } | 2663 } |
| 2655 } | 2664 } |
| 2656 } | 2665 } |
| 2657 if (super_call != NULL) { | 2666 if (super_call != NULL) { |
| 2658 // Generate an implicit call to the super constructor's body. | 2667 // Generate an implicit call to the super constructor's body. |
| 2659 // We need to patch the super _initializer_ call so that it | 2668 // We need to patch the super _initializer_ call so that it |
| 2660 // saves the evaluated actual arguments in temporary variables. | 2669 // saves the evaluated actual arguments in temporary variables. |
| 2661 // The temporary variables are necessary so that the argument | 2670 // The temporary variables are necessary so that the argument |
| 2662 // expressions are not evaluated twice. | 2671 // expressions are not evaluated twice. |
| 2672 // Note: we should never get here in the case of a redirecting |
| 2673 // constructor. In that case, the call to the target constructor |
| 2674 // is the "super call" and is implicitly at the end of the |
| 2675 // initializer list. |
| 2676 ASSERT(!is_redirecting_constructor); |
| 2663 ArgumentListNode* ctor_args = super_call->arguments(); | 2677 ArgumentListNode* ctor_args = super_call->arguments(); |
| 2664 // The super initializer call has at least 2 arguments: the | 2678 // The super initializer call has at least 2 arguments: the |
| 2665 // implicit receiver, and the hidden construction phase. | 2679 // implicit receiver, and the hidden construction phase. |
| 2666 ASSERT(ctor_args->length() >= 2); | 2680 ASSERT(ctor_args->length() >= 2); |
| 2667 for (int i = 2; i < ctor_args->length(); i++) { | 2681 for (int i = 2; i < ctor_args->length(); i++) { |
| 2668 AstNode* arg = ctor_args->NodeAt(i); | 2682 AstNode* arg = ctor_args->NodeAt(i); |
| 2669 if (!IsSimpleLocalOrLiteralNode(arg)) { | 2683 if (!IsSimpleLocalOrLiteralNode(arg)) { |
| 2670 LocalVariable* temp = | 2684 LocalVariable* temp = |
| 2671 CreateTempConstVariable(arg->token_pos(), "sca"); | 2685 CreateTempConstVariable(arg->token_pos(), "sca"); |
| 2672 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); | 2686 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2712 } | 2726 } |
| 2713 } | 2727 } |
| 2714 ASSERT(super_ctor.AreValidArguments(super_call_args->length(), | 2728 ASSERT(super_ctor.AreValidArguments(super_call_args->length(), |
| 2715 super_call_args->names(), | 2729 super_call_args->names(), |
| 2716 NULL)); | 2730 NULL)); |
| 2717 current_block_->statements->Add( | 2731 current_block_->statements->Add( |
| 2718 new StaticCallNode(body_pos, super_ctor, super_call_args)); | 2732 new StaticCallNode(body_pos, super_ctor, super_call_args)); |
| 2719 } | 2733 } |
| 2720 | 2734 |
| 2721 if (CurrentToken() == Token::kLBRACE) { | 2735 if (CurrentToken() == Token::kLBRACE) { |
| 2736 // We checked in the top-level parse phase that a redirecting |
| 2737 // constructor does not have a body. |
| 2738 ASSERT(!is_redirecting_constructor); |
| 2722 ConsumeToken(); | 2739 ConsumeToken(); |
| 2723 ParseStatementSequence(); | 2740 ParseStatementSequence(); |
| 2724 ExpectToken(Token::kRBRACE); | 2741 ExpectToken(Token::kRBRACE); |
| 2725 } else if (CurrentToken() == Token::kARROW) { | 2742 } else if (CurrentToken() == Token::kARROW) { |
| 2726 ErrorMsg("constructors may not return a value"); | 2743 ErrorMsg("constructors may not return a value"); |
| 2727 } else if (IsLiteral("native")) { | 2744 } else if (IsLiteral("native")) { |
| 2728 ErrorMsg("native constructors not supported"); | 2745 ErrorMsg("native constructors not supported"); |
| 2729 } else if (CurrentToken() == Token::kSEMICOLON) { | 2746 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 2730 // Some constructors have no function body. | 2747 // Some constructors have no function body. |
| 2731 ConsumeToken(); | 2748 ConsumeToken(); |
| (...skipping 7693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10425 void Parser::SkipQualIdent() { | 10442 void Parser::SkipQualIdent() { |
| 10426 ASSERT(IsIdentifier()); | 10443 ASSERT(IsIdentifier()); |
| 10427 ConsumeToken(); | 10444 ConsumeToken(); |
| 10428 if (CurrentToken() == Token::kPERIOD) { | 10445 if (CurrentToken() == Token::kPERIOD) { |
| 10429 ConsumeToken(); // Consume the kPERIOD token. | 10446 ConsumeToken(); // Consume the kPERIOD token. |
| 10430 ExpectIdentifier("identifier expected after '.'"); | 10447 ExpectIdentifier("identifier expected after '.'"); |
| 10431 } | 10448 } |
| 10432 } | 10449 } |
| 10433 | 10450 |
| 10434 } // namespace dart | 10451 } // namespace dart |
| OLD | NEW |