summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-12-22 21:50:38 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-12-22 23:08:10 +0900
commit40e3f782dd92749a1fa593ef905d1b75fdd61904 (patch)
tree085eda00672bd4513e2e05dd700f6bca3bc3ed04 /parse.y
parent11c2aa035b0639a2b3550cd8e0b9ef72315f0c2d (diff)
Extract `forwarding_arg_check` function
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y43
1 files changed, 32 insertions, 11 deletions
diff --git a/parse.y b/parse.y
index 27cdf4b75c..75b7151e60 100644
--- a/parse.y
+++ b/parse.y
@@ -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)