yarp 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/src/yarp.c CHANGED
@@ -450,8 +450,8 @@ yp_flip_flop(yp_node_t *node) {
450
450
  case YP_NODE_PARENTHESES_NODE: {
451
451
  yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node;
452
452
 
453
- if ((cast->statements != NULL) && YP_NODE_TYPE_P(cast->statements, YP_NODE_STATEMENTS_NODE)) {
454
- yp_statements_node_t *statements = (yp_statements_node_t *) cast->statements;
453
+ if ((cast->body != NULL) && YP_NODE_TYPE_P(cast->body, YP_NODE_STATEMENTS_NODE)) {
454
+ yp_statements_node_t *statements = (yp_statements_node_t *) cast->body;
455
455
  if (statements->body.size == 1) yp_flip_flop(statements->body.nodes[0]);
456
456
  }
457
457
 
@@ -459,8 +459,12 @@ yp_flip_flop(yp_node_t *node) {
459
459
  }
460
460
  case YP_NODE_RANGE_NODE: {
461
461
  yp_range_node_t *cast = (yp_range_node_t *) node;
462
- yp_flip_flop(cast->left);
463
- yp_flip_flop(cast->right);
462
+ if (cast->left) {
463
+ yp_flip_flop(cast->left);
464
+ }
465
+ if (cast->right) {
466
+ yp_flip_flop(cast->right);
467
+ }
464
468
 
465
469
  // Here we change the range node into a flip flop node. We can do
466
470
  // this since the nodes are exactly the same except for the type.
@@ -654,6 +658,27 @@ yp_and_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *opera
654
658
  return node;
655
659
  }
656
660
 
661
+ // Allocate and initialize a new AndWriteNode.
662
+ static yp_and_write_node_t *
663
+ yp_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
664
+ yp_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_and_write_node_t);
665
+
666
+ *node = (yp_and_write_node_t) {
667
+ {
668
+ .type = YP_NODE_AND_WRITE_NODE,
669
+ .location = {
670
+ .start = target->location.start,
671
+ .end = value->location.end
672
+ },
673
+ },
674
+ .target = target,
675
+ .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
676
+ .value = value
677
+ };
678
+
679
+ return node;
680
+ }
681
+
657
682
  // Allocate an initialize a new arguments node.
658
683
  static yp_arguments_node_t *
659
684
  yp_arguments_node_create(yp_parser_t *parser) {
@@ -993,7 +1018,7 @@ yp_block_argument_node_create(yp_parser_t *parser, const yp_token_t *operator, y
993
1018
 
994
1019
  // Allocate and initialize a new BlockNode node.
995
1020
  static yp_block_node_t *
996
- yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *opening, yp_block_parameters_node_t *parameters, yp_node_t *statements, const yp_token_t *closing) {
1021
+ yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *opening, yp_block_parameters_node_t *parameters, yp_node_t *body, const yp_token_t *closing) {
997
1022
  yp_block_node_t *node = YP_ALLOC_NODE(parser, yp_block_node_t);
998
1023
 
999
1024
  *node = (yp_block_node_t) {
@@ -1003,7 +1028,7 @@ yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
1003
1028
  },
1004
1029
  .locals = *locals,
1005
1030
  .parameters = parameters,
1006
- .statements = statements,
1031
+ .body = body,
1007
1032
  .opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
1008
1033
  .closing_loc = YP_LOCATION_TOKEN_VALUE(closing)
1009
1034
  };
@@ -1461,7 +1486,7 @@ yp_case_node_end_keyword_loc_set(yp_case_node_t *node, const yp_token_t *end_key
1461
1486
 
1462
1487
  // Allocate a new ClassNode node.
1463
1488
  static yp_class_node_t *
1464
- yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *statements, const yp_token_t *end_keyword) {
1489
+ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *body, const yp_token_t *end_keyword) {
1465
1490
  yp_class_node_t *node = YP_ALLOC_NODE(parser, yp_class_node_t);
1466
1491
 
1467
1492
  *node = (yp_class_node_t) {
@@ -1474,81 +1499,13 @@ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
1474
1499
  .constant_path = constant_path,
1475
1500
  .inheritance_operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(inheritance_operator),
1476
1501
  .superclass = superclass,
1477
- .statements = statements,
1502
+ .body = body,
1478
1503
  .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
1479
1504
  };
1480
1505
 
1481
1506
  return node;
1482
1507
  }
1483
1508
 
1484
- // Allocate and initialize a new ClassVariableOperatorAndWriteNode node.
1485
- static yp_class_variable_operator_and_write_node_t *
1486
- yp_class_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1487
- assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE));
1488
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
1489
- yp_class_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_and_write_node_t);
1490
-
1491
- *node = (yp_class_variable_operator_and_write_node_t) {
1492
- {
1493
- .type = YP_NODE_CLASS_VARIABLE_OPERATOR_AND_WRITE_NODE,
1494
- .location = {
1495
- .start = target->location.start,
1496
- .end = value->location.end
1497
- }
1498
- },
1499
- .name_loc = target->location,
1500
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1501
- .value = value
1502
- };
1503
-
1504
- return node;
1505
- }
1506
-
1507
- // Allocate and initialize a new ClassVariableOperatorWriteNode node.
1508
- static yp_class_variable_operator_write_node_t *
1509
- yp_class_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1510
- yp_class_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_write_node_t);
1511
-
1512
- *node = (yp_class_variable_operator_write_node_t) {
1513
- {
1514
- .type = YP_NODE_CLASS_VARIABLE_OPERATOR_WRITE_NODE,
1515
- .location = {
1516
- .start = target->location.start,
1517
- .end = value->location.end
1518
- }
1519
- },
1520
- .name_loc = target->location,
1521
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1522
- .value = value,
1523
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
1524
- };
1525
-
1526
- return node;
1527
- }
1528
-
1529
- // Allocate and initialize a new ClassVariableOperatorOrWriteNode node.
1530
- static yp_class_variable_operator_or_write_node_t *
1531
- yp_class_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1532
- assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE));
1533
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
1534
- yp_class_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_or_write_node_t);
1535
-
1536
- *node = (yp_class_variable_operator_or_write_node_t) {
1537
- {
1538
- .type = YP_NODE_CLASS_VARIABLE_OPERATOR_OR_WRITE_NODE,
1539
- .location = {
1540
- .start = target->location.start,
1541
- .end = value->location.end
1542
- }
1543
- },
1544
- .name_loc = target->location,
1545
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1546
- .value = value
1547
- };
1548
-
1549
- return node;
1550
- }
1551
-
1552
1509
  // Allocate and initialize a new ClassVariableReadNode node.
1553
1510
  static yp_class_variable_read_node_t *
1554
1511
  yp_class_variable_read_node_create(yp_parser_t *parser, const yp_token_t *token) {
@@ -1579,72 +1536,6 @@ yp_class_variable_read_node_to_class_variable_write_node(yp_parser_t *parser, yp
1579
1536
  return node;
1580
1537
  }
1581
1538
 
1582
- // Allocate and initialize a new ConstantPathOperatorAndWriteNode node.
1583
- static yp_constant_path_operator_and_write_node_t *
1584
- yp_constant_path_operator_and_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1585
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
1586
- yp_constant_path_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_and_write_node_t);
1587
-
1588
- *node = (yp_constant_path_operator_and_write_node_t) {
1589
- {
1590
- .type = YP_NODE_CONSTANT_PATH_OPERATOR_AND_WRITE_NODE,
1591
- .location = {
1592
- .start = target->base.location.start,
1593
- .end = value->location.end
1594
- }
1595
- },
1596
- .target = target,
1597
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1598
- .value = value
1599
- };
1600
-
1601
- return node;
1602
- }
1603
-
1604
- // Allocate and initialize a new ConstantPathOperatorWriteNode node.
1605
- static yp_constant_path_operator_write_node_t *
1606
- yp_constant_path_operator_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1607
- yp_constant_path_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_write_node_t);
1608
-
1609
- *node = (yp_constant_path_operator_write_node_t) {
1610
- {
1611
- .type = YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE,
1612
- .location = {
1613
- .start = target->base.location.start,
1614
- .end = value->location.end
1615
- }
1616
- },
1617
- .target = target,
1618
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1619
- .value = value,
1620
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
1621
- };
1622
-
1623
- return node;
1624
- }
1625
-
1626
- // Allocate and initialize a new ConstantPathOperatorOrWriteNode node.
1627
- static yp_constant_path_operator_or_write_node_t *
1628
- yp_constant_path_operator_or_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1629
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
1630
- yp_constant_path_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_or_write_node_t);
1631
-
1632
- *node = (yp_constant_path_operator_or_write_node_t) {
1633
- {
1634
- .type = YP_NODE_CONSTANT_PATH_OPERATOR_OR_WRITE_NODE,
1635
- .location = {
1636
- .start = target->base.location.start,
1637
- .end = value->location.end
1638
- }
1639
- },
1640
- .target = target,
1641
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1642
- .value = value
1643
- };
1644
-
1645
- return node;
1646
- }
1647
-
1648
1539
  // Allocate and initialize a new ConstantPathNode node.
1649
1540
  static yp_constant_path_node_t *
1650
1541
  yp_constant_path_node_create(yp_parser_t *parser, yp_node_t *parent, const yp_token_t *delimiter, yp_node_t *child) {
@@ -1687,74 +1578,6 @@ yp_constant_path_write_node_create(yp_parser_t *parser, yp_constant_path_node_t
1687
1578
  return node;
1688
1579
  }
1689
1580
 
1690
- // Allocate and initialize a new ConstantOperatorAndWriteNode node.
1691
- static yp_constant_operator_and_write_node_t *
1692
- yp_constant_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1693
- assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE));
1694
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
1695
- yp_constant_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_and_write_node_t);
1696
-
1697
- *node = (yp_constant_operator_and_write_node_t) {
1698
- {
1699
- .type = YP_NODE_CONSTANT_OPERATOR_AND_WRITE_NODE,
1700
- .location = {
1701
- .start = target->location.start,
1702
- .end = value->location.end
1703
- }
1704
- },
1705
- .name_loc = target->location,
1706
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1707
- .value = value
1708
- };
1709
-
1710
- return node;
1711
- }
1712
-
1713
- // Allocate and initialize a new ConstantOperatorWriteNode node.
1714
- static yp_constant_operator_write_node_t *
1715
- yp_constant_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1716
- yp_constant_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_write_node_t);
1717
-
1718
- *node = (yp_constant_operator_write_node_t) {
1719
- {
1720
- .type = YP_NODE_CONSTANT_OPERATOR_WRITE_NODE,
1721
- .location = {
1722
- .start = target->location.start,
1723
- .end = value->location.end
1724
- }
1725
- },
1726
- .name_loc = target->location,
1727
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1728
- .value = value,
1729
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
1730
- };
1731
-
1732
- return node;
1733
- }
1734
-
1735
- // Allocate and initialize a new ConstantOperatorOrWriteNode node.
1736
- static yp_constant_operator_or_write_node_t *
1737
- yp_constant_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1738
- assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE));
1739
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
1740
- yp_constant_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_or_write_node_t);
1741
-
1742
- *node = (yp_constant_operator_or_write_node_t) {
1743
- {
1744
- .type = YP_NODE_CONSTANT_OPERATOR_OR_WRITE_NODE,
1745
- .location = {
1746
- .start = target->location.start,
1747
- .end = value->location.end
1748
- }
1749
- },
1750
- .name_loc = target->location,
1751
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1752
- .value = value
1753
- };
1754
-
1755
- return node;
1756
- }
1757
-
1758
1581
  // Allocate and initialize a new ConstantReadNode node.
1759
1582
  static yp_constant_read_node_t *
1760
1583
  yp_constant_read_node_create(yp_parser_t *parser, const yp_token_t *name) {
@@ -1793,7 +1616,7 @@ yp_def_node_create(
1793
1616
  const yp_token_t *name,
1794
1617
  yp_node_t *receiver,
1795
1618
  yp_parameters_node_t *parameters,
1796
- yp_node_t *statements,
1619
+ yp_node_t *body,
1797
1620
  yp_constant_id_list_t *locals,
1798
1621
  const yp_token_t *def_keyword,
1799
1622
  const yp_token_t *operator,
@@ -1806,7 +1629,7 @@ yp_def_node_create(
1806
1629
  const char *end;
1807
1630
 
1808
1631
  if (end_keyword->type == YP_TOKEN_NOT_PROVIDED) {
1809
- end = statements->location.end;
1632
+ end = body->location.end;
1810
1633
  } else {
1811
1634
  end = end_keyword->end;
1812
1635
  }
@@ -1819,7 +1642,7 @@ yp_def_node_create(
1819
1642
  .name_loc = YP_LOCATION_TOKEN_VALUE(name),
1820
1643
  .receiver = receiver,
1821
1644
  .parameters = parameters,
1822
- .statements = statements,
1645
+ .body = body,
1823
1646
  .locals = *locals,
1824
1647
  .def_keyword_loc = YP_LOCATION_TOKEN_VALUE(def_keyword),
1825
1648
  .operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
@@ -2189,74 +2012,6 @@ yp_hash_pattern_node_node_list_create(yp_parser_t *parser, yp_node_list_t *assoc
2189
2012
  return node;
2190
2013
  }
2191
2014
 
2192
- // Allocate and initialize a new GlobalVariableOperatorAndWriteNode node.
2193
- static yp_global_variable_operator_and_write_node_t *
2194
- yp_global_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2195
- assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE));
2196
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
2197
- yp_global_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_and_write_node_t);
2198
-
2199
- *node = (yp_global_variable_operator_and_write_node_t) {
2200
- {
2201
- .type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE,
2202
- .location = {
2203
- .start = target->location.start,
2204
- .end = value->location.end
2205
- }
2206
- },
2207
- .name_loc = target->location,
2208
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2209
- .value = value
2210
- };
2211
-
2212
- return node;
2213
- }
2214
-
2215
- // Allocate and initialize a new GlobalVariableOperatorWriteNode node.
2216
- static yp_global_variable_operator_write_node_t *
2217
- yp_global_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2218
- yp_global_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_write_node_t);
2219
-
2220
- *node = (yp_global_variable_operator_write_node_t) {
2221
- {
2222
- .type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE,
2223
- .location = {
2224
- .start = target->location.start,
2225
- .end = value->location.end
2226
- }
2227
- },
2228
- .name_loc = target->location,
2229
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2230
- .value = value,
2231
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
2232
- };
2233
-
2234
- return node;
2235
- }
2236
-
2237
- // Allocate and initialize a new GlobalVariableOperatorOrWriteNode node.
2238
- static yp_global_variable_operator_or_write_node_t *
2239
- yp_global_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2240
- assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE));
2241
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
2242
- yp_global_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_or_write_node_t);
2243
-
2244
- *node = (yp_global_variable_operator_or_write_node_t) {
2245
- {
2246
- .type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE,
2247
- .location = {
2248
- .start = target->location.start,
2249
- .end = value->location.end
2250
- }
2251
- },
2252
- .name_loc = target->location,
2253
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2254
- .value = value
2255
- };
2256
-
2257
- return node;
2258
- }
2259
-
2260
2015
  // Allocate a new GlobalVariableReadNode node.
2261
2016
  static yp_global_variable_read_node_t *
2262
2017
  yp_global_variable_read_node_create(yp_parser_t *parser, const yp_token_t *name) {
@@ -2547,74 +2302,6 @@ yp_in_node_create(yp_parser_t *parser, yp_node_t *pattern, yp_statements_node_t
2547
2302
  return node;
2548
2303
  }
2549
2304
 
2550
- // Allocate and initialize a new InstanceVariableOperatorAndWriteNode node.
2551
- static yp_instance_variable_operator_and_write_node_t *
2552
- yp_instance_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2553
- assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE));
2554
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
2555
- yp_instance_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_and_write_node_t);
2556
-
2557
- *node = (yp_instance_variable_operator_and_write_node_t) {
2558
- {
2559
- .type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE,
2560
- .location = {
2561
- .start = target->location.start,
2562
- .end = value->location.end
2563
- }
2564
- },
2565
- .name_loc = target->location,
2566
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2567
- .value = value
2568
- };
2569
-
2570
- return node;
2571
- }
2572
-
2573
- // Allocate and initialize a new InstanceVariableOperatorWriteNode node.
2574
- static yp_instance_variable_operator_write_node_t *
2575
- yp_instance_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2576
- yp_instance_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_write_node_t);
2577
-
2578
- *node = (yp_instance_variable_operator_write_node_t) {
2579
- {
2580
- .type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE,
2581
- .location = {
2582
- .start = target->location.start,
2583
- .end = value->location.end
2584
- }
2585
- },
2586
- .name_loc = target->location,
2587
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2588
- .value = value,
2589
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
2590
- };
2591
-
2592
- return node;
2593
- }
2594
-
2595
- // Allocate and initialize a new InstanceVariableOperatorOrWriteNode node.
2596
- static yp_instance_variable_operator_or_write_node_t *
2597
- yp_instance_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2598
- assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE));
2599
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
2600
- yp_instance_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_or_write_node_t);
2601
-
2602
- *node = (yp_instance_variable_operator_or_write_node_t) {
2603
- {
2604
- .type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE,
2605
- .location = {
2606
- .start = target->location.start,
2607
- .end = value->location.end
2608
- }
2609
- },
2610
- .name_loc = target->location,
2611
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2612
- .value = value
2613
- };
2614
-
2615
- return node;
2616
- }
2617
-
2618
2305
  // Allocate and initialize a new InstanceVariableReadNode node.
2619
2306
  static yp_instance_variable_read_node_t *
2620
2307
  yp_instance_variable_read_node_create(yp_parser_t *parser, const yp_token_t *token) {
@@ -2706,6 +2393,10 @@ yp_interpolated_string_node_create(yp_parser_t *parser, const yp_token_t *openin
2706
2393
  // Append a part to an InterpolatedStringNode node.
2707
2394
  static inline void
2708
2395
  yp_interpolated_string_node_append(yp_interpolated_string_node_t *node, yp_node_t *part) {
2396
+ if (node->parts.size == 0 && node->opening_loc.start == NULL) {
2397
+ node->base.location.start = part->location.start;
2398
+ }
2399
+
2709
2400
  yp_node_list_append(&node->parts, part);
2710
2401
  node->base.location.end = part->location.end;
2711
2402
  }
@@ -2862,7 +2553,7 @@ yp_lambda_node_create(
2862
2553
  yp_constant_id_list_t *locals,
2863
2554
  const yp_token_t *opening,
2864
2555
  yp_block_parameters_node_t *parameters,
2865
- yp_node_t *statements,
2556
+ yp_node_t *body,
2866
2557
  const yp_token_t *closing
2867
2558
  ) {
2868
2559
  yp_lambda_node_t *node = YP_ALLOC_NODE(parser, yp_lambda_node_t);
@@ -2878,78 +2569,7 @@ yp_lambda_node_create(
2878
2569
  .locals = *locals,
2879
2570
  .opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
2880
2571
  .parameters = parameters,
2881
- .statements = statements
2882
- };
2883
-
2884
- return node;
2885
- }
2886
-
2887
- // Allocate and initialize a new LocalVariableOperatorAndWriteNode node.
2888
- static yp_local_variable_operator_and_write_node_t *
2889
- yp_local_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
2890
- assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE));
2891
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
2892
- yp_local_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_and_write_node_t);
2893
-
2894
- *node = (yp_local_variable_operator_and_write_node_t) {
2895
- {
2896
- .type = YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE,
2897
- .location = {
2898
- .start = target->location.start,
2899
- .end = value->location.end
2900
- }
2901
- },
2902
- .name_loc = target->location,
2903
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2904
- .value = value,
2905
- .constant_id = constant_id
2906
- };
2907
-
2908
- return node;
2909
- }
2910
-
2911
- // Allocate and initialize a new LocalVariableOperatorWriteNode node.
2912
- static yp_local_variable_operator_write_node_t *
2913
- yp_local_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
2914
- yp_local_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_write_node_t);
2915
-
2916
- *node = (yp_local_variable_operator_write_node_t) {
2917
- {
2918
- .type = YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE,
2919
- .location = {
2920
- .start = target->location.start,
2921
- .end = value->location.end
2922
- }
2923
- },
2924
- .name_loc = target->location,
2925
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2926
- .value = value,
2927
- .constant_id = constant_id,
2928
- .operator_id = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
2929
- };
2930
-
2931
- return node;
2932
- }
2933
-
2934
- // Allocate and initialize a new LocalVariableOperatorOrWriteNode node.
2935
- static yp_local_variable_operator_or_write_node_t *
2936
- yp_local_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
2937
- assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE));
2938
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
2939
- yp_local_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_or_write_node_t);
2940
-
2941
- *node = (yp_local_variable_operator_or_write_node_t) {
2942
- {
2943
- .type = YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE,
2944
- .location = {
2945
- .start = target->location.start,
2946
- .end = value->location.end
2947
- }
2948
- },
2949
- .name_loc = target->location,
2950
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2951
- .value = value,
2952
- .constant_id = constant_id
2572
+ .body = body
2953
2573
  };
2954
2574
 
2955
2575
  return node;
@@ -3059,7 +2679,7 @@ yp_match_required_node_create(yp_parser_t *parser, yp_node_t *value, yp_node_t *
3059
2679
 
3060
2680
  // Allocate a new ModuleNode node.
3061
2681
  static yp_module_node_t *
3062
- yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *statements, const yp_token_t *end_keyword) {
2682
+ yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *body, const yp_token_t *end_keyword) {
3063
2683
  yp_module_node_t *node = YP_ALLOC_NODE(parser, yp_module_node_t);
3064
2684
 
3065
2685
  *node = (yp_module_node_t) {
@@ -3073,7 +2693,7 @@ yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const
3073
2693
  .locals = (locals == NULL ? ((yp_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals),
3074
2694
  .module_keyword_loc = YP_LOCATION_TOKEN_VALUE(module_keyword),
3075
2695
  .constant_path = constant_path,
3076
- .statements = statements,
2696
+ .body = body,
3077
2697
  .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
3078
2698
  };
3079
2699
 
@@ -3188,6 +2808,28 @@ yp_numbered_reference_read_node_create(yp_parser_t *parser, const yp_token_t *na
3188
2808
  return node;
3189
2809
  }
3190
2810
 
2811
+ // Allocate and initialize a new OperatorWriteNode.
2812
+ static yp_operator_write_node_t *
2813
+ yp_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2814
+ yp_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_operator_write_node_t);
2815
+
2816
+ *node = (yp_operator_write_node_t) {
2817
+ {
2818
+ .type = YP_NODE_OPERATOR_WRITE_NODE,
2819
+ .location = {
2820
+ .start = target->location.start,
2821
+ .end = value->location.end
2822
+ },
2823
+ },
2824
+ .target = target,
2825
+ .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2826
+ .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1),
2827
+ .value = value
2828
+ };
2829
+
2830
+ return node;
2831
+ }
2832
+
3191
2833
  // Allocate a new OptionalParameterNode node.
3192
2834
  static yp_optional_parameter_node_t *
3193
2835
  yp_optional_parameter_node_create(yp_parser_t *parser, const yp_token_t *name, const yp_token_t *operator, yp_node_t *value) {
@@ -3231,6 +2873,27 @@ yp_or_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *operat
3231
2873
  return node;
3232
2874
  }
3233
2875
 
2876
+ // Allocate and initialize a new OrWriteNode.
2877
+ static yp_or_write_node_t *
2878
+ yp_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2879
+ yp_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_or_write_node_t);
2880
+
2881
+ *node = (yp_or_write_node_t) {
2882
+ {
2883
+ .type = YP_NODE_OR_WRITE_NODE,
2884
+ .location = {
2885
+ .start = target->location.start,
2886
+ .end = value->location.end
2887
+ },
2888
+ },
2889
+ .target = target,
2890
+ .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2891
+ .value = value
2892
+ };
2893
+
2894
+ return node;
2895
+ }
2896
+
3234
2897
  // Allocate and initialize a new ParametersNode node.
3235
2898
  static yp_parameters_node_t *
3236
2899
  yp_parameters_node_create(yp_parser_t *parser) {
@@ -3343,7 +3006,7 @@ yp_program_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, yp_st
3343
3006
 
3344
3007
  // Allocate and initialize new ParenthesesNode node.
3345
3008
  static yp_parentheses_node_t *
3346
- yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_node_t *statements, const yp_token_t *closing) {
3009
+ yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_node_t *body, const yp_token_t *closing) {
3347
3010
  yp_parentheses_node_t *node = YP_ALLOC_NODE(parser, yp_parentheses_node_t);
3348
3011
 
3349
3012
  *node = (yp_parentheses_node_t) {
@@ -3354,7 +3017,7 @@ yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_no
3354
3017
  .end = closing->end
3355
3018
  }
3356
3019
  },
3357
- .statements = statements,
3020
+ .body = body,
3358
3021
  .opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
3359
3022
  .closing_loc = YP_LOCATION_TOKEN_VALUE(closing)
3360
3023
  };
@@ -3700,7 +3363,7 @@ yp_self_node_create(yp_parser_t *parser, const yp_token_t *token) {
3700
3363
 
3701
3364
  // Allocate a new SingletonClassNode node.
3702
3365
  static yp_singleton_class_node_t *
3703
- yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, const yp_token_t *operator, yp_node_t *expression, yp_node_t *statements, const yp_token_t *end_keyword) {
3366
+ yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, const yp_token_t *operator, yp_node_t *expression, yp_node_t *body, const yp_token_t *end_keyword) {
3704
3367
  yp_singleton_class_node_t *node = YP_ALLOC_NODE(parser, yp_singleton_class_node_t);
3705
3368
 
3706
3369
  *node = (yp_singleton_class_node_t) {
@@ -3715,7 +3378,7 @@ yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *local
3715
3378
  .class_keyword_loc = YP_LOCATION_TOKEN_VALUE(class_keyword),
3716
3379
  .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
3717
3380
  .expression = expression,
3718
- .statements = statements,
3381
+ .body = body,
3719
3382
  .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
3720
3383
  };
3721
3384
 
@@ -3934,10 +3597,10 @@ yp_symbol_node_label_create(yp_parser_t *parser, const yp_token_t *token) {
3934
3597
  yp_token_t label = { .type = YP_TOKEN_LABEL, .start = token->start, .end = token->end - 1 };
3935
3598
  node = yp_symbol_node_create(parser, &opening, &label, &closing);
3936
3599
 
3937
- ptrdiff_t length = label.end - label.start;
3938
- assert(length >= 0);
3600
+ assert((label.end - label.start) >= 0);
3601
+ yp_string_shared_init(&node->unescaped, label.start, label.end);
3939
3602
 
3940
- yp_unescape_manipulate_string(parser, label.start, (size_t) length, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
3603
+ yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
3941
3604
  break;
3942
3605
  }
3943
3606
  case YP_TOKEN_MISSING: {
@@ -5645,13 +5308,23 @@ parser_lex(yp_parser_t *parser) {
5645
5308
  break;
5646
5309
  case '\\':
5647
5310
  if (peek_at(parser, 1) == '\n') {
5648
- yp_newline_list_append(&parser->newline_list, parser->current.end + 1);
5649
- parser->current.end += 2;
5650
- space_seen = true;
5651
- } else if (parser->current.end + 2 < parser->end && peek_at(parser, 1) == '\r' && peek_at(parser, 2) == '\n') {
5652
- yp_newline_list_append(&parser->newline_list, parser->current.end + 2);
5653
- parser->current.end += 3;
5654
- space_seen = true;
5311
+ if (parser->heredoc_end) {
5312
+ parser->current.end = parser->heredoc_end;
5313
+ parser->heredoc_end = NULL;
5314
+ } else {
5315
+ yp_newline_list_append(&parser->newline_list, parser->current.end + 1);
5316
+ parser->current.end += 2;
5317
+ space_seen = true;
5318
+ }
5319
+ } else if (peek_at(parser, 1) == '\r' && peek_at(parser, 2) == '\n') {
5320
+ if (parser->heredoc_end) {
5321
+ parser->current.end = parser->heredoc_end;
5322
+ parser->heredoc_end = NULL;
5323
+ } else {
5324
+ yp_newline_list_append(&parser->newline_list, parser->current.end + 2);
5325
+ parser->current.end += 3;
5326
+ space_seen = true;
5327
+ }
5655
5328
  } else if (yp_char_is_inline_whitespace(*parser->current.end)) {
5656
5329
  parser->current.end += 2;
5657
5330
  } else {
@@ -6486,13 +6159,11 @@ parser_lex(yp_parser_t *parser) {
6486
6159
 
6487
6160
  // % %= %i %I %q %Q %w %W
6488
6161
  case '%': {
6489
- // In a BEG state, if you encounter a % then you must be
6490
- // starting something. In this case if there is no
6491
- // subsequent character then we have an invalid token. We're
6492
- // going to say it's the percent operator because we don't
6493
- // want to move into the string lex mode unnecessarily.
6494
- if (lex_state_beg_p(parser) && (parser->current.end >= parser->end)) {
6495
- yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "unexpected end of input");
6162
+ // If there is no subsequent character then we have an invalid token. We're
6163
+ // going to say it's the percent operator because we don't want to move into the
6164
+ // string lex mode unnecessarily.
6165
+ if ((lex_state_beg_p(parser) || lex_state_arg_p(parser)) && (parser->current.end >= parser->end)) {
6166
+ yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "Unexpected end of input");
6496
6167
  LEX(YP_TOKEN_PERCENT);
6497
6168
  }
6498
6169
 
@@ -6665,7 +6336,7 @@ parser_lex(yp_parser_t *parser) {
6665
6336
  ((parser->current.end - parser->current.start) == 7) &&
6666
6337
  current_token_starts_line(parser) &&
6667
6338
  (strncmp(parser->current.start, "__END__", 7) == 0) &&
6668
- (*parser->current.end == '\n' || (*parser->current.end == '\r' && parser->current.end[1] == '\n'))
6339
+ (parser->current.end == parser->end || *parser->current.end == '\n' || (*parser->current.end == '\r' && parser->current.end[1] == '\n'))
6669
6340
  ) {
6670
6341
  parser->current.end = parser->end;
6671
6342
  parser->current.type = YP_TOKEN___END__;
@@ -7082,6 +6753,7 @@ parser_lex(yp_parser_t *parser) {
7082
6753
  } else {
7083
6754
  parser->current.start = parser->next_start;
7084
6755
  parser->current.end = parser->next_start;
6756
+ parser->heredoc_end = NULL;
7085
6757
  parser->next_start = NULL;
7086
6758
  }
7087
6759
 
@@ -7203,11 +6875,16 @@ parser_lex(yp_parser_t *parser) {
7203
6875
  break;
7204
6876
  }
7205
6877
  case '\\': {
7206
- // If we hit escapes, then we need to treat the next token
7207
- // literally. In this case we'll skip past the next character and
7208
- // find the next breakpoint.
7209
- if (breakpoint[1] == '\n') {
6878
+ // If we hit an escape, then we need to skip past
6879
+ // however many characters the escape takes up. However
6880
+ // it's important that if \n or \r\n are escaped that we
6881
+ // stop looping before the newline and not after the
6882
+ // newline so that we can still potentially find the
6883
+ // terminator of the heredoc.
6884
+ if (breakpoint + 1 < parser->end && breakpoint[1] == '\n') {
7210
6885
  breakpoint++;
6886
+ } else if (breakpoint + 2 < parser->end && breakpoint[1] == '\r' && breakpoint[2] == '\n') {
6887
+ breakpoint += 2;
7211
6888
  } else {
7212
6889
  yp_unescape_type_t unescape_type = (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL;
7213
6890
  size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, unescape_type, false, &parser->error_list);
@@ -7218,6 +6895,7 @@ parser_lex(yp_parser_t *parser) {
7218
6895
 
7219
6896
  breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference));
7220
6897
  }
6898
+
7221
6899
  break;
7222
6900
  }
7223
6901
  case '#': {
@@ -7264,10 +6942,10 @@ static yp_regular_expression_node_t *
7264
6942
  yp_regular_expression_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
7265
6943
  yp_regular_expression_node_t *node = yp_regular_expression_node_create(parser, opening, content, closing);
7266
6944
 
7267
- ptrdiff_t length = content->end - content->start;
7268
- assert(length >= 0);
6945
+ assert((content->end - content->start) >= 0);
6946
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7269
6947
 
7270
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list);
6948
+ yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
7271
6949
  return node;
7272
6950
  }
7273
6951
 
@@ -7275,10 +6953,10 @@ static yp_symbol_node_t *
7275
6953
  yp_symbol_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
7276
6954
  yp_symbol_node_t *node = yp_symbol_node_create(parser, opening, content, closing);
7277
6955
 
7278
- ptrdiff_t length = content->end - content->start;
7279
- assert(length >= 0);
6956
+ assert((content->end - content->start) >= 0);
6957
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7280
6958
 
7281
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list);
6959
+ yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
7282
6960
  return node;
7283
6961
  }
7284
6962
 
@@ -7286,10 +6964,10 @@ static yp_string_node_t *
7286
6964
  yp_string_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
7287
6965
  yp_string_node_t *node = yp_string_node_create(parser, opening, content, closing);
7288
6966
 
7289
- ptrdiff_t length = content->end - content->start;
7290
- assert(length >= 0);
6967
+ assert((content->end - content->start) >= 0);
6968
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7291
6969
 
7292
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list);
6970
+ yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
7293
6971
  return node;
7294
6972
  }
7295
6973
 
@@ -7297,10 +6975,10 @@ static yp_x_string_node_t *
7297
6975
  yp_xstring_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing) {
7298
6976
  yp_x_string_node_t *node = yp_xstring_node_create(parser, opening, content, closing);
7299
6977
 
7300
- ptrdiff_t length = content->end - content->start;
7301
- assert(length >= 0);
6978
+ assert((content->end - content->start) >= 0);
6979
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7302
6980
 
7303
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
6981
+ yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
7304
6982
  return node;
7305
6983
  }
7306
6984
 
@@ -8999,7 +8677,7 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
8999
8677
  }
9000
8678
 
9001
8679
  yp_token_t end_keyword = not_provided(parser);
9002
- yp_node_t *parent;
8680
+ yp_node_t *parent = NULL;
9003
8681
 
9004
8682
  switch (context) {
9005
8683
  case YP_CONTEXT_IF:
@@ -9009,7 +8687,6 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
9009
8687
  parent = (yp_node_t *) yp_unless_node_create(parser, &keyword, predicate, statements);
9010
8688
  break;
9011
8689
  default:
9012
- parent = NULL;
9013
8690
  assert(false && "unreachable");
9014
8691
  break;
9015
8692
  }
@@ -9055,50 +8732,49 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
9055
8732
  switch (context) {
9056
8733
  case YP_CONTEXT_IF:
9057
8734
  ((yp_if_node_t *) current)->consequent = (yp_node_t *) else_node;
9058
- // Recurse down if nodes setting the appropriate end location in
9059
- // all cases.
9060
- yp_node_t *recursing_node = parent;
9061
- bool recursing = true;
9062
-
9063
- while (recursing) {
9064
- switch (YP_NODE_TYPE(recursing_node)) {
9065
- case YP_NODE_IF_NODE:
9066
- yp_if_node_end_keyword_loc_set((yp_if_node_t *) recursing_node, &parser->previous);
9067
- recursing_node = ((yp_if_node_t *) recursing_node)->consequent;
9068
- break;
9069
- case YP_NODE_ELSE_NODE:
9070
- yp_else_node_end_keyword_loc_set((yp_else_node_t *) recursing_node, &parser->previous);
9071
- recursing = false;
9072
- break;
9073
- default: {
9074
- recursing = false;
9075
- break;
9076
- }
9077
- }
9078
- }
9079
8735
  break;
9080
8736
  case YP_CONTEXT_UNLESS:
9081
8737
  ((yp_unless_node_t *) parent)->consequent = else_node;
9082
- yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
9083
8738
  break;
9084
8739
  default:
9085
8740
  assert(false && "unreachable");
9086
8741
  break;
9087
8742
  }
9088
8743
  } else {
9089
- expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close `if` statement.");
8744
+ expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close conditional statement.");
8745
+ }
9090
8746
 
9091
- switch (context) {
9092
- case YP_CONTEXT_IF:
9093
- yp_if_node_end_keyword_loc_set((yp_if_node_t *) parent, &parser->previous);
9094
- break;
9095
- case YP_CONTEXT_UNLESS:
9096
- yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
9097
- break;
9098
- default:
9099
- assert(false && "unreachable");
9100
- break;
8747
+ // Set the appropriate end location for all of the nodes in the subtree.
8748
+ switch (context) {
8749
+ case YP_CONTEXT_IF: {
8750
+ yp_node_t *current = parent;
8751
+ bool recursing = true;
8752
+
8753
+ while (recursing) {
8754
+ switch (YP_NODE_TYPE(current)) {
8755
+ case YP_NODE_IF_NODE:
8756
+ yp_if_node_end_keyword_loc_set((yp_if_node_t *) current, &parser->previous);
8757
+ current = ((yp_if_node_t *) current)->consequent;
8758
+ recursing = current != NULL;
8759
+ break;
8760
+ case YP_NODE_ELSE_NODE:
8761
+ yp_else_node_end_keyword_loc_set((yp_else_node_t *) current, &parser->previous);
8762
+ recursing = false;
8763
+ break;
8764
+ default: {
8765
+ recursing = false;
8766
+ break;
8767
+ }
8768
+ }
8769
+ }
8770
+ break;
9101
8771
  }
8772
+ case YP_CONTEXT_UNLESS:
8773
+ yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
8774
+ break;
8775
+ default:
8776
+ assert(false && "unreachable");
8777
+ break;
9102
8778
  }
9103
8779
 
9104
8780
  return parent;
@@ -9172,7 +8848,12 @@ parse_string_part(yp_parser_t *parser) {
9172
8848
  yp_unescape_type_t unescape_type = YP_UNESCAPE_ALL;
9173
8849
 
9174
8850
  if (parser->lex_modes.current->mode == YP_LEX_HEREDOC) {
9175
- if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) {
8851
+ if (parser->lex_modes.current->as.heredoc.indent == YP_HEREDOC_INDENT_TILDE) {
8852
+ // If we're in a tilde heredoc, we want to unescape it later
8853
+ // because we don't want unescaped newlines to disappear
8854
+ // before we handle them in the dedent.
8855
+ unescape_type = YP_UNESCAPE_NONE;
8856
+ } else if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) {
9176
8857
  unescape_type = YP_UNESCAPE_MINIMAL;
9177
8858
  }
9178
8859
  }
@@ -9545,14 +9226,30 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
9545
9226
  int common_whitespace;
9546
9227
  if ((common_whitespace = parse_heredoc_common_whitespace(parser, nodes)) <= 0) return;
9547
9228
 
9548
- // Iterate over all nodes, and trim whitespace accordingly.
9549
- for (size_t index = 0; index < nodes->size; index++) {
9550
- yp_node_t *node = nodes->nodes[index];
9551
- if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) continue;
9229
+ // The next node should be dedented if it's the first node in the list or if
9230
+ // if follows a string node.
9231
+ bool dedent_next = true;
9232
+
9233
+ // Iterate over all nodes, and trim whitespace accordingly. We're going to
9234
+ // keep around two indices: a read and a write. If we end up trimming all of
9235
+ // the whitespace from a node, then we'll drop it from the list entirely.
9236
+ size_t write_index = 0;
9237
+
9238
+ for (size_t read_index = 0; read_index < nodes->size; read_index++) {
9239
+ yp_node_t *node = nodes->nodes[read_index];
9240
+
9241
+ // We're not manipulating child nodes that aren't strings. In this case
9242
+ // we'll skip past it and indicate that the subsequent node should not
9243
+ // be dedented.
9244
+ if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) {
9245
+ nodes->nodes[write_index++] = node;
9246
+ dedent_next = false;
9247
+ continue;
9248
+ }
9552
9249
 
9553
9250
  // Get a reference to the string struct that is being held by the string
9554
9251
  // node. This is the value we're going to actual manipulate.
9555
- yp_string_t *string = &((yp_string_node_t *) node)->unescaped;
9252
+ yp_string_t *string = &(((yp_string_node_t *) node)->unescaped);
9556
9253
  yp_string_ensure_owned(string);
9557
9254
 
9558
9255
  // Now get the bounds of the existing string. We'll use this as a
@@ -9568,7 +9265,6 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
9568
9265
  // whitespace, so we'll maintain a pointer to the current position in the
9569
9266
  // string that we're writing to.
9570
9267
  char *dest_cursor = source_start;
9571
- bool dedent_next = (index == 0) || YP_NODE_TYPE_P(nodes->nodes[index - 1], YP_NODE_STRING_NODE);
9572
9268
 
9573
9269
  while (source_cursor < source_end) {
9574
9270
  // If we need to dedent the next element within the heredoc or the next
@@ -9613,8 +9309,20 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
9613
9309
  dedent_next = true;
9614
9310
  }
9615
9311
 
9616
- string->length = dest_length;
9312
+ // We only want to write this node into the list if it has any content.
9313
+ if (dest_length == 0) {
9314
+ yp_node_destroy(parser, node);
9315
+ } else {
9316
+ string->length = dest_length;
9317
+ yp_unescape_manipulate_string(parser, string, (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL, &parser->error_list);
9318
+ nodes->nodes[write_index++] = node;
9319
+ }
9320
+
9321
+ // We always dedent the next node if it follows a string node.
9322
+ dedent_next = true;
9617
9323
  }
9324
+
9325
+ nodes->size = write_index;
9618
9326
  }
9619
9327
 
9620
9328
  static yp_node_t *
@@ -10673,12 +10381,15 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
10673
10381
 
10674
10382
  lex_state_set(parser, YP_LEX_STATE_END);
10675
10383
  expect(parser, YP_TOKEN_HEREDOC_END, "Expected a closing delimiter for heredoc.");
10384
+
10676
10385
  if (quote == YP_HEREDOC_QUOTE_BACKTICK) {
10677
10386
  assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_X_STRING_NODE));
10678
10387
  yp_interpolated_xstring_node_closing_set(((yp_interpolated_x_string_node_t *) node), &parser->previous);
10388
+ node->location = ((yp_interpolated_x_string_node_t *) node)->opening_loc;
10679
10389
  } else {
10680
10390
  assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_STRING_NODE));
10681
10391
  yp_interpolated_string_node_closing_set((yp_interpolated_string_node_t *) node, &parser->previous);
10392
+ node->location = ((yp_interpolated_string_node_t *) node)->opening_loc;
10682
10393
  }
10683
10394
 
10684
10395
  // If this is a heredoc that is indented with a ~, then we need to dedent
@@ -12394,14 +12105,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12394
12105
  case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
12395
12106
  yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
12396
12107
  /* fallthrough */
12397
- case YP_NODE_GLOBAL_VARIABLE_READ_NODE: {
12108
+ case YP_NODE_CLASS_VARIABLE_READ_NODE:
12109
+ case YP_NODE_CONSTANT_PATH_NODE:
12110
+ case YP_NODE_CONSTANT_READ_NODE:
12111
+ case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
12112
+ case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
12113
+ case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12398
12114
  parser_lex(parser);
12399
12115
 
12400
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12401
- yp_node_t *result = (yp_node_t *) yp_global_variable_operator_and_write_node_create(parser, node, &token, value);
12116
+ yp_token_t operator = not_provided(parser);
12117
+ node = parse_target(parser, node, &operator, NULL);
12402
12118
 
12403
- yp_node_destroy(parser, node);
12404
- return result;
12119
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12120
+ return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
12405
12121
  }
12406
12122
  case YP_NODE_CALL_NODE: {
12407
12123
  yp_call_node_t *call_node = (yp_call_node_t *) node;
@@ -12419,12 +12135,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12419
12135
 
12420
12136
  parser_lex(parser);
12421
12137
 
12422
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12423
- yp_constant_id_t constant_id = yp_parser_constant_id_location(parser, message_loc.start, message_loc.end);
12424
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_and_write_node_create(parser, node, &token, value, constant_id);
12138
+ yp_token_t operator = not_provided(parser);
12139
+ node = parse_target(parser, node, &operator, NULL);
12425
12140
 
12426
- yp_node_destroy(parser, node);
12427
- return result;
12141
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12142
+ return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
12428
12143
  }
12429
12144
 
12430
12145
  parser_lex(parser);
@@ -12435,49 +12150,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12435
12150
  yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12436
12151
  return (yp_node_t *) yp_call_operator_and_write_node_create(parser, (yp_call_node_t *) node, &token, value);
12437
12152
  }
12438
- case YP_NODE_CLASS_VARIABLE_READ_NODE: {
12439
- parser_lex(parser);
12440
-
12441
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12442
- yp_node_t *result = (yp_node_t *) yp_class_variable_operator_and_write_node_create(parser, node, &token, value);
12443
-
12444
- yp_node_destroy(parser, node);
12445
- return result;
12446
- }
12447
- case YP_NODE_CONSTANT_PATH_NODE: {
12448
- parser_lex(parser);
12449
-
12450
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12451
- return (yp_node_t *) yp_constant_path_operator_and_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
12452
- }
12453
- case YP_NODE_CONSTANT_READ_NODE: {
12454
- parser_lex(parser);
12455
-
12456
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12457
- yp_node_t *result = (yp_node_t *) yp_constant_operator_and_write_node_create(parser, node, &token, value);
12458
-
12459
- yp_node_destroy(parser, node);
12460
- return result;
12461
- }
12462
- case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
12463
- parser_lex(parser);
12464
-
12465
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12466
- yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_and_write_node_create(parser, node, &token, value);
12467
-
12468
- yp_node_destroy(parser, node);
12469
- return result;
12470
- }
12471
- case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12472
- parser_lex(parser);
12473
-
12474
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12475
- yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
12476
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_and_write_node_create(parser, node, &token, value, constant_id);
12477
-
12478
- yp_node_destroy(parser, node);
12479
- return result;
12480
- }
12481
12153
  case YP_NODE_MULTI_WRITE_NODE: {
12482
12154
  parser_lex(parser);
12483
12155
  yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Cannot use `&&=' on a multi-write.");
@@ -12499,14 +12171,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12499
12171
  case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
12500
12172
  yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
12501
12173
  /* fallthrough */
12502
- case YP_NODE_GLOBAL_VARIABLE_READ_NODE: {
12174
+ case YP_NODE_CLASS_VARIABLE_READ_NODE:
12175
+ case YP_NODE_CONSTANT_PATH_NODE:
12176
+ case YP_NODE_CONSTANT_READ_NODE:
12177
+ case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
12178
+ case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
12179
+ case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12503
12180
  parser_lex(parser);
12504
12181
 
12505
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12506
- yp_node_t *result = (yp_node_t *) yp_global_variable_operator_or_write_node_create(parser, node, &token, value);
12182
+ yp_token_t operator = not_provided(parser);
12183
+ node = parse_target(parser, node, &operator, NULL);
12507
12184
 
12508
- yp_node_destroy(parser, node);
12509
- return result;
12185
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12186
+ return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
12510
12187
  }
12511
12188
  case YP_NODE_CALL_NODE: {
12512
12189
  yp_call_node_t *call_node = (yp_call_node_t *) node;
@@ -12524,12 +12201,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12524
12201
 
12525
12202
  parser_lex(parser);
12526
12203
 
12527
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12528
- yp_constant_id_t constant_id = yp_parser_constant_id_location(parser, message_loc.start, message_loc.end);
12529
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_or_write_node_create(parser, node, &token, value, constant_id);
12204
+ yp_token_t operator = not_provided(parser);
12205
+ node = parse_target(parser, node, &operator, NULL);
12530
12206
 
12531
- yp_node_destroy(parser, node);
12532
- return result;
12207
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12208
+ return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
12533
12209
  }
12534
12210
 
12535
12211
  parser_lex(parser);
@@ -12540,49 +12216,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12540
12216
  yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12541
12217
  return (yp_node_t *) yp_call_operator_or_write_node_create(parser, (yp_call_node_t *) node, &token, value);
12542
12218
  }
12543
- case YP_NODE_CLASS_VARIABLE_READ_NODE: {
12544
- parser_lex(parser);
12545
-
12546
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12547
- yp_node_t *result = (yp_node_t *) yp_class_variable_operator_or_write_node_create(parser, node, &token, value);
12548
-
12549
- yp_node_destroy(parser, node);
12550
- return result;
12551
- }
12552
- case YP_NODE_CONSTANT_PATH_NODE: {
12553
- parser_lex(parser);
12554
-
12555
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12556
- return (yp_node_t *) yp_constant_path_operator_or_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
12557
- }
12558
- case YP_NODE_CONSTANT_READ_NODE: {
12559
- parser_lex(parser);
12560
-
12561
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12562
- yp_node_t *result = (yp_node_t *) yp_constant_operator_or_write_node_create(parser, node, &token, value);
12563
-
12564
- yp_node_destroy(parser, node);
12565
- return result;
12566
- }
12567
- case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
12568
- parser_lex(parser);
12569
-
12570
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12571
- yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_or_write_node_create(parser, node, &token, value);
12572
-
12573
- yp_node_destroy(parser, node);
12574
- return result;
12575
- }
12576
- case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12577
- parser_lex(parser);
12578
-
12579
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12580
- yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
12581
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_or_write_node_create(parser, node, &token, value, constant_id);
12582
-
12583
- yp_node_destroy(parser, node);
12584
- return result;
12585
- }
12586
12219
  case YP_NODE_MULTI_WRITE_NODE: {
12587
12220
  parser_lex(parser);
12588
12221
  yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Cannot use `||=' on a multi-write.");
@@ -12614,14 +12247,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12614
12247
  case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
12615
12248
  yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
12616
12249
  /* fallthrough */
12617
- case YP_NODE_GLOBAL_VARIABLE_READ_NODE: {
12250
+ case YP_NODE_CLASS_VARIABLE_READ_NODE:
12251
+ case YP_NODE_CONSTANT_PATH_NODE:
12252
+ case YP_NODE_CONSTANT_READ_NODE:
12253
+ case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
12254
+ case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
12255
+ case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12618
12256
  parser_lex(parser);
12619
12257
 
12620
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator");
12621
- yp_node_t *result = (yp_node_t *) yp_global_variable_operator_write_node_create(parser, node, &token, value);
12258
+ yp_token_t operator = not_provided(parser);
12259
+ node = parse_target(parser, node, &operator, NULL);
12622
12260
 
12623
- yp_node_destroy(parser, node);
12624
- return result;
12261
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator");
12262
+ return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
12625
12263
  }
12626
12264
  case YP_NODE_CALL_NODE: {
12627
12265
  yp_call_node_t *call_node = (yp_call_node_t *) node;
@@ -12639,12 +12277,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12639
12277
 
12640
12278
  parser_lex(parser);
12641
12279
 
12642
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12643
- yp_constant_id_t constant_id = yp_parser_constant_id_location(parser, message_loc.start, message_loc.end);
12644
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_write_node_create(parser, node, &token, value, constant_id);
12280
+ yp_token_t operator = not_provided(parser);
12281
+ node = parse_target(parser, node, &operator, NULL);
12645
12282
 
12646
- yp_node_destroy(parser, node);
12647
- return result;
12283
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12284
+ return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
12648
12285
  }
12649
12286
 
12650
12287
  yp_token_t operator = not_provided(parser);
@@ -12654,49 +12291,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12654
12291
  yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12655
12292
  return (yp_node_t *) yp_call_operator_write_node_create(parser, (yp_call_node_t *) node, &token, value);
12656
12293
  }
12657
- case YP_NODE_CLASS_VARIABLE_READ_NODE: {
12658
- parser_lex(parser);
12659
-
12660
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12661
- yp_node_t *result = (yp_node_t *) yp_class_variable_operator_write_node_create(parser, node, &token, value);
12662
-
12663
- yp_node_destroy(parser, node);
12664
- return result;
12665
- }
12666
- case YP_NODE_CONSTANT_PATH_NODE: {
12667
- parser_lex(parser);
12668
-
12669
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12670
- return (yp_node_t *) yp_constant_path_operator_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
12671
- }
12672
- case YP_NODE_CONSTANT_READ_NODE: {
12673
- parser_lex(parser);
12674
-
12675
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12676
- yp_node_t *result = (yp_node_t *) yp_constant_operator_write_node_create(parser, node, &token, value);
12677
-
12678
- yp_node_destroy(parser, node);
12679
- return result;
12680
- }
12681
- case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
12682
- parser_lex(parser);
12683
-
12684
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12685
- yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_write_node_create(parser, node, &token, value);
12686
-
12687
- yp_node_destroy(parser, node);
12688
- return result;
12689
- }
12690
- case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12691
- parser_lex(parser);
12692
-
12693
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12694
- yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
12695
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_write_node_create(parser, node, &token, value, constant_id);
12696
-
12697
- yp_node_destroy(parser, node);
12698
- return result;
12699
- }
12700
12294
  case YP_NODE_MULTI_WRITE_NODE: {
12701
12295
  parser_lex(parser);
12702
12296
  yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Unexpected operator.");
@@ -13190,6 +12784,8 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
13190
12784
  .enclosure_nesting = 0,
13191
12785
  .lambda_enclosure_nesting = -1,
13192
12786
  .brace_nesting = 0,
12787
+ .do_loop_stack = YP_STATE_STACK_EMPTY,
12788
+ .accepts_block_stack = YP_STATE_STACK_EMPTY,
13193
12789
  .lex_modes = {
13194
12790
  .index = 0,
13195
12791
  .stack = {{ .mode = YP_LEX_DEFAULT }},
@@ -13201,6 +12797,9 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
13201
12797
  .current = { .type = YP_TOKEN_EOF, .start = source, .end = source },
13202
12798
  .next_start = NULL,
13203
12799
  .heredoc_end = NULL,
12800
+ .comment_list = YP_LIST_EMPTY,
12801
+ .warning_list = YP_LIST_EMPTY,
12802
+ .error_list = YP_LIST_EMPTY,
13204
12803
  .current_scope = NULL,
13205
12804
  .current_context = NULL,
13206
12805
  .recovering = false,
@@ -13213,16 +12812,12 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
13213
12812
  .pattern_matching_newlines = false,
13214
12813
  .in_keyword_arg = false,
13215
12814
  .filepath_string = filepath_string,
12815
+ .constant_pool = YP_CONSTANT_POOL_EMPTY,
12816
+ .newline_list = YP_NEWLINE_LIST_EMPTY
13216
12817
  };
13217
12818
 
13218
- yp_state_stack_init(&parser->do_loop_stack);
13219
- yp_state_stack_init(&parser->accepts_block_stack);
13220
12819
  yp_accepts_block_stack_push(parser, true);
13221
12820
 
13222
- yp_list_init(&parser->warning_list);
13223
- yp_list_init(&parser->error_list);
13224
- yp_list_init(&parser->comment_list);
13225
-
13226
12821
  // Initialize the constant pool. We're going to completely guess as to the
13227
12822
  // number of constants that we'll need based on the size of the input. The
13228
12823
  // ratio we chose here is actually less arbitrary than you might think.