blob: 441ccf3c1bec11b1f47ccf053f5d0d4c351dc2f5 [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
Jeremy Hylton71ebc332001-08-30 20:25:55 +000011from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000012 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000013from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000014
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000015# XXX The version-specific code can go, since this code only works with 2.x.
Jeremy Hylton9c048f92000-10-13 21:58:13 +000016# Do we have Python 1.x or Python 2.x?
17try:
18 VERSION = sys.version_info[0]
19except AttributeError:
20 VERSION = 1
21
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000022callfunc_opcode_info = {
23 # (Have *args, Have **args) : opcode
24 (0,0) : "CALL_FUNCTION",
25 (1,0) : "CALL_FUNCTION_VAR",
26 (0,1) : "CALL_FUNCTION_KW",
27 (1,1) : "CALL_FUNCTION_VAR_KW",
28}
29
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000030LOOP = 1
31EXCEPT = 2
32TRY_FINALLY = 3
33END_FINALLY = 4
34
Jeremy Hylton9dca3642001-09-17 21:02:51 +000035def compileFile(filename, display=0):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000036 f = open(filename, 'U')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000037 buf = f.read()
38 f.close()
39 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000040 try:
41 mod.compile(display)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000042 except SyntaxError:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000043 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000044 else:
45 f = open(filename + "c", "wb")
46 mod.dump(f)
47 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000048
Jeremy Hylton9dca3642001-09-17 21:02:51 +000049def compile(source, filename, mode, flags=None, dont_inherit=None):
50 """Replacement for builtin compile() function"""
51 if flags is not None or dont_inherit is not None:
52 raise RuntimeError, "not implemented yet"
Tim Peterse0c446b2001-10-18 21:57:37 +000053
Jeremy Hylton9dca3642001-09-17 21:02:51 +000054 if mode == "single":
55 gen = Interactive(source, filename)
56 elif mode == "exec":
57 gen = Module(source, filename)
58 elif mode == "eval":
59 gen = Expression(source, filename)
60 else:
61 raise ValueError("compile() 3rd arg must be 'exec' or "
62 "'eval' or 'single'")
63 gen.compile()
64 return gen.code
65
66class AbstractCompileMode:
67
68 mode = None # defined by subclass
69
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000070 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000071 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000072 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000073 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000074
Jeremy Hylton9dca3642001-09-17 21:02:51 +000075 def _get_tree(self):
76 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000077 misc.set_filename(self.filename, tree)
78 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000079 return tree
80
81 def compile(self):
82 pass # implemented by subclass
83
84 def getCode(self):
85 return self.code
86
87class Expression(AbstractCompileMode):
88
89 mode = "eval"
90
91 def compile(self):
92 tree = self._get_tree()
93 gen = ExpressionCodeGenerator(tree)
94 self.code = gen.getCode()
95
96class Interactive(AbstractCompileMode):
97
98 mode = "single"
99
100 def compile(self):
101 tree = self._get_tree()
102 gen = InteractiveCodeGenerator(tree)
103 self.code = gen.getCode()
104
105class Module(AbstractCompileMode):
106
107 mode = "exec"
108
109 def compile(self, display=0):
110 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000111 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000112 if display:
113 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000114 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000115 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000116
117 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000118 f.write(self.getPycHeader())
119 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000120
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000121 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000122
123 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000124 # compile.c uses marshal to write a long directly, with
125 # calling the interface that would also generate a 1-byte code
126 # to indicate the type of the value. simplest way to get the
127 # same effect is to call marshal and then skip the code.
Neal Norwitza312c3a2002-06-06 18:30:10 +0000128 mtime = os.path.getmtime(self.filename)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000129 mtime = struct.pack('<i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000130 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000131
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000132class LocalNameFinder:
133 """Find local names in scope"""
134 def __init__(self, names=()):
135 self.names = misc.Set()
136 self.globals = misc.Set()
137 for name in names:
138 self.names.add(name)
139
140 # XXX list comprehensions and for loops
141
142 def getLocals(self):
143 for elt in self.globals.elements():
144 if self.names.has_elt(elt):
145 self.names.remove(elt)
146 return self.names
147
148 def visitDict(self, node):
149 pass
150
151 def visitGlobal(self, node):
152 for name in node.names:
153 self.globals.add(name)
154
155 def visitFunction(self, node):
156 self.names.add(node.name)
157
158 def visitLambda(self, node):
159 pass
160
161 def visitImport(self, node):
162 for name, alias in node.names:
163 self.names.add(alias or name)
164
165 def visitFrom(self, node):
166 for name, alias in node.names:
167 self.names.add(alias or name)
168
169 def visitClass(self, node):
170 self.names.add(node.name)
171
172 def visitAssName(self, node):
173 self.names.add(node.name)
174
Jeremy Hylton2afff322001-08-27 21:51:52 +0000175def is_constant_false(node):
176 if isinstance(node, ast.Const):
177 if not node.value:
178 return 1
179 return 0
180
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000181class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000182 """Defines basic code generator for Python bytecode
183
184 This class is an abstract base class. Concrete subclasses must
185 define an __init__() that defines self.graph and then calls the
186 __init__() defined in this class.
187
188 The concrete class must also define the class attributes
189 NameFinder, FunctionGen, and ClassGen. These attributes can be
190 defined in the initClass() method, which is a hook for
191 initializing these methods after all the classes have been
Tim Peterse0c446b2001-10-18 21:57:37 +0000192 defined.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000193 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000194
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000195 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000196 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000197 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000198
Jeremy Hylton37c93512001-09-17 18:03:55 +0000199 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000200 if self.__initialized is None:
201 self.initClass()
202 self.__class__.__initialized = 1
203 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000204 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000205 self.setups = misc.Stack()
Jeremy Hylton92f39722000-09-01 20:47:37 +0000206 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000207 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000208 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000209
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000210 # XXX set flags based on future features
211 futures = self.get_module().futures
212 for feature in futures:
213 if feature == "division":
214 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000215 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000216 elif feature == "generators":
217 self.graph.setFlag(CO_GENERATOR_ALLOWED)
218
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000219 def initClass(self):
220 """This method is called once for each class"""
221
222 def checkClass(self):
223 """Verify that class is constructed correctly"""
224 try:
225 assert hasattr(self, 'graph')
226 assert getattr(self, 'NameFinder')
227 assert getattr(self, 'FunctionGen')
228 assert getattr(self, 'ClassGen')
229 except AssertionError, msg:
230 intro = "Bad class construction for %s" % self.__class__.__name__
231 raise AssertionError, intro
232
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000233 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000234 self.emit = self.graph.emit
235 self.newBlock = self.graph.newBlock
236 self.startBlock = self.graph.startBlock
237 self.nextBlock = self.graph.nextBlock
238 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000239
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000240 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000241 """Return a code object"""
242 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000243
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000244 def mangle(self, name):
245 if self.class_name is not None:
246 return misc.mangle(name, self.class_name)
247 else:
248 return name
249
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000250 def parseSymbols(self, tree):
251 s = symbols.SymbolVisitor()
252 walk(tree, s)
253 return s.scopes
254
255 def get_module(self):
256 raise RuntimeError, "should be implemented by subclasses"
257
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000258 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000259
Jeremy Hylton40245602000-02-08 21:15:48 +0000260 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000261 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000262
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000263 def storeName(self, name):
264 self._nameOp('STORE', name)
265
266 def loadName(self, name):
267 self._nameOp('LOAD', name)
268
269 def delName(self, name):
270 self._nameOp('DELETE', name)
271
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000272 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000273 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000274 scope = self.scope.check_name(name)
275 if scope == SC_LOCAL:
276 if not self.optimized:
277 self.emit(prefix + '_NAME', name)
278 else:
279 self.emit(prefix + '_FAST', name)
280 elif scope == SC_GLOBAL:
281 if not self.optimized:
282 self.emit(prefix + '_NAME', name)
283 else:
284 self.emit(prefix + '_GLOBAL', name)
285 elif scope == SC_FREE or scope == SC_CELL:
286 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000287 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000288 raise RuntimeError, "unsupported scope for var %s: %d" % \
289 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000290
Jeremy Hylton13d70942001-04-12 21:04:43 +0000291 def _implicitNameOp(self, prefix, name):
292 """Emit name ops for names generated implicitly by for loops
293
294 The interpreter generates names that start with a period or
295 dollar sign. The symbol table ignores these names because
296 they aren't present in the program text.
297 """
298 if self.optimized:
299 self.emit(prefix + '_FAST', name)
300 else:
301 self.emit(prefix + '_NAME', name)
302
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000303 # The set_lineno() function and the explicit emit() calls for
304 # SET_LINENO below are only used to generate the line number table.
305 # As of Python 2.3, the interpreter does not have a SET_LINENO
306 # instruction. pyassem treats SET_LINENO opcodes as a special case.
307
308 def set_lineno(self, node, force=False):
309 """Emit SET_LINENO if necessary.
310
311 The instruction is considered necessary if the node has a
312 lineno attribute and it is different than the last lineno
313 emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000314
315 Returns true if SET_LINENO was emitted.
316
317 There are no rules for when an AST node should have a lineno
318 attribute. The transformer and AST code need to be reviewed
319 and a consistent policy implemented and documented. Until
320 then, this method works around missing line numbers.
321 """
322 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000323 if lineno is not None and (lineno != self.last_lineno
324 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000325 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000326 self.last_lineno = lineno
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000327 return True
328 return False
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000329
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000330 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000331 # code objects. They use class attributes to determine what
332 # specialized code generators to use.
333
334 NameFinder = LocalNameFinder
335 FunctionGen = None
336 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000337
338 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000339 self.scopes = self.parseSymbols(node)
340 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000341 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000342 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000343 self.emit('LOAD_CONST', node.doc)
344 self.storeName('__doc__')
345 lnf = walk(node.node, self.NameFinder(), verbose=0)
346 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000347 self.visit(node.node)
348 self.emit('LOAD_CONST', None)
349 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000350
Barry Warsaw52acb492001-12-21 20:04:22 +0000351 def visitExpression(self, node):
352 self.set_lineno(node)
353 self.scopes = self.parseSymbols(node)
354 self.scope = self.scopes[node]
355 self.visit(node.node)
356 self.emit('RETURN_VALUE')
357
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000358 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000359 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000360 if node.doc:
361 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000362 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000363
364 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000365 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000366
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000367 def _visitFuncOrLambda(self, node, isLambda=0):
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000368 if not isLambda and node.decorators:
Michael W. Hudson0ccff072004-08-17 17:29:16 +0000369 for decorator in node.decorators.nodes:
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000370 self.visit(decorator)
371 ndecorators = len(node.decorators.nodes)
372 else:
373 ndecorators = 0
Tim Petersa45cacf2004-08-20 03:47:14 +0000374
Jeremy Hylton37c93512001-09-17 18:03:55 +0000375 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000376 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000377 walk(node.code, gen)
378 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000379 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000380 for default in node.defaults:
381 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000382 frees = gen.scope.get_free_vars()
383 if frees:
384 for name in frees:
385 self.emit('LOAD_CLOSURE', name)
386 self.emit('LOAD_CONST', gen)
387 self.emit('MAKE_CLOSURE', len(node.defaults))
388 else:
389 self.emit('LOAD_CONST', gen)
390 self.emit('MAKE_FUNCTION', len(node.defaults))
Tim Peters6db15d72004-08-04 02:36:18 +0000391
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000392 for i in range(ndecorators):
393 self.emit('CALL_FUNCTION', 1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000394
395 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000396 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000397 self.get_module())
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000398 walk(node.code, gen)
399 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000400 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000401 self.emit('LOAD_CONST', node.name)
402 for base in node.bases:
403 self.visit(base)
404 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000405 frees = gen.scope.get_free_vars()
406 for name in frees:
407 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000408 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000409 if frees:
410 self.emit('MAKE_CLOSURE', 0)
411 else:
412 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000413 self.emit('CALL_FUNCTION', 0)
414 self.emit('BUILD_CLASS')
415 self.storeName(node.name)
416
417 # The rest are standard visitor methods
418
419 # The next few implement control-flow statements
420
421 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000422 end = self.newBlock()
423 numtests = len(node.tests)
424 for i in range(numtests):
425 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000426 if is_constant_false(test):
427 # XXX will need to check generator stuff here
428 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000429 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000430 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000431 nextTest = self.newBlock()
432 self.emit('JUMP_IF_FALSE', nextTest)
433 self.nextBlock()
434 self.emit('POP_TOP')
435 self.visit(suite)
436 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000437 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000438 self.emit('POP_TOP')
439 if node.else_:
440 self.visit(node.else_)
441 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000442
443 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000444 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000445
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000446 loop = self.newBlock()
447 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000448
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000449 after = self.newBlock()
450 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000451
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000452 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000453 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000454
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000455 self.set_lineno(node, force=True)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000456 self.visit(node.test)
457 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000458
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000459 self.nextBlock()
460 self.emit('POP_TOP')
461 self.visit(node.body)
462 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000463
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000464 self.startBlock(else_) # or just the POPs if not else clause
465 self.emit('POP_TOP')
466 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000467 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000468 if node.else_:
469 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000470 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000471
472 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000473 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000474 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000475 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000476 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000477
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000478 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000479 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000480 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000481 self.emit('GET_ITER')
482
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000483 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000484 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000485 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000486 self.visit(node.assign)
487 self.visit(node.body)
488 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000489 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000490 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000491 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000492 if node.else_:
493 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000494 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000495
496 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000497 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000498 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000499 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000500 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000501 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000502
503 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000504 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000505 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000506 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000507 kind, block = self.setups.top()
508 if kind == LOOP:
509 self.set_lineno(node)
510 self.emit('JUMP_ABSOLUTE', block)
511 self.nextBlock()
512 elif kind == EXCEPT or kind == TRY_FINALLY:
513 self.set_lineno(node)
514 # find the block that starts the loop
515 top = len(self.setups)
516 while top > 0:
517 top = top - 1
518 kind, loop_block = self.setups[top]
519 if kind == LOOP:
520 break
521 if kind != LOOP:
522 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000523 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000524 self.emit('CONTINUE_LOOP', loop_block)
525 self.nextBlock()
526 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000527 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000528 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000529
530 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000531 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000532 for child in node.nodes[:-1]:
533 self.visit(child)
534 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000535 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000536 self.emit('POP_TOP')
537 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000538 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000539
540 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000541 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000542
543 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000544 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000545
546 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000547 self.visit(node.expr)
548 cleanup = self.newBlock()
549 for op, code in node.ops[:-1]:
550 self.visit(code)
551 self.emit('DUP_TOP')
552 self.emit('ROT_THREE')
553 self.emit('COMPARE_OP', op)
554 self.emit('JUMP_IF_FALSE', cleanup)
555 self.nextBlock()
556 self.emit('POP_TOP')
557 # now do the last comparison
558 if node.ops:
559 op, code = node.ops[-1]
560 self.visit(code)
561 self.emit('COMPARE_OP', op)
562 if len(node.ops) > 1:
563 end = self.newBlock()
564 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000565 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000566 self.emit('ROT_TWO')
567 self.emit('POP_TOP')
568 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000569
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000570 # list comprehensions
571 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000572
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000573 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000574 self.set_lineno(node)
575 # setup list
576 append = "$append%d" % self.__list_count
577 self.__list_count = self.__list_count + 1
578 self.emit('BUILD_LIST', 0)
579 self.emit('DUP_TOP')
580 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000581 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000582
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000583 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000584 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000585 start, anchor = self.visit(for_)
586 cont = None
587 for if_ in for_.ifs:
588 if cont is None:
589 cont = self.newBlock()
590 self.visit(if_, cont)
591 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000592
Jeremy Hylton13d70942001-04-12 21:04:43 +0000593 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000594 self.visit(node.expr)
595 self.emit('CALL_FUNCTION', 1)
596 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000597
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000598 for start, cont, anchor in stack:
599 if cont:
600 skip_one = self.newBlock()
601 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000602 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000603 self.emit('POP_TOP')
604 self.nextBlock(skip_one)
605 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000606 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000607 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000608
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000609 self.__list_count = self.__list_count - 1
610
611 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000612 start = self.newBlock()
613 anchor = self.newBlock()
614
615 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000616 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000617 self.nextBlock(start)
Jeremy Hylton18565412002-12-31 18:26:17 +0000618 self.set_lineno(node, force=True)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000619 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000620 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000621 self.visit(node.assign)
622 return start, anchor
623
624 def visitListCompIf(self, node, branch):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000625 self.set_lineno(node, force=True)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000626 self.visit(node.test)
627 self.emit('JUMP_IF_FALSE', branch)
628 self.newBlock()
629 self.emit('POP_TOP')
630
Raymond Hettinger354433a2004-05-19 08:20:33 +0000631 def visitGenExpr(self, node):
632 gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
633 self.get_module())
634 walk(node.code, gen)
635 gen.finish()
636 self.set_lineno(node)
637 frees = gen.scope.get_free_vars()
638 if frees:
639 for name in frees:
640 self.emit('LOAD_CLOSURE', name)
641 self.emit('LOAD_CONST', gen)
642 self.emit('MAKE_CLOSURE', 0)
643 else:
644 self.emit('LOAD_CONST', gen)
645 self.emit('MAKE_FUNCTION', 0)
646
647 # precomputation of outmost iterable
648 self.visit(node.code.quals[0].iter)
649 self.emit('GET_ITER')
650 self.emit('CALL_FUNCTION', 1)
651
652 def visitGenExprInner(self, node):
653 self.set_lineno(node)
654 # setup list
655
656 stack = []
657 for i, for_ in zip(range(len(node.quals)), node.quals):
658 start, anchor = self.visit(for_)
659 cont = None
660 for if_ in for_.ifs:
661 if cont is None:
662 cont = self.newBlock()
663 self.visit(if_, cont)
664 stack.insert(0, (start, cont, anchor))
665
666 self.visit(node.expr)
667 self.emit('YIELD_VALUE')
668
669 for start, cont, anchor in stack:
670 if cont:
671 skip_one = self.newBlock()
672 self.emit('JUMP_FORWARD', skip_one)
673 self.startBlock(cont)
674 self.emit('POP_TOP')
675 self.nextBlock(skip_one)
676 self.emit('JUMP_ABSOLUTE', start)
677 self.startBlock(anchor)
678 self.emit('LOAD_CONST', None)
679
680 def visitGenExprFor(self, node):
681 start = self.newBlock()
682 anchor = self.newBlock()
Tim Peters4e0e1b62004-07-07 20:54:48 +0000683
Raymond Hettinger354433a2004-05-19 08:20:33 +0000684 if node.is_outmost:
685 self.loadName('[outmost-iterable]')
686 else:
687 self.visit(node.iter)
688 self.emit('GET_ITER')
689
690 self.nextBlock(start)
691 self.set_lineno(node, force=True)
692 self.emit('FOR_ITER', anchor)
693 self.nextBlock()
694 self.visit(node.assign)
695 return start, anchor
696
697 def visitGenExprIf(self, node, branch):
698 self.set_lineno(node, force=True)
699 self.visit(node.test)
700 self.emit('JUMP_IF_FALSE', branch)
701 self.newBlock()
702 self.emit('POP_TOP')
703
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000704 # exception related
705
706 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000707 # XXX would be interesting to implement this via a
708 # transformation of the AST before this stage
Jeremy Hylton2876f5a2004-08-07 19:21:56 +0000709 if __debug__:
710 end = self.newBlock()
711 self.set_lineno(node)
712 # XXX AssertionError appears to be special case -- it is always
713 # loaded as a global even if there is a local name. I guess this
714 # is a sort of renaming op.
715 self.nextBlock()
716 self.visit(node.test)
717 self.emit('JUMP_IF_TRUE', end)
718 self.nextBlock()
719 self.emit('POP_TOP')
720 self.emit('LOAD_GLOBAL', 'AssertionError')
721 if node.fail:
722 self.visit(node.fail)
723 self.emit('RAISE_VARARGS', 2)
724 else:
725 self.emit('RAISE_VARARGS', 1)
726 self.nextBlock(end)
727 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000728
729 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000730 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000731 n = 0
732 if node.expr1:
733 self.visit(node.expr1)
734 n = n + 1
735 if node.expr2:
736 self.visit(node.expr2)
737 n = n + 1
738 if node.expr3:
739 self.visit(node.expr3)
740 n = n + 1
741 self.emit('RAISE_VARARGS', n)
742
743 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000744 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000745 handlers = self.newBlock()
746 end = self.newBlock()
747 if node.else_:
748 lElse = self.newBlock()
749 else:
750 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000751 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000752 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000753 self.nextBlock(body)
754 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000755 self.visit(node.body)
756 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000757 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000758 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000759 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000760
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000761 last = len(node.handlers) - 1
762 for i in range(len(node.handlers)):
763 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000764 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000765 if expr:
766 self.emit('DUP_TOP')
767 self.visit(expr)
768 self.emit('COMPARE_OP', 'exception match')
769 next = self.newBlock()
770 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000771 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000772 self.emit('POP_TOP')
773 self.emit('POP_TOP')
774 if target:
775 self.visit(target)
776 else:
777 self.emit('POP_TOP')
778 self.emit('POP_TOP')
779 self.visit(body)
780 self.emit('JUMP_FORWARD', end)
781 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000782 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000783 else:
784 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000785 if expr: # XXX
786 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000787 self.emit('END_FINALLY')
788 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000789 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000790 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000791 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000792
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000793 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000794 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000795 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000796 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000797 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000798 self.nextBlock(body)
799 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000800 self.visit(node.body)
801 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000802 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000803 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000804 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000805 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000806 self.visit(node.final)
807 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000808 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000809
Guido van Rossum7ad94f02006-02-28 00:32:16 +0000810 __with_count = 0
811
812 def visitWith(self, node):
813 body = self.newBlock()
814 final = self.newBlock()
815 exitvar = "$exit%d" % self.__with_count
816 valuevar = "$value%d" % self.__with_count
817 self.__with_count += 1
818 self.set_lineno(node)
819 self.visit(node.expr)
820 self.emit('LOAD_ATTR', '__context__')
821 self.emit('CALL_FUNCTION', 0)
822 self.emit('DUP_TOP')
823 self.emit('LOAD_ATTR', '__exit__')
824 self._implicitNameOp('STORE', exitvar)
825 self.emit('LOAD_ATTR', '__enter__')
826 self.emit('CALL_FUNCTION', 0)
827 if node.vars is None:
828 self.emit('POP_TOP')
829 else:
830 self._implicitNameOp('STORE', valuevar)
831 self.emit('SETUP_FINALLY', final)
832 self.nextBlock(body)
833 self.setups.push((TRY_FINALLY, body))
834 if node.vars is not None:
835 self._implicitNameOp('LOAD', valuevar)
836 self._implicitNameOp('DELETE', valuevar)
837 self.visit(node.vars)
838 self.visit(node.body)
839 self.emit('POP_BLOCK')
840 self.setups.pop()
841 self.emit('LOAD_CONST', None)
842 self.nextBlock(final)
843 self.setups.push((END_FINALLY, final))
844 self.emit('WITH_CLEANUP')
845 self.emit('CALL_FUNCTION', 3)
846 self.emit('POP_TOP')
847 self.emit('END_FINALLY')
848 self.setups.pop()
849 self.__with_count -= 1
850
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000851 # misc
852
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000853 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000854 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000855 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000856 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000857
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000858 def visitConst(self, node):
859 self.emit('LOAD_CONST', node.value)
860
861 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000862 self.emit('LOAD_CONST', node.name)
863 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000864
865 def visitGlobal(self, node):
866 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000867 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000868
869 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000870 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000871 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000872
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000873 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000874 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000875
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000876 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000877 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000878 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000879 if VERSION > 1:
880 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000881 self.emit('IMPORT_NAME', name)
Neal Norwitza312c3a2002-06-06 18:30:10 +0000882 mod = name.split(".")[0]
Michael W. Hudson896e5162003-06-27 12:32:39 +0000883 if alias:
884 self._resolveDots(name)
885 self.storeName(alias)
886 else:
887 self.storeName(mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000888
889 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000890 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000891 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000892 if VERSION > 1:
893 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000894 self.emit('IMPORT_NAME', node.modname)
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:
897 if name == '*':
898 self.namespace = 0
899 self.emit('IMPORT_STAR')
900 # There can only be one name w/ from ... import *
901 assert len(node.names) == 1
902 return
903 else:
904 self.emit('IMPORT_FROM', name)
905 self._resolveDots(name)
906 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000907 else:
908 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000909 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000910
Jeremy Hylton20516082000-09-01 20:33:26 +0000911 def _resolveDots(self, name):
Neal Norwitza312c3a2002-06-06 18:30:10 +0000912 elts = name.split(".")
Jeremy Hylton20516082000-09-01 20:33:26 +0000913 if len(elts) == 1:
914 return
915 for elt in elts[1:]:
916 self.emit('LOAD_ATTR', elt)
917
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000918 def visitGetattr(self, node):
919 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000920 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000921
922 # next five implement assignments
923
924 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000925 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000926 self.visit(node.expr)
927 dups = len(node.nodes) - 1
928 for i in range(len(node.nodes)):
929 elt = node.nodes[i]
930 if i < dups:
931 self.emit('DUP_TOP')
932 if isinstance(elt, ast.Node):
933 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000934
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000935 def visitAssName(self, node):
936 if node.flags == 'OP_ASSIGN':
937 self.storeName(node.name)
938 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000939 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000940 self.delName(node.name)
941 else:
942 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000943
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000944 def visitAssAttr(self, node):
945 self.visit(node.expr)
946 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000947 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000948 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000949 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000950 else:
951 print "warning: unexpected flags:", node.flags
952 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000953
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000954 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000955 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000956 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000957 for child in node.nodes:
958 self.visit(child)
959
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000960 if VERSION > 1:
961 visitAssTuple = _visitAssSequence
962 visitAssList = _visitAssSequence
963 else:
964 def visitAssTuple(self, node):
965 self._visitAssSequence(node, 'UNPACK_TUPLE')
966
967 def visitAssList(self, node):
968 self._visitAssSequence(node, 'UNPACK_LIST')
969
970 # augmented assignment
971
972 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000973 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000974 aug_node = wrap_aug(node.node)
975 self.visit(aug_node, "load")
976 self.visit(node.expr)
977 self.emit(self._augmented_opcode[node.op])
978 self.visit(aug_node, "store")
979
980 _augmented_opcode = {
981 '+=' : 'INPLACE_ADD',
982 '-=' : 'INPLACE_SUBTRACT',
983 '*=' : 'INPLACE_MULTIPLY',
984 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000985 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000986 '%=' : 'INPLACE_MODULO',
987 '**=': 'INPLACE_POWER',
988 '>>=': 'INPLACE_RSHIFT',
989 '<<=': 'INPLACE_LSHIFT',
990 '&=' : 'INPLACE_AND',
991 '^=' : 'INPLACE_XOR',
992 '|=' : 'INPLACE_OR',
993 }
994
995 def visitAugName(self, node, mode):
996 if mode == "load":
997 self.loadName(node.name)
998 elif mode == "store":
999 self.storeName(node.name)
1000
1001 def visitAugGetattr(self, node, mode):
1002 if mode == "load":
1003 self.visit(node.expr)
1004 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001005 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001006 elif mode == "store":
1007 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001008 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001009
1010 def visitAugSlice(self, node, mode):
1011 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001012 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001013 elif mode == "store":
1014 slice = 0
1015 if node.lower:
1016 slice = slice | 1
1017 if node.upper:
1018 slice = slice | 2
1019 if slice == 0:
1020 self.emit('ROT_TWO')
1021 elif slice == 3:
1022 self.emit('ROT_FOUR')
1023 else:
1024 self.emit('ROT_THREE')
1025 self.emit('STORE_SLICE+%d' % slice)
1026
1027 def visitAugSubscript(self, node, mode):
1028 if len(node.subs) > 1:
1029 raise SyntaxError, "augmented assignment to tuple is not possible"
1030 if mode == "load":
1031 self.visitSubscript(node, 1)
1032 elif mode == "store":
1033 self.emit('ROT_THREE')
1034 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001035
1036 def visitExec(self, node):
1037 self.visit(node.expr)
1038 if node.locals is None:
1039 self.emit('LOAD_CONST', None)
1040 else:
1041 self.visit(node.locals)
1042 if node.globals is None:
1043 self.emit('DUP_TOP')
1044 else:
1045 self.visit(node.globals)
1046 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +00001047
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001048 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +00001049 pos = 0
1050 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001051 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001052 self.visit(node.node)
1053 for arg in node.args:
1054 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +00001055 if isinstance(arg, ast.Keyword):
1056 kw = kw + 1
1057 else:
1058 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +00001059 if node.star_args is not None:
1060 self.visit(node.star_args)
1061 if node.dstar_args is not None:
1062 self.visit(node.dstar_args)
1063 have_star = node.star_args is not None
1064 have_dstar = node.dstar_args is not None
1065 opcode = callfunc_opcode_info[have_star, have_dstar]
1066 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001067
Jeremy Hylton2afff322001-08-27 21:51:52 +00001068 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001069 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001070 if node.dest:
1071 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001072 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001073 if node.dest:
1074 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001075 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001076 if node.dest:
1077 self.emit('ROT_TWO')
1078 self.emit('PRINT_ITEM_TO')
1079 else:
1080 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +00001081 if node.dest and not newline:
1082 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001083
1084 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +00001085 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001086 if node.dest:
1087 self.emit('PRINT_NEWLINE_TO')
1088 else:
1089 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001090
1091 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001092 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001093 self.visit(node.value)
1094 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +00001095
Jeremy Hylton1048aa92001-09-14 23:17:55 +00001096 def visitYield(self, node):
1097 self.set_lineno(node)
1098 self.visit(node.value)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001099 self.emit('YIELD_VALUE')
Jeremy Hylton1048aa92001-09-14 23:17:55 +00001100
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001101 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001102
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001103 def visitSlice(self, node, aug_flag=None):
1104 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001105 self.visit(node.expr)
1106 slice = 0
1107 if node.lower:
1108 self.visit(node.lower)
1109 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001110 if node.upper:
1111 self.visit(node.upper)
1112 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001113 if aug_flag:
1114 if slice == 0:
1115 self.emit('DUP_TOP')
1116 elif slice == 3:
1117 self.emit('DUP_TOPX', 3)
1118 else:
1119 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001120 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001121 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001122 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001123 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001124 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001125 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001126 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001127 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001128 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001129
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001130 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001131 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001132 for sub in node.subs:
1133 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001134 if aug_flag:
1135 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001136 if len(node.subs) > 1:
1137 self.emit('BUILD_TUPLE', len(node.subs))
1138 if node.flags == 'OP_APPLY':
1139 self.emit('BINARY_SUBSCR')
1140 elif node.flags == 'OP_ASSIGN':
1141 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001142 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001143 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001144
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001145 # binary ops
1146
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001147 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001148 self.visit(node.left)
1149 self.visit(node.right)
1150 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001151
1152 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001153 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001154
1155 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001156 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001157
1158 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001159 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001160
1161 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001162 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001163
Jeremy Hylton94afe322001-08-29 18:14:39 +00001164 def visitFloorDiv(self, node):
1165 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1166
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001167 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001168 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001169
Jeremy Hylton126960b2000-02-14 21:33:10 +00001170 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001171 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001172
1173 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001174 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001175
1176 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001177 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001178
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001179 # unary ops
1180
1181 def unaryOp(self, node, op):
1182 self.visit(node.expr)
1183 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001184
Jeremy Hylton126960b2000-02-14 21:33:10 +00001185 def visitInvert(self, node):
1186 return self.unaryOp(node, 'UNARY_INVERT')
1187
Jeremy Hylton40245602000-02-08 21:15:48 +00001188 def visitUnarySub(self, node):
1189 return self.unaryOp(node, 'UNARY_NEGATIVE')
1190
1191 def visitUnaryAdd(self, node):
1192 return self.unaryOp(node, 'UNARY_POSITIVE')
1193
1194 def visitUnaryInvert(self, node):
1195 return self.unaryOp(node, 'UNARY_INVERT')
1196
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001197 def visitNot(self, node):
1198 return self.unaryOp(node, 'UNARY_NOT')
1199
Jeremy Hylton40245602000-02-08 21:15:48 +00001200 def visitBackquote(self, node):
1201 return self.unaryOp(node, 'UNARY_CONVERT')
1202
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001203 # bit ops
1204
Jeremy Hyltona5058122000-02-14 14:14:29 +00001205 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001206 self.visit(nodes[0])
1207 for node in nodes[1:]:
1208 self.visit(node)
1209 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001210
1211 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001212 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001213
1214 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001215 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001216
1217 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001218 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001219
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001220 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001221
Jeremy Hyltona5058122000-02-14 14:14:29 +00001222 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001223 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001224
Jeremy Hylton40245602000-02-08 21:15:48 +00001225 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001226 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001227 for elt in node.nodes:
1228 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001229 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001230
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001231 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001232 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001233 for elt in node.nodes:
1234 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001235 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001236
1237 def visitSliceobj(self, node):
1238 for child in node.nodes:
1239 self.visit(child)
1240 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001241
Jeremy Hyltona5058122000-02-14 14:14:29 +00001242 def visitDict(self, node):
Jeremy Hylton18565412002-12-31 18:26:17 +00001243 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001244 self.emit('BUILD_MAP', 0)
1245 for k, v in node.items:
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001246 self.emit('DUP_TOP')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001247 self.visit(k)
Gustavo Niemeyer78429a62002-12-16 13:54:02 +00001248 self.visit(v)
1249 self.emit('ROT_THREE')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001250 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001251
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001252class NestedScopeMixin:
1253 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001254 def initClass(self):
1255 self.__class__.NameFinder = LocalNameFinder
1256 self.__class__.FunctionGen = FunctionCodeGenerator
1257 self.__class__.ClassGen = ClassCodeGenerator
1258
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001259class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001260 __super_init = CodeGenerator.__init__
1261
1262 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001263
Jeremy Hylton37c93512001-09-17 18:03:55 +00001264 def __init__(self, tree):
1265 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001266 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001267 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001268 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001269
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001270 def get_module(self):
1271 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001272
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001273class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1274 __super_init = CodeGenerator.__init__
1275
1276 scopes = None
1277 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001278
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001279 def __init__(self, tree):
1280 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1281 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001282 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001283
1284 def get_module(self):
1285 return self
1286
1287class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1288
1289 __super_init = CodeGenerator.__init__
1290
1291 scopes = None
1292 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001293
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001294 def __init__(self, tree):
1295 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1296 self.__super_init()
1297 self.set_lineno(tree)
1298 walk(tree, self)
1299 self.emit('RETURN_VALUE')
1300
1301 def get_module(self):
1302 return self
Tim Peterse4418602002-02-16 07:34:19 +00001303
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001304 def visitDiscard(self, node):
1305 # XXX Discard means it's an expression. Perhaps this is a bad
1306 # name.
1307 self.visit(node.expr)
1308 self.emit('PRINT_EXPR')
1309
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001310class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001311 optimized = 1
1312 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001313
Jeremy Hylton37c93512001-09-17 18:03:55 +00001314 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001315 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001316 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001317 if isLambda:
1318 klass = FunctionCodeGenerator
1319 name = "<lambda.%d>" % klass.lambdaCount
1320 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001321 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001322 name = func.name
Raymond Hettinger354433a2004-05-19 08:20:33 +00001323
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001324 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001325 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1326 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001327 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001328 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001329
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001330 if not isLambda and func.doc:
1331 self.setDocstring(func.doc)
1332
Jeremy Hylton2afff322001-08-27 21:51:52 +00001333 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001334 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001335 if func.varargs:
1336 self.graph.setFlag(CO_VARARGS)
1337 if func.kwargs:
1338 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001339 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001340 if hasTupleArg:
1341 self.generateArgUnpack(func.argnames)
1342
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001343 def get_module(self):
1344 return self.module
1345
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001346 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001347 self.graph.startExitBlock()
1348 if not self.isLambda:
1349 self.emit('LOAD_CONST', None)
1350 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001351
1352 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001353 for i in range(len(args)):
1354 arg = args[i]
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001355 if isinstance(arg, tuple):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001356 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001357 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001358
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001359 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001360 if VERSION > 1:
1361 self.emit('UNPACK_SEQUENCE', len(tup))
1362 else:
1363 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001364 for elt in tup:
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001365 if isinstance(elt, tuple):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001366 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001367 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001368 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001369
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001370 unpackTuple = unpackSequence
1371
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001372class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001373 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001374 super_init = CodeGenerator.__init__ # call be other init
1375 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001376
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001377 __super_init = AbstractFunctionCode.__init__
1378
Jeremy Hylton37c93512001-09-17 18:03:55 +00001379 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001380 self.scopes = scopes
1381 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001382 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001383 self.graph.setFreeVars(self.scope.get_free_vars())
1384 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001385 if self.scope.generator is not None:
1386 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001387
Raymond Hettinger354433a2004-05-19 08:20:33 +00001388class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
1389 CodeGenerator):
1390 super_init = CodeGenerator.__init__ # call be other init
1391 scopes = None
1392
1393 __super_init = AbstractFunctionCode.__init__
1394
1395 def __init__(self, gexp, scopes, class_name, mod):
1396 self.scopes = scopes
1397 self.scope = scopes[gexp]
1398 self.__super_init(gexp, scopes, 1, class_name, mod)
1399 self.graph.setFreeVars(self.scope.get_free_vars())
1400 self.graph.setCellVars(self.scope.get_cell_vars())
1401 self.graph.setFlag(CO_GENERATOR)
1402
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001403class AbstractClassCode:
1404
Jeremy Hylton37c93512001-09-17 18:03:55 +00001405 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001406 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001407 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001408 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001409 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001410 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001411 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001412 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001413 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001414 if klass.doc:
1415 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001416
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001417 def get_module(self):
1418 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001419
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001420 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001421 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001422 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001423 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001424
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001425class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001426 super_init = CodeGenerator.__init__
1427 scopes = None
1428
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001429 __super_init = AbstractClassCode.__init__
1430
Jeremy Hylton37c93512001-09-17 18:03:55 +00001431 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001432 self.scopes = scopes
1433 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001434 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001435 self.graph.setFreeVars(self.scope.get_free_vars())
1436 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001437 self.set_lineno(klass)
1438 self.emit("LOAD_GLOBAL", "__name__")
1439 self.storeName("__module__")
1440 if klass.doc:
1441 self.emit("LOAD_CONST", klass.doc)
1442 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001443
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001444def generateArgList(arglist):
1445 """Generate an arg list marking TupleArgs"""
1446 args = []
1447 extra = []
1448 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001449 for i in range(len(arglist)):
1450 elt = arglist[i]
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001451 if isinstance(elt, str):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001452 args.append(elt)
Neal Norwitzd752f7d2005-11-25 03:17:59 +00001453 elif isinstance(elt, tuple):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001454 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001455 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001456 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001457 else:
1458 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001459 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001460
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001461def findOp(node):
1462 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1463 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001464 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001465 return v.op
1466
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001467class OpFinder:
1468 def __init__(self):
1469 self.op = None
1470 def visitAssName(self, node):
1471 if self.op is None:
1472 self.op = node.flags
1473 elif self.op != node.flags:
1474 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001475 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001476 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001477
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001478class Delegator:
1479 """Base class to support delegation for augmented assignment nodes
1480
1481 To generator code for augmented assignments, we use the following
1482 wrapper classes. In visitAugAssign, the left-hand expression node
1483 is visited twice. The first time the visit uses the normal method
1484 for that node . The second time the visit uses a different method
1485 that generates the appropriate code to perform the assignment.
1486 These delegator classes wrap the original AST nodes in order to
1487 support the variant visit methods.
1488 """
1489 def __init__(self, obj):
1490 self.obj = obj
1491
1492 def __getattr__(self, attr):
1493 return getattr(self.obj, attr)
1494
1495class AugGetattr(Delegator):
1496 pass
1497
1498class AugName(Delegator):
1499 pass
1500
1501class AugSlice(Delegator):
1502 pass
1503
1504class AugSubscript(Delegator):
1505 pass
1506
1507wrapper = {
1508 ast.Getattr: AugGetattr,
1509 ast.Name: AugName,
1510 ast.Slice: AugSlice,
1511 ast.Subscript: AugSubscript,
1512 }
1513
1514def wrap_aug(node):
1515 return wrapper[node.__class__](node)
1516
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001517if __name__ == "__main__":
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001518 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001519 compileFile(file)