使用python编写虚拟机解释器
来源:互联网 发布:c语言的主函数类型 编辑:程序博客网 时间:2024/05/29 08:04
本文参考自:http://www.ituring.com.cn/article/199660
#!/usr/bin/python3# encoding: utf-8from io import StringIOfrom collections import dequeimport tokenizeimport sysclass Stack(deque): push = deque.append def top(self): return self[-1]class Machine: def __init__(self, code): self.data_stack = Stack() self.return_addr_stack = Stack() self.instruction_pointer = 0 self.code = code def pop(self): return self.data_stack.pop() def push(self, value): self.data_stack.push(value) def top(self): return self.data_stack.top() def run(self): while self.instruction_pointer < len(self.code): opcode = self.code[self.instruction_pointer] self.instruction_pointer += 1 self.dispatch(opcode) def dispatch(self, op): 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, "if": self.if_stmt, "jmp": self.jmp, "over": self.over, "print": self.print, "println": self.println, "read": self.read, "dump": self.dump, "stack": self.stack, "swap": self.swap, } if op in dispatch_map: dispatch_map[op]() elif isinstance(op, int): self.push(op) elif isinstance(op, str) and op[0] == op[-1] == '"': self.push(op[1:-1]) else: raise RuntimeError("Unknown opcode: '%s'" % op) def mod(self): self.push(self.pop() % self.pop()) def mul(self): self.push(self.pop() * self.pop()) def plus(self): self.push(self.pop() + self.pop()) def minus(self): self.push(self.pop() - self.pop()) def div(self): self.push(self.pop() / self.pop()) def eq(self): self.push(self.top() == self.top()) def cast_int(self): self.push(int(self.pop())) def cast_str(self): self.push(str(self.pop())) def drop(self): self.pop() def dup(self): self.push(self.top()) def if_stmt(self): false_clause = self.pop() true_clause = self.pop() test = self.pop() self.push(true_clause if test else false_clause) def jmp(self): addr = self.pop() if (isinstance(addr, int) and 0 <= addr < len(self.code)): self.instruction_pointer = addr else: raise RuntimeError("JMP address must be a valid integer.") def over(self): b = self.pop() a = self.pop() self.push(a) self.push(b) self.push(a) def print(self): sys.stdout.write(str(self.pop())) sys.stdout.flush() def println(self): sys.stdout.write("%s\n" % self.pop()) sys.stdout.flush() def dump(self): pass def read(self): self.push(input()) def stack(self): pass def swap(self): a = self.pop() b = self.pop() self.push(a) self.push(b)def parse(text): tokens = tokenize.generate_tokens(StringIO(text).readline) for toknum, tokval, _, _, _ in tokens: if toknum == tokenize.NUMBER: yield int(tokval) elif toknum in [tokenize.OP, tokenize.STRING, tokenize.NAME]: yield tokval elif toknum == tokenize.ENDMARKER: break else: raise RuntimeError("Unknown token %s: '%s'" % (tokenize.tok_name[toknum], tokval))def constant_fold(code): """Constant-folds simple mathematical expressions like 2 3 + to 5.""" while True: # Find two consecutive numbers and an arithmetic operator for i, (a, b, op) in enumerate(zip(code, code[1:], code[2:])): if isinstance(a, int) and isinstance(b, int) \ and op in {"+", "-", "*", "/"}: m = Machine((a, b, op)) m.run() code[i:i+3] = [m.top()] print("Constant-folded %s%s%s to %s" % (a, op, b, m.top())) break else: break return codedef repl(): print('Hit CTRL-D or type "exit" to quit.') while True: try: source = input("> ") code = list(parse(source)) code = constant_fold(code) Machine(code).run() except (RuntimeError, IndexError) as e: print("IndexError: %s" % e) except KeyboardInterrupt: print("\nKeyBoardInterrupt")if __name__ == "__main__": # Machine([ # '"Enter a number: "', "print", "read", "cast_int", # '"Enter another number: "', "print", "read", "cast_int", # "over", "over", # '"Their sum is: "', "print", "+", "println", # '"Their product is: "', "print", "*", "println" # ]).run() # Machine([ # '"Enter a number: "', "print", "read", "cast_int", # '"The number "', "print", "dup", "print", '" is "', "print", # 2, "%", "==", '"even."', '"odd."', "if", "println", # 0, "jmp" # loop forever! # ]).run() repl()
程序运行结果:
阅读全文
0 0
- 【译】使用 Python 编写虚拟机解释器
- 使用 Python 编写虚拟机解释器
- 使用python编写虚拟机解释器
- 使用python编写虚拟机解释器
- 如何使用Python编写一个Lisp解释器
- 使用python解释器
- 2. 使用Python 解释器
- python教程之一-----使用Python解释器
- [笔记]Python虚拟机对函数的解释
- 一天一点python02(使用python 解释器)
- Unbuntu下使用bison编写文本解释器的方法
- 利用python 编写 简单 虚拟机管理
- Python Tutorial 第二章 使用Python解释器
- The Python Tutorial 3.2-2使用Python解释器
- [Python教程]2. Using the Python Interpreter/使用解释器
- 使用Eclipse编写Python
- 编写简单脚本解释器
- 编写android 注解解释器
- Revit中Dynamo编程——Python Script模块(引用RevitApi、RevitApiUI、math库)
- 注册界面的设计
- 为什么说Flutter是革命性的?
- 教你自制ST-LinkV2下载器
- 关于Dynamic附件上传的那些事儿!
- 使用python编写虚拟机解释器
- C语言中特殊浮点数:-1.#IND00和NAN
- dubbo启动无法向zookeeper注册
- iOS应用支持IPV6,就那点事儿
- 基于vue-cli的vue项目之vuex的使用1---------最简单的vuex模板
- ThinkPHP CURD之修改(更新)
- 游标
- 【opencv】sift + RANSAC
- jQuery EasyUI + php + mySQL 实现数据显示