blob: a4c9e5b18f50267edf46253d180528e8510601ee [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
73 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +000074
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000075 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000076 self.emit = self.graph.emit
77 self.newBlock = self.graph.newBlock
78 self.startBlock = self.graph.startBlock
79 self.nextBlock = self.graph.nextBlock
80 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +000081
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000082 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000083 """Return a code object"""
84 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +000085
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000086 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +000087
Jeremy Hylton40245602000-02-08 21:15:48 +000088 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +000089 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +000090
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000091 def storeName(self, name):
92 self._nameOp('STORE', name)
93
94 def loadName(self, name):
95 self._nameOp('LOAD', name)
96
97 def delName(self, name):
98 self._nameOp('DELETE', name)
99
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000100 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000101 if not self.optimized:
102 self.emit(prefix + '_NAME', name)
103 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000104 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000105 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000106 else:
107 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000108
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000109 def set_lineno(self, node):
110 """Emit SET_LINENO if node has lineno attribute
111
112 Returns true if SET_LINENO was emitted.
113
114 There are no rules for when an AST node should have a lineno
115 attribute. The transformer and AST code need to be reviewed
116 and a consistent policy implemented and documented. Until
117 then, this method works around missing line numbers.
118 """
119 lineno = getattr(node, 'lineno', None)
120 if lineno is not None:
121 self.emit('SET_LINENO', lineno)
122 return 1
123 return 0
124
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000125 # The first few visitor methods handle nodes that generator new
126 # code objects
127
128 def visitModule(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000129 lnf = walk(node.node, LocalNameFinder(), 0)
130 self.locals.push(lnf.getLocals())
131 self.setDocstring(node.doc)
132 self.visit(node.node)
133 self.emit('LOAD_CONST', None)
134 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000135
136 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000137 self._visitFuncOrLambda(node, isLambda=0)
138 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000139
140 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000141 self._visitFuncOrLambda(node, isLambda=1)
142## self.storeName("<lambda>")
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000143
144 def _visitFuncOrLambda(self, node, isLambda):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000145 gen = FunctionCodeGenerator(node, self.filename, isLambda)
146 walk(node.code, gen)
147 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000148 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000149 for default in node.defaults:
150 self.visit(default)
151 self.emit('LOAD_CONST', gen.getCode())
152 self.emit('MAKE_FUNCTION', len(node.defaults))
153
154 def visitClass(self, node):
155 gen = ClassCodeGenerator(node, self.filename)
156 walk(node.code, gen)
157 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000158 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000159 self.emit('LOAD_CONST', node.name)
160 for base in node.bases:
161 self.visit(base)
162 self.emit('BUILD_TUPLE', len(node.bases))
163 self.emit('LOAD_CONST', gen.getCode())
164 self.emit('MAKE_FUNCTION', 0)
165 self.emit('CALL_FUNCTION', 0)
166 self.emit('BUILD_CLASS')
167 self.storeName(node.name)
168
169 # The rest are standard visitor methods
170
171 # The next few implement control-flow statements
172
173 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000174 end = self.newBlock()
175 numtests = len(node.tests)
176 for i in range(numtests):
177 test, suite = node.tests[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000178 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000179 self.visit(test)
180## if i == numtests - 1 and not node.else_:
181## nextTest = end
182## else:
183## nextTest = self.newBlock()
184 nextTest = self.newBlock()
185 self.emit('JUMP_IF_FALSE', nextTest)
186 self.nextBlock()
187 self.emit('POP_TOP')
188 self.visit(suite)
189 self.emit('JUMP_FORWARD', end)
190 self.nextBlock(nextTest)
191 self.emit('POP_TOP')
192 if node.else_:
193 self.visit(node.else_)
194 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000195
196 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000197 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000198
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000199 loop = self.newBlock()
200 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000201
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000202 after = self.newBlock()
203 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000204
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000205 self.nextBlock(loop)
206 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000207
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000208 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000209 self.visit(node.test)
210 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000211
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000212 self.nextBlock()
213 self.emit('POP_TOP')
214 self.visit(node.body)
215 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000216
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000217 self.startBlock(else_) # or just the POPs if not else clause
218 self.emit('POP_TOP')
219 self.emit('POP_BLOCK')
220 if node.else_:
221 self.visit(node.else_)
222 self.loops.pop()
223 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000224
225 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000226 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000227 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000228 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000229 self.loops.push(start)
230
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000231 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000232 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000233 self.visit(node.list)
234 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000235 self.nextBlock(start)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000236 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000237 self.emit('FOR_LOOP', anchor)
238 self.visit(node.assign)
239 self.visit(node.body)
240 self.emit('JUMP_ABSOLUTE', start)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000241 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000242 self.emit('POP_BLOCK')
243 if node.else_:
244 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000245 self.loops.pop()
246 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000247
248 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000249 if not self.loops:
250 raise SyntaxError, "'break' outside loop (%s, %d)" % \
251 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000252 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000253 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000254
255 def visitContinue(self, node):
256 if not self.loops:
257 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000258 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000259 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000260 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000261 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000262 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000263
264 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000265 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000266 for child in node.nodes[:-1]:
267 self.visit(child)
268 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000269 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000270 self.emit('POP_TOP')
271 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000272 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000273
274 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000275 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000276
277 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000278 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000279
280 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000281 self.visit(node.expr)
282 cleanup = self.newBlock()
283 for op, code in node.ops[:-1]:
284 self.visit(code)
285 self.emit('DUP_TOP')
286 self.emit('ROT_THREE')
287 self.emit('COMPARE_OP', op)
288 self.emit('JUMP_IF_FALSE', cleanup)
289 self.nextBlock()
290 self.emit('POP_TOP')
291 # now do the last comparison
292 if node.ops:
293 op, code = node.ops[-1]
294 self.visit(code)
295 self.emit('COMPARE_OP', op)
296 if len(node.ops) > 1:
297 end = self.newBlock()
298 self.emit('JUMP_FORWARD', end)
299 self.nextBlock(cleanup)
300 self.emit('ROT_TWO')
301 self.emit('POP_TOP')
302 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000303
304 # exception related
305
306 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000307 # XXX would be interesting to implement this via a
308 # transformation of the AST before this stage
309 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000310 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000311 # XXX __debug__ and AssertionError appear to be special cases
312 # -- they are always loaded as globals even if there are local
313 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000314 self.emit('LOAD_GLOBAL', '__debug__')
315 self.emit('JUMP_IF_FALSE', end)
316 self.nextBlock()
317 self.emit('POP_TOP')
318 self.visit(node.test)
319 self.emit('JUMP_IF_TRUE', end)
320 self.nextBlock()
321 self.emit('LOAD_GLOBAL', 'AssertionError')
322 self.visit(node.fail)
323 self.emit('RAISE_VARARGS', 2)
324 self.nextBlock(end)
325 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000326
327 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000328 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000329 n = 0
330 if node.expr1:
331 self.visit(node.expr1)
332 n = n + 1
333 if node.expr2:
334 self.visit(node.expr2)
335 n = n + 1
336 if node.expr3:
337 self.visit(node.expr3)
338 n = n + 1
339 self.emit('RAISE_VARARGS', n)
340
341 def visitTryExcept(self, node):
342 handlers = self.newBlock()
343 end = self.newBlock()
344 if node.else_:
345 lElse = self.newBlock()
346 else:
347 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000348 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000349 self.emit('SETUP_EXCEPT', handlers)
350 self.visit(node.body)
351 self.emit('POP_BLOCK')
352 self.emit('JUMP_FORWARD', lElse)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000353 self.nextBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000354
355 last = len(node.handlers) - 1
356 for i in range(len(node.handlers)):
357 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000358 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000359 if expr:
360 self.emit('DUP_TOP')
361 self.visit(expr)
362 self.emit('COMPARE_OP', 'exception match')
363 next = self.newBlock()
364 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000365 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000366 self.emit('POP_TOP')
367 self.emit('POP_TOP')
368 if target:
369 self.visit(target)
370 else:
371 self.emit('POP_TOP')
372 self.emit('POP_TOP')
373 self.visit(body)
374 self.emit('JUMP_FORWARD', end)
375 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000376 self.nextBlock(next)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000377 self.emit('POP_TOP')
378 self.emit('END_FINALLY')
379 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000380 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000381 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000382 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000383
384 def visitTryFinally(self, node):
385 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000386 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000387 self.emit('SETUP_FINALLY', final)
388 self.visit(node.body)
389 self.emit('POP_BLOCK')
390 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000391 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000392 self.visit(node.final)
393 self.emit('END_FINALLY')
394
395 # misc
396
397## def visitStmt(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000398## # nothing to do except walk the children
399## pass
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000400
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000401 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000402 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000403 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000404
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000405 def visitConst(self, node):
406 self.emit('LOAD_CONST', node.value)
407
408 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000409 self.emit('LOAD_CONST', node.name)
410 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000411
412 def visitGlobal(self, node):
413 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000414 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000415
416 def visitName(self, node):
417 self.loadName(node.name)
418
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000419 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000420 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000421
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000422 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000423 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000424 for name, alias in node.names:
425 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000426 self.emit('IMPORT_NAME', name)
Jeremy Hylton20516082000-09-01 20:33:26 +0000427 self._resolveDots(name)
428 self.storeName(alias or name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000429
430 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000431 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000432 fromlist = map(lambda (name, alias): name, node.names)
433 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000434 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000435 for name, alias in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000436 if name == '*':
437 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000438 self.emit('IMPORT_FROM', name)
Jeremy Hylton20516082000-09-01 20:33:26 +0000439 self._resolveDots(name)
440 self.storeName(alias or name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000441 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000442
Jeremy Hylton20516082000-09-01 20:33:26 +0000443 def _resolveDots(self, name):
444 elts = string.split(name, ".")
445 if len(elts) == 1:
446 return
447 for elt in elts[1:]:
448 self.emit('LOAD_ATTR', elt)
449
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000450 def visitGetattr(self, node):
451 self.visit(node.expr)
452 self.emit('LOAD_ATTR', node.attrname)
453
454 # next five implement assignments
455
456 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000457 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000458 self.visit(node.expr)
459 dups = len(node.nodes) - 1
460 for i in range(len(node.nodes)):
461 elt = node.nodes[i]
462 if i < dups:
463 self.emit('DUP_TOP')
464 if isinstance(elt, ast.Node):
465 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000466
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000467 def visitAssName(self, node):
468 if node.flags == 'OP_ASSIGN':
469 self.storeName(node.name)
470 elif node.flags == 'OP_DELETE':
471 self.delName(node.name)
472 else:
473 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000474
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000475 def visitAssAttr(self, node):
476 self.visit(node.expr)
477 if node.flags == 'OP_ASSIGN':
478 self.emit('STORE_ATTR', node.attrname)
479 elif node.flags == 'OP_DELETE':
480 self.emit('DELETE_ATTR', node.attrname)
481 else:
482 print "warning: unexpected flags:", node.flags
483 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000484
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000485 def visitAssTuple(self, node):
486 if findOp(node) != 'OP_DELETE':
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000487 self.emit('UNPACK_SEQUENCE', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000488 for child in node.nodes:
489 self.visit(child)
490
491 visitAssList = visitAssTuple
492
493 def visitExec(self, node):
494 self.visit(node.expr)
495 if node.locals is None:
496 self.emit('LOAD_CONST', None)
497 else:
498 self.visit(node.locals)
499 if node.globals is None:
500 self.emit('DUP_TOP')
501 else:
502 self.visit(node.globals)
503 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000504
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000505 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000506 pos = 0
507 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000508 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000509 self.visit(node.node)
510 for arg in node.args:
511 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000512 if isinstance(arg, ast.Keyword):
513 kw = kw + 1
514 else:
515 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000516 if node.star_args is not None:
517 self.visit(node.star_args)
518 if node.dstar_args is not None:
519 self.visit(node.dstar_args)
520 have_star = node.star_args is not None
521 have_dstar = node.dstar_args is not None
522 opcode = callfunc_opcode_info[have_star, have_dstar]
523 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000524
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000525 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000526 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000527 for child in node.nodes:
528 self.visit(child)
529 self.emit('PRINT_ITEM')
530
531 def visitPrintnl(self, node):
532 self.visitPrint(node)
533 self.emit('PRINT_NEWLINE')
534
535 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000536 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000537 self.visit(node.value)
538 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000539
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000540 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000541
542 def visitSlice(self, node):
543 self.visit(node.expr)
544 slice = 0
545 if node.lower:
546 self.visit(node.lower)
547 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000548 if node.upper:
549 self.visit(node.upper)
550 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000551 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000552 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000553 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000554 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000555 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000556 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000557 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000558 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000559 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000560
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000561 def visitSubscript(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000562 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000563 for sub in node.subs:
564 self.visit(sub)
565 if len(node.subs) > 1:
566 self.emit('BUILD_TUPLE', len(node.subs))
567 if node.flags == 'OP_APPLY':
568 self.emit('BINARY_SUBSCR')
569 elif node.flags == 'OP_ASSIGN':
570 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000571 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000572 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000573
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000574 # binary ops
575
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000576 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000577 self.visit(node.left)
578 self.visit(node.right)
579 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000580
581 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000582 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000583
584 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000585 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000586
587 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000588 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000589
590 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000591 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000592
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000593 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000594 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000595
Jeremy Hylton126960b2000-02-14 21:33:10 +0000596 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000597 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000598
599 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000600 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000601
602 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000603 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000604
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000605 # unary ops
606
607 def unaryOp(self, node, op):
608 self.visit(node.expr)
609 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000610
Jeremy Hylton126960b2000-02-14 21:33:10 +0000611 def visitInvert(self, node):
612 return self.unaryOp(node, 'UNARY_INVERT')
613
Jeremy Hylton40245602000-02-08 21:15:48 +0000614 def visitUnarySub(self, node):
615 return self.unaryOp(node, 'UNARY_NEGATIVE')
616
617 def visitUnaryAdd(self, node):
618 return self.unaryOp(node, 'UNARY_POSITIVE')
619
620 def visitUnaryInvert(self, node):
621 return self.unaryOp(node, 'UNARY_INVERT')
622
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000623 def visitNot(self, node):
624 return self.unaryOp(node, 'UNARY_NOT')
625
Jeremy Hylton40245602000-02-08 21:15:48 +0000626 def visitBackquote(self, node):
627 return self.unaryOp(node, 'UNARY_CONVERT')
628
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000629 # bit ops
630
Jeremy Hyltona5058122000-02-14 14:14:29 +0000631 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000632 self.visit(nodes[0])
633 for node in nodes[1:]:
634 self.visit(node)
635 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000636
637 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000638 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000639
640 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000641 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000642
643 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000644 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000645
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000646 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000647
Jeremy Hyltona5058122000-02-14 14:14:29 +0000648 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000649 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000650
Jeremy Hylton40245602000-02-08 21:15:48 +0000651 def visitTuple(self, node):
652 for elt in node.nodes:
653 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000654 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000655
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000656 def visitList(self, node):
657 for elt in node.nodes:
658 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000659 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000660
661 def visitSliceobj(self, node):
662 for child in node.nodes:
663 self.visit(child)
664 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000665
Jeremy Hyltona5058122000-02-14 14:14:29 +0000666 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000667 lineno = getattr(node, 'lineno', None)
668 if lineno:
669 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000670 self.emit('BUILD_MAP', 0)
671 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000672 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000673 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000674 self.emit('SET_LINENO', lineno2)
675 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000676 self.emit('DUP_TOP')
677 self.visit(v)
678 self.emit('ROT_TWO')
679 self.visit(k)
680 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000681
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000682class ModuleCodeGenerator(CodeGenerator):
683 super_init = CodeGenerator.__init__
684
685 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000686 # XXX <module> is ? in compile.c
687 self.graph = pyassem.PyFlowGraph("<module>", filename)
688 self.super_init(filename)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000689
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000690class FunctionCodeGenerator(CodeGenerator):
691 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000692
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000693 optimized = 1
694 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000695
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000696 def __init__(self, func, filename, isLambda=0):
697 if isLambda:
698 klass = FunctionCodeGenerator
699 name = "<lambda.%d>" % klass.lambdaCount
700 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000701 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000703 args, hasTupleArg = generateArgList(func.argnames)
704 self.graph = pyassem.PyFlowGraph(name, filename, args,
705 optimized=1)
706 self.isLambda = isLambda
707 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000708
709 lnf = walk(func.code, LocalNameFinder(args), 0)
710 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000711 if func.varargs:
712 self.graph.setFlag(CO_VARARGS)
713 if func.kwargs:
714 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000715 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000716 if hasTupleArg:
717 self.generateArgUnpack(func.argnames)
718
719 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000720 self.graph.startExitBlock()
721 if not self.isLambda:
722 self.emit('LOAD_CONST', None)
723 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724
725 def generateArgUnpack(self, args):
726 count = 0
727 for arg in args:
728 if type(arg) == types.TupleType:
729 self.emit('LOAD_FAST', '.nested%d' % count)
730 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000731 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000732
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000733 def unpackSequence(self, tup):
734 self.emit('UNPACK_SEQUENCE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000735 for elt in tup:
736 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000737 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000738 else:
739 self.emit('STORE_FAST', elt)
740
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000741 unpackTuple = unpackSequence
742
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000743class ClassCodeGenerator(CodeGenerator):
744 super_init = CodeGenerator.__init__
745
746 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000747 self.graph = pyassem.PyFlowGraph(klass.name, filename,
748 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000749 self.super_init(filename)
750 lnf = walk(klass.code, LocalNameFinder(), 0)
751 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000752 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000753
754 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000755 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000756 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000757 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000758
759
760def generateArgList(arglist):
761 """Generate an arg list marking TupleArgs"""
762 args = []
763 extra = []
764 count = 0
765 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000766 if type(elt) == types.StringType:
767 args.append(elt)
768 elif type(elt) == types.TupleType:
769 args.append(TupleArg(count, elt))
770 count = count + 1
771 extra.extend(misc.flatten(elt))
772 else:
773 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000774 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000775
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000776class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000777 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000778 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000779 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000780 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000781 for name in names:
782 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000783
784 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000785 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000786 if self.names.has_elt(elt):
787 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000788 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000789
Jeremy Hyltona5058122000-02-14 14:14:29 +0000790 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000791 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000792
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000793 def visitGlobal(self, node):
794 for name in node.names:
795 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000796
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000797 def visitFunction(self, node):
798 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000799
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000800 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000801 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000802
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000803 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000804 for name, alias in node.names:
805 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000806
807 def visitFrom(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
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000811 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000812 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000813
814 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000815 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000816
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000817def findOp(node):
818 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
819 v = OpFinder()
820 walk(node, v, 0)
821 return v.op
822
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000823class OpFinder:
824 def __init__(self):
825 self.op = None
826 def visitAssName(self, node):
827 if self.op is None:
828 self.op = node.flags
829 elif self.op != node.flags:
830 raise ValueError, "mixed ops in stmt"
831
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000832if __name__ == "__main__":
833 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000834
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000835 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000836 compile(file)