diff --git a/snapshots/it_assignment.txt b/snapshots/it_assignment.txt new file mode 100644 index 0000000000..83469791c0 --- /dev/null +++ b/snapshots/it_assignment.txt @@ -0,0 +1,58 @@ +@ ProgramNode (location: (1,0)-(1,24)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(1,24)) + ├── flags: ∅ + └── body: (length: 1) + └── @ CallNode (location: (1,0)-(1,24)) + ├── flags: newline + ├── receiver: + │ @ IntegerNode (location: (1,0)-(1,2)) + │ ├── flags: static_literal, decimal + │ └── value: 42 + ├── call_operator_loc: (1,2)-(1,3) = "." + ├── name: :tap + ├── message_loc: (1,3)-(1,6) = "tap" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + └── block: + @ BlockNode (location: (1,7)-(1,24)) + ├── flags: ∅ + ├── locals: [:it] + ├── parameters: ∅ + ├── body: + │ @ StatementsNode (location: (1,9)-(1,22)) + │ ├── flags: ∅ + │ └── body: (length: 2) + │ ├── @ LocalVariableWriteNode (location: (1,9)-(1,16)) + │ │ ├── flags: newline + │ │ ├── name: :it + │ │ ├── depth: 0 + │ │ ├── name_loc: (1,9)-(1,11) = "it" + │ │ ├── value: + │ │ │ @ LocalVariableReadNode (location: (1,14)-(1,16)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :it + │ │ │ └── depth: 0 + │ │ └── operator_loc: (1,12)-(1,13) = "=" + │ └── @ CallNode (location: (1,18)-(1,22)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :p + │ ├── message_loc: (1,18)-(1,19) = "p" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (1,20)-(1,22)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ LocalVariableReadNode (location: (1,20)-(1,22)) + │ │ ├── flags: ∅ + │ │ ├── name: :it + │ │ └── depth: 0 + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── opening_loc: (1,7)-(1,8) = "{" + └── closing_loc: (1,23)-(1,24) = "}" diff --git a/snapshots/it_read_and_assignment.txt b/snapshots/it_read_and_assignment.txt new file mode 100644 index 0000000000..73aa2b5909 --- /dev/null +++ b/snapshots/it_read_and_assignment.txt @@ -0,0 +1,75 @@ +@ ProgramNode (location: (1,0)-(1,30)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(1,30)) + ├── flags: ∅ + └── body: (length: 1) + └── @ CallNode (location: (1,0)-(1,30)) + ├── flags: newline + ├── receiver: + │ @ IntegerNode (location: (1,0)-(1,2)) + │ ├── flags: static_literal, decimal + │ └── value: 42 + ├── call_operator_loc: (1,2)-(1,3) = "." + ├── name: :tap + ├── message_loc: (1,3)-(1,6) = "tap" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + └── block: + @ BlockNode (location: (1,7)-(1,30)) + ├── flags: ∅ + ├── locals: [:it] + ├── parameters: + │ @ ItParametersNode (location: (1,7)-(1,30)) + │ └── flags: ∅ + ├── body: + │ @ StatementsNode (location: (1,9)-(1,28)) + │ ├── flags: ∅ + │ └── body: (length: 3) + │ ├── @ CallNode (location: (1,9)-(1,13)) + │ │ ├── flags: newline, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :p + │ │ ├── message_loc: (1,9)-(1,10) = "p" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (1,11)-(1,13)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ ItLocalVariableReadNode (location: (1,11)-(1,13)) + │ │ │ └── flags: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── @ LocalVariableWriteNode (location: (1,15)-(1,22)) + │ │ ├── flags: newline + │ │ ├── name: :it + │ │ ├── depth: 0 + │ │ ├── name_loc: (1,15)-(1,17) = "it" + │ │ ├── value: + │ │ │ @ LocalVariableReadNode (location: (1,20)-(1,22)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :it + │ │ │ └── depth: 0 + │ │ └── operator_loc: (1,18)-(1,19) = "=" + │ └── @ CallNode (location: (1,24)-(1,28)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :p + │ ├── message_loc: (1,24)-(1,25) = "p" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (1,26)-(1,28)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ LocalVariableReadNode (location: (1,26)-(1,28)) + │ │ ├── flags: ∅ + │ │ ├── name: :it + │ │ └── depth: 0 + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── opening_loc: (1,7)-(1,8) = "{" + └── closing_loc: (1,29)-(1,30) = "}" diff --git a/src/prism.c b/src/prism.c index 6d4381565c..32930b900e 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21171,6 +21171,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } PRISM_FALLTHROUGH case PM_CASE_WRITABLE: { + // When we have `it = value`, we need to add `it` as a local + // variable before parsing the value, in case the value + // references the variable. + if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) { + pm_parser_local_add_location(parser, node->location.start, node->location.end, 0); + } + parser_lex(parser); pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); diff --git a/test/prism/fixtures/it_assignment.txt b/test/prism/fixtures/it_assignment.txt new file mode 100644 index 0000000000..523b0ffe1e --- /dev/null +++ b/test/prism/fixtures/it_assignment.txt @@ -0,0 +1 @@ +42.tap { it = it; p it } diff --git a/test/prism/fixtures/it_read_and_assignment.txt b/test/prism/fixtures/it_read_and_assignment.txt new file mode 100644 index 0000000000..2cceeb2a54 --- /dev/null +++ b/test/prism/fixtures/it_read_and_assignment.txt @@ -0,0 +1 @@ +42.tap { p it; it = it; p it }