xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/symtable.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Interface to the compiler's internal symbol tables"""
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard Workerimport _symtable
4*cda5da8dSAndroid Build Coastguard Workerfrom _symtable import (USE, DEF_GLOBAL, DEF_NONLOCAL, DEF_LOCAL, DEF_PARAM,
5*cda5da8dSAndroid Build Coastguard Worker     DEF_IMPORT, DEF_BOUND, DEF_ANNOT, SCOPE_OFF, SCOPE_MASK, FREE,
6*cda5da8dSAndroid Build Coastguard Worker     LOCAL, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL)
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Workerimport weakref
9*cda5da8dSAndroid Build Coastguard Worker
10*cda5da8dSAndroid Build Coastguard Worker__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"]
11*cda5da8dSAndroid Build Coastguard Worker
12*cda5da8dSAndroid Build Coastguard Workerdef symtable(code, filename, compile_type):
13*cda5da8dSAndroid Build Coastguard Worker    """ Return the toplevel *SymbolTable* for the source code.
14*cda5da8dSAndroid Build Coastguard Worker
15*cda5da8dSAndroid Build Coastguard Worker    *filename* is the name of the file with the code
16*cda5da8dSAndroid Build Coastguard Worker    and *compile_type* is the *compile()* mode argument.
17*cda5da8dSAndroid Build Coastguard Worker    """
18*cda5da8dSAndroid Build Coastguard Worker    top = _symtable.symtable(code, filename, compile_type)
19*cda5da8dSAndroid Build Coastguard Worker    return _newSymbolTable(top, filename)
20*cda5da8dSAndroid Build Coastguard Worker
21*cda5da8dSAndroid Build Coastguard Workerclass SymbolTableFactory:
22*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
23*cda5da8dSAndroid Build Coastguard Worker        self.__memo = weakref.WeakValueDictionary()
24*cda5da8dSAndroid Build Coastguard Worker
25*cda5da8dSAndroid Build Coastguard Worker    def new(self, table, filename):
26*cda5da8dSAndroid Build Coastguard Worker        if table.type == _symtable.TYPE_FUNCTION:
27*cda5da8dSAndroid Build Coastguard Worker            return Function(table, filename)
28*cda5da8dSAndroid Build Coastguard Worker        if table.type == _symtable.TYPE_CLASS:
29*cda5da8dSAndroid Build Coastguard Worker            return Class(table, filename)
30*cda5da8dSAndroid Build Coastguard Worker        return SymbolTable(table, filename)
31*cda5da8dSAndroid Build Coastguard Worker
32*cda5da8dSAndroid Build Coastguard Worker    def __call__(self, table, filename):
33*cda5da8dSAndroid Build Coastguard Worker        key = table, filename
34*cda5da8dSAndroid Build Coastguard Worker        obj = self.__memo.get(key, None)
35*cda5da8dSAndroid Build Coastguard Worker        if obj is None:
36*cda5da8dSAndroid Build Coastguard Worker            obj = self.__memo[key] = self.new(table, filename)
37*cda5da8dSAndroid Build Coastguard Worker        return obj
38*cda5da8dSAndroid Build Coastguard Worker
39*cda5da8dSAndroid Build Coastguard Worker_newSymbolTable = SymbolTableFactory()
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker
42*cda5da8dSAndroid Build Coastguard Workerclass SymbolTable:
43*cda5da8dSAndroid Build Coastguard Worker
44*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, raw_table, filename):
45*cda5da8dSAndroid Build Coastguard Worker        self._table = raw_table
46*cda5da8dSAndroid Build Coastguard Worker        self._filename = filename
47*cda5da8dSAndroid Build Coastguard Worker        self._symbols = {}
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
50*cda5da8dSAndroid Build Coastguard Worker        if self.__class__ == SymbolTable:
51*cda5da8dSAndroid Build Coastguard Worker            kind = ""
52*cda5da8dSAndroid Build Coastguard Worker        else:
53*cda5da8dSAndroid Build Coastguard Worker            kind = "%s " % self.__class__.__name__
54*cda5da8dSAndroid Build Coastguard Worker
55*cda5da8dSAndroid Build Coastguard Worker        if self._table.name == "top":
56*cda5da8dSAndroid Build Coastguard Worker            return "<{0}SymbolTable for module {1}>".format(kind, self._filename)
57*cda5da8dSAndroid Build Coastguard Worker        else:
58*cda5da8dSAndroid Build Coastguard Worker            return "<{0}SymbolTable for {1} in {2}>".format(kind,
59*cda5da8dSAndroid Build Coastguard Worker                                                            self._table.name,
60*cda5da8dSAndroid Build Coastguard Worker                                                            self._filename)
61*cda5da8dSAndroid Build Coastguard Worker
62*cda5da8dSAndroid Build Coastguard Worker    def get_type(self):
63*cda5da8dSAndroid Build Coastguard Worker        """Return the type of the symbol table.
64*cda5da8dSAndroid Build Coastguard Worker
65*cda5da8dSAndroid Build Coastguard Worker        The values returned are 'class', 'module' and
66*cda5da8dSAndroid Build Coastguard Worker        'function'.
67*cda5da8dSAndroid Build Coastguard Worker        """
68*cda5da8dSAndroid Build Coastguard Worker        if self._table.type == _symtable.TYPE_MODULE:
69*cda5da8dSAndroid Build Coastguard Worker            return "module"
70*cda5da8dSAndroid Build Coastguard Worker        if self._table.type == _symtable.TYPE_FUNCTION:
71*cda5da8dSAndroid Build Coastguard Worker            return "function"
72*cda5da8dSAndroid Build Coastguard Worker        if self._table.type == _symtable.TYPE_CLASS:
73*cda5da8dSAndroid Build Coastguard Worker            return "class"
74*cda5da8dSAndroid Build Coastguard Worker        assert self._table.type in (1, 2, 3), \
75*cda5da8dSAndroid Build Coastguard Worker               "unexpected type: {0}".format(self._table.type)
76*cda5da8dSAndroid Build Coastguard Worker
77*cda5da8dSAndroid Build Coastguard Worker    def get_id(self):
78*cda5da8dSAndroid Build Coastguard Worker        """Return an identifier for the table.
79*cda5da8dSAndroid Build Coastguard Worker        """
80*cda5da8dSAndroid Build Coastguard Worker        return self._table.id
81*cda5da8dSAndroid Build Coastguard Worker
82*cda5da8dSAndroid Build Coastguard Worker    def get_name(self):
83*cda5da8dSAndroid Build Coastguard Worker        """Return the table's name.
84*cda5da8dSAndroid Build Coastguard Worker
85*cda5da8dSAndroid Build Coastguard Worker        This corresponds to the name of the class, function
86*cda5da8dSAndroid Build Coastguard Worker        or 'top' if the table is for a class, function or
87*cda5da8dSAndroid Build Coastguard Worker        global respectively.
88*cda5da8dSAndroid Build Coastguard Worker        """
89*cda5da8dSAndroid Build Coastguard Worker        return self._table.name
90*cda5da8dSAndroid Build Coastguard Worker
91*cda5da8dSAndroid Build Coastguard Worker    def get_lineno(self):
92*cda5da8dSAndroid Build Coastguard Worker        """Return the number of the first line in the
93*cda5da8dSAndroid Build Coastguard Worker        block for the table.
94*cda5da8dSAndroid Build Coastguard Worker        """
95*cda5da8dSAndroid Build Coastguard Worker        return self._table.lineno
96*cda5da8dSAndroid Build Coastguard Worker
97*cda5da8dSAndroid Build Coastguard Worker    def is_optimized(self):
98*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the locals in the table
99*cda5da8dSAndroid Build Coastguard Worker        are optimizable.
100*cda5da8dSAndroid Build Coastguard Worker        """
101*cda5da8dSAndroid Build Coastguard Worker        return bool(self._table.type == _symtable.TYPE_FUNCTION)
102*cda5da8dSAndroid Build Coastguard Worker
103*cda5da8dSAndroid Build Coastguard Worker    def is_nested(self):
104*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the block is a nested class
105*cda5da8dSAndroid Build Coastguard Worker        or function."""
106*cda5da8dSAndroid Build Coastguard Worker        return bool(self._table.nested)
107*cda5da8dSAndroid Build Coastguard Worker
108*cda5da8dSAndroid Build Coastguard Worker    def has_children(self):
109*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the block has nested namespaces.
110*cda5da8dSAndroid Build Coastguard Worker        """
111*cda5da8dSAndroid Build Coastguard Worker        return bool(self._table.children)
112*cda5da8dSAndroid Build Coastguard Worker
113*cda5da8dSAndroid Build Coastguard Worker    def get_identifiers(self):
114*cda5da8dSAndroid Build Coastguard Worker        """Return a view object containing the names of symbols in the table.
115*cda5da8dSAndroid Build Coastguard Worker        """
116*cda5da8dSAndroid Build Coastguard Worker        return self._table.symbols.keys()
117*cda5da8dSAndroid Build Coastguard Worker
118*cda5da8dSAndroid Build Coastguard Worker    def lookup(self, name):
119*cda5da8dSAndroid Build Coastguard Worker        """Lookup a *name* in the table.
120*cda5da8dSAndroid Build Coastguard Worker
121*cda5da8dSAndroid Build Coastguard Worker        Returns a *Symbol* instance.
122*cda5da8dSAndroid Build Coastguard Worker        """
123*cda5da8dSAndroid Build Coastguard Worker        sym = self._symbols.get(name)
124*cda5da8dSAndroid Build Coastguard Worker        if sym is None:
125*cda5da8dSAndroid Build Coastguard Worker            flags = self._table.symbols[name]
126*cda5da8dSAndroid Build Coastguard Worker            namespaces = self.__check_children(name)
127*cda5da8dSAndroid Build Coastguard Worker            module_scope = (self._table.name == "top")
128*cda5da8dSAndroid Build Coastguard Worker            sym = self._symbols[name] = Symbol(name, flags, namespaces,
129*cda5da8dSAndroid Build Coastguard Worker                                               module_scope=module_scope)
130*cda5da8dSAndroid Build Coastguard Worker        return sym
131*cda5da8dSAndroid Build Coastguard Worker
132*cda5da8dSAndroid Build Coastguard Worker    def get_symbols(self):
133*cda5da8dSAndroid Build Coastguard Worker        """Return a list of *Symbol* instances for
134*cda5da8dSAndroid Build Coastguard Worker        names in the table.
135*cda5da8dSAndroid Build Coastguard Worker        """
136*cda5da8dSAndroid Build Coastguard Worker        return [self.lookup(ident) for ident in self.get_identifiers()]
137*cda5da8dSAndroid Build Coastguard Worker
138*cda5da8dSAndroid Build Coastguard Worker    def __check_children(self, name):
139*cda5da8dSAndroid Build Coastguard Worker        return [_newSymbolTable(st, self._filename)
140*cda5da8dSAndroid Build Coastguard Worker                for st in self._table.children
141*cda5da8dSAndroid Build Coastguard Worker                if st.name == name]
142*cda5da8dSAndroid Build Coastguard Worker
143*cda5da8dSAndroid Build Coastguard Worker    def get_children(self):
144*cda5da8dSAndroid Build Coastguard Worker        """Return a list of the nested symbol tables.
145*cda5da8dSAndroid Build Coastguard Worker        """
146*cda5da8dSAndroid Build Coastguard Worker        return [_newSymbolTable(st, self._filename)
147*cda5da8dSAndroid Build Coastguard Worker                for st in self._table.children]
148*cda5da8dSAndroid Build Coastguard Worker
149*cda5da8dSAndroid Build Coastguard Worker
150*cda5da8dSAndroid Build Coastguard Workerclass Function(SymbolTable):
151*cda5da8dSAndroid Build Coastguard Worker
152*cda5da8dSAndroid Build Coastguard Worker    # Default values for instance variables
153*cda5da8dSAndroid Build Coastguard Worker    __params = None
154*cda5da8dSAndroid Build Coastguard Worker    __locals = None
155*cda5da8dSAndroid Build Coastguard Worker    __frees = None
156*cda5da8dSAndroid Build Coastguard Worker    __globals = None
157*cda5da8dSAndroid Build Coastguard Worker    __nonlocals = None
158*cda5da8dSAndroid Build Coastguard Worker
159*cda5da8dSAndroid Build Coastguard Worker    def __idents_matching(self, test_func):
160*cda5da8dSAndroid Build Coastguard Worker        return tuple(ident for ident in self.get_identifiers()
161*cda5da8dSAndroid Build Coastguard Worker                     if test_func(self._table.symbols[ident]))
162*cda5da8dSAndroid Build Coastguard Worker
163*cda5da8dSAndroid Build Coastguard Worker    def get_parameters(self):
164*cda5da8dSAndroid Build Coastguard Worker        """Return a tuple of parameters to the function.
165*cda5da8dSAndroid Build Coastguard Worker        """
166*cda5da8dSAndroid Build Coastguard Worker        if self.__params is None:
167*cda5da8dSAndroid Build Coastguard Worker            self.__params = self.__idents_matching(lambda x:x & DEF_PARAM)
168*cda5da8dSAndroid Build Coastguard Worker        return self.__params
169*cda5da8dSAndroid Build Coastguard Worker
170*cda5da8dSAndroid Build Coastguard Worker    def get_locals(self):
171*cda5da8dSAndroid Build Coastguard Worker        """Return a tuple of locals in the function.
172*cda5da8dSAndroid Build Coastguard Worker        """
173*cda5da8dSAndroid Build Coastguard Worker        if self.__locals is None:
174*cda5da8dSAndroid Build Coastguard Worker            locs = (LOCAL, CELL)
175*cda5da8dSAndroid Build Coastguard Worker            test = lambda x: ((x >> SCOPE_OFF) & SCOPE_MASK) in locs
176*cda5da8dSAndroid Build Coastguard Worker            self.__locals = self.__idents_matching(test)
177*cda5da8dSAndroid Build Coastguard Worker        return self.__locals
178*cda5da8dSAndroid Build Coastguard Worker
179*cda5da8dSAndroid Build Coastguard Worker    def get_globals(self):
180*cda5da8dSAndroid Build Coastguard Worker        """Return a tuple of globals in the function.
181*cda5da8dSAndroid Build Coastguard Worker        """
182*cda5da8dSAndroid Build Coastguard Worker        if self.__globals is None:
183*cda5da8dSAndroid Build Coastguard Worker            glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
184*cda5da8dSAndroid Build Coastguard Worker            test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob
185*cda5da8dSAndroid Build Coastguard Worker            self.__globals = self.__idents_matching(test)
186*cda5da8dSAndroid Build Coastguard Worker        return self.__globals
187*cda5da8dSAndroid Build Coastguard Worker
188*cda5da8dSAndroid Build Coastguard Worker    def get_nonlocals(self):
189*cda5da8dSAndroid Build Coastguard Worker        """Return a tuple of nonlocals in the function.
190*cda5da8dSAndroid Build Coastguard Worker        """
191*cda5da8dSAndroid Build Coastguard Worker        if self.__nonlocals is None:
192*cda5da8dSAndroid Build Coastguard Worker            self.__nonlocals = self.__idents_matching(lambda x:x & DEF_NONLOCAL)
193*cda5da8dSAndroid Build Coastguard Worker        return self.__nonlocals
194*cda5da8dSAndroid Build Coastguard Worker
195*cda5da8dSAndroid Build Coastguard Worker    def get_frees(self):
196*cda5da8dSAndroid Build Coastguard Worker        """Return a tuple of free variables in the function.
197*cda5da8dSAndroid Build Coastguard Worker        """
198*cda5da8dSAndroid Build Coastguard Worker        if self.__frees is None:
199*cda5da8dSAndroid Build Coastguard Worker            is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE
200*cda5da8dSAndroid Build Coastguard Worker            self.__frees = self.__idents_matching(is_free)
201*cda5da8dSAndroid Build Coastguard Worker        return self.__frees
202*cda5da8dSAndroid Build Coastguard Worker
203*cda5da8dSAndroid Build Coastguard Worker
204*cda5da8dSAndroid Build Coastguard Workerclass Class(SymbolTable):
205*cda5da8dSAndroid Build Coastguard Worker
206*cda5da8dSAndroid Build Coastguard Worker    __methods = None
207*cda5da8dSAndroid Build Coastguard Worker
208*cda5da8dSAndroid Build Coastguard Worker    def get_methods(self):
209*cda5da8dSAndroid Build Coastguard Worker        """Return a tuple of methods declared in the class.
210*cda5da8dSAndroid Build Coastguard Worker        """
211*cda5da8dSAndroid Build Coastguard Worker        if self.__methods is None:
212*cda5da8dSAndroid Build Coastguard Worker            d = {}
213*cda5da8dSAndroid Build Coastguard Worker            for st in self._table.children:
214*cda5da8dSAndroid Build Coastguard Worker                d[st.name] = 1
215*cda5da8dSAndroid Build Coastguard Worker            self.__methods = tuple(d)
216*cda5da8dSAndroid Build Coastguard Worker        return self.__methods
217*cda5da8dSAndroid Build Coastguard Worker
218*cda5da8dSAndroid Build Coastguard Worker
219*cda5da8dSAndroid Build Coastguard Workerclass Symbol:
220*cda5da8dSAndroid Build Coastguard Worker
221*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, name, flags, namespaces=None, *, module_scope=False):
222*cda5da8dSAndroid Build Coastguard Worker        self.__name = name
223*cda5da8dSAndroid Build Coastguard Worker        self.__flags = flags
224*cda5da8dSAndroid Build Coastguard Worker        self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope()
225*cda5da8dSAndroid Build Coastguard Worker        self.__namespaces = namespaces or ()
226*cda5da8dSAndroid Build Coastguard Worker        self.__module_scope = module_scope
227*cda5da8dSAndroid Build Coastguard Worker
228*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
229*cda5da8dSAndroid Build Coastguard Worker        return "<symbol {0!r}>".format(self.__name)
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Worker    def get_name(self):
232*cda5da8dSAndroid Build Coastguard Worker        """Return a name of a symbol.
233*cda5da8dSAndroid Build Coastguard Worker        """
234*cda5da8dSAndroid Build Coastguard Worker        return self.__name
235*cda5da8dSAndroid Build Coastguard Worker
236*cda5da8dSAndroid Build Coastguard Worker    def is_referenced(self):
237*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is used in
238*cda5da8dSAndroid Build Coastguard Worker        its block.
239*cda5da8dSAndroid Build Coastguard Worker        """
240*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__flags & _symtable.USE)
241*cda5da8dSAndroid Build Coastguard Worker
242*cda5da8dSAndroid Build Coastguard Worker    def is_parameter(self):
243*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is a parameter.
244*cda5da8dSAndroid Build Coastguard Worker        """
245*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__flags & DEF_PARAM)
246*cda5da8dSAndroid Build Coastguard Worker
247*cda5da8dSAndroid Build Coastguard Worker    def is_global(self):
248*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is global.
249*cda5da8dSAndroid Build Coastguard Worker        """
250*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
251*cda5da8dSAndroid Build Coastguard Worker                    or (self.__module_scope and self.__flags & DEF_BOUND))
252*cda5da8dSAndroid Build Coastguard Worker
253*cda5da8dSAndroid Build Coastguard Worker    def is_nonlocal(self):
254*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is nonlocal."""
255*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__flags & DEF_NONLOCAL)
256*cda5da8dSAndroid Build Coastguard Worker
257*cda5da8dSAndroid Build Coastguard Worker    def is_declared_global(self):
258*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is declared global
259*cda5da8dSAndroid Build Coastguard Worker        with a global statement."""
260*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__scope == GLOBAL_EXPLICIT)
261*cda5da8dSAndroid Build Coastguard Worker
262*cda5da8dSAndroid Build Coastguard Worker    def is_local(self):
263*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is local.
264*cda5da8dSAndroid Build Coastguard Worker        """
265*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__scope in (LOCAL, CELL)
266*cda5da8dSAndroid Build Coastguard Worker                    or (self.__module_scope and self.__flags & DEF_BOUND))
267*cda5da8dSAndroid Build Coastguard Worker
268*cda5da8dSAndroid Build Coastguard Worker    def is_annotated(self):
269*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is annotated.
270*cda5da8dSAndroid Build Coastguard Worker        """
271*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__flags & DEF_ANNOT)
272*cda5da8dSAndroid Build Coastguard Worker
273*cda5da8dSAndroid Build Coastguard Worker    def is_free(self):
274*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if a referenced symbol is
275*cda5da8dSAndroid Build Coastguard Worker        not assigned to.
276*cda5da8dSAndroid Build Coastguard Worker        """
277*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__scope == FREE)
278*cda5da8dSAndroid Build Coastguard Worker
279*cda5da8dSAndroid Build Coastguard Worker    def is_imported(self):
280*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if the symbol is created from
281*cda5da8dSAndroid Build Coastguard Worker        an import statement.
282*cda5da8dSAndroid Build Coastguard Worker        """
283*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__flags & DEF_IMPORT)
284*cda5da8dSAndroid Build Coastguard Worker
285*cda5da8dSAndroid Build Coastguard Worker    def is_assigned(self):
286*cda5da8dSAndroid Build Coastguard Worker        """Return *True* if a symbol is assigned to."""
287*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__flags & DEF_LOCAL)
288*cda5da8dSAndroid Build Coastguard Worker
289*cda5da8dSAndroid Build Coastguard Worker    def is_namespace(self):
290*cda5da8dSAndroid Build Coastguard Worker        """Returns *True* if name binding introduces new namespace.
291*cda5da8dSAndroid Build Coastguard Worker
292*cda5da8dSAndroid Build Coastguard Worker        If the name is used as the target of a function or class
293*cda5da8dSAndroid Build Coastguard Worker        statement, this will be true.
294*cda5da8dSAndroid Build Coastguard Worker
295*cda5da8dSAndroid Build Coastguard Worker        Note that a single name can be bound to multiple objects.  If
296*cda5da8dSAndroid Build Coastguard Worker        is_namespace() is true, the name may also be bound to other
297*cda5da8dSAndroid Build Coastguard Worker        objects, like an int or list, that does not introduce a new
298*cda5da8dSAndroid Build Coastguard Worker        namespace.
299*cda5da8dSAndroid Build Coastguard Worker        """
300*cda5da8dSAndroid Build Coastguard Worker        return bool(self.__namespaces)
301*cda5da8dSAndroid Build Coastguard Worker
302*cda5da8dSAndroid Build Coastguard Worker    def get_namespaces(self):
303*cda5da8dSAndroid Build Coastguard Worker        """Return a list of namespaces bound to this name"""
304*cda5da8dSAndroid Build Coastguard Worker        return self.__namespaces
305*cda5da8dSAndroid Build Coastguard Worker
306*cda5da8dSAndroid Build Coastguard Worker    def get_namespace(self):
307*cda5da8dSAndroid Build Coastguard Worker        """Return the single namespace bound to this name.
308*cda5da8dSAndroid Build Coastguard Worker
309*cda5da8dSAndroid Build Coastguard Worker        Raises ValueError if the name is bound to multiple namespaces
310*cda5da8dSAndroid Build Coastguard Worker        or no namespace.
311*cda5da8dSAndroid Build Coastguard Worker        """
312*cda5da8dSAndroid Build Coastguard Worker        if len(self.__namespaces) == 0:
313*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("name is not bound to any namespaces")
314*cda5da8dSAndroid Build Coastguard Worker        elif len(self.__namespaces) > 1:
315*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("name is bound to multiple namespaces")
316*cda5da8dSAndroid Build Coastguard Worker        else:
317*cda5da8dSAndroid Build Coastguard Worker            return self.__namespaces[0]
318*cda5da8dSAndroid Build Coastguard Worker
319*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__":
320*cda5da8dSAndroid Build Coastguard Worker    import os, sys
321*cda5da8dSAndroid Build Coastguard Worker    with open(sys.argv[0]) as f:
322*cda5da8dSAndroid Build Coastguard Worker        src = f.read()
323*cda5da8dSAndroid Build Coastguard Worker    mod = symtable(src, os.path.split(sys.argv[0])[1], "exec")
324*cda5da8dSAndroid Build Coastguard Worker    for ident in mod.get_identifiers():
325*cda5da8dSAndroid Build Coastguard Worker        info = mod.lookup(ident)
326*cda5da8dSAndroid Build Coastguard Worker        print(info, info.is_local(), info.is_namespace())
327