Mercurial > python-compiler.rs
diff src/ast_convert.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/ast_convert.rs @@ -0,0 +1,366 @@ +use python_ast::{Module, Statement, Expr, BinOp}; + +use cpython::{Python, PyObject}; +use cpython::ObjectProtocol; //for call method + +fn parse_expr_vec(py: Python, ast: PyObject) -> Vec<Expr> { + 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 arguments_type = ast_module.get(py, "arguments").unwrap(); + + assert!(is_instance(&ast, &ast_type)); + + if is_instance(&ast, &arguments_type) { + let args = ast.getattr(py, "args").unwrap(); + let mut arguments = vec!(); + for arg in args.iter(py).unwrap() { + let arg = parse_expr(py, arg.unwrap()); + arguments.push(arg); + } + arguments + } else { + vec!(Expr::Error) + } +} + +fn parse_binop(py: Python, ast: PyObject) -> BinOp { + 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 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(); + + assert!(is_instance(&ast, &ast_type)); + + if is_instance(&ast, &add_type) { + BinOp::BinAdd + } else if is_instance(&ast, &mult_type) { + BinOp::BinMult + } else if is_instance(&ast, &eq_type) { + BinOp::BinEq + } else if is_instance(&ast, <_type) { + BinOp::BinLt + } else { + println!("BinOp {}", ast); + BinOp::Error + } +} + +fn parse_expr(py: Python, ast: PyObject) -> Expr { + 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 arg_type = ast_module.get(py, "arg").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 compare_type = ast_module.get(py, "Compare").unwrap(); + let call_type = ast_module.get(py, "Call").unwrap(); + let alias_type = ast_module.get(py, "alias").unwrap(); + + assert!(is_instance(&ast, &ast_type)); + + if is_instance(&ast, &arg_type) { + let arg = { + let arg = ast.getattr(py, "arg").unwrap(); + let arg = arg.str(py).unwrap(); + let mut arg = arg.to_string(py).unwrap(); + arg.to_mut().to_string() + }; + Expr::Name(arg) + } else if is_instance(&ast, &name_type) { + let id = { + let id = ast.getattr(py, "id").unwrap(); + let id = id.str(py).unwrap(); + let mut id = id.to_string(py).unwrap(); + id.to_mut().to_string() + }; + Expr::Name(id) + } else if is_instance(&ast, &name_constant_type) { + let value = { + let value = ast.getattr(py, "value").unwrap(); + let value = value.str(py).unwrap(); + let mut value = value.to_string(py).unwrap(); + value.to_mut().to_string() + }; + Expr::NameConstant(value) + } else if is_instance(&ast, &num_type) { + let n = { + let n = ast.getattr(py, "n").unwrap(); + let n = n.str(py).unwrap(); + let mut n = n.to_string(py).unwrap(); + n.to_mut().to_string() + }; + Expr::Num(n) + } else if is_instance(&ast, &str_type) { + let s = { + let s = ast.getattr(py, "s").unwrap(); + let s = s.str(py).unwrap(); + let mut s = s.to_string(py).unwrap(); + s.to_mut().to_string() + }; + Expr::Str(s) + } 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 = parse_expr(py, left); + let op = parse_binop(py, op); + let right = parse_expr(py, right); + + Expr::BinOp(Box::new(left), op, Box::new(right)) + } 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 = parse_expr(py, func); + + let mut arguments = vec!(); + for arg in args.iter(py).unwrap() { + let arg = arg.unwrap(); + arguments.push(parse_expr(py, arg)); + } + + Expr::Call(Box::new(func), arguments) + } 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(); + let asname = asname.to_mut().to_string(); + if asname == "None" { + "".to_string() + } else { + asname + } + }; + + Expr::Alias(name, asname) + } 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 = parse_expr(py, left); + let ops = ops.iter(py).unwrap(); + let comparators = comparators.iter(py).unwrap(); + + let mut new_ops = vec!(); + for op in ops { + let op = op.unwrap(); + let op = parse_binop(py, op); + new_ops.push(op); + } + + let mut new_comparators = vec!(); + for comparator in comparators { + let comparator = comparator.unwrap(); + let comparator = parse_expr(py, comparator); + new_comparators.push(comparator); + } + + Expr::Compare(Box::new(left), new_ops, new_comparators) + } else { + println!("Expr {}", ast); + Expr::Error + } +} + +fn parse_statement(py: Python, ast: PyObject) -> Statement { + //Statement::FunctionDef(Expr::Name("function".to_string()), vec!(Expr::Name("a".to_string()), Expr::Name("b".to_string())), vec!()) + //Statement::If(Expr::BinOp(BinOp::BinEq, Box::new(Expr::Name("__name__".to_string())), Box::new(Expr::Str("__main__".to_string()))), vec!(Statement::Expr(Expr::Call(Box::new(Expr::Name("function".to_string())), vec!(Expr::Num(1), Expr::Num(2)))))) + + 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 global_type = ast_module.get(py, "Global").unwrap(); + let assign_type = ast_module.get(py, "Assign").unwrap(); + let return_type = ast_module.get(py, "Return").unwrap(); + let import_from_type = ast_module.get(py, "ImportFrom").unwrap(); + let if_type = ast_module.get(py, "If").unwrap(); + let expr_type = ast_module.get(py, "Expr").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 name = { + let name = name.str(py).unwrap(); + let mut name = name.to_string(py).unwrap(); + name.to_mut().to_string() + }; + + let args = parse_expr_vec(py, args); + /* + let mut arguments = vec!(); + for arg in args.iter(py).unwrap() { + let arg = parse_expr(py, arg.unwrap()); + arguments.push(arg); + } + */ + + let mut statements = vec!(); + for statement in body.iter(py).unwrap() { + let statement = parse_statement(py, statement.unwrap()); + statements.push(statement); + } + + Statement::FunctionDef(Expr::Name(name), args, statements) + } else if is_instance(&ast, &global_type) { + let names = ast.getattr(py, "names").unwrap(); + + let mut globals = vec!(); + for name in names.iter(py).unwrap() { + let name = { + let name = name.unwrap().str(py).unwrap(); + let mut name = name.to_string(py).unwrap(); + name.to_mut().to_string() + }; + globals.push(name); + } + + Statement::Global(globals) + } else if is_instance(&ast, &if_type) { + let test = ast.getattr(py, "test").unwrap(); + let body = ast.getattr(py, "body").unwrap(); + let orelse = ast.getattr(py, "orelse").unwrap(); + + let test = parse_expr(py, test); + + let mut statements = vec!(); + for statement in body.iter(py).unwrap() { + let statement = parse_statement(py, statement.unwrap()); + statements.push(statement); + } + + let mut orelse_ = vec!(); + for statement in orelse.iter(py).unwrap() { + let statement = parse_statement(py, statement.unwrap()); + orelse_.push(statement); + } + + Statement::If(test, statements, orelse_) + } else if is_instance(&ast, &assign_type) { + let targets = ast.getattr(py, "targets").unwrap(); + let value = ast.getattr(py, "value").unwrap(); + + let mut arguments = vec!(); + for target in targets.iter(py).unwrap() { + let target = parse_expr(py, target.unwrap()); + arguments.push(target); + } + + let value = parse_expr(py, value); + + Statement::Assign(arguments, value) + } 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 module = { + let module = module.str(py).unwrap(); + let mut module = module.to_string(py).unwrap(); + module.to_mut().to_string() + }; + + let mut names_ = vec!(); + for alias in names.iter(py).unwrap() { + let alias = alias.unwrap(); + let alias = parse_expr(py, alias); + names_.push(alias); + } + + Statement::ImportFrom(module, names_) + } else if is_instance(&ast, &return_type) { + let value = ast.getattr(py, "value").unwrap(); + let value = parse_expr(py, value); + Statement::Return(value) + } else if is_instance(&ast, &expr_type) { + let value = ast.getattr(py, "value").unwrap(); + let value = parse_expr(py, value); + Statement::Expr(value) + } else { + println!("Statement {}", ast); + Statement::Error + } +} + +#[allow(dead_code)] +pub fn convert_ast(name: String, module: &PyObject) -> Module { + 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(); + let mut statements = vec!(); + for statement in body.iter(py).unwrap() { + let statement = parse_statement(py, statement.unwrap()); + statements.push(statement) + } + Module{name: name, statements: statements} +}