Skip to content

Commit 49b1843

Browse files
committed
Refactor visitIndexAndWriteNode and visitIndexOrWriteNode and move shared logic into a helper method
1 parent 9872ae4 commit 49b1843

File tree

2 files changed

+48
-89
lines changed

2 files changed

+48
-89
lines changed

spec/truffle/parsing/fixtures/operators/&&=/reference_assignment_with_block_argument.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ ast: |
3636
WriteLocalVariableNode
3737
attributes:
3838
flags = 0
39-
frameSlot = 4 # %value_2
39+
frameSlot = 3 # %value_1
4040
children:
4141
valueNode =
4242
IntegerFixnumLiteralNode
@@ -46,7 +46,7 @@ ast: |
4646
WriteLocalVariableNode
4747
attributes:
4848
flags = 0
49-
frameSlot = 3 # %value_1
49+
frameSlot = 4 # %value_2
5050
children:
5151
valueNode =
5252
ToProcNodeGen
@@ -122,7 +122,7 @@ ast: |
122122
ReadLocalVariableNode
123123
attributes:
124124
flags = 0
125-
frameSlot = 4 # %value_2
125+
frameSlot = 3 # %value_1
126126
type = FRAME_LOCAL
127127
]
128128
block =
@@ -134,7 +134,7 @@ ast: |
134134
ReadLocalVariableNode
135135
attributes:
136136
flags = 0
137-
frameSlot = 3 # %value_1
137+
frameSlot = 4 # %value_2
138138
type = FRAME_LOCAL
139139
receiver =
140140
ReadLocalVariableNode
@@ -162,7 +162,7 @@ ast: |
162162
ReadLocalVariableNode
163163
attributes:
164164
flags = 0
165-
frameSlot = 4 # %value_2
165+
frameSlot = 3 # %value_1
166166
type = FRAME_LOCAL
167167
IntegerFixnumLiteralNode
168168
attributes:
@@ -178,7 +178,7 @@ ast: |
178178
ReadLocalVariableNode
179179
attributes:
180180
flags = 0
181-
frameSlot = 3 # %value_1
181+
frameSlot = 4 # %value_2
182182
type = FRAME_LOCAL
183183
receiver =
184184
ReadLocalVariableNode

src/main/java/org/truffleruby/parser/YARPTranslator.java

Lines changed: 42 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,72 +1677,16 @@ public RubyNode visitInNode(Nodes.InNode node) {
16771677

16781678
@Override
16791679
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-
16921680
// arguments
16931681
final Nodes.Node[] arguments;
16941682
if (node.arguments != null) {
16951683
arguments = node.arguments.arguments;
16961684
} else {
16971685
arguments = Nodes.Node.EMPTY_ARRAY;
16981686
}
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-
}
17451687

1688+
final RubyNode rubyNode = translateIndexOrAndIndexAndWriteNodes(true, node.receiver, arguments, node.block,
1689+
node.value);
17461690
return assignPositionAndFlags(node, rubyNode);
17471691
}
17481692

@@ -1818,30 +1762,38 @@ public RubyNode visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) {
18181762

18191763
@Override
18201764
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`
18221783

18231784
// receiver (a) and arguments (b) should be executed only once
18241785
// that's why they are cached in local variables
18251786

1826-
assert node.receiver != null;
1787+
assert receiver != null;
18271788

18281789
// receiver
1829-
final var receiverExpression = new YARPExecutedOnceExpression("opelementassign", node.receiver, this);
1790+
final var receiverExpression = new YARPExecutedOnceExpression("opelementassign", receiver, this);
18301791
final var writeReceiveNode = receiverExpression.getWriteNode();
18311792
final var readReceiver = receiverExpression.getReadYARPNode();
18321793

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++) {
18451797
final var expression = new YARPExecutedOnceExpression("value", arguments[i], this);
18461798
writeArgumentsNodes[i] = expression.getWriteNode();
18471799
readArguments[i] = expression.getReadYARPNode();
@@ -1851,8 +1803,8 @@ public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) {
18511803
final RubyNode writeBlockNode;
18521804
final Nodes.BlockArgumentNode blockArgument;
18531805

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);
18561808
writeBlockNode = expression.getWriteNode();
18571809
Nodes.Node readBlock = expression.getReadYARPNode();
18581810
// imitate Nodes.CallNode structure with &block argument
@@ -1866,25 +1818,32 @@ public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) {
18661818
new Nodes.ArgumentsNode(readArguments, (short) 0, 0, 0), blockArgument, (short) 0, 0, 0);
18671819
final RubyNode readNode = read.accept(this);
18681820

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;
18721824

18731825
final Nodes.Node write = new Nodes.CallNode(readReceiver, "[]=",
18741826
new Nodes.ArgumentsNode(readArgumentsAndValue, (short) 0, 0, 0), blockArgument, (short) 0, 0, 0);
18751827
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+
18771836
final RubyNode writeArgumentsNode = sequence(Arrays.asList(writeArgumentsNodes));
18781837
final RubyNode rubyNode;
18791838

1880-
if (node.block != null) {
1839+
if (block != null) {
18811840
// add block argument write node
1882-
rubyNode = sequence(Arrays.asList(writeArgumentsNode, writeBlockNode, writeReceiveNode, orNode));
1841+
rubyNode = sequence(Arrays.asList(writeArgumentsNode, writeBlockNode, writeReceiveNode, operatorNode));
18831842
} else {
1884-
rubyNode = sequence(Arrays.asList(writeArgumentsNode, writeReceiveNode, orNode));
1843+
rubyNode = sequence(Arrays.asList(writeArgumentsNode, writeReceiveNode, operatorNode));
18851844
}
18861845

1887-
return assignPositionAndFlags(node, rubyNode);
1846+
return rubyNode;
18881847
}
18891848

18901849
@Override

0 commit comments

Comments
 (0)