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

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
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 ((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
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(&params, func); 3697 AddFormalParamsToFunction(&params, 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
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(&params, func); 3804 AddFormalParamsToFunction(&params, 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
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
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
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
OLDNEW
« runtime/vm/object.cc ('K') | « 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