blob: 882e6b1a2bfe1911536def30aac14aaf074a3fef [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 Hylton364f9b92001-04-12 06:40:42 +000012from compiler import pyassem, misc, future, symbols
13from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
14from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
15 CO_NESTED, TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000016
Jeremy Hylton9c048f92000-10-13 21:58:13 +000017# Do we have Python 1.x or Python 2.x?
18try:
19 VERSION = sys.version_info[0]
20except AttributeError:
21 VERSION = 1
22
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000023callfunc_opcode_info = {
24 # (Have *args, Have **args) : opcode
25 (0,0) : "CALL_FUNCTION",
26 (1,0) : "CALL_FUNCTION_VAR",
27 (0,1) : "CALL_FUNCTION_KW",
28 (1,1) : "CALL_FUNCTION_VAR_KW",
29}
30
Jeremy Hylton9c048f92000-10-13 21:58:13 +000031def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000032 f = open(filename)
33 buf = f.read()
34 f.close()
35 mod = Module(buf, filename)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000036 mod.compile(display)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000037 f = open(filename + "c", "wb")
38 mod.dump(f)
39 f.close()
40
41class Module:
42 def __init__(self, source, filename):
Jeremy Hylton2afff322001-08-27 21:51:52 +000043 self.filename = os.path.abspath(filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000044 self.source = source
45 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000046
Jeremy Hylton9c048f92000-10-13 21:58:13 +000047 def compile(self, display=0):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000048 tree = parse(self.source)
Jeremy Hylton2afff322001-08-27 21:51:52 +000049 gen = NestedScopeModuleCodeGenerator(self.filename)
50 walk(tree, gen, verbose=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000051 if display:
52 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000053 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000054 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000055
56 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000057 f.write(self.getPycHeader())
58 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000059
Jeremy Hylton9c048f92000-10-13 21:58:13 +000060 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000061
62 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000063 # compile.c uses marshal to write a long directly, with
64 # calling the interface that would also generate a 1-byte code
65 # to indicate the type of the value. simplest way to get the
66 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000067 mtime = os.stat(self.filename)[stat.ST_MTIME]
68 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000069 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000070
Jeremy Hylton364f9b92001-04-12 06:40:42 +000071class LocalNameFinder:
72 """Find local names in scope"""
73 def __init__(self, names=()):
74 self.names = misc.Set()
75 self.globals = misc.Set()
76 for name in names:
77 self.names.add(name)
78
79 # XXX list comprehensions and for loops
80
81 def getLocals(self):
82 for elt in self.globals.elements():
83 if self.names.has_elt(elt):
84 self.names.remove(elt)
85 return self.names
86
87 def visitDict(self, node):
88 pass
89
90 def visitGlobal(self, node):
91 for name in node.names:
92 self.globals.add(name)
93
94 def visitFunction(self, node):
95 self.names.add(node.name)
96
97 def visitLambda(self, node):
98 pass
99
100 def visitImport(self, node):
101 for name, alias in node.names:
102 self.names.add(alias or name)
103
104 def visitFrom(self, node):
105 for name, alias in node.names:
106 self.names.add(alias or name)
107
108 def visitClass(self, node):
109 self.names.add(node.name)
110
111 def visitAssName(self, node):
112 self.names.add(node.name)
113
Jeremy Hylton2afff322001-08-27 21:51:52 +0000114def is_constant_false(node):
115 if isinstance(node, ast.Const):
116 if not node.value:
117 return 1
118 return 0
119
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000120class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000121 """Defines basic code generator for Python bytecode
122
123 This class is an abstract base class. Concrete subclasses must
124 define an __init__() that defines self.graph and then calls the
125 __init__() defined in this class.
126
127 The concrete class must also define the class attributes
128 NameFinder, FunctionGen, and ClassGen. These attributes can be
129 defined in the initClass() method, which is a hook for
130 initializing these methods after all the classes have been
131 defined.
132 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000133
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000134 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000135 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000136 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000137
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000138 def __init__(self, filename):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000139 if self.__initialized is None:
140 self.initClass()
141 self.__class__.__initialized = 1
142 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000143 self.filename = filename
144 self.locals = misc.Stack()
145 self.loops = misc.Stack()
146 self.curStack = 0
147 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000148 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000149 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000150
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000151 def initClass(self):
152 """This method is called once for each class"""
153
154 def checkClass(self):
155 """Verify that class is constructed correctly"""
156 try:
157 assert hasattr(self, 'graph')
158 assert getattr(self, 'NameFinder')
159 assert getattr(self, 'FunctionGen')
160 assert getattr(self, 'ClassGen')
161 except AssertionError, msg:
162 intro = "Bad class construction for %s" % self.__class__.__name__
163 raise AssertionError, intro
164
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000165 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000166 self.emit = self.graph.emit
167 self.newBlock = self.graph.newBlock
168 self.startBlock = self.graph.startBlock
169 self.nextBlock = self.graph.nextBlock
170 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000171
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000172 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000173 """Return a code object"""
174 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000175
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000176 def mangle(self, name):
177 if self.class_name is not None:
178 return misc.mangle(name, self.class_name)
179 else:
180 return name
181
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000182 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000183
Jeremy Hylton40245602000-02-08 21:15:48 +0000184 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000185 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000186
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000187 def storeName(self, name):
188 self._nameOp('STORE', name)
189
190 def loadName(self, name):
191 self._nameOp('LOAD', name)
192
193 def delName(self, name):
194 self._nameOp('DELETE', name)
195
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000196 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000197 name = self.mangle(name)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000198 if not self.optimized:
199 self.emit(prefix + '_NAME', name)
200 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000201 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000202 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000203 else:
204 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000205
Jeremy Hylton13d70942001-04-12 21:04:43 +0000206 def _implicitNameOp(self, prefix, name):
207 """Emit name ops for names generated implicitly by for loops
208
209 The interpreter generates names that start with a period or
210 dollar sign. The symbol table ignores these names because
211 they aren't present in the program text.
212 """
213 if self.optimized:
214 self.emit(prefix + '_FAST', name)
215 else:
216 self.emit(prefix + '_NAME', name)
217
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000218 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000219 """Emit SET_LINENO if node has lineno attribute and it is
220 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000221
222 Returns true if SET_LINENO was emitted.
223
224 There are no rules for when an AST node should have a lineno
225 attribute. The transformer and AST code need to be reviewed
226 and a consistent policy implemented and documented. Until
227 then, this method works around missing line numbers.
228 """
229 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000230 if lineno is not None and (lineno != self.last_lineno
231 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000232 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000233 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000234 return 1
235 return 0
236
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000237 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000238 # code objects. They use class attributes to determine what
239 # specialized code generators to use.
240
241 NameFinder = LocalNameFinder
242 FunctionGen = None
243 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000244
245 def visitModule(self, node):
Jeremy Hylton13d70942001-04-12 21:04:43 +0000246 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000247 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000248 self.emit('LOAD_CONST', node.doc)
249 self.storeName('__doc__')
250 lnf = walk(node.node, self.NameFinder(), verbose=0)
251 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000252 self.visit(node.node)
253 self.emit('LOAD_CONST', None)
254 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000255
256 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000257 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000258 if node.doc:
259 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000260 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000261
262 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000263 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000264
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000265 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000266 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
267 self.class_name)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000268 walk(node.code, gen)
269 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000270 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000271 for default in node.defaults:
272 self.visit(default)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000273 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000274 self.emit('MAKE_FUNCTION', len(node.defaults))
275
276 def visitClass(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000277 gen = self.ClassGen(node, self.filename, self.scopes)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000278 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000279 self.emit('LOAD_CONST', node.doc)
280 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000281 walk(node.code, gen)
282 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000283 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000284 self.emit('LOAD_CONST', node.name)
285 for base in node.bases:
286 self.visit(base)
287 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000288 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000289 self.emit('MAKE_FUNCTION', 0)
290 self.emit('CALL_FUNCTION', 0)
291 self.emit('BUILD_CLASS')
292 self.storeName(node.name)
293
294 # The rest are standard visitor methods
295
296 # The next few implement control-flow statements
297
298 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000299 end = self.newBlock()
300 numtests = len(node.tests)
301 for i in range(numtests):
302 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000303 if is_constant_false(test):
304 # XXX will need to check generator stuff here
305 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000306 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000307 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000308 nextTest = self.newBlock()
309 self.emit('JUMP_IF_FALSE', nextTest)
310 self.nextBlock()
311 self.emit('POP_TOP')
312 self.visit(suite)
313 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000314 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000315 self.emit('POP_TOP')
316 if node.else_:
317 self.visit(node.else_)
318 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000319
320 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000321 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000322
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000323 loop = self.newBlock()
324 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000325
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000326 after = self.newBlock()
327 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000328
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000329 self.nextBlock(loop)
330 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000331
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000332 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000333 self.visit(node.test)
334 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000335
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000336 self.nextBlock()
337 self.emit('POP_TOP')
338 self.visit(node.body)
339 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000340
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000341 self.startBlock(else_) # or just the POPs if not else clause
342 self.emit('POP_TOP')
343 self.emit('POP_BLOCK')
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000344 self.loops.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000345 if node.else_:
346 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000347 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000348
349 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000350 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000351 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000352 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000353 self.loops.push(start)
354
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000355 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000356 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000357 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000358 self.emit('GET_ITER')
359
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000360 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000361 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000362 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000363 self.visit(node.assign)
364 self.visit(node.body)
365 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000366 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000367 self.emit('POP_BLOCK')
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000368 self.loops.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369 if node.else_:
370 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000371 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000372
373 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000374 if not self.loops:
375 raise SyntaxError, "'break' outside loop (%s, %d)" % \
376 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000377 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000378 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000379
380 def visitContinue(self, node):
381 if not self.loops:
382 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000383 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000384 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000385 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000386 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000387 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000388
389 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000390 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000391 for child in node.nodes[:-1]:
392 self.visit(child)
393 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000394 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000395 self.emit('POP_TOP')
396 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000397 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000398
399 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000400 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000401
402 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000403 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000404
405 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000406 self.visit(node.expr)
407 cleanup = self.newBlock()
408 for op, code in node.ops[:-1]:
409 self.visit(code)
410 self.emit('DUP_TOP')
411 self.emit('ROT_THREE')
412 self.emit('COMPARE_OP', op)
413 self.emit('JUMP_IF_FALSE', cleanup)
414 self.nextBlock()
415 self.emit('POP_TOP')
416 # now do the last comparison
417 if node.ops:
418 op, code = node.ops[-1]
419 self.visit(code)
420 self.emit('COMPARE_OP', op)
421 if len(node.ops) > 1:
422 end = self.newBlock()
423 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000424 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000425 self.emit('ROT_TWO')
426 self.emit('POP_TOP')
427 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000428
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000429 # list comprehensions
430 __list_count = 0
431
432 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000433 self.set_lineno(node)
434 # setup list
435 append = "$append%d" % self.__list_count
436 self.__list_count = self.__list_count + 1
437 self.emit('BUILD_LIST', 0)
438 self.emit('DUP_TOP')
439 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000440 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000441
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000442 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000443 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000444 start, anchor = self.visit(for_)
445 cont = None
446 for if_ in for_.ifs:
447 if cont is None:
448 cont = self.newBlock()
449 self.visit(if_, cont)
450 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000451
Jeremy Hylton13d70942001-04-12 21:04:43 +0000452 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000453 self.visit(node.expr)
454 self.emit('CALL_FUNCTION', 1)
455 self.emit('POP_TOP')
456
457 for start, cont, anchor in stack:
458 if cont:
459 skip_one = self.newBlock()
460 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000461 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000462 self.emit('POP_TOP')
463 self.nextBlock(skip_one)
464 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000465 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000466 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000467
468 self.__list_count = self.__list_count - 1
469
470 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000471 start = self.newBlock()
472 anchor = self.newBlock()
473
474 self.visit(node.list)
475 self.visit(ast.Const(0))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000476 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000477 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000478 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000479 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000480 self.visit(node.assign)
481 return start, anchor
482
483 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000484 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000485 self.visit(node.test)
486 self.emit('JUMP_IF_FALSE', branch)
487 self.newBlock()
488 self.emit('POP_TOP')
489
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000490 # exception related
491
492 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000493 # XXX would be interesting to implement this via a
494 # transformation of the AST before this stage
495 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000496 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000497 # XXX __debug__ and AssertionError appear to be special cases
498 # -- they are always loaded as globals even if there are local
499 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000500 self.emit('LOAD_GLOBAL', '__debug__')
501 self.emit('JUMP_IF_FALSE', end)
502 self.nextBlock()
503 self.emit('POP_TOP')
504 self.visit(node.test)
505 self.emit('JUMP_IF_TRUE', end)
506 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000507 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000508 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000509 if node.fail:
510 self.visit(node.fail)
511 self.emit('RAISE_VARARGS', 2)
512 else:
513 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000514 self.nextBlock(end)
515 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000516
517 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000518 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000519 n = 0
520 if node.expr1:
521 self.visit(node.expr1)
522 n = n + 1
523 if node.expr2:
524 self.visit(node.expr2)
525 n = n + 1
526 if node.expr3:
527 self.visit(node.expr3)
528 n = n + 1
529 self.emit('RAISE_VARARGS', n)
530
531 def visitTryExcept(self, node):
532 handlers = self.newBlock()
533 end = self.newBlock()
534 if node.else_:
535 lElse = self.newBlock()
536 else:
537 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000538 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000539 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000540 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000541 self.visit(node.body)
542 self.emit('POP_BLOCK')
543 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000544 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000545
546 last = len(node.handlers) - 1
547 for i in range(len(node.handlers)):
548 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000549 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000550 if expr:
551 self.emit('DUP_TOP')
552 self.visit(expr)
553 self.emit('COMPARE_OP', 'exception match')
554 next = self.newBlock()
555 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000556 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000557 self.emit('POP_TOP')
558 self.emit('POP_TOP')
559 if target:
560 self.visit(target)
561 else:
562 self.emit('POP_TOP')
563 self.emit('POP_TOP')
564 self.visit(body)
565 self.emit('JUMP_FORWARD', end)
566 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000567 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000568 else:
569 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000570 if expr: # XXX
571 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000572 self.emit('END_FINALLY')
573 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000574 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000575 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000576 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000577
578 def visitTryFinally(self, node):
579 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000580 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000581 self.emit('SETUP_FINALLY', final)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000582 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000583 self.visit(node.body)
584 self.emit('POP_BLOCK')
585 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000586 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000587 self.visit(node.final)
588 self.emit('END_FINALLY')
589
590 # misc
591
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000592 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000593 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000594 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000595 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000596
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000597 def visitConst(self, node):
598 self.emit('LOAD_CONST', node.value)
599
600 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000601 self.emit('LOAD_CONST', node.name)
602 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000603
604 def visitGlobal(self, node):
605 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000606 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000607
608 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000609 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000610 self.loadName(node.name)
611
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000612 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000613 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000614
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000615 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000616 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000617 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000618 if VERSION > 1:
619 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000620 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000621 mod = string.split(name, ".")[0]
622 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000623
624 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000625 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000626 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000627 if VERSION > 1:
628 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000629 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000630 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000631 if VERSION > 1:
632 if name == '*':
633 self.namespace = 0
634 self.emit('IMPORT_STAR')
635 # There can only be one name w/ from ... import *
636 assert len(node.names) == 1
637 return
638 else:
639 self.emit('IMPORT_FROM', name)
640 self._resolveDots(name)
641 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000642 else:
643 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000644 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000645
Jeremy Hylton20516082000-09-01 20:33:26 +0000646 def _resolveDots(self, name):
647 elts = string.split(name, ".")
648 if len(elts) == 1:
649 return
650 for elt in elts[1:]:
651 self.emit('LOAD_ATTR', elt)
652
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000653 def visitGetattr(self, node):
654 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000655 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000656
657 # next five implement assignments
658
659 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000660 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000661 self.visit(node.expr)
662 dups = len(node.nodes) - 1
663 for i in range(len(node.nodes)):
664 elt = node.nodes[i]
665 if i < dups:
666 self.emit('DUP_TOP')
667 if isinstance(elt, ast.Node):
668 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000669
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000670 def visitAssName(self, node):
671 if node.flags == 'OP_ASSIGN':
672 self.storeName(node.name)
673 elif node.flags == 'OP_DELETE':
674 self.delName(node.name)
675 else:
676 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000677
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000678 def visitAssAttr(self, node):
679 self.visit(node.expr)
680 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000681 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000682 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000683 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000684 else:
685 print "warning: unexpected flags:", node.flags
686 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000687
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000688 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000689 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000690 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000691 for child in node.nodes:
692 self.visit(child)
693
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000694 if VERSION > 1:
695 visitAssTuple = _visitAssSequence
696 visitAssList = _visitAssSequence
697 else:
698 def visitAssTuple(self, node):
699 self._visitAssSequence(node, 'UNPACK_TUPLE')
700
701 def visitAssList(self, node):
702 self._visitAssSequence(node, 'UNPACK_LIST')
703
704 # augmented assignment
705
706 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000707 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000708 aug_node = wrap_aug(node.node)
709 self.visit(aug_node, "load")
710 self.visit(node.expr)
711 self.emit(self._augmented_opcode[node.op])
712 self.visit(aug_node, "store")
713
714 _augmented_opcode = {
715 '+=' : 'INPLACE_ADD',
716 '-=' : 'INPLACE_SUBTRACT',
717 '*=' : 'INPLACE_MULTIPLY',
718 '/=' : 'INPLACE_DIVIDE',
719 '%=' : 'INPLACE_MODULO',
720 '**=': 'INPLACE_POWER',
721 '>>=': 'INPLACE_RSHIFT',
722 '<<=': 'INPLACE_LSHIFT',
723 '&=' : 'INPLACE_AND',
724 '^=' : 'INPLACE_XOR',
725 '|=' : 'INPLACE_OR',
726 }
727
728 def visitAugName(self, node, mode):
729 if mode == "load":
730 self.loadName(node.name)
731 elif mode == "store":
732 self.storeName(node.name)
733
734 def visitAugGetattr(self, node, mode):
735 if mode == "load":
736 self.visit(node.expr)
737 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000738 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000739 elif mode == "store":
740 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000741 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000742
743 def visitAugSlice(self, node, mode):
744 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000745 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000746 elif mode == "store":
747 slice = 0
748 if node.lower:
749 slice = slice | 1
750 if node.upper:
751 slice = slice | 2
752 if slice == 0:
753 self.emit('ROT_TWO')
754 elif slice == 3:
755 self.emit('ROT_FOUR')
756 else:
757 self.emit('ROT_THREE')
758 self.emit('STORE_SLICE+%d' % slice)
759
760 def visitAugSubscript(self, node, mode):
761 if len(node.subs) > 1:
762 raise SyntaxError, "augmented assignment to tuple is not possible"
763 if mode == "load":
764 self.visitSubscript(node, 1)
765 elif mode == "store":
766 self.emit('ROT_THREE')
767 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000768
769 def visitExec(self, node):
770 self.visit(node.expr)
771 if node.locals is None:
772 self.emit('LOAD_CONST', None)
773 else:
774 self.visit(node.locals)
775 if node.globals is None:
776 self.emit('DUP_TOP')
777 else:
778 self.visit(node.globals)
779 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000780
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000781 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000782 pos = 0
783 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000784 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000785 self.visit(node.node)
786 for arg in node.args:
787 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000788 if isinstance(arg, ast.Keyword):
789 kw = kw + 1
790 else:
791 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000792 if node.star_args is not None:
793 self.visit(node.star_args)
794 if node.dstar_args is not None:
795 self.visit(node.dstar_args)
796 have_star = node.star_args is not None
797 have_dstar = node.dstar_args is not None
798 opcode = callfunc_opcode_info[have_star, have_dstar]
799 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000800
Jeremy Hylton2afff322001-08-27 21:51:52 +0000801 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000802 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000803 if node.dest:
804 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000805 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000806 if node.dest:
807 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000808 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000809 if node.dest:
810 self.emit('ROT_TWO')
811 self.emit('PRINT_ITEM_TO')
812 else:
813 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000814 if node.dest and not newline:
815 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000816
817 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000818 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000819 if node.dest:
820 self.emit('PRINT_NEWLINE_TO')
821 else:
822 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000823
824 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000825 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000826 self.visit(node.value)
827 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000828
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000829 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000830
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000831 def visitSlice(self, node, aug_flag=None):
832 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000833 self.visit(node.expr)
834 slice = 0
835 if node.lower:
836 self.visit(node.lower)
837 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000838 if node.upper:
839 self.visit(node.upper)
840 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000841 if aug_flag:
842 if slice == 0:
843 self.emit('DUP_TOP')
844 elif slice == 3:
845 self.emit('DUP_TOPX', 3)
846 else:
847 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000848 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000849 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000850 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000851 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000852 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000853 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000854 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000855 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000856 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000857
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000858 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000859 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000860 for sub in node.subs:
861 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000862 if aug_flag:
863 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000864 if len(node.subs) > 1:
865 self.emit('BUILD_TUPLE', len(node.subs))
866 if node.flags == 'OP_APPLY':
867 self.emit('BINARY_SUBSCR')
868 elif node.flags == 'OP_ASSIGN':
869 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000870 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000871 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000872
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000873 # binary ops
874
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000875 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000876 self.visit(node.left)
877 self.visit(node.right)
878 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000879
880 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000881 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000882
883 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000884 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000885
886 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000887 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000888
889 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000890 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000891
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000892 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000893 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000894
Jeremy Hylton126960b2000-02-14 21:33:10 +0000895 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000896 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000897
898 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000899 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000900
901 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000902 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000903
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000904 # unary ops
905
906 def unaryOp(self, node, op):
907 self.visit(node.expr)
908 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000909
Jeremy Hylton126960b2000-02-14 21:33:10 +0000910 def visitInvert(self, node):
911 return self.unaryOp(node, 'UNARY_INVERT')
912
Jeremy Hylton40245602000-02-08 21:15:48 +0000913 def visitUnarySub(self, node):
914 return self.unaryOp(node, 'UNARY_NEGATIVE')
915
916 def visitUnaryAdd(self, node):
917 return self.unaryOp(node, 'UNARY_POSITIVE')
918
919 def visitUnaryInvert(self, node):
920 return self.unaryOp(node, 'UNARY_INVERT')
921
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000922 def visitNot(self, node):
923 return self.unaryOp(node, 'UNARY_NOT')
924
Jeremy Hylton40245602000-02-08 21:15:48 +0000925 def visitBackquote(self, node):
926 return self.unaryOp(node, 'UNARY_CONVERT')
927
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000928 # bit ops
929
Jeremy Hyltona5058122000-02-14 14:14:29 +0000930 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000931 self.visit(nodes[0])
932 for node in nodes[1:]:
933 self.visit(node)
934 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000935
936 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000937 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000938
939 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000940 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000941
942 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000943 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000944
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000945 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000946
Jeremy Hyltona5058122000-02-14 14:14:29 +0000947 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000948 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000949
Jeremy Hylton40245602000-02-08 21:15:48 +0000950 def visitTuple(self, node):
951 for elt in node.nodes:
952 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000953 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000954
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000955 def visitList(self, node):
956 for elt in node.nodes:
957 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000958 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000959
960 def visitSliceobj(self, node):
961 for child in node.nodes:
962 self.visit(child)
963 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000964
Jeremy Hyltona5058122000-02-14 14:14:29 +0000965 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000966 lineno = getattr(node, 'lineno', None)
967 if lineno:
968 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000969 self.emit('BUILD_MAP', 0)
970 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000971 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000972 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000973 self.emit('SET_LINENO', lineno2)
974 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000975 self.emit('DUP_TOP')
976 self.visit(v)
977 self.emit('ROT_TWO')
978 self.visit(k)
979 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000980
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000981class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000982 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000983 __super_visitClass = CodeGenerator.visitClass
984 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
985
986 def parseSymbols(self, tree):
987 s = symbols.SymbolVisitor()
988 walk(tree, s)
989 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000990
991 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000992 self.scopes = self.parseSymbols(node)
993 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000994 self.__super_visitModule(node)
995
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000996 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000997 name = self.mangle(name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000998 scope = self.scope.check_name(name)
999 if scope == SC_LOCAL:
1000 if not self.optimized:
1001 self.emit(prefix + '_NAME', name)
1002 else:
1003 self.emit(prefix + '_FAST', name)
1004 elif scope == SC_GLOBAL:
Jeremy Hyltonf3545752001-08-28 16:35:18 +00001005 if not self.optimized:
1006 self.emit(prefix + '_NAME', name)
1007 else:
1008 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001009 elif scope == SC_FREE or scope == SC_CELL:
1010 self.emit(prefix + '_DEREF', name)
1011 else:
1012 raise RuntimeError, "unsupported scope for var %s: %d" % \
1013 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001014
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001015 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001016 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1017 self.class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001018 walk(node.code, gen)
1019 gen.finish()
1020 self.set_lineno(node)
1021 for default in node.defaults:
1022 self.visit(default)
1023 frees = gen.scope.get_free_vars()
1024 if frees:
1025 for name in frees:
1026 self.emit('LOAD_CLOSURE', name)
1027 self.emit('LOAD_CONST', gen)
1028 self.emit('MAKE_CLOSURE', len(node.defaults))
1029 else:
1030 self.emit('LOAD_CONST', gen)
1031 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001032
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001033 def visitClass(self, node):
1034 gen = self.ClassGen(node, self.filename, self.scopes)
1035 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001036 self.emit('LOAD_CONST', node.doc)
1037 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001038 walk(node.code, gen)
1039 gen.finish()
1040 self.set_lineno(node)
1041 self.emit('LOAD_CONST', node.name)
1042 for base in node.bases:
1043 self.visit(base)
1044 self.emit('BUILD_TUPLE', len(node.bases))
1045 frees = gen.scope.get_free_vars()
1046 for name in frees:
1047 self.emit('LOAD_CLOSURE', name)
1048 self.emit('LOAD_CONST', gen)
1049 if frees:
1050 self.emit('MAKE_CLOSURE', 0)
1051 else:
1052 self.emit('MAKE_FUNCTION', 0)
1053 self.emit('CALL_FUNCTION', 0)
1054 self.emit('BUILD_CLASS')
1055 self.storeName(node.name)
1056
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001057
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001058class LGBScopeMixin:
1059 """Defines initClass() for Python 2.1-compatible scoping"""
1060 def initClass(self):
1061 self.__class__.NameFinder = LocalNameFinder
1062 self.__class__.FunctionGen = FunctionCodeGenerator
1063 self.__class__.ClassGen = ClassCodeGenerator
1064
1065class NestedScopeMixin:
1066 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1067 def initClass(self):
1068 self.__class__.NameFinder = LocalNameFinder
1069 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1070 self.__class__.ClassGen = NestedClassCodeGenerator
1071
1072class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1073 __super_init = CodeGenerator.__init__
1074
1075 scopes = None
1076
1077 def __init__(self, filename):
1078 self.graph = pyassem.PyFlowGraph("<module>", filename)
1079 self.__super_init(filename)
1080
1081class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1082 NestedScopeCodeGenerator):
1083 __super_init = CodeGenerator.__init__
1084
1085 def __init__(self, filename):
1086 self.graph = pyassem.PyFlowGraph("<module>", filename)
1087 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001088## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001089
1090class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001091 optimized = 1
1092 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001093
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001094 def __init__(self, func, filename, scopes, isLambda, class_name):
1095 self.class_name = class_name
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001096 if isLambda:
1097 klass = FunctionCodeGenerator
1098 name = "<lambda.%d>" % klass.lambdaCount
1099 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001100 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001101 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001102 args, hasTupleArg = generateArgList(func.argnames)
1103 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001104 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001105 self.isLambda = isLambda
1106 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001107
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001108 if not isLambda and func.doc:
1109 self.setDocstring(func.doc)
1110
Jeremy Hylton2afff322001-08-27 21:51:52 +00001111 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001112 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001113 if func.varargs:
1114 self.graph.setFlag(CO_VARARGS)
1115 if func.kwargs:
1116 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001117 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001118 if hasTupleArg:
1119 self.generateArgUnpack(func.argnames)
1120
1121 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001122 self.graph.startExitBlock()
1123 if not self.isLambda:
1124 self.emit('LOAD_CONST', None)
1125 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001126
1127 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001128 for i in range(len(args)):
1129 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001130 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001131 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001132 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001133
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001134 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001135 if VERSION > 1:
1136 self.emit('UNPACK_SEQUENCE', len(tup))
1137 else:
1138 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001139 for elt in tup:
1140 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001141 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001142 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001143 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001144
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001145 unpackTuple = unpackSequence
1146
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001147class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1148 CodeGenerator):
1149 super_init = CodeGenerator.__init__ # call be other init
1150 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001151
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001152class NestedFunctionCodeGenerator(AbstractFunctionCode,
1153 NestedScopeMixin,
1154 NestedScopeCodeGenerator):
1155 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1156 __super_init = AbstractFunctionCode.__init__
1157
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001158 def __init__(self, func, filename, scopes, isLambda, class_name):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001159 self.scopes = scopes
1160 self.scope = scopes[func]
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001161 self.__super_init(func, filename, scopes, isLambda, class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001162 self.graph.setFreeVars(self.scope.get_free_vars())
1163 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001164## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001165
1166class AbstractClassCode:
1167
1168 def __init__(self, klass, filename, scopes):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001169 self.class_name = klass.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001170 self.graph = pyassem.PyFlowGraph(klass.name, filename,
1171 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001172 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001173 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001174 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001175 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001176 if klass.doc:
1177 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001178
Jeremy Hylton660cc772001-04-12 06:49:00 +00001179 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001180 name = self.mangle(name)
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001181 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001182 self.emit(prefix + '_NAME', name)
1183
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001184 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001185 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001186 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001187 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001188
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001189class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1190 super_init = CodeGenerator.__init__
1191 scopes = None
1192
1193class NestedClassCodeGenerator(AbstractClassCode,
1194 NestedScopeMixin,
1195 NestedScopeCodeGenerator):
1196 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1197 __super_init = AbstractClassCode.__init__
1198
1199 def __init__(self, klass, filename, scopes):
1200 self.scopes = scopes
1201 self.scope = scopes[klass]
1202 self.__super_init(klass, filename, scopes)
1203 self.graph.setFreeVars(self.scope.get_free_vars())
1204 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001205## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001206
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001207def generateArgList(arglist):
1208 """Generate an arg list marking TupleArgs"""
1209 args = []
1210 extra = []
1211 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001212 for i in range(len(arglist)):
1213 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001214 if type(elt) == types.StringType:
1215 args.append(elt)
1216 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001217 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001218 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001219 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001220 else:
1221 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001222 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001223
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001224def findOp(node):
1225 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1226 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001227 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001228 return v.op
1229
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001230class OpFinder:
1231 def __init__(self):
1232 self.op = None
1233 def visitAssName(self, node):
1234 if self.op is None:
1235 self.op = node.flags
1236 elif self.op != node.flags:
1237 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001238 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001239
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001240class Delegator:
1241 """Base class to support delegation for augmented assignment nodes
1242
1243 To generator code for augmented assignments, we use the following
1244 wrapper classes. In visitAugAssign, the left-hand expression node
1245 is visited twice. The first time the visit uses the normal method
1246 for that node . The second time the visit uses a different method
1247 that generates the appropriate code to perform the assignment.
1248 These delegator classes wrap the original AST nodes in order to
1249 support the variant visit methods.
1250 """
1251 def __init__(self, obj):
1252 self.obj = obj
1253
1254 def __getattr__(self, attr):
1255 return getattr(self.obj, attr)
1256
1257class AugGetattr(Delegator):
1258 pass
1259
1260class AugName(Delegator):
1261 pass
1262
1263class AugSlice(Delegator):
1264 pass
1265
1266class AugSubscript(Delegator):
1267 pass
1268
1269wrapper = {
1270 ast.Getattr: AugGetattr,
1271 ast.Name: AugName,
1272 ast.Slice: AugSlice,
1273 ast.Subscript: AugSubscript,
1274 }
1275
1276def wrap_aug(node):
1277 return wrapper[node.__class__](node)
1278
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001279if __name__ == "__main__":
1280 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001281
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001282 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001283 compile(file)