changeset 59:407b3b217928

Add ast.With.
author Bastien Orivel <eijebong@bananium.fr>
date Sun, 12 Jun 2016 20:14:27 +0200
parents a0b23123901b
children 9f0f457a67f6
files src/ast_convert.rs src/ast_dump.rs src/python_ast.rs tests/test_parse_files/test_with.py
diffstat 4 files changed, 48 insertions(+), 3 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, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword};
+use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword, withitem};
 
 use cpython::{Python, PyObject};
 use cpython::ObjectProtocol; //for call method
@@ -54,6 +54,20 @@ fn parse_alias(py: Python, ast: PyObject
     }
 }
 
+fn parse_withitem(py: Python, ast: PyObject) -> withitem {
+    let context_expr = ast.getattr(py, "context_expr").unwrap();
+    let optional_vars = ast.getattr(py, "optional_vars").unwrap();
+
+    let context_expr = parse_expr(py, context_expr);
+
+    if optional_vars == py.None() {
+        withitem{context_expr: context_expr, optional_vars: None}
+    } else {
+        let optional_vars = parse_expr(py, optional_vars);
+        withitem{context_expr: context_expr, optional_vars: Some(optional_vars)}
+    }
+}
+
 fn parse_unaryop(py: Python, ast: PyObject) -> unaryop {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
@@ -513,6 +527,7 @@ fn parse_statement(py: Python, ast: PyOb
     let pass_type = ast_module.get(py, "Pass").unwrap();
     let continue_type = ast_module.get(py, "Continue").unwrap();
     let assert_type = ast_module.get(py, "Assert").unwrap();
+    let with_type = ast_module.get(py, "With").unwrap();
 
     assert!(is_instance(&ast, &ast_type));
 
@@ -665,6 +680,13 @@ fn parse_statement(py: Python, ast: PyOb
             let msg = parse_expr(py, msg);
             stmt::Assert(test, Some(msg))
         }
+    } else if is_instance(&ast, &with_type) {
+        let items = ast.getattr(py, "items").unwrap();
+        let body = ast.getattr(py, "body").unwrap();
+
+        let items = parse_list(py, items, parse_withitem);
+        let body = parse_list(py, body, parse_statement);
+        stmt::With(items, body)
     } else {
         println!("stmt {}", ast);
         panic!()
--- a/src/ast_dump.rs
+++ b/src/ast_dump.rs
@@ -1,4 +1,4 @@
-use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword, comprehension};
+use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword, comprehension, withitem};
 
 use std::iter;
 
@@ -63,6 +63,15 @@ impl cmpop {
     }
 }
 
+impl to_string_able for withitem {
+    fn to_string(&self) -> String {
+        match self.optional_vars {
+            None => format!("{}", self.context_expr.to_string()),
+            Some(ref optional_var) => format!("{} as {}", self.context_expr.to_string(), optional_var.to_string())
+        }
+    }
+}
+
 fn vec_to_strings_vec<T: to_string_able>(values: Vec<T>) -> Vec<String> {
     let mut vector = vec!();
     for value in values {
@@ -277,6 +286,16 @@ impl stmt {
                         }
                     }
                 )
+            },
+            stmt::With(items, body) => {
+                format!("{}with {}:\n{}",
+                    current_indent,
+                    {
+                        let items = vec_to_strings_vec(items);
+                        items.join(", ")
+                    },
+                    statements_to_string(indent, body)
+                )
             }
         }
     }
--- a/src/python_ast.rs
+++ b/src/python_ast.rs
@@ -40,7 +40,7 @@ pub enum stmt {
     If(expr, Vec<stmt>, Vec<stmt>),
 
     // With(withitem* items, stmt* body)
-    //With(Vec<withitem>, Vec<stmt>)
+    With(Vec<withitem>, Vec<stmt>),
 
     // AsyncWith(withitem* items, stmt* body)
     //AsyncWith(Vec<withitem>, Vec<stmt>)
new file mode 100644
--- /dev/null
+++ b/tests/test_parse_files/test_with.py
@@ -0,0 +1,4 @@
+with a:
+    pass
+with a() as b, c:
+    pass