Skip to content

Commit 9872ae4

Browse files
committed
Add comments for assignment operator visit methods
1 parent f7546af commit 9872ae4

File tree

1 file changed

+83
-12
lines changed

1 file changed

+83
-12
lines changed

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

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,9 @@ public RubyNode visitBreakNode(Nodes.BreakNode node) {
586586

587587
@Override
588588
public RubyNode visitCallAndWriteNode(Nodes.CallAndWriteNode node) {
589+
// `a.b &&= value` is translated into `a.b || a.b = value`
590+
// receiver (a) should be executed only once that's why it's cached into a local variable
591+
589592
assert node.receiver != null; // without receiver `a &&= b` leads to Nodes.LocalVariableAndWriteNode
590593

591594
final var receiverExpression = new YARPExecutedOnceExpression("value", node.receiver, this);
@@ -787,6 +790,9 @@ private boolean isAttrAssign(String methodName) {
787790

788791
@Override
789792
public RubyNode visitCallOperatorWriteNode(Nodes.CallOperatorWriteNode node) {
793+
// e.g. `a.b += value` is translated into `a.b = a.b + value`,
794+
// receiver (a) should be executed only once - that's why it's cached in a local variable
795+
790796
assert node.receiver != null; // without receiver `a += b` leads to Nodes.LocalVariableOperatorWriteNode
791797

792798
final var receiverExpression = new YARPExecutedOnceExpression("value", node.receiver, this);
@@ -817,6 +823,9 @@ public RubyNode visitCallOperatorWriteNode(Nodes.CallOperatorWriteNode node) {
817823

818824
@Override
819825
public RubyNode visitCallOrWriteNode(Nodes.CallOrWriteNode node) {
826+
// `a.b ||= value` is translated into `a.b || a.b = value`
827+
// receiver (a) should be executed only once that's why it's cached into a local variable
828+
820829
assert node.receiver != null; // without receiver `a ||= b` leads to Nodes.LocalVariableOrWriteNode
821830

822831
final var receiverExpression = new YARPExecutedOnceExpression("value", node.receiver, this);
@@ -1019,6 +1028,9 @@ public RubyNode visitClassNode(Nodes.ClassNode node) {
10191028

10201029
@Override
10211030
public RubyNode visitClassVariableAndWriteNode(Nodes.ClassVariableAndWriteNode node) {
1031+
// `@@a &&= value` is translated into @@a && @@a = value`
1032+
// don't check whether variable is defined so exception will be raised otherwise
1033+
10221034
int startOffset = node.startOffset;
10231035
int length = node.length;
10241036

@@ -1032,6 +1044,9 @@ public RubyNode visitClassVariableAndWriteNode(Nodes.ClassVariableAndWriteNode n
10321044

10331045
@Override
10341046
public RubyNode visitClassVariableOperatorWriteNode(Nodes.ClassVariableOperatorWriteNode node) {
1047+
// e.g. `@@a += value` is translated into @@a = @@a + value`
1048+
// don't check whether variable is initialized so exception will be raised otherwise
1049+
10351050
int startOffset = node.startOffset;
10361051
int length = node.length;
10371052
var readNode = new Nodes.ClassVariableReadNode(node.name, startOffset, length);
@@ -1042,13 +1057,17 @@ public RubyNode visitClassVariableOperatorWriteNode(Nodes.ClassVariableOperatorW
10421057

10431058
@Override
10441059
public RubyNode visitClassVariableOrWriteNode(Nodes.ClassVariableOrWriteNode node) {
1045-
// `@@a ||= value` is translated into `(defined?(@@a) && @@a) || @@a = value`
1060+
// `@@a ||= value` is translated into (defined?(@@a) && @@a) || @@a = value`
1061+
// so we check whether variable is defined and no exception will be raised otherwise
1062+
10461063
int startOffset = node.startOffset;
10471064
int length = node.length;
1065+
10481066
var writeNode = new Nodes.ClassVariableWriteNode(node.name, node.value, startOffset, length).accept(this);
10491067
var readNode = new Nodes.ClassVariableReadNode(node.name, startOffset, length).accept(this);
1050-
var definedCheck = AndNodeGen.create(new DefinedNode(readNode), readNode);
1051-
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(definedCheck, writeNode);
1068+
var andNode = AndNodeGen.create(new DefinedNode(readNode), readNode);
1069+
1070+
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(andNode, writeNode);
10521071
return assignPositionAndFlags(node, rubyNode);
10531072
}
10541073

@@ -1084,6 +1103,9 @@ public RubyNode visitClassVariableTargetNode(Nodes.ClassVariableTargetNode node)
10841103

10851104
@Override
10861105
public RubyNode visitConstantAndWriteNode(Nodes.ConstantAndWriteNode node) {
1106+
// `A &&= value` is translated into `A && A = value`
1107+
// don't check whether constant is defined and so exception will be raised otherwise
1108+
10871109
int startOffset = node.startOffset;
10881110
int length = node.length;
10891111

@@ -1097,6 +1119,9 @@ public RubyNode visitConstantAndWriteNode(Nodes.ConstantAndWriteNode node) {
10971119

10981120
@Override
10991121
public RubyNode visitConstantOperatorWriteNode(Nodes.ConstantOperatorWriteNode node) {
1122+
// e.g. `A += value` is translated into A = A + value`
1123+
// don't check whether constant is initialized so warnings will be emitted otherwise
1124+
11001125
int startOffset = node.startOffset;
11011126
int length = node.length;
11021127

@@ -1112,20 +1137,24 @@ public RubyNode visitConstantOperatorWriteNode(Nodes.ConstantOperatorWriteNode n
11121137
@Override
11131138
public RubyNode visitConstantOrWriteNode(Nodes.ConstantOrWriteNode node) {
11141139
// `A ||= value` is translated into `(defined?(A) && A) || A = value`
1140+
// so we check whether constant is defined and no exception will be raised otherwise
11151141

11161142
int startOffset = node.startOffset;
11171143
int length = node.length;
11181144

11191145
var writeNode = new Nodes.ConstantWriteNode(node.name, node.value, startOffset, length).accept(this);
11201146
var readNode = new Nodes.ConstantReadNode(node.name, startOffset, length).accept(this);
1121-
var definedCheck = AndNodeGen.create(new DefinedNode(readNode), readNode);
1147+
var andNode = AndNodeGen.create(new DefinedNode(readNode), readNode);
11221148

1123-
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(definedCheck, writeNode);
1149+
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(andNode, writeNode);
11241150
return assignPositionAndFlags(node, rubyNode);
11251151
}
11261152

11271153
@Override
11281154
public RubyNode visitConstantPathAndWriteNode(Nodes.ConstantPathAndWriteNode node) {
1155+
// `A::B &&= value` is translated into `A::B && A::B = value`
1156+
// don't check whether constant is defined and so exception will be raised otherwise
1157+
11291158
var value = node.value.accept(this);
11301159

11311160
var readNode = (ReadConstantNode) node.target.accept(this);
@@ -1161,6 +1190,9 @@ public RubyNode visitConstantPathNode(Nodes.ConstantPathNode node) {
11611190

11621191
@Override
11631192
public RubyNode visitConstantPathOperatorWriteNode(Nodes.ConstantPathOperatorWriteNode node) {
1193+
// e.g. `A::B += value` is translated into A::B = A::B + value`
1194+
// don't check whether constant is initialized so warnings will be emitted otherwise
1195+
11641196
int startOffset = node.startOffset;
11651197
int length = node.length;
11661198

@@ -1176,6 +1208,12 @@ public RubyNode visitConstantPathOperatorWriteNode(Nodes.ConstantPathOperatorWri
11761208

11771209
@Override
11781210
public RubyNode visitConstantPathOrWriteNode(Nodes.ConstantPathOrWriteNode node) {
1211+
// `A::B ||= value` is translated into `(defined?(A::B) && A::B) || A::B = value`
1212+
// check whether constant is defined so no exception will be raised otherwise
1213+
1214+
// The defined? check is implemented in OrAssignConstantNodeGen and isn't straightforward
1215+
// because of constants autoloading.
1216+
11791217
var value = node.value.accept(this);
11801218

11811219
var readNode = (ReadConstantNode) node.target.accept(this);
@@ -1464,6 +1502,9 @@ public RubyNode visitForwardingSuperNode(Nodes.ForwardingSuperNode node) {
14641502

14651503
@Override
14661504
public RubyNode visitGlobalVariableAndWriteNode(Nodes.GlobalVariableAndWriteNode node) {
1505+
// `$a &&= value` is translated into `$a && $a = value`
1506+
// don't check whether variable is defined so a warning will be emitted otherwise
1507+
14671508
int startOffset = node.startOffset;
14681509
int length = node.length;
14691510

@@ -1477,6 +1518,9 @@ public RubyNode visitGlobalVariableAndWriteNode(Nodes.GlobalVariableAndWriteNode
14771518

14781519
@Override
14791520
public RubyNode visitGlobalVariableOperatorWriteNode(Nodes.GlobalVariableOperatorWriteNode node) {
1521+
// e.g. `$a += value` is translated into $a = $a + value`
1522+
// don't check whether variable is initialized so exception will be raised otherwise
1523+
14801524
int startOffset = node.startOffset;
14811525
int length = node.length;
14821526
var readNode = new Nodes.GlobalVariableReadNode(node.name, startOffset, length);
@@ -1488,11 +1532,15 @@ public RubyNode visitGlobalVariableOperatorWriteNode(Nodes.GlobalVariableOperato
14881532
@Override
14891533
public RubyNode visitGlobalVariableOrWriteNode(Nodes.GlobalVariableOrWriteNode node) {
14901534
// `$a ||= value` is translated into `(defined?($a) && $a) || $a = value`
1535+
// check whether variable is defined so no warnings will be emitted otherwise
1536+
14911537
int startOffset = node.startOffset;
14921538
int length = node.length;
1539+
14931540
var writeNode = new Nodes.GlobalVariableWriteNode(node.name, node.value, startOffset, length).accept(this);
14941541
var readNode = new Nodes.GlobalVariableReadNode(node.name, startOffset, length).accept(this);
14951542
var definedCheck = AndNodeGen.create(new DefinedNode(readNode), readNode);
1543+
14961544
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(definedCheck, writeNode);
14971545
return assignPositionAndFlags(node, rubyNode);
14981546
}
@@ -1629,12 +1677,13 @@ public RubyNode visitInNode(Nodes.InNode node) {
16291677

16301678
@Override
16311679
public RubyNode visitIndexAndWriteNode(Nodes.IndexAndWriteNode node) {
1632-
assert node.receiver != null;
1633-
16341680
// `a[b] &&= c` is translated into `a[b] && a[b] = c`
1681+
16351682
// receiver (a) and arguments (b) should be executed only once
16361683
// that's why they are cached in local variables
16371684

1685+
assert node.receiver != null;
1686+
16381687
// receiver
16391688
final var receiverExpression = new YARPExecutedOnceExpression("opelementassign", node.receiver, this);
16401689
final var writeReceiveNode = receiverExpression.getWriteNode();
@@ -1699,12 +1748,13 @@ public RubyNode visitIndexAndWriteNode(Nodes.IndexAndWriteNode node) {
16991748

17001749
@Override
17011750
public RubyNode visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) {
1702-
assert node.receiver != null;
1751+
// e.g. `a[b] += value` is translated into `a[b] = a[b] + value`,
17031752

1704-
// `a[b] += c` is translated into `a[b] = a[b] + c`
1705-
// receiver (a) and arguments (b) should be executed only once
1753+
// receiver (a) and arguments (b) should be executed only once -
17061754
// that's why they are cached in local variables
17071755

1756+
assert node.receiver != null;
1757+
17081758
// receiver
17091759
final var receiverExpression = new YARPExecutedOnceExpression("opelementassign", node.receiver, this);
17101760
final var writeReceiveNode = receiverExpression.getWriteNode();
@@ -1768,12 +1818,13 @@ public RubyNode visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) {
17681818

17691819
@Override
17701820
public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) {
1771-
assert node.receiver != null;
1772-
17731821
// `a[b] ||= c` is translated into `a[b] || a[b] = c`
1822+
17741823
// receiver (a) and arguments (b) should be executed only once
17751824
// that's why they are cached in local variables
17761825

1826+
assert node.receiver != null;
1827+
17771828
// receiver
17781829
final var receiverExpression = new YARPExecutedOnceExpression("opelementassign", node.receiver, this);
17791830
final var writeReceiveNode = receiverExpression.getWriteNode();
@@ -1838,6 +1889,10 @@ public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) {
18381889

18391890
@Override
18401891
public RubyNode visitInstanceVariableAndWriteNode(Nodes.InstanceVariableAndWriteNode node) {
1892+
// `@a &&= value` is translated into `@a && @a = value`
1893+
// don't check whether variable is initialized because even if an instance variable
1894+
// is not set then it returns nil and does not have side effects (warnings or exceptions)
1895+
18411896
int startOffset = node.startOffset;
18421897
int length = node.length;
18431898

@@ -1851,8 +1906,12 @@ public RubyNode visitInstanceVariableAndWriteNode(Nodes.InstanceVariableAndWrite
18511906

18521907
@Override
18531908
public RubyNode visitInstanceVariableOperatorWriteNode(Nodes.InstanceVariableOperatorWriteNode node) {
1909+
// e.g. `@a += value` is translated into @a = @a + value`
1910+
// don't check whether variable is defined so exception will be raised otherwise
1911+
18541912
int startOffset = node.startOffset;
18551913
int length = node.length;
1914+
18561915
var readNode = new Nodes.InstanceVariableReadNode(node.name, startOffset, length);
18571916
var desugared = new Nodes.InstanceVariableWriteNode(node.name,
18581917
callNode(node, readNode, node.operator, node.value), startOffset, length);
@@ -1865,10 +1924,13 @@ public RubyNode visitInstanceVariableOrWriteNode(Nodes.InstanceVariableOrWriteNo
18651924

18661925
// No need to check `defined?(@ivar)` before reading, as `@ivar` even if not set returns nil and does not have
18671926
// side effects (warnings or exceptions)
1927+
18681928
int startOffset = node.startOffset;
18691929
int length = node.length;
1930+
18701931
var writeNode = new Nodes.InstanceVariableWriteNode(node.name, node.value, startOffset, length).accept(this);
18711932
var readNode = new Nodes.InstanceVariableReadNode(node.name, startOffset, length).accept(this);
1933+
18721934
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(readNode, writeNode);
18731935
return assignPositionAndFlags(node, rubyNode);
18741936
}
@@ -2025,6 +2087,10 @@ public RubyNode visitLocalVariableReadNode(Nodes.LocalVariableReadNode node) {
20252087

20262088
@Override
20272089
public RubyNode visitLocalVariableAndWriteNode(Nodes.LocalVariableAndWriteNode node) {
2090+
// `a &&= value` is translated into `a && a = value`
2091+
// don't check whether variable is initialized because even if a local variable
2092+
// is not set then it returns nil and does not have side effects (warnings or exceptions)
2093+
20282094
int startOffset = node.startOffset;
20292095
int length = node.length;
20302096

@@ -2039,6 +2105,9 @@ public RubyNode visitLocalVariableAndWriteNode(Nodes.LocalVariableAndWriteNode n
20392105

20402106
@Override
20412107
public RubyNode visitLocalVariableOperatorWriteNode(Nodes.LocalVariableOperatorWriteNode node) {
2108+
// e.g. `a += value` is translated into a = a + value`
2109+
// don't check whether variable is initialized so exception will be raised otherwise
2110+
20422111
int startOffset = node.startOffset;
20432112
int length = node.length;
20442113
var readNode = new Nodes.LocalVariableReadNode(node.name, node.depth, startOffset, length);
@@ -2055,9 +2124,11 @@ public RubyNode visitLocalVariableOrWriteNode(Nodes.LocalVariableOrWriteNode nod
20552124
// side effects (warnings or exceptions)
20562125
int startOffset = node.startOffset;
20572126
int length = node.length;
2127+
20582128
var writeNode = new Nodes.LocalVariableWriteNode(node.name, node.depth, node.value, startOffset, length)
20592129
.accept(this);
20602130
var readNode = new Nodes.LocalVariableReadNode(node.name, node.depth, startOffset, length).accept(this);
2131+
20612132
final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(readNode, writeNode);
20622133
return assignPositionAndFlags(node, rubyNode);
20632134
}

0 commit comments

Comments
 (0)