view src/ast_scope.rs @ 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
children 3bf4903d1d2c
line wrap: on
line source

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
}