changeset 53:1a815946c2e5

Implement keywords in expr::Call, and add some tests.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 12 Jun 2016 02:37:28 +0100
parents d9838e8b3ec5
children ad2453a55820
files src/ast_convert.rs src/ast_dump.rs tests/test_parse_files/test_call.py
diffstat 3 files changed, 52 insertions(+), 19 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};
+use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword};
 
 use cpython::{Python, PyObject};
 use cpython::ObjectProtocol; //for call method
@@ -168,6 +168,21 @@ fn parse_comprehension(py: Python, ast: 
     comprehension {target: target, iter: iter, ifs: ifs}
 }
 
+fn parse_keyword(py: Python, ast: PyObject) -> keyword {
+    let arg = ast.getattr(py, "arg").unwrap();
+    let value = ast.getattr(py, "value").unwrap();
+
+    let arg = if arg == py.None() {
+        None
+    } else {
+        let arg = get_str(py, arg);
+        Some(arg)
+    };
+    let value = parse_expr(py, value);
+
+    keyword {arg: arg, value: value}
+}
+
 fn parse_operator(py: Python, ast: PyObject) -> operator {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
@@ -320,16 +335,9 @@ fn parse_expr(py: Python, ast: PyObject)
 
         let func = parse_expr(py, func);
         let args = parse_list(py, args, parse_expr);
+        let keywords = parse_list(py, keywords, parse_keyword);
 
-        /*
-        let mut kwargs = vec!();
-        for arg in keywords.iter(py).unwrap() {
-            let arg = arg.unwrap();
-            kwargs.push(parse_expr(py, arg));
-        }
-        */
-
-        expr::Call(Box::new(func), args, vec!())
+        expr::Call(Box::new(func), args, keywords)
     } else if is_instance(&ast, &compare_type) {
         let left = ast.getattr(py, "left").unwrap();
         let ops = ast.getattr(py, "ops").unwrap();
--- a/src/ast_dump.rs
+++ b/src/ast_dump.rs
@@ -59,6 +59,14 @@ impl cmpop {
     }
 }
 
+fn args_to_strings(args: Vec<expr>) -> Vec<String> {
+    let mut arguments = vec!();
+    for arg in args {
+        arguments.push(arg.to_string());
+    }
+    arguments
+}
+
 fn args_to_string(args: Vec<expr>) -> String {
     let mut arguments = vec!();
     for arg in args {
@@ -67,15 +75,21 @@ fn args_to_string(args: Vec<expr>) -> St
     arguments.join(", ")
 }
 
-fn kwargs_to_string(kwargs: Vec<keyword>) -> String {
-    let mut arguments = vec!();
-    for arg in kwargs {
-        match arg.arg {
-            Some(arg) => arguments.push(arg),
-            None => arguments.push("**kwarg".to_string())
+impl keyword {
+    fn to_string(&self) -> String {
+        match self.arg.clone() {
+            Some(arg) => format!("{}={}", arg, self.value.to_string()),
+            None => format!("**{}", self.value.to_string())
         }
     }
-    arguments.join(", ")
+}
+
+fn kwargs_to_strings(kwargs: Vec<keyword>) -> Vec<String> {
+    let mut arguments = vec!();
+    for kwarg in kwargs {
+        arguments.push(kwarg.to_string());
+    }
+    arguments
 }
 
 fn arguments_to_string(args: arguments) -> String {
@@ -146,7 +160,14 @@ impl expr {
 
                 arguments.join(" ")
             }),
-            expr::Call(func, args, keywords) => format!("{}({}{})", func.to_string(), args_to_string(args), kwargs_to_string(keywords)),
+            expr::Call(func, args, keywords) => format!("{}({})", func.to_string(), {
+                let mut arguments = vec!();
+                let args = args_to_strings(args);
+                let keywords = kwargs_to_strings(keywords);
+                arguments.extend(args);
+                arguments.extend(keywords);
+                arguments.join(", ")
+            }),
             expr::Num(n) => format!("{}", n),
             expr::Str(s) => format!("\"{}\"", s),
             expr::NameConstant(name) => format!("{}", name),
--- a/tests/test_parse_files/test_call.py
+++ b/tests/test_parse_files/test_call.py
@@ -1,1 +1,5 @@
-func(1, b)
+func()
+func(1)
+func(1, a)
+func(b=2, c=3)
+func(a, b, c=3, d=4, **kwargs)