blob: a1b5d1db1a0cfc7c1aa35c9d8e2edf0dafe29d5a [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)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000163 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000164 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)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000198 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000199 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)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000246 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000247 self.visit(node.assign)
248 self.visit(node.body)
249 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000250 self.startBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000251 self.emit('POP_BLOCK')
252 if node.else_:
253 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000254 self.loops.pop()
255 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000256
257 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000258 if not self.loops:
259 raise SyntaxError, "'break' outside loop (%s, %d)" % \
260 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000261 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000262 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000263
264 def visitContinue(self, node):
265 if not self.loops:
266 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000267 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000268 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000269 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000270 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000271 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000272
273 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000274 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000275 for child in node.nodes[:-1]:
276 self.visit(child)
277 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000278 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000279 self.emit('POP_TOP')
280 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000281 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000282
283 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000284 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000285
286 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000287 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000288
289 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000290 self.visit(node.expr)
291 cleanup = self.newBlock()
292 for op, code in node.ops[:-1]:
293 self.visit(code)
294 self.emit('DUP_TOP')
295 self.emit('ROT_THREE')
296 self.emit('COMPARE_OP', op)
297 self.emit('JUMP_IF_FALSE', cleanup)
298 self.nextBlock()
299 self.emit('POP_TOP')
300 # now do the last comparison
301 if node.ops:
302 op, code = node.ops[-1]
303 self.visit(code)
304 self.emit('COMPARE_OP', op)
305 if len(node.ops) > 1:
306 end = self.newBlock()
307 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000308 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000309 self.emit('ROT_TWO')
310 self.emit('POP_TOP')
311 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000312
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000313 # list comprehensions
314 __list_count = 0
315
316 def visitListComp(self, node):
317 # XXX would it be easier to transform the AST into the form it
318 # would have if the list comp were expressed as a series of
319 # for and if stmts and an explicit append?
320 self.set_lineno(node)
321 # setup list
322 append = "$append%d" % self.__list_count
323 self.__list_count = self.__list_count + 1
324 self.emit('BUILD_LIST', 0)
325 self.emit('DUP_TOP')
326 self.emit('LOAD_ATTR', 'append')
327 self.storeName(append)
328 l = len(node.quals)
329 stack = []
330 for i, for_ in zip(range(l), node.quals):
331 start, anchor = self.visit(for_)
332 cont = None
333 for if_ in for_.ifs:
334 if cont is None:
335 cont = self.newBlock()
336 self.visit(if_, cont)
337 stack.insert(0, (start, cont, anchor))
338
339 self.loadName(append)
340 self.visit(node.expr)
341 self.emit('CALL_FUNCTION', 1)
342 self.emit('POP_TOP')
343
344 for start, cont, anchor in stack:
345 if cont:
346 skip_one = self.newBlock()
347 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000348 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000349 self.emit('POP_TOP')
350 self.nextBlock(skip_one)
351 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000352 self.startBlock(anchor)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000353 self.delName(append)
354
355 self.__list_count = self.__list_count - 1
356
357 def visitListCompFor(self, node):
358 self.set_lineno(node)
359 start = self.newBlock()
360 anchor = self.newBlock()
361
362 self.visit(node.list)
363 self.visit(ast.Const(0))
364 self.emit('SET_LINENO', node.lineno)
365 self.nextBlock(start)
366 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000367 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000368 self.visit(node.assign)
369 return start, anchor
370
371 def visitListCompIf(self, node, branch):
372 self.set_lineno(node)
373 self.visit(node.test)
374 self.emit('JUMP_IF_FALSE', branch)
375 self.newBlock()
376 self.emit('POP_TOP')
377
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000378 # exception related
379
380 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000381 # XXX would be interesting to implement this via a
382 # transformation of the AST before this stage
383 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000384 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000385 # XXX __debug__ and AssertionError appear to be special cases
386 # -- they are always loaded as globals even if there are local
387 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000388 self.emit('LOAD_GLOBAL', '__debug__')
389 self.emit('JUMP_IF_FALSE', end)
390 self.nextBlock()
391 self.emit('POP_TOP')
392 self.visit(node.test)
393 self.emit('JUMP_IF_TRUE', end)
394 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000395 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000396 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000397 if node.fail:
398 self.visit(node.fail)
399 self.emit('RAISE_VARARGS', 2)
400 else:
401 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000402 self.nextBlock(end)
403 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000404
405 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000406 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000407 n = 0
408 if node.expr1:
409 self.visit(node.expr1)
410 n = n + 1
411 if node.expr2:
412 self.visit(node.expr2)
413 n = n + 1
414 if node.expr3:
415 self.visit(node.expr3)
416 n = n + 1
417 self.emit('RAISE_VARARGS', n)
418
419 def visitTryExcept(self, node):
420 handlers = self.newBlock()
421 end = self.newBlock()
422 if node.else_:
423 lElse = self.newBlock()
424 else:
425 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000426 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000427 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000428 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000429 self.visit(node.body)
430 self.emit('POP_BLOCK')
431 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000432 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000433
434 last = len(node.handlers) - 1
435 for i in range(len(node.handlers)):
436 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000437 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000438 if expr:
439 self.emit('DUP_TOP')
440 self.visit(expr)
441 self.emit('COMPARE_OP', 'exception match')
442 next = self.newBlock()
443 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000444 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000445 self.emit('POP_TOP')
446 self.emit('POP_TOP')
447 if target:
448 self.visit(target)
449 else:
450 self.emit('POP_TOP')
451 self.emit('POP_TOP')
452 self.visit(body)
453 self.emit('JUMP_FORWARD', end)
454 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000455 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000456 else:
457 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000458 self.emit('POP_TOP')
459 self.emit('END_FINALLY')
460 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000461 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000462 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000463 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000464
465 def visitTryFinally(self, node):
466 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000467 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000468 self.emit('SETUP_FINALLY', final)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000469 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000470 self.visit(node.body)
471 self.emit('POP_BLOCK')
472 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000473 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000474 self.visit(node.final)
475 self.emit('END_FINALLY')
476
477 # misc
478
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000479 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000480 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000481 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000482
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 def visitConst(self, node):
484 self.emit('LOAD_CONST', node.value)
485
486 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000487 self.emit('LOAD_CONST', node.name)
488 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000489
490 def visitGlobal(self, node):
491 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000492 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000493
494 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000495 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000496 self.loadName(node.name)
497
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000498 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000499 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000500
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000501 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000502 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000503 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000504 if VERSION > 1:
505 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000506 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000507 mod = string.split(name, ".")[0]
508 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000509
510 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000511 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000512 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000513 if VERSION > 1:
514 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000515 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000516 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000517 if VERSION > 1:
518 if name == '*':
519 self.namespace = 0
520 self.emit('IMPORT_STAR')
521 # There can only be one name w/ from ... import *
522 assert len(node.names) == 1
523 return
524 else:
525 self.emit('IMPORT_FROM', name)
526 self._resolveDots(name)
527 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000528 else:
529 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000530 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000531
Jeremy Hylton20516082000-09-01 20:33:26 +0000532 def _resolveDots(self, name):
533 elts = string.split(name, ".")
534 if len(elts) == 1:
535 return
536 for elt in elts[1:]:
537 self.emit('LOAD_ATTR', elt)
538
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000539 def visitGetattr(self, node):
540 self.visit(node.expr)
541 self.emit('LOAD_ATTR', node.attrname)
542
543 # next five implement assignments
544
545 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000546 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000547 self.visit(node.expr)
548 dups = len(node.nodes) - 1
549 for i in range(len(node.nodes)):
550 elt = node.nodes[i]
551 if i < dups:
552 self.emit('DUP_TOP')
553 if isinstance(elt, ast.Node):
554 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000555
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000556 def visitAssName(self, node):
557 if node.flags == 'OP_ASSIGN':
558 self.storeName(node.name)
559 elif node.flags == 'OP_DELETE':
560 self.delName(node.name)
561 else:
562 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000563
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000564 def visitAssAttr(self, node):
565 self.visit(node.expr)
566 if node.flags == 'OP_ASSIGN':
567 self.emit('STORE_ATTR', node.attrname)
568 elif node.flags == 'OP_DELETE':
569 self.emit('DELETE_ATTR', node.attrname)
570 else:
571 print "warning: unexpected flags:", node.flags
572 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000573
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000574 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000575 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000576 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000577 for child in node.nodes:
578 self.visit(child)
579
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000580 if VERSION > 1:
581 visitAssTuple = _visitAssSequence
582 visitAssList = _visitAssSequence
583 else:
584 def visitAssTuple(self, node):
585 self._visitAssSequence(node, 'UNPACK_TUPLE')
586
587 def visitAssList(self, node):
588 self._visitAssSequence(node, 'UNPACK_LIST')
589
590 # augmented assignment
591
592 def visitAugAssign(self, node):
593 aug_node = wrap_aug(node.node)
594 self.visit(aug_node, "load")
595 self.visit(node.expr)
596 self.emit(self._augmented_opcode[node.op])
597 self.visit(aug_node, "store")
598
599 _augmented_opcode = {
600 '+=' : 'INPLACE_ADD',
601 '-=' : 'INPLACE_SUBTRACT',
602 '*=' : 'INPLACE_MULTIPLY',
603 '/=' : 'INPLACE_DIVIDE',
604 '%=' : 'INPLACE_MODULO',
605 '**=': 'INPLACE_POWER',
606 '>>=': 'INPLACE_RSHIFT',
607 '<<=': 'INPLACE_LSHIFT',
608 '&=' : 'INPLACE_AND',
609 '^=' : 'INPLACE_XOR',
610 '|=' : 'INPLACE_OR',
611 }
612
613 def visitAugName(self, node, mode):
614 if mode == "load":
615 self.loadName(node.name)
616 elif mode == "store":
617 self.storeName(node.name)
618
619 def visitAugGetattr(self, node, mode):
620 if mode == "load":
621 self.visit(node.expr)
622 self.emit('DUP_TOP')
623 self.emit('LOAD_ATTR', node.attrname)
624 elif mode == "store":
625 self.emit('ROT_TWO')
626 self.emit('STORE_ATTR', node.attrname)
627
628 def visitAugSlice(self, node, mode):
629 if mode == "load":
630 self.visitSlice(node, 1)
631 elif mode == "store":
632 slice = 0
633 if node.lower:
634 slice = slice | 1
635 if node.upper:
636 slice = slice | 2
637 if slice == 0:
638 self.emit('ROT_TWO')
639 elif slice == 3:
640 self.emit('ROT_FOUR')
641 else:
642 self.emit('ROT_THREE')
643 self.emit('STORE_SLICE+%d' % slice)
644
645 def visitAugSubscript(self, node, mode):
646 if len(node.subs) > 1:
647 raise SyntaxError, "augmented assignment to tuple is not possible"
648 if mode == "load":
649 self.visitSubscript(node, 1)
650 elif mode == "store":
651 self.emit('ROT_THREE')
652 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000653
654 def visitExec(self, node):
655 self.visit(node.expr)
656 if node.locals is None:
657 self.emit('LOAD_CONST', None)
658 else:
659 self.visit(node.locals)
660 if node.globals is None:
661 self.emit('DUP_TOP')
662 else:
663 self.visit(node.globals)
664 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000665
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000666 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000667 pos = 0
668 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000669 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000670 self.visit(node.node)
671 for arg in node.args:
672 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000673 if isinstance(arg, ast.Keyword):
674 kw = kw + 1
675 else:
676 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000677 if node.star_args is not None:
678 self.visit(node.star_args)
679 if node.dstar_args is not None:
680 self.visit(node.dstar_args)
681 have_star = node.star_args is not None
682 have_dstar = node.dstar_args is not None
683 opcode = callfunc_opcode_info[have_star, have_dstar]
684 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000685
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000686 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000687 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000688 if node.dest:
689 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000690 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000691 if node.dest:
692 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000693 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000694 if node.dest:
695 self.emit('ROT_TWO')
696 self.emit('PRINT_ITEM_TO')
697 else:
698 self.emit('PRINT_ITEM')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000699
700 def visitPrintnl(self, node):
701 self.visitPrint(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000702 if node.dest:
703 self.emit('PRINT_NEWLINE_TO')
704 else:
705 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000706
707 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000708 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000709 self.visit(node.value)
710 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000711
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000712 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000713
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000714 def visitSlice(self, node, aug_flag=None):
715 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000716 self.visit(node.expr)
717 slice = 0
718 if node.lower:
719 self.visit(node.lower)
720 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000721 if node.upper:
722 self.visit(node.upper)
723 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000724 if aug_flag:
725 if slice == 0:
726 self.emit('DUP_TOP')
727 elif slice == 3:
728 self.emit('DUP_TOPX', 3)
729 else:
730 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000731 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000732 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000733 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000734 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000735 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000736 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000737 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000738 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000739 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000740
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000741 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000742 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000743 for sub in node.subs:
744 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000745 if aug_flag:
746 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000747 if len(node.subs) > 1:
748 self.emit('BUILD_TUPLE', len(node.subs))
749 if node.flags == 'OP_APPLY':
750 self.emit('BINARY_SUBSCR')
751 elif node.flags == 'OP_ASSIGN':
752 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000753 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000754 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000755
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000756 # binary ops
757
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000758 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000759 self.visit(node.left)
760 self.visit(node.right)
761 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000762
763 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000764 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000765
766 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000767 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000768
769 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000770 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000771
772 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000773 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000774
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000775 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000776 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000777
Jeremy Hylton126960b2000-02-14 21:33:10 +0000778 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000779 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000780
781 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000782 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000783
784 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000785 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000786
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000787 # unary ops
788
789 def unaryOp(self, node, op):
790 self.visit(node.expr)
791 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000792
Jeremy Hylton126960b2000-02-14 21:33:10 +0000793 def visitInvert(self, node):
794 return self.unaryOp(node, 'UNARY_INVERT')
795
Jeremy Hylton40245602000-02-08 21:15:48 +0000796 def visitUnarySub(self, node):
797 return self.unaryOp(node, 'UNARY_NEGATIVE')
798
799 def visitUnaryAdd(self, node):
800 return self.unaryOp(node, 'UNARY_POSITIVE')
801
802 def visitUnaryInvert(self, node):
803 return self.unaryOp(node, 'UNARY_INVERT')
804
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000805 def visitNot(self, node):
806 return self.unaryOp(node, 'UNARY_NOT')
807
Jeremy Hylton40245602000-02-08 21:15:48 +0000808 def visitBackquote(self, node):
809 return self.unaryOp(node, 'UNARY_CONVERT')
810
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000811 # bit ops
812
Jeremy Hyltona5058122000-02-14 14:14:29 +0000813 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000814 self.visit(nodes[0])
815 for node in nodes[1:]:
816 self.visit(node)
817 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000818
819 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000820 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000821
822 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000823 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000824
825 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000826 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000827
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000828 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000829
Jeremy Hyltona5058122000-02-14 14:14:29 +0000830 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000831 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000832
Jeremy Hylton40245602000-02-08 21:15:48 +0000833 def visitTuple(self, node):
834 for elt in node.nodes:
835 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000836 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000837
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000838 def visitList(self, node):
839 for elt in node.nodes:
840 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000841 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000842
843 def visitSliceobj(self, node):
844 for child in node.nodes:
845 self.visit(child)
846 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000847
Jeremy Hyltona5058122000-02-14 14:14:29 +0000848 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000849 lineno = getattr(node, 'lineno', None)
850 if lineno:
851 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000852 self.emit('BUILD_MAP', 0)
853 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000854 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000855 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000856 self.emit('SET_LINENO', lineno2)
857 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000858 self.emit('DUP_TOP')
859 self.visit(v)
860 self.emit('ROT_TWO')
861 self.visit(k)
862 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000863
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000864class ModuleCodeGenerator(CodeGenerator):
865 super_init = CodeGenerator.__init__
866
867 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000868 # XXX <module> is ? in compile.c
869 self.graph = pyassem.PyFlowGraph("<module>", filename)
870 self.super_init(filename)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000871
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000872class FunctionCodeGenerator(CodeGenerator):
873 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000874
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000875 optimized = 1
876 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000877
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000878 def __init__(self, func, filename, isLambda=0):
879 if isLambda:
880 klass = FunctionCodeGenerator
881 name = "<lambda.%d>" % klass.lambdaCount
882 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000883 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000884 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000885 args, hasTupleArg = generateArgList(func.argnames)
886 self.graph = pyassem.PyFlowGraph(name, filename, args,
887 optimized=1)
888 self.isLambda = isLambda
889 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000890
891 lnf = walk(func.code, LocalNameFinder(args), 0)
892 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000893 if func.varargs:
894 self.graph.setFlag(CO_VARARGS)
895 if func.kwargs:
896 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000897 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000898 if hasTupleArg:
899 self.generateArgUnpack(func.argnames)
900
901 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000902 self.graph.startExitBlock()
903 if not self.isLambda:
904 self.emit('LOAD_CONST', None)
905 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000906
907 def generateArgUnpack(self, args):
908 count = 0
909 for arg in args:
910 if type(arg) == types.TupleType:
911 self.emit('LOAD_FAST', '.nested%d' % count)
912 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000913 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000914
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000915 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000916 if VERSION > 1:
917 self.emit('UNPACK_SEQUENCE', len(tup))
918 else:
919 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000920 for elt in tup:
921 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000922 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000923 else:
924 self.emit('STORE_FAST', elt)
925
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000926 unpackTuple = unpackSequence
927
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000928class ClassCodeGenerator(CodeGenerator):
929 super_init = CodeGenerator.__init__
930
931 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000932 self.graph = pyassem.PyFlowGraph(klass.name, filename,
933 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000934 self.super_init(filename)
935 lnf = walk(klass.code, LocalNameFinder(), 0)
936 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000937 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000938
939 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000940 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000941 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000942 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000943
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000944def generateArgList(arglist):
945 """Generate an arg list marking TupleArgs"""
946 args = []
947 extra = []
948 count = 0
949 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000950 if type(elt) == types.StringType:
951 args.append(elt)
952 elif type(elt) == types.TupleType:
953 args.append(TupleArg(count, elt))
954 count = count + 1
955 extra.extend(misc.flatten(elt))
956 else:
957 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000958 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000959
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000960class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000961 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000962 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000963 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000964 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000965 for name in names:
966 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000967
968 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000969 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000970 if self.names.has_elt(elt):
971 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000972 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000973
Jeremy Hyltona5058122000-02-14 14:14:29 +0000974 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000975 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000976
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000977 def visitGlobal(self, node):
978 for name in node.names:
979 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000980
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000981 def visitFunction(self, node):
982 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000983
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000984 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000985 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000986
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000987 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000988 for name, alias in node.names:
989 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000990
991 def visitFrom(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +0000992 for name, alias in node.names:
993 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000994
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000995 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000996 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000997
998 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000999 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001000
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001001def findOp(node):
1002 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1003 v = OpFinder()
1004 walk(node, v, 0)
1005 return v.op
1006
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001007class OpFinder:
1008 def __init__(self):
1009 self.op = None
1010 def visitAssName(self, node):
1011 if self.op is None:
1012 self.op = node.flags
1013 elif self.op != node.flags:
1014 raise ValueError, "mixed ops in stmt"
1015
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001016class Delegator:
1017 """Base class to support delegation for augmented assignment nodes
1018
1019 To generator code for augmented assignments, we use the following
1020 wrapper classes. In visitAugAssign, the left-hand expression node
1021 is visited twice. The first time the visit uses the normal method
1022 for that node . The second time the visit uses a different method
1023 that generates the appropriate code to perform the assignment.
1024 These delegator classes wrap the original AST nodes in order to
1025 support the variant visit methods.
1026 """
1027 def __init__(self, obj):
1028 self.obj = obj
1029
1030 def __getattr__(self, attr):
1031 return getattr(self.obj, attr)
1032
1033class AugGetattr(Delegator):
1034 pass
1035
1036class AugName(Delegator):
1037 pass
1038
1039class AugSlice(Delegator):
1040 pass
1041
1042class AugSubscript(Delegator):
1043 pass
1044
1045wrapper = {
1046 ast.Getattr: AugGetattr,
1047 ast.Name: AugName,
1048 ast.Slice: AugSlice,
1049 ast.Subscript: AugSubscript,
1050 }
1051
1052def wrap_aug(node):
1053 return wrapper[node.__class__](node)
1054
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001055if __name__ == "__main__":
1056 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001057
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001058 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001059 compile(file)