Skip to content
This repository was archived by the owner on May 5, 2023. It is now read-only.

Commit 362730a

Browse files
committed
Compile directly to PyCodeObject in Rust
1 parent c574b67 commit 362730a

2 files changed

Lines changed: 70 additions & 50 deletions

File tree

compile_code.py

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,58 @@
33
import sys
44
# from pprint import pprint
55

6-
filename = sys.argv[1]
7-
with open(filename, 'rU') as f:
8-
code = f.read()
96

10-
code = compile(code, filename, "exec")
11-
print("CONSTS: {0}".format(code.co_consts))
12-
print("NAMES: {0}".format(code.co_names))
7+
def parse_co_code_to_str(code):
8+
c = byteplay.Code.from_code(code)
9+
# pprint(c.code)
10+
# print(list(c.code))
11+
12+
def format_label(l):
13+
return "LABEL, {0}".format(id(l))
14+
15+
for op in c.code:
16+
# Byteplay print the actual argument instead of the index. But we are
17+
# Converting them back to the index in case we want to use other bytecode
18+
# disassembler in the future.
19+
# Here is a list of meanings for the arguments
20+
# The argument of opcodes in hasconst is the actual constant.
21+
# The argument of opcodes in hasname is the name, as a string.
22+
# The argument of opcodes in hasjump is a Label instance, which should point to a specific location in the code list.
23+
# The argument of opcodes in haslocal is the local variable name, as a string.
24+
# The argument of opcodes in hascompare is the string representing the comparison operator.
25+
# The argument of opcodes in hasfree is the name of the cell or free variable, as a string.
26+
if op[0] in byteplay.hasconst:
27+
print("{0}, {1}".format(op[0], code.co_consts.index(op[1])))
28+
#print("{0}, {1}".format(op[0], None))
29+
elif op[0] in byteplay.hasname:
30+
print("{0}, {1}".format(op[0], code.co_names.index(op[1])))
31+
elif op[0] in byteplay.hasjump:
32+
print("{0}, {1}".format(op[0], id(op[1])))
33+
elif op[0] in byteplay.hascompare:
34+
print("{0}, {1}".format(op[0], byteplay.cmp_op.index(op[1])))
35+
elif type(op[0]) == byteplay.Label:
36+
assert(op[1] == None)
37+
print(format_label(op[0])) # Is the second argument always None?
38+
# print("{0}, {1}".format(format_label(op[0]), op[1]))
39+
else:
40+
print("{0}, {1}".format(op[0], op[1]))
41+
42+
def main():
43+
44+
filename = sys.argv[1]
45+
with open(filename, 'rU') as f:
46+
code = f.read()
47+
48+
code = compile(code, filename, "exec")
49+
print("CONSTS: {0}".format(code.co_consts))
50+
print("NAMES: {0}".format(code.co_names))
1351
# print(code.co_varnames)
1452
# print(list(bytearray(code.co_code)))
1553
# for elem in list(bytearray(code.co_code)):
1654
# print(dis.opname[elem])
1755
# dis_output = dis.dis(code)
1856

19-
c = byteplay.Code.from_code(code)
20-
# pprint(c.code)
21-
# print(list(c.code))
57+
parse_co_code_to_str(code)
2258

23-
def format_label(l):
24-
return "LABEL, {0}".format(id(l))
25-
26-
for op in c.code:
27-
# Byteplay print the actual argument instead of the index. But we are
28-
# Converting them back to the index in case we want to use other bytecode
29-
# disassembler in the future.
30-
# Here is a list of meanings for the arguments
31-
# The argument of opcodes in hasconst is the actual constant.
32-
# The argument of opcodes in hasname is the name, as a string.
33-
# The argument of opcodes in hasjump is a Label instance, which should point to a specific location in the code list.
34-
# The argument of opcodes in haslocal is the local variable name, as a string.
35-
# The argument of opcodes in hascompare is the string representing the comparison operator.
36-
# The argument of opcodes in hasfree is the name of the cell or free variable, as a string.
37-
if op[0] in byteplay.hasconst:
38-
print("{0}, {1}".format(op[0], code.co_consts.index(op[1])))
39-
#print("{0}, {1}".format(op[0], None))
40-
elif op[0] in byteplay.hasname:
41-
print("{0}, {1}".format(op[0], code.co_names.index(op[1])))
42-
elif op[0] in byteplay.hasjump:
43-
print("{0}, {1}".format(op[0], id(op[1])))
44-
elif op[0] in byteplay.hascompare:
45-
print("{0}, {1}".format(op[0], byteplay.cmp_op.index(op[1])))
46-
elif type(op[0]) == byteplay.Label:
47-
assert(op[1] == None)
48-
print(format_label(op[0])) # Is the second argument always None?
49-
# print("{0}, {1}".format(format_label(op[0]), op[1]))
50-
else:
51-
print("{0}, {1}".format(op[0], op[1]))
59+
if __name__ == "__main__":
60+
main()
Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
use cpython::Python;
22
use cpython::ObjectProtocol; //for call method
33
use cpython::PyObject;
4+
use cpython::PyDict;
45
use python27_sys::PyCodeObject;
56

67

7-
pub fn compile() -> PyObject {
8+
//pub fn compile() -> PyObject {
9+
pub fn compile(){
810
let gil = Python::acquire_gil();
911
let py = gil.python();
1012

11-
/*
12-
let sys = py.import("sys").unwrap();
13-
let version: String = sys.get(py, "version").unwrap().extract(py).unwrap();
13+
let locals = PyDict::new(py);
14+
// TODO: read the filename from commandline
15+
locals.set_item(py, "filename", "../tests/functions.py");
16+
17+
let load_file = "\
18+
import os
19+
print(os.getcwd())
20+
with open(filename, 'rU') as f:\
21+
code = f.read()\
22+
";
23+
py.run(load_file, None, Some(&locals)).unwrap();
24+
let code = py.eval("compile(code, \"foo\", \"exec\")", None, Some(&locals)).unwrap();
25+
println!("{:?}", code.getattr(py, "co_name").unwrap());
26+
println!("{:?}", code.getattr(py, "co_filename").unwrap());
27+
println!("{:?}", code.getattr(py, "co_code").unwrap());
28+
println!("{:?}", code.getattr(py, "co_freevars").unwrap());
29+
println!("{:?}", code.getattr(py, "co_cellvars").unwrap());
30+
println!("{:?}", code.getattr(py, "co_consts").unwrap());
31+
let consts = code.getattr(py, "co_consts").unwrap();
32+
println!("{:?}", consts.get_item(py, 0).unwrap().getattr(py, "co_code"));
1433

15-
let os = py.import("os").unwrap();
16-
let getenv = os.get(py, "getenv").unwrap();
17-
let user: String = getenv.call(py, ("USER",), None).unwrap().extract(py).unwrap();
18-
*/
19-
let builtin = py.import("__builtin__").unwrap();
20-
let compile = builtin.get(py, "compile").unwrap();
21-
let code: PyObject = compile.call(py, ("1+1", "foo", "exec"), None).unwrap();
22-
code
2334
}

0 commit comments

Comments
 (0)