From 7b20dd9f91b4941e4f161dfd2d8b68b33a347a4c Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Thu, 23 Nov 2023 00:06:59 +0900 Subject: [PATCH] [ruby/prism] Fix LocalVariableTargetNode depth in patterns Fix https://github.com/ruby/prism/pull/1821 https://github.com/ruby/prism/commit/7d023a26b4 --- prism/prism.c | 33 +++++++- test/prism/fixtures/patterns.txt | 5 ++ test/prism/snapshots/patterns.txt | 133 +++++++++++++++++++++++------- 3 files changed, 139 insertions(+), 32 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 95bfc5a8db..ba93bbce14 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -4136,6 +4136,22 @@ pm_local_variable_target_node_create(pm_parser_t *parser, const pm_token_t *name ); } +/** + * Allocate and initialize a new LocalVariableTargetNode node with the given depth. + */ +static pm_local_variable_target_node_t * +pm_local_variable_target_node_create_depth(pm_parser_t *parser, const pm_token_t *name, uint32_t depth) { + pm_refute_numbered_parameter(parser, name->start, name->end); + + return pm_local_variable_target_node_create_values( + parser, + &(pm_location_t) { .start = name->start, .end = name->end }, + pm_parser_constant_id_token(parser, name), + depth + ); +} + + /** * Allocate and initialize a new MatchPredicateNode node. */ @@ -13003,8 +13019,13 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { case PM_TOKEN_IDENTIFIER: case PM_TOKEN_METHOD_NAME: { parser_lex(parser); - pm_parser_local_add_token(parser, &parser->previous); - return (pm_node_t *) pm_local_variable_target_node_create(parser, &parser->previous); + pm_token_t name = parser->previous; + int depth = pm_parser_local_depth(parser, &name); + if (depth < 0) { + depth = 0; + pm_parser_local_add_token(parser, &name); + } + return (pm_node_t *) pm_local_variable_target_node_create_depth(parser, &name, (uint32_t) depth); } case PM_TOKEN_BRACKET_LEFT_ARRAY: { pm_token_t opening = parser->current; @@ -13321,9 +13342,13 @@ parse_pattern_primitives(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_PATTERN_IDENT_AFTER_HROCKET); pm_token_t identifier = parser->previous; - pm_parser_local_add_token(parser, &identifier); + int depth = pm_parser_local_depth(parser, &identifier); + if (depth < 0) { + depth = 0; + pm_parser_local_add_token(parser, &identifier); + } - pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create(parser, &identifier); + pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create_depth(parser, &identifier, (uint32_t) depth); node = (pm_node_t *) pm_capture_pattern_node_create(parser, node, target, &operator); } diff --git a/test/prism/fixtures/patterns.txt b/test/prism/fixtures/patterns.txt index 9f73e6ecc5..e4aa83bdf2 100644 --- a/test/prism/fixtures/patterns.txt +++ b/test/prism/fixtures/patterns.txt @@ -193,3 +193,8 @@ foo in A[ foo in bar => baz foo => bar => baz + +foo, bar, baz = 1, 2 +foo do + [1, 2] => [foo, bar] => baz +end diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index 665a345df0..44e15fb644 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(195,17)) -├── locals: [:bar, :baz, :qux, :b, :a] +@ ProgramNode (location: (1,0)-(200,3)) +├── locals: [:bar, :baz, :qux, :b, :a, :foo] └── statements: - @ StatementsNode (location: (1,0)-(195,17)) - └── body: (length: 172) + @ StatementsNode (location: (1,0)-(200,3)) + └── body: (length: 174) ├── @ MatchRequiredNode (location: (1,0)-(1,10)) │ ├── value: │ │ @ CallNode (location: (1,0)-(1,3)) @@ -4575,27 +4575,104 @@ │ │ │ └── depth: 0 │ │ └── operator_loc: (194,11)-(194,13) = "=>" │ └── operator_loc: (194,4)-(194,6) = "in" - └── @ MatchRequiredNode (location: (195,0)-(195,17)) - ├── value: - │ @ CallNode (location: (195,0)-(195,3)) - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :foo - │ ├── message_loc: (195,0)-(195,3) = "foo" - │ ├── opening_loc: ∅ - │ ├── arguments: ∅ - │ ├── closing_loc: ∅ - │ ├── block: ∅ - │ └── flags: variable_call - ├── pattern: - │ @ CapturePatternNode (location: (195,7)-(195,17)) - │ ├── value: - │ │ @ LocalVariableTargetNode (location: (195,7)-(195,10)) - │ │ ├── name: :bar - │ │ └── depth: 0 - │ ├── target: - │ │ @ LocalVariableTargetNode (location: (195,14)-(195,17)) - │ │ ├── name: :baz - │ │ └── depth: 0 - │ └── operator_loc: (195,11)-(195,13) = "=>" - └── operator_loc: (195,4)-(195,6) = "=>" + ├── @ MatchRequiredNode (location: (195,0)-(195,17)) + │ ├── value: + │ │ @ CallNode (location: (195,0)-(195,3)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (195,0)-(195,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ └── flags: variable_call + │ ├── pattern: + │ │ @ CapturePatternNode (location: (195,7)-(195,17)) + │ │ ├── value: + │ │ │ @ LocalVariableTargetNode (location: (195,7)-(195,10)) + │ │ │ ├── name: :bar + │ │ │ └── depth: 0 + │ │ ├── target: + │ │ │ @ LocalVariableTargetNode (location: (195,14)-(195,17)) + │ │ │ ├── name: :baz + │ │ │ └── depth: 0 + │ │ └── operator_loc: (195,11)-(195,13) = "=>" + │ └── operator_loc: (195,4)-(195,6) = "=>" + ├── @ MultiWriteNode (location: (197,0)-(197,20)) + │ ├── lefts: (length: 3) + │ │ ├── @ LocalVariableTargetNode (location: (197,0)-(197,3)) + │ │ │ ├── name: :foo + │ │ │ └── depth: 0 + │ │ ├── @ LocalVariableTargetNode (location: (197,5)-(197,8)) + │ │ │ ├── name: :bar + │ │ │ └── depth: 0 + │ │ └── @ LocalVariableTargetNode (location: (197,10)-(197,13)) + │ │ ├── name: :baz + │ │ └── depth: 0 + │ ├── rest: ∅ + │ ├── rights: (length: 0) + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── operator_loc: (197,14)-(197,15) = "=" + │ └── value: + │ @ ArrayNode (location: (197,16)-(197,20)) + │ ├── elements: (length: 2) + │ │ ├── @ IntegerNode (location: (197,16)-(197,17)) + │ │ │ └── flags: decimal + │ │ └── @ IntegerNode (location: (197,19)-(197,20)) + │ │ └── flags: decimal + │ ├── opening_loc: ∅ + │ ├── closing_loc: ∅ + │ └── flags: ∅ + └── @ CallNode (location: (198,0)-(200,3)) + ├── receiver: ∅ + ├── call_operator_loc: ∅ + ├── name: :foo + ├── message_loc: (198,0)-(198,3) = "foo" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + ├── block: + │ @ BlockNode (location: (198,4)-(200,3)) + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (199,2)-(199,29)) + │ │ └── body: (length: 1) + │ │ └── @ MatchRequiredNode (location: (199,2)-(199,29)) + │ │ ├── value: + │ │ │ @ ArrayNode (location: (199,2)-(199,8)) + │ │ │ ├── elements: (length: 2) + │ │ │ │ ├── @ IntegerNode (location: (199,3)-(199,4)) + │ │ │ │ │ └── flags: decimal + │ │ │ │ └── @ IntegerNode (location: (199,6)-(199,7)) + │ │ │ │ └── flags: decimal + │ │ │ ├── opening_loc: (199,2)-(199,3) = "[" + │ │ │ ├── closing_loc: (199,7)-(199,8) = "]" + │ │ │ └── flags: ∅ + │ │ ├── pattern: + │ │ │ @ CapturePatternNode (location: (199,12)-(199,29)) + │ │ │ ├── value: + │ │ │ │ @ ArrayPatternNode (location: (199,12)-(199,22)) + │ │ │ │ ├── constant: ∅ + │ │ │ │ ├── requireds: (length: 2) + │ │ │ │ │ ├── @ LocalVariableTargetNode (location: (199,13)-(199,16)) + │ │ │ │ │ │ ├── name: :foo + │ │ │ │ │ │ └── depth: 1 + │ │ │ │ │ └── @ LocalVariableTargetNode (location: (199,18)-(199,21)) + │ │ │ │ │ ├── name: :bar + │ │ │ │ │ └── depth: 1 + │ │ │ │ ├── rest: ∅ + │ │ │ │ ├── posts: (length: 0) + │ │ │ │ ├── opening_loc: (199,12)-(199,13) = "[" + │ │ │ │ └── closing_loc: (199,21)-(199,22) = "]" + │ │ │ ├── target: + │ │ │ │ @ LocalVariableTargetNode (location: (199,26)-(199,29)) + │ │ │ │ ├── name: :baz + │ │ │ │ └── depth: 1 + │ │ │ └── operator_loc: (199,23)-(199,25) = "=>" + │ │ └── operator_loc: (199,9)-(199,11) = "=>" + │ ├── opening_loc: (198,4)-(198,6) = "do" + │ └── closing_loc: (200,0)-(200,3) = "end" + └── flags: ∅