Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 140 lines (109 sloc) 3.982 kb
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
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():
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
6 for i in range(10):
7 print i
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
8
9 # define constants for the byte-codes
10 import dis
11 LOAD_CONST = dis.opmap['LOAD_CONST']
12 LOAD_FAST = dis.opmap['LOAD_FAST']
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
13 LOAD_GLOBAL = dis.opmap['LOAD_GLOBAL']
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
14 STORE_FAST = dis.opmap['STORE_FAST']
15 RETURN_VALUE = dis.opmap['RETURN_VALUE']
16 BINARY_ADD = dis.opmap['BINARY_ADD']
17 BINARY_SUBTRACT = dis.opmap['BINARY_SUBTRACT']
18 BINARY_MULTIPLY = dis.opmap['BINARY_MULTIPLY']
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
19 CALL_FUNCTION = dis.opmap['CALL_FUNCTION']
20
21 SETUP_LOOP = dis.opmap['SETUP_LOOP']
22 POP_BLOCK = dis.opmap['POP_BLOCK']
23 GET_ITER = dis.opmap['GET_ITER']
24 FOR_ITER = dis.opmap['FOR_ITER']
25 JUMP_ABSOLUTE = dis.opmap['JUMP_ABSOLUTE']
26
27 PRINT_ITEM = dis.opmap['PRINT_ITEM']
28 PRINT_NEWLINE = dis.opmap['PRINT_NEWLINE']
29
30 import types
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
31
32 class Frame(object):
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
33 def __init__(self, code, globals):
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
34 self.locals = [None] * code.co_nlocals
35 self.PC = 0
36 self.stack = []
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
37 self.globals = globals
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
38 self.code = code
39
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
40 def execute(code, globals):
41 f = Frame(code, globals)
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
42
43 while True:
44 bc = ord(f.code.co_code[f.PC])
45
46 if bc==LOAD_FAST:
47 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
48 f.stack.append(f.locals[arg])
49 f.PC += 3
50
51 elif bc==LOAD_CONST:
52 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
53 f.stack.append(f.code.co_consts[arg])
54 f.PC += 3
55
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
56 elif bc==LOAD_GLOBAL:
57 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
58 f.stack.append(f.globals[f.code.co_names[arg]])
59 f.PC += 3
60
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
61 elif bc==BINARY_ADD:
62 b = f.stack.pop()
63 a = f.stack.pop()
64 f.stack.append(a+b)
65 f.PC += 1
66
67 elif bc==BINARY_SUBTRACT:
68 b = f.stack.pop()
69 a = f.stack.pop()
70 f.stack.append(a-b)
71 f.PC += 1
72
73 elif bc==BINARY_MULTIPLY:
74 b = f.stack.pop()
75 a = f.stack.pop()
76 f.stack.append(a*b)
77 f.PC += 1
78
79 elif bc==STORE_FAST:
80 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
81 f.locals[arg] = f.stack.pop()
82 f.PC += 3
83
84 elif bc==RETURN_VALUE:
85 return f.stack.pop()
86
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
87 elif bc==SETUP_LOOP:
88 f.PC += 3
89
90 elif bc==POP_BLOCK:
91 f.PC += 1
92
93 elif bc==GET_ITER:
94 f.stack.append(iter(f.stack.pop()))
95 f.PC += 1
96
97 elif bc==JUMP_ABSOLUTE:
98 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
99 f.PC = arg
100
101 elif bc==CALL_FUNCTION:
102 arg = ord(f.code.co_code[f.PC+1])
103
104 call_args = [None] * arg
105 for i in range(arg-1, -1, -1):
106 call_args[i] = f.stack.pop()
107
108 callee = f.stack.pop()
109 if type(callee) is types.BuiltinFunctionType:
110 f.stack.append(callee(*call_args))
111 f.PC += 3
112
113 elif bc==FOR_ITER:
114 arg = ord(f.code.co_code[f.PC+1]) + 256*ord(f.code.co_code[f.PC+2])
115 try:
116 nx = next(f.stack[-1])
117 except StopIteration:
118 f.stack.pop()
119 f.PC += arg + 3
120 else:
121 f.stack.append(nx)
122 f.PC += 3
123
124 elif bc==PRINT_ITEM:
125 print f.stack.pop(),
126 f.PC += 1
127
128 elif bc==PRINT_NEWLINE:
129 print
130 f.PC += 1
131
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
132 else:
133 raise Exception('Unknown Opcode %d (%s)' % (bc, dis.opname[bc]))
134
135 print 'normal Python call:', test()
055e2f0a »
2012-02-26 added for-loops, loading global variables and executing a built-in fu…
136 my_globals = {'range': range}
137 print 'own execute function:', execute(test.func_code, my_globals)
ce803f32 »
2012-02-26 first version of interpreter as presented on http://leovt.wordpress.c…
138
139
140
Something went wrong with that request. Please try again.