blob: bf54c3203e0beb3f313ee865605d406855fe5a6e [file] [log] [blame]
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001import imp
Jeremy Hylton53187f32000-02-08 19:01:29 +00002import os
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00003import marshal
Jeremy Hylton53187f32000-02-08 19:01:29 +00004import stat
Jeremy Hylton20516082000-09-01 20:33:26 +00005import string
Jeremy Hylton53187f32000-02-08 19:01:29 +00006import struct
Jeremy Hylton9c048f92000-10-13 21:58:13 +00007import sys
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00008import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00009from cStringIO import StringIO
10
11from compiler import ast, parse, walk
12from compiler import pyassem, misc
Thomas Wouters46cc7c02000-08-12 20:32:46 +000013from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000014
Jeremy Hylton9c048f92000-10-13 21:58:13 +000015# Do we have Python 1.x or Python 2.x?
16try:
17 VERSION = sys.version_info[0]
18except AttributeError:
19 VERSION = 1
20
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000021callfunc_opcode_info = {
22 # (Have *args, Have **args) : opcode
23 (0,0) : "CALL_FUNCTION",
24 (1,0) : "CALL_FUNCTION_VAR",
25 (0,1) : "CALL_FUNCTION_KW",
26 (1,1) : "CALL_FUNCTION_VAR_KW",
27}
28
Jeremy Hylton9c048f92000-10-13 21:58:13 +000029def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000030 f = open(filename)
31 buf = f.read()
32 f.close()
33 mod = Module(buf, filename)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000034 mod.compile(display)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000035 f = open(filename + "c", "wb")
36 mod.dump(f)
37 f.close()
38
39class Module:
40 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000041 self.filename = filename
42 self.source = source
43 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000044
Jeremy Hylton9c048f92000-10-13 21:58:13 +000045 def compile(self, display=0):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000046 ast = parse(self.source)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000047 root, filename = os.path.split(self.filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000048 gen = ModuleCodeGenerator(filename)
49 walk(ast, gen, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000050 if display:
51 import pprint
52 print pprint.pprint(ast)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000053 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000054
55 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000056 f.write(self.getPycHeader())
57 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000058
Jeremy Hylton9c048f92000-10-13 21:58:13 +000059 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000060
61 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000062 # compile.c uses marshal to write a long directly, with
63 # calling the interface that would also generate a 1-byte code
64 # to indicate the type of the value. simplest way to get the
65 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000066 mtime = os.stat(self.filename)[stat.ST_MTIME]
67 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000068 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000069
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000070class CodeGenerator:
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000071
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000072 optimized = 0 # is namespace access optimized?
Jeremy Hylton3050d512000-02-12 00:12:38 +000073
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000074 def __init__(self, filename):
75## Subclasses must define a constructor that intializes self.graph
Jeremy Hylton9c048f92000-10-13 21:58:13 +000076## before calling this init function, e.g.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000077## self.graph = pyassem.PyFlowGraph()
78 self.filename = filename
79 self.locals = misc.Stack()
80 self.loops = misc.Stack()
81 self.curStack = 0
82 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +000083 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +000084 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +000085
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000086 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000087 self.emit = self.graph.emit
88 self.newBlock = self.graph.newBlock
89 self.startBlock = self.graph.startBlock
90 self.nextBlock = self.graph.nextBlock
91 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +000092
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000093 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000094 """Return a code object"""
95 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +000096
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000097 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +000098
Jeremy Hylton40245602000-02-08 21:15:48 +000099 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000100 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000101
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000102 def storeName(self, name):
103 self._nameOp('STORE', name)
104
105 def loadName(self, name):
106 self._nameOp('LOAD', name)
107
108 def delName(self, name):
109 self._nameOp('DELETE', name)
110
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000111 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000112 if not self.optimized:
113 self.emit(prefix + '_NAME', name)
114 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000115 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000116 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000117 else:
118 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000119
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000120 def set_lineno(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000121 """Emit SET_LINENO if node has lineno attribute and it is
122 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000123
124 Returns true if SET_LINENO was emitted.
125
126 There are no rules for when an AST node should have a lineno
127 attribute. The transformer and AST code need to be reviewed
128 and a consistent policy implemented and documented. Until
129 then, this method works around missing line numbers.
130 """
131 lineno = getattr(node, 'lineno', None)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000132 if lineno is not None and lineno != self.last_lineno:
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000133 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000134 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000135 return 1
136 return 0
137
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000138 # The first few visitor methods handle nodes that generator new
139 # code objects
140
141 def visitModule(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000142 lnf = walk(node.node, LocalNameFinder(), 0)
143 self.locals.push(lnf.getLocals())
144 self.setDocstring(node.doc)
145 self.visit(node.node)
146 self.emit('LOAD_CONST', None)
147 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000148
149 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000150 self._visitFuncOrLambda(node, isLambda=0)
151 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000152
153 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000154 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000155
156 def _visitFuncOrLambda(self, node, isLambda):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000157 gen = FunctionCodeGenerator(node, self.filename, isLambda)
158 walk(node.code, gen)
159 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000160 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000161 for default in node.defaults:
162 self.visit(default)
163 self.emit('LOAD_CONST', gen.getCode())
164 self.emit('MAKE_FUNCTION', len(node.defaults))
165
166 def visitClass(self, node):
167 gen = ClassCodeGenerator(node, self.filename)
168 walk(node.code, gen)
169 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000170 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000171 self.emit('LOAD_CONST', node.name)
172 for base in node.bases:
173 self.visit(base)
174 self.emit('BUILD_TUPLE', len(node.bases))
175 self.emit('LOAD_CONST', gen.getCode())
176 self.emit('MAKE_FUNCTION', 0)
177 self.emit('CALL_FUNCTION', 0)
178 self.emit('BUILD_CLASS')
179 self.storeName(node.name)
180
181 # The rest are standard visitor methods
182
183 # The next few implement control-flow statements
184
185 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000186 end = self.newBlock()
187 numtests = len(node.tests)
188 for i in range(numtests):
189 test, suite = node.tests[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000190 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000191 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000192 nextTest = self.newBlock()
193 self.emit('JUMP_IF_FALSE', nextTest)
194 self.nextBlock()
195 self.emit('POP_TOP')
196 self.visit(suite)
197 self.emit('JUMP_FORWARD', end)
198 self.nextBlock(nextTest)
199 self.emit('POP_TOP')
200 if node.else_:
201 self.visit(node.else_)
202 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000203
204 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000205 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000206
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000207 loop = self.newBlock()
208 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000209
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000210 after = self.newBlock()
211 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000212
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000213 self.nextBlock(loop)
214 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000215
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000216 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000217 self.visit(node.test)
218 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000219
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000220 self.nextBlock()
221 self.emit('POP_TOP')
222 self.visit(node.body)
223 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000224
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000225 self.startBlock(else_) # or just the POPs if not else clause
226 self.emit('POP_TOP')
227 self.emit('POP_BLOCK')
228 if node.else_:
229 self.visit(node.else_)
230 self.loops.pop()
231 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000232
233 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000234 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000235 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000236 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000237 self.loops.push(start)
238
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000239 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000240 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000241 self.visit(node.list)
242 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000243 self.nextBlock(start)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000244 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000245 self.emit('FOR_LOOP', anchor)
246 self.visit(node.assign)
247 self.visit(node.body)
248 self.emit('JUMP_ABSOLUTE', start)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000249 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000250 self.emit('POP_BLOCK')
251 if node.else_:
252 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000253 self.loops.pop()
254 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000255
256 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000257 if not self.loops:
258 raise SyntaxError, "'break' outside loop (%s, %d)" % \
259 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000260 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000261 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000262
263 def visitContinue(self, node):
264 if not self.loops:
265 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000266 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000267 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000268 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000269 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000270 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000271
272 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000273 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000274 for child in node.nodes[:-1]:
275 self.visit(child)
276 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000277 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000278 self.emit('POP_TOP')
279 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000280 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000281
282 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000283 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000284
285 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000286 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000287
288 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000289 self.visit(node.expr)
290 cleanup = self.newBlock()
291 for op, code in node.ops[:-1]:
292 self.visit(code)
293 self.emit('DUP_TOP')
294 self.emit('ROT_THREE')
295 self.emit('COMPARE_OP', op)
296 self.emit('JUMP_IF_FALSE', cleanup)
297 self.nextBlock()
298 self.emit('POP_TOP')
299 # now do the last comparison
300 if node.ops:
301 op, code = node.ops[-1]
302 self.visit(code)
303 self.emit('COMPARE_OP', op)
304 if len(node.ops) > 1:
305 end = self.newBlock()
306 self.emit('JUMP_FORWARD', end)
307 self.nextBlock(cleanup)
308 self.emit('ROT_TWO')
309 self.emit('POP_TOP')
310 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000311
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000312 # list comprehensions
313 __list_count = 0
314
315 def visitListComp(self, node):
316 # XXX would it be easier to transform the AST into the form it
317 # would have if the list comp were expressed as a series of
318 # for and if stmts and an explicit append?
319 self.set_lineno(node)
320 # setup list
321 append = "$append%d" % self.__list_count
322 self.__list_count = self.__list_count + 1
323 self.emit('BUILD_LIST', 0)
324 self.emit('DUP_TOP')
325 self.emit('LOAD_ATTR', 'append')
326 self.storeName(append)
327 l = len(node.quals)
328 stack = []
329 for i, for_ in zip(range(l), node.quals):
330 start, anchor = self.visit(for_)
331 cont = None
332 for if_ in for_.ifs:
333 if cont is None:
334 cont = self.newBlock()
335 self.visit(if_, cont)
336 stack.insert(0, (start, cont, anchor))
337
338 self.loadName(append)
339 self.visit(node.expr)
340 self.emit('CALL_FUNCTION', 1)
341 self.emit('POP_TOP')
342
343 for start, cont, anchor in stack:
344 if cont:
345 skip_one = self.newBlock()
346 self.emit('JUMP_FORWARD', skip_one)
347 self.nextBlock(cont)
348 self.emit('POP_TOP')
349 self.nextBlock(skip_one)
350 self.emit('JUMP_ABSOLUTE', start)
351 self.nextBlock(anchor)
352 self.delName(append)
353
354 self.__list_count = self.__list_count - 1
355
356 def visitListCompFor(self, node):
357 self.set_lineno(node)
358 start = self.newBlock()
359 anchor = self.newBlock()
360
361 self.visit(node.list)
362 self.visit(ast.Const(0))
363 self.emit('SET_LINENO', node.lineno)
364 self.nextBlock(start)
365 self.emit('FOR_LOOP', anchor)
366 self.visit(node.assign)
367 return start, anchor
368
369 def visitListCompIf(self, node, branch):
370 self.set_lineno(node)
371 self.visit(node.test)
372 self.emit('JUMP_IF_FALSE', branch)
373 self.newBlock()
374 self.emit('POP_TOP')
375
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000376 # exception related
377
378 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000379 # XXX would be interesting to implement this via a
380 # transformation of the AST before this stage
381 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000382 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000383 # XXX __debug__ and AssertionError appear to be special cases
384 # -- they are always loaded as globals even if there are local
385 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000386 self.emit('LOAD_GLOBAL', '__debug__')
387 self.emit('JUMP_IF_FALSE', end)
388 self.nextBlock()
389 self.emit('POP_TOP')
390 self.visit(node.test)
391 self.emit('JUMP_IF_TRUE', end)
392 self.nextBlock()
393 self.emit('LOAD_GLOBAL', 'AssertionError')
394 self.visit(node.fail)
395 self.emit('RAISE_VARARGS', 2)
396 self.nextBlock(end)
397 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000398
399 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000400 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000401 n = 0
402 if node.expr1:
403 self.visit(node.expr1)
404 n = n + 1
405 if node.expr2:
406 self.visit(node.expr2)
407 n = n + 1
408 if node.expr3:
409 self.visit(node.expr3)
410 n = n + 1
411 self.emit('RAISE_VARARGS', n)
412
413 def visitTryExcept(self, node):
414 handlers = self.newBlock()
415 end = self.newBlock()
416 if node.else_:
417 lElse = self.newBlock()
418 else:
419 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000420 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000421 self.emit('SETUP_EXCEPT', handlers)
422 self.visit(node.body)
423 self.emit('POP_BLOCK')
424 self.emit('JUMP_FORWARD', lElse)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000425 self.nextBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000426
427 last = len(node.handlers) - 1
428 for i in range(len(node.handlers)):
429 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000430 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000431 if expr:
432 self.emit('DUP_TOP')
433 self.visit(expr)
434 self.emit('COMPARE_OP', 'exception match')
435 next = self.newBlock()
436 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000437 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000438 self.emit('POP_TOP')
439 self.emit('POP_TOP')
440 if target:
441 self.visit(target)
442 else:
443 self.emit('POP_TOP')
444 self.emit('POP_TOP')
445 self.visit(body)
446 self.emit('JUMP_FORWARD', end)
447 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000448 self.nextBlock(next)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000449 self.emit('POP_TOP')
450 self.emit('END_FINALLY')
451 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000452 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000453 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000454 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000455
456 def visitTryFinally(self, node):
457 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000458 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000459 self.emit('SETUP_FINALLY', final)
460 self.visit(node.body)
461 self.emit('POP_BLOCK')
462 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000463 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000464 self.visit(node.final)
465 self.emit('END_FINALLY')
466
467 # misc
468
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000469 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000470 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000471 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000472
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000473 def visitConst(self, node):
474 self.emit('LOAD_CONST', node.value)
475
476 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000477 self.emit('LOAD_CONST', node.name)
478 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479
480 def visitGlobal(self, node):
481 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000482 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483
484 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000485 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000486 self.loadName(node.name)
487
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000488 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000489 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000490
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000491 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000492 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000493 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000494 if VERSION > 1:
495 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000496 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000497 mod = string.split(name, ".")[0]
498 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000499
500 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000501 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000502 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000503 if VERSION > 1:
504 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000505 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000506 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000507 if VERSION > 1:
508 if name == '*':
509 self.namespace = 0
510 self.emit('IMPORT_STAR')
511 # There can only be one name w/ from ... import *
512 assert len(node.names) == 1
513 return
514 else:
515 self.emit('IMPORT_FROM', name)
516 self._resolveDots(name)
517 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000518 else:
519 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000520 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000521
Jeremy Hylton20516082000-09-01 20:33:26 +0000522 def _resolveDots(self, name):
523 elts = string.split(name, ".")
524 if len(elts) == 1:
525 return
526 for elt in elts[1:]:
527 self.emit('LOAD_ATTR', elt)
528
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000529 def visitGetattr(self, node):
530 self.visit(node.expr)
531 self.emit('LOAD_ATTR', node.attrname)
532
533 # next five implement assignments
534
535 def visitAssign(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.expr)
538 dups = len(node.nodes) - 1
539 for i in range(len(node.nodes)):
540 elt = node.nodes[i]
541 if i < dups:
542 self.emit('DUP_TOP')
543 if isinstance(elt, ast.Node):
544 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000545
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000546 def visitAssName(self, node):
547 if node.flags == 'OP_ASSIGN':
548 self.storeName(node.name)
549 elif node.flags == 'OP_DELETE':
550 self.delName(node.name)
551 else:
552 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000553
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000554 def visitAssAttr(self, node):
555 self.visit(node.expr)
556 if node.flags == 'OP_ASSIGN':
557 self.emit('STORE_ATTR', node.attrname)
558 elif node.flags == 'OP_DELETE':
559 self.emit('DELETE_ATTR', node.attrname)
560 else:
561 print "warning: unexpected flags:", node.flags
562 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000563
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000564 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000565 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000566 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000567 for child in node.nodes:
568 self.visit(child)
569
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000570 if VERSION > 1:
571 visitAssTuple = _visitAssSequence
572 visitAssList = _visitAssSequence
573 else:
574 def visitAssTuple(self, node):
575 self._visitAssSequence(node, 'UNPACK_TUPLE')
576
577 def visitAssList(self, node):
578 self._visitAssSequence(node, 'UNPACK_LIST')
579
580 # augmented assignment
581
582 def visitAugAssign(self, node):
583 aug_node = wrap_aug(node.node)
584 self.visit(aug_node, "load")
585 self.visit(node.expr)
586 self.emit(self._augmented_opcode[node.op])
587 self.visit(aug_node, "store")
588
589 _augmented_opcode = {
590 '+=' : 'INPLACE_ADD',
591 '-=' : 'INPLACE_SUBTRACT',
592 '*=' : 'INPLACE_MULTIPLY',
593 '/=' : 'INPLACE_DIVIDE',
594 '%=' : 'INPLACE_MODULO',
595 '**=': 'INPLACE_POWER',
596 '>>=': 'INPLACE_RSHIFT',
597 '<<=': 'INPLACE_LSHIFT',
598 '&=' : 'INPLACE_AND',
599 '^=' : 'INPLACE_XOR',
600 '|=' : 'INPLACE_OR',
601 }
602
603 def visitAugName(self, node, mode):
604 if mode == "load":
605 self.loadName(node.name)
606 elif mode == "store":
607 self.storeName(node.name)
608
609 def visitAugGetattr(self, node, mode):
610 if mode == "load":
611 self.visit(node.expr)
612 self.emit('DUP_TOP')
613 self.emit('LOAD_ATTR', node.attrname)
614 elif mode == "store":
615 self.emit('ROT_TWO')
616 self.emit('STORE_ATTR', node.attrname)
617
618 def visitAugSlice(self, node, mode):
619 if mode == "load":
620 self.visitSlice(node, 1)
621 elif mode == "store":
622 slice = 0
623 if node.lower:
624 slice = slice | 1
625 if node.upper:
626 slice = slice | 2
627 if slice == 0:
628 self.emit('ROT_TWO')
629 elif slice == 3:
630 self.emit('ROT_FOUR')
631 else:
632 self.emit('ROT_THREE')
633 self.emit('STORE_SLICE+%d' % slice)
634
635 def visitAugSubscript(self, node, mode):
636 if len(node.subs) > 1:
637 raise SyntaxError, "augmented assignment to tuple is not possible"
638 if mode == "load":
639 self.visitSubscript(node, 1)
640 elif mode == "store":
641 self.emit('ROT_THREE')
642 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000643
644 def visitExec(self, node):
645 self.visit(node.expr)
646 if node.locals is None:
647 self.emit('LOAD_CONST', None)
648 else:
649 self.visit(node.locals)
650 if node.globals is None:
651 self.emit('DUP_TOP')
652 else:
653 self.visit(node.globals)
654 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000655
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000656 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000657 pos = 0
658 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000659 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000660 self.visit(node.node)
661 for arg in node.args:
662 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000663 if isinstance(arg, ast.Keyword):
664 kw = kw + 1
665 else:
666 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000667 if node.star_args is not None:
668 self.visit(node.star_args)
669 if node.dstar_args is not None:
670 self.visit(node.dstar_args)
671 have_star = node.star_args is not None
672 have_dstar = node.dstar_args is not None
673 opcode = callfunc_opcode_info[have_star, have_dstar]
674 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000675
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000676 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000677 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000678 if node.dest:
679 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000680 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000681 if node.dest:
682 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000683 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000684 if node.dest:
685 self.emit('ROT_TWO')
686 self.emit('PRINT_ITEM_TO')
687 else:
688 self.emit('PRINT_ITEM')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000689
690 def visitPrintnl(self, node):
691 self.visitPrint(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000692 if node.dest:
693 self.emit('PRINT_NEWLINE_TO')
694 else:
695 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000696
697 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000698 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000699 self.visit(node.value)
700 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000701
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000703
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000704 def visitSlice(self, node, aug_flag=None):
705 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000706 self.visit(node.expr)
707 slice = 0
708 if node.lower:
709 self.visit(node.lower)
710 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000711 if node.upper:
712 self.visit(node.upper)
713 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000714 if aug_flag:
715 if slice == 0:
716 self.emit('DUP_TOP')
717 elif slice == 3:
718 self.emit('DUP_TOPX', 3)
719 else:
720 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000721 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000722 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000723 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000724 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000725 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000726 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000727 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000728 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000729 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000730
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000731 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000732 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000733 for sub in node.subs:
734 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000735 if aug_flag:
736 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000737 if len(node.subs) > 1:
738 self.emit('BUILD_TUPLE', len(node.subs))
739 if node.flags == 'OP_APPLY':
740 self.emit('BINARY_SUBSCR')
741 elif node.flags == 'OP_ASSIGN':
742 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000743 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000744 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000745
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000746 # binary ops
747
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000748 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000749 self.visit(node.left)
750 self.visit(node.right)
751 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000752
753 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000754 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000755
756 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000757 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000758
759 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000760 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000761
762 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000763 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000764
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000765 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000766 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000767
Jeremy Hylton126960b2000-02-14 21:33:10 +0000768 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000769 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000770
771 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000772 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000773
774 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000775 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000776
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000777 # unary ops
778
779 def unaryOp(self, node, op):
780 self.visit(node.expr)
781 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000782
Jeremy Hylton126960b2000-02-14 21:33:10 +0000783 def visitInvert(self, node):
784 return self.unaryOp(node, 'UNARY_INVERT')
785
Jeremy Hylton40245602000-02-08 21:15:48 +0000786 def visitUnarySub(self, node):
787 return self.unaryOp(node, 'UNARY_NEGATIVE')
788
789 def visitUnaryAdd(self, node):
790 return self.unaryOp(node, 'UNARY_POSITIVE')
791
792 def visitUnaryInvert(self, node):
793 return self.unaryOp(node, 'UNARY_INVERT')
794
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000795 def visitNot(self, node):
796 return self.unaryOp(node, 'UNARY_NOT')
797
Jeremy Hylton40245602000-02-08 21:15:48 +0000798 def visitBackquote(self, node):
799 return self.unaryOp(node, 'UNARY_CONVERT')
800
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000801 # bit ops
802
Jeremy Hyltona5058122000-02-14 14:14:29 +0000803 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000804 self.visit(nodes[0])
805 for node in nodes[1:]:
806 self.visit(node)
807 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000808
809 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000810 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000811
812 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000813 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000814
815 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000816 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000817
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000818 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000819
Jeremy Hyltona5058122000-02-14 14:14:29 +0000820 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000821 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000822
Jeremy Hylton40245602000-02-08 21:15:48 +0000823 def visitTuple(self, node):
824 for elt in node.nodes:
825 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000826 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000827
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000828 def visitList(self, node):
829 for elt in node.nodes:
830 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000831 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000832
833 def visitSliceobj(self, node):
834 for child in node.nodes:
835 self.visit(child)
836 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000837
Jeremy Hyltona5058122000-02-14 14:14:29 +0000838 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000839 lineno = getattr(node, 'lineno', None)
840 if lineno:
841 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000842 self.emit('BUILD_MAP', 0)
843 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000844 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000845 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000846 self.emit('SET_LINENO', lineno2)
847 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000848 self.emit('DUP_TOP')
849 self.visit(v)
850 self.emit('ROT_TWO')
851 self.visit(k)
852 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000853
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000854class ModuleCodeGenerator(CodeGenerator):
855 super_init = CodeGenerator.__init__
856
857 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000858 # XXX <module> is ? in compile.c
859 self.graph = pyassem.PyFlowGraph("<module>", filename)
860 self.super_init(filename)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000861
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000862class FunctionCodeGenerator(CodeGenerator):
863 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000864
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000865 optimized = 1
866 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000867
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000868 def __init__(self, func, filename, isLambda=0):
869 if isLambda:
870 klass = FunctionCodeGenerator
871 name = "<lambda.%d>" % klass.lambdaCount
872 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000873 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000874 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000875 args, hasTupleArg = generateArgList(func.argnames)
876 self.graph = pyassem.PyFlowGraph(name, filename, args,
877 optimized=1)
878 self.isLambda = isLambda
879 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000880
881 lnf = walk(func.code, LocalNameFinder(args), 0)
882 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000883 if func.varargs:
884 self.graph.setFlag(CO_VARARGS)
885 if func.kwargs:
886 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000887 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000888 if hasTupleArg:
889 self.generateArgUnpack(func.argnames)
890
891 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000892 self.graph.startExitBlock()
893 if not self.isLambda:
894 self.emit('LOAD_CONST', None)
895 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000896
897 def generateArgUnpack(self, args):
898 count = 0
899 for arg in args:
900 if type(arg) == types.TupleType:
901 self.emit('LOAD_FAST', '.nested%d' % count)
902 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000903 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000904
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000905 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000906 if VERSION > 1:
907 self.emit('UNPACK_SEQUENCE', len(tup))
908 else:
909 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000910 for elt in tup:
911 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000912 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000913 else:
914 self.emit('STORE_FAST', elt)
915
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000916 unpackTuple = unpackSequence
917
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000918class ClassCodeGenerator(CodeGenerator):
919 super_init = CodeGenerator.__init__
920
921 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000922 self.graph = pyassem.PyFlowGraph(klass.name, filename,
923 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000924 self.super_init(filename)
925 lnf = walk(klass.code, LocalNameFinder(), 0)
926 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000927 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000928
929 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000930 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000931 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000932 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000933
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000934def generateArgList(arglist):
935 """Generate an arg list marking TupleArgs"""
936 args = []
937 extra = []
938 count = 0
939 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000940 if type(elt) == types.StringType:
941 args.append(elt)
942 elif type(elt) == types.TupleType:
943 args.append(TupleArg(count, elt))
944 count = count + 1
945 extra.extend(misc.flatten(elt))
946 else:
947 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000948 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000949
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000950class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000951 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000952 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000953 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000954 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000955 for name in names:
956 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000957
958 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000959 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000960 if self.names.has_elt(elt):
961 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000962 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000963
Jeremy Hyltona5058122000-02-14 14:14:29 +0000964 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000965 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000966
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000967 def visitGlobal(self, node):
968 for name in node.names:
969 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000970
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000971 def visitFunction(self, node):
972 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000973
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000974 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000975 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000976
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000977 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000978 for name, alias in node.names:
979 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000980
981 def visitFrom(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000982 for name, alias in node.names:
983 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000984
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000985 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000986 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000987
988 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000989 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000990
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000991def findOp(node):
992 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
993 v = OpFinder()
994 walk(node, v, 0)
995 return v.op
996
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000997class OpFinder:
998 def __init__(self):
999 self.op = None
1000 def visitAssName(self, node):
1001 if self.op is None:
1002 self.op = node.flags
1003 elif self.op != node.flags:
1004 raise ValueError, "mixed ops in stmt"
1005
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001006class Delegator:
1007 """Base class to support delegation for augmented assignment nodes
1008
1009 To generator code for augmented assignments, we use the following
1010 wrapper classes. In visitAugAssign, the left-hand expression node
1011 is visited twice. The first time the visit uses the normal method
1012 for that node . The second time the visit uses a different method
1013 that generates the appropriate code to perform the assignment.
1014 These delegator classes wrap the original AST nodes in order to
1015 support the variant visit methods.
1016 """
1017 def __init__(self, obj):
1018 self.obj = obj
1019
1020 def __getattr__(self, attr):
1021 return getattr(self.obj, attr)
1022
1023class AugGetattr(Delegator):
1024 pass
1025
1026class AugName(Delegator):
1027 pass
1028
1029class AugSlice(Delegator):
1030 pass
1031
1032class AugSubscript(Delegator):
1033 pass
1034
1035wrapper = {
1036 ast.Getattr: AugGetattr,
1037 ast.Name: AugName,
1038 ast.Slice: AugSlice,
1039 ast.Subscript: AugSubscript,
1040 }
1041
1042def wrap_aug(node):
1043 return wrapper[node.__class__](node)
1044
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001045if __name__ == "__main__":
1046 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001047
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001048 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001049 compile(file)