Skip to content
Newer
Older
100644 155 lines (121 sloc) 4.37 KB
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
1 # Copyright (c) 2012, Leonhard Vogt (name.surname@gmx.ch)
2 # This code is provided "as is" without any warranties.
3 # Redistribution of this code and use in derivative works are permitted.
4
5 def test():
4759926 @leovt calling of functions and executing them in the interpreter
authored
6 return square(4) + square(3)
7
8 def square(n):
9 return n * n
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
10
11 # define constants for the byte-codes
12 import dis
13 LOAD_CONST = dis.opmap['LOAD_CONST']
14 LOAD_FAST = dis.opmap['LOAD_FAST']
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
15 LOAD_GLOBAL = dis.opmap['LOAD_GLOBAL']
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
16 STORE_FAST = dis.opmap['STORE_FAST']
17 RETURN_VALUE = dis.opmap['RETURN_VALUE']
18 BINARY_ADD = dis.opmap['BINARY_ADD']
19 BINARY_SUBTRACT = dis.opmap['BINARY_SUBTRACT']
20 BINARY_MULTIPLY = dis.opmap['BINARY_MULTIPLY']
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
21 CALL_FUNCTION = dis.opmap['CALL_FUNCTION']
22
23 SETUP_LOOP = dis.opmap['SETUP_LOOP']
24 POP_BLOCK = dis.opmap['POP_BLOCK']
25 GET_ITER = dis.opmap['GET_ITER']
26 FOR_ITER = dis.opmap['FOR_ITER']
27 JUMP_ABSOLUTE = dis.opmap['JUMP_ABSOLUTE']
28
29 PRINT_ITEM = dis.opmap['PRINT_ITEM']
30 PRINT_NEWLINE = dis.opmap['PRINT_NEWLINE']
31
32 import types
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
33
34 class Frame(object):
4759926 @leovt calling of functions and executing them in the interpreter
authored
35 def __init__(self, code, globals, caller):
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
36 self.locals = [None] * code.co_nlocals
37 self.PC = 0
38 self.stack = []
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
39 self.globals = globals
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
40 self.code = code
4759926 @leovt calling of functions and executing them in the interpreter
authored
41 self.caller = caller
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
42
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
43 def execute(code, globals):
4759926 @leovt calling of functions and executing them in the interpreter
authored
44 f = Frame(code, globals, None)
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
45
46 while True:
47 bc = ord(f.code.co_code[f.PC])
4759926 @leovt calling of functions and executing them in the interpreter
authored
48
49 #print f.PC, dis.opname[bc], f.stack, f.locals
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
50
51 if bc==LOAD_FAST:
52 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
53 f.stack.append(f.locals[arg])
54 f.PC += 3
55
56 elif bc==LOAD_CONST:
57 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
58 f.stack.append(f.code.co_consts[arg])
59 f.PC += 3
60
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
61 elif bc==LOAD_GLOBAL:
62 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
63 f.stack.append(f.globals[f.code.co_names[arg]])
64 f.PC += 3
65
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
66 elif bc==BINARY_ADD:
67 b = f.stack.pop()
68 a = f.stack.pop()
69 f.stack.append(a+b)
70 f.PC += 1
71
72 elif bc==BINARY_SUBTRACT:
73 b = f.stack.pop()
74 a = f.stack.pop()
75 f.stack.append(a-b)
76 f.PC += 1
77
78 elif bc==BINARY_MULTIPLY:
79 b = f.stack.pop()
80 a = f.stack.pop()
81 f.stack.append(a*b)
82 f.PC += 1
83
84 elif bc==STORE_FAST:
85 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
86 f.locals[arg] = f.stack.pop()
87 f.PC += 3
88
89 elif bc==RETURN_VALUE:
4759926 @leovt calling of functions and executing them in the interpreter
authored
90 if f.caller is None:
91 return f.stack.pop()
92 else:
93 ret = f.stack.pop()
94 f = f.caller
95 f.stack.append(ret)
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
96
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
97 elif bc==SETUP_LOOP:
98 f.PC += 3
99
100 elif bc==POP_BLOCK:
101 f.PC += 1
102
103 elif bc==GET_ITER:
104 f.stack.append(iter(f.stack.pop()))
105 f.PC += 1
106
107 elif bc==JUMP_ABSOLUTE:
108 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
109 f.PC = arg
110
111 elif bc==CALL_FUNCTION:
112 arg = ord(f.code.co_code[f.PC+1])
113
114 call_args = [None] * arg
115 for i in range(arg-1, -1, -1):
116 call_args[i] = f.stack.pop()
117
118 callee = f.stack.pop()
119 if type(callee) is types.BuiltinFunctionType:
120 f.stack.append(callee(*call_args))
121 f.PC += 3
4759926 @leovt calling of functions and executing them in the interpreter
authored
122 elif type(callee) is types.FunctionType:
123 subframe = Frame(callee.func_code, callee.func_globals, f)
124 subframe.locals[:arg] = call_args
125 f.PC += 3
126 f = subframe
055e2f0 @leovt added for-loops, loading global variables and executing a built-in fu…
authored
127
128 elif bc==FOR_ITER:
129 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
130 try:
131 nx = next(f.stack[-1])
132 except StopIteration:
133 f.stack.pop()
134 f.PC += arg + 3
135 else:
136 f.stack.append(nx)
137 f.PC += 3
138
139 elif bc==PRINT_ITEM:
140 print f.stack.pop(),
141 f.PC += 1
142
143 elif bc==PRINT_NEWLINE:
144 print
145 f.PC += 1
146
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
147 else:
148 raise Exception('Unknown Opcode %d (%s)' % (bc, dis.opname[bc]))
149
150 print 'normal Python call:', test()
4759926 @leovt calling of functions and executing them in the interpreter
authored
151 print 'own execute function:', execute(test.func_code, test.func_globals)
ce803f3 @leovt first version of interpreter as presented on http://leovt.wordpress.c…
authored
152
153
154
Something went wrong with that request. Please try again.