blob: 07c82f7f382145f13586d6eeffd1d4aa5e359d16 [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):
Jeremy Hylton19367452001-08-29 20:57:43 +0000956 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +0000957 for elt in node.nodes:
958 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000959 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000960
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000961 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000962 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000963 for elt in node.nodes:
964 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000965 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000966
967 def visitSliceobj(self, node):
968 for child in node.nodes:
969 self.visit(child)
970 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000971
Jeremy Hyltona5058122000-02-14 14:14:29 +0000972 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000973 lineno = getattr(node, 'lineno', None)
974 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +0000975 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000976 self.emit('BUILD_MAP', 0)
977 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000978 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000979 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000980 self.emit('SET_LINENO', lineno2)
981 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000982 self.emit('DUP_TOP')
983 self.visit(v)
984 self.emit('ROT_TWO')
985 self.visit(k)
986 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000987
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000988class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000989 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000990 __super_visitClass = CodeGenerator.visitClass
991 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
992
993 def parseSymbols(self, tree):
994 s = symbols.SymbolVisitor()
995 walk(tree, s)
996 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000997
998 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000999 self.scopes = self.parseSymbols(node)
1000 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001001 self.__super_visitModule(node)
1002
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001003 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001004 name = self.mangle(name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001005 scope = self.scope.check_name(name)
1006 if scope == SC_LOCAL:
1007 if not self.optimized:
1008 self.emit(prefix + '_NAME', name)
1009 else:
1010 self.emit(prefix + '_FAST', name)
1011 elif scope == SC_GLOBAL:
Jeremy Hyltonf3545752001-08-28 16:35:18 +00001012 if not self.optimized:
1013 self.emit(prefix + '_NAME', name)
1014 else:
1015 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001016 elif scope == SC_FREE or scope == SC_CELL:
1017 self.emit(prefix + '_DEREF', name)
1018 else:
1019 raise RuntimeError, "unsupported scope for var %s: %d" % \
1020 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001021
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001022 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001023 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1024 self.class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001025 walk(node.code, gen)
1026 gen.finish()
1027 self.set_lineno(node)
1028 for default in node.defaults:
1029 self.visit(default)
1030 frees = gen.scope.get_free_vars()
1031 if frees:
1032 for name in frees:
1033 self.emit('LOAD_CLOSURE', name)
1034 self.emit('LOAD_CONST', gen)
1035 self.emit('MAKE_CLOSURE', len(node.defaults))
1036 else:
1037 self.emit('LOAD_CONST', gen)
1038 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001039
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001040 def visitClass(self, node):
1041 gen = self.ClassGen(node, self.filename, self.scopes)
1042 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001043 self.emit('LOAD_CONST', node.doc)
1044 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001045 walk(node.code, gen)
1046 gen.finish()
1047 self.set_lineno(node)
1048 self.emit('LOAD_CONST', node.name)
1049 for base in node.bases:
1050 self.visit(base)
1051 self.emit('BUILD_TUPLE', len(node.bases))
1052 frees = gen.scope.get_free_vars()
1053 for name in frees:
1054 self.emit('LOAD_CLOSURE', name)
1055 self.emit('LOAD_CONST', gen)
1056 if frees:
1057 self.emit('MAKE_CLOSURE', 0)
1058 else:
1059 self.emit('MAKE_FUNCTION', 0)
1060 self.emit('CALL_FUNCTION', 0)
1061 self.emit('BUILD_CLASS')
1062 self.storeName(node.name)
1063
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001064
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001065class LGBScopeMixin:
1066 """Defines initClass() for Python 2.1-compatible scoping"""
1067 def initClass(self):
1068 self.__class__.NameFinder = LocalNameFinder
1069 self.__class__.FunctionGen = FunctionCodeGenerator
1070 self.__class__.ClassGen = ClassCodeGenerator
1071
1072class NestedScopeMixin:
1073 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1074 def initClass(self):
1075 self.__class__.NameFinder = LocalNameFinder
1076 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1077 self.__class__.ClassGen = NestedClassCodeGenerator
1078
1079class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1080 __super_init = CodeGenerator.__init__
1081
1082 scopes = None
1083
1084 def __init__(self, filename):
1085 self.graph = pyassem.PyFlowGraph("<module>", filename)
1086 self.__super_init(filename)
1087
1088class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1089 NestedScopeCodeGenerator):
1090 __super_init = CodeGenerator.__init__
1091
1092 def __init__(self, filename):
1093 self.graph = pyassem.PyFlowGraph("<module>", filename)
1094 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001095## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001096
1097class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001098 optimized = 1
1099 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001100
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001101 def __init__(self, func, filename, scopes, isLambda, class_name):
1102 self.class_name = class_name
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001103 if isLambda:
1104 klass = FunctionCodeGenerator
1105 name = "<lambda.%d>" % klass.lambdaCount
1106 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001107 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001108 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001109 args, hasTupleArg = generateArgList(func.argnames)
1110 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001111 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001112 self.isLambda = isLambda
1113 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001114
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001115 if not isLambda and func.doc:
1116 self.setDocstring(func.doc)
1117
Jeremy Hylton2afff322001-08-27 21:51:52 +00001118 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001119 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001120 if func.varargs:
1121 self.graph.setFlag(CO_VARARGS)
1122 if func.kwargs:
1123 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001124 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001125 if hasTupleArg:
1126 self.generateArgUnpack(func.argnames)
1127
1128 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001129 self.graph.startExitBlock()
1130 if not self.isLambda:
1131 self.emit('LOAD_CONST', None)
1132 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001133
1134 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001135 for i in range(len(args)):
1136 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001137 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001138 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001139 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001140
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001141 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001142 if VERSION > 1:
1143 self.emit('UNPACK_SEQUENCE', len(tup))
1144 else:
1145 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001146 for elt in tup:
1147 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001148 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001149 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001150 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001151
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001152 unpackTuple = unpackSequence
1153
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001154class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1155 CodeGenerator):
1156 super_init = CodeGenerator.__init__ # call be other init
1157 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001158
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001159class NestedFunctionCodeGenerator(AbstractFunctionCode,
1160 NestedScopeMixin,
1161 NestedScopeCodeGenerator):
1162 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1163 __super_init = AbstractFunctionCode.__init__
1164
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001165 def __init__(self, func, filename, scopes, isLambda, class_name):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001166 self.scopes = scopes
1167 self.scope = scopes[func]
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001168 self.__super_init(func, filename, scopes, isLambda, class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001169 self.graph.setFreeVars(self.scope.get_free_vars())
1170 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001171## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001172
1173class AbstractClassCode:
1174
1175 def __init__(self, klass, filename, scopes):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001176 self.class_name = klass.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001177 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001178 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001179 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001180 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001181 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001182 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001183 if klass.doc:
1184 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001185
Jeremy Hylton660cc772001-04-12 06:49:00 +00001186 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001187 name = self.mangle(name)
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001188 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001189 self.emit(prefix + '_NAME', name)
1190
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001191 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001192 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001193 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001194 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001195
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001196class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1197 super_init = CodeGenerator.__init__
1198 scopes = None
1199
1200class NestedClassCodeGenerator(AbstractClassCode,
1201 NestedScopeMixin,
1202 NestedScopeCodeGenerator):
1203 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1204 __super_init = AbstractClassCode.__init__
1205
1206 def __init__(self, klass, filename, scopes):
1207 self.scopes = scopes
1208 self.scope = scopes[klass]
1209 self.__super_init(klass, filename, scopes)
1210 self.graph.setFreeVars(self.scope.get_free_vars())
1211 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001212## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001213
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001214def generateArgList(arglist):
1215 """Generate an arg list marking TupleArgs"""
1216 args = []
1217 extra = []
1218 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001219 for i in range(len(arglist)):
1220 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001221 if type(elt) == types.StringType:
1222 args.append(elt)
1223 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001224 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001225 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001226 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001227 else:
1228 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001229 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001230
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001231def findOp(node):
1232 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1233 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001234 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001235 return v.op
1236
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001237class OpFinder:
1238 def __init__(self):
1239 self.op = None
1240 def visitAssName(self, node):
1241 if self.op is None:
1242 self.op = node.flags
1243 elif self.op != node.flags:
1244 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001245 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001246
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001247class Delegator:
1248 """Base class to support delegation for augmented assignment nodes
1249
1250 To generator code for augmented assignments, we use the following
1251 wrapper classes. In visitAugAssign, the left-hand expression node
1252 is visited twice. The first time the visit uses the normal method
1253 for that node . The second time the visit uses a different method
1254 that generates the appropriate code to perform the assignment.
1255 These delegator classes wrap the original AST nodes in order to
1256 support the variant visit methods.
1257 """
1258 def __init__(self, obj):
1259 self.obj = obj
1260
1261 def __getattr__(self, attr):
1262 return getattr(self.obj, attr)
1263
1264class AugGetattr(Delegator):
1265 pass
1266
1267class AugName(Delegator):
1268 pass
1269
1270class AugSlice(Delegator):
1271 pass
1272
1273class AugSubscript(Delegator):
1274 pass
1275
1276wrapper = {
1277 ast.Getattr: AugGetattr,
1278 ast.Name: AugName,
1279 ast.Slice: AugSlice,
1280 ast.Subscript: AugSubscript,
1281 }
1282
1283def wrap_aug(node):
1284 return wrapper[node.__class__](node)
1285
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001286if __name__ == "__main__":
1287 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001288
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001289 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001290 compile(file)