changeset 19:0cb53a31ac12

Implement ast.BoolOp, and improve its display.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 03 Jun 2016 00:55:24 +0100
parents 51ef651266b1
children ace12d6b9855
files src/ast_convert.rs src/ast_dump.rs
diffstat 2 files changed, 54 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/ast_convert.rs
+++ b/src/ast_convert.rs
@@ -1,4 +1,4 @@
-use python_ast::{Module, stmt, expr, expr_context, cmpop, operator, unaryop, arguments, arg, alias, comprehension};
+use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension};
 
 use cpython::{Python, PyObject};
 use cpython::ObjectProtocol; //for call method
@@ -31,7 +31,17 @@ fn get_ctx(py: Python, object: PyObject)
     }
 }
 
-fn parse_expr_vec(py: Python, ast: PyObject) -> Vec<String> {
+fn parse_expr_vec(py: Python, list: PyObject) -> Vec<expr> {
+    let mut exprs = vec!();
+    for item in list.iter(py).unwrap() {
+        let item = item.unwrap();
+        let item = parse_expr(py, item);
+        exprs.push(item);
+    }
+    exprs
+}
+
+fn parse_string_vec(py: Python, ast: PyObject) -> Vec<String> {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
 
@@ -92,6 +102,30 @@ fn parse_unaryop(py: Python, ast: PyObje
     }
 }
 
+fn parse_boolop(py: Python, ast: PyObject) -> boolop {
+    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 and_type = ast_module.get(py, "And").unwrap();
+    let or_type = ast_module.get(py, "Or").unwrap();
+
+    assert!(is_instance(&ast, &ast_type));
+
+    if is_instance(&ast, &and_type) {
+        boolop::And
+    } else if is_instance(&ast, &or_type) {
+        boolop::Or
+    } else {
+        unreachable!()
+    }
+}
+
 fn parse_cmpop(py: Python, ast: PyObject) -> cmpop {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
@@ -228,6 +262,7 @@ fn parse_expr(py: Python, ast: PyObject)
     let ast_type = ast_module.get(py, "AST").unwrap();
     let arg_type = ast_module.get(py, "arg").unwrap();
     let unary_op_type = ast_module.get(py, "UnaryOp").unwrap();
+    let bool_op_type = ast_module.get(py, "BoolOp").unwrap();
     let bin_op_type = ast_module.get(py, "BinOp").unwrap();
     let name_constant_type = ast_module.get(py, "NameConstant").unwrap();
     let attribute_type = ast_module.get(py, "Attribute").unwrap();
@@ -289,6 +324,14 @@ fn parse_expr(py: Python, ast: PyObject)
         let operand = parse_expr(py, operand);
 
         expr::UnaryOp(op, Box::new(operand))
+    } else if is_instance(&ast, &bool_op_type) {
+        let op = ast.getattr(py, "op").unwrap();
+        let values = ast.getattr(py, "values").unwrap();
+
+        let op = parse_boolop(py, op);
+        let values = parse_expr_vec(py, values);
+
+        expr::BoolOp(op, values)
     } else if is_instance(&ast, &bin_op_type) {
         let left = ast.getattr(py, "left").unwrap();
         let op = ast.getattr(py, "op").unwrap();
--- a/src/ast_dump.rs
+++ b/src/ast_dump.rs
@@ -5,8 +5,8 @@ use std::iter;
 impl boolop {
     fn to_string(&self) -> &'static str {
         match *self {
-            boolop::And => "and",
-            boolop::Or => "or"
+            boolop::And => " and ",
+            boolop::Or => " or "
         }
     }
 }
@@ -116,7 +116,13 @@ fn generators_to_string(generators: Vec<
 impl expr {
     fn to_string(&self) -> String {
         match self.clone() {
-            expr::BoolOp(op, values) => format!("{}({})", op.to_string(), args_to_string(values)),
+            expr::BoolOp(op, values) => {
+                let mut data = vec!();
+                for value in values {
+                    data.push(value.to_string());
+                }
+                data.join(op.to_string())
+            },
             expr::BinOp(a, op, b) => format!("{} {} {}", a.to_string(), op.to_string(), b.to_string()),
             expr::UnaryOp(op, operand) => format!("{}{}", op.to_string(), operand.to_string()),