aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2024-01-25 15:08:44 -0800
committerKevin Newton <kddnewton@gmail.com>2024-01-30 13:19:06 -0500
commit8e708e4a077d85e50cd797b2478aba7bfd5e4ac3 (patch)
tree87aeb4f38b86b2c2a5f6a8ae0e606f93f5a0b637
parent6b350bc6e41551161f4be37858c54fcca1a09c46 (diff)
downloadruby-8e708e4a077d85e50cd797b2478aba7bfd5e4ac3.tar.gz
Update forwarding locals for prism
-rw-r--r--lib/prism/debug.rb6
-rw-r--r--prism/parser.h18
-rw-r--r--prism/prism.c89
-rw-r--r--prism_compile.c167
-rw-r--r--test/prism/errors_test.rb12
-rw-r--r--test/prism/snapshots/arrays.txt36
-rw-r--r--test/prism/snapshots/method_calls.txt4
-rw-r--r--test/prism/snapshots/methods.txt40
-rw-r--r--test/prism/snapshots/seattlerb/block_arg__bare.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_arg_forward_args.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_args_forward_args.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_forward_args.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_splat_arg.txt4
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/def.txt4
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/31.txt8
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/32.txt8
-rw-r--r--test/prism/snapshots/whitequark/anonymous_blockarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/args.txt4
-rw-r--r--test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt4
-rw-r--r--test/prism/snapshots/whitequark/forward_arg.txt4
-rw-r--r--test/prism/snapshots/whitequark/forward_arg_with_open_args.txt40
-rw-r--r--test/prism/snapshots/whitequark/forward_args_legacy.txt12
-rw-r--r--test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/forwarded_kwrestarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/forwarded_restarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt4
-rw-r--r--test/prism/snapshots/whitequark/kwrestarg_unnamed.txt4
-rw-r--r--test/prism/snapshots/whitequark/restarg_unnamed.txt4
-rw-r--r--test/prism/snapshots/whitequark/trailing_forward_arg.txt4
-rw-r--r--test/ruby/test_compile_prism.rb24
35 files changed, 333 insertions, 219 deletions
diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb
index 4e8d3f216c..c888436e4d 100644
--- a/lib/prism/debug.rb
+++ b/lib/prism/debug.rb
@@ -143,7 +143,7 @@ module Prism
if params.keyword_rest.is_a?(ForwardingParameterNode)
sorted.push(:*, :**, :&, :"...")
elsif params.keyword_rest.is_a?(KeywordRestParameterNode)
- sorted << params.keyword_rest.name if params.keyword_rest.name
+ sorted << (params.keyword_rest.name || :**)
end
# Recurse down the parameter tree to find any destructured
@@ -162,7 +162,9 @@ module Prism
end
end
- sorted << params.block.name if params.block&.name
+ if params.block
+ sorted << (params.block.name || :&)
+ end
names = sorted.concat(names - sorted)
end
diff --git a/prism/parser.h b/prism/parser.h
index 6ee215c76d..5079c59c5f 100644
--- a/prism/parser.h
+++ b/prism/parser.h
@@ -470,6 +470,19 @@ typedef struct pm_scope {
bool explicit_params;
/**
+ * Booleans indicating whether the parameters for this scope have declared
+ * forwarding parameters.
+ *
+ * For example, some combinations of:
+ * def foo(*); end
+ * def foo(**); end
+ * def foo(&); end
+ * def foo(...); end
+ */
+
+ uint8_t forwarding_params;
+
+ /**
* An integer indicating the number of numbered parameters on this scope.
* This is necessary to determine if child blocks are allowed to use
* numbered parameters, and to pass information to consumers of the AST
@@ -478,6 +491,11 @@ typedef struct pm_scope {
uint8_t numbered_parameters;
} pm_scope_t;
+static const uint8_t PM_FORWARDING_POSITIONALS = 0x1;
+static const uint8_t PM_FORWARDING_KEYWORDS = 0x2;
+static const uint8_t PM_FORWARDING_BLOCK = 0x4;
+static const uint8_t PM_FORWARDING_ALL = 0x8;
+
/**
* This struct represents the overall parser. It contains a reference to the
* source file, as well as pointers that indicate where in the source it's
diff --git a/prism/prism.c b/prism/prism.c
index ea2723cfaf..f387d1305f 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -6029,6 +6029,7 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
.closed = closed,
.explicit_params = false,
.numbered_parameters = 0,
+ .forwarding_params = 0,
};
pm_constant_id_list_init(&scope->locals);
@@ -6037,6 +6038,49 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
return true;
}
+static void
+pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag)
+{
+ pm_scope_t *scope = parser->current_scope;
+ while (scope) {
+ if (scope->forwarding_params & mask) {
+ if (!scope->closed) {
+ pm_parser_err_token(parser, token, diag);
+ return;
+ }
+ return;
+ }
+ if (scope->closed) break;
+ scope = scope->previous;
+ }
+
+ pm_parser_err_token(parser, token, diag);
+}
+
+static inline void
+pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token)
+{
+ pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
+}
+
+static void
+pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token)
+{
+ pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
+}
+
+static inline void
+pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token)
+{
+ pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
+}
+
+static inline void
+pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token)
+{
+ pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_KEYWORDS, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
+}
+
/**
* Save the current param name as the return value and set it to the given
* constant id.
@@ -11341,8 +11385,9 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
if (token_begins_expression_p(parser->current.type)) {
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
- } else if (pm_parser_local_depth(parser, &operator) == -1) {
- pm_parser_err_token(parser, &operator, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
+ }
+ else {
+ pm_parser_scope_forwarding_keywords_check(parser, &operator);
}
element = (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator);
@@ -11491,13 +11536,8 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
if (token_begins_expression_p(parser->current.type)) {
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_ARGUMENT);
} else {
- if (pm_parser_local_depth(parser, &operator) == -1) {
- // A block forwarding in a method having `...` parameter (e.g. `def foo(...); bar(&); end`) is available.
- pm_constant_id_t ellipsis_id = pm_parser_constant_id_constant(parser, "...", 3);
- if (pm_parser_local_depth_constant_id(parser, ellipsis_id) == -1) {
- pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
- }
- }
+ // A block forwarding in a method having `...` parameter (e.g. `def foo(...); bar(&); end`) is available.
+ pm_parser_scope_forwarding_block_check(parser, &operator);
}
argument = (pm_node_t *) pm_block_argument_node_create(parser, &operator, expression);
@@ -11515,10 +11555,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_token_t operator = parser->previous;
if (match4(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_SEMICOLON, PM_TOKEN_BRACKET_RIGHT)) {
- if (pm_parser_local_depth(parser, &parser->previous) == -1) {
- pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
- }
-
+ pm_parser_scope_forwarding_positionals_check(parser, &operator);
argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL);
} else {
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
@@ -11544,9 +11581,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
argument = (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
} else {
- if (pm_parser_local_depth(parser, &parser->previous) == -1) {
- pm_parser_err_previous(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
- }
+ pm_parser_scope_forwarding_all_check(parser, &parser->previous);
if (parsed_first_argument && terminator == PM_TOKEN_EOF) {
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
}
@@ -11813,10 +11848,7 @@ parse_parameters(
pm_parser_local_add_token(parser, &name);
} else {
name = not_provided(parser);
-
- if (allows_forwarding_parameters) {
- pm_parser_local_add_token(parser, &operator);
- }
+ parser->current_scope->forwarding_params |= PM_FORWARDING_BLOCK;
}
pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
@@ -11841,9 +11873,8 @@ parse_parameters(
update_parameter_state(parser, &parser->current, &order);
parser_lex(parser);
- if (allows_forwarding_parameters) {
- pm_parser_local_add_token(parser, &parser->previous);
- }
+ parser->current_scope->forwarding_params |= PM_FORWARDING_BLOCK;
+ parser->current_scope->forwarding_params |= PM_FORWARDING_ALL;
pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous);
if (params->keyword_rest != NULL) {
@@ -12025,9 +12056,7 @@ parse_parameters(
} else {
name = not_provided(parser);
- if (allows_forwarding_parameters) {
- pm_parser_local_add_token(parser, &operator);
- }
+ parser->current_scope->forwarding_params |= PM_FORWARDING_POSITIONALS;
}
pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
@@ -12064,9 +12093,7 @@ parse_parameters(
} else {
name = not_provided(parser);
- if (allows_forwarding_parameters) {
- pm_parser_local_add_token(parser, &operator);
- }
+ parser->current_scope->forwarding_params |= PM_FORWARDING_KEYWORDS;
}
param = (pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &operator, &name);
@@ -14264,9 +14291,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *expression = NULL;
if (match3(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_EOF)) {
- if (pm_parser_local_depth(parser, &parser->previous) == -1) {
- pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
- }
+ pm_parser_scope_forwarding_positionals_check(parser, &operator);
} else {
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR);
}
diff --git a/prism_compile.c b/prism_compile.c
index e325a6e118..8d8ad656a2 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -801,7 +801,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_
// This recurses through scopes and finds the local index at any scope level
// It also takes a pointer to depth, and increments depth appropriately
-// according to the depth of the local
+// according to the depth of the local.
static pm_local_index_t
pm_lookup_local_index(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth)
{
@@ -815,6 +815,7 @@ pm_lookup_local_index(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, pm_con
while (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) {
level++;
+
if (scope_node->previous) {
scope_node = scope_node->previous;
} else {
@@ -1151,6 +1152,7 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf
case PM_SPLAT_NODE: {
*flags |= VM_CALL_ARGS_SPLAT;
pm_splat_node_t *splat_node = (pm_splat_node_t *)argument;
+
if (splat_node->expression) {
PM_COMPILE_NOT_POPPED(splat_node->expression);
}
@@ -1197,16 +1199,26 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf
break;
}
case PM_FORWARDING_ARGUMENTS_NODE: {
- orig_argc++;
- *flags |= VM_CALL_ARGS_BLOCKARG | VM_CALL_ARGS_SPLAT;
-
- pm_local_index_t mult_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0);
- ADD_GETLOCAL(ret, &dummy_line_node, mult_index.index, mult_index.level);
-
- ADD_INSN1(ret, &dummy_line_node, splatarray, RBOOL(arguments_node_list.size > 1));
-
- pm_local_index_t and_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
- ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(and_index.index + VM_ENV_DATA_SIZE - 1), INT2FIX(and_index.level));
+ orig_argc += 2;
+ *flags |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT;
+
+ // Forwarding arguments nodes are treated as foo(*, **, &)
+ // So foo(...) equals foo(*, **, &) and as such the local
+ // table for this method is known in advance
+ //
+ // Push the *
+ pm_local_index_t mult_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0);
+ ADD_GETLOCAL(ret, &dummy_line_node, mult_local.index, mult_local.level);
+ ADD_INSN1(ret, &dummy_line_node, splatarray, Qtrue);
+
+ // Push the **
+ pm_local_index_t pow_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_POW, 0);
+ ADD_GETLOCAL(ret, &dummy_line_node, pow_local.index, pow_local.level);
+
+ // Push the &
+ pm_local_index_t and_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
+ ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(and_local.index + VM_ENV_DATA_SIZE - 1), INT2FIX(and_local.level));
+ ADD_INSN(ret, &dummy_line_node, splatkw);
break;
}
@@ -2863,6 +2875,11 @@ pm_local_table_insert_func(st_data_t *key, st_data_t *value, st_data_t arg, int
return ST_CONTINUE;
}
+/**
+ * Insert a local into the local table for the iseq. This is used to create the
+ * local table in the correct order while compiling the scope. The locals being
+ * inserted are regular named locals, as opposed to special forwarding locals.
+ */
static void
pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq, pm_scope_node_t *scope_node)
{
@@ -2870,7 +2887,18 @@ pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *i
ID local = pm_constant_id_lookup(scope_node, constant_id);
local_table_for_iseq->ids[local_index] = local;
- st_insert(index_lookup_table, (st_data_t)constant_id, local_index);
+ st_insert(index_lookup_table, (st_data_t) constant_id, (st_data_t) local_index);
+}
+
+/**
+ * Insert a local into the local table for the iseq that is a special forwarding
+ * local variable.
+ */
+static void
+pm_insert_local_special(ID local_name, int local_index, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq)
+{
+ local_table_for_iseq->ids[local_index] = local_name;
+ st_insert(index_lookup_table, (st_data_t) (local_name | PM_SPECIAL_CONSTANT_FLAG), (st_data_t) local_index);
}
/**
@@ -3904,13 +3932,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
return;
}
case PM_BLOCK_ARGUMENT_NODE: {
- pm_block_argument_node_t *block_argument_node = (pm_block_argument_node_t *) node;
- if (block_argument_node->expression) {
- PM_COMPILE(block_argument_node->expression);
+ pm_block_argument_node_t *cast = (pm_block_argument_node_t *) node;
+
+ if (cast->expression) {
+ PM_COMPILE(cast->expression);
}
else {
- pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
- ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level);
+ // If there's no expression, this must be block forwarding.
+ pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
+ ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(local_index.index + VM_ENV_DATA_SIZE - 1), INT2FIX(local_index.level));
}
return;
}
@@ -4914,7 +4944,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
argc += local_body->param.lead_num;
}
-
if (local_body->param.flags.has_opt) {
/* optional arguments */
for (int j = 0; j < local_body->param.opt_num; j++) {
@@ -6332,7 +6361,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_node_list_t *posts_list = NULL;
pm_node_list_t *requireds_list = NULL;
pm_node_list_t *block_locals = NULL;
- pm_node_t *block_param_keyword_rest = NULL;
bool trailing_comma = false;
struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
@@ -6344,7 +6372,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
parameters_node = block_parameters_node->parameters;
block_locals = &block_parameters_node->locals;
if (parameters_node) {
- block_param_keyword_rest = parameters_node->keyword_rest;
if (parameters_node->rest && PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE)) {
trailing_comma = true;
}
@@ -6440,10 +6467,24 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
}
- // def underscore_parameters(_, **_); _; end
- // ^^^
- if (parameters_node->keyword_rest && PM_NODE_FLAG_P(parameters_node->keyword_rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
+ // def foo(_, **_); _; end
+ // ^^^
+ if (parameters_node->keyword_rest) {
+ // def foo(...); end
+ // ^^^
+ // When we have a `...` as the keyword_rest, it's a forwarding_parameter_node and
+ // we need to leave space for 4 locals: *, **, &, ...
+ if (PM_NODE_TYPE_P(parameters_node->keyword_rest, PM_FORWARDING_PARAMETER_NODE)) {
+ table_size += 4;
+ }
+ else {
+ pm_keyword_rest_parameter_node_t * kw_rest = (pm_keyword_rest_parameter_node_t *)parameters_node->keyword_rest;
+
+ // If it's anonymous or repeated, then we need to allocate stack space
+ if (!kw_rest->name || PM_NODE_FLAG_P(kw_rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
+ }
}
}
@@ -6468,23 +6509,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
}
- if (block_param_keyword_rest) {
- table_size++;
- }
-
if (parameters_node && parameters_node->block) {
- if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ pm_block_parameter_node_t * block_node = (pm_block_parameter_node_t *)parameters_node->block;
+
+ if (PM_NODE_FLAG_P(block_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER) || !block_node->name) {
table_size++;
}
}
- // When we have a `...` as the keyword_rest, it's a forwarding_parameter_node and
- // we need to leave space for 2 more locals on the locals table (`*` and `&`)
- if (parameters_node && parameters_node->keyword_rest &&
- PM_NODE_TYPE_P(parameters_node->keyword_rest, PM_FORWARDING_PARAMETER_NODE)) {
- table_size += 2;
- }
-
// We can create local_table_for_iseq with the correct size
VALUE idtmp = 0;
rb_ast_id_table_t *local_table_for_iseq = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + table_size * sizeof(ID));
@@ -6522,10 +6554,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
if (requireds_list && requireds_list->size) {
for (size_t i = 0; i < requireds_list->size; i++, local_index++) {
ID local;
- // For each MultiTargetNode, we're going to have one
- // additional anonymous local not represented in the locals table
- // We want to account for this in our table size
+
+ // For each MultiTargetNode, we're going to have one additional
+ // anonymous local not represented in the locals table. We want
+ // to account for this in our table size.
pm_node_t *required = requireds_list->nodes[i];
+
switch (PM_NODE_TYPE(required)) {
// def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
// ^^^^^^^^^^
@@ -6546,6 +6580,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
else {
pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
+
break;
}
default: {
@@ -6582,13 +6617,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// ^^
if (parameters_node && parameters_node->rest) {
body->param.rest_start = local_index;
+
// If there's a trailing comma, we'll have an implicit rest node,
// and we don't want it to impact the rest variables on param
if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) {
body->param.flags.has_rest = true;
assert(body->param.rest_start != -1);
- pm_constant_id_t name = ((pm_rest_parameter_node_t *)parameters_node->rest)->name;
+ pm_constant_id_t name = ((pm_rest_parameter_node_t *) parameters_node->rest)->name;
+
if (name) {
// def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
// ^^
@@ -6603,9 +6640,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
else {
// def foo(a, (b, *c, d), e = 1, *, g, (h, *i, j), k:, l: 1, **m, &n)
// ^
- local_table_for_iseq->ids[local_index] = PM_CONSTANT_MULT;
- st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_MULT, local_index);
+ pm_insert_local_special(idMULT, local_index, index_lookup_table, local_table_for_iseq);
}
+
local_index++;
}
}
@@ -6636,12 +6673,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// ^
case PM_REQUIRED_PARAMETER_NODE: {
pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)post_node;
+
if (PM_NODE_FLAG_P(param, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
ID local = pm_constant_id_lookup(scope_node, param->name);
local_table_for_iseq->ids[local_index] = local;
}
else {
-
pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
break;
@@ -6760,7 +6797,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **nil, &n)
// ^^^^^
case PM_NO_KEYWORDS_PARAMETER_NODE: {
-
body->param.flags.accepts_no_kwarg = true;
break;
}
@@ -6786,9 +6822,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
}
else {
- local_table_for_iseq->ids[local_index] = PM_CONSTANT_POW;
- st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_POW, local_index);
+ pm_insert_local_special(idPow, local_index, index_lookup_table, local_table_for_iseq);
}
+
local_index++;
break;
}
@@ -6797,19 +6833,28 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
case PM_FORWARDING_PARAMETER_NODE: {
body->param.rest_start = local_index;
body->param.flags.has_rest = true;
- local_table_for_iseq->ids[local_index] = PM_CONSTANT_MULT;
- st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_MULT, local_index);
- local_index++;
+
+ // Add the leading *
+ pm_insert_local_special(idMULT, local_index++, index_lookup_table, local_table_for_iseq);
+
+ // Add the kwrest **
+ RUBY_ASSERT(!body->param.flags.has_kw);
+
+ // There are no keywords declared (in the text of the program)
+ // but the forwarding node implies we support kwrest (**)
+ body->param.flags.has_kw = false;
+ body->param.flags.has_kwrest = true;
+ body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
+
+ keyword->rest_start = local_index;
+
+ pm_insert_local_special(idPow, local_index++, index_lookup_table, local_table_for_iseq);
body->param.block_start = local_index;
body->param.flags.has_block = true;
- local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND;
- st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_AND, local_index);
- local_index++;
- local_table_for_iseq->ids[local_index] = PM_CONSTANT_DOT3;
- st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_DOT3, local_index);
- local_index++;
+ pm_insert_local_special(idAnd, local_index++, index_lookup_table, local_table_for_iseq);
+ pm_insert_local_special(idDot3, local_index++, index_lookup_table, local_table_for_iseq);
break;
}
default: {
@@ -6824,13 +6869,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
body->param.block_start = local_index;
body->param.flags.has_block = true;
- pm_constant_id_t name = ((pm_block_parameter_node_t *)parameters_node->block)->name;
+ pm_constant_id_t name = ((pm_block_parameter_node_t *) parameters_node->block)->name;
- if (name == 0) {
- local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND;
- st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_AND, local_index);
- }
- else {
+ if (name) {
if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
ID local = pm_constant_id_lookup(scope_node, name);
local_table_for_iseq->ids[local_index] = local;
@@ -6839,6 +6880,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
}
+ else {
+ pm_insert_local_special(idAnd, local_index, index_lookup_table, local_table_for_iseq);
+ }
+
local_index++;
}
}
diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb
index 4518c8a65d..62e72ea16a 100644
--- a/test/prism/errors_test.rb
+++ b/test/prism/errors_test.rb
@@ -754,8 +754,8 @@ module Prism
nil,
ParametersNode([], [], nil, [RequiredParameterNode(0, :a)], [], nil, BlockParameterNode(0, nil, nil, Location())),
nil,
- [:&, :a],
- 2,
+ [:a],
+ 1,
Location(),
nil,
Location(),
@@ -784,8 +784,8 @@ module Prism
nil
),
nil,
- [:"...", :a],
- 2,
+ [:a],
+ 1,
Location(),
nil,
Location(),
@@ -864,8 +864,8 @@ module Prism
nil,
ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil),
nil,
- [:"..."],
- 1,
+ [],
+ 0,
Location(),
nil,
Location(),
diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt
index bea52be855..dd84e25b4a 100644
--- a/test/prism/snapshots/arrays.txt
+++ b/test/prism/snapshots/arrays.txt
@@ -1066,8 +1066,8 @@
│ │ @ BlockArgumentNode (location: (89,6)-(89,7))
│ │ ├── expression: ∅
│ │ └── operator_loc: (89,6)-(89,7) = "&"
- │ ├── locals: [:&]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (88,0)-(88,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (88,7)-(88,8) = "("
@@ -1847,8 +1847,8 @@
│ │ │ └── expression: ∅
│ │ ├── closing_loc: (128,13)-(128,14) = "]"
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (128,0)-(128,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (128,5)-(128,6) = "("
@@ -1904,8 +1904,8 @@
│ │ │ └── expression: ∅
│ │ ├── closing_loc: (130,16)-(130,17) = "]"
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (130,0)-(130,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (130,5)-(130,6) = "("
@@ -1961,8 +1961,8 @@
│ │ │ └── flags: decimal
│ │ ├── closing_loc: (132,13)-(132,14) = "]"
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (132,0)-(132,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (132,5)-(132,6) = "("
@@ -2020,8 +2020,8 @@
│ │ │ └── flags: decimal
│ │ ├── closing_loc: (134,16)-(134,17) = "]"
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (134,0)-(134,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (134,5)-(134,6) = "("
@@ -2078,8 +2078,8 @@
│ │ └── value:
│ │ @ IntegerNode (location: (136,18)-(136,19))
│ │ └── flags: decimal
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (136,0)-(136,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (136,5)-(136,6) = "("
@@ -2137,8 +2137,8 @@
│ │ └── value:
│ │ @ IntegerNode (location: (138,22)-(138,23))
│ │ └── flags: decimal
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (138,0)-(138,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (138,5)-(138,6) = "("
@@ -2201,8 +2201,8 @@
│ │ ├── else_clause: ∅
│ │ ├── ensure_clause: ∅
│ │ └── end_keyword_loc: (140,26)-(140,29) = "end"
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (140,0)-(140,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (140,5)-(140,6) = "("
@@ -2267,8 +2267,8 @@
│ ├── else_clause: ∅
│ ├── ensure_clause: ∅
│ └── end_keyword_loc: (142,29)-(142,32) = "end"
- ├── locals: [:*]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (142,0)-(142,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (142,5)-(142,6) = "("
diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt
index adf02ef187..f40c2158e4 100644
--- a/test/prism/snapshots/method_calls.txt
+++ b/test/prism/snapshots/method_calls.txt
@@ -2341,8 +2341,8 @@
│ │ │ └── expression: ∅
│ │ ├── closing_loc: ∅
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (149,0)-(149,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (149,5)-(149,6) = "("
diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt
index c4f4b70f50..7f3b61f75d 100644
--- a/test/prism/snapshots/methods.txt
+++ b/test/prism/snapshots/methods.txt
@@ -202,8 +202,8 @@
│ │ │ @ ForwardingParameterNode (location: (19,6)-(19,9))
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (19,0)-(19,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (19,5)-(19,6) = "("
@@ -370,8 +370,8 @@
│ │ │ └── operator_loc: (41,6)-(41,8) = "**"
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:**]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (41,0)-(41,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (41,5)-(41,6) = "("
@@ -743,8 +743,8 @@
│ │ ├── keyword_rest: ∅
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (82,0)-(82,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (82,5)-(82,6) = "("
@@ -983,8 +983,8 @@
│ │ │ └── expression: ∅
│ │ ├── closing_loc: (110,13)-(110,14) = ")"
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (110,0)-(110,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (110,5)-(110,6) = "("
@@ -1022,8 +1022,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (112,14)-(112,17))
│ │ ├── closing_loc: (112,17)-(112,18) = ")"
│ │ └── block: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (112,0)-(112,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (112,5)-(112,6) = "("
@@ -1065,8 +1065,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (114,20)-(114,23))
│ │ ├── closing_loc: (114,23)-(114,24) = ")"
│ │ └── block: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (114,0)-(114,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (114,5)-(114,6) = "("
@@ -1153,8 +1153,8 @@
│ │ ├── name_loc: ∅
│ │ └── operator_loc: (122,6)-(122,7) = "&"
│ ├── body: ∅
- │ ├── locals: [:&]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (122,0)-(122,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (122,5)-(122,6) = "("
@@ -1296,8 +1296,8 @@
│ │ │ │ └── block: ∅
│ │ │ └── closing_loc: (136,24)-(136,25) = "}"
│ │ └── closing_loc: (136,25)-(136,26) = "\""
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (136,0)-(136,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (136,5)-(136,6) = "("
@@ -1747,8 +1747,8 @@
│ │ │ └── expression: ∅
│ │ ├── opening_loc: (167,10)-(167,11) = "["
│ │ └── closing_loc: (167,12)-(167,13) = "]"
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (167,0)-(167,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (167,5)-(167,6) = "("
@@ -1959,8 +1959,8 @@
│ │ @ BlockArgumentNode (location: (178,6)-(178,7))
│ │ ├── expression: ∅
│ │ └── operator_loc: (178,6)-(178,7) = "&"
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (177,0)-(177,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (177,7)-(177,8) = "("
diff --git a/test/prism/snapshots/seattlerb/block_arg__bare.txt b/test/prism/snapshots/seattlerb/block_arg__bare.txt
index f3b6d3c11c..9bf5016ad1 100644
--- a/test/prism/snapshots/seattlerb/block_arg__bare.txt
+++ b/test/prism/snapshots/seattlerb/block_arg__bare.txt
@@ -22,8 +22,8 @@
│ ├── name_loc: ∅
│ └── operator_loc: (1,6)-(1,7) = "&"
├── body: ∅
- ├── locals: [:&]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt
index ecc7ad04a4..fc726fe4de 100644
--- a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt
+++ b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt
@@ -28,8 +28,8 @@
│ ├── keyword_rest: ∅
│ └── block: ∅
├── body: ∅
- ├── locals: [:interp, :*, :args]
- ├── locals_body_index: 3
+ ├── locals: [:interp, :args]
+ ├── locals_body_index: 2
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,8)-(1,9) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt
index 46c0e91ade..2068a8011b 100644
--- a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt
+++ b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt
@@ -40,8 +40,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (1,20)-(1,23))
│ ├── closing_loc: (1,23)-(1,24) = ")"
│ └── block: ∅
- ├── locals: [:x, :"..."]
- ├── locals_body_index: 2
+ ├── locals: [:x]
+ ├── locals_body_index: 1
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt
index e6b72907b0..b6802c2fd8 100644
--- a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt
+++ b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt
@@ -52,8 +52,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (1,32)-(1,35))
│ ├── closing_loc: (1,35)-(1,36) = ")"
│ └── block: ∅
- ├── locals: [:x, :y, :z, :"..."]
- ├── locals_body_index: 4
+ ├── locals: [:x, :y, :z]
+ ├── locals_body_index: 3
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_forward_args.txt b/test/prism/snapshots/seattlerb/defn_forward_args.txt
index 4782e055ec..e13c469f87 100644
--- a/test/prism/snapshots/seattlerb/defn_forward_args.txt
+++ b/test/prism/snapshots/seattlerb/defn_forward_args.txt
@@ -34,8 +34,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (1,14)-(1,17))
│ ├── closing_loc: (1,17)-(1,18) = ")"
│ └── block: ∅
- ├── locals: [:"..."]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt b/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt
index c357b76bed..8b62141c99 100644
--- a/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt
+++ b/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt
@@ -34,8 +34,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (2,4)-(2,7))
│ ├── closing_loc: (2,7)-(2,8) = ")"
│ └── block: ∅
- ├── locals: [:"..."]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: ∅
diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt
index 897a36bc6a..d1cab9b225 100644
--- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt
+++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt
@@ -29,8 +29,8 @@
│ │ └── operator_loc: (1,12)-(1,14) = "**"
│ └── block: ∅
├── body: ∅
- ├── locals: [:b, :**]
- ├── locals_body_index: 2
+ ├── locals: [:b]
+ ├── locals_body_index: 1
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_splat_arg.txt
index 6533258fe6..a187ae49a8 100644
--- a/test/prism/snapshots/seattlerb/defn_splat_arg.txt
+++ b/test/prism/snapshots/seattlerb/defn_splat_arg.txt
@@ -25,8 +25,8 @@
│ ├── keyword_rest: ∅
│ └── block: ∅
├── body: ∅
- ├── locals: [:*, :a]
- ├── locals_body_index: 2
+ ├── locals: [:a]
+ ├── locals_body_index: 1
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/unparser/corpus/literal/def.txt b/test/prism/snapshots/unparser/corpus/literal/def.txt
index d1face8810..b6d88a4e0f 100644
--- a/test/prism/snapshots/unparser/corpus/literal/def.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/def.txt
@@ -774,8 +774,8 @@
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ └── block: ∅
- │ ├── locals: [:*]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (83,0)-(83,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (83,7)-(83,8) = "("
diff --git a/test/prism/snapshots/unparser/corpus/literal/since/31.txt b/test/prism/snapshots/unparser/corpus/literal/since/31.txt
index 7927a8e44a..09e94d6b7f 100644
--- a/test/prism/snapshots/unparser/corpus/literal/since/31.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/since/31.txt
@@ -37,8 +37,8 @@
│ │ @ BlockArgumentNode (location: (2,6)-(2,7))
│ │ ├── expression: ∅
│ │ └── operator_loc: (2,6)-(2,7) = "&"
- │ ├── locals: [:&]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (1,0)-(1,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (1,7)-(1,8) = "("
@@ -82,8 +82,8 @@
│ @ BlockArgumentNode (location: (6,6)-(6,7))
│ ├── expression: ∅
│ └── operator_loc: (6,6)-(6,7) = "&"
- ├── locals: [:a, :&]
- ├── locals_body_index: 2
+ ├── locals: [:a]
+ ├── locals_body_index: 1
├── def_keyword_loc: (5,0)-(5,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (5,7)-(5,8) = "("
diff --git a/test/prism/snapshots/unparser/corpus/literal/since/32.txt b/test/prism/snapshots/unparser/corpus/literal/since/32.txt
index a202628595..9b7fa85fe0 100644
--- a/test/prism/snapshots/unparser/corpus/literal/since/32.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/since/32.txt
@@ -49,8 +49,8 @@
│ │ │ └── operator_loc: (2,16)-(2,18) = "**"
│ │ ├── closing_loc: (2,18)-(2,19) = ")"
│ │ └── block: ∅
- │ ├── locals: [:argument, :**]
- │ ├── locals_body_index: 2
+ │ ├── locals: [:argument]
+ │ ├── locals_body_index: 1
│ ├── def_keyword_loc: (1,0)-(1,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (1,7)-(1,8) = "("
@@ -100,8 +100,8 @@
│ │ └── expression: ∅
│ ├── closing_loc: (6,17)-(6,18) = ")"
│ └── block: ∅
- ├── locals: [:argument, :*]
- ├── locals_body_index: 2
+ ├── locals: [:argument]
+ ├── locals_body_index: 1
├── def_keyword_loc: (5,0)-(5,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (5,7)-(5,8) = "("
diff --git a/test/prism/snapshots/whitequark/anonymous_blockarg.txt b/test/prism/snapshots/whitequark/anonymous_blockarg.txt
index aaeef280a0..da760b785f 100644
--- a/test/prism/snapshots/whitequark/anonymous_blockarg.txt
+++ b/test/prism/snapshots/whitequark/anonymous_blockarg.txt
@@ -37,8 +37,8 @@
│ @ BlockArgumentNode (location: (1,16)-(1,17))
│ ├── expression: ∅
│ └── operator_loc: (1,16)-(1,17) = "&"
- ├── locals: [:&]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/args.txt b/test/prism/snapshots/whitequark/args.txt
index 927ee3c1fe..53bd2ebbc3 100644
--- a/test/prism/snapshots/whitequark/args.txt
+++ b/test/prism/snapshots/whitequark/args.txt
@@ -521,8 +521,8 @@
│ │ │ └── operator_loc: (29,9)-(29,11) = "**"
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:*, :**]
- │ ├── locals_body_index: 2
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (29,0)-(29,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
diff --git a/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt b/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt
index 366258cf92..039b014a1c 100644
--- a/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt
+++ b/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt
@@ -34,8 +34,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (1,19)-(1,22))
│ ├── closing_loc: (1,22)-(1,23) = ")"
│ └── block: ∅
- ├── locals: [:"..."]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forward_arg.txt b/test/prism/snapshots/whitequark/forward_arg.txt
index c81fc7a142..0ec875106d 100644
--- a/test/prism/snapshots/whitequark/forward_arg.txt
+++ b/test/prism/snapshots/whitequark/forward_arg.txt
@@ -34,8 +34,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (1,18)-(1,21))
│ ├── closing_loc: (1,21)-(1,22) = ")"
│ └── block: ∅
- ├── locals: [:"..."]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt
index 75fb87e0e7..a85400a37f 100644
--- a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt
+++ b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt
@@ -38,8 +38,8 @@
│ │ │ │ └── @ ForwardingArgumentsNode (location: (2,6)-(2,9))
│ │ │ ├── closing_loc: (2,9)-(2,10) = ")"
│ │ │ └── block: ∅
- │ │ ├── locals: [:"..."]
- │ │ ├── locals_body_index: 1
+ │ │ ├── locals: []
+ │ │ ├── locals_body_index: 0
│ │ ├── def_keyword_loc: (1,1)-(1,4) = "def"
│ │ ├── operator_loc: ∅
│ │ ├── lparen_loc: ∅
@@ -83,8 +83,8 @@
│ │ │ │ └── @ ForwardingArgumentsNode (location: (5,18)-(5,21))
│ │ │ ├── closing_loc: (5,21)-(5,22) = ")"
│ │ │ └── block: ∅
- │ │ ├── locals: [:"..."]
- │ │ ├── locals_body_index: 1
+ │ │ ├── locals: []
+ │ │ ├── locals_body_index: 0
│ │ ├── def_keyword_loc: (5,1)-(5,4) = "def"
│ │ ├── operator_loc: ∅
│ │ ├── lparen_loc: ∅
@@ -108,8 +108,8 @@
│ │ │ @ ForwardingParameterNode (location: (7,8)-(7,11))
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (7,0)-(7,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -147,8 +147,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (10,17)-(10,20))
│ │ ├── closing_loc: (10,20)-(10,21) = ")"
│ │ └── block: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (10,0)-(10,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -189,8 +189,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (13,6)-(13,9))
│ │ ├── closing_loc: (13,9)-(13,10) = ")"
│ │ └── block: ∅
- │ ├── locals: [:a, :"..."]
- │ ├── locals_body_index: 2
+ │ ├── locals: [:a]
+ │ ├── locals_body_index: 1
│ ├── def_keyword_loc: (12,0)-(12,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -231,8 +231,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (16,20)-(16,23))
│ │ ├── closing_loc: (16,23)-(16,24) = ")"
│ │ └── block: ∅
- │ ├── locals: [:a, :"..."]
- │ ├── locals_body_index: 2
+ │ ├── locals: [:a]
+ │ ├── locals_body_index: 1
│ ├── def_keyword_loc: (16,0)-(16,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -265,8 +265,8 @@
│ │ │ @ ForwardingParameterNode (location: (18,18)-(18,21))
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:a, :b, :"..."]
- │ ├── locals_body_index: 3
+ │ ├── locals: [:a, :b]
+ │ ├── locals_body_index: 2
│ ├── def_keyword_loc: (18,0)-(18,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -312,8 +312,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (22,6)-(22,9))
│ │ ├── closing_loc: (22,9)-(22,10) = ")"
│ │ └── block: ∅
- │ ├── locals: [:b, :"..."]
- │ ├── locals_body_index: 2
+ │ ├── locals: [:b]
+ │ ├── locals_body_index: 1
│ ├── def_keyword_loc: (21,0)-(21,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -359,8 +359,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (25,24)-(25,27))
│ │ ├── closing_loc: (25,27)-(25,28) = ")"
│ │ └── block: ∅
- │ ├── locals: [:b, :"..."]
- │ ├── locals_body_index: 2
+ │ ├── locals: [:b]
+ │ ├── locals_body_index: 1
│ ├── def_keyword_loc: (25,0)-(25,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: ∅
@@ -401,8 +401,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (27,20)-(27,23))
│ ├── closing_loc: (27,23)-(27,24) = ")"
│ └── block: ∅
- ├── locals: [:a, :"..."]
- ├── locals_body_index: 2
+ ├── locals: [:a]
+ ├── locals_body_index: 1
├── def_keyword_loc: (27,0)-(27,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (27,7)-(27,8) = "("
diff --git a/test/prism/snapshots/whitequark/forward_args_legacy.txt b/test/prism/snapshots/whitequark/forward_args_legacy.txt
index 6175e6588f..d2774737e9 100644
--- a/test/prism/snapshots/whitequark/forward_args_legacy.txt
+++ b/test/prism/snapshots/whitequark/forward_args_legacy.txt
@@ -34,8 +34,8 @@
│ │ │ └── @ ForwardingArgumentsNode (location: (1,18)-(1,21))
│ │ ├── closing_loc: (1,21)-(1,22) = ")"
│ │ └── block: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (1,0)-(1,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (1,7)-(1,8) = "("
@@ -57,8 +57,8 @@
│ │ │ @ ForwardingParameterNode (location: (3,8)-(3,11))
│ │ └── block: ∅
│ ├── body: ∅
- │ ├── locals: [:"..."]
- │ ├── locals_body_index: 1
+ │ ├── locals: []
+ │ ├── locals_body_index: 0
│ ├── def_keyword_loc: (3,0)-(3,3) = "def"
│ ├── operator_loc: ∅
│ ├── lparen_loc: (3,7)-(3,8) = "("
@@ -92,8 +92,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (5,20)-(5,23))
│ ├── rparen_loc: (5,23)-(5,24) = ")"
│ └── block: ∅
- ├── locals: [:"..."]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (5,0)-(5,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (5,7)-(5,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt
index ff7a094575..d7a1d53d83 100644
--- a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt
@@ -49,8 +49,8 @@
│ │ └── operator_loc: (1,37)-(1,39) = "**"
│ ├── closing_loc: (1,39)-(1,40) = ")"
│ └── block: ∅
- ├── locals: [:argument, :**]
- ├── locals_body_index: 2
+ ├── locals: [:argument]
+ ├── locals_body_index: 1
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt
index 249a6260ce..df93c463a3 100644
--- a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt
@@ -46,8 +46,8 @@
│ │ └── expression: ∅
│ ├── closing_loc: (1,37)-(1,38) = ")"
│ └── block: ∅
- ├── locals: [:argument, :*]
- ├── locals_body_index: 2
+ ├── locals: [:argument]
+ ├── locals_body_index: 1
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt
index bd2f55aeba..2d44055e21 100644
--- a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt
@@ -43,8 +43,8 @@
│ │ └── operator_loc: (1,17)-(1,19) = "**"
│ ├── closing_loc: (1,19)-(1,20) = ")"
│ └── block: ∅
- ├── locals: [:**]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
index 4299036bf8..5f29c7d61d 100644
--- a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
@@ -54,8 +54,8 @@
│ │ └── operator_loc: ∅
│ ├── closing_loc: (1,35)-(1,36) = ")"
│ └── block: ∅
- ├── locals: [:**]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_restarg.txt b/test/prism/snapshots/whitequark/forwarded_restarg.txt
index 43e514bde5..ac24409eb4 100644
--- a/test/prism/snapshots/whitequark/forwarded_restarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_restarg.txt
@@ -40,8 +40,8 @@
│ │ └── expression: ∅
│ ├── closing_loc: (1,17)-(1,18) = ")"
│ └── block: ∅
- ├── locals: [:*]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt b/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
index f39e6e4466..d951497293 100644
--- a/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
+++ b/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
@@ -49,8 +49,8 @@
│ │ └── operator_loc: (1,21)-(1,23) = "**"
│ ├── closing_loc: (1,23)-(1,24) = ")"
│ └── block: ∅
- ├── locals: [:a, :**]
- ├── locals_body_index: 2
+ ├── locals: [:a]
+ ├── locals_body_index: 1
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt b/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt
index 564dfbcd6f..92e65deb56 100644
--- a/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt
+++ b/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt
@@ -22,8 +22,8 @@
│ │ └── operator_loc: (1,6)-(1,8) = "**"
│ └── block: ∅
├── body: ∅
- ├── locals: [:**]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/whitequark/restarg_unnamed.txt b/test/prism/snapshots/whitequark/restarg_unnamed.txt
index 388dad1972..cf8c57f004 100644
--- a/test/prism/snapshots/whitequark/restarg_unnamed.txt
+++ b/test/prism/snapshots/whitequark/restarg_unnamed.txt
@@ -22,8 +22,8 @@
│ ├── keyword_rest: ∅
│ └── block: ∅
├── body: ∅
- ├── locals: [:*]
- ├── locals_body_index: 1
+ ├── locals: []
+ ├── locals_body_index: 0
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/whitequark/trailing_forward_arg.txt b/test/prism/snapshots/whitequark/trailing_forward_arg.txt
index fa6036e469..20bfe57428 100644
--- a/test/prism/snapshots/whitequark/trailing_forward_arg.txt
+++ b/test/prism/snapshots/whitequark/trailing_forward_arg.txt
@@ -45,8 +45,8 @@
│ │ └── @ ForwardingArgumentsNode (location: (1,31)-(1,34))
│ ├── closing_loc: (1,34)-(1,35) = ")"
│ └── block: ∅
- ├── locals: [:a, :b, :"..."]
- ├── locals_body_index: 3
+ ├── locals: [:a, :b]
+ ├── locals_body_index: 2
├── def_keyword_loc: (1,0)-(1,3) = "def"
├── operator_loc: ∅
├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index 901cc0741e..fc11eb21b7 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -1616,6 +1616,30 @@ a
CODE
end
+ def test_pow_parameters
+ assert_prism_eval("def self.m(a, **); end; method(:m).parameters")
+ end
+
+ def test_star_parameters
+ assert_prism_eval("def self.m(a, *, b); end; method(:m).parameters")
+ end
+
+ def test_repeated_block_params
+ assert_prism_eval("def self.x(&blk); blk; end; x { |_, _, _ = 1, *_, _:, _: 2, **_, &_| }.parameters")
+ end
+
+ def test_repeated_proc_params
+ assert_prism_eval("proc {|_, _, _ = 1, *_, _:, _: 2, **_, &_| }.parameters")
+ end
+
+ def test_forward_parameters_block
+ assert_prism_eval("def self.m(&); end; method(:m).parameters")
+ end
+
+ def test_forward_parameters
+ assert_prism_eval("def self.m(...); end; method(:m).parameters")
+ end
+
def test_repeated_block_underscore
assert_prism_eval("def self.m(_, **_, &_); _; end; method(:m).parameters")
end