diff --git a/src/prism.c b/src/prism.c index cbf0d193562..f0a8030d82b 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9719,7 +9719,7 @@ parser_lex(pm_parser_t *parser) { typedef enum { PM_BINDING_POWER_UNSET = 0, // used to indicate this token cannot be used as an infix operator PM_BINDING_POWER_STATEMENT = 2, - PM_BINDING_POWER_MODIFIER = 4, // if unless until while in + PM_BINDING_POWER_MODIFIER = 4, // if unless until while PM_BINDING_POWER_MODIFIER_RESCUE = 6, // rescue PM_BINDING_POWER_COMPOSITION = 8, // and or PM_BINDING_POWER_NOT = 10, // not @@ -9758,34 +9758,44 @@ typedef struct { /** Whether or not this token can be used as a binary operator. */ bool binary; + + /** + * Whether or not this token can be used as non associative binary operator. + * Usually, non associative operator can be handled by using the above left + * and right binding powers, but some operators (e.g. in and =>) need special + * treatment since they do not call parse_expression recursively. + */ + bool nonassoc; } pm_binding_powers_t; -#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true } -#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true } -#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true } -#define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false } +#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true, false } +#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, false } +#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true, false } +#define NON_ASSOCIATIVE(precedence) { precedence + 1, precedence + 1, true, true } +#define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false, false } pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = { - // if unless until while in rescue + // if unless until while [PM_TOKEN_KEYWORD_IF_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), [PM_TOKEN_KEYWORD_UNLESS_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), [PM_TOKEN_KEYWORD_UNTIL_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), [PM_TOKEN_KEYWORD_WHILE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), - [PM_TOKEN_KEYWORD_IN] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), - // rescue modifier + // rescue [PM_TOKEN_KEYWORD_RESCUE_MODIFIER] = { PM_BINDING_POWER_ASSIGNMENT, PM_BINDING_POWER_MODIFIER_RESCUE + 1, - true + true, + false }, // and or [PM_TOKEN_KEYWORD_AND] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPOSITION), [PM_TOKEN_KEYWORD_OR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPOSITION), - // => - [PM_TOKEN_EQUAL_GREATER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MATCH), + // => in + [PM_TOKEN_EQUAL_GREATER] = NON_ASSOCIATIVE(PM_BINDING_POWER_MATCH), + [PM_TOKEN_KEYWORD_IN] = NON_ASSOCIATIVE(PM_BINDING_POWER_MATCH), // &&= &= ^= = >>= <<= -= %= |= += /= *= **= [PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL] = BINDING_POWER_ASSIGNMENT, @@ -9853,7 +9863,7 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = { // -@ [PM_TOKEN_UMINUS] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UMINUS), - [PM_TOKEN_UMINUS_NUM] = { PM_BINDING_POWER_UMINUS, PM_BINDING_POWER_MAX, false }, + [PM_TOKEN_UMINUS_NUM] = { PM_BINDING_POWER_UMINUS, PM_BINDING_POWER_MAX, false, false }, // ** [PM_TOKEN_STAR_STAR] = RIGHT_ASSOCIATIVE(PM_BINDING_POWER_EXPONENT), @@ -16212,6 +16222,12 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagn current_binding_powers.binary ) { node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right); + if ( + current_binding_powers.nonassoc && + current_binding_powers.right < pm_binding_powers[parser->current.type].left + ) { + break; + } } return node; diff --git a/test/prism/fixtures/patterns.txt b/test/prism/fixtures/patterns.txt index e0c5f303cb5..9f73e6ecc51 100644 --- a/test/prism/fixtures/patterns.txt +++ b/test/prism/fixtures/patterns.txt @@ -190,3 +190,6 @@ foo in A[ value: a ] ] + +foo in bar => baz +foo => bar => baz diff --git a/test/prism/fixtures/until.txt b/test/prism/fixtures/until.txt index fa93819e253..7dcb5d495db 100644 --- a/test/prism/fixtures/until.txt +++ b/test/prism/fixtures/until.txt @@ -9,3 +9,5 @@ next until true return until true foo :a, :b until bar? + +foo while bar in baz diff --git a/test/prism/fixtures/while.txt b/test/prism/fixtures/while.txt index 66321b5368c..eecfbfdddd0 100644 --- a/test/prism/fixtures/while.txt +++ b/test/prism/fixtures/while.txt @@ -19,3 +19,5 @@ while class << self; tap do end; end; break; end while class << self; a = tap do end; end; break; end while def foo = bar do end; end + +foo while bar in baz diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index 0994330e451..d8f4935b96c 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(192,1)) +@ ProgramNode (location: (1,0)-(195,17)) ├── locals: [:bar, :baz, :qux, :b, :a] └── statements: - @ StatementsNode (location: (1,0)-(192,1)) - └── body: (length: 170) + @ StatementsNode (location: (1,0)-(195,17)) + └── body: (length: 172) ├── @ MatchRequiredNode (location: (1,0)-(1,10)) │ ├── value: │ │ @ CallNode (location: (1,0)-(1,3)) @@ -4449,12 +4449,87 @@ │ │ ├── opening_loc: (184,5)-(184,6) = "[" │ │ └── closing_loc: (186,0)-(186,1) = "]" │ └── operator_loc: (184,2)-(184,4) = "=>" - └── @ MatchPredicateNode (location: (188,0)-(192,1)) + ├── @ MatchPredicateNode (location: (188,0)-(192,1)) + │ ├── value: + │ │ @ CallNode (location: (188,0)-(188,3)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── message_loc: (188,0)-(188,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ ├── flags: variable_call + │ │ └── name: :foo + │ ├── pattern: + │ │ @ HashPatternNode (location: (188,7)-(192,1)) + │ │ ├── constant: + │ │ │ @ ConstantReadNode (location: (188,7)-(188,8)) + │ │ │ └── name: :A + │ │ ├── elements: (length: 1) + │ │ │ └── @ AssocNode (location: (189,2)-(191,3)) + │ │ │ ├── key: + │ │ │ │ @ SymbolNode (location: (189,2)-(189,6)) + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (189,2)-(189,5) = "bar" + │ │ │ │ ├── closing_loc: (189,5)-(189,6) = ":" + │ │ │ │ └── unescaped: "bar" + │ │ │ ├── value: + │ │ │ │ @ HashPatternNode (location: (189,7)-(191,3)) + │ │ │ │ ├── constant: + │ │ │ │ │ @ ConstantReadNode (location: (189,7)-(189,8)) + │ │ │ │ │ └── name: :B + │ │ │ │ ├── elements: (length: 1) + │ │ │ │ │ └── @ AssocNode (location: (190,4)-(190,12)) + │ │ │ │ │ ├── key: + │ │ │ │ │ │ @ SymbolNode (location: (190,4)-(190,10)) + │ │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ │ ├── value_loc: (190,4)-(190,9) = "value" + │ │ │ │ │ │ ├── closing_loc: (190,9)-(190,10) = ":" + │ │ │ │ │ │ └── unescaped: "value" + │ │ │ │ │ ├── value: + │ │ │ │ │ │ @ LocalVariableTargetNode (location: (190,11)-(190,12)) + │ │ │ │ │ │ ├── name: :a + │ │ │ │ │ │ └── depth: 0 + │ │ │ │ │ └── operator_loc: ∅ + │ │ │ │ ├── rest: ∅ + │ │ │ │ ├── opening_loc: (189,8)-(189,9) = "[" + │ │ │ │ └── closing_loc: (191,2)-(191,3) = "]" + │ │ │ └── operator_loc: ∅ + │ │ ├── rest: ∅ + │ │ ├── opening_loc: (188,8)-(188,9) = "[" + │ │ └── closing_loc: (192,0)-(192,1) = "]" + │ └── operator_loc: (188,4)-(188,6) = "in" + ├── @ MatchPredicateNode (location: (194,0)-(194,17)) + │ ├── value: + │ │ @ CallNode (location: (194,0)-(194,3)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── message_loc: (194,0)-(194,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ ├── flags: variable_call + │ │ └── name: :foo + │ ├── pattern: + │ │ @ CapturePatternNode (location: (194,7)-(194,17)) + │ │ ├── value: + │ │ │ @ LocalVariableTargetNode (location: (194,7)-(194,10)) + │ │ │ ├── name: :bar + │ │ │ └── depth: 0 + │ │ ├── target: + │ │ │ @ LocalVariableTargetNode (location: (194,14)-(194,17)) + │ │ │ ├── name: :baz + │ │ │ └── depth: 0 + │ │ └── operator_loc: (194,11)-(194,13) = "=>" + │ └── operator_loc: (194,4)-(194,6) = "in" + └── @ MatchRequiredNode (location: (195,0)-(195,17)) ├── value: - │ @ CallNode (location: (188,0)-(188,3)) + │ @ CallNode (location: (195,0)-(195,3)) │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ - │ ├── message_loc: (188,0)-(188,3) = "foo" + │ ├── message_loc: (195,0)-(195,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ @@ -4462,41 +4537,14 @@ │ ├── flags: variable_call │ └── name: :foo ├── pattern: - │ @ HashPatternNode (location: (188,7)-(192,1)) - │ ├── constant: - │ │ @ ConstantReadNode (location: (188,7)-(188,8)) - │ │ └── name: :A - │ ├── elements: (length: 1) - │ │ └── @ AssocNode (location: (189,2)-(191,3)) - │ │ ├── key: - │ │ │ @ SymbolNode (location: (189,2)-(189,6)) - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (189,2)-(189,5) = "bar" - │ │ │ ├── closing_loc: (189,5)-(189,6) = ":" - │ │ │ └── unescaped: "bar" - │ │ ├── value: - │ │ │ @ HashPatternNode (location: (189,7)-(191,3)) - │ │ │ ├── constant: - │ │ │ │ @ ConstantReadNode (location: (189,7)-(189,8)) - │ │ │ │ └── name: :B - │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ AssocNode (location: (190,4)-(190,12)) - │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (190,4)-(190,10)) - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (190,4)-(190,9) = "value" - │ │ │ │ │ ├── closing_loc: (190,9)-(190,10) = ":" - │ │ │ │ │ └── unescaped: "value" - │ │ │ │ ├── value: - │ │ │ │ │ @ LocalVariableTargetNode (location: (190,11)-(190,12)) - │ │ │ │ │ ├── name: :a - │ │ │ │ │ └── depth: 0 - │ │ │ │ └── operator_loc: ∅ - │ │ │ ├── rest: ∅ - │ │ │ ├── opening_loc: (189,8)-(189,9) = "[" - │ │ │ └── closing_loc: (191,2)-(191,3) = "]" - │ │ └── operator_loc: ∅ - │ ├── rest: ∅ - │ ├── opening_loc: (188,8)-(188,9) = "[" - │ └── closing_loc: (192,0)-(192,1) = "]" - └── operator_loc: (188,4)-(188,6) = "in" + │ @ 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) = "=>" diff --git a/test/prism/snapshots/until.txt b/test/prism/snapshots/until.txt index d2fa6b7a522..7e741603db9 100644 --- a/test/prism/snapshots/until.txt +++ b/test/prism/snapshots/until.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(11,21)) -├── locals: [] +@ ProgramNode (location: (1,0)-(13,20)) +├── locals: [:baz] └── statements: - @ StatementsNode (location: (1,0)-(11,21)) - └── body: (length: 6) + @ StatementsNode (location: (1,0)-(13,20)) + └── body: (length: 7) ├── @ UntilNode (location: (1,0)-(1,18)) │ ├── keyword_loc: (1,0)-(1,5) = "until" │ ├── closing_loc: (1,15)-(1,18) = "end" @@ -61,44 +61,79 @@ │ │ ├── keyword_loc: (9,0)-(9,6) = "return" │ │ └── arguments: ∅ │ └── flags: ∅ - └── @ UntilNode (location: (11,0)-(11,21)) - ├── keyword_loc: (11,11)-(11,16) = "until" + ├── @ UntilNode (location: (11,0)-(11,21)) + │ ├── keyword_loc: (11,11)-(11,16) = "until" + │ ├── closing_loc: ∅ + │ ├── predicate: + │ │ @ CallNode (location: (11,17)-(11,21)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── message_loc: (11,17)-(11,21) = "bar?" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ ├── flags: ∅ + │ │ └── name: :bar? + │ ├── statements: + │ │ @ StatementsNode (location: (11,0)-(11,10)) + │ │ └── body: (length: 1) + │ │ └── @ CallNode (location: (11,0)-(11,10)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── message_loc: (11,0)-(11,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (11,4)-(11,10)) + │ │ │ ├── arguments: (length: 2) + │ │ │ │ ├── @ SymbolNode (location: (11,4)-(11,6)) + │ │ │ │ │ ├── opening_loc: (11,4)-(11,5) = ":" + │ │ │ │ │ ├── value_loc: (11,5)-(11,6) = "a" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "a" + │ │ │ │ └── @ SymbolNode (location: (11,8)-(11,10)) + │ │ │ │ ├── opening_loc: (11,8)-(11,9) = ":" + │ │ │ │ ├── value_loc: (11,9)-(11,10) = "b" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "b" + │ │ │ └── flags: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ ├── flags: ∅ + │ │ └── name: :foo + │ └── flags: ∅ + └── @ WhileNode (location: (13,0)-(13,20)) + ├── keyword_loc: (13,4)-(13,9) = "while" ├── closing_loc: ∅ ├── predicate: - │ @ CallNode (location: (11,17)-(11,21)) - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── message_loc: (11,17)-(11,21) = "bar?" - │ ├── opening_loc: ∅ - │ ├── arguments: ∅ - │ ├── closing_loc: ∅ - │ ├── block: ∅ - │ ├── flags: ∅ - │ └── name: :bar? + │ @ MatchPredicateNode (location: (13,10)-(13,20)) + │ ├── value: + │ │ @ CallNode (location: (13,10)-(13,13)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── message_loc: (13,10)-(13,13) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ ├── flags: variable_call + │ │ └── name: :bar + │ ├── pattern: + │ │ @ LocalVariableTargetNode (location: (13,17)-(13,20)) + │ │ ├── name: :baz + │ │ └── depth: 0 + │ └── operator_loc: (13,14)-(13,16) = "in" ├── statements: - │ @ StatementsNode (location: (11,0)-(11,10)) + │ @ StatementsNode (location: (13,0)-(13,3)) │ └── body: (length: 1) - │ └── @ CallNode (location: (11,0)-(11,10)) + │ └── @ CallNode (location: (13,0)-(13,3)) │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ - │ ├── message_loc: (11,0)-(11,3) = "foo" + │ ├── message_loc: (13,0)-(13,3) = "foo" │ ├── opening_loc: ∅ - │ ├── arguments: - │ │ @ ArgumentsNode (location: (11,4)-(11,10)) - │ │ ├── arguments: (length: 2) - │ │ │ ├── @ SymbolNode (location: (11,4)-(11,6)) - │ │ │ │ ├── opening_loc: (11,4)-(11,5) = ":" - │ │ │ │ ├── value_loc: (11,5)-(11,6) = "a" - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── unescaped: "a" - │ │ │ └── @ SymbolNode (location: (11,8)-(11,10)) - │ │ │ ├── opening_loc: (11,8)-(11,9) = ":" - │ │ │ ├── value_loc: (11,9)-(11,10) = "b" - │ │ │ ├── closing_loc: ∅ - │ │ │ └── unescaped: "b" - │ │ └── flags: ∅ + │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ ├── block: ∅ - │ ├── flags: ∅ + │ ├── flags: variable_call │ └── name: :foo └── flags: ∅ diff --git a/test/prism/snapshots/while.txt b/test/prism/snapshots/while.txt index 0fdcfe10c1d..58cbac8ba57 100644 --- a/test/prism/snapshots/while.txt +++ b/test/prism/snapshots/while.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(21,31)) -├── locals: [] +@ ProgramNode (location: (1,0)-(23,20)) +├── locals: [:baz] └── statements: - @ StatementsNode (location: (1,0)-(21,31)) - └── body: (length: 11) + @ StatementsNode (location: (1,0)-(23,20)) + └── body: (length: 12) ├── @ WhileNode (location: (1,0)-(1,18)) │ ├── keyword_loc: (1,0)-(1,5) = "while" │ ├── closing_loc: (1,15)-(1,18) = "end" @@ -282,40 +282,75 @@ │ │ ├── arguments: ∅ │ │ └── keyword_loc: (19,42)-(19,47) = "break" │ └── flags: ∅ - └── @ WhileNode (location: (21,0)-(21,31)) - ├── keyword_loc: (21,0)-(21,5) = "while" - ├── closing_loc: (21,28)-(21,31) = "end" + ├── @ WhileNode (location: (21,0)-(21,31)) + │ ├── keyword_loc: (21,0)-(21,5) = "while" + │ ├── closing_loc: (21,28)-(21,31) = "end" + │ ├── predicate: + │ │ @ DefNode (location: (21,6)-(21,26)) + │ │ ├── name: :foo + │ │ ├── name_loc: (21,10)-(21,13) = "foo" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (21,16)-(21,26)) + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (21,16)-(21,26)) + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── message_loc: (21,16)-(21,19) = "bar" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── block: + │ │ │ │ @ BlockNode (location: (21,20)-(21,26)) + │ │ │ │ ├── locals: [] + │ │ │ │ ├── parameters: ∅ + │ │ │ │ ├── body: ∅ + │ │ │ │ ├── opening_loc: (21,20)-(21,22) = "do" + │ │ │ │ └── closing_loc: (21,23)-(21,26) = "end" + │ │ │ ├── flags: ∅ + │ │ │ └── name: :bar + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (21,6)-(21,9) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (21,14)-(21,15) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── statements: ∅ + │ └── flags: ∅ + └── @ WhileNode (location: (23,0)-(23,20)) + ├── keyword_loc: (23,4)-(23,9) = "while" + ├── closing_loc: ∅ ├── predicate: - │ @ DefNode (location: (21,6)-(21,26)) - │ ├── name: :foo - │ ├── name_loc: (21,10)-(21,13) = "foo" - │ ├── receiver: ∅ - │ ├── parameters: ∅ - │ ├── body: - │ │ @ StatementsNode (location: (21,16)-(21,26)) - │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (21,16)-(21,26)) - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── message_loc: (21,16)-(21,19) = "bar" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ ├── block: - │ │ │ @ BlockNode (location: (21,20)-(21,26)) - │ │ │ ├── locals: [] - │ │ │ ├── parameters: ∅ - │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (21,20)-(21,22) = "do" - │ │ │ └── closing_loc: (21,23)-(21,26) = "end" - │ │ ├── flags: ∅ - │ │ └── name: :bar - │ ├── locals: [] - │ ├── def_keyword_loc: (21,6)-(21,9) = "def" - │ ├── operator_loc: ∅ - │ ├── lparen_loc: ∅ - │ ├── rparen_loc: ∅ - │ ├── equal_loc: (21,14)-(21,15) = "=" - │ └── end_keyword_loc: ∅ - ├── statements: ∅ + │ @ MatchPredicateNode (location: (23,10)-(23,20)) + │ ├── value: + │ │ @ CallNode (location: (23,10)-(23,13)) + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── message_loc: (23,10)-(23,13) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── block: ∅ + │ │ ├── flags: variable_call + │ │ └── name: :bar + │ ├── pattern: + │ │ @ LocalVariableTargetNode (location: (23,17)-(23,20)) + │ │ ├── name: :baz + │ │ └── depth: 0 + │ └── operator_loc: (23,14)-(23,16) = "in" + ├── statements: + │ @ StatementsNode (location: (23,0)-(23,3)) + │ └── body: (length: 1) + │ └── @ CallNode (location: (23,0)-(23,3)) + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── message_loc: (23,0)-(23,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── block: ∅ + │ ├── flags: variable_call + │ └── name: :foo └── flags: ∅