def __init__(self, istream=[], dynamicMem=False, initMem=None, memSize=16): self.core = Core() if initMem is not None: self.mem = initMem if len(self.mem) < memSize: self.mem += [Value(None)] * (memSize - len(self.mem)) self.dynamicMem = dynamicMem self.istream = [Value(i) for i in istream] # For safety self.ostream = [] self.cmd = None # Instruction list
def parseArg(s): if s.lower() in set(('none', '-')): return Value(None) if s.startswith('[') and s.endswith(']'): return Reference(int(s[1:-1])) try: return Value(int(s)) except ValueError: if len(s) != 1: raise ValueError('"{}" is not an argument'.format(s)) return Value(s)
def jz(vm, line): if vm.core.ax == Value(None): raise ValueError("You have nothing to test") if vm.core.ax.zero(): vm.core.pc = line else: vm.core.pc += 1 return True
def inbox(vm): try: vm.core.ax = vm.istream[0] vm.istream = vm.istream[1:] return True except IndexError: vm.core.ax = Value(None) raise CommandError("reached end of input")
def readProgram(stream): prog = Program() lines = [i.strip() for i in stream] while True: isMeta = False # Processed as a meta line meta = lines[0].split() if len(meta) == 0: isMeta = True lines = lines[1:] continue meta[0] = meta[0].lower() if meta[0] == 'mem': isMeta = True prog.initMem = [parseArg(i.strip()) for i in meta[1:]] if meta[0] == 'memsize': isMeta = True memlen = int(meta[1]) assert 0 < memlen <= MAX_INT prog.dynamicMem = False prog.initMem += [Value(None)] * ( (memlen - len(prog.initMem)) if len(prog.initMem) <= memlen else 0) if isMeta: lines = lines[1:] else: break jumps = [] # Later we're going to parse the tags for line in lines: cmd = [i.strip() for i in line.split()] if len(cmd) == 0: # Blank line, ignore it continue if cmd[0].startswith( '#') or cmd[0].lower() == 'comment': # This is a comment continue if cmd[0].endswith(':'): # This is a jump tag prog.tags[cmd[0][:-1]] = len(prog.cmds) continue cmd[0] = cmd[0].lower() if isJump(cmd[0]): jumps.append(len(prog.cmds)) # Record jumps prog.cmds.append(Command(cmd[0], *cmd[1])) continue prog.cmds.append(Command(cmd[0], *[parseArg(i) for i in cmd[1:]])) for i in jumps: # Lookup and replace try: prog.cmds[i].ops[0] = prog.tags[prog.cmds[i].ops[0]] except KeyError: raise ValueError('No such tag "{}"'.format(prog.cmds[i].ops[0])) return prog
def outbox(vm): if vm.core.ax == Value(None): raise CommandError('You have nothing to outbox') vm.ostream.append(vm.core.ax.copy()) vm.core.ax = Value(None) return True
def bumpdown(vm, target): vm.core.ax = vm.getMem(getMemIndex(vm, target)) vm.core.ax -= Value(1) vm.setMem(getMemIndex(vm, target), vm.core.ax) return True
def bumpup(vm, target): # Don't call COPYFROM and COPYTO directly, they will increment the program counter vm.core.ax = vm.getMem(getMemIndex(vm, target)) vm.core.ax += Value(1) vm.setMem(getMemIndex(vm, target), vm.core.ax) return True
def __init__(self, initAx=Value(None)): self.ax = initAx # Accumulator self.pc = 0 # Program Counter