blob: e6849e5045c8042d9488dccfc622e6c8e6f419c0 [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
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000012from compiler import pyassem, misc, future
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):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000046 tree = 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)
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000049 walk(tree, gen, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000050 if display:
51 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000052 print pprint.pprint(tree)
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):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000865 __super_init = CodeGenerator.__init__
866 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000867
868 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000869 # XXX <module> is ? in compile.c
870 self.graph = pyassem.PyFlowGraph("<module>", filename)
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000871 self.__super_init(filename)
872 self.symbols = None
873 self.future = None
874
875 def visitModule(self, node):
876 self.future = future.find_futures(node)
877 self.symbols = self.parseSymbols(node)
878 self.__super_visitModule(node)
879
880 def parseSymbols(self, node):
881 # XXX not implemented
882 return None
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000883
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000884class FunctionCodeGenerator(CodeGenerator):
885 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000886
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000887 optimized = 1
888 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000889
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000890 def __init__(self, func, filename, isLambda=0):
891 if isLambda:
892 klass = FunctionCodeGenerator
893 name = "<lambda.%d>" % klass.lambdaCount
894 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000895 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000896 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000897 args, hasTupleArg = generateArgList(func.argnames)
898 self.graph = pyassem.PyFlowGraph(name, filename, args,
899 optimized=1)
900 self.isLambda = isLambda
901 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000902
903 lnf = walk(func.code, LocalNameFinder(args), 0)
904 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000905 if func.varargs:
906 self.graph.setFlag(CO_VARARGS)
907 if func.kwargs:
908 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000909 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000910 if hasTupleArg:
911 self.generateArgUnpack(func.argnames)
912
913 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000914 self.graph.startExitBlock()
915 if not self.isLambda:
916 self.emit('LOAD_CONST', None)
917 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000918
919 def generateArgUnpack(self, args):
920 count = 0
921 for arg in args:
922 if type(arg) == types.TupleType:
923 self.emit('LOAD_FAST', '.nested%d' % count)
924 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000925 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000926
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000927 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000928 if VERSION > 1:
929 self.emit('UNPACK_SEQUENCE', len(tup))
930 else:
931 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000932 for elt in tup:
933 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000934 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000935 else:
936 self.emit('STORE_FAST', elt)
937
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000938 unpackTuple = unpackSequence
939
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000940class ClassCodeGenerator(CodeGenerator):
941 super_init = CodeGenerator.__init__
942
943 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000944 self.graph = pyassem.PyFlowGraph(klass.name, filename,
945 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000946 self.super_init(filename)
947 lnf = walk(klass.code, LocalNameFinder(), 0)
948 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000949 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000950
951 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000952 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000953 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000954 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000955
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000956def generateArgList(arglist):
957 """Generate an arg list marking TupleArgs"""
958 args = []
959 extra = []
960 count = 0
961 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000962 if type(elt) == types.StringType:
963 args.append(elt)
964 elif type(elt) == types.TupleType:
965 args.append(TupleArg(count, elt))
966 count = count + 1
967 extra.extend(misc.flatten(elt))
968 else:
969 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000970 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000971
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000972class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000973 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000974 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000975 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000976 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000977 for name in names:
978 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000979
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000980 # XXX list comprehensions and for loops
981
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000982 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000983 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000984 if self.names.has_elt(elt):
985 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000986 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000987
Jeremy Hyltona5058122000-02-14 14:14:29 +0000988 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000989 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000990
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000991 def visitGlobal(self, node):
992 for name in node.names:
993 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000994
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000995 def visitFunction(self, node):
996 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000997
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000998 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000999 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +00001000
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001001 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +00001002 for name, alias in node.names:
1003 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001004
1005 def visitFrom(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +00001006 for name, alias in node.names:
1007 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001008
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001009 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001010 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001011
1012 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001013 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001014
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001015def findOp(node):
1016 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1017 v = OpFinder()
1018 walk(node, v, 0)
1019 return v.op
1020
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001021class OpFinder:
1022 def __init__(self):
1023 self.op = None
1024 def visitAssName(self, node):
1025 if self.op is None:
1026 self.op = node.flags
1027 elif self.op != node.flags:
1028 raise ValueError, "mixed ops in stmt"
1029
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001030class Delegator:
1031 """Base class to support delegation for augmented assignment nodes
1032
1033 To generator code for augmented assignments, we use the following
1034 wrapper classes. In visitAugAssign, the left-hand expression node
1035 is visited twice. The first time the visit uses the normal method
1036 for that node . The second time the visit uses a different method
1037 that generates the appropriate code to perform the assignment.
1038 These delegator classes wrap the original AST nodes in order to
1039 support the variant visit methods.
1040 """
1041 def __init__(self, obj):
1042 self.obj = obj
1043
1044 def __getattr__(self, attr):
1045 return getattr(self.obj, attr)
1046
1047class AugGetattr(Delegator):
1048 pass
1049
1050class AugName(Delegator):
1051 pass
1052
1053class AugSlice(Delegator):
1054 pass
1055
1056class AugSubscript(Delegator):
1057 pass
1058
1059wrapper = {
1060 ast.Getattr: AugGetattr,
1061 ast.Name: AugName,
1062 ast.Slice: AugSlice,
1063 ast.Subscript: AugSubscript,
1064 }
1065
1066def wrap_aug(node):
1067 return wrapper[node.__class__](node)
1068
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001069if __name__ == "__main__":
1070 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001071
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001072 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001073 compile(file)