Repository: ruby/yarp
Pull request #1286 (2023-08-19 00:42:12)

Change AndWriteNode, OrWriteNode, OperatorWriteNode to contain write nodes
It is going to make it more difficult to find all locations where a variable is written to if they're just read nodes. To keep things consistent we should make them write nodes.


Patch:
diff --git a/src/yarp.c b/src/yarp.c
index 1871d825..e3d82ab9 100644
--- a/src/yarp.c
+++ b/src/yarp.c
@@ -12112,6 +12112,10 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
                 case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
                 case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
                     parser_lex(parser);
+
+                    yp_token_t operator = not_provided(parser);
+                    node = parse_target(parser, node, &operator, NULL);
+
                     yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
                     return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
                 }
@@ -12130,11 +12134,12 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
                         }
 
                         parser_lex(parser);
-                        yp_node_t *target = (yp_node_t *) yp_local_variable_read_node_create(parser, &(yp_token_t) { .type = YP_TOKEN_IDENTIFIER, .start = message_loc.start, .end = message_loc.end }, 0);
-                        yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
 
-                        yp_node_destroy(parser, node);
-                        return (yp_node_t *) yp_and_write_node_create(parser, target, &token, value);
+                        yp_token_t operator = not_provided(parser);
+                        node = parse_target(parser, node, &operator, NULL);
+
+                        yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
+                        return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
                     }
 
                     parser_lex(parser);
@@ -12174,6 +12179,9 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
                 case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
                     parser_lex(parser);
 
+                    yp_token_t operator = not_provided(parser);
+                    node = parse_target(parser, node, &operator, NULL);
+
                     yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
                     return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
                 }
@@ -12192,11 +12200,12 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
                         }
 
                         parser_lex(parser);
-                        yp_node_t *target = (yp_node_t *) yp_local_variable_read_node_create(parser, &(yp_token_t) { .type = YP_TOKEN_IDENTIFIER, .start = message_loc.start, .end = message_loc.end }, 0);
-                        yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
 
-                        yp_node_destroy(parser, node);
-                        return (yp_node_t *) yp_or_write_node_create(parser, target, &token, value);
+                        yp_token_t operator = not_provided(parser);
+                        node = parse_target(parser, node, &operator, NULL);
+
+                        yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
+                        return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
                     }
 
                     parser_lex(parser);
@@ -12246,6 +12255,9 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
                 case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
                     parser_lex(parser);
 
+                    yp_token_t operator = not_provided(parser);
+                    node = parse_target(parser, node, &operator, NULL);
+
                     yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator");
                     return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
                 }
@@ -12264,11 +12276,12 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
                         }
 
                         parser_lex(parser);
-                        yp_node_t *target = (yp_node_t *) yp_local_variable_read_node_create(parser, &(yp_token_t) { .type = YP_TOKEN_IDENTIFIER, .start = message_loc.start, .end = message_loc.end }, 0);
-                        yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
 
-                        yp_node_destroy(parser, node);
-                        return (yp_node_t *) yp_operator_write_node_create(parser, target, &token, value);
+                        yp_token_t operator = not_provided(parser);
+                        node = parse_target(parser, node, &operator, NULL);
+
+                        yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
+                        return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
                     }
 
                     yp_token_t operator = not_provided(parser);


Test patch:
diff --git a/test/snapshots/blocks.txt b/test/snapshots/blocks.txt
index 214f5e54..089b63b8 100644
--- a/test/snapshots/blocks.txt
+++ b/test/snapshots/blocks.txt
@@ -89,7 +89,7 @@ ProgramNode(0...402)(
          ),
          StatementsNode(63...72)(
            [OperatorWriteNode(63...72)(
-              LocalVariableReadNode(63...67)(:memo, 0),
+              LocalVariableWriteNode(63...67)(:memo, 0, nil, (63...67), nil),
               (68...70),
               :+,
               LocalVariableReadNode(71...72)(:x, 0)
diff --git a/test/snapshots/boolean_operators.txt b/test/snapshots/boolean_operators.txt
index 39a3b6ef..c6cfc311 100644
--- a/test/snapshots/boolean_operators.txt
+++ b/test/snapshots/boolean_operators.txt
@@ -2,18 +2,18 @@ ProgramNode(0...24)(
   [:a],
   StatementsNode(0...24)(
     [AndWriteNode(0...7)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"),
        (2...5)
      ),
      OperatorWriteNode(9...15)(
-       LocalVariableReadNode(9...10)(:a, 0),
+       LocalVariableWriteNode(9...10)(:a, 0, nil, (9...10), nil),
        (11...13),
        :+,
        CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "b")
      ),
      OrWriteNode(17...24)(
-       LocalVariableReadNode(17...18)(:a, 0),
+       LocalVariableWriteNode(17...18)(:a, 0, nil, (17...18), nil),
        CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 2, "b"),
        (19...22)
      )]
diff --git a/test/snapshots/defined.txt b/test/snapshots/defined.txt
index 3d938b69..6c2cad65 100644
--- a/test/snapshots/defined.txt
+++ b/test/snapshots/defined.txt
@@ -9,7 +9,7 @@ ProgramNode(0...78)(
      DefinedNode(27...43)(
        (35...36),
        OperatorWriteNode(36...42)(
-         LocalVariableReadNode(36...37)(:x, 0),
+         LocalVariableWriteNode(36...37)(:x, 0, nil, (36...37), nil),
          (38...40),
          :%,
          IntegerNode(41...42)()
diff --git a/test/snapshots/seattlerb/bug_op_asgn_rescue.txt b/test/snapshots/seattlerb/bug_op_asgn_rescue.txt
index ca841c4e..c672ef6b 100644
--- a/test/snapshots/seattlerb/bug_op_asgn_rescue.txt
+++ b/test/snapshots/seattlerb/bug_op_asgn_rescue.txt
@@ -2,7 +2,7 @@ ProgramNode(0...18)(
   [:a],
   StatementsNode(0...18)(
     [OrWriteNode(0...18)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        RescueModifierNode(6...18)(
          CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"),
          (8...14),
diff --git a/test/snapshots/seattlerb/const_2_op_asgn_or2.txt b/test/snapshots/seattlerb/const_2_op_asgn_or2.txt
index 369adfb8..7405ad8e 100644
--- a/test/snapshots/seattlerb/const_2_op_asgn_or2.txt
+++ b/test/snapshots/seattlerb/const_2_op_asgn_or2.txt
@@ -2,10 +2,14 @@ ProgramNode(0...12)(
   [],
   StatementsNode(0...12)(
     [OrWriteNode(0...12)(
-       ConstantPathNode(0...6)(
-         ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
-         ConstantReadNode(5...6)(),
-         (3...5)
+       ConstantPathWriteNode(0...6)(
+         ConstantPathNode(0...6)(
+           ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+           ConstantReadNode(5...6)(),
+           (3...5)
+         ),
+         nil,
+         nil
        ),
        IntegerNode(11...12)(),
        (7...10)
diff --git a/test/snapshots/seattlerb/const_3_op_asgn_or.txt b/test/snapshots/seattlerb/const_3_op_asgn_or.txt
index 60b59b6f..838287c5 100644
--- a/test/snapshots/seattlerb/const_3_op_asgn_or.txt
+++ b/test/snapshots/seattlerb/const_3_op_asgn_or.txt
@@ -2,7 +2,11 @@ ProgramNode(0...9)(
   [],
   StatementsNode(0...9)(
     [OrWriteNode(0...9)(
-       ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+       ConstantPathWriteNode(0...3)(
+         ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+         nil,
+         nil
+       ),
        IntegerNode(8...9)(),
        (4...7)
      )]
diff --git a/test/snapshots/seattlerb/const_op_asgn_and1.txt b/test/snapshots/seattlerb/const_op_asgn_and1.txt
index e2ba0e9a..2fdcd972 100644
--- a/test/snapshots/seattlerb/const_op_asgn_and1.txt
+++ b/test/snapshots/seattlerb/const_op_asgn_and1.txt
@@ -2,7 +2,11 @@ ProgramNode(0...8)(
   [],
   StatementsNode(0...8)(
     [OperatorWriteNode(0...8)(
-       ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+       ConstantPathWriteNode(0...3)(
+         ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+         nil,
+         nil
+       ),
        (4...6),
        :&,
        IntegerNode(7...8)()
diff --git a/test/snapshots/seattlerb/const_op_asgn_and2.txt b/test/snapshots/seattlerb/const_op_asgn_and2.txt
index 6c9c8157..275aa823 100644
--- a/test/snapshots/seattlerb/const_op_asgn_and2.txt
+++ b/test/snapshots/seattlerb/const_op_asgn_and2.txt
@@ -2,7 +2,11 @@ ProgramNode(0...9)(
   [],
   StatementsNode(0...9)(
     [AndWriteNode(0...9)(
-       ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+       ConstantPathWriteNode(0...3)(
+         ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+         nil,
+         nil
+       ),
        IntegerNode(8...9)(),
        (4...7)
      )]
diff --git a/test/snapshots/seattlerb/const_op_asgn_or.txt b/test/snapshots/seattlerb/const_op_asgn_or.txt
index 8a42b824..c14175c4 100644
--- a/test/snapshots/seattlerb/const_op_asgn_or.txt
+++ b/test/snapshots/seattlerb/const_op_asgn_or.txt
@@ -2,10 +2,14 @@ ProgramNode(0...10)(
   [],
   StatementsNode(0...10)(
     [OrWriteNode(0...10)(
-       ConstantPathNode(0...4)(
-         ConstantReadNode(0...1)(),
-         ConstantReadNode(3...4)(),
-         (1...3)
+       ConstantPathWriteNode(0...4)(
+         ConstantPathNode(0...4)(
+           ConstantReadNode(0...1)(),
+           ConstantReadNode(3...4)(),
+           (1...3)
+         ),
+         nil,
+         nil
        ),
        IntegerNode(9...10)(),
        (5...8)
diff --git a/test/snapshots/seattlerb/messy_op_asgn_lineno.txt b/test/snapshots/seattlerb/messy_op_asgn_lineno.txt
index a27ed4b8..8c678e89 100644
--- a/test/snapshots/seattlerb/messy_op_asgn_lineno.txt
+++ b/test/snapshots/seattlerb/messy_op_asgn_lineno.txt
@@ -10,10 +10,14 @@ ProgramNode(0...15)(
          [ParenthesesNode(2...15)(
             StatementsNode(3...14)(
               [OperatorWriteNode(3...14)(
-                 ConstantPathNode(3...7)(
-                   ConstantReadNode(3...4)(),
-                   ConstantReadNode(6...7)(),
-                   (4...6)
+                 ConstantPathWriteNode(3...7)(
+                   ConstantPathNode(3...7)(
+                     ConstantReadNode(3...4)(),
+                     ConstantReadNode(6...7)(),
+                     (4...6)
+                   ),
+                   nil,
+                   nil
                  ),
                  (8...10),
                  :*,
diff --git a/test/snapshots/seattlerb/op_asgn_command_call.txt b/test/snapshots/seattlerb/op_asgn_command_call.txt
index 6d7177dc..deb7e170 100644
--- a/test/snapshots/seattlerb/op_asgn_command_call.txt
+++ b/test/snapshots/seattlerb/op_asgn_command_call.txt
@@ -2,7 +2,7 @@ ProgramNode(0...11)(
   [:a],
   StatementsNode(0...11)(
     [OrWriteNode(0...11)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        CallNode(6...11)(
          CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"),
          (7...8),
diff --git a/test/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt b/test/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt
index a69dc2e6..d071a454 100644
--- a/test/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt
+++ b/test/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt
@@ -2,10 +2,14 @@ ProgramNode(0...11)(
   [],
   StatementsNode(0...11)(
     [OperatorWriteNode(0...11)(
-       ConstantPathNode(0...4)(
-         ConstantReadNode(0...1)(),
-         ConstantReadNode(3...4)(),
-         (1...3)
+       ConstantPathWriteNode(0...4)(
+         ConstantPathNode(0...4)(
+           ConstantReadNode(0...1)(),
+           ConstantReadNode(3...4)(),
+           (1...3)
+         ),
+         nil,
+         nil
        ),
        (5...7),
        :*,
diff --git a/test/snapshots/seattlerb/parse_line_defn_complex.txt b/test/snapshots/seattlerb/parse_line_defn_complex.txt
index 4da4f25e..5d4820be 100644
--- a/test/snapshots/seattlerb/parse_line_defn_complex.txt
+++ b/test/snapshots/seattlerb/parse_line_defn_complex.txt
@@ -26,7 +26,7 @@ ProgramNode(0...40)(
             "p"
           ),
           OperatorWriteNode(18...24)(
-            LocalVariableReadNode(18...19)(:y, 0),
+            LocalVariableWriteNode(18...19)(:y, 0, nil, (18...19), nil),
             (20...22),
             :*,
             IntegerNode(23...24)()
diff --git a/test/snapshots/seattlerb/parse_line_op_asgn.txt b/test/snapshots/seattlerb/parse_line_op_asgn.txt
index 8763aab9..d8bd9891 100644
--- a/test/snapshots/seattlerb/parse_line_op_asgn.txt
+++ b/test/snapshots/seattlerb/parse_line_op_asgn.txt
@@ -2,7 +2,7 @@ ProgramNode(6...34)(
   [:foo],
   StatementsNode(6...34)(
     [OperatorWriteNode(6...24)(
-       LocalVariableReadNode(6...9)(:foo, 0),
+       LocalVariableWriteNode(6...9)(:foo, 0, nil, (6...9), nil),
        (10...12),
        :+,
        CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "bar")
diff --git a/test/snapshots/unparser/corpus/literal/assignment.txt b/test/snapshots/unparser/corpus/literal/assignment.txt
index 63b60ba9..ffaedf4f 100644
--- a/test/snapshots/unparser/corpus/literal/assignment.txt
+++ b/test/snapshots/unparser/corpus/literal/assignment.txt
@@ -611,7 +611,7 @@ ProgramNode(0...704)(
        (543...546)
      ),
      OrWriteNode(551...561)(
-       InstanceVariableReadNode(551...553)(),
+       InstanceVariableWriteNode(551...553)((551...553), nil, nil),
        StringNode(558...561)((558...560), (560...560), (560...561), ""),
        (554...557)
      ),
@@ -704,7 +704,7 @@ ProgramNode(0...704)(
        (665...668)
      ),
      OrWriteNode(687...704)(
-       InstanceVariableReadNode(687...689)(),
+       InstanceVariableWriteNode(687...689)((687...689), nil, nil),
        InterpolatedStringNode(694...704)(
          (694...704),
          [StringNode(705...707)(nil, (705...707), nil, "  "),
diff --git a/test/snapshots/unparser/corpus/literal/opasgn.txt b/test/snapshots/unparser/corpus/literal/opasgn.txt
index 21933e30..98045976 100644
--- a/test/snapshots/unparser/corpus/literal/opasgn.txt
+++ b/test/snapshots/unparser/corpus/literal/opasgn.txt
@@ -2,42 +2,42 @@ ProgramNode(0...233)(
   [:a, :h],
   StatementsNode(0...233)(
     [OperatorWriteNode(0...6)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        (2...4),
        :+,
        IntegerNode(5...6)()
      ),
      OperatorWriteNode(7...13)(
-       LocalVariableReadNode(7...8)(:a, 0),
+       LocalVariableWriteNode(7...8)(:a, 0, nil, (7...8), nil),
        (9...11),
        :-,
        IntegerNode(12...13)()
      ),
      OperatorWriteNode(14...21)(
-       LocalVariableReadNode(14...15)(:a, 0),
+       LocalVariableWriteNode(14...15)(:a, 0, nil, (14...15), nil),
        (16...19),
        :**,
        IntegerNode(20...21)()
      ),
      OperatorWriteNode(22...28)(
-       LocalVariableReadNode(22...23)(:a, 0),
+       LocalVariableWriteNode(22...23)(:a, 0, nil, (22...23), nil),
        (24...26),
        :*,
        IntegerNode(27...28)()
      ),
      OperatorWriteNode(29...35)(
-       LocalVariableReadNode(29...30)(:a, 0),
+       LocalVariableWriteNode(29...30)(:a, 0, nil, (29...30), nil),
        (31...33),
        :/,
        IntegerNode(34...35)()
      ),
      AndWriteNode(36...43)(
-       LocalVariableReadNode(36...37)(:a, 0),
+       LocalVariableWriteNode(36...37)(:a, 0, nil, (36...37), nil),
        CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 2, "b"),
        (38...41)
      ),
      OrWriteNode(44...51)(
-       LocalVariableReadNode(44...45)(:a, 0),
+       LocalVariableWriteNode(44...45)(:a, 0, nil, (44...45), nil),
        IntegerNode(50...51)(),
        (46...49)
      ),
@@ -45,7 +45,7 @@ ProgramNode(0...233)(
        ParenthesesNode(52...61)(
          StatementsNode(53...60)(
            [OrWriteNode(53...60)(
-              LocalVariableReadNode(53...54)(:a, 0),
+              LocalVariableWriteNode(53...54)(:a, 0, nil, (53...54), nil),
               IntegerNode(59...60)(),
               (55...58)
             )]
@@ -66,7 +66,7 @@ ProgramNode(0...233)(
        ParenthesesNode(66...76)(
          StatementsNode(67...75)(
            [OrWriteNode(67...75)(
-              LocalVariableReadNode(67...68)(:h, 0),
+              LocalVariableWriteNode(67...68)(:h, 0, nil, (67...68), nil),
               HashNode(73...75)((73...74), [], (74...75)),
               (69...72)
             )]
diff --git a/test/snapshots/unparser/corpus/literal/send.txt b/test/snapshots/unparser/corpus/literal/send.txt
index a3f5e988..2c2ce8cd 100644
--- a/test/snapshots/unparser/corpus/literal/send.txt
+++ b/test/snapshots/unparser/corpus/literal/send.txt
@@ -7,7 +7,7 @@ ProgramNode(0...999)(
        ConstantReadNode(7...8)(),
        StatementsNode(11...31)(
          [OrWriteNode(11...31)(
-            LocalVariableReadNode(11...14)(:foo, 0),
+            LocalVariableWriteNode(11...14)(:foo, 0, nil, (11...14), nil),
             ParenthesesNode(19...31)(
               StatementsNode(21...30)(
                 [MultiWriteNode(21...30)(
diff --git a/test/snapshots/whitequark/const_op_asgn.txt b/test/snapshots/whitequark/const_op_asgn.txt
index a9da130f..e212170a 100644
--- a/test/snapshots/whitequark/const_op_asgn.txt
+++ b/test/snapshots/whitequark/const_op_asgn.txt
@@ -2,22 +2,30 @@ ProgramNode(0...77)(
   [],
   StatementsNode(0...77)(
     [OperatorWriteNode(0...8)(
-       ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+       ConstantPathWriteNode(0...3)(
+         ConstantPathNode(0...3)(nil, ConstantReadNode(2...3)(), (0...2)),
+         nil,
+         nil
+       ),
        (4...6),
        :+,
        IntegerNode(7...8)()
      ),
      OperatorWriteNode(10...16)(
-       ConstantReadNode(10...11)(),
+       ConstantWriteNode(10...11)((10...11), nil, nil),
        (12...14),
        :+,
        IntegerNode(15...16)()
      ),
      OperatorWriteNode(18...27)(
-       ConstantPathNode(18...22)(
-         ConstantReadNode(18...19)(),
-         ConstantReadNode(21...22)(),
-         (19...21)
+       ConstantPathWriteNode(18...22)(
+         ConstantPathNode(18...22)(
+           ConstantReadNode(18...19)(),
+           ConstantReadNode(21...22)(),
+           (19...21)
+         ),
+         nil,
+         nil
        ),
        (23...25),
        :+,
@@ -29,10 +37,14 @@ ProgramNode(0...77)(
        nil,
        StatementsNode(36...45)(
          [OrWriteNode(36...45)(
-            ConstantPathNode(36...39)(
+            ConstantPathWriteNode(36...39)(
+              ConstantPathNode(36...39)(
+                nil,
+                ConstantReadNode(38...39)(),
+                (36...38)
+              ),
               nil,
-              ConstantReadNode(38...39)(),
-              (36...38)
+              nil
             ),
             IntegerNode(44...45)(),
             (40...43)
@@ -52,10 +64,14 @@ ProgramNode(0...77)(
        nil,
        StatementsNode(59...72)(
          [OrWriteNode(59...72)(
-            ConstantPathNode(59...66)(
-              SelfNode(59...63)(),
-              ConstantReadNode(65...66)(),
-              (63...65)
+            ConstantPathWriteNode(59...66)(
+              ConstantPathNode(59...66)(
+                SelfNode(59...63)(),
+                ConstantReadNode(65...66)(),
+                (63...65)
+              ),
+              nil,
+              nil
             ),
             IntegerNode(71...72)(),
             (67...70)
diff --git a/test/snapshots/whitequark/op_asgn_cmd.txt b/test/snapshots/whitequark/op_asgn_cmd.txt
index 116d641b..ccc8730d 100644
--- a/test/snapshots/whitequark/op_asgn_cmd.txt
+++ b/test/snapshots/whitequark/op_asgn_cmd.txt
@@ -78,10 +78,24 @@ ProgramNode(0...64)(
        :+
      ),
      OperatorWriteNode(32...47)(
-       ConstantPathNode(32...38)(
-         CallNode(32...35)(nil, nil, (32...35), nil, nil, nil, nil, 2, "foo"),
-         ConstantReadNode(37...38)(),
-         (35...37)
+       ConstantPathWriteNode(32...38)(
+         ConstantPathNode(32...38)(
+           CallNode(32...35)(
+             nil,
+             nil,
+             (32...35),
+             nil,
+             nil,
+             nil,
+             nil,
+             2,
+             "foo"
+           ),
+           ConstantReadNode(37...38)(),
+           (35...37)
+         ),
+         nil,
+         nil
        ),
        (39...41),
        :+,
diff --git a/test/snapshots/whitequark/rescue_mod_op_assign.txt b/test/snapshots/whitequark/rescue_mod_op_assign.txt
index 14125cec..8ae81caa 100644
--- a/test/snapshots/whitequark/rescue_mod_op_assign.txt
+++ b/test/snapshots/whitequark/rescue_mod_op_assign.txt
@@ -2,7 +2,7 @@ ProgramNode(0...22)(
   [:foo],
   StatementsNode(0...22)(
     [OperatorWriteNode(0...22)(
-       LocalVariableReadNode(0...3)(:foo, 0),
+       LocalVariableWriteNode(0...3)(:foo, 0, nil, (0...3), nil),
        (4...6),
        :+,
        RescueModifierNode(7...22)(
diff --git a/test/snapshots/whitequark/ruby_bug_12402.txt b/test/snapshots/whitequark/ruby_bug_12402.txt
index 9573dc5f..4ca03bab 100644
--- a/test/snapshots/whitequark/ruby_bug_12402.txt
+++ b/test/snapshots/whitequark/ruby_bug_12402.txt
@@ -2,7 +2,7 @@ ProgramNode(0...437)(
   [:foo],
   StatementsNode(0...437)(
     [OperatorWriteNode(0...27)(
-       LocalVariableReadNode(0...3)(:foo, 0),
+       LocalVariableWriteNode(0...3)(:foo, 0, nil, (0...3), nil),
        (4...6),
        :+,
        CallNode(7...27)(
@@ -34,7 +34,7 @@ ProgramNode(0...437)(
        )
      ),
      OperatorWriteNode(29...57)(
-       LocalVariableReadNode(29...32)(:foo, 0),
+       LocalVariableWriteNode(29...32)(:foo, 0, nil, (29...32), nil),
        (33...35),
        :+,
        RescueModifierNode(36...57)(
@@ -300,10 +300,14 @@ ProgramNode(0...437)(
        :+
      ),
      OrWriteNode(242...273)(
-       ConstantPathNode(242...248)(
-         LocalVariableReadNode(242...245)(:foo, 0),
-         ConstantReadNode(247...248)(),
-         (245...247)
+       ConstantPathWriteNode(242...248)(
+         ConstantPathNode(242...248)(
+           LocalVariableReadNode(242...245)(:foo, 0),
+           ConstantReadNode(247...248)(),
+           (245...247)
+         ),
+         nil,
+         nil
        ),
        CallNode(253...273)(
          nil,
@@ -335,10 +339,14 @@ ProgramNode(0...437)(
        (249...252)
      ),
      OrWriteNode(275...307)(
-       ConstantPathNode(275...281)(
-         LocalVariableReadNode(275...278)(:foo, 0),
-         ConstantReadNode(280...281)(),
-         (278...280)
+       ConstantPathWriteNode(275...281)(
+         ConstantPathNode(275...281)(
+           LocalVariableReadNode(275...278)(:foo, 0),
+           ConstantReadNode(280...281)(),
+           (278...280)
+         ),
+         nil,
+         nil
        ),
        RescueModifierNode(286...307)(
          CallNode(286...296)(
diff --git a/test/snapshots/whitequark/ruby_bug_12669.txt b/test/snapshots/whitequark/ruby_bug_12669.txt
index c7932a40..6eb9e9a0 100644
--- a/test/snapshots/whitequark/ruby_bug_12669.txt
+++ b/test/snapshots/whitequark/ruby_bug_12669.txt
@@ -2,11 +2,11 @@ ProgramNode(0...74)(
   [:a, :b],
   StatementsNode(0...74)(
     [OperatorWriteNode(0...18)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        (2...4),
        :+,
        OperatorWriteNode(5...18)(
-         LocalVariableReadNode(5...6)(:b, 0),
+         LocalVariableWriteNode(5...6)(:b, 0, nil, (5...6), nil),
          (7...9),
          :+,
          CallNode(10...18)(
@@ -25,7 +25,7 @@ ProgramNode(0...74)(
        )
      ),
      OperatorWriteNode(20...37)(
-       LocalVariableReadNode(20...21)(:a, 0),
+       LocalVariableWriteNode(20...21)(:a, 0, nil, (20...21), nil),
        (22...24),
        :+,
        LocalVariableWriteNode(25...37)(
@@ -52,7 +52,7 @@ ProgramNode(0...74)(
        :a,
        0,
        OperatorWriteNode(43...56)(
-         LocalVariableReadNode(43...44)(:b, 0),
+         LocalVariableWriteNode(43...44)(:b, 0, nil, (43...44), nil),
          (45...47),
          :+,
          CallNode(48...56)(
diff --git a/test/snapshots/whitequark/var_and_asgn.txt b/test/snapshots/whitequark/var_and_asgn.txt
index 8d476a81..a082413a 100644
--- a/test/snapshots/whitequark/var_and_asgn.txt
+++ b/test/snapshots/whitequark/var_and_asgn.txt
@@ -2,7 +2,7 @@ ProgramNode(0...7)(
   [:a],
   StatementsNode(0...7)(
     [AndWriteNode(0...7)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        IntegerNode(6...7)(),
        (2...5)
      )]
diff --git a/test/snapshots/whitequark/var_op_asgn.txt b/test/snapshots/whitequark/var_op_asgn.txt
index 863605eb..08b72403 100644
--- a/test/snapshots/whitequark/var_op_asgn.txt
+++ b/test/snapshots/whitequark/var_op_asgn.txt
@@ -2,19 +2,19 @@ ProgramNode(0...53)(
   [:a],
   StatementsNode(0...53)(
     [OperatorWriteNode(0...11)(
-       ClassVariableReadNode(0...5)(),
+       ClassVariableWriteNode(0...5)((0...5), nil, nil),
        (6...8),
        :|,
        IntegerNode(9...11)()
      ),
      OperatorWriteNode(13...20)(
-       InstanceVariableReadNode(13...15)(),
+       InstanceVariableWriteNode(13...15)((13...15), nil, nil),
        (16...18),
        :|,
        IntegerNode(19...20)()
      ),
      OperatorWriteNode(22...28)(
-       LocalVariableReadNode(22...23)(:a, 0),
+       LocalVariableWriteNode(22...23)(:a, 0, nil, (22...23), nil),
        (24...26),
        :+,
        IntegerNode(27...28)()
@@ -25,7 +25,7 @@ ProgramNode(0...53)(
        nil,
        StatementsNode(37...48)(
          [OperatorWriteNode(37...48)(
-            ClassVariableReadNode(37...42)(),
+            ClassVariableWriteNode(37...42)((37...42), nil, nil),
             (43...45),
             :|,
             IntegerNode(46...48)()
diff --git a/test/snapshots/whitequark/var_op_asgn_cmd.txt b/test/snapshots/whitequark/var_op_asgn_cmd.txt
index 4d7ef7d4..f78329a1 100644
--- a/test/snapshots/whitequark/var_op_asgn_cmd.txt
+++ b/test/snapshots/whitequark/var_op_asgn_cmd.txt
@@ -2,7 +2,7 @@ ProgramNode(0...12)(
   [:foo],
   StatementsNode(0...12)(
     [OperatorWriteNode(0...12)(
-       LocalVariableReadNode(0...3)(:foo, 0),
+       LocalVariableWriteNode(0...3)(:foo, 0, nil, (0...3), nil),
        (4...6),
        :+,
        CallNode(7...12)(
diff --git a/test/snapshots/whitequark/var_or_asgn.txt b/test/snapshots/whitequark/var_or_asgn.txt
index cc029042..bb2f8c6b 100644
--- a/test/snapshots/whitequark/var_or_asgn.txt
+++ b/test/snapshots/whitequark/var_or_asgn.txt
@@ -2,7 +2,7 @@ ProgramNode(0...7)(
   [:a],
   StatementsNode(0...7)(
     [OrWriteNode(0...7)(
-       LocalVariableReadNode(0...1)(:a, 0),
+       LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil),
        IntegerNode(6...7)(),
        (2...5)
      )]