blob: b0bddb71a84b9d9eaa67a090b6315b540f16ff39 [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':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000674 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000675 self.delName(node.name)
676 else:
677 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000678
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000679 def visitAssAttr(self, node):
680 self.visit(node.expr)
681 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000682 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000683 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000684 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000685 else:
686 print "warning: unexpected flags:", node.flags
687 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000688
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000689 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000690 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000691 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000692 for child in node.nodes:
693 self.visit(child)
694
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000695 if VERSION > 1:
696 visitAssTuple = _visitAssSequence
697 visitAssList = _visitAssSequence
698 else:
699 def visitAssTuple(self, node):
700 self._visitAssSequence(node, 'UNPACK_TUPLE')
701
702 def visitAssList(self, node):
703 self._visitAssSequence(node, 'UNPACK_LIST')
704
705 # augmented assignment
706
707 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000708 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000709 aug_node = wrap_aug(node.node)
710 self.visit(aug_node, "load")
711 self.visit(node.expr)
712 self.emit(self._augmented_opcode[node.op])
713 self.visit(aug_node, "store")
714
715 _augmented_opcode = {
716 '+=' : 'INPLACE_ADD',
717 '-=' : 'INPLACE_SUBTRACT',
718 '*=' : 'INPLACE_MULTIPLY',
719 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000720 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000721 '%=' : 'INPLACE_MODULO',
722 '**=': 'INPLACE_POWER',
723 '>>=': 'INPLACE_RSHIFT',
724 '<<=': 'INPLACE_LSHIFT',
725 '&=' : 'INPLACE_AND',
726 '^=' : 'INPLACE_XOR',
727 '|=' : 'INPLACE_OR',
728 }
729
730 def visitAugName(self, node, mode):
731 if mode == "load":
732 self.loadName(node.name)
733 elif mode == "store":
734 self.storeName(node.name)
735
736 def visitAugGetattr(self, node, mode):
737 if mode == "load":
738 self.visit(node.expr)
739 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000740 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000741 elif mode == "store":
742 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000743 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000744
745 def visitAugSlice(self, node, mode):
746 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000747 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000748 elif mode == "store":
749 slice = 0
750 if node.lower:
751 slice = slice | 1
752 if node.upper:
753 slice = slice | 2
754 if slice == 0:
755 self.emit('ROT_TWO')
756 elif slice == 3:
757 self.emit('ROT_FOUR')
758 else:
759 self.emit('ROT_THREE')
760 self.emit('STORE_SLICE+%d' % slice)
761
762 def visitAugSubscript(self, node, mode):
763 if len(node.subs) > 1:
764 raise SyntaxError, "augmented assignment to tuple is not possible"
765 if mode == "load":
766 self.visitSubscript(node, 1)
767 elif mode == "store":
768 self.emit('ROT_THREE')
769 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000770
771 def visitExec(self, node):
772 self.visit(node.expr)
773 if node.locals is None:
774 self.emit('LOAD_CONST', None)
775 else:
776 self.visit(node.locals)
777 if node.globals is None:
778 self.emit('DUP_TOP')
779 else:
780 self.visit(node.globals)
781 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000782
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000783 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000784 pos = 0
785 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000786 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000787 self.visit(node.node)
788 for arg in node.args:
789 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000790 if isinstance(arg, ast.Keyword):
791 kw = kw + 1
792 else:
793 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000794 if node.star_args is not None:
795 self.visit(node.star_args)
796 if node.dstar_args is not None:
797 self.visit(node.dstar_args)
798 have_star = node.star_args is not None
799 have_dstar = node.dstar_args is not None
800 opcode = callfunc_opcode_info[have_star, have_dstar]
801 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000802
Jeremy Hylton2afff322001-08-27 21:51:52 +0000803 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000804 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000805 if node.dest:
806 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000807 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000808 if node.dest:
809 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000810 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000811 if node.dest:
812 self.emit('ROT_TWO')
813 self.emit('PRINT_ITEM_TO')
814 else:
815 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000816 if node.dest and not newline:
817 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000818
819 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000820 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000821 if node.dest:
822 self.emit('PRINT_NEWLINE_TO')
823 else:
824 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000825
826 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000827 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000828 self.visit(node.value)
829 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000830
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000831 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000832
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000833 def visitSlice(self, node, aug_flag=None):
834 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000835 self.visit(node.expr)
836 slice = 0
837 if node.lower:
838 self.visit(node.lower)
839 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000840 if node.upper:
841 self.visit(node.upper)
842 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000843 if aug_flag:
844 if slice == 0:
845 self.emit('DUP_TOP')
846 elif slice == 3:
847 self.emit('DUP_TOPX', 3)
848 else:
849 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000850 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000851 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000852 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000853 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000854 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000855 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000856 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000857 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000858 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000859
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000860 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000861 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000862 for sub in node.subs:
863 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000864 if aug_flag:
865 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000866 if len(node.subs) > 1:
867 self.emit('BUILD_TUPLE', len(node.subs))
868 if node.flags == 'OP_APPLY':
869 self.emit('BINARY_SUBSCR')
870 elif node.flags == 'OP_ASSIGN':
871 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000872 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000873 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000874
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000875 # binary ops
876
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000877 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000878 self.visit(node.left)
879 self.visit(node.right)
880 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000881
882 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000883 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000884
885 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000886 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000887
888 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000889 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000890
891 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000892 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000893
Jeremy Hylton94afe322001-08-29 18:14:39 +0000894 def visitFloorDiv(self, node):
895 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
896
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000897 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000898 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000899
Jeremy Hylton126960b2000-02-14 21:33:10 +0000900 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000901 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000902
903 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000904 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000905
906 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000907 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000908
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000909 # unary ops
910
911 def unaryOp(self, node, op):
912 self.visit(node.expr)
913 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000914
Jeremy Hylton126960b2000-02-14 21:33:10 +0000915 def visitInvert(self, node):
916 return self.unaryOp(node, 'UNARY_INVERT')
917
Jeremy Hylton40245602000-02-08 21:15:48 +0000918 def visitUnarySub(self, node):
919 return self.unaryOp(node, 'UNARY_NEGATIVE')
920
921 def visitUnaryAdd(self, node):
922 return self.unaryOp(node, 'UNARY_POSITIVE')
923
924 def visitUnaryInvert(self, node):
925 return self.unaryOp(node, 'UNARY_INVERT')
926
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000927 def visitNot(self, node):
928 return self.unaryOp(node, 'UNARY_NOT')
929
Jeremy Hylton40245602000-02-08 21:15:48 +0000930 def visitBackquote(self, node):
931 return self.unaryOp(node, 'UNARY_CONVERT')
932
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000933 # bit ops
934
Jeremy Hyltona5058122000-02-14 14:14:29 +0000935 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000936 self.visit(nodes[0])
937 for node in nodes[1:]:
938 self.visit(node)
939 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000940
941 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000942 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000943
944 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000945 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000946
947 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000948 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000949
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000950 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000951
Jeremy Hyltona5058122000-02-14 14:14:29 +0000952 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000953 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000954
Jeremy Hylton40245602000-02-08 21:15:48 +0000955 def visitTuple(self, node):
956 for elt in node.nodes:
957 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000958 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000959
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000960 def visitList(self, node):
961 for elt in node.nodes:
962 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000963 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000964
965 def visitSliceobj(self, node):
966 for child in node.nodes:
967 self.visit(child)
968 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000969
Jeremy Hyltona5058122000-02-14 14:14:29 +0000970 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000971 lineno = getattr(node, 'lineno', None)
972 if lineno:
973 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000974 self.emit('BUILD_MAP', 0)
975 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000976 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000977 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000978 self.emit('SET_LINENO', lineno2)
979 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000980 self.emit('DUP_TOP')
981 self.visit(v)
982 self.emit('ROT_TWO')
983 self.visit(k)
984 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000985
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000986class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000987 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000988 __super_visitClass = CodeGenerator.visitClass
989 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
990
991 def parseSymbols(self, tree):
992 s = symbols.SymbolVisitor()
993 walk(tree, s)
994 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000995
996 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000997 self.scopes = self.parseSymbols(node)
998 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000999 self.__super_visitModule(node)
1000
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001001 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001002 name = self.mangle(name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001003 scope = self.scope.check_name(name)
1004 if scope == SC_LOCAL:
1005 if not self.optimized:
1006 self.emit(prefix + '_NAME', name)
1007 else:
1008 self.emit(prefix + '_FAST', name)
1009 elif scope == SC_GLOBAL:
Jeremy Hyltonf3545752001-08-28 16:35:18 +00001010 if not self.optimized:
1011 self.emit(prefix + '_NAME', name)
1012 else:
1013 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001014 elif scope == SC_FREE or scope == SC_CELL:
1015 self.emit(prefix + '_DEREF', name)
1016 else:
1017 raise RuntimeError, "unsupported scope for var %s: %d" % \
1018 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001019
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001020 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001021 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1022 self.class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001023 walk(node.code, gen)
1024 gen.finish()
1025 self.set_lineno(node)
1026 for default in node.defaults:
1027 self.visit(default)
1028 frees = gen.scope.get_free_vars()
1029 if frees:
1030 for name in frees:
1031 self.emit('LOAD_CLOSURE', name)
1032 self.emit('LOAD_CONST', gen)
1033 self.emit('MAKE_CLOSURE', len(node.defaults))
1034 else:
1035 self.emit('LOAD_CONST', gen)
1036 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001037
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001038 def visitClass(self, node):
1039 gen = self.ClassGen(node, self.filename, self.scopes)
1040 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001041 self.emit('LOAD_CONST', node.doc)
1042 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001043 walk(node.code, gen)
1044 gen.finish()
1045 self.set_lineno(node)
1046 self.emit('LOAD_CONST', node.name)
1047 for base in node.bases:
1048 self.visit(base)
1049 self.emit('BUILD_TUPLE', len(node.bases))
1050 frees = gen.scope.get_free_vars()
1051 for name in frees:
1052 self.emit('LOAD_CLOSURE', name)
1053 self.emit('LOAD_CONST', gen)
1054 if frees:
1055 self.emit('MAKE_CLOSURE', 0)
1056 else:
1057 self.emit('MAKE_FUNCTION', 0)
1058 self.emit('CALL_FUNCTION', 0)
1059 self.emit('BUILD_CLASS')
1060 self.storeName(node.name)
1061
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001062
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001063class LGBScopeMixin:
1064 """Defines initClass() for Python 2.1-compatible scoping"""
1065 def initClass(self):
1066 self.__class__.NameFinder = LocalNameFinder
1067 self.__class__.FunctionGen = FunctionCodeGenerator
1068 self.__class__.ClassGen = ClassCodeGenerator
1069
1070class NestedScopeMixin:
1071 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1072 def initClass(self):
1073 self.__class__.NameFinder = LocalNameFinder
1074 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1075 self.__class__.ClassGen = NestedClassCodeGenerator
1076
1077class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1078 __super_init = CodeGenerator.__init__
1079
1080 scopes = None
1081
1082 def __init__(self, filename):
1083 self.graph = pyassem.PyFlowGraph("<module>", filename)
1084 self.__super_init(filename)
1085
1086class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1087 NestedScopeCodeGenerator):
1088 __super_init = CodeGenerator.__init__
1089
1090 def __init__(self, filename):
1091 self.graph = pyassem.PyFlowGraph("<module>", filename)
1092 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001093## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001094
1095class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001096 optimized = 1
1097 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001098
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001099 def __init__(self, func, filename, scopes, isLambda, class_name):
1100 self.class_name = class_name
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001101 if isLambda:
1102 klass = FunctionCodeGenerator
1103 name = "<lambda.%d>" % klass.lambdaCount
1104 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001105 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001106 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001107 args, hasTupleArg = generateArgList(func.argnames)
1108 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001109 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001110 self.isLambda = isLambda
1111 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001112
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001113 if not isLambda and func.doc:
1114 self.setDocstring(func.doc)
1115
Jeremy Hylton2afff322001-08-27 21:51:52 +00001116 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001117 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001118 if func.varargs:
1119 self.graph.setFlag(CO_VARARGS)
1120 if func.kwargs:
1121 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001122 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001123 if hasTupleArg:
1124 self.generateArgUnpack(func.argnames)
1125
1126 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001127 self.graph.startExitBlock()
1128 if not self.isLambda:
1129 self.emit('LOAD_CONST', None)
1130 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001131
1132 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001133 for i in range(len(args)):
1134 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001135 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001136 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001137 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001138
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001139 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001140 if VERSION > 1:
1141 self.emit('UNPACK_SEQUENCE', len(tup))
1142 else:
1143 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001144 for elt in tup:
1145 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001146 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001147 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001148 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001149
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001150 unpackTuple = unpackSequence
1151
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001152class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1153 CodeGenerator):
1154 super_init = CodeGenerator.__init__ # call be other init
1155 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001156
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001157class NestedFunctionCodeGenerator(AbstractFunctionCode,
1158 NestedScopeMixin,
1159 NestedScopeCodeGenerator):
1160 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1161 __super_init = AbstractFunctionCode.__init__
1162
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001163 def __init__(self, func, filename, scopes, isLambda, class_name):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001164 self.scopes = scopes
1165 self.scope = scopes[func]
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001166 self.__super_init(func, filename, scopes, isLambda, class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001167 self.graph.setFreeVars(self.scope.get_free_vars())
1168 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001169## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001170
1171class AbstractClassCode:
1172
1173 def __init__(self, klass, filename, scopes):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001174 self.class_name = klass.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001175 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001176 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001177 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001178 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001179 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001180 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001181 if klass.doc:
1182 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001183
Jeremy Hylton660cc772001-04-12 06:49:00 +00001184 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001185 name = self.mangle(name)
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001186 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001187 self.emit(prefix + '_NAME', name)
1188
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001189 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001190 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001191 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001192 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001193
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001194class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1195 super_init = CodeGenerator.__init__
1196 scopes = None
1197
1198class NestedClassCodeGenerator(AbstractClassCode,
1199 NestedScopeMixin,
1200 NestedScopeCodeGenerator):
1201 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1202 __super_init = AbstractClassCode.__init__
1203
1204 def __init__(self, klass, filename, scopes):
1205 self.scopes = scopes
1206 self.scope = scopes[klass]
1207 self.__super_init(klass, filename, scopes)
1208 self.graph.setFreeVars(self.scope.get_free_vars())
1209 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001210## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001211
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001212def generateArgList(arglist):
1213 """Generate an arg list marking TupleArgs"""
1214 args = []
1215 extra = []
1216 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001217 for i in range(len(arglist)):
1218 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001219 if type(elt) == types.StringType:
1220 args.append(elt)
1221 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001222 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001223 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001224 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001225 else:
1226 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001227 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001228
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001229def findOp(node):
1230 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1231 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001232 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001233 return v.op
1234
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001235class OpFinder:
1236 def __init__(self):
1237 self.op = None
1238 def visitAssName(self, node):
1239 if self.op is None:
1240 self.op = node.flags
1241 elif self.op != node.flags:
1242 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001243 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001244
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001245class Delegator:
1246 """Base class to support delegation for augmented assignment nodes
1247
1248 To generator code for augmented assignments, we use the following
1249 wrapper classes. In visitAugAssign, the left-hand expression node
1250 is visited twice. The first time the visit uses the normal method
1251 for that node . The second time the visit uses a different method
1252 that generates the appropriate code to perform the assignment.
1253 These delegator classes wrap the original AST nodes in order to
1254 support the variant visit methods.
1255 """
1256 def __init__(self, obj):
1257 self.obj = obj
1258
1259 def __getattr__(self, attr):
1260 return getattr(self.obj, attr)
1261
1262class AugGetattr(Delegator):
1263 pass
1264
1265class AugName(Delegator):
1266 pass
1267
1268class AugSlice(Delegator):
1269 pass
1270
1271class AugSubscript(Delegator):
1272 pass
1273
1274wrapper = {
1275 ast.Getattr: AugGetattr,
1276 ast.Name: AugName,
1277 ast.Slice: AugSlice,
1278 ast.Subscript: AugSubscript,
1279 }
1280
1281def wrap_aug(node):
1282 return wrapper[node.__class__](node)
1283
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001284if __name__ == "__main__":
1285 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001286
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001287 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001288 compile(file)