Skip to content

Commit

Permalink
[ruby/prism] Emit error when assigning to a numbered parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
haldun authored and matzbot committed Oct 6, 2023
1 parent 7b8d472 commit 7eccc13
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
14 changes: 9 additions & 5 deletions prism/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -3444,11 +3444,20 @@ pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name,
return node;
}

static inline bool
token_is_numbered_parameter(const uint8_t *start, const uint8_t *end) {
return (end - start == 2) && (start[0] == '_') && (start[1] != '0') && (pm_char_is_decimal_digit(start[1]));
}

// Allocate and initialize a new LocalVariableTargetNode node.
static pm_local_variable_target_node_t *
pm_local_variable_target_node_create(pm_parser_t *parser, const pm_token_t *name) {
pm_local_variable_target_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_target_node_t);

if (token_is_numbered_parameter(name->start, name->end)) {
pm_parser_err_token(parser, name, PM_ERR_PARAMETER_NUMBERED_RESERVED);
}

*node = (pm_local_variable_target_node_t) {
{
.type = PM_LOCAL_VARIABLE_TARGET_NODE,
Expand Down Expand Up @@ -4944,11 +4953,6 @@ pm_parser_local_add_owned(pm_parser_t *parser, const uint8_t *start, size_t leng
if (constant_id != 0) pm_parser_local_add(parser, constant_id);
}

static inline bool
token_is_numbered_parameter(const uint8_t *start, const uint8_t *end) {
return (end - start == 2) && (start[0] == '_') && (start[1] != '0') && (pm_char_is_decimal_digit(start[1]));
}

// Add a parameter name to the current scope and check whether the name of the
// parameter is unique or not.
static void
Expand Down
15 changes: 15 additions & 0 deletions test/prism/errors_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,21 @@ def test_repeated_parameter_name_in_destructured_params
], compare_ripper: compare_ripper
end

def test_assign_to_numbered_parameter
source = "
a in _1
a => _1
1 => a, _1
1 in a, _1
"
assert_errors expression(source), source, [
["Token reserved for a numbered parameter", 14..16],
["Token reserved for a numbered parameter", 30..32],
["Token reserved for a numbered parameter", 49..51],
["Token reserved for a numbered parameter", 68..70],
]
end

private

def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")
Expand Down

0 comments on commit 7eccc13

Please sign in to comment.