blob: e1581a46cf3bb0572b59d01aa22086826780c196 [file] [log] [blame]
Jeremy Hylton8b966dc2001-04-09 04:35:35 +00001"""Module symbol-table generator"""
2
3from compiler import ast
Jeremy Hylton364f9b92001-04-12 06:40:42 +00004from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00005from compiler.misc import mangle
Jeremy Hyltonf870c952001-04-09 13:57:32 +00006import types
Jeremy Hylton8b966dc2001-04-09 04:35:35 +00007
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00008
Jeremy Hylton364f9b92001-04-12 06:40:42 +00009import sys
10
Jeremy Hyltonf870c952001-04-09 13:57:32 +000011MANGLE_LEN = 256
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000012
13class Scope:
14 # XXX how much information do I need about each name?
Jeremy Hyltonf870c952001-04-09 13:57:32 +000015 def __init__(self, name, module, klass=None):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000016 self.name = name
Jeremy Hyltonf870c952001-04-09 13:57:32 +000017 self.module = module
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000018 self.defs = {}
19 self.uses = {}
20 self.globals = {}
21 self.params = {}
Jeremy Hylton364f9b92001-04-12 06:40:42 +000022 self.frees = {}
23 self.cells = {}
Jeremy Hyltonf870c952001-04-09 13:57:32 +000024 self.children = []
Jeremy Hylton364f9b92001-04-12 06:40:42 +000025 # nested is true if the class could contain free variables,
26 # i.e. if it is nested within another function.
27 self.nested = None
Jeremy Hyltond4be10d2001-08-29 18:10:51 +000028 self.generator = None
Jeremy Hyltonf870c952001-04-09 13:57:32 +000029 self.klass = None
30 if klass is not None:
31 for i in range(len(klass)):
32 if klass[i] != '_':
33 self.klass = klass[i:]
34 break
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000035
36 def __repr__(self):
37 return "<%s: %s>" % (self.__class__.__name__, self.name)
38
Jeremy Hyltonf870c952001-04-09 13:57:32 +000039 def mangle(self, name):
40 if self.klass is None:
41 return name
Jeremy Hyltonc59e2202001-08-27 22:56:16 +000042 return mangle(name, self.klass)
Jeremy Hyltonf870c952001-04-09 13:57:32 +000043
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000044 def add_def(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000045 self.defs[self.mangle(name)] = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000046
47 def add_use(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000048 self.uses[self.mangle(name)] = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000049
50 def add_global(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000051 name = self.mangle(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000052 if self.uses.has_key(name) or self.defs.has_key(name):
53 pass # XXX warn about global following def/use
54 if self.params.has_key(name):
55 raise SyntaxError, "%s in %s is global and parameter" % \
56 (name, self.name)
57 self.globals[name] = 1
Jeremy Hyltonf870c952001-04-09 13:57:32 +000058 self.module.add_def(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000059
60 def add_param(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000061 name = self.mangle(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000062 self.defs[name] = 1
63 self.params[name] = 1
64
65 def get_names(self):
66 d = {}
67 d.update(self.defs)
68 d.update(self.uses)
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +000069 d.update(self.globals)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000070 return d.keys()
71
Jeremy Hyltonf870c952001-04-09 13:57:32 +000072 def add_child(self, child):
73 self.children.append(child)
74
75 def get_children(self):
76 return self.children
77
Jeremy Hylton364f9b92001-04-12 06:40:42 +000078 def DEBUG(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +000079 print >> sys.stderr, self.name, self.nested and "nested" or ""
80 print >> sys.stderr, "\tglobals: ", self.globals
81 print >> sys.stderr, "\tcells: ", self.cells
82 print >> sys.stderr, "\tdefs: ", self.defs
83 print >> sys.stderr, "\tuses: ", self.uses
84 print >> sys.stderr, "\tfrees:", self.frees
85
86 def check_name(self, name):
87 """Return scope of name.
88
89 The scope of a name could be LOCAL, GLOBAL, FREE, or CELL.
90 """
91 if self.globals.has_key(name):
92 return SC_GLOBAL
93 if self.cells.has_key(name):
94 return SC_CELL
95 if self.defs.has_key(name):
96 return SC_LOCAL
97 if self.nested and (self.frees.has_key(name) or
98 self.uses.has_key(name)):
99 return SC_FREE
100 if self.nested:
101 return SC_UNKNOWN
102 else:
103 return SC_GLOBAL
104
105 def get_free_vars(self):
106 if not self.nested:
107 return ()
108 free = {}
109 free.update(self.frees)
110 for name in self.uses.keys():
111 if not (self.defs.has_key(name) or
112 self.globals.has_key(name)):
113 free[name] = 1
114 return free.keys()
115
116 def handle_children(self):
117 for child in self.children:
118 frees = child.get_free_vars()
119 globals = self.add_frees(frees)
120 for name in globals:
121 child.force_global(name)
122
123 def force_global(self, name):
124 """Force name to be global in scope.
125
126 Some child of the current node had a free reference to name.
127 When the child was processed, it was labelled a free
128 variable. Now that all its enclosing scope have been
129 processed, the name is known to be a global or builtin. So
130 walk back down the child chain and set the name to be global
131 rather than free.
132
133 Be careful to stop if a child does not think the name is
Tim Peterse0c446b2001-10-18 21:57:37 +0000134 free.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000135 """
136 self.globals[name] = 1
137 if self.frees.has_key(name):
138 del self.frees[name]
139 for child in self.children:
140 if child.check_name(name) == SC_FREE:
141 child.force_global(name)
142
143 def add_frees(self, names):
144 """Process list of free vars from nested scope.
145
146 Returns a list of names that are either 1) declared global in the
147 parent or 2) undefined in a top-level parent. In either case,
148 the nested scope should treat them as globals.
149 """
150 child_globals = []
151 for name in names:
152 sc = self.check_name(name)
153 if self.nested:
154 if sc == SC_UNKNOWN or sc == SC_FREE \
155 or isinstance(self, ClassScope):
156 self.frees[name] = 1
157 elif sc == SC_GLOBAL:
158 child_globals.append(name)
159 elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
160 self.cells[name] = 1
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000161 elif sc != SC_CELL:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000162 child_globals.append(name)
163 else:
164 if sc == SC_LOCAL:
165 self.cells[name] = 1
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000166 elif sc != SC_CELL:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000167 child_globals.append(name)
168 return child_globals
169
170 def get_cell_vars(self):
171 return self.cells.keys()
172
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000173class ModuleScope(Scope):
174 __super_init = Scope.__init__
Tim Peterse0c446b2001-10-18 21:57:37 +0000175
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000176 def __init__(self):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000177 self.__super_init("global", self)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000178
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000179class FunctionScope(Scope):
180 pass
181
Raymond Hettinger354433a2004-05-19 08:20:33 +0000182class GenExprScope(Scope):
183 __super_init = Scope.__init__
184
185 __counter = 1
186
187 def __init__(self, module, klass=None):
188 i = self.__counter
189 self.__counter += 1
190 self.__super_init("generator expression<%d>"%i, module, klass)
191 self.add_param('[outmost-iterable]')
192
193 def get_names(self):
194 keys = Scope.get_names()
195 return keys
196
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000197class LambdaScope(FunctionScope):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000198 __super_init = Scope.__init__
199
200 __counter = 1
Tim Peterse0c446b2001-10-18 21:57:37 +0000201
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000202 def __init__(self, module, klass=None):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000203 i = self.__counter
204 self.__counter += 1
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000205 self.__super_init("lambda.%d" % i, module, klass)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000206
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000207class ClassScope(Scope):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000208 __super_init = Scope.__init__
209
210 def __init__(self, name, module):
211 self.__super_init(name, module, name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000212
213class SymbolVisitor:
214 def __init__(self):
215 self.scopes = {}
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000216 self.klass = None
Tim Peterse0c446b2001-10-18 21:57:37 +0000217
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000218 # node that define new scopes
219
220 def visitModule(self, node):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000221 scope = self.module = self.scopes[node] = ModuleScope()
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000222 self.visit(node.node, scope)
223
Barry Warsaw52acb492001-12-21 20:04:22 +0000224 visitExpression = visitModule
225
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000226 def visitFunction(self, node, parent):
227 parent.add_def(node.name)
228 for n in node.defaults:
229 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000230 scope = FunctionScope(node.name, self.module, self.klass)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000231 if parent.nested or isinstance(parent, FunctionScope):
232 scope.nested = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000233 self.scopes[node] = scope
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000234 self._do_args(scope, node.argnames)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000235 self.visit(node.code, scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000236 self.handle_free_vars(scope, parent)
Tim Peterse0c446b2001-10-18 21:57:37 +0000237
Raymond Hettinger354433a2004-05-19 08:20:33 +0000238 def visitGenExpr(self, node, parent):
239 scope = GenExprScope(self.module, self.klass);
240 if parent.nested or isinstance(parent, FunctionScope) \
241 or isinstance(parent, GenExprScope):
242 scope.nested = 1
243
244 self.scopes[node] = scope
245 self.visit(node.code, scope)
246
247 self.handle_free_vars(scope, parent)
248
249 def visitGenExprInner(self, node, scope):
250 for genfor in node.quals:
251 self.visit(genfor, scope)
252
253 self.visit(node.expr, scope)
254
255 def visitGenExprFor(self, node, scope):
256 self.visit(node.assign, scope, 1)
257 self.visit(node.iter, scope)
258 for if_ in node.ifs:
259 self.visit(if_, scope)
260
261 def visitGenExprIf(self, node, scope):
262 self.visit(node.test, scope)
Tim Peters4e0e1b62004-07-07 20:54:48 +0000263
Jeremy Hyltonead21f52003-08-28 02:09:26 +0000264 def visitLambda(self, node, parent, assign=0):
265 # Lambda is an expression, so it could appear in an expression
266 # context where assign is passed. The transformer should catch
267 # any code that has a lambda on the left-hand side.
Tim Peters4e0e1b62004-07-07 20:54:48 +0000268 assert not assign
269
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000270 for n in node.defaults:
271 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000272 scope = LambdaScope(self.module, self.klass)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000273 if parent.nested or isinstance(parent, FunctionScope):
274 scope.nested = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000275 self.scopes[node] = scope
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000276 self._do_args(scope, node.argnames)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000277 self.visit(node.code, scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000278 self.handle_free_vars(scope, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000279
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000280 def _do_args(self, scope, args):
281 for name in args:
282 if type(name) == types.TupleType:
283 self._do_args(scope, name)
284 else:
285 scope.add_param(name)
286
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000287 def handle_free_vars(self, scope, parent):
288 parent.add_child(scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000289 scope.handle_children()
290
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000291 def visitClass(self, node, parent):
292 parent.add_def(node.name)
293 for n in node.bases:
294 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000295 scope = ClassScope(node.name, self.module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000296 if parent.nested or isinstance(parent, FunctionScope):
297 scope.nested = 1
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000298 if node.doc is not None:
299 scope.add_def('__doc__')
300 scope.add_def('__module__')
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000301 self.scopes[node] = scope
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000302 prev = self.klass
303 self.klass = node.name
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000304 self.visit(node.code, scope)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000305 self.klass = prev
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000306 self.handle_free_vars(scope, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000307
308 # name can be a def or a use
309
310 # XXX a few calls and nodes expect a third "assign" arg that is
311 # true if the name is being used as an assignment. only
312 # expressions contained within statements may have the assign arg.
313
314 def visitName(self, node, scope, assign=0):
315 if assign:
316 scope.add_def(node.name)
317 else:
318 scope.add_use(node.name)
319
320 # operations that bind new names
321
322 def visitFor(self, node, scope):
323 self.visit(node.assign, scope, 1)
324 self.visit(node.list, scope)
325 self.visit(node.body, scope)
326 if node.else_:
327 self.visit(node.else_, scope)
328
329 def visitFrom(self, node, scope):
330 for name, asname in node.names:
331 if name == "*":
332 continue
333 scope.add_def(asname or name)
334
335 def visitImport(self, node, scope):
336 for name, asname in node.names:
337 i = name.find(".")
338 if i > -1:
339 name = name[:i]
340 scope.add_def(asname or name)
341
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000342 def visitGlobal(self, node, scope):
343 for name in node.names:
344 scope.add_global(name)
345
346 def visitAssign(self, node, scope):
347 """Propagate assignment flag down to child nodes.
348
349 The Assign node doesn't itself contains the variables being
350 assigned to. Instead, the children in node.nodes are visited
351 with the assign flag set to true. When the names occur in
352 those nodes, they are marked as defs.
353
354 Some names that occur in an assignment target are not bound by
355 the assignment, e.g. a name occurring inside a slice. The
356 visitor handles these nodes specially; they do not propagate
357 the assign flag to their children.
358 """
359 for n in node.nodes:
360 self.visit(n, scope, 1)
361 self.visit(node.expr, scope)
362
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000363 def visitAssName(self, node, scope, assign=1):
364 scope.add_def(node.name)
365
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000366 def visitAssAttr(self, node, scope, assign=0):
367 self.visit(node.expr, scope, 0)
368
369 def visitSubscript(self, node, scope, assign=0):
370 self.visit(node.expr, scope, 0)
371 for n in node.subs:
372 self.visit(n, scope, 0)
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000373
374 def visitSlice(self, node, scope, assign=0):
Jeremy Hylton652a2242001-09-14 22:45:57 +0000375 self.visit(node.expr, scope, 0)
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000376 if node.lower:
377 self.visit(node.lower, scope, 0)
378 if node.upper:
379 self.visit(node.upper, scope, 0)
Tim Peterse0c446b2001-10-18 21:57:37 +0000380
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000381 def visitAugAssign(self, node, scope):
Jeremy Hylton5c9aad62001-04-12 07:06:25 +0000382 # If the LHS is a name, then this counts as assignment.
383 # Otherwise, it's just use.
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000384 self.visit(node.node, scope)
Jeremy Hylton5c9aad62001-04-12 07:06:25 +0000385 if isinstance(node.node, ast.Name):
386 self.visit(node.node, scope, 1) # XXX worry about this
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000387 self.visit(node.expr, scope)
388
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000389 # prune if statements if tests are false
390
391 _const_types = types.StringType, types.IntType, types.FloatType
392
393 def visitIf(self, node, scope):
394 for test, body in node.tests:
395 if isinstance(test, ast.Const):
396 if type(test.value) in self._const_types:
397 if not test.value:
398 continue
399 self.visit(test, scope)
400 self.visit(body, scope)
401 if node.else_:
402 self.visit(node.else_, scope)
403
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000404 # a yield statement signals a generator
405
406 def visitYield(self, node, scope):
Jeremy Hylton652a2242001-09-14 22:45:57 +0000407 scope.generator = 1
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000408 self.visit(node.value, scope)
409
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000410def sort(l):
411 l = l[:]
412 l.sort()
413 return l
414
415def list_eq(l1, l2):
416 return sort(l1) == sort(l2)
417
418if __name__ == "__main__":
419 import sys
420 from compiler import parseFile, walk
421 import symtable
422
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000423 def get_names(syms):
424 return [s for s in [s.get_name() for s in syms.get_symbols()]
Tim Peterse0c446b2001-10-18 21:57:37 +0000425 if not (s.startswith('_[') or s.startswith('.'))]
426
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000427 for file in sys.argv[1:]:
428 print file
429 f = open(file)
430 buf = f.read()
431 f.close()
432 syms = symtable.symtable(buf, file, "exec")
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000433 mod_names = get_names(syms)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000434 tree = parseFile(file)
435 s = SymbolVisitor()
436 walk(tree, s)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000437
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000438 # compare module-level symbols
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000439 names2 = s.scopes[tree].get_names()
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000440
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000441 if not list_eq(mod_names, names2):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000442 print
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000443 print "oops", file
444 print sort(mod_names)
445 print sort(names2)
446 sys.exit(-1)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000447
448 d = {}
449 d.update(s.scopes)
450 del d[tree]
451 scopes = d.values()
452 del d
453
454 for s in syms.get_symbols():
455 if s.is_namespace():
456 l = [sc for sc in scopes
457 if sc.name == s.get_name()]
458 if len(l) > 1:
459 print "skipping", s.get_name()
460 else:
461 if not list_eq(get_names(s.get_namespace()),
462 l[0].get_names()):
463 print s.get_name()
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000464 print sort(get_names(s.get_namespace()))
465 print sort(l[0].get_names())
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000466 sys.exit(-1)