blob: 4f7603d4a0fe89e338ac0fe64fe003b7eac34b47 [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
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
15 CO_NESTED, CO_GENERATOR
16from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000017
Jeremy Hylton9c048f92000-10-13 21:58:13 +000018# Do we have Python 1.x or Python 2.x?
19try:
20 VERSION = sys.version_info[0]
21except AttributeError:
22 VERSION = 1
23
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000024callfunc_opcode_info = {
25 # (Have *args, Have **args) : opcode
26 (0,0) : "CALL_FUNCTION",
27 (1,0) : "CALL_FUNCTION_VAR",
28 (0,1) : "CALL_FUNCTION_KW",
29 (1,1) : "CALL_FUNCTION_VAR_KW",
30}
31
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000032LOOP = 1
33EXCEPT = 2
34TRY_FINALLY = 3
35END_FINALLY = 4
36
Jeremy Hylton9c048f92000-10-13 21:58:13 +000037def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000038 f = open(filename)
39 buf = f.read()
40 f.close()
41 mod = Module(buf, filename)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000042 mod.compile(display)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000043 f = open(filename + "c", "wb")
44 mod.dump(f)
45 f.close()
46
47class Module:
48 def __init__(self, source, filename):
Jeremy Hylton2afff322001-08-27 21:51:52 +000049 self.filename = os.path.abspath(filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000050 self.source = source
51 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000052
Jeremy Hylton9c048f92000-10-13 21:58:13 +000053 def compile(self, display=0):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000054 tree = parse(self.source)
Jeremy Hylton2afff322001-08-27 21:51:52 +000055 gen = NestedScopeModuleCodeGenerator(self.filename)
56 walk(tree, gen, verbose=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000057 if display:
58 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000059 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000060 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000061
62 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000063 f.write(self.getPycHeader())
64 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000065
Jeremy Hylton9c048f92000-10-13 21:58:13 +000066 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000067
68 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000069 # compile.c uses marshal to write a long directly, with
70 # calling the interface that would also generate a 1-byte code
71 # to indicate the type of the value. simplest way to get the
72 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000073 mtime = os.stat(self.filename)[stat.ST_MTIME]
74 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000075 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000076
Jeremy Hylton364f9b92001-04-12 06:40:42 +000077class LocalNameFinder:
78 """Find local names in scope"""
79 def __init__(self, names=()):
80 self.names = misc.Set()
81 self.globals = misc.Set()
82 for name in names:
83 self.names.add(name)
84
85 # XXX list comprehensions and for loops
86
87 def getLocals(self):
88 for elt in self.globals.elements():
89 if self.names.has_elt(elt):
90 self.names.remove(elt)
91 return self.names
92
93 def visitDict(self, node):
94 pass
95
96 def visitGlobal(self, node):
97 for name in node.names:
98 self.globals.add(name)
99
100 def visitFunction(self, node):
101 self.names.add(node.name)
102
103 def visitLambda(self, node):
104 pass
105
106 def visitImport(self, node):
107 for name, alias in node.names:
108 self.names.add(alias or name)
109
110 def visitFrom(self, node):
111 for name, alias in node.names:
112 self.names.add(alias or name)
113
114 def visitClass(self, node):
115 self.names.add(node.name)
116
117 def visitAssName(self, node):
118 self.names.add(node.name)
119
Jeremy Hylton2afff322001-08-27 21:51:52 +0000120def is_constant_false(node):
121 if isinstance(node, ast.Const):
122 if not node.value:
123 return 1
124 return 0
125
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000126class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000127 """Defines basic code generator for Python bytecode
128
129 This class is an abstract base class. Concrete subclasses must
130 define an __init__() that defines self.graph and then calls the
131 __init__() defined in this class.
132
133 The concrete class must also define the class attributes
134 NameFinder, FunctionGen, and ClassGen. These attributes can be
135 defined in the initClass() method, which is a hook for
136 initializing these methods after all the classes have been
137 defined.
138 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000139
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000140 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000141 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000142 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000143
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000144 def __init__(self, filename):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000145 if self.__initialized is None:
146 self.initClass()
147 self.__class__.__initialized = 1
148 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000149 self.filename = filename
150 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000151 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000152 self.curStack = 0
153 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000154 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000155 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000156
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000157 def initClass(self):
158 """This method is called once for each class"""
159
160 def checkClass(self):
161 """Verify that class is constructed correctly"""
162 try:
163 assert hasattr(self, 'graph')
164 assert getattr(self, 'NameFinder')
165 assert getattr(self, 'FunctionGen')
166 assert getattr(self, 'ClassGen')
167 except AssertionError, msg:
168 intro = "Bad class construction for %s" % self.__class__.__name__
169 raise AssertionError, intro
170
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000171 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000172 self.emit = self.graph.emit
173 self.newBlock = self.graph.newBlock
174 self.startBlock = self.graph.startBlock
175 self.nextBlock = self.graph.nextBlock
176 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000177
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000178 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000179 """Return a code object"""
180 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000181
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000182 def mangle(self, name):
183 if self.class_name is not None:
184 return misc.mangle(name, self.class_name)
185 else:
186 return name
187
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000188 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000189
Jeremy Hylton40245602000-02-08 21:15:48 +0000190 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000191 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000192
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000193 def storeName(self, name):
194 self._nameOp('STORE', name)
195
196 def loadName(self, name):
197 self._nameOp('LOAD', name)
198
199 def delName(self, name):
200 self._nameOp('DELETE', name)
201
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000202 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000203 name = self.mangle(name)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000204 if not self.optimized:
205 self.emit(prefix + '_NAME', name)
206 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000207 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000208 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000209 else:
210 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000211
Jeremy Hylton13d70942001-04-12 21:04:43 +0000212 def _implicitNameOp(self, prefix, name):
213 """Emit name ops for names generated implicitly by for loops
214
215 The interpreter generates names that start with a period or
216 dollar sign. The symbol table ignores these names because
217 they aren't present in the program text.
218 """
219 if self.optimized:
220 self.emit(prefix + '_FAST', name)
221 else:
222 self.emit(prefix + '_NAME', name)
223
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000224 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000225 """Emit SET_LINENO if node has lineno attribute and it is
226 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000227
228 Returns true if SET_LINENO was emitted.
229
230 There are no rules for when an AST node should have a lineno
231 attribute. The transformer and AST code need to be reviewed
232 and a consistent policy implemented and documented. Until
233 then, this method works around missing line numbers.
234 """
235 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000236 if lineno is not None and (lineno != self.last_lineno
237 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000238 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000239 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000240 return 1
241 return 0
242
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000243 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000244 # code objects. They use class attributes to determine what
245 # specialized code generators to use.
246
247 NameFinder = LocalNameFinder
248 FunctionGen = None
249 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000250
251 def visitModule(self, node):
Jeremy Hylton13d70942001-04-12 21:04:43 +0000252 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000253 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000254 self.emit('LOAD_CONST', node.doc)
255 self.storeName('__doc__')
256 lnf = walk(node.node, self.NameFinder(), verbose=0)
257 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000258 self.visit(node.node)
259 self.emit('LOAD_CONST', None)
260 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000261
262 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000263 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000264 if node.doc:
265 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000266 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000267
268 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000269 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000270
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000271 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000272 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
273 self.class_name)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000274 walk(node.code, gen)
275 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000276 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000277 for default in node.defaults:
278 self.visit(default)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000279 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000280 self.emit('MAKE_FUNCTION', len(node.defaults))
281
282 def visitClass(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000283 gen = self.ClassGen(node, self.filename, self.scopes)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000284 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000285 self.emit('LOAD_CONST', node.doc)
286 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000287 walk(node.code, gen)
288 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000289 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000290 self.emit('LOAD_CONST', node.name)
291 for base in node.bases:
292 self.visit(base)
293 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000294 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000295 self.emit('MAKE_FUNCTION', 0)
296 self.emit('CALL_FUNCTION', 0)
297 self.emit('BUILD_CLASS')
298 self.storeName(node.name)
299
300 # The rest are standard visitor methods
301
302 # The next few implement control-flow statements
303
304 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000305 end = self.newBlock()
306 numtests = len(node.tests)
307 for i in range(numtests):
308 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000309 if is_constant_false(test):
310 # XXX will need to check generator stuff here
311 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000312 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000313 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000314 nextTest = self.newBlock()
315 self.emit('JUMP_IF_FALSE', nextTest)
316 self.nextBlock()
317 self.emit('POP_TOP')
318 self.visit(suite)
319 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000320 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000321 self.emit('POP_TOP')
322 if node.else_:
323 self.visit(node.else_)
324 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000325
326 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000327 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000328
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000329 loop = self.newBlock()
330 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000331
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000332 after = self.newBlock()
333 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000334
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000335 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000336 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000337
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000338 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000339 self.visit(node.test)
340 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000341
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000342 self.nextBlock()
343 self.emit('POP_TOP')
344 self.visit(node.body)
345 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000346
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000347 self.startBlock(else_) # or just the POPs if not else clause
348 self.emit('POP_TOP')
349 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000350 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000351 if node.else_:
352 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000353 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000354
355 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000356 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000357 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000358 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000359 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000360
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000361 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000362 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000363 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000364 self.emit('GET_ITER')
365
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000366 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000367 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000368 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369 self.visit(node.assign)
370 self.visit(node.body)
371 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000372 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000373 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000374 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000375 if node.else_:
376 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000377 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000378
379 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000380 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000381 raise SyntaxError, "'break' outside loop (%s, %d)" % \
382 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000383 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000384 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000385
386 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000387 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000388 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000389 (self.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000390 kind, block = self.setups.top()
391 if kind == LOOP:
392 self.set_lineno(node)
393 self.emit('JUMP_ABSOLUTE', block)
394 self.nextBlock()
395 elif kind == EXCEPT or kind == TRY_FINALLY:
396 self.set_lineno(node)
397 # find the block that starts the loop
398 top = len(self.setups)
399 while top > 0:
400 top = top - 1
401 kind, loop_block = self.setups[top]
402 if kind == LOOP:
403 break
404 if kind != LOOP:
405 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
406 (self.filename, node.lineno)
407 self.emit('CONTINUE_LOOP', loop_block)
408 self.nextBlock()
409 elif kind == END_FINALLY:
410 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
411 raise SyntaxError, msg % (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000412
413 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000414 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000415 for child in node.nodes[:-1]:
416 self.visit(child)
417 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000418 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000419 self.emit('POP_TOP')
420 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000421 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000422
423 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000424 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000425
426 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000427 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000428
429 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000430 self.visit(node.expr)
431 cleanup = self.newBlock()
432 for op, code in node.ops[:-1]:
433 self.visit(code)
434 self.emit('DUP_TOP')
435 self.emit('ROT_THREE')
436 self.emit('COMPARE_OP', op)
437 self.emit('JUMP_IF_FALSE', cleanup)
438 self.nextBlock()
439 self.emit('POP_TOP')
440 # now do the last comparison
441 if node.ops:
442 op, code = node.ops[-1]
443 self.visit(code)
444 self.emit('COMPARE_OP', op)
445 if len(node.ops) > 1:
446 end = self.newBlock()
447 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000448 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000449 self.emit('ROT_TWO')
450 self.emit('POP_TOP')
451 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000452
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000453 # list comprehensions
454 __list_count = 0
455
456 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000457 self.set_lineno(node)
458 # setup list
459 append = "$append%d" % self.__list_count
460 self.__list_count = self.__list_count + 1
461 self.emit('BUILD_LIST', 0)
462 self.emit('DUP_TOP')
463 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000464 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000465
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000466 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000467 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000468 start, anchor = self.visit(for_)
469 cont = None
470 for if_ in for_.ifs:
471 if cont is None:
472 cont = self.newBlock()
473 self.visit(if_, cont)
474 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000475
Jeremy Hylton13d70942001-04-12 21:04:43 +0000476 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000477 self.visit(node.expr)
478 self.emit('CALL_FUNCTION', 1)
479 self.emit('POP_TOP')
480
481 for start, cont, anchor in stack:
482 if cont:
483 skip_one = self.newBlock()
484 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000485 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000486 self.emit('POP_TOP')
487 self.nextBlock(skip_one)
488 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000489 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000490 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000491
492 self.__list_count = self.__list_count - 1
493
494 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000495 start = self.newBlock()
496 anchor = self.newBlock()
497
498 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000499 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000500 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000501 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000502 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000503 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000504 self.visit(node.assign)
505 return start, anchor
506
507 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000508 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000509 self.visit(node.test)
510 self.emit('JUMP_IF_FALSE', branch)
511 self.newBlock()
512 self.emit('POP_TOP')
513
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000514 # exception related
515
516 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000517 # XXX would be interesting to implement this via a
518 # transformation of the AST before this stage
519 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000520 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000521 # XXX __debug__ and AssertionError appear to be special cases
522 # -- they are always loaded as globals even if there are local
523 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000524 self.emit('LOAD_GLOBAL', '__debug__')
525 self.emit('JUMP_IF_FALSE', end)
526 self.nextBlock()
527 self.emit('POP_TOP')
528 self.visit(node.test)
529 self.emit('JUMP_IF_TRUE', end)
530 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000531 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000532 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000533 if node.fail:
534 self.visit(node.fail)
535 self.emit('RAISE_VARARGS', 2)
536 else:
537 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000538 self.nextBlock(end)
539 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000540
541 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000542 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000543 n = 0
544 if node.expr1:
545 self.visit(node.expr1)
546 n = n + 1
547 if node.expr2:
548 self.visit(node.expr2)
549 n = n + 1
550 if node.expr3:
551 self.visit(node.expr3)
552 n = n + 1
553 self.emit('RAISE_VARARGS', n)
554
555 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000556 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000557 handlers = self.newBlock()
558 end = self.newBlock()
559 if node.else_:
560 lElse = self.newBlock()
561 else:
562 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000563 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000564 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000565 self.nextBlock(body)
566 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000567 self.visit(node.body)
568 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000569 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000570 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000571 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000572
573 last = len(node.handlers) - 1
574 for i in range(len(node.handlers)):
575 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000576 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000577 if expr:
578 self.emit('DUP_TOP')
579 self.visit(expr)
580 self.emit('COMPARE_OP', 'exception match')
581 next = self.newBlock()
582 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000583 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000584 self.emit('POP_TOP')
585 self.emit('POP_TOP')
586 if target:
587 self.visit(target)
588 else:
589 self.emit('POP_TOP')
590 self.emit('POP_TOP')
591 self.visit(body)
592 self.emit('JUMP_FORWARD', end)
593 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000594 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000595 else:
596 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000597 if expr: # XXX
598 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000599 self.emit('END_FINALLY')
600 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000601 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000602 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000603 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000604
605 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000606 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000607 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000608 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000609 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000610 self.nextBlock(body)
611 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000612 self.visit(node.body)
613 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000614 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000615 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000616 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000617 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000618 self.visit(node.final)
619 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000620 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000621
622 # misc
623
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000624 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000625 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000626 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000627 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000628
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000629 def visitConst(self, node):
630 self.emit('LOAD_CONST', node.value)
631
632 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000633 self.emit('LOAD_CONST', node.name)
634 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000635
636 def visitGlobal(self, node):
637 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000638 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000639
640 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000641 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000642 self.loadName(node.name)
643
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000644 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000645 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000646
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000647 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000648 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000649 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000650 if VERSION > 1:
651 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000652 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000653 mod = string.split(name, ".")[0]
654 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000655
656 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000657 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000658 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000659 if VERSION > 1:
660 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000661 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000662 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000663 if VERSION > 1:
664 if name == '*':
665 self.namespace = 0
666 self.emit('IMPORT_STAR')
667 # There can only be one name w/ from ... import *
668 assert len(node.names) == 1
669 return
670 else:
671 self.emit('IMPORT_FROM', name)
672 self._resolveDots(name)
673 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000674 else:
675 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000676 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000677
Jeremy Hylton20516082000-09-01 20:33:26 +0000678 def _resolveDots(self, name):
679 elts = string.split(name, ".")
680 if len(elts) == 1:
681 return
682 for elt in elts[1:]:
683 self.emit('LOAD_ATTR', elt)
684
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000685 def visitGetattr(self, node):
686 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000687 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000688
689 # next five implement assignments
690
691 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000692 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000693 self.visit(node.expr)
694 dups = len(node.nodes) - 1
695 for i in range(len(node.nodes)):
696 elt = node.nodes[i]
697 if i < dups:
698 self.emit('DUP_TOP')
699 if isinstance(elt, ast.Node):
700 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000701
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 def visitAssName(self, node):
703 if node.flags == 'OP_ASSIGN':
704 self.storeName(node.name)
705 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000706 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000707 self.delName(node.name)
708 else:
709 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000710
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000711 def visitAssAttr(self, node):
712 self.visit(node.expr)
713 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000714 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000715 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000716 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000717 else:
718 print "warning: unexpected flags:", node.flags
719 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000720
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000721 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000722 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000723 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724 for child in node.nodes:
725 self.visit(child)
726
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000727 if VERSION > 1:
728 visitAssTuple = _visitAssSequence
729 visitAssList = _visitAssSequence
730 else:
731 def visitAssTuple(self, node):
732 self._visitAssSequence(node, 'UNPACK_TUPLE')
733
734 def visitAssList(self, node):
735 self._visitAssSequence(node, 'UNPACK_LIST')
736
737 # augmented assignment
738
739 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000740 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000741 aug_node = wrap_aug(node.node)
742 self.visit(aug_node, "load")
743 self.visit(node.expr)
744 self.emit(self._augmented_opcode[node.op])
745 self.visit(aug_node, "store")
746
747 _augmented_opcode = {
748 '+=' : 'INPLACE_ADD',
749 '-=' : 'INPLACE_SUBTRACT',
750 '*=' : 'INPLACE_MULTIPLY',
751 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000752 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000753 '%=' : 'INPLACE_MODULO',
754 '**=': 'INPLACE_POWER',
755 '>>=': 'INPLACE_RSHIFT',
756 '<<=': 'INPLACE_LSHIFT',
757 '&=' : 'INPLACE_AND',
758 '^=' : 'INPLACE_XOR',
759 '|=' : 'INPLACE_OR',
760 }
761
762 def visitAugName(self, node, mode):
763 if mode == "load":
764 self.loadName(node.name)
765 elif mode == "store":
766 self.storeName(node.name)
767
768 def visitAugGetattr(self, node, mode):
769 if mode == "load":
770 self.visit(node.expr)
771 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000772 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000773 elif mode == "store":
774 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000775 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000776
777 def visitAugSlice(self, node, mode):
778 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000779 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000780 elif mode == "store":
781 slice = 0
782 if node.lower:
783 slice = slice | 1
784 if node.upper:
785 slice = slice | 2
786 if slice == 0:
787 self.emit('ROT_TWO')
788 elif slice == 3:
789 self.emit('ROT_FOUR')
790 else:
791 self.emit('ROT_THREE')
792 self.emit('STORE_SLICE+%d' % slice)
793
794 def visitAugSubscript(self, node, mode):
795 if len(node.subs) > 1:
796 raise SyntaxError, "augmented assignment to tuple is not possible"
797 if mode == "load":
798 self.visitSubscript(node, 1)
799 elif mode == "store":
800 self.emit('ROT_THREE')
801 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000802
803 def visitExec(self, node):
804 self.visit(node.expr)
805 if node.locals is None:
806 self.emit('LOAD_CONST', None)
807 else:
808 self.visit(node.locals)
809 if node.globals is None:
810 self.emit('DUP_TOP')
811 else:
812 self.visit(node.globals)
813 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000814
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000815 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000816 pos = 0
817 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000818 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000819 self.visit(node.node)
820 for arg in node.args:
821 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000822 if isinstance(arg, ast.Keyword):
823 kw = kw + 1
824 else:
825 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000826 if node.star_args is not None:
827 self.visit(node.star_args)
828 if node.dstar_args is not None:
829 self.visit(node.dstar_args)
830 have_star = node.star_args is not None
831 have_dstar = node.dstar_args is not None
832 opcode = callfunc_opcode_info[have_star, have_dstar]
833 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000834
Jeremy Hylton2afff322001-08-27 21:51:52 +0000835 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000836 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000837 if node.dest:
838 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000839 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000840 if node.dest:
841 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000842 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000843 if node.dest:
844 self.emit('ROT_TWO')
845 self.emit('PRINT_ITEM_TO')
846 else:
847 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000848 if node.dest and not newline:
849 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000850
851 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000852 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000853 if node.dest:
854 self.emit('PRINT_NEWLINE_TO')
855 else:
856 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000857
858 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000859 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000860 self.visit(node.value)
861 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000862
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000863 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000864
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000865 def visitSlice(self, node, aug_flag=None):
866 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000867 self.visit(node.expr)
868 slice = 0
869 if node.lower:
870 self.visit(node.lower)
871 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000872 if node.upper:
873 self.visit(node.upper)
874 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000875 if aug_flag:
876 if slice == 0:
877 self.emit('DUP_TOP')
878 elif slice == 3:
879 self.emit('DUP_TOPX', 3)
880 else:
881 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000882 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000883 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000884 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000885 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000886 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000887 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000888 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000889 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000890 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000891
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000892 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000893 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000894 for sub in node.subs:
895 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000896 if aug_flag:
897 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000898 if len(node.subs) > 1:
899 self.emit('BUILD_TUPLE', len(node.subs))
900 if node.flags == 'OP_APPLY':
901 self.emit('BINARY_SUBSCR')
902 elif node.flags == 'OP_ASSIGN':
903 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000904 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000905 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000906
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000907 # binary ops
908
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000909 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000910 self.visit(node.left)
911 self.visit(node.right)
912 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000913
914 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000915 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000916
917 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000918 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000919
920 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000921 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000922
923 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000924 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000925
Jeremy Hylton94afe322001-08-29 18:14:39 +0000926 def visitFloorDiv(self, node):
927 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
928
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000929 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000930 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000931
Jeremy Hylton126960b2000-02-14 21:33:10 +0000932 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000933 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000934
935 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000936 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000937
938 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000939 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000940
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000941 # unary ops
942
943 def unaryOp(self, node, op):
944 self.visit(node.expr)
945 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000946
Jeremy Hylton126960b2000-02-14 21:33:10 +0000947 def visitInvert(self, node):
948 return self.unaryOp(node, 'UNARY_INVERT')
949
Jeremy Hylton40245602000-02-08 21:15:48 +0000950 def visitUnarySub(self, node):
951 return self.unaryOp(node, 'UNARY_NEGATIVE')
952
953 def visitUnaryAdd(self, node):
954 return self.unaryOp(node, 'UNARY_POSITIVE')
955
956 def visitUnaryInvert(self, node):
957 return self.unaryOp(node, 'UNARY_INVERT')
958
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000959 def visitNot(self, node):
960 return self.unaryOp(node, 'UNARY_NOT')
961
Jeremy Hylton40245602000-02-08 21:15:48 +0000962 def visitBackquote(self, node):
963 return self.unaryOp(node, 'UNARY_CONVERT')
964
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000965 # bit ops
966
Jeremy Hyltona5058122000-02-14 14:14:29 +0000967 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000968 self.visit(nodes[0])
969 for node in nodes[1:]:
970 self.visit(node)
971 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000972
973 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000974 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000975
976 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000977 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000978
979 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000980 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000981
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000982 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000983
Jeremy Hyltona5058122000-02-14 14:14:29 +0000984 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000985 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000986
Jeremy Hylton40245602000-02-08 21:15:48 +0000987 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000988 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +0000989 for elt in node.nodes:
990 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000991 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000992
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000993 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000994 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000995 for elt in node.nodes:
996 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000997 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000998
999 def visitSliceobj(self, node):
1000 for child in node.nodes:
1001 self.visit(child)
1002 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001003
Jeremy Hyltona5058122000-02-14 14:14:29 +00001004 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001005 lineno = getattr(node, 'lineno', None)
1006 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001007 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001008 self.emit('BUILD_MAP', 0)
1009 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001010 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001011 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001012 self.emit('SET_LINENO', lineno2)
1013 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001014 self.emit('DUP_TOP')
1015 self.visit(v)
1016 self.emit('ROT_TWO')
1017 self.visit(k)
1018 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001019
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001020class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001021 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001022 __super_visitClass = CodeGenerator.visitClass
1023 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
1024
1025 def parseSymbols(self, tree):
1026 s = symbols.SymbolVisitor()
1027 walk(tree, s)
1028 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001029
1030 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001031 self.scopes = self.parseSymbols(node)
1032 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001033 self.__super_visitModule(node)
1034
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001035 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001036 name = self.mangle(name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001037 scope = self.scope.check_name(name)
1038 if scope == SC_LOCAL:
1039 if not self.optimized:
1040 self.emit(prefix + '_NAME', name)
1041 else:
1042 self.emit(prefix + '_FAST', name)
1043 elif scope == SC_GLOBAL:
Jeremy Hyltonf3545752001-08-28 16:35:18 +00001044 if not self.optimized:
1045 self.emit(prefix + '_NAME', name)
1046 else:
1047 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001048 elif scope == SC_FREE or scope == SC_CELL:
1049 self.emit(prefix + '_DEREF', name)
1050 else:
1051 raise RuntimeError, "unsupported scope for var %s: %d" % \
1052 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001053
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001054 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001055 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1056 self.class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001057 walk(node.code, gen)
1058 gen.finish()
1059 self.set_lineno(node)
1060 for default in node.defaults:
1061 self.visit(default)
1062 frees = gen.scope.get_free_vars()
1063 if frees:
1064 for name in frees:
1065 self.emit('LOAD_CLOSURE', name)
1066 self.emit('LOAD_CONST', gen)
1067 self.emit('MAKE_CLOSURE', len(node.defaults))
1068 else:
1069 self.emit('LOAD_CONST', gen)
1070 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001071
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001072 def visitClass(self, node):
1073 gen = self.ClassGen(node, self.filename, self.scopes)
1074 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001075 self.emit('LOAD_CONST', node.doc)
1076 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001077 walk(node.code, gen)
1078 gen.finish()
1079 self.set_lineno(node)
1080 self.emit('LOAD_CONST', node.name)
1081 for base in node.bases:
1082 self.visit(base)
1083 self.emit('BUILD_TUPLE', len(node.bases))
1084 frees = gen.scope.get_free_vars()
1085 for name in frees:
1086 self.emit('LOAD_CLOSURE', name)
1087 self.emit('LOAD_CONST', gen)
1088 if frees:
1089 self.emit('MAKE_CLOSURE', 0)
1090 else:
1091 self.emit('MAKE_FUNCTION', 0)
1092 self.emit('CALL_FUNCTION', 0)
1093 self.emit('BUILD_CLASS')
1094 self.storeName(node.name)
1095
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001096
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001097class LGBScopeMixin:
1098 """Defines initClass() for Python 2.1-compatible scoping"""
1099 def initClass(self):
1100 self.__class__.NameFinder = LocalNameFinder
1101 self.__class__.FunctionGen = FunctionCodeGenerator
1102 self.__class__.ClassGen = ClassCodeGenerator
1103
1104class NestedScopeMixin:
1105 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1106 def initClass(self):
1107 self.__class__.NameFinder = LocalNameFinder
1108 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1109 self.__class__.ClassGen = NestedClassCodeGenerator
1110
1111class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1112 __super_init = CodeGenerator.__init__
1113
1114 scopes = None
1115
1116 def __init__(self, filename):
1117 self.graph = pyassem.PyFlowGraph("<module>", filename)
1118 self.__super_init(filename)
1119
1120class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1121 NestedScopeCodeGenerator):
1122 __super_init = CodeGenerator.__init__
1123
1124 def __init__(self, filename):
1125 self.graph = pyassem.PyFlowGraph("<module>", filename)
1126 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001127## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001128
1129class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001130 optimized = 1
1131 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001132
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001133 def __init__(self, func, filename, scopes, isLambda, class_name):
1134 self.class_name = class_name
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001135 if isLambda:
1136 klass = FunctionCodeGenerator
1137 name = "<lambda.%d>" % klass.lambdaCount
1138 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001139 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001140 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001141 args, hasTupleArg = generateArgList(func.argnames)
1142 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001143 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001144 self.isLambda = isLambda
1145 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001146
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001147 if not isLambda and func.doc:
1148 self.setDocstring(func.doc)
1149
Jeremy Hylton2afff322001-08-27 21:51:52 +00001150 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001151 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001152 if func.varargs:
1153 self.graph.setFlag(CO_VARARGS)
1154 if func.kwargs:
1155 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001156 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001157 if hasTupleArg:
1158 self.generateArgUnpack(func.argnames)
1159
1160 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001161 self.graph.startExitBlock()
1162 if not self.isLambda:
1163 self.emit('LOAD_CONST', None)
1164 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001165
1166 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001167 for i in range(len(args)):
1168 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001169 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001170 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001171 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001172
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001173 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001174 if VERSION > 1:
1175 self.emit('UNPACK_SEQUENCE', len(tup))
1176 else:
1177 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001178 for elt in tup:
1179 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001180 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001181 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001182 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001183
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001184 unpackTuple = unpackSequence
1185
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001186class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1187 CodeGenerator):
1188 super_init = CodeGenerator.__init__ # call be other init
1189 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001190
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001191class NestedFunctionCodeGenerator(AbstractFunctionCode,
1192 NestedScopeMixin,
1193 NestedScopeCodeGenerator):
1194 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1195 __super_init = AbstractFunctionCode.__init__
1196
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001197 def __init__(self, func, filename, scopes, isLambda, class_name):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001198 self.scopes = scopes
1199 self.scope = scopes[func]
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001200 self.__super_init(func, filename, scopes, isLambda, class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001201 self.graph.setFreeVars(self.scope.get_free_vars())
1202 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton71ebc332001-08-30 20:25:55 +00001203 if self.scope.generator is not None:
1204 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001205## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001206
1207class AbstractClassCode:
1208
1209 def __init__(self, klass, filename, scopes):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001210 self.class_name = klass.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001211 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001212 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001213 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001214 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001215 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001216 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001217 if klass.doc:
1218 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001219
Jeremy Hylton660cc772001-04-12 06:49:00 +00001220 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001221 name = self.mangle(name)
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001222 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001223 self.emit(prefix + '_NAME', name)
1224
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001225 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001226 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001227 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001228 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001229
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001230class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1231 super_init = CodeGenerator.__init__
1232 scopes = None
1233
1234class NestedClassCodeGenerator(AbstractClassCode,
1235 NestedScopeMixin,
1236 NestedScopeCodeGenerator):
1237 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1238 __super_init = AbstractClassCode.__init__
1239
1240 def __init__(self, klass, filename, scopes):
1241 self.scopes = scopes
1242 self.scope = scopes[klass]
1243 self.__super_init(klass, filename, scopes)
1244 self.graph.setFreeVars(self.scope.get_free_vars())
1245 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001246## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001247
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001248def generateArgList(arglist):
1249 """Generate an arg list marking TupleArgs"""
1250 args = []
1251 extra = []
1252 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001253 for i in range(len(arglist)):
1254 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001255 if type(elt) == types.StringType:
1256 args.append(elt)
1257 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001258 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001259 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001260 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001261 else:
1262 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001263 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001264
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001265def findOp(node):
1266 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1267 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001268 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001269 return v.op
1270
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001271class OpFinder:
1272 def __init__(self):
1273 self.op = None
1274 def visitAssName(self, node):
1275 if self.op is None:
1276 self.op = node.flags
1277 elif self.op != node.flags:
1278 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001279 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001280
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001281class Delegator:
1282 """Base class to support delegation for augmented assignment nodes
1283
1284 To generator code for augmented assignments, we use the following
1285 wrapper classes. In visitAugAssign, the left-hand expression node
1286 is visited twice. The first time the visit uses the normal method
1287 for that node . The second time the visit uses a different method
1288 that generates the appropriate code to perform the assignment.
1289 These delegator classes wrap the original AST nodes in order to
1290 support the variant visit methods.
1291 """
1292 def __init__(self, obj):
1293 self.obj = obj
1294
1295 def __getattr__(self, attr):
1296 return getattr(self.obj, attr)
1297
1298class AugGetattr(Delegator):
1299 pass
1300
1301class AugName(Delegator):
1302 pass
1303
1304class AugSlice(Delegator):
1305 pass
1306
1307class AugSubscript(Delegator):
1308 pass
1309
1310wrapper = {
1311 ast.Getattr: AugGetattr,
1312 ast.Name: AugName,
1313 ast.Slice: AugSlice,
1314 ast.Subscript: AugSubscript,
1315 }
1316
1317def wrap_aug(node):
1318 return wrapper[node.__class__](node)
1319
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001320if __name__ == "__main__":
1321 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001322
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001323 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001324 compile(file)