时间:2023-06-27 07:03:02 | 来源:网站运营
时间:2023-06-27 07:03:02 来源:网站运营
用Python实现一个虚拟机需要多久?10分钟!:来源:Python高效编程# Python高效编程class Machine: def __init__(self, code): self.code = code self.stack = list() self.addr = 0
原理其实很简单,我们通过不断获取当前指令地址,从指令列表中获取指令和数据,如果是数字或者字符串,就压入栈中;如果是指令,就执行相应函数。def push(self, value): self.stack.append(value)def pop(self): return self.stack.pop()@propertydef top(self): return self.stack[-1]
我们通过 dispatch 方法,来判断当前从指令列表中取得的片段是指令还是数据:def dispatch(self, opcode): dispatch_map = { "%": self.mod, "*": self.mul, "+": self.plus, "-": self.minus, "/": self.div, "==": self.eq, "cast_int": self.cast_int, "cast_str": self.cast_str, "drop": self.drop, "dup": self.dup, "exit": self.exit, "if": self.if_stmt, "jmp": self.jmp, "over": self.over, "print": self.print, "println": self.println, "read": self.read, "stack": self.dump_stack, "swap": self.swap, } if opcode in dispatch_map: dispatch_map[opcode]() elif isinstance(opcode, int): self.push(opcode) elif isinstance(opcode, str)/ and opcode[0] == opcode[-1] == '"': self.push(opcode[1:-1])
dispatch_map 就对应我们在 Machine 类中实现的方法。def plus(self): v2 = self.pop() v1 = self.pop() self.push(v1 + v2)def jmp(self): addr = self.pop() if 0 <= addr < len(self.code): self.addr = addr else: raise RuntimeError("addr must be integer")
其余方法也很简单,大家可以直接查看源代码。def run(self): while self.addr < len(self.code): opcode = self.code[self.addr] self.addr += 1 self.dispatch(opcode)
我们创建 Machine 类,并执行 run 函数,注意字符串要用引号括起来。>>> from vm import Machine>>> Machine([521, 1314,"+", 6, "*","println"]).run()11010
我们还可以给虚拟机加一个交互式界面:def repl(prompt="VM>> "): welcome() while True: try: text = read(prompt) code = list(tokenize(text)) code = constants_fold(code) Machine(code).run() except (RuntimeError, IndexError): stdout.write("1表达式不合法/n") except KeyboardInterrupt: stdout.write("请使用exit退出程序/n")
在读取用户输入字符串之后,对字符串处理:def parse_word(word): try: return int(word) except ValueError: try: return float(word) except ValueError: return worddef tokenize(text): for word in text.split(): yield parse_word(word)
最后放张效果图:关键词:实现,虚拟