forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompile_code.py
60 lines (44 loc) · 1.47 KB
/
compile_code.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
import bytecode
import sys
import json
import types
class CodeEncoder(json.JSONEncoder):
def default(self, obj):
if (isinstance(obj, types.CodeType)):
return serialize_code(obj)
return json.JSONEncoder.default(self, obj)
def serialize_code(code):
c = bytecode.Bytecode().from_code(code).to_concrete_bytecode()
return (
{
"co_consts": consts_to_rust_enum(c.consts),
"co_names": c.names,
"co_name": c.name,
"co_code": parse_co_code_to_str(c),
"co_varnames": c.varnames
}
)
def consts_to_rust_enum(consts):
def capitalize_first(s):
return s[0].upper() + s[1:]
def const_to_rust_enum(const):
if type(const).__name__ == "tuple":
return {capitalize_first(str(type(const).__name__)): list(map(const_to_rust_enum, const))}
else:
return {capitalize_first(str(type(const).__name__)): const}
return list(map(const_to_rust_enum, consts))
def parse_co_code_to_str(c):
return list(
map(lambda op: (op.size, op.name, op.arg if op.arg != bytecode.UNSET else None),
c)
)
def compile_to_bytecode(filename, out_file=None):
with open(filename, 'rU') as f:
code = f.read()
code = compile(code, filename, "exec")
print(CodeEncoder(indent=4).encode(code), file=out_file)
def main():
filename = sys.argv[1]
compile_to_bytecode(filename)
if __name__ == "__main__":
main()