comparison src/python_dump.rs @ 0:211b0df72e64

Hello world!
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 29 May 2016 19:15:02 +0100
parents
children b90e49ab734b
comparison
equal deleted inserted replaced
-1:000000000000 0:211b0df72e64
1 extern crate cpython;
2
3 use std::iter;
4
5 use cpython::{Python, PyObject};
6 use cpython::ObjectProtocol; //for call method
7
8 fn dump(py: Python, indent: usize, ast: PyObject) -> String {
9 let builtins_module = py.import("builtins").unwrap();
10 let isinstance = builtins_module.get(py, "isinstance").unwrap();
11
12 let is_instance = |object: &PyObject, type_: &PyObject| {
13 return isinstance.call(py, (object, type_), None).unwrap().is_true(py).unwrap();
14 };
15
16 let ast_module = py.import("ast").unwrap();
17 let ast_type = ast_module.get(py, "AST").unwrap();
18 let function_def_type = ast_module.get(py, "FunctionDef").unwrap();
19 let arguments_type = ast_module.get(py, "arguments").unwrap();
20 let arg_type = ast_module.get(py, "arg").unwrap();
21 let assign_type = ast_module.get(py, "Assign").unwrap();
22 let return_type = ast_module.get(py, "Return").unwrap();
23 let bin_op_type = ast_module.get(py, "BinOp").unwrap();
24 let name_constant_type = ast_module.get(py, "NameConstant").unwrap();
25 let name_type = ast_module.get(py, "Name").unwrap();
26 let num_type = ast_module.get(py, "Num").unwrap();
27 let str_type = ast_module.get(py, "Str").unwrap();
28 let add_type = ast_module.get(py, "Add").unwrap();
29 let mult_type = ast_module.get(py, "Mult").unwrap();
30 let eq_type = ast_module.get(py, "Eq").unwrap();
31 let lt_type = ast_module.get(py, "Lt").unwrap();
32 let if_type = ast_module.get(py, "If").unwrap();
33 let compare_type = ast_module.get(py, "Compare").unwrap();
34 let expr_type = ast_module.get(py, "Expr").unwrap();
35 let call_type = ast_module.get(py, "Call").unwrap();
36 let import_from_type = ast_module.get(py, "ImportFrom").unwrap();
37 let alias_type = ast_module.get(py, "alias").unwrap();
38
39 assert!(is_instance(&ast, &ast_type));
40
41 /*
42 // TODO: implement Hash for PyObject. (trivial)
43 let map = {
44 let fields = ast.getattr(py, "_fields").unwrap();
45 let mut map = HashMap::new();
46 for field in fields.iter(py).unwrap() {
47 let field = field.unwrap();
48 let value = ast.getattr(py, field).unwrap();
49 map.insert(field, value);
50 }
51 map
52 };
53 */
54
55 if is_instance(&ast, &function_def_type) {
56 let name = ast.getattr(py, "name").unwrap();
57 let args = ast.getattr(py, "args").unwrap();
58 let body = ast.getattr(py, "body").unwrap();
59 let args = dump(py, indent, args);
60 let declaration = format!("def {}({}):", name, args);
61 let mut statements = vec!("".to_string());
62 for statement in body.iter(py).unwrap() {
63 let statement = dump(py, indent + 1, statement.unwrap());
64 statements.push(statement);
65 }
66 let indent: String = iter::repeat(" ").take(indent + 1).collect();
67 let indent = format!("\n{}", indent);
68 let indent = indent.as_str();
69 let body = statements.join(indent);
70 format!("{}{}", declaration, body)
71 } else if is_instance(&ast, &if_type) {
72 let test = ast.getattr(py, "test").unwrap();
73 let body = ast.getattr(py, "body").unwrap();
74
75 let test = dump(py, indent, test);
76
77 let declaration = format!("if {}:", test);
78 let mut statements = vec!("".to_string());
79 for statement in body.iter(py).unwrap() {
80 let statement = dump(py, indent + 1, statement.unwrap());
81 statements.push(statement);
82 }
83 let indent: String = iter::repeat(" ").take(indent + 1).collect();
84 let indent = format!("\n{}", indent);
85 let indent = indent.as_str();
86 let body = statements.join(indent);
87 format!("{}{}", declaration, body)
88 } else if is_instance(&ast, &arguments_type) {
89 let args_list = ast.getattr(py, "args").unwrap();
90 let mut arguments = vec!();
91 for arg in args_list.iter(py).unwrap() {
92 let arg = arg.unwrap();
93 arguments.push(dump(py, indent, arg));
94 }
95 format!("{}", arguments.join(", "))
96 } else if is_instance(&ast, &arg_type) {
97 let arg = ast.getattr(py, "arg").unwrap();
98 format!("{}", arg)
99 } else if is_instance(&ast, &compare_type) {
100 let left = ast.getattr(py, "left").unwrap();
101 let ops = ast.getattr(py, "ops").unwrap();
102 let comparators = ast.getattr(py, "comparators").unwrap();
103
104 let left = dump(py, indent, left);
105 let ops = ops.iter(py).unwrap();
106 let comparators = comparators.iter(py).unwrap();
107
108 let mut comparisons = vec!();
109 for (op, comparator) in ops.zip(comparators) {
110 let op = op.unwrap();
111 let comparator = comparator.unwrap();
112
113 let op = dump(py, indent, op);
114 let comparator = dump(py, indent, comparator);
115
116 comparisons.push(format!("{} {}", op, comparator));
117 }
118 format!("{} {}", left, comparisons.join(" "))
119 } else if is_instance(&ast, &assign_type) {
120 let targets = ast.getattr(py, "targets").unwrap();
121 let value = ast.getattr(py, "value").unwrap();
122 let mut cibles = vec!();
123 for target in targets.iter(py).unwrap() {
124 let target = target.unwrap();
125 let target = dump(py, indent, target);
126 cibles.push(target.to_string());
127 }
128 let value = dump(py, indent, value);
129 format!("{} = {}", cibles.join(", "), value)
130 } else if is_instance(&ast, &return_type) {
131 let value = ast.getattr(py, "value").unwrap();
132 let value = dump(py, indent, value);
133 format!("return {}", value)
134 } else if is_instance(&ast, &bin_op_type) {
135 let left = ast.getattr(py, "left").unwrap();
136 let op = ast.getattr(py, "op").unwrap();
137 let right = ast.getattr(py, "right").unwrap();
138
139 let left = dump(py, indent, left);
140 let op = dump(py, indent, op);
141 let right = dump(py, indent, right);
142
143 format!("{} {} {}", left, op, right)
144 } else if is_instance(&ast, &name_type) {
145 let id = ast.getattr(py, "id").unwrap();
146 format!("{}", id)
147 } else if is_instance(&ast, &name_constant_type) {
148 let value = ast.getattr(py, "value").unwrap();
149 format!("{}", value)
150 } else if is_instance(&ast, &expr_type) {
151 let value = ast.getattr(py, "value").unwrap();
152 let value = dump(py, indent, value);
153 format!("{}", value)
154 } else if is_instance(&ast, &call_type) {
155 let func = ast.getattr(py, "func").unwrap();
156 let args = ast.getattr(py, "args").unwrap();
157 //let keywords = ast.getattr(py, "keywords").unwrap();
158
159 let func = dump(py, indent, func);
160
161 let mut arguments = vec!();
162 for arg in args.iter(py).unwrap() {
163 let arg = arg.unwrap();
164 arguments.push(dump(py, indent, arg));
165 }
166
167 format!("{}({})", func, arguments.join(", "))
168 } else if is_instance(&ast, &import_from_type) {
169 let module = ast.getattr(py, "module").unwrap();
170 let names = ast.getattr(py, "names").unwrap();
171 //let level = ast.getattr(py, "level").unwrap();
172
173 let mut arguments = vec!();
174 for name in names.iter(py).unwrap() {
175 let name = name.unwrap();
176 arguments.push(dump(py, indent, name));
177 }
178
179 format!("from {} import {}", module, arguments.join(", "))
180 } else if is_instance(&ast, &alias_type) {
181 let name = ast.getattr(py, "name").unwrap();
182 let asname = ast.getattr(py, "asname").unwrap();
183
184 let name = {
185 let name = name.str(py).unwrap();
186 let mut name = name.to_string(py).unwrap();
187 name.to_mut().to_string()
188 };
189
190 let asname = {
191 let asname = asname.str(py).unwrap();
192 let mut asname = asname.to_string(py).unwrap();
193 asname.to_mut().to_string()
194 };
195
196 if asname == "None" {
197 format!("{}", name)
198 } else {
199 format!("{} as {}", name, asname)
200 }
201 } else if is_instance(&ast, &num_type) {
202 let n = ast.getattr(py, "n").unwrap();
203 format!("{}", n)
204 } else if is_instance(&ast, &str_type) {
205 let s = ast.getattr(py, "s").unwrap();
206 format!("\"{}\"", s)
207 } else if is_instance(&ast, &add_type) {
208 format!("+")
209 } else if is_instance(&ast, &mult_type) {
210 format!("*")
211 } else if is_instance(&ast, &eq_type) {
212 format!("==")
213 } else if is_instance(&ast, &lt_type) {
214 format!("<")
215 } else {
216 format!("unknown {}", ast)
217 }
218 }
219
220 #[allow(dead_code)]
221 pub fn dump_module(module: &PyObject) {
222 let gil = Python::acquire_gil();
223 let py = gil.python();
224
225 let builtins_module = py.import("builtins").unwrap();
226 let isinstance = builtins_module.get(py, "isinstance").unwrap();
227
228 let ast_module = py.import("ast").unwrap();
229 let module_type = ast_module.get(py, "Module").unwrap();
230
231 assert!(isinstance.call(py, (module, module_type), None).unwrap().is_true(py).unwrap());
232
233 let body = module.getattr(py, "body").unwrap();
234 for statement in body.iter(py).unwrap() {
235 println!("{}", dump(py, 0, statement.unwrap()));
236 }
237 }