blob: 2a1b3081c66cdc05147e282fd15bd3e01b6967a8 [file] [log] [blame]
Jeremy Hylton53187f32000-02-08 19:01:29 +00001import os
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00002import marshal
Jeremy Hylton53187f32000-02-08 19:01:29 +00003import stat
Jeremy Hylton20516082000-09-01 20:33:26 +00004import string
Jeremy Hylton53187f32000-02-08 19:01:29 +00005import struct
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00006import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00007from cStringIO import StringIO
8
9from compiler import ast, parse, walk
10from compiler import pyassem, misc
Thomas Wouters46cc7c02000-08-12 20:32:46 +000011from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000012
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000013callfunc_opcode_info = {
14 # (Have *args, Have **args) : opcode
15 (0,0) : "CALL_FUNCTION",
16 (1,0) : "CALL_FUNCTION_VAR",
17 (0,1) : "CALL_FUNCTION_KW",
18 (1,1) : "CALL_FUNCTION_VAR_KW",
19}
20
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000021def compile(filename):
22 f = open(filename)
23 buf = f.read()
24 f.close()
25 mod = Module(buf, filename)
26 mod.compile()
27 f = open(filename + "c", "wb")
28 mod.dump(f)
29 f.close()
30
31class Module:
32 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000033 self.filename = filename
34 self.source = source
35 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000036
37 def compile(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000038 ast = parse(self.source)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000039 root, filename = os.path.split(self.filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000040 gen = ModuleCodeGenerator(filename)
41 walk(ast, gen, 1)
42 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000043
44 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000045 f.write(self.getPycHeader())
46 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000047
Jeremy Hylton20516082000-09-01 20:33:26 +000048 MAGIC = (50823 | (ord('\r')<<16) | (ord('\n')<<24))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000049
50 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000051 # compile.c uses marshal to write a long directly, with
52 # calling the interface that would also generate a 1-byte code
53 # to indicate the type of the value. simplest way to get the
54 # same effect is to call marshal and then skip the code.
55 magic = marshal.dumps(self.MAGIC)[1:]
56 mtime = os.stat(self.filename)[stat.ST_MTIME]
57 mtime = struct.pack('i', mtime)
58 return magic + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000059
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000060class CodeGenerator:
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000061
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000062 optimized = 0 # is namespace access optimized?
Jeremy Hylton3050d512000-02-12 00:12:38 +000063
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000064 def __init__(self, filename):
65## Subclasses must define a constructor that intializes self.graph
66## before calling this init function
Thomas Wouters46cc7c02000-08-12 20:32:46 +000067## self.graph = pyassem.PyFlowGraph()
68 self.filename = filename
69 self.locals = misc.Stack()
70 self.loops = misc.Stack()
71 self.curStack = 0
72 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +000073 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +000074 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +000075
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000076 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000077 self.emit = self.graph.emit
78 self.newBlock = self.graph.newBlock
79 self.startBlock = self.graph.startBlock
80 self.nextBlock = self.graph.nextBlock
81 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +000082
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000083 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000084 """Return a code object"""
85 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +000086
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000087 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +000088
Jeremy Hylton40245602000-02-08 21:15:48 +000089 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +000090 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +000091
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000092 def storeName(self, name):
93 self._nameOp('STORE', name)
94
95 def loadName(self, name):
96 self._nameOp('LOAD', name)
97
98 def delName(self, name):
99 self._nameOp('DELETE', name)
100
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000101 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000102 if not self.optimized:
103 self.emit(prefix + '_NAME', name)
104 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000105 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000106 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000107 else:
108 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000109
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000110 def set_lineno(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000111 """Emit SET_LINENO if node has lineno attribute and it is
112 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000113
114 Returns true if SET_LINENO was emitted.
115
116 There are no rules for when an AST node should have a lineno
117 attribute. The transformer and AST code need to be reviewed
118 and a consistent policy implemented and documented. Until
119 then, this method works around missing line numbers.
120 """
121 lineno = getattr(node, 'lineno', None)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000122 if lineno is not None and lineno != self.last_lineno:
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000123 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000124 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000125 return 1
126 return 0
127
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000128 # The first few visitor methods handle nodes that generator new
129 # code objects
130
131 def visitModule(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000132 lnf = walk(node.node, LocalNameFinder(), 0)
133 self.locals.push(lnf.getLocals())
134 self.setDocstring(node.doc)
135 self.visit(node.node)
136 self.emit('LOAD_CONST', None)
137 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000138
139 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000140 self._visitFuncOrLambda(node, isLambda=0)
141 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000142
143 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000144 self._visitFuncOrLambda(node, isLambda=1)
145## self.storeName("<lambda>")
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000146
147 def _visitFuncOrLambda(self, node, isLambda):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000148 gen = FunctionCodeGenerator(node, self.filename, isLambda)
149 walk(node.code, gen)
150 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000151 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000152 for default in node.defaults:
153 self.visit(default)
154 self.emit('LOAD_CONST', gen.getCode())
155 self.emit('MAKE_FUNCTION', len(node.defaults))
156
157 def visitClass(self, node):
158 gen = ClassCodeGenerator(node, self.filename)
159 walk(node.code, gen)
160 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000161 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000162 self.emit('LOAD_CONST', node.name)
163 for base in node.bases:
164 self.visit(base)
165 self.emit('BUILD_TUPLE', len(node.bases))
166 self.emit('LOAD_CONST', gen.getCode())
167 self.emit('MAKE_FUNCTION', 0)
168 self.emit('CALL_FUNCTION', 0)
169 self.emit('BUILD_CLASS')
170 self.storeName(node.name)
171
172 # The rest are standard visitor methods
173
174 # The next few implement control-flow statements
175
176 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000177 end = self.newBlock()
178 numtests = len(node.tests)
179 for i in range(numtests):
180 test, suite = node.tests[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000181 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000182 self.visit(test)
183## if i == numtests - 1 and not node.else_:
184## nextTest = end
185## else:
186## nextTest = self.newBlock()
187 nextTest = self.newBlock()
188 self.emit('JUMP_IF_FALSE', nextTest)
189 self.nextBlock()
190 self.emit('POP_TOP')
191 self.visit(suite)
192 self.emit('JUMP_FORWARD', end)
193 self.nextBlock(nextTest)
194 self.emit('POP_TOP')
195 if node.else_:
196 self.visit(node.else_)
197 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000198
199 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000200 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000201
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000202 loop = self.newBlock()
203 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000204
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000205 after = self.newBlock()
206 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000207
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000208 self.nextBlock(loop)
209 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000210
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000211 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000212 self.visit(node.test)
213 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000214
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000215 self.nextBlock()
216 self.emit('POP_TOP')
217 self.visit(node.body)
218 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000219
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000220 self.startBlock(else_) # or just the POPs if not else clause
221 self.emit('POP_TOP')
222 self.emit('POP_BLOCK')
223 if node.else_:
224 self.visit(node.else_)
225 self.loops.pop()
226 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000227
228 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000229 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000230 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000231 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000232 self.loops.push(start)
233
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000234 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000235 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236 self.visit(node.list)
237 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000238 self.nextBlock(start)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000239 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000240 self.emit('FOR_LOOP', anchor)
241 self.visit(node.assign)
242 self.visit(node.body)
243 self.emit('JUMP_ABSOLUTE', start)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000244 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000245 self.emit('POP_BLOCK')
246 if node.else_:
247 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000248 self.loops.pop()
249 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000250
251 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000252 if not self.loops:
253 raise SyntaxError, "'break' outside loop (%s, %d)" % \
254 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000255 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000256 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000257
258 def visitContinue(self, node):
259 if not self.loops:
260 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000261 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000262 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000263 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000264 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000265 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000266
267 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000268 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000269 for child in node.nodes[:-1]:
270 self.visit(child)
271 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000272 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000273 self.emit('POP_TOP')
274 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000275 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000276
277 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000278 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000279
280 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000281 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000282
283 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000284 self.visit(node.expr)
285 cleanup = self.newBlock()
286 for op, code in node.ops[:-1]:
287 self.visit(code)
288 self.emit('DUP_TOP')
289 self.emit('ROT_THREE')
290 self.emit('COMPARE_OP', op)
291 self.emit('JUMP_IF_FALSE', cleanup)
292 self.nextBlock()
293 self.emit('POP_TOP')
294 # now do the last comparison
295 if node.ops:
296 op, code = node.ops[-1]
297 self.visit(code)
298 self.emit('COMPARE_OP', op)
299 if len(node.ops) > 1:
300 end = self.newBlock()
301 self.emit('JUMP_FORWARD', end)
302 self.nextBlock(cleanup)
303 self.emit('ROT_TWO')
304 self.emit('POP_TOP')
305 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000306
307 # exception related
308
309 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000310 # XXX would be interesting to implement this via a
311 # transformation of the AST before this stage
312 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000313 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000314 # XXX __debug__ and AssertionError appear to be special cases
315 # -- they are always loaded as globals even if there are local
316 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000317 self.emit('LOAD_GLOBAL', '__debug__')
318 self.emit('JUMP_IF_FALSE', end)
319 self.nextBlock()
320 self.emit('POP_TOP')
321 self.visit(node.test)
322 self.emit('JUMP_IF_TRUE', end)
323 self.nextBlock()
324 self.emit('LOAD_GLOBAL', 'AssertionError')
325 self.visit(node.fail)
326 self.emit('RAISE_VARARGS', 2)
327 self.nextBlock(end)
328 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000329
330 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000331 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000332 n = 0
333 if node.expr1:
334 self.visit(node.expr1)
335 n = n + 1
336 if node.expr2:
337 self.visit(node.expr2)
338 n = n + 1
339 if node.expr3:
340 self.visit(node.expr3)
341 n = n + 1
342 self.emit('RAISE_VARARGS', n)
343
344 def visitTryExcept(self, node):
345 handlers = self.newBlock()
346 end = self.newBlock()
347 if node.else_:
348 lElse = self.newBlock()
349 else:
350 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000351 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000352 self.emit('SETUP_EXCEPT', handlers)
353 self.visit(node.body)
354 self.emit('POP_BLOCK')
355 self.emit('JUMP_FORWARD', lElse)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000356 self.nextBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000357
358 last = len(node.handlers) - 1
359 for i in range(len(node.handlers)):
360 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000361 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000362 if expr:
363 self.emit('DUP_TOP')
364 self.visit(expr)
365 self.emit('COMPARE_OP', 'exception match')
366 next = self.newBlock()
367 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000368 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369 self.emit('POP_TOP')
370 self.emit('POP_TOP')
371 if target:
372 self.visit(target)
373 else:
374 self.emit('POP_TOP')
375 self.emit('POP_TOP')
376 self.visit(body)
377 self.emit('JUMP_FORWARD', end)
378 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000379 self.nextBlock(next)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000380 self.emit('POP_TOP')
381 self.emit('END_FINALLY')
382 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000383 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000384 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000385 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000386
387 def visitTryFinally(self, node):
388 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000389 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000390 self.emit('SETUP_FINALLY', final)
391 self.visit(node.body)
392 self.emit('POP_BLOCK')
393 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000394 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000395 self.visit(node.final)
396 self.emit('END_FINALLY')
397
398 # misc
399
400## def visitStmt(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000401## # nothing to do except walk the children
402## pass
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000403
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000404 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000405 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000406 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000407
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000408 def visitConst(self, node):
409 self.emit('LOAD_CONST', node.value)
410
411 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000412 self.emit('LOAD_CONST', node.name)
413 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000414
415 def visitGlobal(self, node):
416 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000417 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000418
419 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000420 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000421 self.loadName(node.name)
422
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000423 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000424 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000425
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000426 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000427 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000428 for name, alias in node.names:
429 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000430 self.emit('IMPORT_NAME', name)
Jeremy Hylton20516082000-09-01 20:33:26 +0000431 self._resolveDots(name)
432 self.storeName(alias or name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000433
434 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000435 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000436 fromlist = map(lambda (name, alias): name, node.names)
437 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000438 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000439 for name, alias in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000440 if name == '*':
441 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000442 self.emit('IMPORT_FROM', name)
Jeremy Hylton20516082000-09-01 20:33:26 +0000443 self._resolveDots(name)
444 self.storeName(alias or name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000445 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000446
Jeremy Hylton20516082000-09-01 20:33:26 +0000447 def _resolveDots(self, name):
448 elts = string.split(name, ".")
449 if len(elts) == 1:
450 return
451 for elt in elts[1:]:
452 self.emit('LOAD_ATTR', elt)
453
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000454 def visitGetattr(self, node):
455 self.visit(node.expr)
456 self.emit('LOAD_ATTR', node.attrname)
457
458 # next five implement assignments
459
460 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000461 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000462 self.visit(node.expr)
463 dups = len(node.nodes) - 1
464 for i in range(len(node.nodes)):
465 elt = node.nodes[i]
466 if i < dups:
467 self.emit('DUP_TOP')
468 if isinstance(elt, ast.Node):
469 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000470
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000471 def visitAssName(self, node):
472 if node.flags == 'OP_ASSIGN':
473 self.storeName(node.name)
474 elif node.flags == 'OP_DELETE':
475 self.delName(node.name)
476 else:
477 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000478
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479 def visitAssAttr(self, node):
480 self.visit(node.expr)
481 if node.flags == 'OP_ASSIGN':
482 self.emit('STORE_ATTR', node.attrname)
483 elif node.flags == 'OP_DELETE':
484 self.emit('DELETE_ATTR', node.attrname)
485 else:
486 print "warning: unexpected flags:", node.flags
487 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000488
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000489 def visitAssTuple(self, node):
490 if findOp(node) != 'OP_DELETE':
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000491 self.emit('UNPACK_SEQUENCE', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000492 for child in node.nodes:
493 self.visit(child)
494
495 visitAssList = visitAssTuple
496
497 def visitExec(self, node):
498 self.visit(node.expr)
499 if node.locals is None:
500 self.emit('LOAD_CONST', None)
501 else:
502 self.visit(node.locals)
503 if node.globals is None:
504 self.emit('DUP_TOP')
505 else:
506 self.visit(node.globals)
507 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000508
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000509 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000510 pos = 0
511 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000512 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000513 self.visit(node.node)
514 for arg in node.args:
515 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000516 if isinstance(arg, ast.Keyword):
517 kw = kw + 1
518 else:
519 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000520 if node.star_args is not None:
521 self.visit(node.star_args)
522 if node.dstar_args is not None:
523 self.visit(node.dstar_args)
524 have_star = node.star_args is not None
525 have_dstar = node.dstar_args is not None
526 opcode = callfunc_opcode_info[have_star, have_dstar]
527 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000528
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000529 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000530 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000531 for child in node.nodes:
532 self.visit(child)
533 self.emit('PRINT_ITEM')
534
535 def visitPrintnl(self, node):
536 self.visitPrint(node)
537 self.emit('PRINT_NEWLINE')
538
539 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000540 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000541 self.visit(node.value)
542 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000543
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000544 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000545
546 def visitSlice(self, node):
547 self.visit(node.expr)
548 slice = 0
549 if node.lower:
550 self.visit(node.lower)
551 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000552 if node.upper:
553 self.visit(node.upper)
554 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000555 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000556 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000557 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000558 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000559 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000560 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000561 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000562 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000563 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000564
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000565 def visitSubscript(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000566 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000567 for sub in node.subs:
568 self.visit(sub)
569 if len(node.subs) > 1:
570 self.emit('BUILD_TUPLE', len(node.subs))
571 if node.flags == 'OP_APPLY':
572 self.emit('BINARY_SUBSCR')
573 elif node.flags == 'OP_ASSIGN':
574 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000575 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000576 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000577
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000578 # binary ops
579
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000580 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000581 self.visit(node.left)
582 self.visit(node.right)
583 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000584
585 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000586 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000587
588 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000589 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000590
591 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000592 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000593
594 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000595 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000596
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000597 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000598 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000599
Jeremy Hylton126960b2000-02-14 21:33:10 +0000600 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000601 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000602
603 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000604 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000605
606 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000607 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000608
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000609 # unary ops
610
611 def unaryOp(self, node, op):
612 self.visit(node.expr)
613 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000614
Jeremy Hylton126960b2000-02-14 21:33:10 +0000615 def visitInvert(self, node):
616 return self.unaryOp(node, 'UNARY_INVERT')
617
Jeremy Hylton40245602000-02-08 21:15:48 +0000618 def visitUnarySub(self, node):
619 return self.unaryOp(node, 'UNARY_NEGATIVE')
620
621 def visitUnaryAdd(self, node):
622 return self.unaryOp(node, 'UNARY_POSITIVE')
623
624 def visitUnaryInvert(self, node):
625 return self.unaryOp(node, 'UNARY_INVERT')
626
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000627 def visitNot(self, node):
628 return self.unaryOp(node, 'UNARY_NOT')
629
Jeremy Hylton40245602000-02-08 21:15:48 +0000630 def visitBackquote(self, node):
631 return self.unaryOp(node, 'UNARY_CONVERT')
632
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000633 # bit ops
634
Jeremy Hyltona5058122000-02-14 14:14:29 +0000635 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000636 self.visit(nodes[0])
637 for node in nodes[1:]:
638 self.visit(node)
639 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000640
641 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000642 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000643
644 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000645 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000646
647 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000648 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000649
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000650 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000651
Jeremy Hyltona5058122000-02-14 14:14:29 +0000652 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000653 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000654
Jeremy Hylton40245602000-02-08 21:15:48 +0000655 def visitTuple(self, node):
656 for elt in node.nodes:
657 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000658 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000659
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000660 def visitList(self, node):
661 for elt in node.nodes:
662 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000663 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000664
665 def visitSliceobj(self, node):
666 for child in node.nodes:
667 self.visit(child)
668 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000669
Jeremy Hyltona5058122000-02-14 14:14:29 +0000670 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000671 lineno = getattr(node, 'lineno', None)
672 if lineno:
673 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000674 self.emit('BUILD_MAP', 0)
675 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000676 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000677 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000678 self.emit('SET_LINENO', lineno2)
679 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000680 self.emit('DUP_TOP')
681 self.visit(v)
682 self.emit('ROT_TWO')
683 self.visit(k)
684 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000685
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000686class ModuleCodeGenerator(CodeGenerator):
687 super_init = CodeGenerator.__init__
688
689 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000690 # XXX <module> is ? in compile.c
691 self.graph = pyassem.PyFlowGraph("<module>", filename)
692 self.super_init(filename)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000693
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000694class FunctionCodeGenerator(CodeGenerator):
695 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000696
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000697 optimized = 1
698 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000699
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000700 def __init__(self, func, filename, isLambda=0):
701 if isLambda:
702 klass = FunctionCodeGenerator
703 name = "<lambda.%d>" % klass.lambdaCount
704 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000705 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000706 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000707 args, hasTupleArg = generateArgList(func.argnames)
708 self.graph = pyassem.PyFlowGraph(name, filename, args,
709 optimized=1)
710 self.isLambda = isLambda
711 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000712
713 lnf = walk(func.code, LocalNameFinder(args), 0)
714 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000715 if func.varargs:
716 self.graph.setFlag(CO_VARARGS)
717 if func.kwargs:
718 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000719 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000720 if hasTupleArg:
721 self.generateArgUnpack(func.argnames)
722
723 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000724 self.graph.startExitBlock()
725 if not self.isLambda:
726 self.emit('LOAD_CONST', None)
727 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000728
729 def generateArgUnpack(self, args):
730 count = 0
731 for arg in args:
732 if type(arg) == types.TupleType:
733 self.emit('LOAD_FAST', '.nested%d' % count)
734 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000735 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000736
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000737 def unpackSequence(self, tup):
738 self.emit('UNPACK_SEQUENCE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000739 for elt in tup:
740 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000741 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000742 else:
743 self.emit('STORE_FAST', elt)
744
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000745 unpackTuple = unpackSequence
746
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000747class ClassCodeGenerator(CodeGenerator):
748 super_init = CodeGenerator.__init__
749
750 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000751 self.graph = pyassem.PyFlowGraph(klass.name, filename,
752 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000753 self.super_init(filename)
754 lnf = walk(klass.code, LocalNameFinder(), 0)
755 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000756 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000757
758 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000759 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000760 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000761 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000762
763
764def generateArgList(arglist):
765 """Generate an arg list marking TupleArgs"""
766 args = []
767 extra = []
768 count = 0
769 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000770 if type(elt) == types.StringType:
771 args.append(elt)
772 elif type(elt) == types.TupleType:
773 args.append(TupleArg(count, elt))
774 count = count + 1
775 extra.extend(misc.flatten(elt))
776 else:
777 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000778 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000779
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000780class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000781 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000782 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000783 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000784 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000785 for name in names:
786 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000787
788 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000789 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000790 if self.names.has_elt(elt):
791 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000792 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000793
Jeremy Hyltona5058122000-02-14 14:14:29 +0000794 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000795 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000796
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000797 def visitGlobal(self, node):
798 for name in node.names:
799 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000800
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000801 def visitFunction(self, node):
802 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000803
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000804 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000805 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000806
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000807 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000808 for name, alias in node.names:
809 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000810
811 def visitFrom(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000812 for name, alias in node.names:
813 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000814
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000815 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000816 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000817
818 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000819 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000820
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000821def findOp(node):
822 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
823 v = OpFinder()
824 walk(node, v, 0)
825 return v.op
826
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000827class OpFinder:
828 def __init__(self):
829 self.op = None
830 def visitAssName(self, node):
831 if self.op is None:
832 self.op = node.flags
833 elif self.op != node.flags:
834 raise ValueError, "mixed ops in stmt"
835
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000836if __name__ == "__main__":
837 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000838
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000839 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000840 compile(file)