-
Notifications
You must be signed in to change notification settings - Fork 122
/
Copy pathpyexec.py
91 lines (65 loc) · 1.77 KB
/
pyexec.py
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
import ast
def PyObject(ty, val):
return {'type': ty, 'value': val}
Type = PyObject(None, 'type')
Type['type'] = Type
Int = PyObject(Type, 'int')
Builtin = PyObject(Type, 'builtin_function_or_method')
def load_name(frame, name):
if name in frame['locals']:
return frame['locals'][name]
if name in frame['globals']:
return frame['globals'][name]
if name in frame['builtins']:
return frame['builtins'][name]
raise NameError(name)
def store_name(frame, name, value):
frame['locals'][name] = value
def exec_expr(frame, tree):
match tree:
case ast.Name(name):
return load_name(frame, name)
case ast.Constant(int(value)):
return PyObject(Int, value)
case ast.Call(ast.Name(name), [arg]):
func = load_name(frame, name)['value']
return func(exec_expr(frame, arg))
case _:
raise SyntaxError
def exec_stmt(frame, tree):
match tree:
case ast.Assign([name], expr):
store_name(frame, name.id, exec_expr(frame, expr))
case ast.Expr(expr):
exec_expr(frame, expr)
case _:
raise SyntaxError
def exec_block(frame, tree):
for stmt in tree:
exec_stmt(frame, stmt)
def exec_module(frame, tree):
match tree:
case ast.Module(block):
exec_block(frame, block)
case _:
raise SyntaxError
def print_func(obj):
print(obj['value'])
def type_func(obj):
return obj['type']
builtins = {
'print': PyObject(Builtin, print_func),
'type': PyObject(Builtin, type_func)
}
globs = {}
Frame = {
'locals': globs,
'globals': globs,
'builtins': builtins
}
src = '''
x = 42
print(type(x))
print(print)
'''
exec_module(Frame, ast.parse(src))