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, &lt_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}
+}