blob: 3cdf108badd9f9726bcfc657948f438cf113b5f0 [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
Jeremy Hylton37c93512001-09-17 18:03:55 +000011from compiler import ast, parse, walk, syntax
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,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000015 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000016from 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 Hylton1e99a772001-09-14 22:49:08 +000037class BlockStack(misc.Stack):
38 __super_init = misc.Stack.__init__
39
40 def __init__(self):
41 self.__super_init(self)
42 self.loop = None
43
Jeremy Hylton9dca3642001-09-17 21:02:51 +000044def compileFile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000045 f = open(filename)
46 buf = f.read()
47 f.close()
48 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000049 try:
50 mod.compile(display)
51 except SyntaxError, err:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000052 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000053 else:
54 f = open(filename + "c", "wb")
55 mod.dump(f)
56 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000057
Jeremy Hylton9dca3642001-09-17 21:02:51 +000058def compile(source, filename, mode, flags=None, dont_inherit=None):
59 """Replacement for builtin compile() function"""
60 if flags is not None or dont_inherit is not None:
61 raise RuntimeError, "not implemented yet"
62
63 if mode == "single":
64 gen = Interactive(source, filename)
65 elif mode == "exec":
66 gen = Module(source, filename)
67 elif mode == "eval":
68 gen = Expression(source, filename)
69 else:
70 raise ValueError("compile() 3rd arg must be 'exec' or "
71 "'eval' or 'single'")
72 gen.compile()
73 return gen.code
74
75class AbstractCompileMode:
76
77 mode = None # defined by subclass
78
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000079 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000080 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000081 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000082 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000083
Jeremy Hylton9dca3642001-09-17 21:02:51 +000084 def _get_tree(self):
85 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000086 misc.set_filename(self.filename, tree)
87 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000088 return tree
89
90 def compile(self):
91 pass # implemented by subclass
92
93 def getCode(self):
94 return self.code
95
96class Expression(AbstractCompileMode):
97
98 mode = "eval"
99
100 def compile(self):
101 tree = self._get_tree()
102 gen = ExpressionCodeGenerator(tree)
103 self.code = gen.getCode()
104
105class Interactive(AbstractCompileMode):
106
107 mode = "single"
108
109 def compile(self):
110 tree = self._get_tree()
111 gen = InteractiveCodeGenerator(tree)
112 self.code = gen.getCode()
113
114class Module(AbstractCompileMode):
115
116 mode = "exec"
117
118 def compile(self, display=0):
119 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000120 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000121 if display:
122 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000123 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000124 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000125
126 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000127 f.write(self.getPycHeader())
128 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000129
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000130 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000131
132 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000133 # compile.c uses marshal to write a long directly, with
134 # calling the interface that would also generate a 1-byte code
135 # to indicate the type of the value. simplest way to get the
136 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000137 mtime = os.stat(self.filename)[stat.ST_MTIME]
138 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000139 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000140
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000141class LocalNameFinder:
142 """Find local names in scope"""
143 def __init__(self, names=()):
144 self.names = misc.Set()
145 self.globals = misc.Set()
146 for name in names:
147 self.names.add(name)
148
149 # XXX list comprehensions and for loops
150
151 def getLocals(self):
152 for elt in self.globals.elements():
153 if self.names.has_elt(elt):
154 self.names.remove(elt)
155 return self.names
156
157 def visitDict(self, node):
158 pass
159
160 def visitGlobal(self, node):
161 for name in node.names:
162 self.globals.add(name)
163
164 def visitFunction(self, node):
165 self.names.add(node.name)
166
167 def visitLambda(self, node):
168 pass
169
170 def visitImport(self, node):
171 for name, alias in node.names:
172 self.names.add(alias or name)
173
174 def visitFrom(self, node):
175 for name, alias in node.names:
176 self.names.add(alias or name)
177
178 def visitClass(self, node):
179 self.names.add(node.name)
180
181 def visitAssName(self, node):
182 self.names.add(node.name)
183
Jeremy Hylton2afff322001-08-27 21:51:52 +0000184def is_constant_false(node):
185 if isinstance(node, ast.Const):
186 if not node.value:
187 return 1
188 return 0
189
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000190class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000191 """Defines basic code generator for Python bytecode
192
193 This class is an abstract base class. Concrete subclasses must
194 define an __init__() that defines self.graph and then calls the
195 __init__() defined in this class.
196
197 The concrete class must also define the class attributes
198 NameFinder, FunctionGen, and ClassGen. These attributes can be
199 defined in the initClass() method, which is a hook for
200 initializing these methods after all the classes have been
201 defined.
202 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000203
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000204 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000205 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000206 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000207
Jeremy Hylton37c93512001-09-17 18:03:55 +0000208 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000209 if self.__initialized is None:
210 self.initClass()
211 self.__class__.__initialized = 1
212 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000213 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000214 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000215 self.curStack = 0
216 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000217 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000218 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000219 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000220
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000221 # XXX set flags based on future features
222 futures = self.get_module().futures
223 for feature in futures:
224 if feature == "division":
225 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000226 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000227 elif feature == "generators":
228 self.graph.setFlag(CO_GENERATOR_ALLOWED)
229
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000230 def initClass(self):
231 """This method is called once for each class"""
232
233 def checkClass(self):
234 """Verify that class is constructed correctly"""
235 try:
236 assert hasattr(self, 'graph')
237 assert getattr(self, 'NameFinder')
238 assert getattr(self, 'FunctionGen')
239 assert getattr(self, 'ClassGen')
240 except AssertionError, msg:
241 intro = "Bad class construction for %s" % self.__class__.__name__
242 raise AssertionError, intro
243
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000244 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000245 self.emit = self.graph.emit
246 self.newBlock = self.graph.newBlock
247 self.startBlock = self.graph.startBlock
248 self.nextBlock = self.graph.nextBlock
249 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000250
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000251 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000252 """Return a code object"""
253 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000254
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000255 def mangle(self, name):
256 if self.class_name is not None:
257 return misc.mangle(name, self.class_name)
258 else:
259 return name
260
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000261 def parseSymbols(self, tree):
262 s = symbols.SymbolVisitor()
263 walk(tree, s)
264 return s.scopes
265
266 def get_module(self):
267 raise RuntimeError, "should be implemented by subclasses"
268
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000269 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000270
Jeremy Hylton40245602000-02-08 21:15:48 +0000271 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000272 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000273
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000274 def storeName(self, name):
275 self._nameOp('STORE', name)
276
277 def loadName(self, name):
278 self._nameOp('LOAD', name)
279
280 def delName(self, name):
281 self._nameOp('DELETE', name)
282
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000283 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000284 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000285 scope = self.scope.check_name(name)
286 if scope == SC_LOCAL:
287 if not self.optimized:
288 self.emit(prefix + '_NAME', name)
289 else:
290 self.emit(prefix + '_FAST', name)
291 elif scope == SC_GLOBAL:
292 if not self.optimized:
293 self.emit(prefix + '_NAME', name)
294 else:
295 self.emit(prefix + '_GLOBAL', name)
296 elif scope == SC_FREE or scope == SC_CELL:
297 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000298 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000299 raise RuntimeError, "unsupported scope for var %s: %d" % \
300 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000301
Jeremy Hylton13d70942001-04-12 21:04:43 +0000302 def _implicitNameOp(self, prefix, name):
303 """Emit name ops for names generated implicitly by for loops
304
305 The interpreter generates names that start with a period or
306 dollar sign. The symbol table ignores these names because
307 they aren't present in the program text.
308 """
309 if self.optimized:
310 self.emit(prefix + '_FAST', name)
311 else:
312 self.emit(prefix + '_NAME', name)
313
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000314 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000315 """Emit SET_LINENO if node has lineno attribute and it is
316 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000317
318 Returns true if SET_LINENO was emitted.
319
320 There are no rules for when an AST node should have a lineno
321 attribute. The transformer and AST code need to be reviewed
322 and a consistent policy implemented and documented. Until
323 then, this method works around missing line numbers.
324 """
325 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000326 if lineno is not None and (lineno != self.last_lineno
327 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000328 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000329 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000330 return 1
331 return 0
332
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000333 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000334 # code objects. They use class attributes to determine what
335 # specialized code generators to use.
336
337 NameFinder = LocalNameFinder
338 FunctionGen = None
339 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000340
341 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000342 self.scopes = self.parseSymbols(node)
343 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000344 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000345 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000346 self.emit('LOAD_CONST', node.doc)
347 self.storeName('__doc__')
348 lnf = walk(node.node, self.NameFinder(), verbose=0)
349 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000350 self.visit(node.node)
351 self.emit('LOAD_CONST', None)
352 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000353
354 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000355 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000356 if node.doc:
357 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000358 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000359
360 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000361 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000362
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000363 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000364 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000365 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000366 walk(node.code, gen)
367 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000368 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369 for default in node.defaults:
370 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000371 frees = gen.scope.get_free_vars()
372 if frees:
373 for name in frees:
374 self.emit('LOAD_CLOSURE', name)
375 self.emit('LOAD_CONST', gen)
376 self.emit('MAKE_CLOSURE', len(node.defaults))
377 else:
378 self.emit('LOAD_CONST', gen)
379 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000380
381 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000382 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000383 self.get_module())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000384 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000385 self.emit('LOAD_CONST', node.doc)
386 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000387 walk(node.code, gen)
388 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000389 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000390 self.emit('LOAD_CONST', node.name)
391 for base in node.bases:
392 self.visit(base)
393 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000394 frees = gen.scope.get_free_vars()
395 for name in frees:
396 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000397 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000398 if frees:
399 self.emit('MAKE_CLOSURE', 0)
400 else:
401 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000402 self.emit('CALL_FUNCTION', 0)
403 self.emit('BUILD_CLASS')
404 self.storeName(node.name)
405
406 # The rest are standard visitor methods
407
408 # The next few implement control-flow statements
409
410 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000411 end = self.newBlock()
412 numtests = len(node.tests)
413 for i in range(numtests):
414 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000415 if is_constant_false(test):
416 # XXX will need to check generator stuff here
417 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000418 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000419 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000420 nextTest = self.newBlock()
421 self.emit('JUMP_IF_FALSE', nextTest)
422 self.nextBlock()
423 self.emit('POP_TOP')
424 self.visit(suite)
425 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000426 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000427 self.emit('POP_TOP')
428 if node.else_:
429 self.visit(node.else_)
430 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000431
432 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000433 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000434
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000435 loop = self.newBlock()
436 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000437
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000438 after = self.newBlock()
439 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000440
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000441 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000442 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000443
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000444 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000445 self.visit(node.test)
446 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000447
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000448 self.nextBlock()
449 self.emit('POP_TOP')
450 self.visit(node.body)
451 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000452
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000453 self.startBlock(else_) # or just the POPs if not else clause
454 self.emit('POP_TOP')
455 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000456 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000457 if node.else_:
458 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000459 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000460
461 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000462 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000463 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000464 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000465 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000466
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000467 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000468 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000469 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000470 self.emit('GET_ITER')
471
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000472 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000473 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000474 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000475 self.visit(node.assign)
476 self.visit(node.body)
477 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000478 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000480 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000481 if node.else_:
482 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000483 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000484
485 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000486 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000487 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000488 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000489 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000490 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000491
492 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000493 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000494 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000495 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000496 kind, block = self.setups.top()
497 if kind == LOOP:
498 self.set_lineno(node)
499 self.emit('JUMP_ABSOLUTE', block)
500 self.nextBlock()
501 elif kind == EXCEPT or kind == TRY_FINALLY:
502 self.set_lineno(node)
503 # find the block that starts the loop
504 top = len(self.setups)
505 while top > 0:
506 top = top - 1
507 kind, loop_block = self.setups[top]
508 if kind == LOOP:
509 break
510 if kind != LOOP:
511 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000512 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000513 self.emit('CONTINUE_LOOP', loop_block)
514 self.nextBlock()
515 elif kind == END_FINALLY:
516 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000517 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000518
519 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000520 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000521 for child in node.nodes[:-1]:
522 self.visit(child)
523 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000524 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000525 self.emit('POP_TOP')
526 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000527 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000528
529 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000530 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000531
532 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000533 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000534
535 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000536 self.visit(node.expr)
537 cleanup = self.newBlock()
538 for op, code in node.ops[:-1]:
539 self.visit(code)
540 self.emit('DUP_TOP')
541 self.emit('ROT_THREE')
542 self.emit('COMPARE_OP', op)
543 self.emit('JUMP_IF_FALSE', cleanup)
544 self.nextBlock()
545 self.emit('POP_TOP')
546 # now do the last comparison
547 if node.ops:
548 op, code = node.ops[-1]
549 self.visit(code)
550 self.emit('COMPARE_OP', op)
551 if len(node.ops) > 1:
552 end = self.newBlock()
553 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000554 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000555 self.emit('ROT_TWO')
556 self.emit('POP_TOP')
557 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000558
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000559 # list comprehensions
560 __list_count = 0
561
562 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000563 self.set_lineno(node)
564 # setup list
565 append = "$append%d" % self.__list_count
566 self.__list_count = self.__list_count + 1
567 self.emit('BUILD_LIST', 0)
568 self.emit('DUP_TOP')
569 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000570 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000571
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000572 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000573 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000574 start, anchor = self.visit(for_)
575 cont = None
576 for if_ in for_.ifs:
577 if cont is None:
578 cont = self.newBlock()
579 self.visit(if_, cont)
580 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000581
Jeremy Hylton13d70942001-04-12 21:04:43 +0000582 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000583 self.visit(node.expr)
584 self.emit('CALL_FUNCTION', 1)
585 self.emit('POP_TOP')
586
587 for start, cont, anchor in stack:
588 if cont:
589 skip_one = self.newBlock()
590 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000591 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000592 self.emit('POP_TOP')
593 self.nextBlock(skip_one)
594 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000595 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000596 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000597
598 self.__list_count = self.__list_count - 1
599
600 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000601 start = self.newBlock()
602 anchor = self.newBlock()
603
604 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000605 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000606 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000607 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000608 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000609 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000610 self.visit(node.assign)
611 return start, anchor
612
613 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000614 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000615 self.visit(node.test)
616 self.emit('JUMP_IF_FALSE', branch)
617 self.newBlock()
618 self.emit('POP_TOP')
619
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000620 # exception related
621
622 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000623 # XXX would be interesting to implement this via a
624 # transformation of the AST before this stage
625 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000626 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000627 # XXX __debug__ and AssertionError appear to be special cases
628 # -- they are always loaded as globals even if there are local
629 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000630 self.emit('LOAD_GLOBAL', '__debug__')
631 self.emit('JUMP_IF_FALSE', end)
632 self.nextBlock()
633 self.emit('POP_TOP')
634 self.visit(node.test)
635 self.emit('JUMP_IF_TRUE', end)
636 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000637 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000638 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000639 if node.fail:
640 self.visit(node.fail)
641 self.emit('RAISE_VARARGS', 2)
642 else:
643 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000644 self.nextBlock(end)
645 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000646
647 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000648 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000649 n = 0
650 if node.expr1:
651 self.visit(node.expr1)
652 n = n + 1
653 if node.expr2:
654 self.visit(node.expr2)
655 n = n + 1
656 if node.expr3:
657 self.visit(node.expr3)
658 n = n + 1
659 self.emit('RAISE_VARARGS', n)
660
661 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000662 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000663 handlers = self.newBlock()
664 end = self.newBlock()
665 if node.else_:
666 lElse = self.newBlock()
667 else:
668 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000669 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000670 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000671 self.nextBlock(body)
672 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000673 self.visit(node.body)
674 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000675 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000676 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000677 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000678
679 last = len(node.handlers) - 1
680 for i in range(len(node.handlers)):
681 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000682 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000683 if expr:
684 self.emit('DUP_TOP')
685 self.visit(expr)
686 self.emit('COMPARE_OP', 'exception match')
687 next = self.newBlock()
688 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000689 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000690 self.emit('POP_TOP')
691 self.emit('POP_TOP')
692 if target:
693 self.visit(target)
694 else:
695 self.emit('POP_TOP')
696 self.emit('POP_TOP')
697 self.visit(body)
698 self.emit('JUMP_FORWARD', end)
699 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000700 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000701 else:
702 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000703 if expr: # XXX
704 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000705 self.emit('END_FINALLY')
706 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000707 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000708 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000709 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000710
711 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000712 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000713 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000714 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000715 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000716 self.nextBlock(body)
717 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000718 self.visit(node.body)
719 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000720 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000722 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000723 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724 self.visit(node.final)
725 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000726 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000727
728 # misc
729
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000730 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000731 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000732 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000733 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000734
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000735 def visitConst(self, node):
736 self.emit('LOAD_CONST', node.value)
737
738 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000739 self.emit('LOAD_CONST', node.name)
740 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000741
742 def visitGlobal(self, node):
743 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000744 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000745
746 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000747 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000748 self.loadName(node.name)
749
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000750 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000751 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000752
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000753 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000754 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000755 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000756 if VERSION > 1:
757 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000758 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000759 mod = string.split(name, ".")[0]
760 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000761
762 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000763 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000764 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000765 if VERSION > 1:
766 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000767 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000768 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000769 if VERSION > 1:
770 if name == '*':
771 self.namespace = 0
772 self.emit('IMPORT_STAR')
773 # There can only be one name w/ from ... import *
774 assert len(node.names) == 1
775 return
776 else:
777 self.emit('IMPORT_FROM', name)
778 self._resolveDots(name)
779 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000780 else:
781 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000782 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000783
Jeremy Hylton20516082000-09-01 20:33:26 +0000784 def _resolveDots(self, name):
785 elts = string.split(name, ".")
786 if len(elts) == 1:
787 return
788 for elt in elts[1:]:
789 self.emit('LOAD_ATTR', elt)
790
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000791 def visitGetattr(self, node):
792 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000793 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000794
795 # next five implement assignments
796
797 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000798 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000799 self.visit(node.expr)
800 dups = len(node.nodes) - 1
801 for i in range(len(node.nodes)):
802 elt = node.nodes[i]
803 if i < dups:
804 self.emit('DUP_TOP')
805 if isinstance(elt, ast.Node):
806 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000807
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000808 def visitAssName(self, node):
809 if node.flags == 'OP_ASSIGN':
810 self.storeName(node.name)
811 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000812 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000813 self.delName(node.name)
814 else:
815 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000816
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000817 def visitAssAttr(self, node):
818 self.visit(node.expr)
819 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000820 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000821 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000822 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000823 else:
824 print "warning: unexpected flags:", node.flags
825 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000826
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000827 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000828 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000829 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000830 for child in node.nodes:
831 self.visit(child)
832
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000833 if VERSION > 1:
834 visitAssTuple = _visitAssSequence
835 visitAssList = _visitAssSequence
836 else:
837 def visitAssTuple(self, node):
838 self._visitAssSequence(node, 'UNPACK_TUPLE')
839
840 def visitAssList(self, node):
841 self._visitAssSequence(node, 'UNPACK_LIST')
842
843 # augmented assignment
844
845 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000846 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000847 aug_node = wrap_aug(node.node)
848 self.visit(aug_node, "load")
849 self.visit(node.expr)
850 self.emit(self._augmented_opcode[node.op])
851 self.visit(aug_node, "store")
852
853 _augmented_opcode = {
854 '+=' : 'INPLACE_ADD',
855 '-=' : 'INPLACE_SUBTRACT',
856 '*=' : 'INPLACE_MULTIPLY',
857 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000858 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000859 '%=' : 'INPLACE_MODULO',
860 '**=': 'INPLACE_POWER',
861 '>>=': 'INPLACE_RSHIFT',
862 '<<=': 'INPLACE_LSHIFT',
863 '&=' : 'INPLACE_AND',
864 '^=' : 'INPLACE_XOR',
865 '|=' : 'INPLACE_OR',
866 }
867
868 def visitAugName(self, node, mode):
869 if mode == "load":
870 self.loadName(node.name)
871 elif mode == "store":
872 self.storeName(node.name)
873
874 def visitAugGetattr(self, node, mode):
875 if mode == "load":
876 self.visit(node.expr)
877 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000878 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000879 elif mode == "store":
880 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000881 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000882
883 def visitAugSlice(self, node, mode):
884 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000885 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000886 elif mode == "store":
887 slice = 0
888 if node.lower:
889 slice = slice | 1
890 if node.upper:
891 slice = slice | 2
892 if slice == 0:
893 self.emit('ROT_TWO')
894 elif slice == 3:
895 self.emit('ROT_FOUR')
896 else:
897 self.emit('ROT_THREE')
898 self.emit('STORE_SLICE+%d' % slice)
899
900 def visitAugSubscript(self, node, mode):
901 if len(node.subs) > 1:
902 raise SyntaxError, "augmented assignment to tuple is not possible"
903 if mode == "load":
904 self.visitSubscript(node, 1)
905 elif mode == "store":
906 self.emit('ROT_THREE')
907 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000908
909 def visitExec(self, node):
910 self.visit(node.expr)
911 if node.locals is None:
912 self.emit('LOAD_CONST', None)
913 else:
914 self.visit(node.locals)
915 if node.globals is None:
916 self.emit('DUP_TOP')
917 else:
918 self.visit(node.globals)
919 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000920
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000921 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000922 pos = 0
923 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000924 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000925 self.visit(node.node)
926 for arg in node.args:
927 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000928 if isinstance(arg, ast.Keyword):
929 kw = kw + 1
930 else:
931 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000932 if node.star_args is not None:
933 self.visit(node.star_args)
934 if node.dstar_args is not None:
935 self.visit(node.dstar_args)
936 have_star = node.star_args is not None
937 have_dstar = node.dstar_args is not None
938 opcode = callfunc_opcode_info[have_star, have_dstar]
939 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000940
Jeremy Hylton2afff322001-08-27 21:51:52 +0000941 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000942 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000943 if node.dest:
944 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000945 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000946 if node.dest:
947 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000948 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000949 if node.dest:
950 self.emit('ROT_TWO')
951 self.emit('PRINT_ITEM_TO')
952 else:
953 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000954 if node.dest and not newline:
955 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000956
957 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000958 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000959 if node.dest:
960 self.emit('PRINT_NEWLINE_TO')
961 else:
962 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000963
964 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000965 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000966 self.visit(node.value)
967 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000968
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000969 def visitYield(self, node):
970 self.set_lineno(node)
971 self.visit(node.value)
972 self.emit('YIELD_STMT')
973
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000974 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000975
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000976 def visitSlice(self, node, aug_flag=None):
977 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000978 self.visit(node.expr)
979 slice = 0
980 if node.lower:
981 self.visit(node.lower)
982 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000983 if node.upper:
984 self.visit(node.upper)
985 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000986 if aug_flag:
987 if slice == 0:
988 self.emit('DUP_TOP')
989 elif slice == 3:
990 self.emit('DUP_TOPX', 3)
991 else:
992 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000993 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000994 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000995 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000996 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000997 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000998 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000999 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001000 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001001 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001002
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001003 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001004 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001005 for sub in node.subs:
1006 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001007 if aug_flag:
1008 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001009 if len(node.subs) > 1:
1010 self.emit('BUILD_TUPLE', len(node.subs))
1011 if node.flags == 'OP_APPLY':
1012 self.emit('BINARY_SUBSCR')
1013 elif node.flags == 'OP_ASSIGN':
1014 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001015 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001016 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001017
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001018 # binary ops
1019
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001020 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001021 self.visit(node.left)
1022 self.visit(node.right)
1023 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001024
1025 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001026 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001027
1028 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001029 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001030
1031 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001032 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001033
1034 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001035 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001036
Jeremy Hylton94afe322001-08-29 18:14:39 +00001037 def visitFloorDiv(self, node):
1038 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1039
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001040 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001041 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001042
Jeremy Hylton126960b2000-02-14 21:33:10 +00001043 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001044 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001045
1046 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001047 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001048
1049 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001050 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001051
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001052 # unary ops
1053
1054 def unaryOp(self, node, op):
1055 self.visit(node.expr)
1056 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001057
Jeremy Hylton126960b2000-02-14 21:33:10 +00001058 def visitInvert(self, node):
1059 return self.unaryOp(node, 'UNARY_INVERT')
1060
Jeremy Hylton40245602000-02-08 21:15:48 +00001061 def visitUnarySub(self, node):
1062 return self.unaryOp(node, 'UNARY_NEGATIVE')
1063
1064 def visitUnaryAdd(self, node):
1065 return self.unaryOp(node, 'UNARY_POSITIVE')
1066
1067 def visitUnaryInvert(self, node):
1068 return self.unaryOp(node, 'UNARY_INVERT')
1069
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001070 def visitNot(self, node):
1071 return self.unaryOp(node, 'UNARY_NOT')
1072
Jeremy Hylton40245602000-02-08 21:15:48 +00001073 def visitBackquote(self, node):
1074 return self.unaryOp(node, 'UNARY_CONVERT')
1075
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001076 # bit ops
1077
Jeremy Hyltona5058122000-02-14 14:14:29 +00001078 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001079 self.visit(nodes[0])
1080 for node in nodes[1:]:
1081 self.visit(node)
1082 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001083
1084 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001085 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001086
1087 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001088 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001089
1090 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001091 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001092
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001093 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001094
Jeremy Hyltona5058122000-02-14 14:14:29 +00001095 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001096 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001097
Jeremy Hylton40245602000-02-08 21:15:48 +00001098 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001099 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001100 for elt in node.nodes:
1101 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001102 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001103
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001104 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001105 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001106 for elt in node.nodes:
1107 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001108 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001109
1110 def visitSliceobj(self, node):
1111 for child in node.nodes:
1112 self.visit(child)
1113 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001114
Jeremy Hyltona5058122000-02-14 14:14:29 +00001115 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001116 lineno = getattr(node, 'lineno', None)
1117 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001118 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001119 self.emit('BUILD_MAP', 0)
1120 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001121 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001122 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001123 self.emit('SET_LINENO', lineno2)
1124 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001125 self.emit('DUP_TOP')
1126 self.visit(v)
1127 self.emit('ROT_TWO')
1128 self.visit(k)
1129 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001130
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001131class NestedScopeMixin:
1132 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001133 def initClass(self):
1134 self.__class__.NameFinder = LocalNameFinder
1135 self.__class__.FunctionGen = FunctionCodeGenerator
1136 self.__class__.ClassGen = ClassCodeGenerator
1137
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001138class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001139 __super_init = CodeGenerator.__init__
1140
1141 scopes = None
1142
Jeremy Hylton37c93512001-09-17 18:03:55 +00001143 def __init__(self, tree):
1144 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001145 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001146 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001147 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001148
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001149 def get_module(self):
1150 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001151
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001152class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1153 __super_init = CodeGenerator.__init__
1154
1155 scopes = None
1156 futures = ()
1157
1158 def __init__(self, tree):
1159 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1160 self.__super_init()
1161 self.set_lineno(tree)
1162 walk(tree, self)
1163 self.emit('RETURN_VALUE')
1164
1165 def get_module(self):
1166 return self
1167
1168class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1169
1170 __super_init = CodeGenerator.__init__
1171
1172 scopes = None
1173 futures = ()
1174
1175 def __init__(self, tree):
1176 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1177 self.__super_init()
1178 self.set_lineno(tree)
1179 walk(tree, self)
1180 self.emit('RETURN_VALUE')
1181
1182 def get_module(self):
1183 return self
1184 def visitDiscard(self, node):
1185 # XXX Discard means it's an expression. Perhaps this is a bad
1186 # name.
1187 self.visit(node.expr)
1188 self.emit('PRINT_EXPR')
1189
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001190class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001191 optimized = 1
1192 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001193
Jeremy Hylton37c93512001-09-17 18:03:55 +00001194 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001195 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001196 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001197 if isLambda:
1198 klass = FunctionCodeGenerator
1199 name = "<lambda.%d>" % klass.lambdaCount
1200 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001201 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001202 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001203 args, hasTupleArg = generateArgList(func.argnames)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001204 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001205 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001206 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001207 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001208
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001209 if not isLambda and func.doc:
1210 self.setDocstring(func.doc)
1211
Jeremy Hylton2afff322001-08-27 21:51:52 +00001212 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001213 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001214 if func.varargs:
1215 self.graph.setFlag(CO_VARARGS)
1216 if func.kwargs:
1217 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001218 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001219 if hasTupleArg:
1220 self.generateArgUnpack(func.argnames)
1221
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001222 def get_module(self):
1223 return self.module
1224
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001225 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001226 self.graph.startExitBlock()
1227 if not self.isLambda:
1228 self.emit('LOAD_CONST', None)
1229 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001230
1231 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001232 for i in range(len(args)):
1233 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001234 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001235 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001236 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001237
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001238 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001239 if VERSION > 1:
1240 self.emit('UNPACK_SEQUENCE', len(tup))
1241 else:
1242 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001243 for elt in tup:
1244 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001245 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001246 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001247 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001248
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001249 unpackTuple = unpackSequence
1250
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001251class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001252 CodeGenerator):
1253 super_init = CodeGenerator.__init__ # call be other init
1254 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001255
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001256 __super_init = AbstractFunctionCode.__init__
1257
Jeremy Hylton37c93512001-09-17 18:03:55 +00001258 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001259 self.scopes = scopes
1260 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001261 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001262 self.graph.setFreeVars(self.scope.get_free_vars())
1263 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001264 if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
1265 if self.scope.generator is not None:
1266 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001267
1268class AbstractClassCode:
1269
Jeremy Hylton37c93512001-09-17 18:03:55 +00001270 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001271 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001272 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001273 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001274 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001275 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001276 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001277 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001278 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001279 if klass.doc:
1280 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001281
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001282 def get_module(self):
1283 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001284
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001285 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001286 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001287 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001288 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001289
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001290class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001291 super_init = CodeGenerator.__init__
1292 scopes = None
1293
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001294 __super_init = AbstractClassCode.__init__
1295
Jeremy Hylton37c93512001-09-17 18:03:55 +00001296 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001297 self.scopes = scopes
1298 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001299 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001300 self.graph.setFreeVars(self.scope.get_free_vars())
1301 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001302## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001303
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001304def generateArgList(arglist):
1305 """Generate an arg list marking TupleArgs"""
1306 args = []
1307 extra = []
1308 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001309 for i in range(len(arglist)):
1310 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001311 if type(elt) == types.StringType:
1312 args.append(elt)
1313 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001314 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001315 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001316 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001317 else:
1318 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001319 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001320
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001321def findOp(node):
1322 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1323 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001324 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001325 return v.op
1326
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001327class OpFinder:
1328 def __init__(self):
1329 self.op = None
1330 def visitAssName(self, node):
1331 if self.op is None:
1332 self.op = node.flags
1333 elif self.op != node.flags:
1334 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001335 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001336
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001337class Delegator:
1338 """Base class to support delegation for augmented assignment nodes
1339
1340 To generator code for augmented assignments, we use the following
1341 wrapper classes. In visitAugAssign, the left-hand expression node
1342 is visited twice. The first time the visit uses the normal method
1343 for that node . The second time the visit uses a different method
1344 that generates the appropriate code to perform the assignment.
1345 These delegator classes wrap the original AST nodes in order to
1346 support the variant visit methods.
1347 """
1348 def __init__(self, obj):
1349 self.obj = obj
1350
1351 def __getattr__(self, attr):
1352 return getattr(self.obj, attr)
1353
1354class AugGetattr(Delegator):
1355 pass
1356
1357class AugName(Delegator):
1358 pass
1359
1360class AugSlice(Delegator):
1361 pass
1362
1363class AugSubscript(Delegator):
1364 pass
1365
1366wrapper = {
1367 ast.Getattr: AugGetattr,
1368 ast.Name: AugName,
1369 ast.Slice: AugSlice,
1370 ast.Subscript: AugSubscript,
1371 }
1372
1373def wrap_aug(node):
1374 return wrapper[node.__class__](node)
1375
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001376if __name__ == "__main__":
1377 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001378
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001379 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001380 compile(file)