Skip to content

Commit

Permalink
Make anonymous rest arg (*) and block arg (&) accessible from ARGS node
Browse files Browse the repository at this point in the history
  • Loading branch information
yui-knk committed Nov 18, 2022
1 parent ddd62fa commit f0ce118
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
1 change: 1 addition & 0 deletions node.h
Expand Up @@ -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;
};
Expand Down
11 changes: 7 additions & 4 deletions parse.y
Expand Up @@ -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;
/*% %*/
}
;

Expand Down Expand Up @@ -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) %*/
}
Expand All @@ -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) %*/
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
24 changes: 24 additions & 0 deletions test/ruby/test_ast.rb
Expand Up @@ -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")
Expand Down

0 comments on commit f0ce118

Please sign in to comment.