Chromium Code Reviews| 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 "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
| (...skipping 3602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3613 } | 3613 } |
| 3614 } | 3614 } |
| 3615 } | 3615 } |
| 3616 | 3616 |
| 3617 | 3617 |
| 3618 void Parser::ParseTopLevelFunction(TopLevel* top_level) { | 3618 void Parser::ParseTopLevelFunction(TopLevel* top_level) { |
| 3619 TRACE_PARSER("ParseTopLevelFunction"); | 3619 TRACE_PARSER("ParseTopLevelFunction"); |
| 3620 AbstractType& result_type = Type::Handle(Type::DynamicType()); | 3620 AbstractType& result_type = Type::Handle(Type::DynamicType()); |
| 3621 const bool is_static = true; | 3621 const bool is_static = true; |
| 3622 bool is_external = false; | 3622 bool is_external = false; |
| 3623 if (CurrentToken() == Token::kEXTERNAL) { | 3623 bool is_patch = false; |
| 3624 if ((CurrentToken() == Token::kIDENT) && | |
| 3625 (CurrentLiteral()->Equals("patch"))) { | |
| 3626 ConsumeToken(); | |
|
hausner
2012/08/07 22:56:36
This code can't handle an untyped top-level functi
Ivan Posva
2012/08/08 00:56:52
external is a pseudo-keyword -> not a problem
A ty
| |
| 3627 is_patch = true; | |
| 3628 } else if (CurrentToken() == Token::kEXTERNAL) { | |
| 3624 ConsumeToken(); | 3629 ConsumeToken(); |
| 3625 is_external = true; | 3630 is_external = true; |
| 3626 } | 3631 } |
| 3627 if (CurrentToken() == Token::kVOID) { | 3632 if (CurrentToken() == Token::kVOID) { |
| 3628 ConsumeToken(); | 3633 ConsumeToken(); |
| 3629 result_type = Type::VoidType(); | 3634 result_type = Type::VoidType(); |
| 3630 } else { | 3635 } else { |
| 3631 // Parse optional type. | 3636 // Parse optional type. |
| 3632 if ((CurrentToken() == Token::kIDENT) && | 3637 if ((CurrentToken() == Token::kIDENT) && |
| 3633 (LookaheadToken(1) != Token::kLPAREN)) { | 3638 (LookaheadToken(1) != Token::kLPAREN)) { |
| 3634 result_type = ParseType(ClassFinalizer::kTryResolve); | 3639 result_type = ParseType(ClassFinalizer::kTryResolve); |
| 3635 } | 3640 } |
| 3636 } | 3641 } |
| 3637 const intptr_t name_pos = TokenPos(); | 3642 const intptr_t name_pos = TokenPos(); |
| 3638 const String& func_name = *ExpectIdentifier("function name expected"); | 3643 const String& func_name = *ExpectIdentifier("function name expected"); |
| 3639 | 3644 |
| 3640 if (library_.LookupObject(func_name) != Object::null()) { | 3645 bool found = library_.LookupObject(func_name) != Object::null(); |
| 3646 if (found && !is_patch) { | |
| 3641 ErrorMsg(name_pos, "'%s' is already defined", func_name.ToCString()); | 3647 ErrorMsg(name_pos, "'%s' is already defined", func_name.ToCString()); |
| 3648 } else if (!found && is_patch) { | |
| 3649 ErrorMsg(name_pos, "missing '%s' cannot be patched", func_name.ToCString()); | |
| 3642 } | 3650 } |
| 3643 String& accessor_name = String::Handle(Field::GetterName(func_name)); | 3651 String& accessor_name = String::Handle(Field::GetterName(func_name)); |
| 3644 if (library_.LookupObject(accessor_name) != Object::null()) { | 3652 if (library_.LookupObject(accessor_name) != Object::null()) { |
| 3645 ErrorMsg(name_pos, "'%s' is already defined as getter", | 3653 ErrorMsg(name_pos, "'%s' is already defined as getter", |
| 3646 func_name.ToCString()); | 3654 func_name.ToCString()); |
| 3647 } | 3655 } |
| 3648 accessor_name = Field::SetterName(func_name); | 3656 accessor_name = Field::SetterName(func_name); |
| 3649 if (library_.LookupObject(accessor_name) != Object::null()) { | 3657 if (library_.LookupObject(accessor_name) != Object::null()) { |
| 3650 ErrorMsg(name_pos, "'%s' is already defined as setter", | 3658 ErrorMsg(name_pos, "'%s' is already defined as setter", |
| 3651 func_name.ToCString()); | 3659 func_name.ToCString()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 3681 is_static, | 3689 is_static, |
| 3682 /* is_const = */ false, | 3690 /* is_const = */ false, |
| 3683 /* is_abstract = */ false, | 3691 /* is_abstract = */ false, |
| 3684 is_external, | 3692 is_external, |
| 3685 current_class(), | 3693 current_class(), |
| 3686 function_pos)); | 3694 function_pos)); |
| 3687 func.set_result_type(result_type); | 3695 func.set_result_type(result_type); |
| 3688 func.set_end_token_pos(function_end_pos); | 3696 func.set_end_token_pos(function_end_pos); |
| 3689 AddFormalParamsToFunction(¶ms, func); | 3697 AddFormalParamsToFunction(¶ms, func); |
| 3690 top_level->functions.Add(func); | 3698 top_level->functions.Add(func); |
| 3691 library_.AddObject(func, func_name); | 3699 if (!is_patch) { |
| 3700 library_.AddObject(func, func_name); | |
| 3701 } else { | |
| 3702 library_.ReplaceObject(func, func_name); | |
| 3703 } | |
| 3692 } | 3704 } |
| 3693 | 3705 |
| 3694 | 3706 |
| 3695 void Parser::ParseTopLevelAccessor(TopLevel* top_level) { | 3707 void Parser::ParseTopLevelAccessor(TopLevel* top_level) { |
| 3696 TRACE_PARSER("ParseTopLevelAccessor"); | 3708 TRACE_PARSER("ParseTopLevelAccessor"); |
| 3697 const bool is_static = true; | 3709 const bool is_static = true; |
| 3710 bool is_external = false; | |
| 3711 bool is_patch = false; | |
| 3698 AbstractType& result_type = AbstractType::Handle(); | 3712 AbstractType& result_type = AbstractType::Handle(); |
| 3713 if ((CurrentToken() == Token::kIDENT) && | |
| 3714 (CurrentLiteral()->Equals("patch"))) { | |
|
hausner
2012/08/07 22:56:36
This does not work for a getter that declares a re
Ivan Posva
2012/08/08 00:56:52
ditto.
| |
| 3715 ConsumeToken(); | |
| 3716 is_patch = true; | |
| 3717 } else if (CurrentToken() == Token::kEXTERNAL) { | |
| 3718 ConsumeToken(); | |
| 3719 is_external = true; | |
| 3720 } | |
| 3699 bool is_getter = (CurrentToken() == Token::kGET); | 3721 bool is_getter = (CurrentToken() == Token::kGET); |
| 3700 if (CurrentToken() == Token::kGET || | 3722 if (CurrentToken() == Token::kGET || |
| 3701 CurrentToken() == Token::kSET) { | 3723 CurrentToken() == Token::kSET) { |
| 3702 ConsumeToken(); | 3724 ConsumeToken(); |
| 3703 result_type = Type::DynamicType(); | 3725 result_type = Type::DynamicType(); |
| 3704 } else { | 3726 } else { |
| 3705 if (CurrentToken() == Token::kVOID) { | 3727 if (CurrentToken() == Token::kVOID) { |
| 3706 ConsumeToken(); | 3728 ConsumeToken(); |
| 3707 result_type = Type::VoidType(); | 3729 result_type = Type::VoidType(); |
| 3708 } else { | 3730 } else { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 3737 if ((params.num_fixed_parameters != expected_num_parameters) || | 3759 if ((params.num_fixed_parameters != expected_num_parameters) || |
| 3738 (params.num_optional_parameters != 0)) { | 3760 (params.num_optional_parameters != 0)) { |
| 3739 ErrorMsg(name_pos, "illegal %s parameters", | 3761 ErrorMsg(name_pos, "illegal %s parameters", |
| 3740 is_getter ? "getter" : "setter"); | 3762 is_getter ? "getter" : "setter"); |
| 3741 } | 3763 } |
| 3742 | 3764 |
| 3743 if (library_.LookupObject(*field_name) != Object::null()) { | 3765 if (library_.LookupObject(*field_name) != Object::null()) { |
| 3744 ErrorMsg(name_pos, "'%s' is already defined in this library", | 3766 ErrorMsg(name_pos, "'%s' is already defined in this library", |
| 3745 field_name->ToCString()); | 3767 field_name->ToCString()); |
| 3746 } | 3768 } |
| 3747 if (library_.LookupObject(accessor_name) != Object::null()) { | 3769 bool found = library_.LookupObject(accessor_name) != Object::null(); |
| 3770 if (found && !is_patch) { | |
| 3748 ErrorMsg(name_pos, "%s for '%s' is already defined", | 3771 ErrorMsg(name_pos, "%s for '%s' is already defined", |
| 3749 is_getter ? "getter" : "setter", | 3772 is_getter ? "getter" : "setter", |
| 3750 field_name->ToCString()); | 3773 field_name->ToCString()); |
| 3774 } else if (!found && is_patch) { | |
| 3775 ErrorMsg(name_pos, "missing %s for '%s' cannot be patched", | |
| 3776 is_getter ? "getter" : "setter", | |
| 3777 field_name->ToCString()); | |
| 3751 } | 3778 } |
| 3752 | 3779 |
| 3753 if (CurrentToken() == Token::kLBRACE) { | 3780 if (is_external) { |
| 3781 ExpectSemicolon(); | |
|
hausner
2012/08/07 22:56:36
Can we handle the common case first?
Ivan Posva
2012/08/08 00:56:52
Then
external get a() {}
would pass without erro
| |
| 3782 } else if (CurrentToken() == Token::kLBRACE) { | |
| 3754 SkipBlock(); | 3783 SkipBlock(); |
| 3755 } else if (CurrentToken() == Token::kARROW) { | 3784 } else if (CurrentToken() == Token::kARROW) { |
| 3756 ConsumeToken(); | 3785 ConsumeToken(); |
| 3757 SkipExpr(); | 3786 SkipExpr(); |
| 3758 ExpectSemicolon(); | 3787 ExpectSemicolon(); |
| 3759 } else if (IsLiteral("native")) { | 3788 } else if (IsLiteral("native")) { |
| 3760 ParseNativeDeclaration(); | 3789 ParseNativeDeclaration(); |
| 3761 } else { | 3790 } else { |
| 3762 ErrorMsg("function block expected"); | 3791 ErrorMsg("function block expected"); |
| 3763 } | 3792 } |
| 3764 Function& func = Function::Handle( | 3793 Function& func = Function::Handle( |
| 3765 Function::New(accessor_name, | 3794 Function::New(accessor_name, |
| 3766 is_getter? RawFunction::kGetterFunction : | 3795 is_getter? RawFunction::kGetterFunction : |
| 3767 RawFunction::kSetterFunction, | 3796 RawFunction::kSetterFunction, |
| 3768 is_static, | 3797 is_static, |
| 3769 /* is_const = */ false, | 3798 /* is_const = */ false, |
| 3770 /* is_abstract = */ false, | 3799 /* is_abstract = */ false, |
| 3771 /* is_external = */ false, | 3800 is_external, |
| 3772 current_class(), | 3801 current_class(), |
| 3773 accessor_pos)); | 3802 accessor_pos)); |
| 3774 func.set_result_type(result_type); | 3803 func.set_result_type(result_type); |
| 3775 AddFormalParamsToFunction(¶ms, func); | 3804 AddFormalParamsToFunction(¶ms, func); |
| 3776 top_level->functions.Add(func); | 3805 top_level->functions.Add(func); |
| 3777 library_.AddObject(func, accessor_name); | 3806 if (!is_patch) { |
| 3807 library_.AddObject(func, accessor_name); | |
| 3808 } else { | |
| 3809 library_.ReplaceObject(func, accessor_name); | |
| 3810 } | |
| 3778 } | 3811 } |
| 3779 | 3812 |
| 3780 | 3813 |
| 3781 void Parser::ParseLibraryName() { | 3814 void Parser::ParseLibraryName() { |
| 3782 TRACE_PARSER("ParseLibraryName"); | 3815 TRACE_PARSER("ParseLibraryName"); |
| 3783 if ((script_.kind() == RawScript::kLibraryTag) && | 3816 if ((script_.kind() == RawScript::kLibraryTag) && |
| 3784 (CurrentToken() != Token::kLIBRARY)) { | 3817 (CurrentToken() != Token::kLIBRARY)) { |
| 3785 // Handle error case early to get consistent error message. | 3818 // Handle error case early to get consistent error message. |
| 3786 ExpectToken(Token::kLIBRARY); | 3819 ExpectToken(Token::kLIBRARY); |
| 3787 } | 3820 } |
| (...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4685 SetPosition(saved_pos); | 4718 SetPosition(saved_pos); |
| 4686 return is_var_decl; | 4719 return is_var_decl; |
| 4687 } | 4720 } |
| 4688 | 4721 |
| 4689 | 4722 |
| 4690 // Look ahead to detect whether the next tokens should be parsed as | 4723 // Look ahead to detect whether the next tokens should be parsed as |
| 4691 // a function declaration. Token position remains unchanged. | 4724 // a function declaration. Token position remains unchanged. |
| 4692 bool Parser::IsFunctionDeclaration() { | 4725 bool Parser::IsFunctionDeclaration() { |
| 4693 const intptr_t saved_pos = TokenPos(); | 4726 const intptr_t saved_pos = TokenPos(); |
| 4694 bool is_external = false; | 4727 bool is_external = false; |
| 4695 if (is_top_level_ && (CurrentToken() == Token::kEXTERNAL)) { | 4728 if (is_top_level_) { |
| 4696 // Skip over 'external' for top-level function declarations. | 4729 if (is_patch_source() && |
| 4697 is_external = true; | 4730 (CurrentToken() == Token::kIDENT) && |
| 4698 ConsumeToken(); | 4731 (CurrentLiteral()->Equals("patch"))) { |
| 4732 // Skip over 'patch' for top-level function declarations in patch sources. | |
| 4733 ConsumeToken(); | |
| 4734 } else if (CurrentToken() == Token::kEXTERNAL) { | |
| 4735 // Skip over 'external' for top-level function declarations. | |
| 4736 is_external = true; | |
| 4737 ConsumeToken(); | |
| 4738 } | |
| 4699 } | 4739 } |
| 4700 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { | 4740 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { |
| 4701 // Possibly a function without explicit return type. | 4741 // Possibly a function without explicit return type. |
| 4702 ConsumeToken(); // Consume function identifier. | 4742 ConsumeToken(); // Consume function identifier. |
| 4703 } else if (TryParseReturnType()) { | 4743 } else if (TryParseReturnType()) { |
| 4704 if (!IsIdentifier()) { | 4744 if (!IsIdentifier()) { |
| 4705 SetPosition(saved_pos); | 4745 SetPosition(saved_pos); |
| 4706 return false; | 4746 return false; |
| 4707 } | 4747 } |
| 4708 ConsumeToken(); // Consume function identifier. | 4748 ConsumeToken(); // Consume function identifier. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 4720 SetPosition(saved_pos); | 4760 SetPosition(saved_pos); |
| 4721 return true; | 4761 return true; |
| 4722 } | 4762 } |
| 4723 } | 4763 } |
| 4724 SetPosition(saved_pos); | 4764 SetPosition(saved_pos); |
| 4725 return false; | 4765 return false; |
| 4726 } | 4766 } |
| 4727 | 4767 |
| 4728 | 4768 |
| 4729 bool Parser::IsTopLevelAccessor() { | 4769 bool Parser::IsTopLevelAccessor() { |
| 4770 const intptr_t saved_pos = TokenPos(); | |
| 4771 if (is_patch_source() && | |
| 4772 (CurrentToken() == Token::kIDENT) && | |
| 4773 (CurrentLiteral()->Equals("patch"))) { | |
| 4774 ConsumeToken(); | |
| 4775 } else if (CurrentToken() == Token::kEXTERNAL) { | |
| 4776 ConsumeToken(); | |
| 4777 } | |
| 4730 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { | 4778 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { |
| 4779 SetPosition(saved_pos); | |
| 4731 return true; | 4780 return true; |
| 4732 } | 4781 } |
| 4733 const intptr_t saved_pos = TokenPos(); | |
| 4734 if (TryParseReturnType()) { | 4782 if (TryParseReturnType()) { |
| 4735 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { | 4783 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { |
| 4736 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. | 4784 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. |
| 4737 SetPosition(saved_pos); | 4785 SetPosition(saved_pos); |
| 4738 return true; | 4786 return true; |
| 4739 } | 4787 } |
| 4740 } | 4788 } |
| 4741 } | 4789 } |
| 4742 SetPosition(saved_pos); | 4790 SetPosition(saved_pos); |
| 4743 return false; | 4791 return false; |
| (...skipping 4200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8944 void Parser::SkipQualIdent() { | 8992 void Parser::SkipQualIdent() { |
| 8945 ASSERT(IsIdentifier()); | 8993 ASSERT(IsIdentifier()); |
| 8946 ConsumeToken(); | 8994 ConsumeToken(); |
| 8947 if (CurrentToken() == Token::kPERIOD) { | 8995 if (CurrentToken() == Token::kPERIOD) { |
| 8948 ConsumeToken(); // Consume the kPERIOD token. | 8996 ConsumeToken(); // Consume the kPERIOD token. |
| 8949 ExpectIdentifier("identifier expected after '.'"); | 8997 ExpectIdentifier("identifier expected after '.'"); |
| 8950 } | 8998 } |
| 8951 } | 8999 } |
| 8952 | 9000 |
| 8953 } // namespace dart | 9001 } // namespace dart |
| OLD | NEW |