-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecutor.py
More file actions
101 lines (94 loc) · 3.27 KB
/
executor.py
File metadata and controls
101 lines (94 loc) · 3.27 KB
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
91
92
93
94
95
96
97
98
99
100
101
import types
from bytecodes import Bytecode
from datatypes import frame, function, sym
def execute_bytecodes(bytecodes, builtins=None, debug=False):
if builtins is None:
builtins = frame()
exec_stack = []
call_stack = []
instr_ptr = 0
env = builtins
maxs=0
while instr_ptr < len(bytecodes):
if len(call_stack)>maxs:
maxs=len(call_stack)
bytecode = bytecodes[instr_ptr][0]
line = bytecodes[instr_ptr][1]
instr = bytecode[0]
try:
if instr == Bytecode.POP:
exec_stack.pop()
elif instr == Bytecode.PUSH:
exec_stack.append(bytecode[1])
elif instr == Bytecode.DEF:
env[bytecode[1]] = exec_stack.pop()
elif instr == Bytecode.REF:
try:
exec_stack.append(env[bytecode[1]])
except KeyError:
raise NameError("%s is not defined"%bytecode[1])
elif instr == Bytecode.GOTO:
instr_ptr = bytecode[1]
elif instr == Bytecode.BRANCH:
if exec_stack.pop():
instr_ptr = bytecode[1]
elif instr == Bytecode.LAMBDA:
b = bytecode
exec_stack.append(function((b[1][0], env, b[1][1])))
elif instr == Bytecode.CALL or instr == Bytecode.TAIL_CALL:
func = exec_stack.pop()
if hasattr(func, '__call__'):
args = [exec_stack.pop()
for _ in range(bytecode[1])]
exec_stack.append(func(*args))
else:
if instr != Bytecode.TAIL_CALL:
call_stack.append((bytecodes, instr_ptr, env))
instr_ptr = -1
bytecodes = func[0]
env = frame(func[1])
if func[2] != bytecode[1]:
raise RuntimeError('incorrect # of args')
elif instr == Bytecode.RETURN:
bytecodes, instr_ptr, env = call_stack.pop()
elif instr == Bytecode.LABEL:
pass
else:
raise RuntimeError('unknown bytecode: '+bytecode)
except Exception as e:
if debug:
raise e
raise RuntimeError("Error at line %s: "%line+e.args[0])
instr_ptr += 1
yield
if debug:
print(maxs)
for expr in exec_stack:
print(expr)
if __name__ == '__main__':
import tokenizer
import parser_
import compiler
import assembler
import operator
from builtins_ import jcli_builtins
try:
raw_input
except NameError:
raw_input = input
globals_ = dict(jcli_builtins)
while True:
try:
src = raw_input('executor> ')
tokens = tokenizer.tokenize(src)
ast = parser_.parse(tokens)
asm = compiler.compile_(ast)
bc = assembler.assemble(asm)
ex = execute_bytecodes(bc, globals_, debug=True)
while True:
try:
next(ex)
except StopIteration as e:
break
except Exception as e:
print(e.args[0])