blob: a1236de6340b427b24dcba3fdb4b60a243cf2d89 [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 Hylton36cc6a22000-03-16 20:06:59 +00006from cStringIO import StringIO
7
Jeremy Hylton37c93512001-09-17 18:03:55 +00008from compiler import ast, parse, walk, syntax
Jeremy Hylton364f9b92001-04-12 06:40:42 +00009from compiler import pyassem, misc, future, symbols
10from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +000011from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
Neal Norwitzeaed39f2006-03-03 19:12:58 +000012 CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +000013 CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT)
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"
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +0000217 elif feature == "absolute_import":
218 self.graph.setFlag(CO_FUTURE_ABSIMPORT)
219 elif feature == "with_statement":
220 self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000221
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000222 def initClass(self):
223 """This method is called once for each class"""
224
225 def checkClass(self):
226 """Verify that class is constructed correctly"""
227 try:
228 assert hasattr(self, 'graph')
229 assert getattr(self, 'NameFinder')
230 assert getattr(self, 'FunctionGen')
231 assert getattr(self, 'ClassGen')
232 except AssertionError, msg:
233 intro = "Bad class construction for %s" % self.__class__.__name__
234 raise AssertionError, intro
235
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000237 self.emit = self.graph.emit
238 self.newBlock = self.graph.newBlock
239 self.startBlock = self.graph.startBlock
240 self.nextBlock = self.graph.nextBlock
241 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000242
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000243 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000244 """Return a code object"""
245 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000246
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000247 def mangle(self, name):
248 if self.class_name is not None:
249 return misc.mangle(name, self.class_name)
250 else:
251 return name
252
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000253 def parseSymbols(self, tree):
254 s = symbols.SymbolVisitor()
255 walk(tree, s)
256 return s.scopes
257
258 def get_module(self):
259 raise RuntimeError, "should be implemented by subclasses"
260
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000261 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000262
Jeremy Hylton40245602000-02-08 21:15:48 +0000263 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000264 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000265
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000266 def storeName(self, name):
267 self._nameOp('STORE', name)
268
269 def loadName(self, name):
270 self._nameOp('LOAD', name)
271
272 def delName(self, name):
273 self._nameOp('DELETE', name)
274
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000275 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000276 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000277 scope = self.scope.check_name(name)
278 if scope == SC_LOCAL:
279 if not self.optimized:
280 self.emit(prefix + '_NAME', name)
281 else:
282 self.emit(prefix + '_FAST', name)
283 elif scope == SC_GLOBAL:
284 if not self.optimized:
285 self.emit(prefix + '_NAME', name)
286 else:
287 self.emit(prefix + '_GLOBAL', name)
288 elif scope == SC_FREE or scope == SC_CELL:
289 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000290 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000291 raise RuntimeError, "unsupported scope for var %s: %d" % \
292 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000293
Jeremy Hylton13d70942001-04-12 21:04:43 +0000294 def _implicitNameOp(self, prefix, name):
295 """Emit name ops for names generated implicitly by for loops
296
297 The interpreter generates names that start with a period or
298 dollar sign. The symbol table ignores these names because
299 they aren't present in the program text.
300 """
301 if self.optimized:
302 self.emit(prefix + '_FAST', name)
303 else:
304 self.emit(prefix + '_NAME', name)
305
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000306 # The set_lineno() function and the explicit emit() calls for
307 # SET_LINENO below are only used to generate the line number table.
308 # As of Python 2.3, the interpreter does not have a SET_LINENO
309 # instruction. pyassem treats SET_LINENO opcodes as a special case.
310
311 def set_lineno(self, node, force=False):
312 """Emit SET_LINENO if necessary.
313
314 The instruction is considered necessary if the node has a
315 lineno attribute and it is different than the last lineno
316 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 Hyltonaccb62b2002-12-31 18:17:44 +0000330 return True
331 return False
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000332
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
Barry Warsaw52acb492001-12-21 20:04:22 +0000354 def visitExpression(self, node):
355 self.set_lineno(node)
356 self.scopes = self.parseSymbols(node)
357 self.scope = self.scopes[node]
358 self.visit(node.node)
359 self.emit('RETURN_VALUE')
360
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000361 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000362 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000363 if node.doc:
364 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000365 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000366
367 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000368 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000370 def _visitFuncOrLambda(self, node, isLambda=0):
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000371 if not isLambda and node.decorators:
Michael W. Hudson0ccff072004-08-17 17:29:16 +0000372 for decorator in node.decorators.nodes:
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000373 self.visit(decorator)
374 ndecorators = len(node.decorators.nodes)
375 else:
376 ndecorators = 0
Tim Petersa45cacf2004-08-20 03:47:14 +0000377
Jeremy Hylton37c93512001-09-17 18:03:55 +0000378 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000379 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000380 walk(node.code, gen)
381 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000382 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000383 for default in node.defaults:
384 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000385 frees = gen.scope.get_free_vars()
386 if frees:
387 for name in frees:
388 self.emit('LOAD_CLOSURE', name)
389 self.emit('LOAD_CONST', gen)
390 self.emit('MAKE_CLOSURE', len(node.defaults))
391 else:
392 self.emit('LOAD_CONST', gen)
393 self.emit('MAKE_FUNCTION', len(node.defaults))
Tim Peters6db15d72004-08-04 02:36:18 +0000394
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000395 for i in range(ndecorators):
396 self.emit('CALL_FUNCTION', 1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000397
398 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000399 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000400 self.get_module())
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000401 walk(node.code, gen)
402 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000403 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000404 self.emit('LOAD_CONST', node.name)
405 for base in node.bases:
406 self.visit(base)
407 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000408 frees = gen.scope.get_free_vars()
409 for name in frees:
410 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000411 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000412 if frees:
413 self.emit('MAKE_CLOSURE', 0)
414 else:
415 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000416 self.emit('CALL_FUNCTION', 0)
417 self.emit('BUILD_CLASS')
418 self.storeName(node.name)
419
420 # The rest are standard visitor methods
421
422 # The next few implement control-flow statements
423
424 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000425 end = self.newBlock()
426 numtests = len(node.tests)
427 for i in range(numtests):
428 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000429 if is_constant_false(test):
430 # XXX will need to check generator stuff here
431 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000432 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000433 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000434 nextTest = self.newBlock()
435 self.emit('JUMP_IF_FALSE', nextTest)
436 self.nextBlock()
437 self.emit('POP_TOP')
438 self.visit(suite)
439 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000440 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000441 self.emit('POP_TOP')
442 if node.else_:
443 self.visit(node.else_)
444 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000445
446 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000447 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000448
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000449 loop = self.newBlock()
450 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000451
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000452 after = self.newBlock()
453 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000454
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000455 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000456 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000457
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000458 self.set_lineno(node, force=True)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000459 self.visit(node.test)
460 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000461
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000462 self.nextBlock()
463 self.emit('POP_TOP')
464 self.visit(node.body)
465 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000466
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000467 self.startBlock(else_) # or just the POPs if not else clause
468 self.emit('POP_TOP')
469 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000470 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000471 if node.else_:
472 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000473 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000474
475 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000476 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000477 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000478 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000479 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000480
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000481 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000482 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000484 self.emit('GET_ITER')
485
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000486 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000487 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000488 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000489 self.visit(node.assign)
490 self.visit(node.body)
491 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000492 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000493 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000494 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000495 if node.else_:
496 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000497 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000498
499 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000500 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000501 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000502 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000503 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000504 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000505
506 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000507 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000508 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000509 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000510 kind, block = self.setups.top()
511 if kind == LOOP:
512 self.set_lineno(node)
513 self.emit('JUMP_ABSOLUTE', block)
514 self.nextBlock()
515 elif kind == EXCEPT or kind == TRY_FINALLY:
516 self.set_lineno(node)
517 # find the block that starts the loop
518 top = len(self.setups)
519 while top > 0:
520 top = top - 1
521 kind, loop_block = self.setups[top]
522 if kind == LOOP:
523 break
524 if kind != LOOP:
525 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000526 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000527 self.emit('CONTINUE_LOOP', loop_block)
528 self.nextBlock()
529 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000530 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000531 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000532
533 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000534 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000535 for child in node.nodes[:-1]:
536 self.visit(child)
537 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000538 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000539 self.emit('POP_TOP')
540 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000541 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000542
543 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000544 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000545
546 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000547 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000548
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +0000549 def visitIfExp(self, node):
550 endblock = self.newBlock()
551 elseblock = self.newBlock()
552 self.visit(node.test)
553 self.emit('JUMP_IF_FALSE', elseblock)
554 self.emit('POP_TOP')
555 self.visit(node.then)
556 self.emit('JUMP_FORWARD', endblock)
557 self.nextBlock(elseblock)
558 self.emit('POP_TOP')
559 self.visit(node.else_)
560 self.nextBlock(endblock)
561
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000562 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000563 self.visit(node.expr)
564 cleanup = self.newBlock()
565 for op, code in node.ops[:-1]:
566 self.visit(code)
567 self.emit('DUP_TOP')
568 self.emit('ROT_THREE')
569 self.emit('COMPARE_OP', op)
570 self.emit('JUMP_IF_FALSE', cleanup)
571 self.nextBlock()
572 self.emit('POP_TOP')
573 # now do the last comparison
574 if node.ops:
575 op, code = node.ops[-1]
576 self.visit(code)
577 self.emit('COMPARE_OP', op)
578 if len(node.ops) > 1:
579 end = self.newBlock()
580 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000581 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000582 self.emit('ROT_TWO')
583 self.emit('POP_TOP')
584 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000585
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000586 # list comprehensions
587 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000588
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000589 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000590 self.set_lineno(node)
591 # setup list
592 append = "$append%d" % self.__list_count
593 self.__list_count = self.__list_count + 1
594 self.emit('BUILD_LIST', 0)
595 self.emit('DUP_TOP')
596 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000597 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000598
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000599 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000600 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000601 start, anchor = self.visit(for_)
602 cont = None
603 for if_ in for_.ifs:
604 if cont is None:
605 cont = self.newBlock()
606 self.visit(if_, cont)
607 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000608
Jeremy Hylton13d70942001-04-12 21:04:43 +0000609 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000610 self.visit(node.expr)
611 self.emit('CALL_FUNCTION', 1)
612 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000613
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000614 for start, cont, anchor in stack:
615 if cont:
616 skip_one = self.newBlock()
617 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000618 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000619 self.emit('POP_TOP')
620 self.nextBlock(skip_one)
621 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000622 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000623 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000624
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000625 self.__list_count = self.__list_count - 1
626
627 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000628 start = self.newBlock()
629 anchor = self.newBlock()
630
631 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000632 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000633 self.nextBlock(start)
Jeremy Hylton18565412002-12-31 18:26:17 +0000634 self.set_lineno(node, force=True)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000635 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000636 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000637 self.visit(node.assign)
638 return start, anchor
639
640 def visitListCompIf(self, node, branch):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000641 self.set_lineno(node, force=True)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000642 self.visit(node.test)
643 self.emit('JUMP_IF_FALSE', branch)
644 self.newBlock()
645 self.emit('POP_TOP')
646
Raymond Hettinger354433a2004-05-19 08:20:33 +0000647 def visitGenExpr(self, node):
648 gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
649 self.get_module())
650 walk(node.code, gen)
651 gen.finish()
652 self.set_lineno(node)
653 frees = gen.scope.get_free_vars()
654 if frees:
655 for name in frees:
656 self.emit('LOAD_CLOSURE', name)
657 self.emit('LOAD_CONST', gen)
658 self.emit('MAKE_CLOSURE', 0)
659 else:
660 self.emit('LOAD_CONST', gen)
661 self.emit('MAKE_FUNCTION', 0)
662
663 # precomputation of outmost iterable
664 self.visit(node.code.quals[0].iter)
665 self.emit('GET_ITER')
666 self.emit('CALL_FUNCTION', 1)
667
668 def visitGenExprInner(self, node):
669 self.set_lineno(node)
670 # setup list
671
672 stack = []
673 for i, for_ in zip(range(len(node.quals)), node.quals):
674 start, anchor = self.visit(for_)
675 cont = None
676 for if_ in for_.ifs:
677 if cont is None:
678 cont = self.newBlock()
679 self.visit(if_, cont)
680 stack.insert(0, (start, cont, anchor))
681
682 self.visit(node.expr)
683 self.emit('YIELD_VALUE')
684
685 for start, cont, anchor in stack:
686 if cont:
687 skip_one = self.newBlock()
688 self.emit('JUMP_FORWARD', skip_one)
689 self.startBlock(cont)
690 self.emit('POP_TOP')
691 self.nextBlock(skip_one)
692 self.emit('JUMP_ABSOLUTE', start)
693 self.startBlock(anchor)
694 self.emit('LOAD_CONST', None)
695
696 def visitGenExprFor(self, node):
697 start = self.newBlock()
698 anchor = self.newBlock()
Tim Peters4e0e1b62004-07-07 20:54:48 +0000699
Raymond Hettinger354433a2004-05-19 08:20:33 +0000700 if node.is_outmost:
701 self.loadName('[outmost-iterable]')
702 else:
703 self.visit(node.iter)
704 self.emit('GET_ITER')
705
706 self.nextBlock(start)
707 self.set_lineno(node, force=True)
708 self.emit('FOR_ITER', anchor)
709 self.nextBlock()
710 self.visit(node.assign)
711 return start, anchor
712
713 def visitGenExprIf(self, node, branch):
714 self.set_lineno(node, force=True)
715 self.visit(node.test)
716 self.emit('JUMP_IF_FALSE', branch)
717 self.newBlock()
718 self.emit('POP_TOP')
719
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000720 # exception related
721
722 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000723 # XXX would be interesting to implement this via a
724 # transformation of the AST before this stage
Jeremy Hylton2876f5a2004-08-07 19:21:56 +0000725 if __debug__:
726 end = self.newBlock()
727 self.set_lineno(node)
728 # XXX AssertionError appears to be special case -- it is always
729 # loaded as a global even if there is a local name. I guess this
730 # is a sort of renaming op.
731 self.nextBlock()
732 self.visit(node.test)
733 self.emit('JUMP_IF_TRUE', end)
734 self.nextBlock()
735 self.emit('POP_TOP')
736 self.emit('LOAD_GLOBAL', 'AssertionError')
737 if node.fail:
738 self.visit(node.fail)
739 self.emit('RAISE_VARARGS', 2)
740 else:
741 self.emit('RAISE_VARARGS', 1)
742 self.nextBlock(end)
743 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000744
745 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000746 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000747 n = 0
748 if node.expr1:
749 self.visit(node.expr1)
750 n = n + 1
751 if node.expr2:
752 self.visit(node.expr2)
753 n = n + 1
754 if node.expr3:
755 self.visit(node.expr3)
756 n = n + 1
757 self.emit('RAISE_VARARGS', n)
758
759 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000760 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000761 handlers = self.newBlock()
762 end = self.newBlock()
763 if node.else_:
764 lElse = self.newBlock()
765 else:
766 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000767 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000768 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000769 self.nextBlock(body)
770 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000771 self.visit(node.body)
772 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000773 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000774 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000775 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000776
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000777 last = len(node.handlers) - 1
778 for i in range(len(node.handlers)):
779 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000780 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000781 if expr:
782 self.emit('DUP_TOP')
783 self.visit(expr)
784 self.emit('COMPARE_OP', 'exception match')
785 next = self.newBlock()
786 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000787 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000788 self.emit('POP_TOP')
789 self.emit('POP_TOP')
790 if target:
791 self.visit(target)
792 else:
793 self.emit('POP_TOP')
794 self.emit('POP_TOP')
795 self.visit(body)
796 self.emit('JUMP_FORWARD', end)
797 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000798 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000799 else:
800 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000801 if expr: # XXX
802 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000803 self.emit('END_FINALLY')
804 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000805 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000806 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000807 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000808
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000809 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000810 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000811 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000812 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000813 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000814 self.nextBlock(body)
815 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000816 self.visit(node.body)
817 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000818 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000819 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000820 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000821 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000822 self.visit(node.final)
823 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000824 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000825
Guido van Rossum7ad94f02006-02-28 00:32:16 +0000826 __with_count = 0
827
828 def visitWith(self, node):
829 body = self.newBlock()
830 final = self.newBlock()
831 exitvar = "$exit%d" % self.__with_count
832 valuevar = "$value%d" % self.__with_count
833 self.__with_count += 1
834 self.set_lineno(node)
835 self.visit(node.expr)
836 self.emit('LOAD_ATTR', '__context__')
837 self.emit('CALL_FUNCTION', 0)
838 self.emit('DUP_TOP')
839 self.emit('LOAD_ATTR', '__exit__')
840 self._implicitNameOp('STORE', exitvar)
841 self.emit('LOAD_ATTR', '__enter__')
842 self.emit('CALL_FUNCTION', 0)
843 if node.vars is None:
844 self.emit('POP_TOP')
845 else:
846 self._implicitNameOp('STORE', valuevar)
847 self.emit('SETUP_FINALLY', final)
848 self.nextBlock(body)
849 self.setups.push((TRY_FINALLY, body))
850 if node.vars is not None:
851 self._implicitNameOp('LOAD', valuevar)
852 self._implicitNameOp('DELETE', valuevar)
853 self.visit(node.vars)
854 self.visit(node.body)
855 self.emit('POP_BLOCK')
856 self.setups.pop()
857 self.emit('LOAD_CONST', None)
858 self.nextBlock(final)
859 self.setups.push((END_FINALLY, final))
860 self.emit('WITH_CLEANUP')
861 self.emit('CALL_FUNCTION', 3)
862 self.emit('POP_TOP')
863 self.emit('END_FINALLY')
864 self.setups.pop()
865 self.__with_count -= 1
866
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000867 # misc
868
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000869 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000870 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000871 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000872 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000873
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000874 def visitConst(self, node):
875 self.emit('LOAD_CONST', node.value)
876
877 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000878 self.emit('LOAD_CONST', node.name)
879 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000880
881 def visitGlobal(self, node):
882 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000883 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000884
885 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000886 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000887 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000888
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000889 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000890 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000891
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000892 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000893 self.set_lineno(node)
Neal Norwitzd4e30352006-03-03 20:21:48 +0000894 level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1
Jeremy Hylton20516082000-09-01 20:33:26 +0000895 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000896 if VERSION > 1:
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +0000897 self.emit('LOAD_CONST', level)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000898 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000899 self.emit('IMPORT_NAME', name)
Neal Norwitza312c3a2002-06-06 18:30:10 +0000900 mod = name.split(".")[0]
Michael W. Hudson896e5162003-06-27 12:32:39 +0000901 if alias:
902 self._resolveDots(name)
903 self.storeName(alias)
904 else:
905 self.storeName(mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000906
907 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000908 self.set_lineno(node)
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +0000909 level = node.level
Neal Norwitzd4e30352006-03-03 20:21:48 +0000910 if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +0000911 level = -1
Jeremy Hylton20516082000-09-01 20:33:26 +0000912 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000913 if VERSION > 1:
Thomas Woutersfa0cf4f2006-03-03 18:16:20 +0000914 self.emit('LOAD_CONST', level)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000915 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000916 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000917 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000918 if VERSION > 1:
919 if name == '*':
920 self.namespace = 0
921 self.emit('IMPORT_STAR')
922 # There can only be one name w/ from ... import *
923 assert len(node.names) == 1
924 return
925 else:
926 self.emit('IMPORT_FROM', name)
927 self._resolveDots(name)
928 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000929 else:
930 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000931 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000932
Jeremy Hylton20516082000-09-01 20:33:26 +0000933 def _resolveDots(self, name):
Neal Norwitza312c3a2002-06-06 18:30:10 +0000934 elts = name.split(".")
Jeremy Hylton20516082000-09-01 20:33:26 +0000935 if len(elts) == 1:
936 return
937 for elt in elts[1:]:
938 self.emit('LOAD_ATTR', elt)
939
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000940 def visitGetattr(self, node):
941 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000942 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000943
944 # next five implement assignments
945
946 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000947 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000948 self.visit(node.expr)
949 dups = len(node.nodes) - 1
950 for i in range(len(node.nodes)):
951 elt = node.nodes[i]
952 if i < dups:
953 self.emit('DUP_TOP')
954 if isinstance(elt, ast.Node):
955 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000956
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000957 def visitAssName(self, node):
958 if node.flags == 'OP_ASSIGN':
959 self.storeName(node.name)
960 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000961 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000962 self.delName(node.name)
963 else:
964 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000965
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000966 def visitAssAttr(self, node):
967 self.visit(node.expr)
968 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000969 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000970 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000971 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000972 else:
973 print "warning: unexpected flags:", node.flags
974 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000975
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000976 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000977 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000978 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000979 for child in node.nodes:
980 self.visit(child)
981
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000982 if VERSION > 1:
983 visitAssTuple = _visitAssSequence
984 visitAssList = _visitAssSequence
985 else:
986 def visitAssTuple(self, node):
987 self._visitAssSequence(node, 'UNPACK_TUPLE')
988
989 def visitAssList(self, node):
990 self._visitAssSequence(node, 'UNPACK_LIST')
991
992 # augmented assignment
993
994 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000995 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000996 aug_node = wrap_aug(node.node)
997 self.visit(aug_node, "load")
998 self.visit(node.expr)
999 self.emit(self._augmented_opcode[node.op])
1000 self.visit(aug_node, "store")
1001
1002 _augmented_opcode = {
1003 '+=' : 'INPLACE_ADD',
1004 '-=' : 'INPLACE_SUBTRACT',
1005 '*=' : 'INPLACE_MULTIPLY',
1006 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +00001007 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001008 '%=' : 'INPLACE_MODULO',
1009 '**=': 'INPLACE_POWER',
1010 '>>=': 'INPLACE_RSHIFT',
1011 '<<=': 'INPLACE_LSHIFT',
1012 '&=' : 'INPLACE_AND',
1013 '^=' : 'INPLACE_XOR',
1014 '|=' : 'INPLACE_OR',
1015 }
1016
1017 def visitAugName(self, node, mode):
1018 if mode == "load":
1019 self.loadName(node.name)
1020 elif mode == "store":
1021 self.storeName(node.name)
1022
1023 def visitAugGetattr(self, node, mode):
1024 if mode == "load":
1025 self.visit(node.expr)
1026 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001027 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001028 elif mode == "store":
1029 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001030 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001031
1032 def visitAugSlice(self, node, mode):
1033 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001034 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001035 elif mode == "store":
1036 slice = 0
1037 if node.lower:
1038 slice = slice | 1
1039 if node.upper:
1040 slice = slice | 2
1041 if slice == 0:
1042 self.emit('ROT_TWO')
1043 elif slice == 3:
1044 self.emit('ROT_FOUR')
1045 else:
1046 self.emit('ROT_THREE')
1047 self.emit('STORE_SLICE+%d' % slice)
1048
1049 def visitAugSubscript(self, node, mode):
1050 if len(node.subs) > 1:
1051 raise SyntaxError, "augmented assignment to tuple is not possible"
1052 if mode == "load":
1053 self.visitSubscript(node, 1)
1054 elif mode == "store":
1055 self.emit('ROT_THREE')
1056 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001057
1058 def visitExec(self, node):
1059 self.visit(node.expr)
1060 if node.locals is None:
1061 self.emit('LOAD_CONST', None)
1062 else:
1063 self.visit(node.locals)
1064 if node.globals is None:
1065 self.emit('DUP_TOP')
1066 else:
1067 self.visit(node.globals)
1068 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +00001069
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001070 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +00001071 pos = 0
1072 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001073 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001074 self.visit(node.node)
1075 for arg in node.args:
1076 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +00001077 if isinstance(arg, ast.Keyword):
1078 kw = kw + 1
1079 else:
1080 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +00001081 if node.star_args is not None:
1082 self.visit(node.star_args)
1083 if node.dstar_args is not None:
1084 self.visit(node.dstar_args)
1085 have_star = node.star_args is not None
1086 have_dstar = node.dstar_args is not None
1087 opcode = callfunc_opcode_info[have_star, have_dstar]
1088 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001089
Jeremy Hylton2afff322001-08-27 21:51:52 +00001090 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001091 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001092 if node.dest:
1093 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001094 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001095 if node.dest:
1096 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001097 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001098 if node.dest:
1099 self.emit('ROT_TWO')
1100 self.emit('PRINT_ITEM_TO')
1101 else:
1102 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +00001103 if node.dest and not newline:
1104 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001105
1106 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +00001107 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001108 if node.dest:
1109 self.emit('PRINT_NEWLINE_TO')
1110 else:
1111 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001112
1113 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001114 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001115 self.visit(node.value)
1116 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +00001117
Jeremy Hylton1048aa92001-09-14 23:17:55 +00001118 def visitYield(self, node):
1119 self.set_lineno(node)
1120 self.visit(node.value)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001121 self.emit('YIELD_VALUE')
Jeremy Hylton1048aa92001-09-14 23:17:55 +00001122
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001123 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001124
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001125 def visitSlice(self, node, aug_flag=None):
1126 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001127 self.visit(node.expr)
1128 slice = 0
1129 if node.lower:
1130 self.visit(node.lower)
1131 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001132 if node.upper:
1133 self.visit(node.upper)
1134 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001135 if aug_flag:
1136 if slice == 0:
1137 self.emit('DUP_TOP')
1138 elif slice == 3:
1139 self.emit('DUP_TOPX', 3)
1140 else:
1141 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001142 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001143 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001144 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001145 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001146 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001147 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001148 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001149 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001150 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001151
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001152 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001153 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001154 for sub in node.subs:
1155 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001156 if aug_flag:
1157 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001158 if len(node.subs) > 1:
1159 self.emit('BUILD_TUPLE', len(node.subs))
1160 if node.flags == 'OP_APPLY':
1161 self.emit('BINARY_SUBSCR')
1162 elif node.flags == 'OP_ASSIGN':
1163 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001164 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001165 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001166
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001167 # binary ops
1168
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001169 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001170 self.visit(node.left)
1171 self.visit(node.right)
1172 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001173
1174 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001175 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001176
1177 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001178 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001179
1180 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001181 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001182
1183 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001184 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001185
Jeremy Hylton94afe322001-08-29 18:14:39 +00001186 def visitFloorDiv(self, node):
1187 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1188
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001189 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001190 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001191
Jeremy Hylton126960b2000-02-14 21:33:10 +00001192 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001193 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001194
1195 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001196 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001197
1198 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001199 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001200
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001201 # unary ops
1202
1203 def unaryOp(self, node, op):
1204 self.visit(node.expr)
1205 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001206
Jeremy Hylton126960b2000-02-14 21:33:10 +00001207 def visitInvert(self, node):
1208 return self.unaryOp(node, 'UNARY_INVERT')
1209
Jeremy Hylton40245602000-02-08 21:15:48 +00001210 def visitUnarySub(self, node):
1211 return self.unaryOp(node, 'UNARY_NEGATIVE')
1212
1213 def visitUnaryAdd(self, node):
1214 return self.unaryOp(node, 'UNARY_POSITIVE')
1215
1216 def visitUnaryInvert(self, node):
1217 return self.unaryOp(node, 'UNARY_INVERT')
1218
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001219 def visitNot(self, node):
1220 return self.unaryOp(node, 'UNARY_NOT')
1221
Jeremy Hylton40245602000-02-08 21:15:48 +00001222 def visitBackquote(self, node):
1223 return self.unaryOp(node, 'UNARY_CONVERT')
1224
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001225 # bit ops
1226
Jeremy Hyltona5058122000-02-14 14:14:29 +00001227 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001228 self.visit(nodes[0])
1229 for node in nodes[1:]:
1230 self.visit(node)
1231 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001232
1233 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001234 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001235
1236 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001237 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001238
1239 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001240 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001241
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001242 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001243
Jeremy Hyltona5058122000-02-14 14:14:29 +00001244 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001245 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001246
Jeremy Hylton40245602000-02-08 21:15:48 +00001247 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001248 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001249 for elt in node.nodes:
1250 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001251 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001252
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001253 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001254 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001255 for elt in node.nodes:
1256 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001257 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001258
1259 def visitSliceobj(self, node):
1260 for child in node.nodes:
1261 self.visit(child)
1262 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001263
Jeremy Hyltona5058122000-02-14 14:14:29 +00001264 def visitDict(self, node):
Jeremy Hylton18565412002-12-31 18:26:17 +00001265 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001266 self.emit('BUILD_MAP', 0)
1267 for k, v in node.items:
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001268 self.emit('DUP_TOP')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001269 self.visit(k)
Gustavo Niemeyer78429a62002-12-16 13:54:02 +00001270 self.visit(v)
1271 self.emit('ROT_THREE')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001272 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001273
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001274class NestedScopeMixin:
1275 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001276 def initClass(self):
1277 self.__class__.NameFinder = LocalNameFinder
1278 self.__class__.FunctionGen = FunctionCodeGenerator
1279 self.__class__.ClassGen = ClassCodeGenerator
1280
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001281class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001282 __super_init = CodeGenerator.__init__
1283
1284 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001285
Jeremy Hylton37c93512001-09-17 18:03:55 +00001286 def __init__(self, tree):
1287 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001288 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001289 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001290 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001291
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001292 def get_module(self):
1293 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001294
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001295class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1296 __super_init = CodeGenerator.__init__
1297
1298 scopes = None
1299 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001300
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001301 def __init__(self, tree):
1302 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1303 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001304 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001305
1306 def get_module(self):
1307 return self
1308
1309class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1310
1311 __super_init = CodeGenerator.__init__
1312
1313 scopes = None
1314 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001315
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001316 def __init__(self, tree):
1317 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1318 self.__super_init()
1319 self.set_lineno(tree)
1320 walk(tree, self)
1321 self.emit('RETURN_VALUE')
1322
1323 def get_module(self):
1324 return self
Tim Peterse4418602002-02-16 07:34:19 +00001325
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001326 def visitDiscard(self, node):
1327 # XXX Discard means it's an expression. Perhaps this is a bad
1328 # name.
1329 self.visit(node.expr)
1330 self.emit('PRINT_EXPR')
1331
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001332class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001333 optimized = 1
1334 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001335
Jeremy Hylton37c93512001-09-17 18:03:55 +00001336 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001337 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001338 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001339 if isLambda:
1340 klass = FunctionCodeGenerator
1341 name = "<lambda.%d>" % klass.lambdaCount
1342 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001343 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001344 name = func.name
Raymond Hettinger354433a2004-05-19 08:20:33 +00001345
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001346 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001347 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1348 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001349 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001350 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001351
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001352 if not isLambda and func.doc:
1353 self.setDocstring(func.doc)
1354
Jeremy Hylton2afff322001-08-27 21:51:52 +00001355 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001356 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001357 if func.varargs:
1358 self.graph.setFlag(CO_VARARGS)
1359 if func.kwargs:
1360 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001361 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001362 if hasTupleArg:
1363 self.generateArgUnpack(func.argnames)
1364
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001365 def get_module(self):
1366 return self.module
1367
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001368 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001369 self.graph.startExitBlock()
1370 if not self.isLambda:
1371 self.emit('LOAD_CONST', None)
1372 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001373
1374 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001375 for i in range(len(args)):
1376 arg = args[i]
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001377 if isinstance(arg, tuple):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001378 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001379 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001380
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001381 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001382 if VERSION > 1:
1383 self.emit('UNPACK_SEQUENCE', len(tup))
1384 else:
1385 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001386 for elt in tup:
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001387 if isinstance(elt, tuple):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001388 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001389 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001390 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001391
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001392 unpackTuple = unpackSequence
1393
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001394class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001395 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001396 super_init = CodeGenerator.__init__ # call be other init
1397 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001398
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001399 __super_init = AbstractFunctionCode.__init__
1400
Jeremy Hylton37c93512001-09-17 18:03:55 +00001401 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001402 self.scopes = scopes
1403 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001404 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001405 self.graph.setFreeVars(self.scope.get_free_vars())
1406 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001407 if self.scope.generator is not None:
1408 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001409
Raymond Hettinger354433a2004-05-19 08:20:33 +00001410class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
1411 CodeGenerator):
1412 super_init = CodeGenerator.__init__ # call be other init
1413 scopes = None
1414
1415 __super_init = AbstractFunctionCode.__init__
1416
1417 def __init__(self, gexp, scopes, class_name, mod):
1418 self.scopes = scopes
1419 self.scope = scopes[gexp]
1420 self.__super_init(gexp, scopes, 1, class_name, mod)
1421 self.graph.setFreeVars(self.scope.get_free_vars())
1422 self.graph.setCellVars(self.scope.get_cell_vars())
1423 self.graph.setFlag(CO_GENERATOR)
1424
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001425class AbstractClassCode:
1426
Jeremy Hylton37c93512001-09-17 18:03:55 +00001427 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001428 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001429 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001430 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001431 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001432 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001433 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001434 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001435 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001436 if klass.doc:
1437 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001438
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001439 def get_module(self):
1440 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001441
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001442 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001443 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001444 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001445 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001446
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001447class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001448 super_init = CodeGenerator.__init__
1449 scopes = None
1450
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001451 __super_init = AbstractClassCode.__init__
1452
Jeremy Hylton37c93512001-09-17 18:03:55 +00001453 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001454 self.scopes = scopes
1455 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001456 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001457 self.graph.setFreeVars(self.scope.get_free_vars())
1458 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001459 self.set_lineno(klass)
1460 self.emit("LOAD_GLOBAL", "__name__")
1461 self.storeName("__module__")
1462 if klass.doc:
1463 self.emit("LOAD_CONST", klass.doc)
1464 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001465
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001466def generateArgList(arglist):
1467 """Generate an arg list marking TupleArgs"""
1468 args = []
1469 extra = []
1470 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001471 for i in range(len(arglist)):
1472 elt = arglist[i]
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001473 if isinstance(elt, str):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001474 args.append(elt)
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001475 elif isinstance(elt, tuple):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001476 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001477 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001478 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001479 else:
1480 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001481 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001482
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001483def findOp(node):
1484 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1485 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001486 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001487 return v.op
1488
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001489class OpFinder:
1490 def __init__(self):
1491 self.op = None
1492 def visitAssName(self, node):
1493 if self.op is None:
1494 self.op = node.flags
1495 elif self.op != node.flags:
1496 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001497 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001498 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001499
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001500class Delegator:
1501 """Base class to support delegation for augmented assignment nodes
1502
1503 To generator code for augmented assignments, we use the following
1504 wrapper classes. In visitAugAssign, the left-hand expression node
1505 is visited twice. The first time the visit uses the normal method
1506 for that node . The second time the visit uses a different method
1507 that generates the appropriate code to perform the assignment.
1508 These delegator classes wrap the original AST nodes in order to
1509 support the variant visit methods.
1510 """
1511 def __init__(self, obj):
1512 self.obj = obj
1513
1514 def __getattr__(self, attr):
1515 return getattr(self.obj, attr)
1516
1517class AugGetattr(Delegator):
1518 pass
1519
1520class AugName(Delegator):
1521 pass
1522
1523class AugSlice(Delegator):
1524 pass
1525
1526class AugSubscript(Delegator):
1527 pass
1528
1529wrapper = {
1530 ast.Getattr: AugGetattr,
1531 ast.Name: AugName,
1532 ast.Slice: AugSlice,
1533 ast.Subscript: AugSubscript,
1534 }
1535
1536def wrap_aug(node):
1537 return wrapper[node.__class__](node)
1538
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001539if __name__ == "__main__":
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001540 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001541 compileFile(file)