blob: 4d5f728811266491cc21be6825c0d1a63ebf51ef [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 struct
Jeremy Hylton9c048f92000-10-13 21:58:13 +00005import sys
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00006import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00007from cStringIO import StringIO
8
Jeremy Hylton37c93512001-09-17 18:03:55 +00009from compiler import ast, parse, walk, syntax
Jeremy Hylton364f9b92001-04-12 06:40:42 +000010from compiler import pyassem, misc, future, symbols
11from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
Jeremy Hylton71ebc332001-08-30 20:25:55 +000012from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000013 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000015
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000016# XXX The version-specific code can go, since this code only works with 2.x.
Jeremy Hylton9c048f92000-10-13 21:58:13 +000017# Do we have Python 1.x or Python 2.x?
18try:
19 VERSION = sys.version_info[0]
20except AttributeError:
21 VERSION = 1
22
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000023callfunc_opcode_info = {
24 # (Have *args, Have **args) : opcode
25 (0,0) : "CALL_FUNCTION",
26 (1,0) : "CALL_FUNCTION_VAR",
27 (0,1) : "CALL_FUNCTION_KW",
28 (1,1) : "CALL_FUNCTION_VAR_KW",
29}
30
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000031LOOP = 1
32EXCEPT = 2
33TRY_FINALLY = 3
34END_FINALLY = 4
35
Jeremy Hylton9dca3642001-09-17 21:02:51 +000036def compileFile(filename, display=0):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000037 f = open(filename, 'U')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000038 buf = f.read()
39 f.close()
40 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000041 try:
42 mod.compile(display)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000043 except SyntaxError:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000044 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000045 else:
46 f = open(filename + "c", "wb")
47 mod.dump(f)
48 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000049
Jeremy Hylton9dca3642001-09-17 21:02:51 +000050def compile(source, filename, mode, flags=None, dont_inherit=None):
51 """Replacement for builtin compile() function"""
52 if flags is not None or dont_inherit is not None:
53 raise RuntimeError, "not implemented yet"
Tim Peterse0c446b2001-10-18 21:57:37 +000054
Jeremy Hylton9dca3642001-09-17 21:02:51 +000055 if mode == "single":
56 gen = Interactive(source, filename)
57 elif mode == "exec":
58 gen = Module(source, filename)
59 elif mode == "eval":
60 gen = Expression(source, filename)
61 else:
62 raise ValueError("compile() 3rd arg must be 'exec' or "
63 "'eval' or 'single'")
64 gen.compile()
65 return gen.code
66
67class AbstractCompileMode:
68
69 mode = None # defined by subclass
70
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000071 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000072 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000073 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000074 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000075
Jeremy Hylton9dca3642001-09-17 21:02:51 +000076 def _get_tree(self):
77 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000078 misc.set_filename(self.filename, tree)
79 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000080 return tree
81
82 def compile(self):
83 pass # implemented by subclass
84
85 def getCode(self):
86 return self.code
87
88class Expression(AbstractCompileMode):
89
90 mode = "eval"
91
92 def compile(self):
93 tree = self._get_tree()
94 gen = ExpressionCodeGenerator(tree)
95 self.code = gen.getCode()
96
97class Interactive(AbstractCompileMode):
98
99 mode = "single"
100
101 def compile(self):
102 tree = self._get_tree()
103 gen = InteractiveCodeGenerator(tree)
104 self.code = gen.getCode()
105
106class Module(AbstractCompileMode):
107
108 mode = "exec"
109
110 def compile(self, display=0):
111 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000112 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000113 if display:
114 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000115 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000116 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000117
118 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000119 f.write(self.getPycHeader())
120 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000121
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000122 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000123
124 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000125 # compile.c uses marshal to write a long directly, with
126 # calling the interface that would also generate a 1-byte code
127 # to indicate the type of the value. simplest way to get the
128 # same effect is to call marshal and then skip the code.
Neal Norwitza312c3a2002-06-06 18:30:10 +0000129 mtime = os.path.getmtime(self.filename)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000130 mtime = struct.pack('<i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000131 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000132
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000133class LocalNameFinder:
134 """Find local names in scope"""
135 def __init__(self, names=()):
136 self.names = misc.Set()
137 self.globals = misc.Set()
138 for name in names:
139 self.names.add(name)
140
141 # XXX list comprehensions and for loops
142
143 def getLocals(self):
144 for elt in self.globals.elements():
145 if self.names.has_elt(elt):
146 self.names.remove(elt)
147 return self.names
148
149 def visitDict(self, node):
150 pass
151
152 def visitGlobal(self, node):
153 for name in node.names:
154 self.globals.add(name)
155
156 def visitFunction(self, node):
157 self.names.add(node.name)
158
159 def visitLambda(self, node):
160 pass
161
162 def visitImport(self, node):
163 for name, alias in node.names:
164 self.names.add(alias or name)
165
166 def visitFrom(self, node):
167 for name, alias in node.names:
168 self.names.add(alias or name)
169
170 def visitClass(self, node):
171 self.names.add(node.name)
172
173 def visitAssName(self, node):
174 self.names.add(node.name)
175
Jeremy Hylton2afff322001-08-27 21:51:52 +0000176def is_constant_false(node):
177 if isinstance(node, ast.Const):
178 if not node.value:
179 return 1
180 return 0
181
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000182class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000183 """Defines basic code generator for Python bytecode
184
185 This class is an abstract base class. Concrete subclasses must
186 define an __init__() that defines self.graph and then calls the
187 __init__() defined in this class.
188
189 The concrete class must also define the class attributes
190 NameFinder, FunctionGen, and ClassGen. These attributes can be
191 defined in the initClass() method, which is a hook for
192 initializing these methods after all the classes have been
Tim Peterse0c446b2001-10-18 21:57:37 +0000193 defined.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000194 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000195
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000196 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000197 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000198 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000199
Jeremy Hylton37c93512001-09-17 18:03:55 +0000200 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000201 if self.__initialized is None:
202 self.initClass()
203 self.__class__.__initialized = 1
204 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000205 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000206 self.setups = misc.Stack()
Jeremy Hylton92f39722000-09-01 20:47:37 +0000207 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000208 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000209 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000210
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000211 # XXX set flags based on future features
212 futures = self.get_module().futures
213 for feature in futures:
214 if feature == "division":
215 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000216 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000217 elif feature == "generators":
218 self.graph.setFlag(CO_GENERATOR_ALLOWED)
219
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000220 def initClass(self):
221 """This method is called once for each class"""
222
223 def checkClass(self):
224 """Verify that class is constructed correctly"""
225 try:
226 assert hasattr(self, 'graph')
227 assert getattr(self, 'NameFinder')
228 assert getattr(self, 'FunctionGen')
229 assert getattr(self, 'ClassGen')
230 except AssertionError, msg:
231 intro = "Bad class construction for %s" % self.__class__.__name__
232 raise AssertionError, intro
233
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000234 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000235 self.emit = self.graph.emit
236 self.newBlock = self.graph.newBlock
237 self.startBlock = self.graph.startBlock
238 self.nextBlock = self.graph.nextBlock
239 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000240
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000241 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000242 """Return a code object"""
243 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000244
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000245 def mangle(self, name):
246 if self.class_name is not None:
247 return misc.mangle(name, self.class_name)
248 else:
249 return name
250
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000251 def parseSymbols(self, tree):
252 s = symbols.SymbolVisitor()
253 walk(tree, s)
254 return s.scopes
255
256 def get_module(self):
257 raise RuntimeError, "should be implemented by subclasses"
258
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000259 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000260
Jeremy Hylton40245602000-02-08 21:15:48 +0000261 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000262 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000263
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000264 def storeName(self, name):
265 self._nameOp('STORE', name)
266
267 def loadName(self, name):
268 self._nameOp('LOAD', name)
269
270 def delName(self, name):
271 self._nameOp('DELETE', name)
272
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000273 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000274 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000275 scope = self.scope.check_name(name)
276 if scope == SC_LOCAL:
277 if not self.optimized:
278 self.emit(prefix + '_NAME', name)
279 else:
280 self.emit(prefix + '_FAST', name)
281 elif scope == SC_GLOBAL:
282 if not self.optimized:
283 self.emit(prefix + '_NAME', name)
284 else:
285 self.emit(prefix + '_GLOBAL', name)
286 elif scope == SC_FREE or scope == SC_CELL:
287 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000288 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000289 raise RuntimeError, "unsupported scope for var %s: %d" % \
290 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000291
Jeremy Hylton13d70942001-04-12 21:04:43 +0000292 def _implicitNameOp(self, prefix, name):
293 """Emit name ops for names generated implicitly by for loops
294
295 The interpreter generates names that start with a period or
296 dollar sign. The symbol table ignores these names because
297 they aren't present in the program text.
298 """
299 if self.optimized:
300 self.emit(prefix + '_FAST', name)
301 else:
302 self.emit(prefix + '_NAME', name)
303
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000304 # The set_lineno() function and the explicit emit() calls for
305 # SET_LINENO below are only used to generate the line number table.
306 # As of Python 2.3, the interpreter does not have a SET_LINENO
307 # instruction. pyassem treats SET_LINENO opcodes as a special case.
308
309 def set_lineno(self, node, force=False):
310 """Emit SET_LINENO if necessary.
311
312 The instruction is considered necessary if the node has a
313 lineno attribute and it is different than the last lineno
314 emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000315
316 Returns true if SET_LINENO was emitted.
317
318 There are no rules for when an AST node should have a lineno
319 attribute. The transformer and AST code need to be reviewed
320 and a consistent policy implemented and documented. Until
321 then, this method works around missing line numbers.
322 """
323 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000324 if lineno is not None and (lineno != self.last_lineno
325 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000326 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000327 self.last_lineno = lineno
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000328 return True
329 return False
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000330
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000331 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000332 # code objects. They use class attributes to determine what
333 # specialized code generators to use.
334
335 NameFinder = LocalNameFinder
336 FunctionGen = None
337 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000338
339 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000340 self.scopes = self.parseSymbols(node)
341 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000342 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000343 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000344 self.emit('LOAD_CONST', node.doc)
345 self.storeName('__doc__')
346 lnf = walk(node.node, self.NameFinder(), verbose=0)
347 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000348 self.visit(node.node)
349 self.emit('LOAD_CONST', None)
350 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000351
Barry Warsaw52acb492001-12-21 20:04:22 +0000352 def visitExpression(self, node):
353 self.set_lineno(node)
354 self.scopes = self.parseSymbols(node)
355 self.scope = self.scopes[node]
356 self.visit(node.node)
357 self.emit('RETURN_VALUE')
358
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000359 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000360 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000361 if node.doc:
362 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000363 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000364
365 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000366 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000367
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000368 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000369 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000370 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000371 walk(node.code, gen)
372 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000373 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000374 for default in node.defaults:
375 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000376 frees = gen.scope.get_free_vars()
377 if frees:
378 for name in frees:
379 self.emit('LOAD_CLOSURE', name)
380 self.emit('LOAD_CONST', gen)
381 self.emit('MAKE_CLOSURE', len(node.defaults))
382 else:
383 self.emit('LOAD_CONST', gen)
384 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000385
386 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000387 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000388 self.get_module())
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000389 walk(node.code, gen)
390 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000391 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000392 self.emit('LOAD_CONST', node.name)
393 for base in node.bases:
394 self.visit(base)
395 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000396 frees = gen.scope.get_free_vars()
397 for name in frees:
398 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000399 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000400 if frees:
401 self.emit('MAKE_CLOSURE', 0)
402 else:
403 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000404 self.emit('CALL_FUNCTION', 0)
405 self.emit('BUILD_CLASS')
406 self.storeName(node.name)
407
408 # The rest are standard visitor methods
409
410 # The next few implement control-flow statements
411
412 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000413 end = self.newBlock()
414 numtests = len(node.tests)
415 for i in range(numtests):
416 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000417 if is_constant_false(test):
418 # XXX will need to check generator stuff here
419 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000420 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000421 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000422 nextTest = self.newBlock()
423 self.emit('JUMP_IF_FALSE', nextTest)
424 self.nextBlock()
425 self.emit('POP_TOP')
426 self.visit(suite)
427 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000428 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000429 self.emit('POP_TOP')
430 if node.else_:
431 self.visit(node.else_)
432 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000433
434 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000435 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000436
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000437 loop = self.newBlock()
438 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000439
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000440 after = self.newBlock()
441 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000442
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000443 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000444 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000445
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000446 self.set_lineno(node, force=True)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000447 self.visit(node.test)
448 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000449
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000450 self.nextBlock()
451 self.emit('POP_TOP')
452 self.visit(node.body)
453 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000454
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000455 self.startBlock(else_) # or just the POPs if not else clause
456 self.emit('POP_TOP')
457 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000458 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000459 if node.else_:
460 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000461 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000462
463 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000464 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000465 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000466 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000467 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000468
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000469 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000470 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000471 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000472 self.emit('GET_ITER')
473
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000474 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000475 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000476 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000477 self.visit(node.assign)
478 self.visit(node.body)
479 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000480 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000481 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000482 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 if node.else_:
484 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000485 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000486
487 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000488 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000489 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000490 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000491 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000492 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000493
494 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000495 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000496 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000497 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000498 kind, block = self.setups.top()
499 if kind == LOOP:
500 self.set_lineno(node)
501 self.emit('JUMP_ABSOLUTE', block)
502 self.nextBlock()
503 elif kind == EXCEPT or kind == TRY_FINALLY:
504 self.set_lineno(node)
505 # find the block that starts the loop
506 top = len(self.setups)
507 while top > 0:
508 top = top - 1
509 kind, loop_block = self.setups[top]
510 if kind == LOOP:
511 break
512 if kind != LOOP:
513 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000514 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000515 self.emit('CONTINUE_LOOP', loop_block)
516 self.nextBlock()
517 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000518 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000519 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000520
521 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000522 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000523 for child in node.nodes[:-1]:
524 self.visit(child)
525 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000526 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000527 self.emit('POP_TOP')
528 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000529 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000530
531 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000532 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000533
534 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000535 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000536
537 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000538 self.visit(node.expr)
539 cleanup = self.newBlock()
540 for op, code in node.ops[:-1]:
541 self.visit(code)
542 self.emit('DUP_TOP')
543 self.emit('ROT_THREE')
544 self.emit('COMPARE_OP', op)
545 self.emit('JUMP_IF_FALSE', cleanup)
546 self.nextBlock()
547 self.emit('POP_TOP')
548 # now do the last comparison
549 if node.ops:
550 op, code = node.ops[-1]
551 self.visit(code)
552 self.emit('COMPARE_OP', op)
553 if len(node.ops) > 1:
554 end = self.newBlock()
555 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000556 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000557 self.emit('ROT_TWO')
558 self.emit('POP_TOP')
559 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000560
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000561 # list comprehensions
562 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000563
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000564 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000565 self.set_lineno(node)
566 # setup list
567 append = "$append%d" % self.__list_count
568 self.__list_count = self.__list_count + 1
569 self.emit('BUILD_LIST', 0)
570 self.emit('DUP_TOP')
571 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000572 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000573
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000574 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000575 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000576 start, anchor = self.visit(for_)
577 cont = None
578 for if_ in for_.ifs:
579 if cont is None:
580 cont = self.newBlock()
581 self.visit(if_, cont)
582 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000583
Jeremy Hylton13d70942001-04-12 21:04:43 +0000584 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000585 self.visit(node.expr)
586 self.emit('CALL_FUNCTION', 1)
587 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000588
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000589 for start, cont, anchor in stack:
590 if cont:
591 skip_one = self.newBlock()
592 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000593 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000594 self.emit('POP_TOP')
595 self.nextBlock(skip_one)
596 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000597 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000598 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000599
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000600 self.__list_count = self.__list_count - 1
601
602 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000603 start = self.newBlock()
604 anchor = self.newBlock()
605
606 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000607 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000608 self.nextBlock(start)
Jeremy Hylton18565412002-12-31 18:26:17 +0000609 self.set_lineno(node, force=True)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000610 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000611 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000612 self.visit(node.assign)
613 return start, anchor
614
615 def visitListCompIf(self, node, branch):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000616 self.set_lineno(node, force=True)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000617 self.visit(node.test)
618 self.emit('JUMP_IF_FALSE', branch)
619 self.newBlock()
620 self.emit('POP_TOP')
621
Raymond Hettinger354433a2004-05-19 08:20:33 +0000622 def visitGenExpr(self, node):
623 gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
624 self.get_module())
625 walk(node.code, gen)
626 gen.finish()
627 self.set_lineno(node)
628 frees = gen.scope.get_free_vars()
629 if frees:
630 for name in frees:
631 self.emit('LOAD_CLOSURE', name)
632 self.emit('LOAD_CONST', gen)
633 self.emit('MAKE_CLOSURE', 0)
634 else:
635 self.emit('LOAD_CONST', gen)
636 self.emit('MAKE_FUNCTION', 0)
637
638 # precomputation of outmost iterable
639 self.visit(node.code.quals[0].iter)
640 self.emit('GET_ITER')
641 self.emit('CALL_FUNCTION', 1)
642
643 def visitGenExprInner(self, node):
644 self.set_lineno(node)
645 # setup list
646
647 stack = []
648 for i, for_ in zip(range(len(node.quals)), node.quals):
649 start, anchor = self.visit(for_)
650 cont = None
651 for if_ in for_.ifs:
652 if cont is None:
653 cont = self.newBlock()
654 self.visit(if_, cont)
655 stack.insert(0, (start, cont, anchor))
656
657 self.visit(node.expr)
658 self.emit('YIELD_VALUE')
659
660 for start, cont, anchor in stack:
661 if cont:
662 skip_one = self.newBlock()
663 self.emit('JUMP_FORWARD', skip_one)
664 self.startBlock(cont)
665 self.emit('POP_TOP')
666 self.nextBlock(skip_one)
667 self.emit('JUMP_ABSOLUTE', start)
668 self.startBlock(anchor)
669 self.emit('LOAD_CONST', None)
670
671 def visitGenExprFor(self, node):
672 start = self.newBlock()
673 anchor = self.newBlock()
Tim Peters4e0e1b62004-07-07 20:54:48 +0000674
Raymond Hettinger354433a2004-05-19 08:20:33 +0000675 if node.is_outmost:
676 self.loadName('[outmost-iterable]')
677 else:
678 self.visit(node.iter)
679 self.emit('GET_ITER')
680
681 self.nextBlock(start)
682 self.set_lineno(node, force=True)
683 self.emit('FOR_ITER', anchor)
684 self.nextBlock()
685 self.visit(node.assign)
686 return start, anchor
687
688 def visitGenExprIf(self, node, branch):
689 self.set_lineno(node, force=True)
690 self.visit(node.test)
691 self.emit('JUMP_IF_FALSE', branch)
692 self.newBlock()
693 self.emit('POP_TOP')
694
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000695 # exception related
696
697 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000698 # XXX would be interesting to implement this via a
699 # transformation of the AST before this stage
700 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000701 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 # XXX __debug__ and AssertionError appear to be special cases
703 # -- they are always loaded as globals even if there are local
704 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000705 self.emit('LOAD_GLOBAL', '__debug__')
706 self.emit('JUMP_IF_FALSE', end)
707 self.nextBlock()
708 self.emit('POP_TOP')
709 self.visit(node.test)
710 self.emit('JUMP_IF_TRUE', end)
711 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000712 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000713 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000714 if node.fail:
715 self.visit(node.fail)
716 self.emit('RAISE_VARARGS', 2)
717 else:
718 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000719 self.nextBlock(end)
720 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721
722 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000723 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724 n = 0
725 if node.expr1:
726 self.visit(node.expr1)
727 n = n + 1
728 if node.expr2:
729 self.visit(node.expr2)
730 n = n + 1
731 if node.expr3:
732 self.visit(node.expr3)
733 n = n + 1
734 self.emit('RAISE_VARARGS', n)
735
736 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000737 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000738 handlers = self.newBlock()
739 end = self.newBlock()
740 if node.else_:
741 lElse = self.newBlock()
742 else:
743 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000744 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000745 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000746 self.nextBlock(body)
747 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000748 self.visit(node.body)
749 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000750 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000751 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000752 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000753
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000754 last = len(node.handlers) - 1
755 for i in range(len(node.handlers)):
756 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000757 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000758 if expr:
759 self.emit('DUP_TOP')
760 self.visit(expr)
761 self.emit('COMPARE_OP', 'exception match')
762 next = self.newBlock()
763 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000764 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000765 self.emit('POP_TOP')
766 self.emit('POP_TOP')
767 if target:
768 self.visit(target)
769 else:
770 self.emit('POP_TOP')
771 self.emit('POP_TOP')
772 self.visit(body)
773 self.emit('JUMP_FORWARD', end)
774 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000775 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000776 else:
777 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000778 if expr: # XXX
779 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000780 self.emit('END_FINALLY')
781 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000782 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000783 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000784 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000785
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000786 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000787 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000788 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000789 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000790 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000791 self.nextBlock(body)
792 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000793 self.visit(node.body)
794 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000795 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000796 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000797 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000798 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000799 self.visit(node.final)
800 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000801 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000802
803 # misc
804
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000805 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000806 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000807 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000808 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000809
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000810 def visitConst(self, node):
811 self.emit('LOAD_CONST', node.value)
812
813 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000814 self.emit('LOAD_CONST', node.name)
815 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000816
817 def visitGlobal(self, node):
818 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000819 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000820
821 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000822 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000823 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000824
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000825 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000826 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000827
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000828 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000829 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000830 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000831 if VERSION > 1:
832 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000833 self.emit('IMPORT_NAME', name)
Neal Norwitza312c3a2002-06-06 18:30:10 +0000834 mod = name.split(".")[0]
Michael W. Hudson896e5162003-06-27 12:32:39 +0000835 if alias:
836 self._resolveDots(name)
837 self.storeName(alias)
838 else:
839 self.storeName(mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000840
841 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000842 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000843 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000844 if VERSION > 1:
845 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000846 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000847 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000848 if VERSION > 1:
849 if name == '*':
850 self.namespace = 0
851 self.emit('IMPORT_STAR')
852 # There can only be one name w/ from ... import *
853 assert len(node.names) == 1
854 return
855 else:
856 self.emit('IMPORT_FROM', name)
857 self._resolveDots(name)
858 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000859 else:
860 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000861 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000862
Jeremy Hylton20516082000-09-01 20:33:26 +0000863 def _resolveDots(self, name):
Neal Norwitza312c3a2002-06-06 18:30:10 +0000864 elts = name.split(".")
Jeremy Hylton20516082000-09-01 20:33:26 +0000865 if len(elts) == 1:
866 return
867 for elt in elts[1:]:
868 self.emit('LOAD_ATTR', elt)
869
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000870 def visitGetattr(self, node):
871 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000872 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000873
874 # next five implement assignments
875
876 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000877 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000878 self.visit(node.expr)
879 dups = len(node.nodes) - 1
880 for i in range(len(node.nodes)):
881 elt = node.nodes[i]
882 if i < dups:
883 self.emit('DUP_TOP')
884 if isinstance(elt, ast.Node):
885 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000886
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000887 def visitAssName(self, node):
888 if node.flags == 'OP_ASSIGN':
889 self.storeName(node.name)
890 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000891 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000892 self.delName(node.name)
893 else:
894 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000895
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000896 def visitAssAttr(self, node):
897 self.visit(node.expr)
898 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000899 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000900 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000901 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000902 else:
903 print "warning: unexpected flags:", node.flags
904 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000905
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000906 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000907 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000908 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000909 for child in node.nodes:
910 self.visit(child)
911
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000912 if VERSION > 1:
913 visitAssTuple = _visitAssSequence
914 visitAssList = _visitAssSequence
915 else:
916 def visitAssTuple(self, node):
917 self._visitAssSequence(node, 'UNPACK_TUPLE')
918
919 def visitAssList(self, node):
920 self._visitAssSequence(node, 'UNPACK_LIST')
921
922 # augmented assignment
923
924 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000925 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000926 aug_node = wrap_aug(node.node)
927 self.visit(aug_node, "load")
928 self.visit(node.expr)
929 self.emit(self._augmented_opcode[node.op])
930 self.visit(aug_node, "store")
931
932 _augmented_opcode = {
933 '+=' : 'INPLACE_ADD',
934 '-=' : 'INPLACE_SUBTRACT',
935 '*=' : 'INPLACE_MULTIPLY',
936 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000937 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000938 '%=' : 'INPLACE_MODULO',
939 '**=': 'INPLACE_POWER',
940 '>>=': 'INPLACE_RSHIFT',
941 '<<=': 'INPLACE_LSHIFT',
942 '&=' : 'INPLACE_AND',
943 '^=' : 'INPLACE_XOR',
944 '|=' : 'INPLACE_OR',
945 }
946
947 def visitAugName(self, node, mode):
948 if mode == "load":
949 self.loadName(node.name)
950 elif mode == "store":
951 self.storeName(node.name)
952
953 def visitAugGetattr(self, node, mode):
954 if mode == "load":
955 self.visit(node.expr)
956 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000957 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000958 elif mode == "store":
959 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000960 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000961
962 def visitAugSlice(self, node, mode):
963 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000964 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000965 elif mode == "store":
966 slice = 0
967 if node.lower:
968 slice = slice | 1
969 if node.upper:
970 slice = slice | 2
971 if slice == 0:
972 self.emit('ROT_TWO')
973 elif slice == 3:
974 self.emit('ROT_FOUR')
975 else:
976 self.emit('ROT_THREE')
977 self.emit('STORE_SLICE+%d' % slice)
978
979 def visitAugSubscript(self, node, mode):
980 if len(node.subs) > 1:
981 raise SyntaxError, "augmented assignment to tuple is not possible"
982 if mode == "load":
983 self.visitSubscript(node, 1)
984 elif mode == "store":
985 self.emit('ROT_THREE')
986 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000987
988 def visitExec(self, node):
989 self.visit(node.expr)
990 if node.locals is None:
991 self.emit('LOAD_CONST', None)
992 else:
993 self.visit(node.locals)
994 if node.globals is None:
995 self.emit('DUP_TOP')
996 else:
997 self.visit(node.globals)
998 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000999
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001000 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +00001001 pos = 0
1002 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001003 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001004 self.visit(node.node)
1005 for arg in node.args:
1006 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +00001007 if isinstance(arg, ast.Keyword):
1008 kw = kw + 1
1009 else:
1010 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +00001011 if node.star_args is not None:
1012 self.visit(node.star_args)
1013 if node.dstar_args is not None:
1014 self.visit(node.dstar_args)
1015 have_star = node.star_args is not None
1016 have_dstar = node.dstar_args is not None
1017 opcode = callfunc_opcode_info[have_star, have_dstar]
1018 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001019
Jeremy Hylton2afff322001-08-27 21:51:52 +00001020 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001021 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001022 if node.dest:
1023 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001024 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001025 if node.dest:
1026 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001027 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001028 if node.dest:
1029 self.emit('ROT_TWO')
1030 self.emit('PRINT_ITEM_TO')
1031 else:
1032 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +00001033 if node.dest and not newline:
1034 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001035
1036 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +00001037 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001038 if node.dest:
1039 self.emit('PRINT_NEWLINE_TO')
1040 else:
1041 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001042
1043 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001044 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001045 self.visit(node.value)
1046 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +00001047
Jeremy Hylton1048aa92001-09-14 23:17:55 +00001048 def visitYield(self, node):
1049 self.set_lineno(node)
1050 self.visit(node.value)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001051 self.emit('YIELD_VALUE')
Jeremy Hylton1048aa92001-09-14 23:17:55 +00001052
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001053 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001054
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001055 def visitSlice(self, node, aug_flag=None):
1056 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001057 self.visit(node.expr)
1058 slice = 0
1059 if node.lower:
1060 self.visit(node.lower)
1061 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001062 if node.upper:
1063 self.visit(node.upper)
1064 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001065 if aug_flag:
1066 if slice == 0:
1067 self.emit('DUP_TOP')
1068 elif slice == 3:
1069 self.emit('DUP_TOPX', 3)
1070 else:
1071 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001072 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001073 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001074 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001075 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001076 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001077 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001078 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001079 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001080 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001081
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001082 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001083 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001084 for sub in node.subs:
1085 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001086 if aug_flag:
1087 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001088 if len(node.subs) > 1:
1089 self.emit('BUILD_TUPLE', len(node.subs))
1090 if node.flags == 'OP_APPLY':
1091 self.emit('BINARY_SUBSCR')
1092 elif node.flags == 'OP_ASSIGN':
1093 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001094 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001095 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001096
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001097 # binary ops
1098
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001099 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001100 self.visit(node.left)
1101 self.visit(node.right)
1102 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001103
1104 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001105 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001106
1107 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001108 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001109
1110 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001111 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001112
1113 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001114 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001115
Jeremy Hylton94afe322001-08-29 18:14:39 +00001116 def visitFloorDiv(self, node):
1117 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1118
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001119 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001120 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001121
Jeremy Hylton126960b2000-02-14 21:33:10 +00001122 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001123 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001124
1125 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001126 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001127
1128 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001129 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001130
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001131 # unary ops
1132
1133 def unaryOp(self, node, op):
1134 self.visit(node.expr)
1135 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001136
Jeremy Hylton126960b2000-02-14 21:33:10 +00001137 def visitInvert(self, node):
1138 return self.unaryOp(node, 'UNARY_INVERT')
1139
Jeremy Hylton40245602000-02-08 21:15:48 +00001140 def visitUnarySub(self, node):
1141 return self.unaryOp(node, 'UNARY_NEGATIVE')
1142
1143 def visitUnaryAdd(self, node):
1144 return self.unaryOp(node, 'UNARY_POSITIVE')
1145
1146 def visitUnaryInvert(self, node):
1147 return self.unaryOp(node, 'UNARY_INVERT')
1148
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001149 def visitNot(self, node):
1150 return self.unaryOp(node, 'UNARY_NOT')
1151
Jeremy Hylton40245602000-02-08 21:15:48 +00001152 def visitBackquote(self, node):
1153 return self.unaryOp(node, 'UNARY_CONVERT')
1154
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001155 # bit ops
1156
Jeremy Hyltona5058122000-02-14 14:14:29 +00001157 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001158 self.visit(nodes[0])
1159 for node in nodes[1:]:
1160 self.visit(node)
1161 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001162
1163 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001164 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001165
1166 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001167 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001168
1169 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001170 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001171
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001172 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001173
Jeremy Hyltona5058122000-02-14 14:14:29 +00001174 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001175 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001176
Jeremy Hylton40245602000-02-08 21:15:48 +00001177 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001178 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001179 for elt in node.nodes:
1180 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001181 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001182
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001183 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001184 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001185 for elt in node.nodes:
1186 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001187 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001188
1189 def visitSliceobj(self, node):
1190 for child in node.nodes:
1191 self.visit(child)
1192 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001193
Jeremy Hyltona5058122000-02-14 14:14:29 +00001194 def visitDict(self, node):
Jeremy Hylton18565412002-12-31 18:26:17 +00001195 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001196 self.emit('BUILD_MAP', 0)
1197 for k, v in node.items:
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001198 self.emit('DUP_TOP')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001199 self.visit(k)
Gustavo Niemeyer78429a62002-12-16 13:54:02 +00001200 self.visit(v)
1201 self.emit('ROT_THREE')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001202 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001203
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001204class NestedScopeMixin:
1205 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001206 def initClass(self):
1207 self.__class__.NameFinder = LocalNameFinder
1208 self.__class__.FunctionGen = FunctionCodeGenerator
1209 self.__class__.ClassGen = ClassCodeGenerator
1210
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001211class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001212 __super_init = CodeGenerator.__init__
1213
1214 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001215
Jeremy Hylton37c93512001-09-17 18:03:55 +00001216 def __init__(self, tree):
1217 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001218 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001219 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001220 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001221
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001222 def get_module(self):
1223 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001224
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001225class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1226 __super_init = CodeGenerator.__init__
1227
1228 scopes = None
1229 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001230
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001231 def __init__(self, tree):
1232 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1233 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001234 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001235
1236 def get_module(self):
1237 return self
1238
1239class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1240
1241 __super_init = CodeGenerator.__init__
1242
1243 scopes = None
1244 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001245
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001246 def __init__(self, tree):
1247 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1248 self.__super_init()
1249 self.set_lineno(tree)
1250 walk(tree, self)
1251 self.emit('RETURN_VALUE')
1252
1253 def get_module(self):
1254 return self
Tim Peterse4418602002-02-16 07:34:19 +00001255
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001256 def visitDiscard(self, node):
1257 # XXX Discard means it's an expression. Perhaps this is a bad
1258 # name.
1259 self.visit(node.expr)
1260 self.emit('PRINT_EXPR')
1261
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001262class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001263 optimized = 1
1264 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001265
Jeremy Hylton37c93512001-09-17 18:03:55 +00001266 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001267 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001268 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001269 if isLambda:
1270 klass = FunctionCodeGenerator
1271 name = "<lambda.%d>" % klass.lambdaCount
1272 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001273 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001274 name = func.name
Raymond Hettinger354433a2004-05-19 08:20:33 +00001275
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001276 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001277 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1278 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001279 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001280 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001281
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001282 if not isLambda and func.doc:
1283 self.setDocstring(func.doc)
1284
Jeremy Hylton2afff322001-08-27 21:51:52 +00001285 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001286 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001287 if func.varargs:
1288 self.graph.setFlag(CO_VARARGS)
1289 if func.kwargs:
1290 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001291 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001292 if hasTupleArg:
1293 self.generateArgUnpack(func.argnames)
1294
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001295 def get_module(self):
1296 return self.module
1297
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001298 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001299 self.graph.startExitBlock()
1300 if not self.isLambda:
1301 self.emit('LOAD_CONST', None)
1302 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001303
1304 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001305 for i in range(len(args)):
1306 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001307 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001308 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001309 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001310
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001311 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001312 if VERSION > 1:
1313 self.emit('UNPACK_SEQUENCE', len(tup))
1314 else:
1315 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001316 for elt in tup:
1317 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001318 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001319 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001320 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001321
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001322 unpackTuple = unpackSequence
1323
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001324class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001325 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001326 super_init = CodeGenerator.__init__ # call be other init
1327 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001328
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001329 __super_init = AbstractFunctionCode.__init__
1330
Jeremy Hylton37c93512001-09-17 18:03:55 +00001331 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001332 self.scopes = scopes
1333 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001334 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001335 self.graph.setFreeVars(self.scope.get_free_vars())
1336 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001337 if self.scope.generator is not None:
1338 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001339
Raymond Hettinger354433a2004-05-19 08:20:33 +00001340class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
1341 CodeGenerator):
1342 super_init = CodeGenerator.__init__ # call be other init
1343 scopes = None
1344
1345 __super_init = AbstractFunctionCode.__init__
1346
1347 def __init__(self, gexp, scopes, class_name, mod):
1348 self.scopes = scopes
1349 self.scope = scopes[gexp]
1350 self.__super_init(gexp, scopes, 1, class_name, mod)
1351 self.graph.setFreeVars(self.scope.get_free_vars())
1352 self.graph.setCellVars(self.scope.get_cell_vars())
1353 self.graph.setFlag(CO_GENERATOR)
1354
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001355class AbstractClassCode:
1356
Jeremy Hylton37c93512001-09-17 18:03:55 +00001357 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001358 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001359 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001360 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001361 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001362 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001363 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001364 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001365 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001366 if klass.doc:
1367 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001368
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001369 def get_module(self):
1370 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001371
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001372 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001373 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001374 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001375 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001376
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001377class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001378 super_init = CodeGenerator.__init__
1379 scopes = None
1380
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001381 __super_init = AbstractClassCode.__init__
1382
Jeremy Hylton37c93512001-09-17 18:03:55 +00001383 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001384 self.scopes = scopes
1385 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001386 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001387 self.graph.setFreeVars(self.scope.get_free_vars())
1388 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001389 self.set_lineno(klass)
1390 self.emit("LOAD_GLOBAL", "__name__")
1391 self.storeName("__module__")
1392 if klass.doc:
1393 self.emit("LOAD_CONST", klass.doc)
1394 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001395
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001396def generateArgList(arglist):
1397 """Generate an arg list marking TupleArgs"""
1398 args = []
1399 extra = []
1400 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001401 for i in range(len(arglist)):
1402 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001403 if type(elt) == types.StringType:
1404 args.append(elt)
1405 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001406 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001407 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001408 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001409 else:
1410 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001411 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001412
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001413def findOp(node):
1414 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1415 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001416 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001417 return v.op
1418
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001419class OpFinder:
1420 def __init__(self):
1421 self.op = None
1422 def visitAssName(self, node):
1423 if self.op is None:
1424 self.op = node.flags
1425 elif self.op != node.flags:
1426 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001427 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001428 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001429
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001430class Delegator:
1431 """Base class to support delegation for augmented assignment nodes
1432
1433 To generator code for augmented assignments, we use the following
1434 wrapper classes. In visitAugAssign, the left-hand expression node
1435 is visited twice. The first time the visit uses the normal method
1436 for that node . The second time the visit uses a different method
1437 that generates the appropriate code to perform the assignment.
1438 These delegator classes wrap the original AST nodes in order to
1439 support the variant visit methods.
1440 """
1441 def __init__(self, obj):
1442 self.obj = obj
1443
1444 def __getattr__(self, attr):
1445 return getattr(self.obj, attr)
1446
1447class AugGetattr(Delegator):
1448 pass
1449
1450class AugName(Delegator):
1451 pass
1452
1453class AugSlice(Delegator):
1454 pass
1455
1456class AugSubscript(Delegator):
1457 pass
1458
1459wrapper = {
1460 ast.Getattr: AugGetattr,
1461 ast.Name: AugName,
1462 ast.Slice: AugSlice,
1463 ast.Subscript: AugSubscript,
1464 }
1465
1466def wrap_aug(node):
1467 return wrapper[node.__class__](node)
1468
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001469if __name__ == "__main__":
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001470 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001471 compileFile(file)