from __future__ import print_function import sys, struct FETCH, STORE, PUSH, ADD, SUB, MUL, DIV, MOD, LT, GT, LE, GE, EQ, NE, AND, OR, NEG, NOT, \ JMP, JZ, PRTC, PRTS, PRTI, HALT = range(24) code_map = { "fetch": FETCH, "store": STORE, "push": PUSH, "add": ADD, "sub": SUB, "mul": MUL, "div": DIV, "mod": MOD, "lt": LT, "gt": GT, "le": LE, "ge": GE, "eq": EQ, "ne": NE, "and": AND, "or": OR, "not": NOT, "neg": NEG, "jmp": JMP, "jz": JZ, "prtc": PRTC, "prts": PRTS, "prti": PRTI, "halt": HALT } input_file = None code = bytearray() string_pool = [] word_size = 4 #*** show error and exit def error(msg): print("%s" % (msg)) exit(1) def int_to_bytes(val): return struct.pack(" stack[-1]; stack.pop() elif op == LE: stack[-2] = stack[-2] <= stack[-1]; stack.pop() elif op == GE: stack[-2] = stack[-2] >= stack[-1]; stack.pop() elif op == EQ: stack[-2] = stack[-2] == stack[-1]; stack.pop() elif op == NE: stack[-2] = stack[-2] != stack[-1]; stack.pop() elif op == AND: stack[-2] = stack[-2] and stack[-1]; stack.pop() elif op == OR: stack[-2] = stack[-2] or stack[-1]; stack.pop() elif op == NEG: stack[-1] = -stack[-1] elif op == NOT: stack[-1] = not stack[-1] elif op == JMP: pc += bytes_to_int(code[pc:pc+word_size])[0] elif op == JZ: if stack.pop(): pc += word_size else: pc += bytes_to_int(code[pc:pc+word_size])[0] elif op == PRTC: print("%c" % (stack[-1]), end=''); stack.pop() elif op == PRTS: print("%s" % (string_pool[stack[-1]]), end=''); stack.pop() elif op == PRTI: print("%d" % (stack[-1]), end=''); stack.pop() elif op == HALT: break def str_trans(srce): dest = "" i = 0 while i < len(srce): if srce[i] == '\\' and i + 1 < len(srce): if srce[i + 1] == 'n': dest += '\n' i += 2 elif srce[i + 1] == '\\': dest += '\\' i += 2 else: dest += srce[i] i += 1 return dest #*** def load_code(): global string_pool line = input_file.readline() if len(line) == 0: error("empty line") line_list = line.split() data_size = int(line_list[1]) n_strings = int(line_list[3]) for i in range(n_strings): string_pool.append(str_trans(input_file.readline().strip('"\n'))) while True: line = input_file.readline() if len(line) == 0: break line_list = line.split() offset = int(line_list[0]) instr = line_list[1] opcode = code_map.get(instr) if opcode == None: error("Unknown instruction %s at %d" % (instr, offset)) emit_byte(opcode) if opcode in [JMP, JZ]: p = int(line_list[3]) emit_word(p - (offset + 1)) elif opcode == PUSH: value = int(line_list[2]) emit_word(value) elif opcode in [FETCH, STORE]: value = int(line_list[2].strip('[]')) emit_word(value) return data_size #*** main driver input_file = sys.stdin if len(sys.argv) > 1: try: input_file = open(sys.argv[1], "r", 4096) except IOError as e: error(0, 0, "Can't open %s" % sys.argv[1]) data_size = load_code() run_vm(data_size)