def test_loop_stack_nested(): stack = LoopStack([ LoopTree.CARTESIAN(3, [ LoopTree.LEAF(2), LoopTree.LEAF(4), ]), ]) stack.start_loop() for j in range(3): assert not stack.next() stack.start_loop() for i in range(2): assert not stack.next() assert stack.next() stack.start_loop() for i in range(4): assert not stack.next() assert stack.next() assert stack.next() with pytest.raises(ValueError) as ex: stack.next() assert 'No current loop' == str(ex.value)
def test_nested_loop(): vm = VM( LoopStack([ LoopTree.CARTESIAN(3, [ LoopTree.LEAF(3), LoopTree.LEAF(5), ]), ]), num_locals=0, ram_size=0, ) ins = InsLoopSpecified( Block([ InsLoopSpecified( Block([ InsArith([0], True, ArithMode.CHECKED, lambda n: n - 1), ])), InsLoopSpecified( Block([ InsArith([0], True, ArithMode.CHECKED, lambda n: n + 1), ])), InsArith([0], True, ArithMode.CHECKED, lambda n: n * 2), ])) ins.run(vm) result = vm.belt().get_num(0).value.expect_int() assert result == 28
def test_loop_stack_leaf(): stack = LoopStack([ LoopTree.LEAF(9), ]) stack.start_loop() for _ in range(9): assert not stack.next() assert stack.next() with pytest.raises(ValueError) as ex: stack.next() assert 'No current loop' == str(ex.value)
def test_loop_stack_nested2(): stack = LoopStack([ LoopTree.CARTESIAN(2, [ LoopTree.ROLLED_OUT([ [LoopTree.LEAF(3), LoopTree.LEAF(1)], [LoopTree.LEAF(4), LoopTree.LEAF(2)], ]), ]), ]) stack.start_loop() for _ in range(2): assert not stack.next() stack.start_loop() for loop1, loop2 in [(3, 1), (4, 2)]: assert not stack.next() stack.start_loop() for _ in range(loop1): assert not stack.next() assert stack.next() stack.start_loop() for _ in range(loop2): assert not stack.next() assert stack.next() assert stack.next() assert stack.next() with pytest.raises(ValueError) as ex: stack.next() assert 'No current loop' == str(ex.value)
def test_two_simple_loops_break(): vm = VM( LoopStack([ LoopTree.LEAF(16), LoopTree.LEAF(16), ]), num_locals=1, ram_size=0, ) ins = Block([ InsLoopSpecified( Block([ InsArith([0], False, ArithMode.CHECKED, lambda n: n + 1), InsLocalSet(0), InsConst(BeltNum(DataType.I8, Integer(3))), InsRel(a_idx=0, b_idx=1, is_signed=False, op=lambda a, b: a < b), InsBrIf(condition_idx=0, br_depth=1), InsLocalGet(0), ])), InsLoopSpecified( Block([ InsArith([0], False, ArithMode.CHECKED, lambda n: n + 1), InsLocalSet(0), InsConst(BeltNum(DataType.I8, Integer(7))), InsRel(a_idx=0, b_idx=1, is_signed=False, op=lambda a, b: a < b), InsBrIf(condition_idx=0, br_depth=1), InsLocalGet(0), ])), ]) ins.run(vm) belt = [vm.belt().get_num(i).value.expect_int() for i in range(Belt.SIZE)] assert belt == [1, 7, 8, 7, 0, 7, 7, 6, 0, 7, 6, 5, 0, 7, 5, 4] assert vm.local(0).value.expect_int() == 8
def test_simple_loop(): vm = VM( LoopStack([ LoopTree.LEAF(8), ]), num_locals=0, ram_size=0, ) ins = InsLoopSpecified( Block([ InsArith([0], False, ArithMode.CHECKED, lambda n: n + 1), ])) ins.run(vm) result = vm.belt().get_num(0).value.expect_int() assert result == 8
def test_simple_loop_break(): vm = VM( LoopStack([ LoopTree.LEAF(8), ]), num_locals=0, ram_size=0, ) ins = InsLoopSpecified( Block([ InsBrIf(condition_idx=0, br_depth=1), InsArith([2], False, ArithMode.CHECKED, lambda n: n + 1), InsConst(BeltNum(DataType.I8, Integer(3))), InsRel(a_idx=0, b_idx=1, is_signed=False, op=lambda a, b: a < b), ])) ins.run(vm) belt = [vm.belt().get_num(i).value.expect_int() for i in range(Belt.SIZE)] assert belt == [1, 3, 4, 0, 3, 3, 0, 3, 2, 0, 3, 1, 0, 0, 0, 0]
def test_fib_loop(): vm = VM( LoopStack([ LoopTree.LEAF(16), ]), num_locals=0, ram_size=0, ) ins = Block([ InsConst(BeltNum(DataType.I64, Integer(1))), InsLoopSpecified( Block([ InsArith([0, 1], False, ArithMode.CHECKED, int.__add__), ])), ]) ins.run(vm) belt = [vm.belt().get_num(i).value.expect_int() for i in range(Belt.SIZE)] assert belt == [ 1597, 987, 610, 377, 233, 144, 89, 55, 34, 21, 13, 8, 5, 3, 2, 1 ]
def test_nested_loop_break(): vm = VM( LoopStack([ LoopTree.CARTESIAN(3, [ LoopTree.LEAF(3), LoopTree.LEAF(5), ]), LoopTree.LEAF(2), ]), num_locals=1, ram_size=0, ) ins = Block([ InsLoopSpecified( Block([ # decrement 3 times InsLoopSpecified( Block([ InsArith([0], True, ArithMode.CHECKED, lambda n: n - 1), ])), # increment 5 times; if number reaches 10, terminate outer loop InsLoopSpecified( Block([ InsArith([0], True, ArithMode.CHECKED, lambda n: n + 1), InsLocalSet(0), InsConst(BeltNum(DataType.I8, Integer(10))), InsRel(0, 1, True, lambda a, b: a < b), InsBrIf(0, 2), InsLocalGet(0), ])), # double InsArith([0], True, ArithMode.CHECKED, lambda n: n * 2), ])), InsLocalGet(0), InsLoopSpecified( Block([ InsArith([0], True, ArithMode.CHECKED, lambda n: n + 2), ])), ]) ins.run(vm) belt = [vm.belt().get_num(i).value.expect_int() for i in range(Belt.SIZE)] assert belt == [ 15, 13, # 2 times +2 11, # local get 1, 10, 11, # final loop iteration 10, 0, 10, 10, # second to last loop iteration 9, 10, 11, # decrementing loop 12, # *2 6, 0 ] # local get, rel
def test_parse_complex_tree(): assert parse_loop_trees( io.BytesIO(bytes.fromhex( '020403' + ( '0009' '010302' + ( '0008' '0001' '0000' '0005' '0007' '0002' ) + '020601' '0003' ) + '010201' + ( '000a' '0002' ) )) ) == [ LoopTree.CARTESIAN(4, [ LoopTree.LEAF(9), LoopTree.ROLLED_OUT([ [LoopTree.LEAF(8), LoopTree.LEAF(1)], [LoopTree.LEAF(0), LoopTree.LEAF(5)], [LoopTree.LEAF(7), LoopTree.LEAF(2)], ]), LoopTree.CARTESIAN(6, [ LoopTree.LEAF(3), ]), ]), LoopTree.ROLLED_OUT([ [LoopTree.LEAF(0xa)], [LoopTree.LEAF(2)], ]), ]
def test_parse_multi_leaf(): assert parse_loop_trees(io.BytesIO(bytes.fromhex('000300ff01007f'))) == \ [LoopTree.LEAF(3), LoopTree.LEAF(leb128.u.decode(b'\xff\x01')), LoopTree.LEAF(0x7f)]
def test_parse_single_leaf(): assert parse_loop_trees(io.BytesIO(bytes.fromhex('0003'))) == \ [LoopTree.LEAF(3)]
def test_loop_stack_complex_no_break(): stack = LoopStack([ LoopTree.CARTESIAN(4, [ LoopTree.LEAF(9), LoopTree.ROLLED_OUT([ [LoopTree.LEAF(8), LoopTree.LEAF(1)], [LoopTree.LEAF(0), LoopTree.LEAF(5)], [LoopTree.LEAF(7), LoopTree.LEAF(2)], ]), LoopTree.CARTESIAN(6, [ LoopTree.LEAF(3), ]), ]), LoopTree.ROLLED_OUT([ [LoopTree.LEAF(10)], [LoopTree.LEAF(2)], ]), ]) stack.start_loop() for _ in range(4): assert not stack.next() stack.start_loop() for _ in range(9): assert not stack.next() assert stack.next() stack.start_loop() for loop1, loop2 in [(8, 1), (0, 5), (7, 2)]: assert not stack.next() stack.start_loop() for _ in range(loop1): assert not stack.next() assert stack.next() stack.start_loop() for _ in range(loop2): assert not stack.next() assert stack.next() assert stack.next() stack.start_loop() for _ in range(6): assert not stack.next() stack.start_loop() for _ in range(3): assert not stack.next() assert stack.next() assert stack.next() assert stack.next() stack.start_loop() for loop in [10, 2]: assert not stack.next() stack.start_loop() for _ in range(loop): assert not stack.next() assert stack.next() assert stack.next() with pytest.raises(ValueError) as ex: stack.next() assert 'No current loop' == str(ex.value)