Mercurial > python-compiler.rs
view src/python_symtable.rs @ 96:20c1c9d7803d default tip
Fix dump failure in strings containing backquotes and double quotes.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 28 Jun 2016 01:40:55 +0100 |
parents | 4e62a8927dcc |
children |
line wrap: on
line source
use cpython::{Python, PyObject, PyErr, NoArgs}; use cpython::ObjectProtocol; //for call method #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Type { Module, Class, Function } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct SymbolTable { pub type_: Type, pub id: usize, pub name: String, pub lineno: usize, pub optimized: bool, pub nested: bool, pub has_exec: bool, pub identifiers: Vec<String>, pub symbols: Vec<Symbol>, pub children: Vec<SymbolTable> } impl SymbolTable { fn lookup(self, name: String) -> Option<Symbol> { for symbol in self.symbols { if symbol.name == name { return Some(symbol); } } None } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Symbol { pub name: String, pub referenced: bool, pub imported: bool, pub parameter: bool, pub global: bool, pub declared_global: bool, pub local: bool, pub free: bool, pub assigned: bool, pub namespaces: Vec<SymbolTable> } fn parse_symbol(py: Python, symbol: PyObject) -> Symbol { let get_name = symbol.getattr(py, "get_name").unwrap(); let name = get_name.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_referenced = symbol.getattr(py, "is_referenced").unwrap(); let referenced = is_referenced.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_imported = symbol.getattr(py, "is_imported").unwrap(); let imported = is_imported.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_parameter = symbol.getattr(py, "is_parameter").unwrap(); let parameter = is_parameter.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_global = symbol.getattr(py, "is_global").unwrap(); let global = is_global.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_declared_global = symbol.getattr(py, "is_declared_global").unwrap(); let declared_global = is_declared_global.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_local = symbol.getattr(py, "is_local").unwrap(); let local = is_local.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_free = symbol.getattr(py, "is_free").unwrap(); let free = is_free.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_assigned = symbol.getattr(py, "is_assigned").unwrap(); let assigned = is_assigned.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_namespace = symbol.getattr(py, "is_namespace").unwrap(); let namespace = is_namespace.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let namespaces = if namespace { let get_namespaces = symbol.getattr(py, "get_namespaces").unwrap(); let namespaces = get_namespaces.call(py, NoArgs, None).unwrap().iter(py).unwrap(); let mut new_namespaces = vec!(); for namespace in namespaces { let namespace = namespace.unwrap(); let symtable = parse_symtable(py, namespace); new_namespaces.push(symtable); } new_namespaces } else { vec!() }; Symbol{name: name, referenced: referenced, imported: imported, parameter: parameter, global: global, declared_global: declared_global, local: local, free: free, assigned: assigned, namespaces: namespaces} } fn parse_symtable(py: Python, symtable: PyObject) -> SymbolTable { let get_type = symtable.getattr(py, "get_type").unwrap(); let type_: String = get_type.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let type_ = if type_ == "module" { Type::Module } else if type_ == "class" { Type::Class } else if type_ == "function" { Type::Function } else { unreachable!(); }; let get_id = symtable.getattr(py, "get_id").unwrap(); let id = get_id.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let get_name = symtable.getattr(py, "get_name").unwrap(); let name = get_name.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let get_lineno = symtable.getattr(py, "get_lineno").unwrap(); let lineno = get_lineno.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_optimized = symtable.getattr(py, "is_optimized").unwrap(); let optimized = is_optimized.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let is_nested = symtable.getattr(py, "is_nested").unwrap(); let nested = is_nested.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let has_children = symtable.getattr(py, "has_children").unwrap(); let has_children = has_children.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let has_exec = symtable.getattr(py, "has_exec").unwrap(); let has_exec = has_exec.call(py, NoArgs, None).unwrap().extract(py).unwrap(); let identifiers = { let get_identifiers = symtable.getattr(py, "get_identifiers").unwrap(); let identifiers = get_identifiers.call(py, NoArgs, None).unwrap().iter(py).unwrap(); let mut new_identifiers = vec!(); for identifier in identifiers { let identifier = identifier.unwrap().extract(py).unwrap(); new_identifiers.push(identifier); } new_identifiers }; let symbols = { let get_symbols = symtable.getattr(py, "get_symbols").unwrap(); let symbols = get_symbols.call(py, NoArgs, None).unwrap().iter(py).unwrap(); let mut new_symbols = vec!(); for symbol in symbols { let symbol = symbol.unwrap(); let symbol = parse_symbol(py, symbol); new_symbols.push(symbol); } new_symbols }; let children = if has_children { let get_children = symtable.getattr(py, "get_children").unwrap(); let children = get_children.call(py, NoArgs, None).unwrap().iter(py).unwrap(); let mut new_children = vec!(); for child in children { let child = child.unwrap(); let child = parse_symtable(py, child); new_children.push(child); } new_children } else { vec!() }; SymbolTable{type_: type_, id: id, name: name, lineno: lineno, optimized: optimized, nested: nested, has_exec: has_exec, identifiers: identifiers, symbols: symbols, children: children} } pub fn generate_symtable(code: String, filename: &String) -> Result<SymbolTable, PyErr> { let gil = Python::acquire_gil(); let py = gil.python(); let symtable_module = py.import("symtable").unwrap(); let symtable_symtable = symtable_module.get(py, "symtable").unwrap(); let symtable = try!(symtable_symtable.call(py, (code, filename, "exec"), None)); //Ok(symtable) Ok(parse_symtable(py, symtable)) }