diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-12-22 21:50:38 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-12-22 23:08:10 +0900 |
commit | 40e3f782dd92749a1fa593ef905d1b75fdd61904 (patch) | |
tree | 085eda00672bd4513e2e05dd700f6bca3bc3ed04 /parse.y | |
parent | 11c2aa035b0639a2b3550cd8e0b9ef72315f0c2d (diff) |
Extract `forwarding_arg_check` function
Diffstat (limited to 'parse.y')
-rw-r--r-- | parse.y | 43 |
1 files changed, 32 insertions, 11 deletions
@@ -1378,6 +1378,7 @@ static NODE *new_args_forward_call(struct parser_params*, NODE*, const YYLTYPE*, #endif static int check_forwarding_args(struct parser_params*); static void add_forwarding_args(struct parser_params *p); +static void forwarding_arg_check(struct parser_params *p, ID arg, ID all, const char *var); static const struct vtable *dyna_push(struct parser_params *); static void dyna_pop(struct parser_params*, const struct vtable *); @@ -3756,9 +3757,7 @@ block_arg : tAMPER arg_value } | tAMPER { - if (!local_id(p, idFWD_BLOCK)) { - compile_error(p, "no anonymous block parameter"); - } + forwarding_arg_check(p, idFWD_BLOCK, 0, "block"); /*%%%*/ $$ = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@1), &@$); /*% %*/ @@ -3814,10 +3813,7 @@ arg_splat : tSTAR arg_value } | tSTAR /* none */ { - if (!local_id(p, idFWD_REST) || - local_id(p, idFWD_ALL)) { - compile_error(p, "no anonymous rest parameter"); - } + forwarding_arg_check(p, idFWD_REST, idFWD_ALL, "rest"); /*%%%*/ $$ = NEW_LVAR(idFWD_REST, &@1); /*% %*/ @@ -6689,10 +6685,7 @@ assoc : arg_value tASSOC arg_value } | tDSTAR { - if (!local_id(p, idFWD_KWREST) || - local_id(p, idFWD_ALL)) { - compile_error(p, "no anonymous keyword rest parameter"); - } + forwarding_arg_check(p, idFWD_KWREST, idFWD_ALL, "keyword rest"); /*%%%*/ $$ = list_append(p, NEW_LIST(0, &@$), NEW_LVAR(idFWD_KWREST, &@$)); @@ -15013,6 +15006,34 @@ add_forwarding_args(struct parser_params *p) arg_var(p, idFWD_ALL); } +static void +forwarding_arg_check(struct parser_params *p, ID arg, ID all, const char *var) +{ + struct vtable *vars, *args; + + vars = p->lvtbl->vars; + args = p->lvtbl->args; + + while (vars && !DVARS_TERMINAL_P(vars->prev)) { + vars = vars->prev; + args = args->prev; + } + + bool found = false; + if (vars && vars->prev == DVARS_INHERIT) { + found = (rb_local_defined(arg, p->parent_iseq) && + !(all && rb_local_defined(all, p->parent_iseq))); + } + else { + found = (vtable_included(args, arg) && + !(all && vtable_included(args, all))); + } + + if (!found) { + compile_error(p, "no anonymous %s parameter", var); + } +} + #ifndef RIPPER static NODE * new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc, const YYLTYPE *argsloc) |