diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2024-01-25 15:08:44 -0800 |
---|---|---|
committer | Kevin Newton <kddnewton@gmail.com> | 2024-01-30 13:19:06 -0500 |
commit | 8e708e4a077d85e50cd797b2478aba7bfd5e4ac3 (patch) | |
tree | 87aeb4f38b86b2c2a5f6a8ae0e606f93f5a0b637 | |
parent | 6b350bc6e41551161f4be37858c54fcca1a09c46 (diff) | |
download | ruby-8e708e4a077d85e50cd797b2478aba7bfd5e4ac3.tar.gz |
Update forwarding locals for prism
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 |