view src/ast_scope.rs @ 12:0e96c5bc401d

Remove the need for a Box in BlockStatement.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 02 Jun 2016 03:14:01 +0100
parents 5c169d5807b5
children 38b0d63697b1
line wrap: on
line source

use python_ast::{Module, Statement, Expr};

use std::collections::HashMap;

#[derive(Debug)]
struct BlockStatement {
    statement: Statement,
    block: Option<Block>
}

#[derive(Debug)]
struct Block {
    statements: Vec<BlockStatement>,
    bindings: Vec<String>
}

#[derive(Debug)]
pub struct Scoping {
    modules: HashMap<String, Block>
}

fn scope_expr(expr: Expr, block: &mut Block) {
    println!("{:?}", expr);
}

fn scope_statement(statement: Statement, block: &mut Block) {
    let new_block = match statement.clone() {
        Statement::Assign(targets, value) => {
            //scope_expr(value, &mut block);
            for target in targets {
                match target {
                    Expr::Name(name) => block.bindings.push(name),
                    _ => ()  // No new binding.
                }
            }
            None
        },
        Statement::FunctionDef(name, args, statements) => {
            block.bindings.push(name.clone());
            let mut function_block = Block{statements: vec!(), bindings: args.clone()};
            for statement in statements {
                scope_statement(statement, &mut function_block);
            }
            Some(function_block)
        },
        Statement::ImportFrom(module, names) => {
            for name in names {
                let name = match name {
                    Expr::Alias(name, asname) => (name, asname),
                    _ => panic!()
                };
                let nameas = name.1;
                let name = name.0;
                match nameas {
                    Some(name) => block.bindings.push(name),
                    None => block.bindings.push(name)
                }
            }
            None
        },
        _ => None
    };
    block.statements.push(BlockStatement{statement: statement, block: 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
}