diff --git a/node.h b/node.h index 39427257ddc466..220de3135e136e 100644 --- a/node.h +++ b/node.h @@ -461,6 +461,7 @@ struct rb_args_info { NODE *opt_args; unsigned int no_kwarg: 1; unsigned int ruby2_keywords: 1; + unsigned int forwarding: 1; VALUE imemo; }; diff --git a/parse.y b/parse.y index a69a7bea55f2b9..9d298dc317ad01 100644 --- a/parse.y +++ b/parse.y @@ -5322,6 +5322,9 @@ args_tail : f_kwarg ',' f_kwrest opt_f_block_arg { add_forwarding_args(p); $$ = new_args_tail(p, Qnone, $1, ID2VAL(idFWD_BLOCK), &@1); + /*%%%*/ + ($$->nd_ainfo)->forwarding = 1; + /*% %*/ } ; @@ -5688,7 +5691,7 @@ f_rest_arg : restarg_mark tIDENTIFIER { arg_var(p, ANON_REST_ID); /*%%%*/ - $$ = internal_id(p); + $$ = ANON_REST_ID; /*% %*/ /*% ripper: rest_param!(Qnil) %*/ } @@ -5710,7 +5713,7 @@ f_block_arg : blkarg_mark tIDENTIFIER { arg_var(p, ANON_BLOCK_ID); /*%%%*/ - $$ = internal_id(p); + $$ = ANON_BLOCK_ID; /*% %*/ /*% ripper: blockarg!(Qnil) %*/ } @@ -12204,7 +12207,7 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N int saved_line = p->ruby_sourceline; struct rb_args_info *args = tail->nd_ainfo; - if (args->block_arg == idFWD_BLOCK) { + if (args->forwarding) { if (rest_arg) { yyerror1(&tail->nd_loc, "... after rest argument"); return tail; @@ -12223,7 +12226,7 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N args->opt_args = opt_args; - args->ruby2_keywords = rest_arg == idFWD_REST; + args->ruby2_keywords = args->forwarding; p->ruby_sourceline = saved_line; nd_set_loc(tail, loc); diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index 0932e93d5a909e..7a9f2bad2cc7da 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -461,6 +461,30 @@ def test_until assert_not_equal(type1, type2) end + def test_rest_arg + rest_arg = lambda do |arg_str| + node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end") + node = node.children.last.children.last.children[1].children[-4] + end + + assert_equal(nil, rest_arg.call('')) + assert_equal(:r, rest_arg.call('*r')) + assert_equal(:r, rest_arg.call('a, *r')) + assert_equal(:*, rest_arg.call('*')) + assert_equal(:*, rest_arg.call('a, *')) + end + + def test_block_arg + block_arg = lambda do |arg_str| + node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end") + node = node.children.last.children.last.children[1].children[-1] + end + + assert_equal(nil, block_arg.call('')) + assert_equal(:block, block_arg.call('&block')) + assert_equal(:&, block_arg.call('&')) + end + def test_keyword_rest kwrest = lambda do |arg_str| node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")