Mercurial > python-compiler.rs
diff 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 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/python_dump.rs @@ -0,0 +1,237 @@ +extern crate cpython; + +use std::iter; + +use cpython::{Python, PyObject}; +use cpython::ObjectProtocol; //for call method + +fn dump(py: Python, indent: usize, ast: PyObject) -> String { + let builtins_module = py.import("builtins").unwrap(); + let isinstance = builtins_module.get(py, "isinstance").unwrap(); + + let is_instance = |object: &PyObject, type_: &PyObject| { + return isinstance.call(py, (object, type_), None).unwrap().is_true(py).unwrap(); + }; + + let ast_module = py.import("ast").unwrap(); + let ast_type = ast_module.get(py, "AST").unwrap(); + let function_def_type = ast_module.get(py, "FunctionDef").unwrap(); + let arguments_type = ast_module.get(py, "arguments").unwrap(); + let arg_type = ast_module.get(py, "arg").unwrap(); + let assign_type = ast_module.get(py, "Assign").unwrap(); + let return_type = ast_module.get(py, "Return").unwrap(); + let bin_op_type = ast_module.get(py, "BinOp").unwrap(); + let name_constant_type = ast_module.get(py, "NameConstant").unwrap(); + let name_type = ast_module.get(py, "Name").unwrap(); + let num_type = ast_module.get(py, "Num").unwrap(); + let str_type = ast_module.get(py, "Str").unwrap(); + let add_type = ast_module.get(py, "Add").unwrap(); + let mult_type = ast_module.get(py, "Mult").unwrap(); + let eq_type = ast_module.get(py, "Eq").unwrap(); + let lt_type = ast_module.get(py, "Lt").unwrap(); + let if_type = ast_module.get(py, "If").unwrap(); + let compare_type = ast_module.get(py, "Compare").unwrap(); + let expr_type = ast_module.get(py, "Expr").unwrap(); + let call_type = ast_module.get(py, "Call").unwrap(); + let import_from_type = ast_module.get(py, "ImportFrom").unwrap(); + let alias_type = ast_module.get(py, "alias").unwrap(); + + assert!(is_instance(&ast, &ast_type)); + + /* + // TODO: implement Hash for PyObject. (trivial) + let map = { + let fields = ast.getattr(py, "_fields").unwrap(); + let mut map = HashMap::new(); + for field in fields.iter(py).unwrap() { + let field = field.unwrap(); + let value = ast.getattr(py, field).unwrap(); + map.insert(field, value); + } + map + }; + */ + + if is_instance(&ast, &function_def_type) { + let name = ast.getattr(py, "name").unwrap(); + let args = ast.getattr(py, "args").unwrap(); + let body = ast.getattr(py, "body").unwrap(); + let args = dump(py, indent, args); + let declaration = format!("def {}({}):", name, args); + let mut statements = vec!("".to_string()); + for statement in body.iter(py).unwrap() { + let statement = dump(py, indent + 1, statement.unwrap()); + statements.push(statement); + } + let indent: String = iter::repeat(" ").take(indent + 1).collect(); + let indent = format!("\n{}", indent); + let indent = indent.as_str(); + let body = statements.join(indent); + format!("{}{}", declaration, body) + } else if is_instance(&ast, &if_type) { + let test = ast.getattr(py, "test").unwrap(); + let body = ast.getattr(py, "body").unwrap(); + + let test = dump(py, indent, test); + + let declaration = format!("if {}:", test); + let mut statements = vec!("".to_string()); + for statement in body.iter(py).unwrap() { + let statement = dump(py, indent + 1, statement.unwrap()); + statements.push(statement); + } + let indent: String = iter::repeat(" ").take(indent + 1).collect(); + let indent = format!("\n{}", indent); + let indent = indent.as_str(); + let body = statements.join(indent); + format!("{}{}", declaration, body) + } else if is_instance(&ast, &arguments_type) { + let args_list = ast.getattr(py, "args").unwrap(); + let mut arguments = vec!(); + for arg in args_list.iter(py).unwrap() { + let arg = arg.unwrap(); + arguments.push(dump(py, indent, arg)); + } + format!("{}", arguments.join(", ")) + } else if is_instance(&ast, &arg_type) { + let arg = ast.getattr(py, "arg").unwrap(); + format!("{}", arg) + } else if is_instance(&ast, &compare_type) { + let left = ast.getattr(py, "left").unwrap(); + let ops = ast.getattr(py, "ops").unwrap(); + let comparators = ast.getattr(py, "comparators").unwrap(); + + let left = dump(py, indent, left); + let ops = ops.iter(py).unwrap(); + let comparators = comparators.iter(py).unwrap(); + + let mut comparisons = vec!(); + for (op, comparator) in ops.zip(comparators) { + let op = op.unwrap(); + let comparator = comparator.unwrap(); + + let op = dump(py, indent, op); + let comparator = dump(py, indent, comparator); + + comparisons.push(format!("{} {}", op, comparator)); + } + format!("{} {}", left, comparisons.join(" ")) + } else if is_instance(&ast, &assign_type) { + let targets = ast.getattr(py, "targets").unwrap(); + let value = ast.getattr(py, "value").unwrap(); + let mut cibles = vec!(); + for target in targets.iter(py).unwrap() { + let target = target.unwrap(); + let target = dump(py, indent, target); + cibles.push(target.to_string()); + } + let value = dump(py, indent, value); + format!("{} = {}", cibles.join(", "), value) + } else if is_instance(&ast, &return_type) { + let value = ast.getattr(py, "value").unwrap(); + let value = dump(py, indent, value); + format!("return {}", value) + } else if is_instance(&ast, &bin_op_type) { + let left = ast.getattr(py, "left").unwrap(); + let op = ast.getattr(py, "op").unwrap(); + let right = ast.getattr(py, "right").unwrap(); + + let left = dump(py, indent, left); + let op = dump(py, indent, op); + let right = dump(py, indent, right); + + format!("{} {} {}", left, op, right) + } else if is_instance(&ast, &name_type) { + let id = ast.getattr(py, "id").unwrap(); + format!("{}", id) + } else if is_instance(&ast, &name_constant_type) { + let value = ast.getattr(py, "value").unwrap(); + format!("{}", value) + } else if is_instance(&ast, &expr_type) { + let value = ast.getattr(py, "value").unwrap(); + let value = dump(py, indent, value); + format!("{}", value) + } else if is_instance(&ast, &call_type) { + let func = ast.getattr(py, "func").unwrap(); + let args = ast.getattr(py, "args").unwrap(); + //let keywords = ast.getattr(py, "keywords").unwrap(); + + let func = dump(py, indent, func); + + let mut arguments = vec!(); + for arg in args.iter(py).unwrap() { + let arg = arg.unwrap(); + arguments.push(dump(py, indent, arg)); + } + + format!("{}({})", func, arguments.join(", ")) + } else if is_instance(&ast, &import_from_type) { + let module = ast.getattr(py, "module").unwrap(); + let names = ast.getattr(py, "names").unwrap(); + //let level = ast.getattr(py, "level").unwrap(); + + let mut arguments = vec!(); + for name in names.iter(py).unwrap() { + let name = name.unwrap(); + arguments.push(dump(py, indent, name)); + } + + format!("from {} import {}", module, arguments.join(", ")) + } else if is_instance(&ast, &alias_type) { + let name = ast.getattr(py, "name").unwrap(); + let asname = ast.getattr(py, "asname").unwrap(); + + let name = { + let name = name.str(py).unwrap(); + let mut name = name.to_string(py).unwrap(); + name.to_mut().to_string() + }; + + let asname = { + let asname = asname.str(py).unwrap(); + let mut asname = asname.to_string(py).unwrap(); + asname.to_mut().to_string() + }; + + if asname == "None" { + format!("{}", name) + } else { + format!("{} as {}", name, asname) + } + } else if is_instance(&ast, &num_type) { + let n = ast.getattr(py, "n").unwrap(); + format!("{}", n) + } else if is_instance(&ast, &str_type) { + let s = ast.getattr(py, "s").unwrap(); + format!("\"{}\"", s) + } else if is_instance(&ast, &add_type) { + format!("+") + } else if is_instance(&ast, &mult_type) { + format!("*") + } else if is_instance(&ast, &eq_type) { + format!("==") + } else if is_instance(&ast, <_type) { + format!("<") + } else { + format!("unknown {}", ast) + } +} + +#[allow(dead_code)] +pub fn dump_module(module: &PyObject) { + let gil = Python::acquire_gil(); + let py = gil.python(); + + let builtins_module = py.import("builtins").unwrap(); + let isinstance = builtins_module.get(py, "isinstance").unwrap(); + + let ast_module = py.import("ast").unwrap(); + let module_type = ast_module.get(py, "Module").unwrap(); + + assert!(isinstance.call(py, (module, module_type), None).unwrap().is_true(py).unwrap()); + + let body = module.getattr(py, "body").unwrap(); + for statement in body.iter(py).unwrap() { + println!("{}", dump(py, 0, statement.unwrap())); + } +}