1
1
"""Interface to the compiler's internal symbol tables"""
4
from _symtable import USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM, \
5
DEF_STAR, DEF_DOUBLESTAR, DEF_INTUPLE, DEF_FREE, \
6
DEF_FREE_GLOBAL, DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND, \
7
OPT_IMPORT_STAR, OPT_EXEC, OPT_BARE_EXEC
4
from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM,
5
DEF_IMPORT, DEF_BOUND, OPT_IMPORT_STAR, OPT_EXEC, OPT_BARE_EXEC,
6
SCOPE_OFF, SCOPE_MASK, FREE, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
11
__all__ = ["symtable", "SymbolTable", "newSymbolTable", "Class",
11
__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"]
14
13
def symtable(code, filename, compile_type):
15
14
raw = _symtable.symtable(code, filename, compile_type)
16
15
for top in raw.itervalues():
17
16
if top.name == 'top':
19
return newSymbolTable(top, filename)
18
return _newSymbolTable(top, filename)
21
20
class SymbolTableFactory:
22
21
def __init__(self):
36
35
obj = self.__memo[key] = self.new(table, filename)
39
newSymbolTable = SymbolTableFactory()
42
if (flags & (USE | DEF_FREE)) \
43
and (flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)):
45
if flags & DEF_FREE_CLASS:
38
_newSymbolTable = SymbolTableFactory()
41
class SymbolTable(object):
50
43
def __init__(self, raw_table, filename):
51
44
self._table = raw_table
52
45
self._filename = filename
59
52
kind = "%s " % self.__class__.__name__
61
54
if self._table.name == "global":
62
return "<%sSymbolTable for module %s>" % (kind, self._filename)
55
return "<{0}SymbolTable for module {1}>".format(kind, self._filename)
64
return "<%sSymbolTable for %s in %s>" % (kind, self._table.name,
57
return "<{0}SymbolTable for {1} in {2}>".format(kind,
67
61
def get_type(self):
68
62
if self._table.type == _symtable.TYPE_MODULE:
72
66
if self._table.type == _symtable.TYPE_CLASS:
74
68
assert self._table.type in (1, 2, 3), \
75
"unexpected type: %s" % self._table.type
69
"unexpected type: {0}".format(self._table.type)
78
72
return self._table.id
116
110
return [self.lookup(ident) for ident in self.get_identifiers()]
118
112
def __check_children(self, name):
119
return [newSymbolTable(st, self._filename)
113
return [_newSymbolTable(st, self._filename)
120
114
for st in self._table.children
121
115
if st.name == name]
123
117
def get_children(self):
124
return [newSymbolTable(st, self._filename)
118
return [_newSymbolTable(st, self._filename)
125
119
for st in self._table.children]
127
122
class Function(SymbolTable):
129
124
# Default values for instance variables
149
144
def get_globals(self):
150
145
if self.__globals is None:
151
glob = DEF_GLOBAL | DEF_FREE_GLOBAL
152
self.__globals = self.__idents_matching(lambda x:x & glob)
146
glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
147
test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob
148
self.__globals = self.__idents_matching(test)
153
149
return self.__globals
155
151
def get_frees(self):
156
152
if self.__frees is None:
153
is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE
157
154
self.__frees = self.__idents_matching(is_free)
158
155
return self.__frees
160
158
class Class(SymbolTable):
169
167
self.__methods = tuple(d)
170
168
return self.__methods
171
class Symbol(object):
173
173
def __init__(self, name, flags, namespaces=None):
174
174
self.__name = name
175
175
self.__flags = flags
176
self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope()
176
177
self.__namespaces = namespaces or ()
178
179
def __repr__(self):
179
return "<symbol '%s'>" % self.__name
180
return "<symbol {0!r}>".format(self.__name)
181
182
def get_name(self):
182
183
return self.__name
188
189
return bool(self.__flags & DEF_PARAM)
190
191
def is_global(self):
191
return bool((self.__flags & DEF_GLOBAL)
192
or (self.__flags & DEF_FREE_GLOBAL))
192
return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT))
194
194
def is_vararg(self):
195
return bool(self.__flags & DEF_STAR)
195
warnings.warn("is_vararg() is obsolete and will be removed",
196
DeprecationWarning, 2)
197
199
def is_keywordarg(self):
198
return bool(self.__flags & DEF_DOUBLESTAR)
200
warnings.warn("is_keywordarg() is obsolete and will be removed",
201
DeprecationWarning, 2)
200
204
def is_local(self):
201
205
return bool(self.__flags & DEF_BOUND)
203
207
def is_free(self):
204
if (self.__flags & (USE | DEF_FREE)) \
205
and (self.__flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)):
207
if self.__flags & DEF_FREE_CLASS:
208
return bool(self.__scope == FREE)
211
210
def is_imported(self):
212
211
return bool(self.__flags & DEF_IMPORT)
215
214
return bool(self.__flags & DEF_LOCAL)
217
216
def is_in_tuple(self):
218
return bool(self.__flags & DEF_INTUPLE)
217
warnings.warn("is_in_tuple() is obsolete and will be removed",
218
DeprecationWarning, 2)
220
220
def is_namespace(self):
221
221
"""Returns true if name binding introduces new namespace.