python解释器
且任容枯 Lv4

A Tiny Interpreter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""
LOAD_VALUE 把值入栈
STORE_NAME 出栈赋值给变量
LOAD_NAME 把变量值入栈
"""


from dis import Instruction


what_to_execute = {
"instructions": [("LOAD_VALUE", 0),
("STORE_NAME", 0),
("LOAD_VALUE", 1),
("STORE_NAME", 1),
("LOAD_NAME", 0),
("LOAD_NAME", 1),
("ADD_TWO_VALUES", None),
("PRINT_ANSWER", None)],
"numbers": [1, 2],
"names": ["a", "b"]
}

class Interpreter:
def __init__(self):
self.stack = []
self.environment = {}

def STORE_NAME(self, name):
val = self.stack.pop()
self.environment[name] = val

def LOAD_NAME(self, name):
val = self.environment[name]
self.stack.append(val)

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)

def parse_argument(self, instruction, argument, what_to_execute):
numbers = ["LOAD_VALUE"]
names = ["LOAD_NAME", "STORE_NAME"]
if instruction in numbers:
argument = what_to_execute["numbers"][argument]
elif instruction in names:
argument = what_to_execute["names"][argument]
return argument

def run_code(self, what_to_execute):
instructions = what_to_execute['instructions']
for each_step in instructions:
instruction, argument = each_step
argument = self.parse_argument(instruction, argument, what_to_execute)

if instruction == 'LOAD_VALUE':
self.LOAD_VALUE(argument)
elif instruction == 'ADD_TWO_VALUES':
self.ADD_TWO_VALUES()
elif instruction == 'PRINT_ANSWER':
self.PRINT_ANSWER()
elif instruction == 'STORE_NAME':
self.STORE_NAME(argument)
elif instruction == "LOAD_NAME":
self.LOAD_NAME(argument)

def execute(self, what_to_execute):
instructions = what_to_execute["instructions"]
for each_step in instructions:
instruction, argument = each_step
argument = self.parse_argument(instruction, argument, what_to_execute)
bytecode_method = getattr(self, instruction)
if argument is None:
bytecode_method()
else:
bytecode_method(argument)


interpreter = Interpreter()
interpreter.run_code(what_to_execute)
interpreter.execute(what_to_execute)

Frames

Python虚拟机是一个栈机器。它能顺序执行指令,在指令间跳转,压入或弹出栈值。
一个frame是一些信息的集合和代码的执行上下文。frames在Python代码执行时动态的创建和销毁。每个frame对应函数的一次调用。— 所以每个frame只有一个code object与之关联,而一个code object可以很多frame。比如你有一个函数递归的调用自己10次,这时有11个frame。总的来说,Python程序的每个作用域有一个frame,比如,每个module,每个函数调用,每个类定义。

来源

https://aosabook.org/en/500L/a-python-interpreter-written-in-python.html