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 __init__(self, loop_stack: LoopStack, num_locals: int, ram_size: int): self._belt = Belt() self._loop_stack = loop_stack self._locals = [BeltNum(data_type=DataType.I8, value=Integer(0)) ] * num_locals self._ram = BeltSlice(bytearray(ram_size), 0, ram_size) self._alignment = 0
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 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 _handle_lit(self, names: List[str], lit: Tree) -> List[Instruction]: assigned_name, = names lit, = lit.children lit = lit.replace('_', '') if assigned_name.startswith('$'): raise ValueError('Cannot assign literals to locals (yet?)') m = self.REG_LIT.match(lit) num = int(m.group(1)) is_signed = m.group(2) == 'i' bit_size = int(m.group(3)) self._push(CompilerBeltItem(assigned_name, is_signed, False)) return [ InsConst( BeltNum.from_signed(Integer(num), DataType(bit_size), is_signed)) ]
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 func(num: BeltNum, _data_type: DataType, _: bool) -> BeltNum: return num.wrap(_data_type)
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) vm.belt().push( BeltNum(DataType.I8, Integer(1 if num.value.to_int() is None else 0))) return None