@@ -1677,72 +1677,16 @@ public RubyNode visitInNode(Nodes.InNode node) {
1677
1677
1678
1678
@ Override
1679
1679
public RubyNode visitIndexAndWriteNode (Nodes .IndexAndWriteNode node ) {
1680
- // `a[b] &&= c` is translated into `a[b] && a[b] = c`
1681
-
1682
- // receiver (a) and arguments (b) should be executed only once
1683
- // that's why they are cached in local variables
1684
-
1685
- assert node .receiver != null ;
1686
-
1687
- // receiver
1688
- final var receiverExpression = new YARPExecutedOnceExpression ("opelementassign" , node .receiver , this );
1689
- final var writeReceiveNode = receiverExpression .getWriteNode ();
1690
- final var readReceiver = receiverExpression .getReadYARPNode ();
1691
-
1692
1680
// arguments
1693
1681
final Nodes .Node [] arguments ;
1694
1682
if (node .arguments != null ) {
1695
1683
arguments = node .arguments .arguments ;
1696
1684
} else {
1697
1685
arguments = Nodes .Node .EMPTY_ARRAY ;
1698
1686
}
1699
- final int argumentsCount = arguments .length ;
1700
-
1701
- // block argument
1702
- final RubyNode writeBlockNode ;
1703
- final Nodes .BlockArgumentNode blockArgument ;
1704
-
1705
- if (node .block != null ) {
1706
- var expression = new YARPExecutedOnceExpression ("value" , node .block , this );
1707
- writeBlockNode = expression .getWriteNode ();
1708
- Nodes .Node readBlock = expression .getReadYARPNode ();
1709
- // imitate Nodes.CallNode structure with &block argument
1710
- blockArgument = new Nodes .BlockArgumentNode (readBlock , 0 , 0 );
1711
- } else {
1712
- writeBlockNode = null ;
1713
- blockArgument = null ;
1714
- }
1715
-
1716
- final RubyNode [] writeArgumentsNodes = new RubyNode [argumentsCount ];
1717
- final Nodes .Node [] readArguments = new Nodes .Node [argumentsCount ];
1718
- for (int i = 0 ; i < argumentsCount ; i ++) {
1719
- var expression = new YARPExecutedOnceExpression ("value" , arguments [i ], this );
1720
- writeArgumentsNodes [i ] = expression .getWriteNode ();
1721
- readArguments [i ] = expression .getReadYARPNode ();
1722
- }
1723
-
1724
- final Nodes .Node read = new Nodes .CallNode (readReceiver , "[]" ,
1725
- new Nodes .ArgumentsNode (readArguments , (short ) 0 , 0 , 0 ), blockArgument , (short ) 0 , 0 , 0 );
1726
- final RubyNode readNode = read .accept (this );
1727
-
1728
- final Nodes .Node [] readArgumentsAndValue = new Nodes .Node [argumentsCount + 1 ];
1729
- System .arraycopy (readArguments , 0 , readArgumentsAndValue , 0 , argumentsCount );
1730
- readArgumentsAndValue [argumentsCount ] = node .value ;
1731
-
1732
- final Nodes .Node write = new Nodes .CallNode (readReceiver , "[]=" ,
1733
- new Nodes .ArgumentsNode (readArgumentsAndValue , (short ) 0 , 0 , 0 ), blockArgument , (short ) 0 , 0 , 0 );
1734
- final RubyNode writeNode = write .accept (this );
1735
- final RubyNode andNode = AndNodeGen .create (readNode , writeNode );
1736
- final RubyNode writeArgumentsNode = sequence (Arrays .asList (writeArgumentsNodes ));
1737
- final RubyNode rubyNode ;
1738
-
1739
- if (node .block != null ) {
1740
- // add block argument write node
1741
- rubyNode = sequence (Arrays .asList (writeArgumentsNode , writeBlockNode , writeReceiveNode , andNode ));
1742
- } else {
1743
- rubyNode = sequence (Arrays .asList (writeArgumentsNode , writeReceiveNode , andNode ));
1744
- }
1745
1687
1688
+ final RubyNode rubyNode = translateIndexOrAndIndexAndWriteNodes (true , node .receiver , arguments , node .block ,
1689
+ node .value );
1746
1690
return assignPositionAndFlags (node , rubyNode );
1747
1691
}
1748
1692
@@ -1818,30 +1762,38 @@ public RubyNode visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) {
1818
1762
1819
1763
@ Override
1820
1764
public RubyNode visitIndexOrWriteNode (Nodes .IndexOrWriteNode node ) {
1821
- // `a[b] ||= c` is translated into `a[b] || a[b] = c`
1765
+ // arguments
1766
+ final Nodes .Node [] arguments ;
1767
+ if (node .arguments != null ) {
1768
+ arguments = node .arguments .arguments ;
1769
+ } else {
1770
+ arguments = Nodes .Node .EMPTY_ARRAY ;
1771
+ }
1772
+
1773
+ final RubyNode rubyNode = translateIndexOrAndIndexAndWriteNodes (false , node .receiver , arguments , node .block ,
1774
+ node .value );
1775
+ return assignPositionAndFlags (node , rubyNode );
1776
+ }
1777
+
1778
+ private RubyNode translateIndexOrAndIndexAndWriteNodes (boolean isAndOperator , Nodes .Node receiver ,
1779
+ Nodes .Node [] arguments , Nodes .Node block , Nodes .Node value ) {
1780
+ // Handle both &&= and ||= operators:
1781
+ // `a[b] ||= c` is translated into `a[b] || a[b] = c`
1782
+ // `a[b] &&= c` is translated into `a[b] && a[b] = c`
1822
1783
1823
1784
// receiver (a) and arguments (b) should be executed only once
1824
1785
// that's why they are cached in local variables
1825
1786
1826
- assert node . receiver != null ;
1787
+ assert receiver != null ;
1827
1788
1828
1789
// receiver
1829
- final var receiverExpression = new YARPExecutedOnceExpression ("opelementassign" , node . receiver , this );
1790
+ final var receiverExpression = new YARPExecutedOnceExpression ("opelementassign" , receiver , this );
1830
1791
final var writeReceiveNode = receiverExpression .getWriteNode ();
1831
1792
final var readReceiver = receiverExpression .getReadYARPNode ();
1832
1793
1833
- // arguments
1834
- final Nodes .Node [] arguments ;
1835
- if (node .arguments != null ) {
1836
- arguments = node .arguments .arguments ;
1837
- } else {
1838
- arguments = Nodes .Node .EMPTY_ARRAY ;
1839
- }
1840
- final int argumentsCount = arguments .length ;
1841
-
1842
- final RubyNode [] writeArgumentsNodes = new RubyNode [argumentsCount ];
1843
- final Nodes .Node [] readArguments = new Nodes .Node [argumentsCount ];
1844
- for (int i = 0 ; i < argumentsCount ; i ++) {
1794
+ final RubyNode [] writeArgumentsNodes = new RubyNode [arguments .length ];
1795
+ final Nodes .Node [] readArguments = new Nodes .Node [arguments .length ];
1796
+ for (int i = 0 ; i < arguments .length ; i ++) {
1845
1797
final var expression = new YARPExecutedOnceExpression ("value" , arguments [i ], this );
1846
1798
writeArgumentsNodes [i ] = expression .getWriteNode ();
1847
1799
readArguments [i ] = expression .getReadYARPNode ();
@@ -1851,8 +1803,8 @@ public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) {
1851
1803
final RubyNode writeBlockNode ;
1852
1804
final Nodes .BlockArgumentNode blockArgument ;
1853
1805
1854
- if (node . block != null ) {
1855
- var expression = new YARPExecutedOnceExpression ("value" , node . block , this );
1806
+ if (block != null ) {
1807
+ var expression = new YARPExecutedOnceExpression ("value" , block , this );
1856
1808
writeBlockNode = expression .getWriteNode ();
1857
1809
Nodes .Node readBlock = expression .getReadYARPNode ();
1858
1810
// imitate Nodes.CallNode structure with &block argument
@@ -1866,25 +1818,32 @@ public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) {
1866
1818
new Nodes .ArgumentsNode (readArguments , (short ) 0 , 0 , 0 ), blockArgument , (short ) 0 , 0 , 0 );
1867
1819
final RubyNode readNode = read .accept (this );
1868
1820
1869
- final Nodes .Node [] readArgumentsAndValue = new Nodes .Node [argumentsCount + 1 ];
1870
- System .arraycopy (readArguments , 0 , readArgumentsAndValue , 0 , argumentsCount );
1871
- readArgumentsAndValue [argumentsCount ] = node . value ;
1821
+ final Nodes .Node [] readArgumentsAndValue = new Nodes .Node [arguments . length + 1 ];
1822
+ System .arraycopy (readArguments , 0 , readArgumentsAndValue , 0 , arguments . length );
1823
+ readArgumentsAndValue [arguments . length ] = value ;
1872
1824
1873
1825
final Nodes .Node write = new Nodes .CallNode (readReceiver , "[]=" ,
1874
1826
new Nodes .ArgumentsNode (readArgumentsAndValue , (short ) 0 , 0 , 0 ), blockArgument , (short ) 0 , 0 , 0 );
1875
1827
final RubyNode writeNode = write .accept (this );
1876
- final RubyNode orNode = OrNodeGen .create (readNode , writeNode );
1828
+
1829
+ final RubyNode operatorNode ;
1830
+ if (isAndOperator ) {
1831
+ operatorNode = AndNodeGen .create (readNode , writeNode );
1832
+ } else {
1833
+ operatorNode = OrNodeGen .create (readNode , writeNode );
1834
+ }
1835
+
1877
1836
final RubyNode writeArgumentsNode = sequence (Arrays .asList (writeArgumentsNodes ));
1878
1837
final RubyNode rubyNode ;
1879
1838
1880
- if (node . block != null ) {
1839
+ if (block != null ) {
1881
1840
// add block argument write node
1882
- rubyNode = sequence (Arrays .asList (writeArgumentsNode , writeBlockNode , writeReceiveNode , orNode ));
1841
+ rubyNode = sequence (Arrays .asList (writeArgumentsNode , writeBlockNode , writeReceiveNode , operatorNode ));
1883
1842
} else {
1884
- rubyNode = sequence (Arrays .asList (writeArgumentsNode , writeReceiveNode , orNode ));
1843
+ rubyNode = sequence (Arrays .asList (writeArgumentsNode , writeReceiveNode , operatorNode ));
1885
1844
}
1886
1845
1887
- return assignPositionAndFlags ( node , rubyNode ) ;
1846
+ return rubyNode ;
1888
1847
}
1889
1848
1890
1849
@ Override
0 commit comments