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 } |