summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTSUYUSATO Kitsune <[email protected]>2024-01-03 13:30:23 +0900
committergit <[email protected]>2024-01-03 17:20:33 +0000
commita25329e0dab2a3ada395b1e4e0254a15cd498de2 ()
tree5fb67f8a41eb5505902ef4459634e2ba597b467d
parent3a3fcf56d0ab6b6887024ce7eba0676bae0ce13d (diff)
[ruby/prism] Fix parsing pinned local variable pattern for numbered parameter
Fix https://.com/ruby/prism/pull/2094 The part of `parse_variable_call` for variables was split into a new function `parse_variable` and used it. https://.com/ruby/prism/commit/4c5fd1a746
-rw-r--r--prism/prism.c124
-rw-r--r--test/prism/fixtures/case.txt6
-rw-r--r--test/prism/fixtures/patterns.txt2
-rw-r--r--test/prism/snapshots/case.txt90
-rw-r--r--test/prism/snapshots/patterns.txt105
5 files changed, 210 insertions, 117 deletions
@@ -12776,6 +12776,65 @@ outer_scope_using_numbered_parameters_p(pm_parser_t *parser) {
}
/**
* Parse an identifier into either a local variable read or a call.
*/
static pm_node_t *
@@ -12783,56 +12842,8 @@ parse_variable_call(pm_parser_t *parser) {
pm_node_flags_t flags = 0;
if (!match1(parser, PM_TOKEN_PARENTHESIS_LEFT) && (parser->previous.end[-1] != '!') && (parser->previous.end[-1] != '?')) {
- int depth;
- if ((depth = pm_parser_local_depth(parser, &parser->previous)) != -1) {
- return (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth);
- }
-
- if (!parser->current_scope->closed && pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) {
- // Now that we know we have a numbered parameter, we need to check
- // if it's allowed in this context. If it is, then we will create a
- // local variable read. If it's not, then we'll create a normal call
- // node but add an error.
- if (parser->current_scope->explicit_params) {
- pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED);
- } else if (outer_scope_using_numbered_parameters_p(parser)) {
- pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE);
- } else {
- // Indicate that this scope is using numbered params so that child
- // scopes cannot.
- uint8_t number = parser->previous.start[1];
-
- // We subtract the value for the character '0' to get the actual
- // integer value of the number (only _1 through _9 are valid)
- uint8_t numbered_parameters = (uint8_t) (number - '0');
- if (numbered_parameters > parser->current_scope->numbered_parameters) {
- parser->current_scope->numbered_parameters = numbered_parameters;
- pm_parser_numbered_parameters_set(parser, numbered_parameters);
- }
-
- // When you use a numbered parameter, it implies the existence
- // of all of the locals that exist before it. For example,
- // referencing _2 means that _1 must exist. Therefore here we
- // loop through all of the possibilities and add them into the
- // constant pool.
- uint8_t current = '1';
- uint8_t *value;
-
- while (current < number) {
- value = malloc(2);
- value[0] = '_';
- value[1] = current++;
- pm_parser_local_add_owned(parser, value, 2);
- }
-
- // Now we can add the actual token that is being used. For
- // this one we can add a shared version since it is directly
- // referenced in the source.
- pm_parser_local_add_token(parser, &parser->previous);
- return (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, 0);
- }
- }
-
flags |= PM_CALL_NODE_FLAGS_VARIABLE_CALL;
}
@@ -13391,15 +13402,12 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
// expression to determine if it's a variable or an expression.
switch (parser->current.type) {
case PM_TOKEN_IDENTIFIER: {
- int depth = pm_parser_local_depth(parser, &parser->current);
-
- if (depth == -1) {
- depth = 0;
- PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_NO_LOCAL_VARIABLE, (int) (parser->current.end - parser->current.start), parser->current.start);
- }
-
- pm_node_t *variable = (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->current, (uint32_t) depth);
parser_lex(parser);
return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
}
@@ -42,3 +42,9 @@ in 3
end
case 1 in 2; in 3; end
@@ -200,3 +200,5 @@ foo do
end
foo => Object[{x:}]
@@ -1,8 +1,8 @@
-@ ProgramNode (location: (1,0)-(44,22))
├── locals: []
└── statements:
- @ StatementsNode (location: (1,0)-(44,22))
- └── body: (length: 13)
├── @ CaseNode (location: (1,0)-(3,3))
│ ├── predicate:
│ │ @ SymbolNode (location: (1,5)-(1,8))
@@ -335,24 +335,66 @@
│ ├── consequent: ∅
│ ├── case_keyword_loc: (40,0)-(40,4) = "case"
│ └── end_keyword_loc: (42,0)-(42,3) = "end"
- └── @ CaseMatchNode (location: (44,0)-(44,22))
- ├── predicate:
- │ @ MatchPredicateNode (location: (44,5)-(44,11))
- │ ├── value:
- │ │ @ IntegerNode (location: (44,5)-(44,6))
- │ │ └── flags: decimal
- │ ├── pattern:
- │ │ @ IntegerNode (location: (44,10)-(44,11))
- │ │ └── flags: decimal
- │ └── operator_loc: (44,7)-(44,9) = "in"
- ├── conditions: (length: 1)
- │ └── @ InNode (location: (44,13)-(44,17))
- │ ├── pattern:
- │ │ @ IntegerNode (location: (44,16)-(44,17))
- │ │ └── flags: decimal
- │ ├── statements: ∅
- │ ├── in_loc: (44,13)-(44,15) = "in"
- │ └── then_loc: ∅
- ├── consequent: ∅
- ├── case_keyword_loc: (44,0)-(44,4) = "case"
- └── end_keyword_loc: (44,19)-(44,22) = "end"
@@ -1,8 +1,8 @@
-@ ProgramNode (location: (1,0)-(202,19))
├── locals: [:bar, :baz, :qux, :b, :a, :foo, :x]
└── statements:
- @ StatementsNode (location: (1,0)-(202,19))
- └── body: (length: 176)
├── @ MatchRequiredNode (location: (1,0)-(1,10))
│ ├── value:
│ │ @ CallNode (location: (1,0)-(1,3))
@@ -4735,35 +4735,70 @@
│ │ └── operator_loc: (199,9)-(199,11) = "=>"
│ ├── opening_loc: (198,4)-(198,6) = "do"
│ └── closing_loc: (200,0)-(200,3) = "end"
- └── @ MatchRequiredNode (location: (202,0)-(202,19))
- ├── value:
- │ @ LocalVariableReadNode (location: (202,0)-(202,3))
- │ ├── name: :foo
- │ └── depth: 0
- ├── pattern:
- │ @ ArrayPatternNode (location: (202,7)-(202,19))
- │ ├── constant:
- │ │ @ ConstantReadNode (location: (202,7)-(202,13))
- │ │ └── name: :Object
- │ ├── requireds: (length: 1)
- │ │ └── @ HashPatternNode (location: (202,14)-(202,18))
- │ │ ├── constant: ∅
- │ │ ├── elements: (length: 1)
- │ │ │ └── @ AssocNode (location: (202,15)-(202,17))
- │ │ │ ├── key:
- │ │ │ │ @ SymbolNode (location: (202,15)-(202,17))
- │ │ │ │ ├── flags: ∅
- │ │ │ │ ├── opening_loc: ∅
- │ │ │ │ ├── value_loc: (202,15)-(202,16) = "x"
- │ │ │ │ ├── closing_loc: (202,16)-(202,17) = ":"
- │ │ │ │ └── unescaped: "x"
- │ │ │ ├── value: ∅
- │ │ │ └── operator_loc: ∅
- │ │ ├── rest: ∅
- │ │ ├── opening_loc: (202,14)-(202,15) = "{"
- │ │ └── closing_loc: (202,17)-(202,18) = "}"
- │ ├── rest: ∅
- │ ├── posts: (length: 0)
- │ ├── opening_loc: (202,13)-(202,14) = "["
- │ └── closing_loc: (202,18)-(202,19) = "]"
- └── operator_loc: (202,4)-(202,6) = "=>"