@@ -2474,58 +2474,98 @@ public RubyNode visitOpElementAsgnNode(OpElementAsgnParseNode node) {
2474
2474
tempName ,
2475
2475
0 ,
2476
2476
node .getReceiverNode ());
2477
+ final ArrayList <ValueFromNode > argValues = argsToTemp (node );
2477
2478
2478
2479
final String op = node .getOperatorName ();
2479
2480
final boolean logicalOperation = op .equals ("&&" ) || op .equals ("||" );
2480
2481
2481
2482
if (logicalOperation ) {
2482
- final ParseNode write = write (node , readReceiverFromTemp , value );
2483
- final ParseNode operation = operation (node , readReceiverFromTemp , op , write );
2483
+ final ParseNode write = write (node , readReceiverFromTemp , argValues , value );
2484
+ final ParseNode operation = operation (node , readReceiverFromTemp , argValues , op , write );
2484
2485
2485
- return block (node , writeReceiverToTemp , operation );
2486
+ return block (node , writeReceiverToTemp , argValues , operation );
2486
2487
} else {
2487
- final ParseNode operation = operation (node , readReceiverFromTemp , op , value );
2488
- final ParseNode write = write (node , readReceiverFromTemp , operation );
2488
+ final ParseNode operation = operation (node , readReceiverFromTemp , argValues , op , value );
2489
+ final ParseNode write = write (node , readReceiverFromTemp , argValues , operation );
2489
2490
2490
- return block (node , writeReceiverToTemp , write );
2491
+ return block (node , writeReceiverToTemp , argValues , write );
2491
2492
}
2492
2493
}
2493
2494
2494
- private RubyNode block (OpElementAsgnParseNode node , ParseNode writeReceiverToTemp , ParseNode main ) {
2495
+ private RubyNode block (OpElementAsgnParseNode node , ParseNode writeReceiverToTemp ,
2496
+ ArrayList <ValueFromNode > argValues , ParseNode main ) {
2495
2497
final BlockParseNode block = new BlockParseNode (node .getPosition ());
2496
2498
block .add (writeReceiverToTemp );
2497
2499
block .add (main );
2498
2500
2499
- final RubyNode ret = block .accept (this );
2501
+ /* prepareAndThen is going to take an argument, and the action that comes after it, and return a node that does
2502
+ * both of those things. We start off with ret being the block (our final action) and so the first node we
2503
+ * should produce is one that evaluates the last argument, and then the block. The final value of ret should be
2504
+ * a node that evaluates the first argument, and then any other arguments, and then the block. So, we must go
2505
+ * through the argument list in reverse order. */
2506
+ RubyNode ret = block .accept (this );
2507
+ var listIterator = argValues .listIterator (argValues .size ());
2508
+ while (listIterator .hasPrevious ()) {
2509
+ ret = listIterator .previous ().prepareAndThen (node .getPosition (), ret );
2510
+ }
2500
2511
return addNewlineIfNeeded (node , ret );
2501
2512
}
2502
2513
2503
- private ParseNode write (OpElementAsgnParseNode node , ParseNode readReceiverFromTemp , ParseNode value ) {
2504
- final ParseNode readArguments = node . getArgsNode ();
2514
+ private ParseNode write (OpElementAsgnParseNode node , ParseNode readReceiverFromTemp ,
2515
+ ArrayList < ValueFromNode > argValues , ParseNode value ) {
2505
2516
final ParseNode writeArguments ;
2506
2517
// Like ParserSupport#arg_add, but copy the first node
2507
- if (readArguments instanceof ArrayParseNode ) {
2518
+ if (node . getArgsNode () instanceof ArrayParseNode ) {
2508
2519
final ArrayParseNode readArgsCopy = new ArrayParseNode (node .getPosition ());
2509
- readArgsCopy .addAll ((ArrayParseNode ) readArguments ).add (value );
2520
+ for (var arg : argValues ) {
2521
+ readArgsCopy .add (arg .get (node .getPosition ()));
2522
+ }
2523
+ readArgsCopy .add (value );
2510
2524
writeArguments = readArgsCopy ;
2511
2525
} else {
2512
- writeArguments = new ArgsPushParseNode (node .getPosition (), readArguments , value );
2526
+ writeArguments = new ArgsPushParseNode (node .getPosition (), argValues . get ( 0 ). get ( node . getPosition ()) , value );
2513
2527
}
2514
2528
2515
2529
return new AttrAssignParseNode (node .getPosition (), readReceiverFromTemp , "[]=" , writeArguments , false );
2516
2530
}
2517
2531
2532
+ private ArrayList <ValueFromNode > argsToTemp (OpElementAsgnParseNode node ) {
2533
+ ArrayList <ValueFromNode > argValues = new ArrayList <>();
2534
+
2535
+ final ParseNode readArguments = node .getArgsNode ();
2536
+ if (readArguments instanceof ArrayParseNode ) {
2537
+ for (ParseNode child : ((ArrayParseNode ) readArguments ).children ()) {
2538
+ argValues .add (ValueFromNode .valueFromNode (this , child ));
2539
+ }
2540
+ } else {
2541
+ argValues .add (ValueFromNode .valueFromNode (this , readArguments ));
2542
+ }
2543
+
2544
+ return argValues ;
2545
+ }
2546
+
2518
2547
private ParseNode operation (
2519
2548
OpElementAsgnParseNode node ,
2520
2549
ParseNode readReceiverFromTemp ,
2550
+ ArrayList <ValueFromNode > argValues ,
2521
2551
String op ,
2522
2552
ParseNode right ) {
2553
+ ParseNode readArguments ;
2554
+ if (node .getArgsNode () instanceof ArrayParseNode ) {
2555
+ final ArrayParseNode readArgsArray = new ArrayParseNode (node .getPosition ());
2556
+ for (var arg : argValues ) {
2557
+ readArgsArray .add (arg .get (node .getPosition ()));
2558
+ }
2559
+ readArguments = readArgsArray ;
2560
+ } else {
2561
+ readArguments = argValues .get (0 ).get (node .getPosition ());
2562
+ }
2523
2563
2524
2564
final ParseNode read = new CallParseNode (
2525
2565
node .getPosition (),
2526
2566
readReceiverFromTemp ,
2527
2567
"[]" ,
2528
- node . getArgsNode () ,
2568
+ readArguments ,
2529
2569
null );
2530
2570
ParseNode operation ;
2531
2571
switch (op ) {
0 commit comments