[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]