blob: 288872975a55f01f2ddaef32c50b0a9afca60c70 [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 Hylton4e1be722000-10-12 20:23:23 +0000442 self.emit('IMPORT_STAR')
443 # There can only be one name w/ from ... import *
444 assert len(node.names) == 1
445 return
446 else:
447 self.emit('IMPORT_FROM', name)
448 self._resolveDots(name)
449 self.storeName(alias or name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000450 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000451
Jeremy Hylton20516082000-09-01 20:33:26 +0000452 def _resolveDots(self, name):
453 elts = string.split(name, ".")
454 if len(elts) == 1:
455 return
456 for elt in elts[1:]:
457 self.emit('LOAD_ATTR', elt)
458
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000459 def visitGetattr(self, node):
460 self.visit(node.expr)
461 self.emit('LOAD_ATTR', node.attrname)
462
463 # next five implement assignments
464
465 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000466 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000467 self.visit(node.expr)
468 dups = len(node.nodes) - 1
469 for i in range(len(node.nodes)):
470 elt = node.nodes[i]
471 if i < dups:
472 self.emit('DUP_TOP')
473 if isinstance(elt, ast.Node):
474 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000475
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000476 def visitAssName(self, node):
477 if node.flags == 'OP_ASSIGN':
478 self.storeName(node.name)
479 elif node.flags == 'OP_DELETE':
480 self.delName(node.name)
481 else:
482 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000483
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000484 def visitAssAttr(self, node):
485 self.visit(node.expr)
486 if node.flags == 'OP_ASSIGN':
487 self.emit('STORE_ATTR', node.attrname)
488 elif node.flags == 'OP_DELETE':
489 self.emit('DELETE_ATTR', node.attrname)
490 else:
491 print "warning: unexpected flags:", node.flags
492 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000493
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000494 def visitAssTuple(self, node):
495 if findOp(node) != 'OP_DELETE':
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000496 self.emit('UNPACK_SEQUENCE', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000497 for child in node.nodes:
498 self.visit(child)
499
500 visitAssList = visitAssTuple
501
502 def visitExec(self, node):
503 self.visit(node.expr)
504 if node.locals is None:
505 self.emit('LOAD_CONST', None)
506 else:
507 self.visit(node.locals)
508 if node.globals is None:
509 self.emit('DUP_TOP')
510 else:
511 self.visit(node.globals)
512 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000513
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000514 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000515 pos = 0
516 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000517 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000518 self.visit(node.node)
519 for arg in node.args:
520 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000521 if isinstance(arg, ast.Keyword):
522 kw = kw + 1
523 else:
524 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000525 if node.star_args is not None:
526 self.visit(node.star_args)
527 if node.dstar_args is not None:
528 self.visit(node.dstar_args)
529 have_star = node.star_args is not None
530 have_dstar = node.dstar_args is not None
531 opcode = callfunc_opcode_info[have_star, have_dstar]
532 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000533
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000534 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000535 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000536 for child in node.nodes:
537 self.visit(child)
538 self.emit('PRINT_ITEM')
539
540 def visitPrintnl(self, node):
541 self.visitPrint(node)
542 self.emit('PRINT_NEWLINE')
543
544 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000545 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000546 self.visit(node.value)
547 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000548
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000549 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000550
551 def visitSlice(self, node):
552 self.visit(node.expr)
553 slice = 0
554 if node.lower:
555 self.visit(node.lower)
556 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000557 if node.upper:
558 self.visit(node.upper)
559 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000560 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000561 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000562 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000563 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000564 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000565 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000566 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000567 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000568 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000569
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000570 def visitSubscript(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000571 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000572 for sub in node.subs:
573 self.visit(sub)
574 if len(node.subs) > 1:
575 self.emit('BUILD_TUPLE', len(node.subs))
576 if node.flags == 'OP_APPLY':
577 self.emit('BINARY_SUBSCR')
578 elif node.flags == 'OP_ASSIGN':
579 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000580 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000581 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000582
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000583 # binary ops
584
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000585 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000586 self.visit(node.left)
587 self.visit(node.right)
588 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000589
590 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000591 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000592
593 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000594 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000595
596 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000597 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000598
599 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000600 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000601
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000602 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000603 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000604
Jeremy Hylton126960b2000-02-14 21:33:10 +0000605 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000606 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000607
608 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000609 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000610
611 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000612 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000613
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000614 # unary ops
615
616 def unaryOp(self, node, op):
617 self.visit(node.expr)
618 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000619
Jeremy Hylton126960b2000-02-14 21:33:10 +0000620 def visitInvert(self, node):
621 return self.unaryOp(node, 'UNARY_INVERT')
622
Jeremy Hylton40245602000-02-08 21:15:48 +0000623 def visitUnarySub(self, node):
624 return self.unaryOp(node, 'UNARY_NEGATIVE')
625
626 def visitUnaryAdd(self, node):
627 return self.unaryOp(node, 'UNARY_POSITIVE')
628
629 def visitUnaryInvert(self, node):
630 return self.unaryOp(node, 'UNARY_INVERT')
631
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000632 def visitNot(self, node):
633 return self.unaryOp(node, 'UNARY_NOT')
634
Jeremy Hylton40245602000-02-08 21:15:48 +0000635 def visitBackquote(self, node):
636 return self.unaryOp(node, 'UNARY_CONVERT')
637
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000638 # bit ops
639
Jeremy Hyltona5058122000-02-14 14:14:29 +0000640 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000641 self.visit(nodes[0])
642 for node in nodes[1:]:
643 self.visit(node)
644 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000645
646 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000647 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000648
649 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000650 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000651
652 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000653 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000654
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000655 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000656
Jeremy Hyltona5058122000-02-14 14:14:29 +0000657 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000658 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000659
Jeremy Hylton40245602000-02-08 21:15:48 +0000660 def visitTuple(self, node):
661 for elt in node.nodes:
662 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000663 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000664
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000665 def visitList(self, node):
666 for elt in node.nodes:
667 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000668 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000669
670 def visitSliceobj(self, node):
671 for child in node.nodes:
672 self.visit(child)
673 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000674
Jeremy Hyltona5058122000-02-14 14:14:29 +0000675 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000676 lineno = getattr(node, 'lineno', None)
677 if lineno:
678 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000679 self.emit('BUILD_MAP', 0)
680 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000681 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000682 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000683 self.emit('SET_LINENO', lineno2)
684 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000685 self.emit('DUP_TOP')
686 self.visit(v)
687 self.emit('ROT_TWO')
688 self.visit(k)
689 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000690
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000691class ModuleCodeGenerator(CodeGenerator):
692 super_init = CodeGenerator.__init__
693
694 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000695 # XXX <module> is ? in compile.c
696 self.graph = pyassem.PyFlowGraph("<module>", filename)
697 self.super_init(filename)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000698
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000699class FunctionCodeGenerator(CodeGenerator):
700 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000701
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 optimized = 1
703 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000704
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000705 def __init__(self, func, filename, isLambda=0):
706 if isLambda:
707 klass = FunctionCodeGenerator
708 name = "<lambda.%d>" % klass.lambdaCount
709 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000710 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000711 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000712 args, hasTupleArg = generateArgList(func.argnames)
713 self.graph = pyassem.PyFlowGraph(name, filename, args,
714 optimized=1)
715 self.isLambda = isLambda
716 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000717
718 lnf = walk(func.code, LocalNameFinder(args), 0)
719 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000720 if func.varargs:
721 self.graph.setFlag(CO_VARARGS)
722 if func.kwargs:
723 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000724 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000725 if hasTupleArg:
726 self.generateArgUnpack(func.argnames)
727
728 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000729 self.graph.startExitBlock()
730 if not self.isLambda:
731 self.emit('LOAD_CONST', None)
732 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000733
734 def generateArgUnpack(self, args):
735 count = 0
736 for arg in args:
737 if type(arg) == types.TupleType:
738 self.emit('LOAD_FAST', '.nested%d' % count)
739 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000740 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000741
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000742 def unpackSequence(self, tup):
743 self.emit('UNPACK_SEQUENCE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000744 for elt in tup:
745 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000746 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000747 else:
748 self.emit('STORE_FAST', elt)
749
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000750 unpackTuple = unpackSequence
751
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000752class ClassCodeGenerator(CodeGenerator):
753 super_init = CodeGenerator.__init__
754
755 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000756 self.graph = pyassem.PyFlowGraph(klass.name, filename,
757 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000758 self.super_init(filename)
759 lnf = walk(klass.code, LocalNameFinder(), 0)
760 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000761 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000762
763 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000764 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000765 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000766 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000767
768
769def generateArgList(arglist):
770 """Generate an arg list marking TupleArgs"""
771 args = []
772 extra = []
773 count = 0
774 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000775 if type(elt) == types.StringType:
776 args.append(elt)
777 elif type(elt) == types.TupleType:
778 args.append(TupleArg(count, elt))
779 count = count + 1
780 extra.extend(misc.flatten(elt))
781 else:
782 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000783 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000784
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000785class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000786 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000787 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000788 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000789 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000790 for name in names:
791 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000792
793 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000794 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000795 if self.names.has_elt(elt):
796 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000797 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000798
Jeremy Hyltona5058122000-02-14 14:14:29 +0000799 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000800 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000801
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000802 def visitGlobal(self, node):
803 for name in node.names:
804 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000805
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000806 def visitFunction(self, node):
807 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000808
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000809 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000810 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000811
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000812 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000813 for name, alias in node.names:
814 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000815
816 def visitFrom(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000817 for name, alias in node.names:
818 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000819
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000820 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000821 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000822
823 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000824 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000825
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000826def findOp(node):
827 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
828 v = OpFinder()
829 walk(node, v, 0)
830 return v.op
831
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000832class OpFinder:
833 def __init__(self):
834 self.op = None
835 def visitAssName(self, node):
836 if self.op is None:
837 self.op = node.flags
838 elif self.op != node.flags:
839 raise ValueError, "mixed ops in stmt"
840
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000841if __name__ == "__main__":
842 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000843
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000844 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000845 compile(file)