前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python写的Python解释器(二)

Python写的Python解释器(二)

作者头像
哒呵呵
发布2018-08-06 11:30:33
6220
发布2018-08-06 11:30:33
举报
文章被收录于专栏:鸿的学习笔记鸿的学习笔记

编译自:http://www.aosabook.org/en/500L/a-python-interpreter-written-in-python.html 作者:Taavi Burns 翻译:鸿 如有翻译问题或建议,请公众号留言

玩具解释器 首先从一个玩具解释器开始,这个微型解释器只能做加法,而且值包含了三个指令,这三个指令是:

代码语言:javascript
复制
LOAD_VALUE
ADD_TWO_VALUES
PRINT_ANSWER

由于我们跳过了词法分析,语法分析和编译过程,所以我们可以使用dis模块来帮助解析,例如:

代码语言:javascript
复制
7+5

可以使用下面的语句解释:

代码语言:javascript
复制
what_to_execute = {
    "instructions": [("LOAD_VALUE", 0),  # the first number
                     ("LOAD_VALUE", 1),  # the second number
                     ("ADD_TWO_VALUES", None),
                     ("PRINT_ANSWER", None)],
    "numbers": [7, 5] }

Python解释器是一个堆栈机,所以它必须操作堆栈以添加两个数字。解释器将首先执行第一条指令LOAD_VALUE,将第一个数字推入堆栈,再会将第二个数字推入堆栈。 对于第三条指令ADD_TWO_VALUES,它将推出堆栈里的两个数字,将它们加在一起将结果推入堆栈。 最后将答案从堆栈中推出并print出来。

LOAD_VALUE指令表示解释器将一个数字推入堆栈,但指令本身并未指定哪个数字,所以每条指令都需要一条额外的信息,告诉解释器在哪里找到所需要的数字。所以我们的指令集分为两部分:指令本身,以及指令需要的常量列表。现在让我们开始写解释器本身。解释器对象拥有一个列表来表示堆栈。该对象还具有描述执行每条指令的方法。例如,对于LOAD_VALUE,解释器会将值推入堆栈。

代码语言:javascript
复制
class Interpreter:
    def __init__(self):
        self.stack = []
    def LOAD_VALUE(self, number):
        self.stack.append(number)
    def PRINT_ANSWER(self):
        answer = self.stack.pop()
        print(answer)
    def ADD_TWO_VALUES(self):
        first_num = self.stack.pop()
        second_num = self.stack.pop()
        total = first_num + second_num
        self.stack.append(total)

这三个方法实现了解释器所能理解的三条指令。解释器还需要将所有方法联系在一起并实际执行。run_code方法将上面定义的what_to_execute字典作为参数,在循环每一条指令,如果某个指令存在的话就处理该指令的参数,然后在调用解释器对象相应的方法。

代码语言:javascript
复制
def run_code(self, what_to_execute):
    instructions = what_to_execute["instructions"]
    numbers = what_to_execute["numbers"]
    for each_step in instructions:
        instruction, argument = each_step
        if instruction == "LOAD_VALUE":
            number = numbers[argument]
            self.LOAD_VALUE(number)
        elif instruction == "ADD_TWO_VALUES":
            self.ADD_TWO_VALUES()
        elif instruction == "PRINT_ANSWER":
            self.PRINT_ANSWER()

创建相应的实例进行测试:

代码语言:javascript
复制
interpreter = Interpreter()
interpreter.run_code(what_to_execute)

界面上显示:12。尽管这个解释器功能非常有限,但展现的数字相加的过程几乎就是真正的Python解释器所实现的。不过在这个小例子中,也有几件事需要注意。首先,部分指令需要参数。在真正的Python字节码中,大约一半的指令有参数。参数与指令紧密结合。但是请注意,指令的参数不同于调用方法的参数。其次,注意ADD_TWO_VALUES指令不需要任何参数。相反,要相加在一起的值是从解释器的堆栈弹出,这就是基于堆栈的解释器的明确特征。请记住,如果给定有效的指令集,而不对我们的解释器进行任何更改,则可以添加多个数字。看看下面的指令集。

代码语言:javascript
复制
what_to_execute = {
        "instructions": [("LOAD_VALUE", 0),
                         ("LOAD_VALUE", 1),
                         ("ADD_TWO_VALUES", None),
                         ("LOAD_VALUE", 2),
                         ("ADD_TWO_VALUES", None),
                         ("PRINT_ANSWER", None)],
        "numbers": [7, 5, 8] }

由此可以开始看到这个结构是如何扩展的:在解释器对象上添加描述更多操作的方法(只要有一个编译器来处理格式良好的指令集)。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档