Skip to content

Commit b35e37b

Browse files
authored
Merge pull request #3604 from S-H-GAMELINKS/fix/bug-21139
Make `it = it` assign `nil` to match parse.y behavior [Bug #21139]
2 parents 28cf683 + fb136c6 commit b35e37b

File tree

5 files changed

+142
-0
lines changed

5 files changed

+142
-0
lines changed

snapshots/it_assignment.txt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
@ ProgramNode (location: (1,0)-(1,24))
2+
├── flags: ∅
3+
├── locals: []
4+
└── statements:
5+
@ StatementsNode (location: (1,0)-(1,24))
6+
├── flags: ∅
7+
└── body: (length: 1)
8+
└── @ CallNode (location: (1,0)-(1,24))
9+
├── flags: newline
10+
├── receiver:
11+
│ @ IntegerNode (location: (1,0)-(1,2))
12+
│ ├── flags: static_literal, decimal
13+
│ └── value: 42
14+
├── call_operator_loc: (1,2)-(1,3) = "."
15+
├── name: :tap
16+
├── message_loc: (1,3)-(1,6) = "tap"
17+
├── opening_loc: ∅
18+
├── arguments: ∅
19+
├── closing_loc: ∅
20+
└── block:
21+
@ BlockNode (location: (1,7)-(1,24))
22+
├── flags: ∅
23+
├── locals: [:it]
24+
├── parameters: ∅
25+
├── body:
26+
│ @ StatementsNode (location: (1,9)-(1,22))
27+
│ ├── flags: ∅
28+
│ └── body: (length: 2)
29+
│ ├── @ LocalVariableWriteNode (location: (1,9)-(1,16))
30+
│ │ ├── flags: newline
31+
│ │ ├── name: :it
32+
│ │ ├── depth: 0
33+
│ │ ├── name_loc: (1,9)-(1,11) = "it"
34+
│ │ ├── value:
35+
│ │ │ @ LocalVariableReadNode (location: (1,14)-(1,16))
36+
│ │ │ ├── flags: ∅
37+
│ │ │ ├── name: :it
38+
│ │ │ └── depth: 0
39+
│ │ └── operator_loc: (1,12)-(1,13) = "="
40+
│ └── @ CallNode (location: (1,18)-(1,22))
41+
│ ├── flags: newline, ignore_visibility
42+
│ ├── receiver: ∅
43+
│ ├── call_operator_loc: ∅
44+
│ ├── name: :p
45+
│ ├── message_loc: (1,18)-(1,19) = "p"
46+
│ ├── opening_loc: ∅
47+
│ ├── arguments:
48+
│ │ @ ArgumentsNode (location: (1,20)-(1,22))
49+
│ │ ├── flags: ∅
50+
│ │ └── arguments: (length: 1)
51+
│ │ └── @ LocalVariableReadNode (location: (1,20)-(1,22))
52+
│ │ ├── flags: ∅
53+
│ │ ├── name: :it
54+
│ │ └── depth: 0
55+
│ ├── closing_loc: ∅
56+
│ └── block: ∅
57+
├── opening_loc: (1,7)-(1,8) = "{"
58+
└── closing_loc: (1,23)-(1,24) = "}"
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
@ ProgramNode (location: (1,0)-(1,30))
2+
├── flags: ∅
3+
├── locals: []
4+
└── statements:
5+
@ StatementsNode (location: (1,0)-(1,30))
6+
├── flags: ∅
7+
└── body: (length: 1)
8+
└── @ CallNode (location: (1,0)-(1,30))
9+
├── flags: newline
10+
├── receiver:
11+
│ @ IntegerNode (location: (1,0)-(1,2))
12+
│ ├── flags: static_literal, decimal
13+
│ └── value: 42
14+
├── call_operator_loc: (1,2)-(1,3) = "."
15+
├── name: :tap
16+
├── message_loc: (1,3)-(1,6) = "tap"
17+
├── opening_loc: ∅
18+
├── arguments: ∅
19+
├── closing_loc: ∅
20+
└── block:
21+
@ BlockNode (location: (1,7)-(1,30))
22+
├── flags: ∅
23+
├── locals: [:it]
24+
├── parameters:
25+
│ @ ItParametersNode (location: (1,7)-(1,30))
26+
│ └── flags: ∅
27+
├── body:
28+
│ @ StatementsNode (location: (1,9)-(1,28))
29+
│ ├── flags: ∅
30+
│ └── body: (length: 3)
31+
│ ├── @ CallNode (location: (1,9)-(1,13))
32+
│ │ ├── flags: newline, ignore_visibility
33+
│ │ ├── receiver: ∅
34+
│ │ ├── call_operator_loc: ∅
35+
│ │ ├── name: :p
36+
│ │ ├── message_loc: (1,9)-(1,10) = "p"
37+
│ │ ├── opening_loc: ∅
38+
│ │ ├── arguments:
39+
│ │ │ @ ArgumentsNode (location: (1,11)-(1,13))
40+
│ │ │ ├── flags: ∅
41+
│ │ │ └── arguments: (length: 1)
42+
│ │ │ └── @ ItLocalVariableReadNode (location: (1,11)-(1,13))
43+
│ │ │ └── flags: ∅
44+
│ │ ├── closing_loc: ∅
45+
│ │ └── block: ∅
46+
│ ├── @ LocalVariableWriteNode (location: (1,15)-(1,22))
47+
│ │ ├── flags: newline
48+
│ │ ├── name: :it
49+
│ │ ├── depth: 0
50+
│ │ ├── name_loc: (1,15)-(1,17) = "it"
51+
│ │ ├── value:
52+
│ │ │ @ LocalVariableReadNode (location: (1,20)-(1,22))
53+
│ │ │ ├── flags: ∅
54+
│ │ │ ├── name: :it
55+
│ │ │ └── depth: 0
56+
│ │ └── operator_loc: (1,18)-(1,19) = "="
57+
│ └── @ CallNode (location: (1,24)-(1,28))
58+
│ ├── flags: newline, ignore_visibility
59+
│ ├── receiver: ∅
60+
│ ├── call_operator_loc: ∅
61+
│ ├── name: :p
62+
│ ├── message_loc: (1,24)-(1,25) = "p"
63+
│ ├── opening_loc: ∅
64+
│ ├── arguments:
65+
│ │ @ ArgumentsNode (location: (1,26)-(1,28))
66+
│ │ ├── flags: ∅
67+
│ │ └── arguments: (length: 1)
68+
│ │ └── @ LocalVariableReadNode (location: (1,26)-(1,28))
69+
│ │ ├── flags: ∅
70+
│ │ ├── name: :it
71+
│ │ └── depth: 0
72+
│ ├── closing_loc: ∅
73+
│ └── block: ∅
74+
├── opening_loc: (1,7)-(1,8) = "{"
75+
└── closing_loc: (1,29)-(1,30) = "}"

src/prism.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21183,6 +21183,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
2118321183
}
2118421184
PRISM_FALLTHROUGH
2118521185
case PM_CASE_WRITABLE: {
21186+
// When we have `it = value`, we need to add `it` as a local
21187+
// variable before parsing the value, in case the value
21188+
// references the variable.
21189+
if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) {
21190+
pm_parser_local_add_location(parser, node->location.start, node->location.end, 0);
21191+
}
21192+
2118621193
parser_lex(parser);
2118721194
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));
2118821195

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
42.tap { it = it; p it }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
42.tap { p it; it = it; p it }

0 commit comments

Comments
 (0)