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