Mercurial > python-compiler.rs
annotate src/python_dump.rs @ 83:e59cd5754268
Add ast.Starred.
| author | Bastien Orivel <eijebong@bananium.fr> |
|---|---|
| date | Mon, 13 Jun 2016 21:41:14 +0200 |
| parents | a0b23123901b |
| children |
| rev | line source |
|---|---|
| 0 | 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(); | |
|
5
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
33 let for_type = ast_module.get(py, "For").unwrap(); |
| 0 | 34 let compare_type = ast_module.get(py, "Compare").unwrap(); |
| 35 let expr_type = ast_module.get(py, "Expr").unwrap(); | |
| 36 let call_type = ast_module.get(py, "Call").unwrap(); | |
| 37 let import_from_type = ast_module.get(py, "ImportFrom").unwrap(); | |
| 38 let alias_type = ast_module.get(py, "alias").unwrap(); | |
| 39 | |
| 40 assert!(is_instance(&ast, &ast_type)); | |
| 41 | |
| 42 /* | |
| 43 // TODO: implement Hash for PyObject. (trivial) | |
| 44 let map = { | |
| 45 let fields = ast.getattr(py, "_fields").unwrap(); | |
| 46 let mut map = HashMap::new(); | |
| 47 for field in fields.iter(py).unwrap() { | |
| 48 let field = field.unwrap(); | |
| 49 let value = ast.getattr(py, field).unwrap(); | |
| 50 map.insert(field, value); | |
| 51 } | |
| 52 map | |
| 53 }; | |
| 54 */ | |
| 55 | |
|
1
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
56 fn get_str(py: Python, object: PyObject) -> String { |
|
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
57 let pystring = object.str(py).unwrap(); |
|
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
58 let mut string = pystring.to_string(py).unwrap(); |
|
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
59 string.to_mut().to_string() |
|
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
60 } |
|
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
61 |
| 0 | 62 if is_instance(&ast, &function_def_type) { |
| 63 let name = ast.getattr(py, "name").unwrap(); | |
| 64 let args = ast.getattr(py, "args").unwrap(); | |
| 65 let body = ast.getattr(py, "body").unwrap(); | |
| 66 let args = dump(py, indent, args); | |
| 67 let declaration = format!("def {}({}):", name, args); | |
|
58
a0b23123901b
Replace "".to_string() and format!("") by String::new().
Bastien Orivel <eijebong@bananium.fr>
parents:
5
diff
changeset
|
68 let mut statements = vec!(String::new()); |
| 0 | 69 for statement in body.iter(py).unwrap() { |
| 70 let statement = dump(py, indent + 1, statement.unwrap()); | |
| 71 statements.push(statement); | |
| 72 } | |
| 73 let indent: String = iter::repeat(" ").take(indent + 1).collect(); | |
| 74 let indent = format!("\n{}", indent); | |
| 75 let indent = indent.as_str(); | |
| 76 let body = statements.join(indent); | |
| 77 format!("{}{}", declaration, body) | |
| 78 } else if is_instance(&ast, &if_type) { | |
| 79 let test = ast.getattr(py, "test").unwrap(); | |
| 80 let body = ast.getattr(py, "body").unwrap(); | |
| 81 | |
| 82 let test = dump(py, indent, test); | |
| 83 | |
| 84 let declaration = format!("if {}:", test); | |
|
58
a0b23123901b
Replace "".to_string() and format!("") by String::new().
Bastien Orivel <eijebong@bananium.fr>
parents:
5
diff
changeset
|
85 let mut statements = vec!(String::new()); |
| 0 | 86 for statement in body.iter(py).unwrap() { |
| 87 let statement = dump(py, indent + 1, statement.unwrap()); | |
| 88 statements.push(statement); | |
| 89 } | |
| 90 let indent: String = iter::repeat(" ").take(indent + 1).collect(); | |
| 91 let indent = format!("\n{}", indent); | |
| 92 let indent = indent.as_str(); | |
| 93 let body = statements.join(indent); | |
| 94 format!("{}{}", declaration, body) | |
|
5
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
95 } else if is_instance(&ast, &for_type) { |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
96 let target = ast.getattr(py, "target").unwrap(); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
97 let iter = ast.getattr(py, "iter").unwrap(); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
98 let body = ast.getattr(py, "body").unwrap(); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
99 //let orelse = ast.getattr(py, "orelse").unwrap(); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
100 |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
101 let target = dump(py, indent, target); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
102 let iter = dump(py, indent, iter); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
103 |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
104 let declaration = format!("for {} in {}:", target, iter); |
|
58
a0b23123901b
Replace "".to_string() and format!("") by String::new().
Bastien Orivel <eijebong@bananium.fr>
parents:
5
diff
changeset
|
105 let mut statements = vec!(String::new()); |
|
5
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
106 for statement in body.iter(py).unwrap() { |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
107 let statement = dump(py, indent + 1, statement.unwrap()); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
108 statements.push(statement); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
109 } |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
110 let indent: String = iter::repeat(" ").take(indent + 1).collect(); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
111 let indent = format!("\n{}", indent); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
112 let indent = indent.as_str(); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
113 let body = statements.join(indent); |
|
ddf372373a77
Add ast.For, ast.UnaryOp, and Sub and Div to ast.BinOp.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
114 format!("{}{}", declaration, body) |
| 0 | 115 } else if is_instance(&ast, &arguments_type) { |
| 116 let args_list = ast.getattr(py, "args").unwrap(); | |
| 117 let mut arguments = vec!(); | |
| 118 for arg in args_list.iter(py).unwrap() { | |
| 119 let arg = arg.unwrap(); | |
| 120 arguments.push(dump(py, indent, arg)); | |
| 121 } | |
| 122 format!("{}", arguments.join(", ")) | |
| 123 } else if is_instance(&ast, &arg_type) { | |
| 124 let arg = ast.getattr(py, "arg").unwrap(); | |
| 125 format!("{}", arg) | |
| 126 } else if is_instance(&ast, &compare_type) { | |
| 127 let left = ast.getattr(py, "left").unwrap(); | |
| 128 let ops = ast.getattr(py, "ops").unwrap(); | |
| 129 let comparators = ast.getattr(py, "comparators").unwrap(); | |
| 130 | |
| 131 let left = dump(py, indent, left); | |
| 132 let ops = ops.iter(py).unwrap(); | |
| 133 let comparators = comparators.iter(py).unwrap(); | |
| 134 | |
| 135 let mut comparisons = vec!(); | |
| 136 for (op, comparator) in ops.zip(comparators) { | |
| 137 let op = op.unwrap(); | |
| 138 let comparator = comparator.unwrap(); | |
| 139 | |
| 140 let op = dump(py, indent, op); | |
| 141 let comparator = dump(py, indent, comparator); | |
| 142 | |
| 143 comparisons.push(format!("{} {}", op, comparator)); | |
| 144 } | |
| 145 format!("{} {}", left, comparisons.join(" ")) | |
| 146 } else if is_instance(&ast, &assign_type) { | |
| 147 let targets = ast.getattr(py, "targets").unwrap(); | |
| 148 let value = ast.getattr(py, "value").unwrap(); | |
| 149 let mut cibles = vec!(); | |
| 150 for target in targets.iter(py).unwrap() { | |
| 151 let target = target.unwrap(); | |
| 152 let target = dump(py, indent, target); | |
| 153 cibles.push(target.to_string()); | |
| 154 } | |
| 155 let value = dump(py, indent, value); | |
| 156 format!("{} = {}", cibles.join(", "), value) | |
| 157 } else if is_instance(&ast, &return_type) { | |
| 158 let value = ast.getattr(py, "value").unwrap(); | |
| 159 let value = dump(py, indent, value); | |
| 160 format!("return {}", value) | |
| 161 } else if is_instance(&ast, &bin_op_type) { | |
| 162 let left = ast.getattr(py, "left").unwrap(); | |
| 163 let op = ast.getattr(py, "op").unwrap(); | |
| 164 let right = ast.getattr(py, "right").unwrap(); | |
| 165 | |
| 166 let left = dump(py, indent, left); | |
| 167 let op = dump(py, indent, op); | |
| 168 let right = dump(py, indent, right); | |
| 169 | |
| 170 format!("{} {} {}", left, op, right) | |
| 171 } else if is_instance(&ast, &name_type) { | |
| 172 let id = ast.getattr(py, "id").unwrap(); | |
| 173 format!("{}", id) | |
| 174 } else if is_instance(&ast, &name_constant_type) { | |
| 175 let value = ast.getattr(py, "value").unwrap(); | |
| 176 format!("{}", value) | |
| 177 } else if is_instance(&ast, &expr_type) { | |
| 178 let value = ast.getattr(py, "value").unwrap(); | |
| 179 let value = dump(py, indent, value); | |
| 180 format!("{}", value) | |
| 181 } else if is_instance(&ast, &call_type) { | |
| 182 let func = ast.getattr(py, "func").unwrap(); | |
| 183 let args = ast.getattr(py, "args").unwrap(); | |
| 184 //let keywords = ast.getattr(py, "keywords").unwrap(); | |
| 185 | |
| 186 let func = dump(py, indent, func); | |
| 187 | |
| 188 let mut arguments = vec!(); | |
| 189 for arg in args.iter(py).unwrap() { | |
| 190 let arg = arg.unwrap(); | |
| 191 arguments.push(dump(py, indent, arg)); | |
| 192 } | |
| 193 | |
| 194 format!("{}({})", func, arguments.join(", ")) | |
| 195 } else if is_instance(&ast, &import_from_type) { | |
| 196 let module = ast.getattr(py, "module").unwrap(); | |
| 197 let names = ast.getattr(py, "names").unwrap(); | |
| 198 //let level = ast.getattr(py, "level").unwrap(); | |
| 199 | |
| 200 let mut arguments = vec!(); | |
| 201 for name in names.iter(py).unwrap() { | |
| 202 let name = name.unwrap(); | |
| 203 arguments.push(dump(py, indent, name)); | |
| 204 } | |
| 205 | |
| 206 format!("from {} import {}", module, arguments.join(", ")) | |
| 207 } else if is_instance(&ast, &alias_type) { | |
| 208 let name = ast.getattr(py, "name").unwrap(); | |
| 209 let asname = ast.getattr(py, "asname").unwrap(); | |
| 210 | |
|
1
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
211 let name = get_str(py, name); |
|
b90e49ab734b
Factorise conversion of Python str into Rust String.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
212 let asname = get_str(py, asname); |
| 0 | 213 |
| 214 if asname == "None" { | |
| 215 format!("{}", name) | |
| 216 } else { | |
| 217 format!("{} as {}", name, asname) | |
| 218 } | |
| 219 } else if is_instance(&ast, &num_type) { | |
| 220 let n = ast.getattr(py, "n").unwrap(); | |
| 221 format!("{}", n) | |
| 222 } else if is_instance(&ast, &str_type) { | |
| 223 let s = ast.getattr(py, "s").unwrap(); | |
| 224 format!("\"{}\"", s) | |
| 225 } else if is_instance(&ast, &add_type) { | |
| 226 format!("+") | |
| 227 } else if is_instance(&ast, &mult_type) { | |
| 228 format!("*") | |
| 229 } else if is_instance(&ast, &eq_type) { | |
| 230 format!("==") | |
| 231 } else if is_instance(&ast, <_type) { | |
| 232 format!("<") | |
| 233 } else { | |
| 234 format!("unknown {}", ast) | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 #[allow(dead_code)] | |
| 239 pub fn dump_module(module: &PyObject) { | |
| 240 let gil = Python::acquire_gil(); | |
| 241 let py = gil.python(); | |
| 242 | |
| 243 let builtins_module = py.import("builtins").unwrap(); | |
| 244 let isinstance = builtins_module.get(py, "isinstance").unwrap(); | |
| 245 | |
| 246 let ast_module = py.import("ast").unwrap(); | |
| 247 let module_type = ast_module.get(py, "Module").unwrap(); | |
| 248 | |
| 249 assert!(isinstance.call(py, (module, module_type), None).unwrap().is_true(py).unwrap()); | |
| 250 | |
| 251 let body = module.getattr(py, "body").unwrap(); | |
| 252 for statement in body.iter(py).unwrap() { | |
| 253 println!("{}", dump(py, 0, statement.unwrap())); | |
| 254 } | |
| 255 } |
