Mercurial > python-compiler.rs
comparison src/python_symtable.rs @ 90:4e62a8927dcc
Add a symtable module, to obtain information about symbols.
| author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
|---|---|
| date | Thu, 23 Jun 2016 03:16:59 +0100 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 89:898876834564 | 90:4e62a8927dcc |
|---|---|
| 1 use cpython::{Python, PyObject, PyErr, NoArgs}; | |
| 2 use cpython::ObjectProtocol; //for call method | |
| 3 | |
| 4 #[derive(Clone, Debug, PartialEq, Eq, Hash)] | |
| 5 pub enum Type { | |
| 6 Module, | |
| 7 Class, | |
| 8 Function | |
| 9 } | |
| 10 | |
| 11 #[derive(Clone, Debug, PartialEq, Eq, Hash)] | |
| 12 pub struct SymbolTable { | |
| 13 pub type_: Type, | |
| 14 pub id: usize, | |
| 15 pub name: String, | |
| 16 pub lineno: usize, | |
| 17 pub optimized: bool, | |
| 18 pub nested: bool, | |
| 19 pub has_exec: bool, | |
| 20 pub identifiers: Vec<String>, | |
| 21 pub symbols: Vec<Symbol>, | |
| 22 pub children: Vec<SymbolTable> | |
| 23 } | |
| 24 | |
| 25 impl SymbolTable { | |
| 26 fn lookup(self, name: String) -> Option<Symbol> { | |
| 27 for symbol in self.symbols { | |
| 28 if symbol.name == name { | |
| 29 return Some(symbol); | |
| 30 } | |
| 31 } | |
| 32 None | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 #[derive(Clone, Debug, PartialEq, Eq, Hash)] | |
| 37 pub struct Symbol { | |
| 38 pub name: String, | |
| 39 pub referenced: bool, | |
| 40 pub imported: bool, | |
| 41 pub parameter: bool, | |
| 42 pub global: bool, | |
| 43 pub declared_global: bool, | |
| 44 pub local: bool, | |
| 45 pub free: bool, | |
| 46 pub assigned: bool, | |
| 47 pub namespaces: Vec<SymbolTable> | |
| 48 } | |
| 49 | |
| 50 fn parse_symbol(py: Python, symbol: PyObject) -> Symbol { | |
| 51 let get_name = symbol.getattr(py, "get_name").unwrap(); | |
| 52 let name = get_name.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 53 | |
| 54 let is_referenced = symbol.getattr(py, "is_referenced").unwrap(); | |
| 55 let referenced = is_referenced.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 56 | |
| 57 let is_imported = symbol.getattr(py, "is_imported").unwrap(); | |
| 58 let imported = is_imported.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 59 | |
| 60 let is_parameter = symbol.getattr(py, "is_parameter").unwrap(); | |
| 61 let parameter = is_parameter.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 62 | |
| 63 let is_global = symbol.getattr(py, "is_global").unwrap(); | |
| 64 let global = is_global.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 65 | |
| 66 let is_declared_global = symbol.getattr(py, "is_declared_global").unwrap(); | |
| 67 let declared_global = is_declared_global.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 68 | |
| 69 let is_local = symbol.getattr(py, "is_local").unwrap(); | |
| 70 let local = is_local.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 71 | |
| 72 let is_free = symbol.getattr(py, "is_free").unwrap(); | |
| 73 let free = is_free.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 74 | |
| 75 let is_assigned = symbol.getattr(py, "is_assigned").unwrap(); | |
| 76 let assigned = is_assigned.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 77 | |
| 78 let is_namespace = symbol.getattr(py, "is_namespace").unwrap(); | |
| 79 let namespace = is_namespace.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 80 | |
| 81 let namespaces = if namespace { | |
| 82 let get_namespaces = symbol.getattr(py, "get_namespaces").unwrap(); | |
| 83 let namespaces = get_namespaces.call(py, NoArgs, None).unwrap().iter(py).unwrap(); | |
| 84 let mut new_namespaces = vec!(); | |
| 85 for namespace in namespaces { | |
| 86 let namespace = namespace.unwrap(); | |
| 87 let symtable = parse_symtable(py, namespace); | |
| 88 new_namespaces.push(symtable); | |
| 89 } | |
| 90 new_namespaces | |
| 91 } else { | |
| 92 vec!() | |
| 93 }; | |
| 94 | |
| 95 Symbol{name: name, referenced: referenced, imported: imported, parameter: parameter, global: global, declared_global: declared_global, local: local, free: free, assigned: assigned, namespaces: namespaces} | |
| 96 } | |
| 97 | |
| 98 fn parse_symtable(py: Python, symtable: PyObject) -> SymbolTable { | |
| 99 let get_type = symtable.getattr(py, "get_type").unwrap(); | |
| 100 let type_: String = get_type.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 101 let type_ = if type_ == "module" { | |
| 102 Type::Module | |
| 103 } else if type_ == "class" { | |
| 104 Type::Class | |
| 105 } else if type_ == "function" { | |
| 106 Type::Function | |
| 107 } else { | |
| 108 unreachable!(); | |
| 109 }; | |
| 110 | |
| 111 let get_id = symtable.getattr(py, "get_id").unwrap(); | |
| 112 let id = get_id.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 113 | |
| 114 let get_name = symtable.getattr(py, "get_name").unwrap(); | |
| 115 let name = get_name.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 116 | |
| 117 let get_lineno = symtable.getattr(py, "get_lineno").unwrap(); | |
| 118 let lineno = get_lineno.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 119 | |
| 120 let is_optimized = symtable.getattr(py, "is_optimized").unwrap(); | |
| 121 let optimized = is_optimized.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 122 | |
| 123 let is_nested = symtable.getattr(py, "is_nested").unwrap(); | |
| 124 let nested = is_nested.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 125 | |
| 126 let has_children = symtable.getattr(py, "has_children").unwrap(); | |
| 127 let has_children = has_children.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 128 | |
| 129 let has_exec = symtable.getattr(py, "has_exec").unwrap(); | |
| 130 let has_exec = has_exec.call(py, NoArgs, None).unwrap().extract(py).unwrap(); | |
| 131 | |
| 132 let identifiers = { | |
| 133 let get_identifiers = symtable.getattr(py, "get_identifiers").unwrap(); | |
| 134 let identifiers = get_identifiers.call(py, NoArgs, None).unwrap().iter(py).unwrap(); | |
| 135 let mut new_identifiers = vec!(); | |
| 136 for identifier in identifiers { | |
| 137 let identifier = identifier.unwrap().extract(py).unwrap(); | |
| 138 new_identifiers.push(identifier); | |
| 139 } | |
| 140 new_identifiers | |
| 141 }; | |
| 142 | |
| 143 let symbols = { | |
| 144 let get_symbols = symtable.getattr(py, "get_symbols").unwrap(); | |
| 145 let symbols = get_symbols.call(py, NoArgs, None).unwrap().iter(py).unwrap(); | |
| 146 let mut new_symbols = vec!(); | |
| 147 for symbol in symbols { | |
| 148 let symbol = symbol.unwrap(); | |
| 149 let symbol = parse_symbol(py, symbol); | |
| 150 new_symbols.push(symbol); | |
| 151 } | |
| 152 new_symbols | |
| 153 }; | |
| 154 | |
| 155 let children = if has_children { | |
| 156 let get_children = symtable.getattr(py, "get_children").unwrap(); | |
| 157 let children = get_children.call(py, NoArgs, None).unwrap().iter(py).unwrap(); | |
| 158 let mut new_children = vec!(); | |
| 159 for child in children { | |
| 160 let child = child.unwrap(); | |
| 161 let child = parse_symtable(py, child); | |
| 162 new_children.push(child); | |
| 163 } | |
| 164 new_children | |
| 165 } else { | |
| 166 vec!() | |
| 167 }; | |
| 168 | |
| 169 SymbolTable{type_: type_, id: id, name: name, lineno: lineno, optimized: optimized, nested: nested, has_exec: has_exec, identifiers: identifiers, symbols: symbols, children: children} | |
| 170 } | |
| 171 | |
| 172 pub fn generate_symtable(code: String, filename: &String) -> Result<SymbolTable, PyErr> { | |
| 173 let gil = Python::acquire_gil(); | |
| 174 let py = gil.python(); | |
| 175 | |
| 176 let symtable_module = py.import("symtable").unwrap(); | |
| 177 let symtable_symtable = symtable_module.get(py, "symtable").unwrap(); | |
| 178 | |
| 179 let symtable = try!(symtable_symtable.call(py, (code, filename, "exec"), None)); | |
| 180 //Ok(symtable) | |
| 181 Ok(parse_symtable(py, symtable)) | |
| 182 } |
