Mercurial > python-compiler.rs
view src/ast_convert.rs @ 65:ce5e27a3f277
Add ClassDef.decorator_list support.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Mon, 13 Jun 2016 01:27:10 +0100 |
parents | 53817b39f139 |
children | 8ce78e2ba48c |
line wrap: on
line source
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 fn get_str(py: Python, object: PyObject) -> String { let pystring = object.str(py).unwrap(); let mut string = pystring.to_string(py).unwrap(); string.to_mut().to_string() } fn get_ctx(py: Python, object: PyObject) -> expr_context { 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 store_type = ast_module.get(py, "Store").unwrap(); let load_type = ast_module.get(py, "Load").unwrap(); let del_type = ast_module.get(py, "Del").unwrap(); let ctx = object.getattr(py, "ctx").unwrap(); if is_instance(&ctx, &store_type) { expr_context::Store } else if is_instance(&ctx, &load_type) { expr_context::Load } else if is_instance(&ctx, &del_type) { expr_context::Del } else{ unreachable!(); } } 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(py, item); exprs.push(item); } exprs } fn parse_alias(py: Python, ast: PyObject) -> alias { let ast_alias = get_str(py, ast.getattr(py, "name").unwrap()); let asname = ast.getattr(py, "asname").unwrap(); if asname == py.None() { alias{name: ast_alias, asname: None} } else { alias{name: ast_alias, asname: Some(get_str(py, asname))} } } 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(); 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 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, &invert_type) { unaryop::Invert } else if is_instance(&ast, ¬_type) { unaryop::Not } else if is_instance(&ast, &uadd_type) { unaryop::UAdd } else if is_instance(&ast, &usub_type) { unaryop::USub } else { unreachable!() } } 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(); 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 lte_type = ast_module.get(py, "LtE").unwrap(); let gt_type = ast_module.get(py, "Gt").unwrap(); let gte_type = ast_module.get(py, "GtE").unwrap(); let is_type = ast_module.get(py, "Is").unwrap(); let is_not_type = ast_module.get(py, "IsNot").unwrap(); let in_type = ast_module.get(py, "In").unwrap(); let not_in_type = ast_module.get(py, "NotIn").unwrap(); assert!(is_instance(&ast, &ast_type)); if is_instance(&ast, &eq_type) { cmpop::Eq } else if is_instance(&ast, ¬eq_type) { cmpop::NotEq } else if is_instance(&ast, <_type) { cmpop::Lt } else if is_instance(&ast, <e_type) { cmpop::LtE } else if is_instance(&ast, >_type) { cmpop::Gt } else if is_instance(&ast, >e_type) { cmpop::GtE } else if is_instance(&ast, &is_type) { cmpop::Is } else if is_instance(&ast, &is_not_type) { cmpop::IsNot } else if is_instance(&ast, &in_type) { cmpop::In } else if is_instance(&ast, ¬_in_type) { cmpop::NotIn } else { unreachable!() } } 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 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_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(); 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 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 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) { operator::Add } else if is_instance(&ast, &sub_type) { operator::Sub } else if is_instance(&ast, &mult_type) { operator::Mult } else if is_instance(&ast, &matmult_type) { operator::MatMult } else if is_instance(&ast, &div_type) { 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!("operator {}", ast); panic!() } } fn parse_optional_expr(py: Python, ast: PyObject) -> Option<expr> { if ast == py.None() { None } else { let ast = parse_expr(py, ast); Some(ast) } } fn parse_expr(py: Python, ast: PyObject) -> expr { 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 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(); let name_type = ast_module.get(py, "Name").unwrap(); let num_type = ast_module.get(py, "Num").unwrap(); let str_type = ast_module.get(py, "Str").unwrap(); 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 listcomp_type = ast_module.get(py, "ListComp").unwrap(); let dictcomp_type = ast_module.get(py, "DictComp").unwrap(); let tuple_type = ast_module.get(py, "Tuple").unwrap(); let ellipsis_type = ast_module.get(py, "Ellipsis").unwrap(); assert!(is_instance(&ast, &ast_type)); if is_instance(&ast, &attribute_type) { let value = ast.getattr(py, "value").unwrap(); let attr = ast.getattr(py, "attr").unwrap(); let value = parse_expr(py, value); let attr = get_str(py, attr); expr::Attribute(Box::new(value), attr, get_ctx(py, ast)) } else if is_instance(&ast, &name_type) { let id = ast.getattr(py, "id").unwrap(); let id = get_str(py, id); expr::Name(id, get_ctx(py, ast)) } else if is_instance(&ast, &name_constant_type) { let value = ast.getattr(py, "value").unwrap(); let value = get_str(py, 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) } else if is_instance(&ast, &str_type) { let s = ast.getattr(py, "s").unwrap(); let s = get_str(py, s); expr::Str(s) } else if is_instance(&ast, &list_type) { let elts = ast.getattr(py, "elts").unwrap(); 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(); let operand = ast.getattr(py, "operand").unwrap(); let op = parse_unaryop(py, op); 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_list(py, values, parse_expr); 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(); let right = ast.getattr(py, "right").unwrap(); let left = parse_expr(py, left); let op = parse_operator(py, op); let right = parse_expr(py, 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 func = parse_expr(py, func); let args = parse_list(py, args, parse_expr); let keywords = parse_list(py, keywords, parse_keyword); 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(); let comparators = ast.getattr(py, "comparators").unwrap(); let left = parse_expr(py, left); let ops = parse_list(py, ops, parse_cmpop); let comparators = parse_list(py, comparators, parse_expr); 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 elt = parse_expr(py, elt); let generators = parse_list(py, generators, parse_comprehension); 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 key = parse_expr(py, key); let value = parse_expr(py, value); let generators = parse_list(py, generators, parse_comprehension); 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 = parse_list(py, elts, parse_expr); expr::Tuple(elts, get_ctx(py, ast)) } else if is_instance(&ast, &ellipsis_type) { expr::Ellipsis } else { println!("expr {}", ast); unreachable!() } } fn parse_arg(py: Python, ast: PyObject) -> arg { let arg = ast.getattr(py, "arg").unwrap(); let annotation = ast.getattr(py, "annotation").unwrap(); let arg = get_str(py, arg); let annotation = parse_optional_expr(py, annotation); arg{arg: arg, annotation: annotation} } 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 = parse_arg(py, arg); arguments.push(arg); } arguments }, //vararg: Option<arg>, vararg: { let vararg = ast.getattr(py, "vararg").unwrap(); if vararg == py.None() { None } else { let arg = parse_arg(py, vararg); Some(arg) } }, //kwonlyargs: Vec<arg>, kwonlyargs: { let kwonlyargs = ast.getattr(py, "kwonlyargs").unwrap(); let mut arguments = vec!(); for arg in kwonlyargs.iter(py).unwrap() { let arg = arg.unwrap(); assert!(is_instance(&arg, &arg_type)); let arg = parse_arg(py, arg); arguments.push(arg); } arguments }, //kw_defaults: Vec<Option<expr>>, kw_defaults: { let kw_defaults = ast.getattr(py, "kw_defaults").unwrap(); let mut arguments = vec!(); for arg in kw_defaults.iter(py).unwrap() { let arg = arg.unwrap(); let arg = parse_optional_expr(py, arg); arguments.push(arg); } arguments }, //kwarg: Option<arg>, kwarg: { let kwarg = ast.getattr(py, "kwarg").unwrap(); if kwarg == py.None() { None } else { let arg = parse_arg(py, kwarg); Some(arg) } }, //defaults: Vec<expr> defaults: { let defaults = ast.getattr(py, "defaults").unwrap(); let mut arguments = vec!(); for arg in defaults.iter(py).unwrap() { let arg = arg.unwrap(); let arg = parse_expr(py, arg); arguments.push(arg); } arguments } }; 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(); 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 class_def_type = ast_module.get(py, "ClassDef").unwrap(); let function_def_type = ast_module.get(py, "FunctionDef").unwrap(); let global_type = ast_module.get(py, "Global").unwrap(); let nonlocal_type = ast_module.get(py, "Nonlocal").unwrap(); let assign_type = ast_module.get(py, "Assign").unwrap(); let aug_assign_type = ast_module.get(py, "AugAssign").unwrap(); let return_type = ast_module.get(py, "Return").unwrap(); let import_from_type = ast_module.get(py, "ImportFrom").unwrap(); let import_type = ast_module.get(py, "Import").unwrap(); let if_type = ast_module.get(py, "If").unwrap(); let while_type = ast_module.get(py, "While").unwrap(); let for_type = ast_module.get(py, "For").unwrap(); let expr_type = ast_module.get(py, "Expr").unwrap(); let break_type = ast_module.get(py, "Break").unwrap(); let delete_type = ast_module.get(py, "Delete").unwrap(); 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(); let raise_type = ast_module.get(py, "Raise").unwrap(); assert!(is_instance(&ast, &ast_type)); /* // TODO: implement Hash for PyObject. (trivial) let map = { let fields = ast.getattr(py, "_fields").unwrap(); let mut map = HashMap::new(); for field in fields.iter(py).unwrap() { let field = field.unwrap(); let value = ast.getattr(py, field).unwrap(); map.insert(field, value); } map }; */ if is_instance(&ast, &class_def_type) { let name = ast.getattr(py, "name").unwrap(); let bases = ast.getattr(py, "bases").unwrap(); //let keywords = ast.getattr(py, "keywords").unwrap(); let body = ast.getattr(py, "body").unwrap(); let decorator_list = ast.getattr(py, "decorator_list").unwrap(); let name = get_str(py, name); let bases = parse_list(py, bases, parse_expr); let body = parse_list(py, body, parse_statement); let decorator_list = parse_list(py, decorator_list, parse_expr); stmt::ClassDef(name, bases, vec!(), body, decorator_list) } 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 decorator_list = ast.getattr(py, "decorator_list").unwrap(); let returns = ast.getattr(py, "returns").unwrap(); let name = get_str(py, name); let args = parse_arguments(py, args); let body = parse_list(py, body, parse_statement); let decorator_list = parse_list(py, decorator_list, parse_expr); let returns = parse_optional_expr(py, returns); stmt::FunctionDef(name, args, body, decorator_list, returns) } else if is_instance(&ast, &global_type) { let names = ast.getattr(py, "names").unwrap(); let names = parse_list(py, names, get_str); stmt::Global(names) } else if is_instance(&ast, &nonlocal_type) { let names = ast.getattr(py, "names").unwrap(); let names = parse_list(py, names, get_str); stmt::Nonlocal(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 body = parse_list(py, body, parse_statement); let orelse = parse_list(py, orelse, parse_statement); 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 body = parse_list(py, body, parse_statement); let orelse = parse_list(py, orelse, parse_statement); 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(); let body = ast.getattr(py, "body").unwrap(); let orelse = ast.getattr(py, "orelse").unwrap(); let target = parse_expr(py, target); let iter = parse_expr(py, iter); let body = parse_list(py, body, parse_statement); let orelse = parse_list(py, orelse, parse_statement); 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 targets = parse_list(py, targets, parse_expr); let value = parse_expr(py, 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(); let value = ast.getattr(py, "value").unwrap(); let target = parse_expr(py, target); let op = parse_operator(py, op); let value = parse_expr(py, 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 module = get_str(py, module); let names = parse_list(py, names, parse_alias); if level == py.None() { stmt::ImportFrom(module, names, None) } else { let level = level.extract(py).unwrap(); stmt::ImportFrom(module, names, Some(level)) } } else if is_instance(&ast, &import_type) { let names = ast.getattr(py, "names").unwrap(); let names = parse_list(py, names, parse_alias); stmt::Import(names) } else if is_instance(&ast, &return_type) { let value = ast.getattr(py, "value").unwrap(); let value = parse_optional_expr(py, value); stmt::Return(value) } else if is_instance(&ast, &expr_type) { let value = ast.getattr(py, "value").unwrap(); let value = parse_expr(py, value); stmt::Expr(value) } else if is_instance(&ast, &break_type) { stmt::Break } else if is_instance(&ast, &delete_type) { let targets = ast.getattr(py, "targets").unwrap(); let targets = parse_list(py, targets, parse_expr); stmt::Delete(targets) } else if is_instance(&ast, &pass_type) { stmt::Pass } else if is_instance(&ast, &continue_type) { stmt::Continue } else if is_instance(&ast, &assert_type) { let test = ast.getattr(py, "test").unwrap(); let msg = ast.getattr(py, "msg").unwrap(); let test = parse_expr(py, test); let msg = parse_optional_expr(py, msg); stmt::Assert(test, 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 if is_instance(&ast, &raise_type) { let exc = ast.getattr(py, "exc").unwrap(); let cause = ast.getattr(py, "cause").unwrap(); let exc = parse_optional_expr(py, exc); let cause = parse_optional_expr(py, cause); stmt::Raise(exc, cause) } else { println!("stmt {}", ast); panic!() } } #[allow(dead_code)] pub fn convert_ast(name: String, module: &PyObject) -> Module { let gil = Python::acquire_gil(); let py = gil.python(); let builtins_module = py.import("builtins").unwrap(); let isinstance = builtins_module.get(py, "isinstance").unwrap(); let ast_module = py.import("ast").unwrap(); let module_type = ast_module.get(py, "Module").unwrap(); assert!(isinstance.call(py, (module, module_type), None).unwrap().is_true(py).unwrap()); let body = module.getattr(py, "body").unwrap(); let body = parse_list(py, body, parse_statement); Module{name: name, statements: body} }