Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1371)

Side by Side Diff: runtime/vm/parser.cc

Issue 10824209: - Allow patching of top-level methods and accessors. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 (is_patch_source() &&
3625 (CurrentToken() == Token::kIDENT) &&
3626 CurrentLiteral()->Equals("patch") &&
3627 (LookaheadToken(1) != Token::kLPAREN)) {
3628 ConsumeToken();
3629 is_patch = true;
3630 } else if (CurrentToken() == Token::kEXTERNAL) {
3624 ConsumeToken(); 3631 ConsumeToken();
3625 is_external = true; 3632 is_external = true;
3626 } 3633 }
3627 if (CurrentToken() == Token::kVOID) { 3634 if (CurrentToken() == Token::kVOID) {
3628 ConsumeToken(); 3635 ConsumeToken();
3629 result_type = Type::VoidType(); 3636 result_type = Type::VoidType();
3630 } else { 3637 } else {
3631 // Parse optional type. 3638 // Parse optional type.
3632 if ((CurrentToken() == Token::kIDENT) && 3639 if ((CurrentToken() == Token::kIDENT) &&
3633 (LookaheadToken(1) != Token::kLPAREN)) { 3640 (LookaheadToken(1) != Token::kLPAREN)) {
3634 result_type = ParseType(ClassFinalizer::kTryResolve); 3641 result_type = ParseType(ClassFinalizer::kTryResolve);
3635 } 3642 }
3636 } 3643 }
3637 const intptr_t name_pos = TokenPos(); 3644 const intptr_t name_pos = TokenPos();
3638 const String& func_name = *ExpectIdentifier("function name expected"); 3645 const String& func_name = *ExpectIdentifier("function name expected");
3639 3646
3640 if (library_.LookupObject(func_name) != Object::null()) { 3647 bool found = library_.LookupObject(func_name) != Object::null();
3648 if (found && !is_patch) {
3641 ErrorMsg(name_pos, "'%s' is already defined", func_name.ToCString()); 3649 ErrorMsg(name_pos, "'%s' is already defined", func_name.ToCString());
3650 } else if (!found && is_patch) {
3651 ErrorMsg(name_pos, "missing '%s' cannot be patched", func_name.ToCString());
3642 } 3652 }
3643 String& accessor_name = String::Handle(Field::GetterName(func_name)); 3653 String& accessor_name = String::Handle(Field::GetterName(func_name));
3644 if (library_.LookupObject(accessor_name) != Object::null()) { 3654 if (library_.LookupObject(accessor_name) != Object::null()) {
3645 ErrorMsg(name_pos, "'%s' is already defined as getter", 3655 ErrorMsg(name_pos, "'%s' is already defined as getter",
3646 func_name.ToCString()); 3656 func_name.ToCString());
3647 } 3657 }
3648 accessor_name = Field::SetterName(func_name); 3658 accessor_name = Field::SetterName(func_name);
3649 if (library_.LookupObject(accessor_name) != Object::null()) { 3659 if (library_.LookupObject(accessor_name) != Object::null()) {
3650 ErrorMsg(name_pos, "'%s' is already defined as setter", 3660 ErrorMsg(name_pos, "'%s' is already defined as setter",
3651 func_name.ToCString()); 3661 func_name.ToCString());
(...skipping 29 matching lines...) Expand all
3681 is_static, 3691 is_static,
3682 /* is_const = */ false, 3692 /* is_const = */ false,
3683 /* is_abstract = */ false, 3693 /* is_abstract = */ false,
3684 is_external, 3694 is_external,
3685 current_class(), 3695 current_class(),
3686 function_pos)); 3696 function_pos));
3687 func.set_result_type(result_type); 3697 func.set_result_type(result_type);
3688 func.set_end_token_pos(function_end_pos); 3698 func.set_end_token_pos(function_end_pos);
3689 AddFormalParamsToFunction(&params, func); 3699 AddFormalParamsToFunction(&params, func);
3690 top_level->functions.Add(func); 3700 top_level->functions.Add(func);
3691 library_.AddObject(func, func_name); 3701 if (!is_patch) {
3702 library_.AddObject(func, func_name);
3703 } else {
3704 library_.ReplaceObject(func, func_name);
3705 }
3692 } 3706 }
3693 3707
3694 3708
3695 void Parser::ParseTopLevelAccessor(TopLevel* top_level) { 3709 void Parser::ParseTopLevelAccessor(TopLevel* top_level) {
3696 TRACE_PARSER("ParseTopLevelAccessor"); 3710 TRACE_PARSER("ParseTopLevelAccessor");
3697 const bool is_static = true; 3711 const bool is_static = true;
3712 bool is_external = false;
3713 bool is_patch = false;
3698 AbstractType& result_type = AbstractType::Handle(); 3714 AbstractType& result_type = AbstractType::Handle();
3715 if (is_patch_source() &&
3716 (CurrentToken() == Token::kIDENT) &&
3717 (CurrentLiteral()->Equals("patch"))) {
3718 ConsumeToken();
3719 is_patch = true;
3720 } else if (CurrentToken() == Token::kEXTERNAL) {
3721 ConsumeToken();
3722 is_external = true;
3723 }
3699 bool is_getter = (CurrentToken() == Token::kGET); 3724 bool is_getter = (CurrentToken() == Token::kGET);
3700 if (CurrentToken() == Token::kGET || 3725 if (CurrentToken() == Token::kGET ||
3701 CurrentToken() == Token::kSET) { 3726 CurrentToken() == Token::kSET) {
3702 ConsumeToken(); 3727 ConsumeToken();
3703 result_type = Type::DynamicType(); 3728 result_type = Type::DynamicType();
3704 } else { 3729 } else {
3705 if (CurrentToken() == Token::kVOID) { 3730 if (CurrentToken() == Token::kVOID) {
3706 ConsumeToken(); 3731 ConsumeToken();
3707 result_type = Type::VoidType(); 3732 result_type = Type::VoidType();
3708 } else { 3733 } else {
(...skipping 28 matching lines...) Expand all
3737 if ((params.num_fixed_parameters != expected_num_parameters) || 3762 if ((params.num_fixed_parameters != expected_num_parameters) ||
3738 (params.num_optional_parameters != 0)) { 3763 (params.num_optional_parameters != 0)) {
3739 ErrorMsg(name_pos, "illegal %s parameters", 3764 ErrorMsg(name_pos, "illegal %s parameters",
3740 is_getter ? "getter" : "setter"); 3765 is_getter ? "getter" : "setter");
3741 } 3766 }
3742 3767
3743 if (library_.LookupObject(*field_name) != Object::null()) { 3768 if (library_.LookupObject(*field_name) != Object::null()) {
3744 ErrorMsg(name_pos, "'%s' is already defined in this library", 3769 ErrorMsg(name_pos, "'%s' is already defined in this library",
3745 field_name->ToCString()); 3770 field_name->ToCString());
3746 } 3771 }
3747 if (library_.LookupObject(accessor_name) != Object::null()) { 3772 bool found = library_.LookupObject(accessor_name) != Object::null();
3773 if (found && !is_patch) {
3748 ErrorMsg(name_pos, "%s for '%s' is already defined", 3774 ErrorMsg(name_pos, "%s for '%s' is already defined",
3749 is_getter ? "getter" : "setter", 3775 is_getter ? "getter" : "setter",
3750 field_name->ToCString()); 3776 field_name->ToCString());
3777 } else if (!found && is_patch) {
3778 ErrorMsg(name_pos, "missing %s for '%s' cannot be patched",
3779 is_getter ? "getter" : "setter",
3780 field_name->ToCString());
3751 } 3781 }
3752 3782
3753 if (CurrentToken() == Token::kLBRACE) { 3783 if (is_external) {
3784 ExpectSemicolon();
3785 } else if (CurrentToken() == Token::kLBRACE) {
3754 SkipBlock(); 3786 SkipBlock();
3755 } else if (CurrentToken() == Token::kARROW) { 3787 } else if (CurrentToken() == Token::kARROW) {
3756 ConsumeToken(); 3788 ConsumeToken();
3757 SkipExpr(); 3789 SkipExpr();
3758 ExpectSemicolon(); 3790 ExpectSemicolon();
3759 } else if (IsLiteral("native")) { 3791 } else if (IsLiteral("native")) {
3760 ParseNativeDeclaration(); 3792 ParseNativeDeclaration();
3761 } else { 3793 } else {
3762 ErrorMsg("function block expected"); 3794 ErrorMsg("function block expected");
3763 } 3795 }
3764 Function& func = Function::Handle( 3796 Function& func = Function::Handle(
3765 Function::New(accessor_name, 3797 Function::New(accessor_name,
3766 is_getter? RawFunction::kGetterFunction : 3798 is_getter? RawFunction::kGetterFunction :
3767 RawFunction::kSetterFunction, 3799 RawFunction::kSetterFunction,
3768 is_static, 3800 is_static,
3769 /* is_const = */ false, 3801 /* is_const = */ false,
3770 /* is_abstract = */ false, 3802 /* is_abstract = */ false,
3771 /* is_external = */ false, 3803 is_external,
3772 current_class(), 3804 current_class(),
3773 accessor_pos)); 3805 accessor_pos));
3774 func.set_result_type(result_type); 3806 func.set_result_type(result_type);
3775 AddFormalParamsToFunction(&params, func); 3807 AddFormalParamsToFunction(&params, func);
3776 top_level->functions.Add(func); 3808 top_level->functions.Add(func);
3777 library_.AddObject(func, accessor_name); 3809 if (!is_patch) {
3810 library_.AddObject(func, accessor_name);
3811 } else {
3812 library_.ReplaceObject(func, accessor_name);
3813 }
3778 } 3814 }
3779 3815
3780 3816
3781 void Parser::ParseLibraryName() { 3817 void Parser::ParseLibraryName() {
3782 TRACE_PARSER("ParseLibraryName"); 3818 TRACE_PARSER("ParseLibraryName");
3783 if ((script_.kind() == RawScript::kLibraryTag) && 3819 if ((script_.kind() == RawScript::kLibraryTag) &&
3784 (CurrentToken() != Token::kLIBRARY)) { 3820 (CurrentToken() != Token::kLIBRARY)) {
3785 // Handle error case early to get consistent error message. 3821 // Handle error case early to get consistent error message.
3786 ExpectToken(Token::kLIBRARY); 3822 ExpectToken(Token::kLIBRARY);
3787 } 3823 }
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
4685 SetPosition(saved_pos); 4721 SetPosition(saved_pos);
4686 return is_var_decl; 4722 return is_var_decl;
4687 } 4723 }
4688 4724
4689 4725
4690 // Look ahead to detect whether the next tokens should be parsed as 4726 // Look ahead to detect whether the next tokens should be parsed as
4691 // a function declaration. Token position remains unchanged. 4727 // a function declaration. Token position remains unchanged.
4692 bool Parser::IsFunctionDeclaration() { 4728 bool Parser::IsFunctionDeclaration() {
4693 const intptr_t saved_pos = TokenPos(); 4729 const intptr_t saved_pos = TokenPos();
4694 bool is_external = false; 4730 bool is_external = false;
4695 if (is_top_level_ && (CurrentToken() == Token::kEXTERNAL)) { 4731 if (is_top_level_) {
4696 // Skip over 'external' for top-level function declarations. 4732 if (is_patch_source() &&
4697 is_external = true; 4733 (CurrentToken() == Token::kIDENT) &&
4698 ConsumeToken(); 4734 CurrentLiteral()->Equals("patch") &&
4735 (LookaheadToken(1) != Token::kLPAREN)) {
4736 // Skip over 'patch' for top-level function declarations in patch sources.
4737 ConsumeToken();
4738 } else if (CurrentToken() == Token::kEXTERNAL) {
4739 // Skip over 'external' for top-level function declarations.
4740 is_external = true;
4741 ConsumeToken();
4742 }
4699 } 4743 }
4700 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { 4744 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) {
4701 // Possibly a function without explicit return type. 4745 // Possibly a function without explicit return type.
4702 ConsumeToken(); // Consume function identifier. 4746 ConsumeToken(); // Consume function identifier.
4703 } else if (TryParseReturnType()) { 4747 } else if (TryParseReturnType()) {
4704 if (!IsIdentifier()) { 4748 if (!IsIdentifier()) {
4705 SetPosition(saved_pos); 4749 SetPosition(saved_pos);
4706 return false; 4750 return false;
4707 } 4751 }
4708 ConsumeToken(); // Consume function identifier. 4752 ConsumeToken(); // Consume function identifier.
(...skipping 11 matching lines...) Expand all
4720 SetPosition(saved_pos); 4764 SetPosition(saved_pos);
4721 return true; 4765 return true;
4722 } 4766 }
4723 } 4767 }
4724 SetPosition(saved_pos); 4768 SetPosition(saved_pos);
4725 return false; 4769 return false;
4726 } 4770 }
4727 4771
4728 4772
4729 bool Parser::IsTopLevelAccessor() { 4773 bool Parser::IsTopLevelAccessor() {
4774 const intptr_t saved_pos = TokenPos();
4775 if (is_patch_source() &&
4776 (CurrentToken() == Token::kIDENT) &&
4777 (CurrentLiteral()->Equals("patch"))) {
4778 ConsumeToken();
4779 } else if (CurrentToken() == Token::kEXTERNAL) {
4780 ConsumeToken();
4781 }
4730 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { 4782 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
4783 SetPosition(saved_pos);
4731 return true; 4784 return true;
4732 } 4785 }
4733 const intptr_t saved_pos = TokenPos();
4734 if (TryParseReturnType()) { 4786 if (TryParseReturnType()) {
4735 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { 4787 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
4736 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. 4788 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name.
4737 SetPosition(saved_pos); 4789 SetPosition(saved_pos);
4738 return true; 4790 return true;
4739 } 4791 }
4740 } 4792 }
4741 } 4793 }
4742 SetPosition(saved_pos); 4794 SetPosition(saved_pos);
4743 return false; 4795 return false;
(...skipping 4200 matching lines...) Expand 10 before | Expand all | Expand 10 after
8944 void Parser::SkipQualIdent() { 8996 void Parser::SkipQualIdent() {
8945 ASSERT(IsIdentifier()); 8997 ASSERT(IsIdentifier());
8946 ConsumeToken(); 8998 ConsumeToken();
8947 if (CurrentToken() == Token::kPERIOD) { 8999 if (CurrentToken() == Token::kPERIOD) {
8948 ConsumeToken(); // Consume the kPERIOD token. 9000 ConsumeToken(); // Consume the kPERIOD token.
8949 ExpectIdentifier("identifier expected after '.'"); 9001 ExpectIdentifier("identifier expected after '.'");
8950 } 9002 }
8951 } 9003 }
8952 9004
8953 } // namespace dart 9005 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698