Mercurial > python-compiler.rs
diff src/ast_convert.rs @ 13:38b0d63697b1
Import the full AST grammar from CPython 3.5.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Thu, 02 Jun 2016 05:33:23 +0100 |
parents | fa7e285f88e7 |
children | 719a27f1c1c7 |
line wrap: on
line diff
--- a/src/ast_convert.rs +++ b/src/ast_convert.rs @@ -1,4 +1,4 @@ -use python_ast::{Module, Statement, Expr, BinOp, UnaryOp}; +use python_ast::{Module, stmt, expr, expr_context, cmpop, operator, unaryop, arguments, arg, alias}; use cpython::{Python, PyObject}; use cpython::ObjectProtocol; //for call method @@ -30,7 +30,7 @@ fn parse_expr_vec(py: Python, ast: PyObj let arg = arg.unwrap(); let arg = parse_expr(py, arg); arguments.push(match arg { - Expr::Name(arg) => arg, + expr::Name(arg, expr_context::Load) => arg, _ => panic!() }); } @@ -40,7 +40,7 @@ fn parse_expr_vec(py: Python, ast: PyObj } } -fn parse_unaryop(py: Python, ast: PyObject) -> UnaryOp { +fn parse_unaryop(py: Python, ast: PyObject) -> unaryop { let builtins_module = py.import("builtins").unwrap(); let isinstance = builtins_module.get(py, "isinstance").unwrap(); @@ -50,22 +50,57 @@ fn parse_unaryop(py: Python, ast: PyObje 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, &uadd_type) { - UnaryOp::UAdd + 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 + unaryop::USub } else { - println!("UnaryOp {}", ast); - UnaryOp::Error + unreachable!() } } -fn parse_binop(py: Python, ast: PyObject) -> BinOp { +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 gt_type = ast_module.get(py, "Gt").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, >_type) { + cmpop::Gt + } else { + unreachable!() + } +} + +fn parse_operator(py: Python, ast: PyObject) -> operator { let builtins_module = py.import("builtins").unwrap(); let isinstance = builtins_module.get(py, "isinstance").unwrap(); @@ -76,36 +111,54 @@ fn parse_binop(py: Python, ast: PyObject 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 eq_type = ast_module.get(py, "Eq").unwrap(); - let lt_type = ast_module.get(py, "Lt").unwrap(); - let gt_type = ast_module.get(py, "Gt").unwrap(); - let sub_type = ast_module.get(py, "Sub").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) { - BinOp::BinAdd + operator::Add + } else if is_instance(&ast, &sub_type) { + operator::Sub } else if is_instance(&ast, &mult_type) { - BinOp::BinMult - } else if is_instance(&ast, &eq_type) { - BinOp::BinEq - } else if is_instance(&ast, <_type) { - BinOp::BinLt - } else if is_instance(&ast, >_type) { - BinOp::BinGt - } else if is_instance(&ast, &sub_type) { - BinOp::Sub + operator::Mult + } else if is_instance(&ast, &matmult_type) { + operator::MatMult } else if is_instance(&ast, &div_type) { - BinOp::Div + 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!("BinOp {}", ast); - BinOp::Error + println!("operator {}", ast); + panic!() } } -fn parse_expr(py: Python, ast: PyObject) -> Expr { +fn parse_expr(py: Python, ast: PyObject) -> expr { let builtins_module = py.import("builtins").unwrap(); let isinstance = builtins_module.get(py, "isinstance").unwrap(); @@ -126,14 +179,13 @@ fn parse_expr(py: Python, ast: PyObject) 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 alias_type = ast_module.get(py, "alias").unwrap(); assert!(is_instance(&ast, &ast_type)); if is_instance(&ast, &arg_type) { let arg = ast.getattr(py, "arg").unwrap(); let arg = get_str(py, arg); - Expr::Name(arg) + expr::Name(arg, expr_context::Load) } else if is_instance(&ast, &attribute_type) { let value = ast.getattr(py, "value").unwrap(); let attr = ast.getattr(py, "attr").unwrap(); @@ -141,23 +193,23 @@ fn parse_expr(py: Python, ast: PyObject) let value = parse_expr(py, value); let attr = get_str(py, attr); - Expr::Attribute(Box::new(value), attr) + expr::Attribute(Box::new(value), attr, expr_context::Load) } else if is_instance(&ast, &name_type) { let id = ast.getattr(py, "id").unwrap(); let id = get_str(py, id); - Expr::Name(id) + expr::Name(id, expr_context::Load) } else if is_instance(&ast, &name_constant_type) { let value = ast.getattr(py, "value").unwrap(); let value = get_str(py, value); - Expr::NameConstant(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) + 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) + expr::Str(s) } else if is_instance(&ast, &list_type) { let elts = ast.getattr(py, "elts").unwrap(); @@ -167,7 +219,7 @@ fn parse_expr(py: Python, ast: PyObject) elements.push(parse_expr(py, elt)); } - Expr::List(elements) + expr::List(elements, expr_context::Load) } else if is_instance(&ast, &unary_op_type) { let op = ast.getattr(py, "op").unwrap(); let operand = ast.getattr(py, "operand").unwrap(); @@ -175,21 +227,21 @@ fn parse_expr(py: Python, ast: PyObject) let op = parse_unaryop(py, op); let operand = parse_expr(py, operand); - Expr::UnaryOp(op, Box::new(operand)) + expr::UnaryOp(op, Box::new(operand)) } 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_binop(py, op); + let op = parse_operator(py, op); let right = parse_expr(py, right); - Expr::BinOp(Box::new(left), op, Box::new(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 keywords = ast.getattr(py, "keywords").unwrap(); let func = parse_expr(py, func); @@ -199,19 +251,15 @@ fn parse_expr(py: Python, ast: PyObject) arguments.push(parse_expr(py, arg)); } - Expr::Call(Box::new(func), arguments) - } else if is_instance(&ast, &alias_type) { - let name = ast.getattr(py, "name").unwrap(); - let asname = ast.getattr(py, "asname").unwrap(); + /* + let mut kwargs = vec!(); + for arg in keywords.iter(py).unwrap() { + let arg = arg.unwrap(); + kwargs.push(parse_expr(py, arg)); + } + */ - let name = get_str(py, name); - let asname = if asname == py.None() { - None - } else { - Some(get_str(py, asname)) - }; - - Expr::Alias(name, asname) + expr::Call(Box::new(func), arguments, vec!()) } else if is_instance(&ast, &compare_type) { let left = ast.getattr(py, "left").unwrap(); let ops = ast.getattr(py, "ops").unwrap(); @@ -224,7 +272,7 @@ fn parse_expr(py: Python, ast: PyObject) let mut new_ops = vec!(); for op in ops { let op = op.unwrap(); - let op = parse_binop(py, op); + let op = parse_cmpop(py, op); new_ops.push(op); } @@ -235,16 +283,63 @@ fn parse_expr(py: Python, ast: PyObject) new_comparators.push(comparator); } - Expr::Compare(Box::new(left), new_ops, new_comparators) + expr::Compare(Box::new(left), new_ops, new_comparators) } else { - println!("Expr {}", ast); - Expr::Error + println!("expr {}", ast); + unreachable!() } } -fn parse_statement(py: Python, ast: PyObject) -> Statement { - //Statement::FunctionDef(Expr::Name("function".to_string()), vec!(Expr::Name("a".to_string()), Expr::Name("b".to_string())), vec!()) - //Statement::If(Expr::BinOp(BinOp::BinEq, Box::new(Expr::Name("__name__".to_string())), Box::new(Expr::Str("__main__".to_string()))), vec!(Statement::Expr(Expr::Call(Box::new(Expr::Name("function".to_string())), vec!(Expr::Num(1), Expr::Num(2)))))) +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 = get_str(py, arg); + arguments.push(arg{arg: arg, annotation: None}); + } + arguments + }, + //vararg: Option<arg>, + vararg: None, + //kwonlyargs: Vec<arg>, + kwonlyargs: vec!(), + //kw_defaults: Vec<expr>, + kw_defaults: vec!(), + //kwarg: Option<arg>, + kwarg: None, + //defaults: Vec<expr> + defaults: vec!() + }; + 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(); @@ -307,21 +402,14 @@ fn parse_statement(py: Python, ast: PyOb statements.push(statement); } - Statement::ClassDef(name, nodes, statements) + stmt::ClassDef(name, nodes, vec!(), statements, vec!()) } 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 name = get_str(py, name); - let args = parse_expr_vec(py, args); - /* - let mut arguments = vec!(); - for arg in args.iter(py).unwrap() { - let arg = parse_expr(py, arg.unwrap()); - arguments.push(arg); - } - */ + let args = parse_arguments(py, args); let mut statements = vec!(); for statement in body.iter(py).unwrap() { @@ -329,7 +417,10 @@ fn parse_statement(py: Python, ast: PyOb statements.push(statement); } - Statement::FunctionDef(name, args, statements) + let decorators = vec!(); + let returns = None; + + stmt::FunctionDef(name, args, statements, decorators, returns) } else if is_instance(&ast, &global_type) { let names = ast.getattr(py, "names").unwrap(); @@ -340,7 +431,7 @@ fn parse_statement(py: Python, ast: PyOb globals.push(name); } - Statement::Global(globals) + stmt::Global(globals) } else if is_instance(&ast, &if_type) { let test = ast.getattr(py, "test").unwrap(); let body = ast.getattr(py, "body").unwrap(); @@ -362,7 +453,7 @@ fn parse_statement(py: Python, ast: PyOb orelse_.push(statement); } - Statement::If(test, statements, orelse_) + stmt::If(test, statements, orelse_) } else if is_instance(&ast, &while_type) { let test = ast.getattr(py, "test").unwrap(); let body = ast.getattr(py, "body").unwrap(); @@ -384,7 +475,7 @@ fn parse_statement(py: Python, ast: PyOb orelse_.push(statement); } - Statement::While(test, statements, orelse_) + stmt::While(test, statements, orelse_) } else if is_instance(&ast, &for_type) { let target = ast.getattr(py, "target").unwrap(); let iter = ast.getattr(py, "iter").unwrap(); @@ -408,7 +499,7 @@ fn parse_statement(py: Python, ast: PyOb orelse_.push(statement); } - Statement::For(target, iter, statements, orelse_) + stmt::For(target, iter, statements, orelse_) } else if is_instance(&ast, &assign_type) { let targets = ast.getattr(py, "targets").unwrap(); let value = ast.getattr(py, "value").unwrap(); @@ -422,21 +513,21 @@ fn parse_statement(py: Python, ast: PyOb let value = parse_expr(py, value); - Statement::Assign(arguments, value) + stmt::Assign(arguments, 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_binop(py, op); + let op = parse_operator(py, op); let value = parse_expr(py, value); - Statement::AugAssign(target, op, 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 level = ast.getattr(py, "level").unwrap(); let module = get_str(py, module); @@ -444,23 +535,29 @@ fn parse_statement(py: Python, ast: PyOb for alias in names.iter(py).unwrap() { let alias = alias.unwrap(); let alias = parse_expr(py, alias); - names_.push(alias); + println!("{:?}", alias); + // XXX + //names_.push(alias{name: alias, asname: alias}); } - Statement::ImportFrom(module, names_) + stmt::ImportFrom(module, names_, None) } else if is_instance(&ast, &return_type) { let value = ast.getattr(py, "value").unwrap(); - let value = parse_expr(py, value); - Statement::Return(value) + if value == py.None() { + stmt::Return(None) + } else { + let value = parse_expr(py, value); + stmt::Return(Some(value)) + } } else if is_instance(&ast, &expr_type) { let value = ast.getattr(py, "value").unwrap(); let value = parse_expr(py, value); - Statement::Expr(value) + stmt::Expr(value) } else if is_instance(&ast, &break_type) { - Statement::Break + stmt::Break } else { - println!("Statement {}", ast); - Statement::Error + println!("stmt {}", ast); + panic!() } }