blob: 3ba31e47653c32dbb360e3348c367ed41075d7f3 [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)
Jeremy Hylton84ec1f92001-04-11 16:43:13 +000048 if "nested_scopes" in future.find_futures(tree):
49 gen = NestedScopeCodeGenerator(filename)
50 else:
51 gen = ModuleCodeGenerator(filename)
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000052 walk(tree, gen, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000053 if display:
54 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000055 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000056 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000057
58 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000059 f.write(self.getPycHeader())
60 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000061
Jeremy Hylton9c048f92000-10-13 21:58:13 +000062 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000063
64 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000065 # compile.c uses marshal to write a long directly, with
66 # calling the interface that would also generate a 1-byte code
67 # to indicate the type of the value. simplest way to get the
68 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000069 mtime = os.stat(self.filename)[stat.ST_MTIME]
70 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000071 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000072
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000073class CodeGenerator:
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000074
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000075 optimized = 0 # is namespace access optimized?
Jeremy Hylton3050d512000-02-12 00:12:38 +000076
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000077 def __init__(self, filename):
78## Subclasses must define a constructor that intializes self.graph
Jeremy Hylton9c048f92000-10-13 21:58:13 +000079## before calling this init function, e.g.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000080## self.graph = pyassem.PyFlowGraph()
81 self.filename = filename
82 self.locals = misc.Stack()
83 self.loops = misc.Stack()
84 self.curStack = 0
85 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +000086 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +000087 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +000088
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000089 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000090 self.emit = self.graph.emit
91 self.newBlock = self.graph.newBlock
92 self.startBlock = self.graph.startBlock
93 self.nextBlock = self.graph.nextBlock
94 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +000095
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000096 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000097 """Return a code object"""
98 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +000099
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000100 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000101
Jeremy Hylton40245602000-02-08 21:15:48 +0000102 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000103 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000104
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000105 def storeName(self, name):
106 self._nameOp('STORE', name)
107
108 def loadName(self, name):
109 self._nameOp('LOAD', name)
110
111 def delName(self, name):
112 self._nameOp('DELETE', name)
113
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000114 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000115 if not self.optimized:
116 self.emit(prefix + '_NAME', name)
117 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000118 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000119 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000120 else:
121 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000122
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000123 def set_lineno(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000124 """Emit SET_LINENO if node has lineno attribute and it is
125 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000126
127 Returns true if SET_LINENO was emitted.
128
129 There are no rules for when an AST node should have a lineno
130 attribute. The transformer and AST code need to be reviewed
131 and a consistent policy implemented and documented. Until
132 then, this method works around missing line numbers.
133 """
134 lineno = getattr(node, 'lineno', None)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000135 if lineno is not None and lineno != self.last_lineno:
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000136 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000137 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000138 return 1
139 return 0
140
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000141 # The first few visitor methods handle nodes that generator new
142 # code objects
143
144 def visitModule(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000145 lnf = walk(node.node, LocalNameFinder(), 0)
146 self.locals.push(lnf.getLocals())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000147 if node.doc:
148 self.fixDocstring(node.node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000149 self.visit(node.node)
150 self.emit('LOAD_CONST', None)
151 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000152
153 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000154 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000155 if node.doc:
156 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000157 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000158
159 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000160 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000161
162 def _visitFuncOrLambda(self, node, isLambda):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000163 gen = FunctionCodeGenerator(node, self.filename, isLambda)
164 walk(node.code, gen)
165 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000166 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000167 for default in node.defaults:
168 self.visit(default)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000169 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000170 self.emit('MAKE_FUNCTION', len(node.defaults))
171
172 def visitClass(self, node):
173 gen = ClassCodeGenerator(node, self.filename)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000174 if node.doc:
175 self.fixDocstring(node.code)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000176 walk(node.code, gen)
177 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000178 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000179 self.emit('LOAD_CONST', node.name)
180 for base in node.bases:
181 self.visit(base)
182 self.emit('BUILD_TUPLE', len(node.bases))
183 self.emit('LOAD_CONST', gen.getCode())
184 self.emit('MAKE_FUNCTION', 0)
185 self.emit('CALL_FUNCTION', 0)
186 self.emit('BUILD_CLASS')
187 self.storeName(node.name)
188
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000189 def fixDocstring(self, node):
190 """Rewrite the ast for a class with a docstring.
191
192 The AST includes a Discard(Const(docstring)) node. Replace
193 this with an Assign([AssName('__doc__', ...])
194 """
195 assert isinstance(node, ast.Stmt)
196 stmts = node.nodes
197 discard = stmts[0]
198 assert isinstance(discard, ast.Discard)
199 stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
200 discard.expr)
201 stmts[0].lineno = discard.lineno
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000202 # The rest are standard visitor methods
203
204 # The next few implement control-flow statements
205
206 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000207 end = self.newBlock()
208 numtests = len(node.tests)
209 for i in range(numtests):
210 test, suite = node.tests[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000211 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000212 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000213 nextTest = self.newBlock()
214 self.emit('JUMP_IF_FALSE', nextTest)
215 self.nextBlock()
216 self.emit('POP_TOP')
217 self.visit(suite)
218 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000219 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000220 self.emit('POP_TOP')
221 if node.else_:
222 self.visit(node.else_)
223 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000224
225 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000226 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000227
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000228 loop = self.newBlock()
229 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000230
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000231 after = self.newBlock()
232 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000233
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000234 self.nextBlock(loop)
235 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000237 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000238 self.visit(node.test)
239 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000240
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000241 self.nextBlock()
242 self.emit('POP_TOP')
243 self.visit(node.body)
244 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000245
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000246 self.startBlock(else_) # or just the POPs if not else clause
247 self.emit('POP_TOP')
248 self.emit('POP_BLOCK')
249 if node.else_:
250 self.visit(node.else_)
251 self.loops.pop()
252 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000253
254 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000255 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000256 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000257 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000258 self.loops.push(start)
259
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000260 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000261 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000262 self.visit(node.list)
263 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000264 self.nextBlock(start)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000265 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000266 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000267 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000268 self.visit(node.assign)
269 self.visit(node.body)
270 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000271 self.startBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000272 self.emit('POP_BLOCK')
273 if node.else_:
274 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000275 self.loops.pop()
276 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000277
278 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000279 if not self.loops:
280 raise SyntaxError, "'break' outside loop (%s, %d)" % \
281 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000282 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000283 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000284
285 def visitContinue(self, node):
286 if not self.loops:
287 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000288 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000289 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000290 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000291 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000292 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000293
294 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000295 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000296 for child in node.nodes[:-1]:
297 self.visit(child)
298 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000299 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000300 self.emit('POP_TOP')
301 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000302 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000303
304 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000305 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000306
307 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000308 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000309
310 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000311 self.visit(node.expr)
312 cleanup = self.newBlock()
313 for op, code in node.ops[:-1]:
314 self.visit(code)
315 self.emit('DUP_TOP')
316 self.emit('ROT_THREE')
317 self.emit('COMPARE_OP', op)
318 self.emit('JUMP_IF_FALSE', cleanup)
319 self.nextBlock()
320 self.emit('POP_TOP')
321 # now do the last comparison
322 if node.ops:
323 op, code = node.ops[-1]
324 self.visit(code)
325 self.emit('COMPARE_OP', op)
326 if len(node.ops) > 1:
327 end = self.newBlock()
328 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000329 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000330 self.emit('ROT_TWO')
331 self.emit('POP_TOP')
332 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000333
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000334 # list comprehensions
335 __list_count = 0
336
337 def visitListComp(self, node):
338 # XXX would it be easier to transform the AST into the form it
339 # would have if the list comp were expressed as a series of
340 # for and if stmts and an explicit append?
341 self.set_lineno(node)
342 # setup list
343 append = "$append%d" % self.__list_count
344 self.__list_count = self.__list_count + 1
345 self.emit('BUILD_LIST', 0)
346 self.emit('DUP_TOP')
347 self.emit('LOAD_ATTR', 'append')
348 self.storeName(append)
349 l = len(node.quals)
350 stack = []
351 for i, for_ in zip(range(l), node.quals):
352 start, anchor = self.visit(for_)
353 cont = None
354 for if_ in for_.ifs:
355 if cont is None:
356 cont = self.newBlock()
357 self.visit(if_, cont)
358 stack.insert(0, (start, cont, anchor))
359
360 self.loadName(append)
361 self.visit(node.expr)
362 self.emit('CALL_FUNCTION', 1)
363 self.emit('POP_TOP')
364
365 for start, cont, anchor in stack:
366 if cont:
367 skip_one = self.newBlock()
368 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000369 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000370 self.emit('POP_TOP')
371 self.nextBlock(skip_one)
372 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000373 self.startBlock(anchor)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000374 self.delName(append)
375
376 self.__list_count = self.__list_count - 1
377
378 def visitListCompFor(self, node):
379 self.set_lineno(node)
380 start = self.newBlock()
381 anchor = self.newBlock()
382
383 self.visit(node.list)
384 self.visit(ast.Const(0))
385 self.emit('SET_LINENO', node.lineno)
386 self.nextBlock(start)
387 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000388 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000389 self.visit(node.assign)
390 return start, anchor
391
392 def visitListCompIf(self, node, branch):
393 self.set_lineno(node)
394 self.visit(node.test)
395 self.emit('JUMP_IF_FALSE', branch)
396 self.newBlock()
397 self.emit('POP_TOP')
398
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000399 # exception related
400
401 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000402 # XXX would be interesting to implement this via a
403 # transformation of the AST before this stage
404 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000405 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000406 # XXX __debug__ and AssertionError appear to be special cases
407 # -- they are always loaded as globals even if there are local
408 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000409 self.emit('LOAD_GLOBAL', '__debug__')
410 self.emit('JUMP_IF_FALSE', end)
411 self.nextBlock()
412 self.emit('POP_TOP')
413 self.visit(node.test)
414 self.emit('JUMP_IF_TRUE', end)
415 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000416 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000417 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000418 if node.fail:
419 self.visit(node.fail)
420 self.emit('RAISE_VARARGS', 2)
421 else:
422 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000423 self.nextBlock(end)
424 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000425
426 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000427 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000428 n = 0
429 if node.expr1:
430 self.visit(node.expr1)
431 n = n + 1
432 if node.expr2:
433 self.visit(node.expr2)
434 n = n + 1
435 if node.expr3:
436 self.visit(node.expr3)
437 n = n + 1
438 self.emit('RAISE_VARARGS', n)
439
440 def visitTryExcept(self, node):
441 handlers = self.newBlock()
442 end = self.newBlock()
443 if node.else_:
444 lElse = self.newBlock()
445 else:
446 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000447 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000448 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000449 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000450 self.visit(node.body)
451 self.emit('POP_BLOCK')
452 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000453 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000454
455 last = len(node.handlers) - 1
456 for i in range(len(node.handlers)):
457 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000458 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000459 if expr:
460 self.emit('DUP_TOP')
461 self.visit(expr)
462 self.emit('COMPARE_OP', 'exception match')
463 next = self.newBlock()
464 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000465 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000466 self.emit('POP_TOP')
467 self.emit('POP_TOP')
468 if target:
469 self.visit(target)
470 else:
471 self.emit('POP_TOP')
472 self.emit('POP_TOP')
473 self.visit(body)
474 self.emit('JUMP_FORWARD', end)
475 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000476 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000477 else:
478 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479 self.emit('POP_TOP')
480 self.emit('END_FINALLY')
481 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000482 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000484 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000485
486 def visitTryFinally(self, node):
487 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000488 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000489 self.emit('SETUP_FINALLY', final)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000490 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000491 self.visit(node.body)
492 self.emit('POP_BLOCK')
493 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000494 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000495 self.visit(node.final)
496 self.emit('END_FINALLY')
497
498 # misc
499
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000500 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000501 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000502 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000503 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000504
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000505 def visitConst(self, node):
506 self.emit('LOAD_CONST', node.value)
507
508 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000509 self.emit('LOAD_CONST', node.name)
510 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000511
512 def visitGlobal(self, node):
513 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000514 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000515
516 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000517 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000518 self.loadName(node.name)
519
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000520 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000521 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000522
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000523 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000524 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000525 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000526 if VERSION > 1:
527 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000528 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000529 mod = string.split(name, ".")[0]
530 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000531
532 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000533 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000534 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000535 if VERSION > 1:
536 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000537 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000538 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000539 if VERSION > 1:
540 if name == '*':
541 self.namespace = 0
542 self.emit('IMPORT_STAR')
543 # There can only be one name w/ from ... import *
544 assert len(node.names) == 1
545 return
546 else:
547 self.emit('IMPORT_FROM', name)
548 self._resolveDots(name)
549 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000550 else:
551 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000552 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000553
Jeremy Hylton20516082000-09-01 20:33:26 +0000554 def _resolveDots(self, name):
555 elts = string.split(name, ".")
556 if len(elts) == 1:
557 return
558 for elt in elts[1:]:
559 self.emit('LOAD_ATTR', elt)
560
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000561 def visitGetattr(self, node):
562 self.visit(node.expr)
563 self.emit('LOAD_ATTR', node.attrname)
564
565 # next five implement assignments
566
567 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000568 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000569 self.visit(node.expr)
570 dups = len(node.nodes) - 1
571 for i in range(len(node.nodes)):
572 elt = node.nodes[i]
573 if i < dups:
574 self.emit('DUP_TOP')
575 if isinstance(elt, ast.Node):
576 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000577
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000578 def visitAssName(self, node):
579 if node.flags == 'OP_ASSIGN':
580 self.storeName(node.name)
581 elif node.flags == 'OP_DELETE':
582 self.delName(node.name)
583 else:
584 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000585
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000586 def visitAssAttr(self, node):
587 self.visit(node.expr)
588 if node.flags == 'OP_ASSIGN':
589 self.emit('STORE_ATTR', node.attrname)
590 elif node.flags == 'OP_DELETE':
591 self.emit('DELETE_ATTR', node.attrname)
592 else:
593 print "warning: unexpected flags:", node.flags
594 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000595
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000596 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000597 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000598 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000599 for child in node.nodes:
600 self.visit(child)
601
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000602 if VERSION > 1:
603 visitAssTuple = _visitAssSequence
604 visitAssList = _visitAssSequence
605 else:
606 def visitAssTuple(self, node):
607 self._visitAssSequence(node, 'UNPACK_TUPLE')
608
609 def visitAssList(self, node):
610 self._visitAssSequence(node, 'UNPACK_LIST')
611
612 # augmented assignment
613
614 def visitAugAssign(self, node):
615 aug_node = wrap_aug(node.node)
616 self.visit(aug_node, "load")
617 self.visit(node.expr)
618 self.emit(self._augmented_opcode[node.op])
619 self.visit(aug_node, "store")
620
621 _augmented_opcode = {
622 '+=' : 'INPLACE_ADD',
623 '-=' : 'INPLACE_SUBTRACT',
624 '*=' : 'INPLACE_MULTIPLY',
625 '/=' : 'INPLACE_DIVIDE',
626 '%=' : 'INPLACE_MODULO',
627 '**=': 'INPLACE_POWER',
628 '>>=': 'INPLACE_RSHIFT',
629 '<<=': 'INPLACE_LSHIFT',
630 '&=' : 'INPLACE_AND',
631 '^=' : 'INPLACE_XOR',
632 '|=' : 'INPLACE_OR',
633 }
634
635 def visitAugName(self, node, mode):
636 if mode == "load":
637 self.loadName(node.name)
638 elif mode == "store":
639 self.storeName(node.name)
640
641 def visitAugGetattr(self, node, mode):
642 if mode == "load":
643 self.visit(node.expr)
644 self.emit('DUP_TOP')
645 self.emit('LOAD_ATTR', node.attrname)
646 elif mode == "store":
647 self.emit('ROT_TWO')
648 self.emit('STORE_ATTR', node.attrname)
649
650 def visitAugSlice(self, node, mode):
651 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000652 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000653 elif mode == "store":
654 slice = 0
655 if node.lower:
656 slice = slice | 1
657 if node.upper:
658 slice = slice | 2
659 if slice == 0:
660 self.emit('ROT_TWO')
661 elif slice == 3:
662 self.emit('ROT_FOUR')
663 else:
664 self.emit('ROT_THREE')
665 self.emit('STORE_SLICE+%d' % slice)
666
667 def visitAugSubscript(self, node, mode):
668 if len(node.subs) > 1:
669 raise SyntaxError, "augmented assignment to tuple is not possible"
670 if mode == "load":
671 self.visitSubscript(node, 1)
672 elif mode == "store":
673 self.emit('ROT_THREE')
674 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000675
676 def visitExec(self, node):
677 self.visit(node.expr)
678 if node.locals is None:
679 self.emit('LOAD_CONST', None)
680 else:
681 self.visit(node.locals)
682 if node.globals is None:
683 self.emit('DUP_TOP')
684 else:
685 self.visit(node.globals)
686 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000687
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000688 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000689 pos = 0
690 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000691 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000692 self.visit(node.node)
693 for arg in node.args:
694 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000695 if isinstance(arg, ast.Keyword):
696 kw = kw + 1
697 else:
698 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000699 if node.star_args is not None:
700 self.visit(node.star_args)
701 if node.dstar_args is not None:
702 self.visit(node.dstar_args)
703 have_star = node.star_args is not None
704 have_dstar = node.dstar_args is not None
705 opcode = callfunc_opcode_info[have_star, have_dstar]
706 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000707
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000708 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000709 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000710 if node.dest:
711 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000712 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000713 if node.dest:
714 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000715 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000716 if node.dest:
717 self.emit('ROT_TWO')
718 self.emit('PRINT_ITEM_TO')
719 else:
720 self.emit('PRINT_ITEM')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721
722 def visitPrintnl(self, node):
723 self.visitPrint(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000724 if node.dest:
725 self.emit('PRINT_NEWLINE_TO')
726 else:
727 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000728
729 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000730 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000731 self.visit(node.value)
732 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000733
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000734 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000735
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000736 def visitSlice(self, node, aug_flag=None):
737 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000738 self.visit(node.expr)
739 slice = 0
740 if node.lower:
741 self.visit(node.lower)
742 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000743 if node.upper:
744 self.visit(node.upper)
745 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000746 if aug_flag:
747 if slice == 0:
748 self.emit('DUP_TOP')
749 elif slice == 3:
750 self.emit('DUP_TOPX', 3)
751 else:
752 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000753 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000754 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000755 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000756 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000757 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000758 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000759 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000760 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000761 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000762
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000763 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000764 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000765 for sub in node.subs:
766 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000767 if aug_flag:
768 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000769 if len(node.subs) > 1:
770 self.emit('BUILD_TUPLE', len(node.subs))
771 if node.flags == 'OP_APPLY':
772 self.emit('BINARY_SUBSCR')
773 elif node.flags == 'OP_ASSIGN':
774 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000775 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000776 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000777
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000778 # binary ops
779
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000780 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000781 self.visit(node.left)
782 self.visit(node.right)
783 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000784
785 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000786 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000787
788 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000789 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000790
791 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000792 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000793
794 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000795 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000796
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000797 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000798 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000799
Jeremy Hylton126960b2000-02-14 21:33:10 +0000800 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000801 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000802
803 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000804 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000805
806 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000807 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000808
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000809 # unary ops
810
811 def unaryOp(self, node, op):
812 self.visit(node.expr)
813 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000814
Jeremy Hylton126960b2000-02-14 21:33:10 +0000815 def visitInvert(self, node):
816 return self.unaryOp(node, 'UNARY_INVERT')
817
Jeremy Hylton40245602000-02-08 21:15:48 +0000818 def visitUnarySub(self, node):
819 return self.unaryOp(node, 'UNARY_NEGATIVE')
820
821 def visitUnaryAdd(self, node):
822 return self.unaryOp(node, 'UNARY_POSITIVE')
823
824 def visitUnaryInvert(self, node):
825 return self.unaryOp(node, 'UNARY_INVERT')
826
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000827 def visitNot(self, node):
828 return self.unaryOp(node, 'UNARY_NOT')
829
Jeremy Hylton40245602000-02-08 21:15:48 +0000830 def visitBackquote(self, node):
831 return self.unaryOp(node, 'UNARY_CONVERT')
832
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000833 # bit ops
834
Jeremy Hyltona5058122000-02-14 14:14:29 +0000835 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000836 self.visit(nodes[0])
837 for node in nodes[1:]:
838 self.visit(node)
839 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000840
841 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000842 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000843
844 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000845 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000846
847 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000848 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000849
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000850 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000851
Jeremy Hyltona5058122000-02-14 14:14:29 +0000852 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000853 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000854
Jeremy Hylton40245602000-02-08 21:15:48 +0000855 def visitTuple(self, node):
856 for elt in node.nodes:
857 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000858 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000859
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000860 def visitList(self, node):
861 for elt in node.nodes:
862 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000863 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000864
865 def visitSliceobj(self, node):
866 for child in node.nodes:
867 self.visit(child)
868 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000869
Jeremy Hyltona5058122000-02-14 14:14:29 +0000870 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000871 lineno = getattr(node, 'lineno', None)
872 if lineno:
873 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000874 self.emit('BUILD_MAP', 0)
875 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000876 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000877 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000878 self.emit('SET_LINENO', lineno2)
879 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000880 self.emit('DUP_TOP')
881 self.visit(v)
882 self.emit('ROT_TWO')
883 self.visit(k)
884 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000885
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000886class ModuleCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000887 __super_init = CodeGenerator.__init__
888 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000889
890 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000891 # XXX <module> is ? in compile.c
892 self.graph = pyassem.PyFlowGraph("<module>", filename)
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000893 self.__super_init(filename)
894 self.symbols = None
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000895
896 def visitModule(self, node):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000897 self.symbols = self.parseSymbols(node)
898 self.__super_visitModule(node)
899
900 def parseSymbols(self, node):
901 # XXX not implemented
902 return None
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000903
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000904class NestedScopeCodeGenerator(ModuleCodeGenerator):
905 pass
906
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000907class FunctionCodeGenerator(CodeGenerator):
908 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000909
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000910 optimized = 1
911 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000912
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000913 def __init__(self, func, filename, isLambda=0):
914 if isLambda:
915 klass = FunctionCodeGenerator
916 name = "<lambda.%d>" % klass.lambdaCount
917 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000918 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000919 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000920 args, hasTupleArg = generateArgList(func.argnames)
921 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000922 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000923 self.isLambda = isLambda
924 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000925
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000926 if not isLambda and func.doc:
927 self.setDocstring(func.doc)
928
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000929 lnf = walk(func.code, LocalNameFinder(args), 0)
930 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000931 if func.varargs:
932 self.graph.setFlag(CO_VARARGS)
933 if func.kwargs:
934 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000935 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000936 if hasTupleArg:
937 self.generateArgUnpack(func.argnames)
938
939 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000940 self.graph.startExitBlock()
941 if not self.isLambda:
942 self.emit('LOAD_CONST', None)
943 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000944
945 def generateArgUnpack(self, args):
946 count = 0
947 for arg in args:
948 if type(arg) == types.TupleType:
949 self.emit('LOAD_FAST', '.nested%d' % count)
950 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000951 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000952
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000953 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000954 if VERSION > 1:
955 self.emit('UNPACK_SEQUENCE', len(tup))
956 else:
957 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000958 for elt in tup:
959 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000960 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000961 else:
962 self.emit('STORE_FAST', elt)
963
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000964 unpackTuple = unpackSequence
965
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000966class ClassCodeGenerator(CodeGenerator):
967 super_init = CodeGenerator.__init__
968
969 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000970 self.graph = pyassem.PyFlowGraph(klass.name, filename,
971 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000972 self.super_init(filename)
973 lnf = walk(klass.code, LocalNameFinder(), 0)
974 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000975 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000976 if klass.doc:
977 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000978
979 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000980 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000981 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000982 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000983
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000984def generateArgList(arglist):
985 """Generate an arg list marking TupleArgs"""
986 args = []
987 extra = []
988 count = 0
989 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000990 if type(elt) == types.StringType:
991 args.append(elt)
992 elif type(elt) == types.TupleType:
993 args.append(TupleArg(count, elt))
994 count = count + 1
995 extra.extend(misc.flatten(elt))
996 else:
997 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000998 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000999
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001000class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001001 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001002 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001003 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001004 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001005 for name in names:
1006 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001007
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001008 # XXX list comprehensions and for loops
1009
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001010 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001011 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001012 if self.names.has_elt(elt):
1013 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001014 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001015
Jeremy Hyltona5058122000-02-14 14:14:29 +00001016 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001017 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +00001018
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001019 def visitGlobal(self, node):
1020 for name in node.names:
1021 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001022
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001023 def visitFunction(self, node):
1024 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001025
Jeremy Hylton76d01b82000-02-11 20:27:07 +00001026 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001027 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +00001028
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001029 def visitImport(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +00001030 for name, alias in node.names:
1031 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001032
1033 def visitFrom(self, node):
Jeremy Hylton20516082000-09-01 20:33:26 +00001034 for name, alias in node.names:
1035 self.names.add(alias or name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001036
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001037 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001038 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001039
1040 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001041 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001042
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001043def findOp(node):
1044 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1045 v = OpFinder()
1046 walk(node, v, 0)
1047 return v.op
1048
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001049class OpFinder:
1050 def __init__(self):
1051 self.op = None
1052 def visitAssName(self, node):
1053 if self.op is None:
1054 self.op = node.flags
1055 elif self.op != node.flags:
1056 raise ValueError, "mixed ops in stmt"
1057
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001058class Delegator:
1059 """Base class to support delegation for augmented assignment nodes
1060
1061 To generator code for augmented assignments, we use the following
1062 wrapper classes. In visitAugAssign, the left-hand expression node
1063 is visited twice. The first time the visit uses the normal method
1064 for that node . The second time the visit uses a different method
1065 that generates the appropriate code to perform the assignment.
1066 These delegator classes wrap the original AST nodes in order to
1067 support the variant visit methods.
1068 """
1069 def __init__(self, obj):
1070 self.obj = obj
1071
1072 def __getattr__(self, attr):
1073 return getattr(self.obj, attr)
1074
1075class AugGetattr(Delegator):
1076 pass
1077
1078class AugName(Delegator):
1079 pass
1080
1081class AugSlice(Delegator):
1082 pass
1083
1084class AugSubscript(Delegator):
1085 pass
1086
1087wrapper = {
1088 ast.Getattr: AugGetattr,
1089 ast.Name: AugName,
1090 ast.Slice: AugSlice,
1091 ast.Subscript: AugSubscript,
1092 }
1093
1094def wrap_aug(node):
1095 return wrapper[node.__class__](node)
1096
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001097if __name__ == "__main__":
1098 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001099
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001100 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001101 compile(file)