|
82 | 82 | import org.truffleruby.language.control.NextNode;
|
83 | 83 | import org.truffleruby.language.control.NotNodeGen;
|
84 | 84 | import org.truffleruby.language.control.OnceNode;
|
| 85 | +import org.truffleruby.language.control.OrLazyValueDefinedNodeGen; |
85 | 86 | import org.truffleruby.language.control.OrNodeGen;
|
86 | 87 | import org.truffleruby.language.control.RaiseException;
|
87 | 88 | import org.truffleruby.language.control.RedoNode;
|
@@ -917,7 +918,13 @@ public RubyNode visitClassVariableOperatorWriteNode(Nodes.ClassVariableOperatorW
|
917 | 918 |
|
918 | 919 | @Override
|
919 | 920 | public RubyNode visitClassVariableOrWriteNode(Nodes.ClassVariableOrWriteNode node) {
|
920 |
| - return defaultVisit(node); |
| 921 | + int startOffset = node.startOffset; |
| 922 | + int length = node.length; |
| 923 | + var readNode = new Nodes.ClassVariableReadNode(node.name, startOffset, length).accept(this); |
| 924 | + var definedCheck = AndNodeGen.create(new DefinedNode(readNode), readNode); |
| 925 | + var writeNode = new Nodes.ClassVariableWriteNode(node.name, node.value, startOffset, length).accept(this); |
| 926 | + final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(definedCheck, writeNode); |
| 927 | + return assignPositionAndFlags(node, rubyNode); |
921 | 928 | }
|
922 | 929 |
|
923 | 930 | @Override
|
@@ -1259,7 +1266,13 @@ public RubyNode visitGlobalVariableOperatorWriteNode(Nodes.GlobalVariableOperato
|
1259 | 1266 |
|
1260 | 1267 | @Override
|
1261 | 1268 | public RubyNode visitGlobalVariableOrWriteNode(Nodes.GlobalVariableOrWriteNode node) {
|
1262 |
| - return defaultVisit(node); |
| 1269 | + int startOffset = node.startOffset; |
| 1270 | + int length = node.length; |
| 1271 | + var readNode = new Nodes.GlobalVariableReadNode(node.name, startOffset, length).accept(this); |
| 1272 | + var definedCheck = AndNodeGen.create(new DefinedNode(readNode), readNode); |
| 1273 | + var writeNode = new Nodes.GlobalVariableWriteNode(node.name, node.value, startOffset, length).accept(this); |
| 1274 | + final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(definedCheck, writeNode); |
| 1275 | + return assignPositionAndFlags(node, rubyNode); |
1263 | 1276 | }
|
1264 | 1277 |
|
1265 | 1278 | @Override
|
@@ -1419,21 +1432,25 @@ public RubyNode visitInstanceVariableOperatorWriteNode(Nodes.InstanceVariableOpe
|
1419 | 1432 |
|
1420 | 1433 | @Override
|
1421 | 1434 | public RubyNode visitInstanceVariableOrWriteNode(Nodes.InstanceVariableOrWriteNode node) {
|
1422 |
| - return defaultVisit(node); |
| 1435 | + // No need to check `defined?(@ivar)` before reading, as `@ivar` even if not set returns nil and does not have side effects |
| 1436 | + int startOffset = node.startOffset; |
| 1437 | + int length = node.length; |
| 1438 | + var readNode = new Nodes.InstanceVariableReadNode(node.name, startOffset, length).accept(this); |
| 1439 | + var writeNode = new Nodes.InstanceVariableWriteNode(node.name, node.value, startOffset, length).accept(this); |
| 1440 | + final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(readNode, writeNode); |
| 1441 | + return assignPositionAndFlags(node, rubyNode); |
1423 | 1442 | }
|
1424 | 1443 |
|
1425 | 1444 | @Override
|
1426 | 1445 | public RubyNode visitInstanceVariableReadNode(Nodes.InstanceVariableReadNode node) {
|
1427 | 1446 | final RubyNode rubyNode = new ReadInstanceVariableNode(node.name);
|
1428 |
| - |
1429 | 1447 | return assignPositionAndFlags(node, rubyNode);
|
1430 | 1448 | }
|
1431 | 1449 |
|
1432 | 1450 | @Override
|
1433 | 1451 | public RubyNode visitInstanceVariableWriteNode(Nodes.InstanceVariableWriteNode node) {
|
1434 | 1452 | final RubyNode value = node.value.accept(this);
|
1435 | 1453 | final RubyNode rubyNode = WriteInstanceVariableNodeGen.create(node.name, value);
|
1436 |
| - |
1437 | 1454 | return assignPositionAndFlags(node, rubyNode);
|
1438 | 1455 | }
|
1439 | 1456 |
|
@@ -1561,7 +1578,14 @@ public RubyNode visitLocalVariableOperatorWriteNode(Nodes.LocalVariableOperatorW
|
1561 | 1578 |
|
1562 | 1579 | @Override
|
1563 | 1580 | public RubyNode visitLocalVariableOrWriteNode(Nodes.LocalVariableOrWriteNode node) {
|
1564 |
| - return defaultVisit(node); |
| 1581 | + // No need to check `defined?(var)` before reading, as `var` even if not set returns nil and does not have side effects |
| 1582 | + int startOffset = node.startOffset; |
| 1583 | + int length = node.length; |
| 1584 | + var readNode = new Nodes.LocalVariableReadNode(node.name, node.depth, startOffset, length).accept(this); |
| 1585 | + var writeNode = new Nodes.LocalVariableWriteNode(node.name, node.depth, node.value, startOffset, length) |
| 1586 | + .accept(this); |
| 1587 | + final RubyNode rubyNode = OrLazyValueDefinedNodeGen.create(readNode, writeNode); |
| 1588 | + return assignPositionAndFlags(node, rubyNode); |
1565 | 1589 | }
|
1566 | 1590 |
|
1567 | 1591 | @Override
|
|
0 commit comments