Mercurial > python-compiler.rs
changeset 9:fa7e285f88e7
Add a scoping pass, associating each module/statement with a block.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Wed, 01 Jun 2016 22:17:28 +0100 |
parents | 94ff501bf336 |
children | 3bf4903d1d2c |
files | example/blocks.py src/ast_convert.rs src/ast_scope.rs src/main.rs src/python_ast.rs |
diffstat | 5 files changed, 146 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/example/blocks.py @@ -0,0 +1,5 @@ +def a(b): + def c(): + return b + return c() +print(a(1))
--- a/src/ast_convert.rs +++ b/src/ast_convert.rs @@ -9,7 +9,7 @@ fn get_str(py: Python, object: PyObject) string.to_mut().to_string() } -fn parse_expr_vec(py: Python, ast: PyObject) -> Vec<Expr> { +fn parse_expr_vec(py: Python, ast: PyObject) -> Vec<String> { let builtins_module = py.import("builtins").unwrap(); let isinstance = builtins_module.get(py, "isinstance").unwrap(); @@ -27,12 +27,16 @@ fn parse_expr_vec(py: Python, ast: PyObj let args = ast.getattr(py, "args").unwrap(); let mut arguments = vec!(); for arg in args.iter(py).unwrap() { - let arg = parse_expr(py, arg.unwrap()); - arguments.push(arg); + let arg = arg.unwrap(); + let arg = parse_expr(py, arg); + arguments.push(match arg { + Expr::Name(arg) => arg, + _ => panic!() + }); } arguments } else { - vec!(Expr::Error) + panic!() } }
new file mode 100644 --- /dev/null +++ b/src/ast_scope.rs @@ -0,0 +1,127 @@ +use python_ast::{Module, Statement, Expr}; + +use std::collections::HashMap; + +/* +trait Visitor<T> { + fn visit(&mut self, modules: Vec<Module>) -> Vec<T>; + fn visit_module(&mut self, block: &mut Block, module: Module) -> T; + fn visit_statement(&mut self, block: &mut Block, statement: Statement) -> Option<Box<T>>; + fn visit_expr(&mut self, block: &mut Block, expr: Expr) -> (); +} +*/ + +#[derive(Debug)] +struct Block { + statements: Vec<(Statement, Option<Box<Block>>)>, + bindings: Vec<String> +} + +#[derive(Debug)] +pub struct Scoping { + modules: HashMap<String, Block> +} + +/* +impl Visitor<Block> for Scoping { + fn visit(&mut self, modules: Vec<Module>) -> Vec<Block> { + println!("Scoping all modules."); + let mut blocks = vec!(); + for module in modules { + let mut block = Block{statements: vec!(), bindings: vec!()}; + let block = self.visit_module(&mut block, module); + blocks.push(block); + } + blocks + } + + fn visit_module(&mut self, block: &mut Block, module: Module) -> Block { + println!("Scoping module {}.", module.name); + for statement in module.statements { + self.visit_statement(block, statement); + } + println!("Module block: {:?}", block); + } + + fn visit_statement(&mut self, block: &mut Block, statement: Statement) -> Option<Box<Block>> { + match statement { + //Statement::ClassDef(a, b, c) => println!("{:?} {:?} {:?}", a, b, c), + Statement::FunctionDef(name, args, statements) => { + block.bindings.push(name.clone()); + //block.statements.insert(module.name, block); + println!("{:?} {:?}", name, args); + let mut function_block = Block{statements: vec!(), bindings: vec!()}; + for statement in statements { + let option = self.visit_statement(block, statement); + function_block.statements.push((statement, option)); + } + Some(Box::new(function_block)) + }, + Statement::For(target, iter, statements, orelse) => { + println!("for"); + for statement in statements { + let option = self.visit_statement(block, statement); + } + block.statements.push(name.clone()); + Some(Box::new()) + }, + Statement::Assign(lhs, rhs) => { + for target in lhs.clone() { + match target.clone() { + Expr::Name(name) => block.bindings.push(name), + _ => panic!() + } + self.visit_expr(block, target); + } + println!("assign {:?} {:?}", lhs, rhs); + Some() + }, + _ => { + println!("something"); + None + } + } + } + + fn visit_expr(&mut self, block: &mut Block, expr: Expr) -> () { + } +} +*/ + +/* +#[allow(dead_code)] +pub fn scope_ast(ast: Module) -> Scoping { + let mut modules = HashMap::new(); + let mut scoping = Scoping{modules: modules}; + scoping.visit(vec!(ast)); + scoping +} +*/ + +fn scope_statement(statement: Statement, block: &mut Block) { + let new_block = match statement.clone() { + Statement::FunctionDef(name, args, statements) => { + block.bindings.push(name.clone()); + let mut function_block = Block{statements: vec!(), bindings: args.clone()}; + for other_statement in statements { + scope_statement(other_statement, &mut function_block); + } + Some(Box::new(function_block)) + }, + _ => None + }; + block.statements.push((statement, new_block)); +} + +#[allow(dead_code)] +pub fn scope_ast(modules: Vec<Module>) -> Scoping { + let mut scoping = Scoping{modules: HashMap::new()}; + for module in modules { + let mut block = Block{statements: vec!(), bindings: vec!()}; + for statement in module.statements { + scope_statement(statement, &mut block); + } + scoping.modules.insert(module.name, block); + } + scoping +}
--- a/src/main.rs +++ b/src/main.rs @@ -5,9 +5,10 @@ mod python_parse; mod python_dump; mod python_ast; mod ast_convert; +mod ast_scope; mod ast_dump; //mod ast_rewrite; -mod ast_type; +//mod ast_type; use std::fs::File; use std::io::Read; @@ -49,6 +50,8 @@ fn main() { //python_dump::dump_module(&module); let module_ast = ast_convert::convert_ast("__main__".to_string(), &module); ast_dump::dump_ast(&module_ast); + let scoped_ast = ast_scope::scope_ast(vec!(module_ast)); + println!("{:#?}", scoped_ast); //ast_rewrite::rewrite_ast(module_ast); - ast_type::type_ast(module_ast); + //ast_type::type_ast(scoped_ast); }
--- a/src/python_ast.rs +++ b/src/python_ast.rs @@ -7,7 +7,7 @@ pub struct Module { #[derive(Clone, Debug)] pub enum Statement { ClassDef(String, Vec<Expr>, Vec<Statement>), - FunctionDef(String, Vec<Expr>, Vec<Statement>), + FunctionDef(String, Vec<String>, Vec<Statement>), Global(Vec<String>), If(Expr, Vec<Statement>, Vec<Statement>), For(Expr, Expr, Vec<Statement>, Vec<Statement>),