diff src/ast_convert.rs @ 13:38b0d63697b1

Import the full AST grammar from CPython 3.5.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 02 Jun 2016 05:33:23 +0100
parents fa7e285f88e7
children 719a27f1c1c7
line wrap: on
line diff
--- a/src/ast_convert.rs
+++ b/src/ast_convert.rs
@@ -1,4 +1,4 @@
-use python_ast::{Module, Statement, Expr, BinOp, UnaryOp};
+use python_ast::{Module, stmt, expr, expr_context, cmpop, operator, unaryop, arguments, arg, alias};
 
 use cpython::{Python, PyObject};
 use cpython::ObjectProtocol; //for call method
@@ -30,7 +30,7 @@ fn parse_expr_vec(py: Python, ast: PyObj
             let arg = arg.unwrap();
             let arg = parse_expr(py, arg);
             arguments.push(match arg {
-                Expr::Name(arg) => arg,
+                expr::Name(arg, expr_context::Load) => arg,
                 _ => panic!()
             });
         }
@@ -40,7 +40,7 @@ fn parse_expr_vec(py: Python, ast: PyObj
     }
 }
 
-fn parse_unaryop(py: Python, ast: PyObject) -> UnaryOp {
+fn parse_unaryop(py: Python, ast: PyObject) -> unaryop {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
 
@@ -50,22 +50,57 @@ fn parse_unaryop(py: Python, ast: PyObje
 
     let ast_module = py.import("ast").unwrap();
     let ast_type = ast_module.get(py, "AST").unwrap();
+    let invert_type = ast_module.get(py, "Invert").unwrap();
+    let not_type = ast_module.get(py, "Not").unwrap();
     let uadd_type = ast_module.get(py, "UAdd").unwrap();
     let usub_type = ast_module.get(py, "USub").unwrap();
 
     assert!(is_instance(&ast, &ast_type));
 
-    if is_instance(&ast, &uadd_type) {
-        UnaryOp::UAdd
+    if is_instance(&ast, &invert_type) {
+        unaryop::Invert
+    } else if is_instance(&ast, &not_type) {
+        unaryop::Not
+    } else if is_instance(&ast, &uadd_type) {
+        unaryop::UAdd
     } else if is_instance(&ast, &usub_type) {
-        UnaryOp::USub
+        unaryop::USub
     } else {
-        println!("UnaryOp {}", ast);
-        UnaryOp::Error
+        unreachable!()
     }
 }
 
-fn parse_binop(py: Python, ast: PyObject) -> BinOp {
+fn parse_cmpop(py: Python, ast: PyObject) -> cmpop {
+    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 eq_type = ast_module.get(py, "Eq").unwrap();
+    let noteq_type = ast_module.get(py, "NotEq").unwrap();
+    let lt_type = ast_module.get(py, "Lt").unwrap();
+    let gt_type = ast_module.get(py, "Gt").unwrap();
+
+    assert!(is_instance(&ast, &ast_type));
+
+    if is_instance(&ast, &eq_type) {
+        cmpop::Eq
+    } else if is_instance(&ast, &noteq_type) {
+        cmpop::NotEq
+    } else if is_instance(&ast, &lt_type) {
+        cmpop::Lt
+    } else if is_instance(&ast, &gt_type) {
+        cmpop::Gt
+    } else {
+        unreachable!()
+    }
+}
+
+fn parse_operator(py: Python, ast: PyObject) -> operator {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
 
@@ -76,36 +111,54 @@ fn parse_binop(py: Python, ast: PyObject
     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 sub_type = ast_module.get(py, "Sub").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 gt_type = ast_module.get(py, "Gt").unwrap();
-    let sub_type = ast_module.get(py, "Sub").unwrap();
+    let matmult_type = ast_module.get(py, "MatMult").unwrap();
     let div_type = ast_module.get(py, "Div").unwrap();
+    let mod_type = ast_module.get(py, "Mod").unwrap();
+    let pow_type = ast_module.get(py, "Pow").unwrap();
+    let lshift_type = ast_module.get(py, "LShift").unwrap();
+    let rshift_type = ast_module.get(py, "RShift").unwrap();
+    let bitor_type = ast_module.get(py, "BitOr").unwrap();
+    let bitxor_type = ast_module.get(py, "BitXor").unwrap();
+    let bitand_type = ast_module.get(py, "BitAnd").unwrap();
+    let floordiv_type = ast_module.get(py, "FloorDiv").unwrap();
 
     assert!(is_instance(&ast, &ast_type));
 
     if is_instance(&ast, &add_type) {
-        BinOp::BinAdd
+        operator::Add
+    } else if is_instance(&ast, &sub_type) {
+        operator::Sub
     } 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 if is_instance(&ast, &gt_type) {
-        BinOp::BinGt
-    } else if is_instance(&ast, &sub_type) {
-        BinOp::Sub
+        operator::Mult
+    } else if is_instance(&ast, &matmult_type) {
+        operator::MatMult
     } else if is_instance(&ast, &div_type) {
-        BinOp::Div
+        operator::Div
+    } else if is_instance(&ast, &mod_type) {
+        operator::Mod
+    } else if is_instance(&ast, &pow_type) {
+        operator::Pow
+    } else if is_instance(&ast, &lshift_type) {
+        operator::LShift
+    } else if is_instance(&ast, &rshift_type) {
+        operator::RShift
+    } else if is_instance(&ast, &bitor_type) {
+        operator::BitOr
+    } else if is_instance(&ast, &bitxor_type) {
+        operator::BitXor
+    } else if is_instance(&ast, &bitand_type) {
+        operator::BitAnd
+    } else if is_instance(&ast, &floordiv_type) {
+        operator::FloorDiv
     } else {
-        println!("BinOp {}", ast);
-        BinOp::Error
+        println!("operator {}", ast);
+        panic!()
     }
 }
 
-fn parse_expr(py: Python, ast: PyObject) -> Expr {
+fn parse_expr(py: Python, ast: PyObject) -> expr {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
 
@@ -126,14 +179,13 @@ fn parse_expr(py: Python, ast: PyObject)
     let list_type = ast_module.get(py, "List").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 = ast.getattr(py, "arg").unwrap();
         let arg = get_str(py, arg);
-        Expr::Name(arg)
+        expr::Name(arg, expr_context::Load)
     } else if is_instance(&ast, &attribute_type) {
         let value = ast.getattr(py, "value").unwrap();
         let attr = ast.getattr(py, "attr").unwrap();
@@ -141,23 +193,23 @@ fn parse_expr(py: Python, ast: PyObject)
         let value = parse_expr(py, value);
         let attr = get_str(py, attr);
 
-        Expr::Attribute(Box::new(value), attr)
+        expr::Attribute(Box::new(value), attr, expr_context::Load)
     } else if is_instance(&ast, &name_type) {
         let id = ast.getattr(py, "id").unwrap();
         let id = get_str(py, id);
-        Expr::Name(id)
+        expr::Name(id, expr_context::Load)
     } else if is_instance(&ast, &name_constant_type) {
         let value = ast.getattr(py, "value").unwrap();
         let value = get_str(py, value);
-        Expr::NameConstant(value)
+        expr::NameConstant(value)
     } else if is_instance(&ast, &num_type) {
         let n = ast.getattr(py, "n").unwrap();
         let n = get_str(py, n);
-        Expr::Num(n)
+        expr::Num(n)
     } else if is_instance(&ast, &str_type) {
         let s = ast.getattr(py, "s").unwrap();
         let s = get_str(py, s);
-        Expr::Str(s)
+        expr::Str(s)
     } else if is_instance(&ast, &list_type) {
         let elts = ast.getattr(py, "elts").unwrap();
 
@@ -167,7 +219,7 @@ fn parse_expr(py: Python, ast: PyObject)
             elements.push(parse_expr(py, elt));
         }
 
-        Expr::List(elements)
+        expr::List(elements, expr_context::Load)
     } else if is_instance(&ast, &unary_op_type) {
         let op = ast.getattr(py, "op").unwrap();
         let operand = ast.getattr(py, "operand").unwrap();
@@ -175,21 +227,21 @@ fn parse_expr(py: Python, ast: PyObject)
         let op = parse_unaryop(py, op);
         let operand = parse_expr(py, operand);
 
-        Expr::UnaryOp(op, Box::new(operand))
+        expr::UnaryOp(op, Box::new(operand))
     } 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 op = parse_operator(py, op);
         let right = parse_expr(py, right);
 
-        Expr::BinOp(Box::new(left), op, Box::new(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 keywords = ast.getattr(py, "keywords").unwrap();
 
         let func = parse_expr(py, func);
 
@@ -199,19 +251,15 @@ fn parse_expr(py: Python, ast: PyObject)
             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 mut kwargs = vec!();
+        for arg in keywords.iter(py).unwrap() {
+            let arg = arg.unwrap();
+            kwargs.push(parse_expr(py, arg));
+        }
+        */
 
-        let name = get_str(py, name);
-        let asname = if asname == py.None() {
-            None
-        } else {
-            Some(get_str(py, asname))
-        };
-
-        Expr::Alias(name, asname)
+        expr::Call(Box::new(func), arguments, vec!())
     } else if is_instance(&ast, &compare_type) {
         let left = ast.getattr(py, "left").unwrap();
         let ops = ast.getattr(py, "ops").unwrap();
@@ -224,7 +272,7 @@ fn parse_expr(py: Python, ast: PyObject)
         let mut new_ops = vec!();
         for op in ops {
             let op = op.unwrap();
-            let op = parse_binop(py, op);
+            let op = parse_cmpop(py, op);
             new_ops.push(op);
         }
 
@@ -235,16 +283,63 @@ fn parse_expr(py: Python, ast: PyObject)
             new_comparators.push(comparator);
         }
 
-        Expr::Compare(Box::new(left), new_ops, new_comparators)
+        expr::Compare(Box::new(left), new_ops, new_comparators)
     } else {
-        println!("Expr {}", ast);
-        Expr::Error
+        println!("expr {}", ast);
+        unreachable!()
     }
 }
 
-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))))))
+fn parse_arguments(py: Python, ast: PyObject) -> arguments {
+    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();
+    let arg_type = ast_module.get(py, "arg").unwrap();
+
+    assert!(is_instance(&ast, &ast_type));
+
+    if is_instance(&ast, &arguments_type) {
+        let args = arguments{
+            //args: Vec<arg>,
+            args: {
+                let args = ast.getattr(py, "args").unwrap();
+                let mut arguments = vec!();
+                for arg in args.iter(py).unwrap() {
+                    let arg = arg.unwrap();
+                    assert!(is_instance(&arg, &arg_type));
+                    let arg = get_str(py, arg);
+                    arguments.push(arg{arg: arg, annotation: None});
+                }
+                arguments
+            },
+            //vararg: Option<arg>,
+            vararg: None,
+            //kwonlyargs: Vec<arg>,
+            kwonlyargs: vec!(),
+            //kw_defaults: Vec<expr>,
+            kw_defaults: vec!(),
+            //kwarg: Option<arg>,
+            kwarg: None,
+            //defaults: Vec<expr>
+            defaults: vec!()
+        };
+        args
+    } else {
+        println!("arguments {}", ast);
+        panic!()
+    }
+}
+
+fn parse_statement(py: Python, ast: PyObject) -> stmt {
+    //stmt::FunctionDef(expr::Name("function".to_string()), vec!(expr::Name("a".to_string()), expr::Name("b".to_string())), vec!())
+    //stmt::If(expr::BinOp(BinOp::BinEq, Box::new(expr::Name("__name__".to_string())), Box::new(expr::Str("__main__".to_string()))), vec!(stmt::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();
@@ -307,21 +402,14 @@ fn parse_statement(py: Python, ast: PyOb
             statements.push(statement);
         }
 
-        Statement::ClassDef(name, nodes, statements)
+        stmt::ClassDef(name, nodes, vec!(), statements, vec!())
     } else 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 = get_str(py, name);
-        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 args = parse_arguments(py, args);
 
         let mut statements = vec!();
         for statement in body.iter(py).unwrap() {
@@ -329,7 +417,10 @@ fn parse_statement(py: Python, ast: PyOb
             statements.push(statement);
         }
 
-        Statement::FunctionDef(name, args, statements)
+        let decorators = vec!();
+        let returns = None;
+
+        stmt::FunctionDef(name, args, statements, decorators, returns)
     } else if is_instance(&ast, &global_type) {
         let names = ast.getattr(py, "names").unwrap();
 
@@ -340,7 +431,7 @@ fn parse_statement(py: Python, ast: PyOb
             globals.push(name);
         }
 
-        Statement::Global(globals)
+        stmt::Global(globals)
     } else if is_instance(&ast, &if_type) {
         let test = ast.getattr(py, "test").unwrap();
         let body = ast.getattr(py, "body").unwrap();
@@ -362,7 +453,7 @@ fn parse_statement(py: Python, ast: PyOb
             orelse_.push(statement);
         }
 
-        Statement::If(test, statements, orelse_)
+        stmt::If(test, statements, orelse_)
     } else if is_instance(&ast, &while_type) {
         let test = ast.getattr(py, "test").unwrap();
         let body = ast.getattr(py, "body").unwrap();
@@ -384,7 +475,7 @@ fn parse_statement(py: Python, ast: PyOb
             orelse_.push(statement);
         }
 
-        Statement::While(test, statements, orelse_)
+        stmt::While(test, statements, orelse_)
     } else if is_instance(&ast, &for_type) {
         let target = ast.getattr(py, "target").unwrap();
         let iter = ast.getattr(py, "iter").unwrap();
@@ -408,7 +499,7 @@ fn parse_statement(py: Python, ast: PyOb
             orelse_.push(statement);
         }
 
-        Statement::For(target, iter, statements, orelse_)
+        stmt::For(target, iter, statements, orelse_)
     } else if is_instance(&ast, &assign_type) {
         let targets = ast.getattr(py, "targets").unwrap();
         let value = ast.getattr(py, "value").unwrap();
@@ -422,21 +513,21 @@ fn parse_statement(py: Python, ast: PyOb
 
         let value = parse_expr(py, value);
 
-        Statement::Assign(arguments, value)
+        stmt::Assign(arguments, value)
     } else if is_instance(&ast, &aug_assign_type) {
         let target = ast.getattr(py, "target").unwrap();
         let op = ast.getattr(py, "op").unwrap();
         let value = ast.getattr(py, "value").unwrap();
 
         let target = parse_expr(py, target);
-        let op = parse_binop(py, op);
+        let op = parse_operator(py, op);
         let value = parse_expr(py, value);
 
-        Statement::AugAssign(target, op, value)
+        stmt::AugAssign(target, op, 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 level = ast.getattr(py, "level").unwrap();
 
         let module = get_str(py, module);
 
@@ -444,23 +535,29 @@ fn parse_statement(py: Python, ast: PyOb
         for alias in names.iter(py).unwrap() {
             let alias = alias.unwrap();
             let alias = parse_expr(py, alias);
-            names_.push(alias);
+            println!("{:?}", alias);
+            // XXX
+            //names_.push(alias{name: alias, asname: alias});
         }
 
-        Statement::ImportFrom(module, names_)
+        stmt::ImportFrom(module, names_, None)
     } else if is_instance(&ast, &return_type) {
         let value = ast.getattr(py, "value").unwrap();
-        let value = parse_expr(py, value);
-        Statement::Return(value)
+        if value == py.None() {
+            stmt::Return(None)
+        } else {
+            let value = parse_expr(py, value);
+            stmt::Return(Some(value))
+        }
     } else if is_instance(&ast, &expr_type) {
         let value = ast.getattr(py, "value").unwrap();
         let value = parse_expr(py, value);
-        Statement::Expr(value)
+        stmt::Expr(value)
     } else if is_instance(&ast, &break_type) {
-        Statement::Break
+        stmt::Break
     } else {
-        println!("Statement {}", ast);
-        Statement::Error
+        println!("stmt {}", ast);
+        panic!()
     }
 }