symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/symtable.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Interface to the compiler's internal symbol tables"""
       
     2 
       
     3 import _symtable
       
     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)
       
     7 
       
     8 import warnings
       
     9 import weakref
       
    10 
       
    11 __all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"]
       
    12 
       
    13 def symtable(code, filename, compile_type):
       
    14     raw = _symtable.symtable(code, filename, compile_type)
       
    15     for top in raw.itervalues():
       
    16         if top.name == 'top':
       
    17             break
       
    18     return _newSymbolTable(top, filename)
       
    19 
       
    20 class SymbolTableFactory:
       
    21     def __init__(self):
       
    22         self.__memo = weakref.WeakValueDictionary()
       
    23 
       
    24     def new(self, table, filename):
       
    25         if table.type == _symtable.TYPE_FUNCTION:
       
    26             return Function(table, filename)
       
    27         if table.type == _symtable.TYPE_CLASS:
       
    28             return Class(table, filename)
       
    29         return SymbolTable(table, filename)
       
    30 
       
    31     def __call__(self, table, filename):
       
    32         key = table, filename
       
    33         obj = self.__memo.get(key, None)
       
    34         if obj is None:
       
    35             obj = self.__memo[key] = self.new(table, filename)
       
    36         return obj
       
    37 
       
    38 _newSymbolTable = SymbolTableFactory()
       
    39 
       
    40 
       
    41 class SymbolTable(object):
       
    42 
       
    43     def __init__(self, raw_table, filename):
       
    44         self._table = raw_table
       
    45         self._filename = filename
       
    46         self._symbols = {}
       
    47 
       
    48     def __repr__(self):
       
    49         if self.__class__ == SymbolTable:
       
    50             kind = ""
       
    51         else:
       
    52             kind = "%s " % self.__class__.__name__
       
    53 
       
    54         if self._table.name == "global":
       
    55             return "<{0}SymbolTable for module {1}>".format(kind, self._filename)
       
    56         else:
       
    57             return "<{0}SymbolTable for {1} in {2}>".format(kind,
       
    58                                                             self._table.name,
       
    59                                                             self._filename)
       
    60 
       
    61     def get_type(self):
       
    62         if self._table.type == _symtable.TYPE_MODULE:
       
    63             return "module"
       
    64         if self._table.type == _symtable.TYPE_FUNCTION:
       
    65             return "function"
       
    66         if self._table.type == _symtable.TYPE_CLASS:
       
    67             return "class"
       
    68         assert self._table.type in (1, 2, 3), \
       
    69                "unexpected type: {0}".format(self._table.type)
       
    70 
       
    71     def get_id(self):
       
    72         return self._table.id
       
    73 
       
    74     def get_name(self):
       
    75         return self._table.name
       
    76 
       
    77     def get_lineno(self):
       
    78         return self._table.lineno
       
    79 
       
    80     def is_optimized(self):
       
    81         return bool(self._table.type == _symtable.TYPE_FUNCTION
       
    82                     and not self._table.optimized)
       
    83 
       
    84     def is_nested(self):
       
    85         return bool(self._table.nested)
       
    86 
       
    87     def has_children(self):
       
    88         return bool(self._table.children)
       
    89 
       
    90     def has_exec(self):
       
    91         """Return true if the scope uses exec"""
       
    92         return bool(self._table.optimized & (OPT_EXEC | OPT_BARE_EXEC))
       
    93 
       
    94     def has_import_star(self):
       
    95         """Return true if the scope uses import *"""
       
    96         return bool(self._table.optimized & OPT_IMPORT_STAR)
       
    97 
       
    98     def get_identifiers(self):
       
    99         return self._table.symbols.keys()
       
   100 
       
   101     def lookup(self, name):
       
   102         sym = self._symbols.get(name)
       
   103         if sym is None:
       
   104             flags = self._table.symbols[name]
       
   105             namespaces = self.__check_children(name)
       
   106             sym = self._symbols[name] = Symbol(name, flags, namespaces)
       
   107         return sym
       
   108 
       
   109     def get_symbols(self):
       
   110         return [self.lookup(ident) for ident in self.get_identifiers()]
       
   111 
       
   112     def __check_children(self, name):
       
   113         return [_newSymbolTable(st, self._filename)
       
   114                 for st in self._table.children
       
   115                 if st.name == name]
       
   116 
       
   117     def get_children(self):
       
   118         return [_newSymbolTable(st, self._filename)
       
   119                 for st in self._table.children]
       
   120 
       
   121 
       
   122 class Function(SymbolTable):
       
   123 
       
   124     # Default values for instance variables
       
   125     __params = None
       
   126     __locals = None
       
   127     __frees = None
       
   128     __globals = None
       
   129 
       
   130     def __idents_matching(self, test_func):
       
   131         return tuple([ident for ident in self.get_identifiers()
       
   132                       if test_func(self._table.symbols[ident])])
       
   133 
       
   134     def get_parameters(self):
       
   135         if self.__params is None:
       
   136             self.__params = self.__idents_matching(lambda x:x & DEF_PARAM)
       
   137         return self.__params
       
   138 
       
   139     def get_locals(self):
       
   140         if self.__locals is None:
       
   141             self.__locals = self.__idents_matching(lambda x:x & DEF_BOUND)
       
   142         return self.__locals
       
   143 
       
   144     def get_globals(self):
       
   145         if self.__globals is None:
       
   146             glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
       
   147             test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob
       
   148             self.__globals = self.__idents_matching(test)
       
   149         return self.__globals
       
   150 
       
   151     def get_frees(self):
       
   152         if self.__frees is None:
       
   153             is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE
       
   154             self.__frees = self.__idents_matching(is_free)
       
   155         return self.__frees
       
   156 
       
   157 
       
   158 class Class(SymbolTable):
       
   159 
       
   160     __methods = None
       
   161 
       
   162     def get_methods(self):
       
   163         if self.__methods is None:
       
   164             d = {}
       
   165             for st in self._table.children:
       
   166                 d[st.name] = 1
       
   167             self.__methods = tuple(d)
       
   168         return self.__methods
       
   169 
       
   170 
       
   171 class Symbol(object):
       
   172 
       
   173     def __init__(self, name, flags, namespaces=None):
       
   174         self.__name = name
       
   175         self.__flags = flags
       
   176         self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope()
       
   177         self.__namespaces = namespaces or ()
       
   178 
       
   179     def __repr__(self):
       
   180         return "<symbol {0!r}>".format(self.__name)
       
   181 
       
   182     def get_name(self):
       
   183         return self.__name
       
   184 
       
   185     def is_referenced(self):
       
   186         return bool(self.__flags & _symtable.USE)
       
   187 
       
   188     def is_parameter(self):
       
   189         return bool(self.__flags & DEF_PARAM)
       
   190 
       
   191     def is_global(self):
       
   192         return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT))
       
   193 
       
   194     def is_vararg(self):
       
   195         warnings.warn("is_vararg() is obsolete and will be removed",
       
   196                       DeprecationWarning, 2)
       
   197         return False
       
   198 
       
   199     def is_keywordarg(self):
       
   200         warnings.warn("is_keywordarg() is obsolete and will be removed",
       
   201                       DeprecationWarning, 2)
       
   202         return False
       
   203 
       
   204     def is_local(self):
       
   205         return bool(self.__flags & DEF_BOUND)
       
   206 
       
   207     def is_free(self):
       
   208         return bool(self.__scope == FREE)
       
   209 
       
   210     def is_imported(self):
       
   211         return bool(self.__flags & DEF_IMPORT)
       
   212 
       
   213     def is_assigned(self):
       
   214         return bool(self.__flags & DEF_LOCAL)
       
   215 
       
   216     def is_in_tuple(self):
       
   217         warnings.warn("is_in_tuple() is obsolete and will be removed",
       
   218                       DeprecationWarning, 2)
       
   219 
       
   220     def is_namespace(self):
       
   221         """Returns true if name binding introduces new namespace.
       
   222 
       
   223         If the name is used as the target of a function or class
       
   224         statement, this will be true.
       
   225 
       
   226         Note that a single name can be bound to multiple objects.  If
       
   227         is_namespace() is true, the name may also be bound to other
       
   228         objects, like an int or list, that does not introduce a new
       
   229         namespace.
       
   230         """
       
   231         return bool(self.__namespaces)
       
   232 
       
   233     def get_namespaces(self):
       
   234         """Return a list of namespaces bound to this name"""
       
   235         return self.__namespaces
       
   236 
       
   237     def get_namespace(self):
       
   238         """Returns the single namespace bound to this name.
       
   239 
       
   240         Raises ValueError if the name is bound to multiple namespaces.
       
   241         """
       
   242         if len(self.__namespaces) != 1:
       
   243             raise ValueError, "name is bound to multiple namespaces"
       
   244         return self.__namespaces[0]
       
   245 
       
   246 if __name__ == "__main__":
       
   247     import os, sys
       
   248     src = open(sys.argv[0]).read()
       
   249     mod = symtable(src, os.path.split(sys.argv[0])[1], "exec")
       
   250     for ident in mod.get_identifiers():
       
   251         info = mod.lookup(ident)
       
   252         print info, info.is_local(), info.is_namespace()