changeset 20:ace12d6b9855

Replace every loop in ast_convert with parse_list.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 03 Jun 2016 01:22:12 +0100
parents 0cb53a31ac12
children 7af637f444d1
files src/ast_convert.rs
diffstat 1 files changed, 43 insertions(+), 193 deletions(-) [+]
line wrap: on
line diff
--- a/src/ast_convert.rs
+++ b/src/ast_convert.rs
@@ -31,47 +31,16 @@ fn get_ctx(py: Python, object: PyObject)
     }
 }
 
-fn parse_expr_vec(py: Python, list: PyObject) -> Vec<expr> {
+fn parse_list<T, F: Fn(Python, PyObject) -> T>(py: Python, list: PyObject, parse: F) -> Vec<T> {
     let mut exprs = vec!();
     for item in list.iter(py).unwrap() {
         let item = item.unwrap();
-        let item = parse_expr(py, item);
+        let item = parse(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();
-
-    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 = arg.unwrap();
-            let arg = parse_expr(py, arg);
-            arguments.push(match arg {
-                expr::Name(arg, expr_context::Load) => arg,
-                _ => panic!()
-            });
-        }
-        arguments
-    } else {
-        panic!()
-    }
-}
-
 fn parse_unaryop(py: Python, ast: PyObject) -> unaryop {
     let builtins_module = py.import("builtins").unwrap();
     let isinstance = builtins_module.get(py, "isinstance").unwrap();
@@ -175,21 +144,15 @@ fn parse_cmpop(py: Python, ast: PyObject
 }
 
 fn parse_comprehension(py: Python, ast: PyObject) -> comprehension {
-        let target = ast.getattr(py, "target").unwrap();
-        let iter = ast.getattr(py, "iter").unwrap();
-        let ifs = ast.getattr(py, "ifs").unwrap();
-        let ifs = ifs.iter(py).unwrap();
-
-        let target = parse_expr(py, target);
-        let iter = parse_expr(py, iter);
+    let target = ast.getattr(py, "target").unwrap();
+    let iter = ast.getattr(py, "iter").unwrap();
+    let ifs = ast.getattr(py, "ifs").unwrap();
 
-        let mut new_ifs = vec!();
-        for if_ in ifs {
-            let if_ = parse_expr(py, if_.unwrap());
-            new_ifs.push(if_);
-        }
-        comprehension {target: target, iter: iter, ifs: new_ifs}
+    let target = parse_expr(py, target);
+    let iter = parse_expr(py, iter);
+    let ifs = parse_list(py, ifs, parse_expr);
 
+    comprehension {target: target, iter: iter, ifs: ifs}
 }
 
 fn parse_operator(py: Python, ast: PyObject) -> operator {
@@ -308,13 +271,7 @@ fn parse_expr(py: Python, ast: PyObject)
         expr::Str(s)
     } else if is_instance(&ast, &list_type) {
         let elts = ast.getattr(py, "elts").unwrap();
-
-        let mut elements = vec!();
-        for elt in elts.iter(py).unwrap() {
-            let elt = elt.unwrap();
-            elements.push(parse_expr(py, elt));
-        }
-
+        let elements = parse_list(py, elts, parse_expr);
         expr::List(elements, get_ctx(py, ast))
     } else if is_instance(&ast, &unary_op_type) {
         let op = ast.getattr(py, "op").unwrap();
@@ -329,7 +286,7 @@ fn parse_expr(py: Python, ast: PyObject)
         let values = ast.getattr(py, "values").unwrap();
 
         let op = parse_boolop(py, op);
-        let values = parse_expr_vec(py, values);
+        let values = parse_list(py, values, parse_expr);
 
         expr::BoolOp(op, values)
     } else if is_instance(&ast, &bin_op_type) {
@@ -348,12 +305,7 @@ fn parse_expr(py: Python, ast: PyObject)
         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));
-        }
+        let args = parse_list(py, args, parse_expr);
 
         /*
         let mut kwargs = vec!();
@@ -363,72 +315,39 @@ fn parse_expr(py: Python, ast: PyObject)
         }
         */
 
-        expr::Call(Box::new(func), arguments, vec!())
+        expr::Call(Box::new(func), args, vec!())
     } 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 ops = parse_list(py, ops, parse_cmpop);
+        let comparators = parse_list(py, comparators, parse_expr);
 
-        let mut new_ops = vec!();
-        for op in ops {
-            let op = op.unwrap();
-            let op = parse_cmpop(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)
+        expr::Compare(Box::new(left), ops, comparators)
     } else if is_instance(&ast, &listcomp_type) {
         let elt = ast.getattr(py, "elt").unwrap();
         let generators = ast.getattr(py, "generators").unwrap();
-        let generators = generators.iter(py).unwrap();
 
         let elt = parse_expr(py, elt);
+        let generators = parse_list(py, generators, parse_comprehension);
 
-        let mut new_gens = vec!();
-        for gen in generators {
-            let gen = gen.unwrap();
-            let gen = parse_comprehension(py, gen);
-            new_gens.push(gen);
-        }
-        expr::ListComp(Box::new(elt), new_gens)
+        expr::ListComp(Box::new(elt), generators)
     } else if is_instance(&ast, &dictcomp_type) {
         let key = ast.getattr(py, "key").unwrap();
         let value = ast.getattr(py, "value").unwrap();
         let generators = ast.getattr(py, "generators").unwrap();
-        let generators = generators.iter(py).unwrap();
 
         let key = parse_expr(py, key);
         let value = parse_expr(py, value);
+        let generators = parse_list(py, generators, parse_comprehension);
 
-        let mut new_gens = vec!();
-        for gen in generators {
-            let gen = gen.unwrap();
-            let gen = parse_comprehension(py, gen);
-            new_gens.push(gen);
-        }
-        expr::DictComp(Box::new(key), Box::new(value), new_gens)
+        expr::DictComp(Box::new(key), Box::new(value), generators)
     } else if is_instance(&ast, &tuple_type) {
         let elts = ast.getattr(py, "elts").unwrap();
-        let elts = elts.iter(py).unwrap();
-
-        let mut new_elts = vec!();
-        for elt in elts {
-            let elt = elt.unwrap();
-            let elt = parse_expr(py, elt);
-            new_elts.push(elt);
-        }
-        expr::Tuple(new_elts, get_ctx(py, ast))
+        let elts = parse_list(py, elts, parse_expr);
+        expr::Tuple(elts, get_ctx(py, ast))
     } else {
         println!("expr {}", ast);
         unreachable!()
@@ -532,22 +451,10 @@ fn parse_statement(py: Python, ast: PyOb
         //let decorator_list = ast.getattr(py, "decorator_list").unwrap();
 
         let name = get_str(py, name);
-
-        let mut nodes = vec!();
-        for name_node in bases.iter(py).unwrap() {
-            let name_node = name_node.unwrap();
-            let name_node = parse_expr(py, name_node);
-            nodes.push(name_node);
-        }
+        let bases = parse_list(py, bases, parse_expr);
+        let body = parse_list(py, body, parse_statement);
 
-        let mut statements = vec!();
-        for statement in body.iter(py).unwrap() {
-            let statement = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            statements.push(statement);
-        }
-
-        stmt::ClassDef(name, nodes, vec!(), statements, vec!())
+        stmt::ClassDef(name, bases, vec!(), body, vec!())
     } else if is_instance(&ast, &function_def_type) {
         let name = ast.getattr(py, "name").unwrap();
         let args = ast.getattr(py, "args").unwrap();
@@ -555,72 +462,36 @@ fn parse_statement(py: Python, ast: PyOb
 
         let name = get_str(py, name);
         let args = parse_arguments(py, args);
-
-        let mut statements = vec!();
-        for statement in body.iter(py).unwrap() {
-            let statement = parse_statement(py, statement.unwrap());
-            statements.push(statement);
-        }
+        let body = parse_list(py, body, parse_statement);
 
         let decorators = vec!();
         let returns = None;
 
-        stmt::FunctionDef(name, args, statements, decorators, returns)
+        stmt::FunctionDef(name, args, body, decorators, returns)
     } 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 = name.unwrap();
-            let name = get_str(py, name);
-            globals.push(name);
-        }
-
-        stmt::Global(globals)
+        let names = parse_list(py, names, get_str);
+        stmt::Global(names)
     } 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 = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            statements.push(statement);
-        }
+        let body = parse_list(py, body, parse_statement);
+        let orelse = parse_list(py, orelse, parse_statement);
 
-        let mut orelse_ = vec!();
-        for statement in orelse.iter(py).unwrap() {
-            let statement = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            orelse_.push(statement);
-        }
-
-        stmt::If(test, statements, orelse_)
+        stmt::If(test, body, orelse)
     } else if is_instance(&ast, &while_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 = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            statements.push(statement);
-        }
+        let body = parse_list(py, body, parse_statement);
+        let orelse = parse_list(py, orelse, parse_statement);
 
-        let mut orelse_ = vec!();
-        for statement in orelse.iter(py).unwrap() {
-            let statement = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            orelse_.push(statement);
-        }
-
-        stmt::While(test, statements, orelse_)
+        stmt::While(test, body, orelse)
     } else if is_instance(&ast, &for_type) {
         let target = ast.getattr(py, "target").unwrap();
         let iter = ast.getattr(py, "iter").unwrap();
@@ -629,36 +500,18 @@ fn parse_statement(py: Python, ast: PyOb
 
         let target = parse_expr(py, target);
         let iter = parse_expr(py, iter);
-
-        let mut statements = vec!();
-        for statement in body.iter(py).unwrap() {
-            let statement = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            statements.push(statement);
-        }
+        let body = parse_list(py, body, parse_statement);
+        let orelse = parse_list(py, orelse, parse_statement);
 
-        let mut orelse_ = vec!();
-        for statement in orelse.iter(py).unwrap() {
-            let statement = statement.unwrap();
-            let statement = parse_statement(py, statement);
-            orelse_.push(statement);
-        }
-
-        stmt::For(target, iter, statements, orelse_)
+        stmt::For(target, iter, body, 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 = target.unwrap();
-            let target = parse_expr(py, target);
-            arguments.push(target);
-        }
-
+        let targets = parse_list(py, targets, parse_expr);
         let value = parse_expr(py, value);
 
-        stmt::Assign(arguments, value)
+        stmt::Assign(targets, value)
     } else if is_instance(&ast, &aug_assign_type) {
         let target = ast.getattr(py, "target").unwrap();
         let op = ast.getattr(py, "op").unwrap();
@@ -676,6 +529,7 @@ fn parse_statement(py: Python, ast: PyOb
 
         let module = get_str(py, module);
 
+        // TODO: move that into another function.
         let mut names_ = vec!();
         for alias in names.iter(py).unwrap() {
             let alias = alias.unwrap();
@@ -720,10 +574,6 @@ pub fn convert_ast(name: String, module:
     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}
+    let body = parse_list(py, body, parse_statement);
+    Module{name: name, statements: body}
 }