ruby-changes:69548
From: Nobuyoshi <ko1@a...>
Date: Sun, 31 Oct 2021 18:28:21 +0900 (JST)
Subject: [ruby-changes:69548] 13a9597c7c (master): Argument forwarding definition without parentheses [Bug #18267]
https://git.ruby-lang.org/ruby.git/commit/?id=13a9597c7c From 13a9597c7ca83fced5738e9345660ae6aef87eb7 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Sun, 31 Oct 2021 15:20:48 +0900 Subject: Argument forwarding definition without parentheses [Bug #18267] --- parse.y | 49 ++++++++++++++++++++---------------------------- test/ruby/test_syntax.rb | 15 ++++++++++++++- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/parse.y b/parse.y index acea8244738..d3eb42e33f2 100644 --- a/parse.y +++ b/parse.y @@ -675,7 +675,6 @@ static int local_id_ref(struct parser_params*, ID, ID **); https://github.com/ruby/ruby/blob/trunk/parse.y#L675 #ifndef RIPPER static ID internal_id(struct parser_params*); static NODE *new_args_forward_call(struct parser_params*, NODE*, const YYLTYPE*, const YYLTYPE*); -static NODE *new_args_forward_def(struct parser_params*, NODE*, const YYLTYPE*); #endif static int check_forwarding_args(struct parser_params*); static void add_forwarding_args(struct parser_params *p); @@ -5128,26 +5127,6 @@ f_paren_args : '(' f_args rparen https://github.com/ruby/ruby/blob/trunk/parse.y#L5127 SET_LEX_STATE(EXPR_BEG); p->command_start = TRUE; } - | '(' f_arg ',' args_forward rparen - { - add_forwarding_args(p); - /*%%%*/ - $$ = new_args_forward_def(p, $2, &@$); - /*% %*/ - /*% ripper: paren!(params!($2, Qnone, $4, Qnone, Qnone, Qnone, Qnone)) %*/ - SET_LEX_STATE(EXPR_BEG); - p->command_start = TRUE; - } - | '(' args_forward rparen - { - add_forwarding_args(p); - /*%%%*/ - $$ = new_args_forward_def(p, 0, &@$); - /*% %*/ - /*% ripper: paren!(params!(Qnone, Qnone, $2, Qnone, Qnone, Qnone, Qnone)) %*/ - SET_LEX_STATE(EXPR_BEG); - p->command_start = TRUE; - } ; f_arglist : f_paren_args @@ -5181,6 +5160,11 @@ args_tail : f_kwarg ',' f_kwrest opt_f_block_arg https://github.com/ruby/ruby/blob/trunk/parse.y#L5160 { $$ = new_args_tail(p, Qnone, Qnone, $1, &@1); } + | args_forward + { + add_forwarding_args(p); + $$ = new_args_tail(p, Qnone, $1, ID2VAL(idFWD_BLOCK), &@1); + } ; opt_args_tail : ',' args_tail @@ -5259,7 +5243,7 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail https://github.com/ruby/ruby/blob/trunk/parse.y#L5243 args_forward : tBDOT3 { /*%%%*/ - $$ = idDot3; + $$ = idFWD_KWREST; /*% %*/ /*% ripper: args_forward! %*/ } @@ -9653,6 +9637,12 @@ parser_yylex(struct parser_params *p) https://github.com/ruby/ruby/blob/trunk/parse.y#L9637 if ((c = nextc(p)) == '.') { if ((c = nextc(p)) == '.') { if (p->lex.paren_nest == 0 && looking_at_eol_p(p)) { + if (p->ctxt.in_argdef || /* def foo a, ... */ + IS_lex_state_for(last_state, EXPR_ENDFN) || /* def foo ... */ + 0) { + SET_LEX_STATE(EXPR_ENDARG); + return tBDOT3; + } rb_warn0("... at EOL, should be parenthesized?"); } else if (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest) { @@ -11967,6 +11957,14 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N https://github.com/ruby/ruby/blob/trunk/parse.y#L11957 int saved_line = p->ruby_sourceline; struct rb_args_info *args = tail->nd_ainfo; + if (args->block_arg == idFWD_BLOCK) { + if (rest_arg) { + yyerror1(&tail->nd_loc, "... after rest argument"); + return tail; + } + rest_arg = idFWD_REST; + } + args->pre_args_num = pre_args ? rb_long2int(pre_args->nd_plen) : 0; args->pre_init = pre_args ? pre_args->nd_next : 0; @@ -12697,13 +12695,6 @@ new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc https://github.com/ruby/ruby/blob/trunk/parse.y#L12695 #endif return arg_blk_pass(args, block); } - -static NODE * -new_args_forward_def(struct parser_params *p, NODE *leading, const YYLTYPE *loc) -{ - NODE *n = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, loc); - return new_args(p, leading, Qnone, idFWD_REST, Qnone, n, loc); -} #endif static NODE * diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index fc40a7f21a9..11953ab5635 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1575,6 +1575,7 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1575 def test_argument_forwarding assert_valid_syntax('def foo(...) bar(...) end') assert_valid_syntax('def foo(...) end') + assert_valid_syntax("def foo ...\n bar(...)\nend") assert_valid_syntax('def ==(...) end') assert_valid_syntax('def [](...) end') assert_valid_syntax('def nil(...) end') @@ -1604,7 +1605,9 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1605 [args, kws] end end + obj4 = obj1.clone obj1.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__) + obj4.instance_eval("def foo ...\n bar(...)\n""end", __FILE__, __LINE__) klass = Class.new { def foo(*args, **kws, &block) @@ -1633,7 +1636,7 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1636 end obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__) - [obj1, obj2, obj3].each do |obj| + [obj1, obj2, obj3, obj4].each do |obj| assert_warning('') { assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x}) } @@ -1766,6 +1769,16 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1769 assert_equal [[4, 1, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} + + obj.singleton_class.send(:remove_method, :foo) + obj.instance_eval("def foo a, ...\n bar(a, ...)\n"" end", __FILE__, __LINE__) + assert_equal [[4], {}], obj.foo(4) + assert_equal [[4, 2], {}], obj.foo(4, 2) + assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3) + assert_equal [[4], {a: 1}], obj.foo(4, a: 1) + assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) + assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} end def test_cdhash -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/