Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5abcb5a

Browse files
committed
Handle => operator for rightward assignment
1 parent d4d7f0b commit 5abcb5a

File tree

2 files changed

+76
-2
lines changed

2 files changed

+76
-2
lines changed

lib/syntax_tree/compiler.rb

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,11 +1394,13 @@ def visit_range(node)
13941394
end
13951395

13961396
def visit_rassign(node)
1397+
iseq.putnil
1398+
13971399
if node.operator.is_a?(Kw)
1398-
iseq.putnil
1400+
jumps = []
1401+
13991402
visit(node.value)
14001403
iseq.dup
1401-
jumps = []
14021404

14031405
case node.pattern
14041406
when VarField
@@ -1417,6 +1419,77 @@ def visit_rassign(node)
14171419
jumps.each { |jump| jump[1] = iseq.label }
14181420
iseq.adjuststack(2)
14191421
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
14201493
end
14211494
end
14221495

test/compiler_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ class CompilerTest < Minitest::Test
423423
"foo in [bar, baz]",
424424
"foo in [1, 2, 3, bar, 4, 5, 6, baz]",
425425
"foo in Foo[1, 2, 3, bar, 4, 5, 6, baz]",
426+
"foo => bar"
426427
]
427428

428429
# These are the combinations of instructions that we're going to test.

0 commit comments

Comments
 (0)