def run(self, vm: VM) -> Optional['Break']: a_num = vm.belt().get_num(self._a_idx) b_num = vm.belt().get_num(self._b_idx) a = a_num.to_signed(self._is_signed).to_int() b = b_num.to_signed(self._is_signed).to_int() if a is None or b is None: vm.belt().push(BeltNum(DataType.I8, Integer(None))) else: result = self._op(a, b) vm.belt().push(BeltNum(DataType.I8, Integer(int(result)))) return None
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 run(self, vm: VM) -> Optional['Break']: param_nums = [vm.belt().get_num(idx) for idx in self._param_indices] params = [ num.to_signed(self._is_signed).to_int() for num in param_nums ] data_type = functools.reduce(DataType.promote, (param.data_type for param in param_nums)) if any(param is None for param in params): vm.belt().push(BeltNum(data_type, Integer(None))) else: results = self._op(data_type, *params) for result in reversed(results): vm.belt().push( BeltNum.from_signed(Integer(result), data_type, is_signed=self._is_signed)) return None
def run(self, vm: VM) -> Optional['Break']: a_num = vm.belt().get_num(self._a_idx) b_num = vm.belt().get_num(self._b_idx) a = a_num.to_signed(self._is_signed).to_int() b = b_num.to_signed(self._is_signed).to_int() if a is None or b is None or not self._op(a, b): raise ValueError('Verify failed') return None
def run(self, vm: VM) -> Optional['Break']: if vm.belt().get_num(self._condition_idx).value.expect_int(): block = self._then_block else: block = self._else_block br = block.run(vm) if br is not None and br.depth == 0 and br.is_continue: raise ValueError('Cannot continue if/else/end block') return br
def run(self, vm: VM) -> Optional['Break']: for ins in self._instructions: br = ins.run(vm) print(ins, [ vm.belt().get_num(i).value.expect_int() for i in range(Belt.SIZE) ]) if br is not None and br.depth > 0: return Break(br.depth - 1, is_continue=br.is_continue)
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_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 run(self, vm: VM) -> Optional['Break']: vm.belt().push(self._belt_num) return None
def run(self, vm: VM) -> Optional['Break']: item = vm.belt().get_num(self._item_idx) vm.belt().push(self._op(item, self._data_type, self._is_signed)) return None
def run(self, vm: VM) -> Optional['Break']: slc = vm.belt().get_slice(self._slice_idx) num = vm.belt().get_num(self._item_idx) slc.store(self._offset, num) return None
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 run(self, vm: VM) -> Optional['Break']: slc = vm.belt().get_slice(self._slice_idx) vm.belt().push(slc.load(self._data_type, self._offset)) return None
def run(self, vm: VM) -> Optional['Break']: vm.belt().push(vm.local(self._local_idx)) return None
def run(self, vm: VM) -> Optional['Break']: vm.set_local(self._local_idx, vm.belt()[0]) return None
def run(self, vm: VM) -> Optional['Break']: slc = vm.belt().get_slice(self._slice_idx) num_bytes = vm.belt().get_num(self._num_bytes_idx).value.expect_int() vm.belt().push(self._op(slc, num_bytes)) return None
def run(self, vm: VM) -> Optional['Break']: slc = vm.belt().get_slice(self._slice_idx) vm.belt().push(BeltNum(DataType.I32, Integer(slc.length))) return None
def run(self, vm: VM) -> Optional['Break']: num = vm.belt().get_num(self._item_idx) if num.value.to_int() is None: raise ValueError('Verify failed') return None
def run(self, vm: VM) -> Optional['Break']: num = vm.belt().get_num(self._item_idx) vm.belt().push( BeltNum(DataType.I8, Integer(1 if num.value.to_int() is None else 0))) return None
def run(self, vm: VM) -> Optional['Break']: if vm.belt().get_num(self._condition_idx).value.expect_int(): return Break(self._br_depth, is_continue=False)
def run(self, vm: VM) -> Optional['Break']: slc = vm.belt().get_slice(self._slice_idx) start = vm.belt().get_num(self._start_idx).value.expect_int() length = vm.belt().get_num(self._length_idx).value.expect_int() vm.belt().push(slc.subslice(start, length)) return None