def run(self): pc = 0 context = Context() stack = Stack() self.dprint("Begining execution...") while True: line = self.bytecode[pc] opcode = line[0] arg = ' '.join(line[1:]) if opcode == "LOAD": try: if float(arg) == int(arg): self.dprint("Load '{}' as int" .format(arg)) stack.push(int(arg)) else: self.dprint("Load '{}' as float" .format(arg)) stack.push(float(arg)) except ValueError: if context.getSymbol(arg) is not None: self.dprint("Load symbol '{}'" .format(arg)) stack.push(context.getSymbol( arg)) else: self.dprint("Raw load '{}'". format(arg)) stack.push(arg) elif opcode == "LOADSTR": arg = arg[1:-1] stack.push(arg) self.dprint("Load '{}' as string".format(arg)) elif opcode == "STORE": val = stack.pop() self.dprint("Store '{}' as symbol '{}'" .format(val,arg)) context.setSymbol(arg,val) elif opcode == "ADD": val2 = stack.pop() val1 = stack.pop() if isinstance(val2,str) or isinstance(val1,str): stack.push(''.join([str(val1),str(val2)])) self.dprint("Add {} and {} as str".format(val1,val2)) else: stack.push(val1 + val2) self.dprint("Add {} and {}".format(val1,val2)) elif opcode == "SUBTRACT": val2 = stack.pop() val1 = stack.pop() stack.push(val1 - val2) self.dprint("Subtract {} from {}".format( val2,val1)) elif opcode == "MULTIPLY": val2 = stack.pop() val1 = stack.pop() stack.push(val1 * val2) self.dprint("Multiply {} and {}".format( val1,val2)) elif opcode == "DIVIDE": val2 = stack.pop() val1 = stack.pop() stack.push(val1 / val2) self.dprint("Divide {} and {}".format( val1,val2)) elif opcode == "LESSTHAN": val2 = stack.pop() val1 = stack.pop() stack.push(val1 < val2) self.dprint("{} < {}".format(val1,val2)) elif opcode == "GREATERTHAN": val2 = stack.pop() val1 = stack.pop() stack.push(val1 > val2) self.dprint("{} > {}".format(val1,val2)) elif opcode == "EQUALS": val2 = stack.pop() val1 = stack.pop() stack.push(val1 == val2) self.dprint("{} == {}".format(val1,val2)) elif opcode == "NEGATE": val1 = stack.pop() stack.push(-1*val1) self.dprint("Negate {}".format(val1)) elif opcode == "BNOT": val1 = stack.pop() stack.push(not val1) self.dprint("BoolNot {}".format(val1)) elif opcode == "AND": val2 = stack.pop() val1 = stack.pop() stack.push(val2 and val1) self.dprint("{} AND {}".format(val2,val1)) elif opcode == "OR": val2 = stack.pop() val1 = stack.pop() stack.push(val2 or val1) self.dprint("{} OR {}".format(val2,val1)) elif opcode == "POWER": val1 = stack.pop() val2 = stack.pop() stack.push(val2**val1) elif opcode == "PAUSE": if arg: val = arg else: val = stack.pop() sleep(val) self.dprint("Sleep for {} seconds".format(val)) elif opcode == "JUMPNEWCONTEXT": context = context.newContext() context.setReturnPc(pc) pc = int(arg)-1 self.dprint("Procedure call to line {}" .format(pc)) elif opcode == "JUMPOLDCONTEXT": pc = context.getReturnPc() context = context.destroy() self.dprint("Return to caller") elif opcode == "JUMPIFNOT": loc = int(arg) condition = not stack.pop() if condition: self.dprint("Jump to {}".format(loc)) pc = loc-1 else: self.dprint("Jump not taken") elif opcode == "JUMP": loc = int(arg) pc = loc-1 self.dprint("Jumping back to loop condition.") elif opcode == "INPUT": if arg: val = input(arg) else: val = input() try: if float(val) == int(val): stack.push(int(val)) else: stack.push(float(val)) except ValueError: stack.push(val) self.dprint("Read input '{}'".format(val)) elif opcode == "PRINT": if arg: val = context.getSymbol(arg) else: val = stack.pop() self.dprint("Printing '{}'".format(val)) if isinstance(val,str): val = val.replace("\\n","\n") val = val.replace("\_"," ") val = val.replace("\\","") print(val,end="") elif opcode == "TERM": self.dprint("Terminating...") input("Press ENTER to continue...") break else: self.dprint("Unexpected opcode '{}'".format(opcode)) raise Exception("VirtualMachine - Invalid Opcode") pc += 1