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 }