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>),