@@ -1394,11 +1394,13 @@ def visit_range(node)
1394
1394
end
1395
1395
1396
1396
def visit_rassign ( node )
1397
+ iseq . putnil
1398
+
1397
1399
if node . operator . is_a? ( Kw )
1398
- iseq . putnil
1400
+ jumps = [ ]
1401
+
1399
1402
visit ( node . value )
1400
1403
iseq . dup
1401
- jumps = [ ]
1402
1404
1403
1405
case node . pattern
1404
1406
when VarField
@@ -1417,6 +1419,77 @@ def visit_rassign(node)
1417
1419
jumps . each { |jump | jump [ 1 ] = iseq . label }
1418
1420
iseq . adjuststack ( 2 )
1419
1421
iseq . putobject ( true )
1422
+ else
1423
+ jumps_to_match = [ ]
1424
+
1425
+ iseq . putnil
1426
+ iseq . putobject ( false )
1427
+ iseq . putnil
1428
+ iseq . putnil
1429
+ visit ( node . value )
1430
+ iseq . dup
1431
+
1432
+ # Visit the pattern. If it matches,
1433
+ case node . pattern
1434
+ when VarField
1435
+ lookup = visit ( node . pattern )
1436
+ iseq . setlocal ( lookup . index , lookup . level )
1437
+ jumps_to_match << iseq . jump ( -1 )
1438
+ else
1439
+ jumps_to_match . concat ( visit ( node . pattern ) )
1440
+ end
1441
+
1442
+ # First we're going to push the core onto the stack, then we'll check if
1443
+ # the value to match is truthy. If it is, we'll jump down to raise
1444
+ # NoMatchingPatternKeyError. Otherwise we'll raise
1445
+ # NoMatchingPatternError.
1446
+ iseq . putspecialobject ( YARV ::VM_SPECIAL_OBJECT_VMCORE )
1447
+ iseq . topn ( 4 )
1448
+ branchif_no_key = iseq . branchif ( -1 )
1449
+
1450
+ # Here we're going to raise NoMatchingPatternError.
1451
+ iseq . putobject ( NoMatchingPatternError )
1452
+ iseq . putspecialobject ( YARV ::VM_SPECIAL_OBJECT_VMCORE )
1453
+ iseq . putobject ( "%p: %s" )
1454
+ iseq . topn ( 4 )
1455
+ iseq . topn ( 7 )
1456
+ iseq . send ( :"core#sprintf" , 3 )
1457
+ iseq . send ( :"core#raise" , 2 )
1458
+ jump_to_exit = iseq . jump ( -1 )
1459
+
1460
+ # Here we're going to raise NoMatchingPatternKeyError.
1461
+ branchif_no_key . patch! ( iseq )
1462
+ iseq . putobject ( NoMatchingPatternKeyError )
1463
+ iseq . putspecialobject ( YARV ::VM_SPECIAL_OBJECT_VMCORE )
1464
+ iseq . putobject ( "%p: %s" )
1465
+ iseq . topn ( 4 )
1466
+ iseq . topn ( 7 )
1467
+ iseq . send ( :"core#sprintf" , 3 )
1468
+ iseq . topn ( 7 )
1469
+ iseq . topn ( 9 )
1470
+
1471
+ # Super special behavior here because of the weird kw_arg handling.
1472
+ iseq . stack . change_by ( -( 1 + 1 ) + 1 )
1473
+ call_data = { mid : :new , flag : YARV ::VM_CALL_KWARG , orig_argc : 1 , kw_arg : [ :matchee , :key ] }
1474
+
1475
+ if specialized_instruction
1476
+ iseq . push ( [ :opt_send_without_block , call_data ] )
1477
+ else
1478
+ iseq . push ( [ :send , call_data , nil ] )
1479
+ end
1480
+
1481
+ iseq . send ( :"core#raise" , 1 )
1482
+
1483
+ # This runs when the pattern fails to match.
1484
+ jump_to_exit [ 1 ] = iseq . label
1485
+ iseq . adjuststack ( 7 )
1486
+ iseq . putnil
1487
+ iseq . leave
1488
+
1489
+ # This runs when the pattern matches successfully.
1490
+ jumps_to_match . each { |jump | jump [ 1 ] = iseq . label }
1491
+ iseq . adjuststack ( 6 )
1492
+ iseq . putnil
1420
1493
end
1421
1494
end
1422
1495
0 commit comments