blob: a6face0a796f4c23392ab90dacb16825bc4b7716 [file] [log] [blame]
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001import imp
Jeremy Hylton53187f32000-02-08 19:01:29 +00002import os
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00003import marshal
Jeremy Hylton53187f32000-02-08 19:01:29 +00004import struct
Jeremy Hylton9c048f92000-10-13 21:58:13 +00005import sys
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00006import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00007from cStringIO import StringIO
8
Jeremy Hylton37c93512001-09-17 18:03:55 +00009from compiler import ast, parse, walk, syntax
Jeremy Hylton364f9b92001-04-12 06:40:42 +000010from compiler import pyassem, misc, future, symbols
11from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
Jeremy Hylton71ebc332001-08-30 20:25:55 +000012from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000013 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000015
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000016# XXX The version-specific code can go, since this code only works with 2.x.
Jeremy Hylton9c048f92000-10-13 21:58:13 +000017# Do we have Python 1.x or Python 2.x?
18try:
19 VERSION = sys.version_info[0]
20except AttributeError:
21 VERSION = 1
22
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000023callfunc_opcode_info = {
24 # (Have *args, Have **args) : opcode
25 (0,0) : "CALL_FUNCTION",
26 (1,0) : "CALL_FUNCTION_VAR",
27 (0,1) : "CALL_FUNCTION_KW",
28 (1,1) : "CALL_FUNCTION_VAR_KW",
29}
30
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000031LOOP = 1
32EXCEPT = 2
33TRY_FINALLY = 3
34END_FINALLY = 4
35
Jeremy Hylton9dca3642001-09-17 21:02:51 +000036def compileFile(filename, display=0):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000037 f = open(filename, 'U')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000038 buf = f.read()
39 f.close()
40 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000041 try:
42 mod.compile(display)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000043 except SyntaxError:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000044 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000045 else:
46 f = open(filename + "c", "wb")
47 mod.dump(f)
48 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000049
Jeremy Hylton9dca3642001-09-17 21:02:51 +000050def compile(source, filename, mode, flags=None, dont_inherit=None):
51 """Replacement for builtin compile() function"""
52 if flags is not None or dont_inherit is not None:
53 raise RuntimeError, "not implemented yet"
Tim Peterse0c446b2001-10-18 21:57:37 +000054
Jeremy Hylton9dca3642001-09-17 21:02:51 +000055 if mode == "single":
56 gen = Interactive(source, filename)
57 elif mode == "exec":
58 gen = Module(source, filename)
59 elif mode == "eval":
60 gen = Expression(source, filename)
61 else:
62 raise ValueError("compile() 3rd arg must be 'exec' or "
63 "'eval' or 'single'")
64 gen.compile()
65 return gen.code
66
67class AbstractCompileMode:
68
69 mode = None # defined by subclass
70
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000071 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000072 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000073 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000074 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000075
Jeremy Hylton9dca3642001-09-17 21:02:51 +000076 def _get_tree(self):
77 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000078 misc.set_filename(self.filename, tree)
79 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000080 return tree
81
82 def compile(self):
83 pass # implemented by subclass
84
85 def getCode(self):
86 return self.code
87
88class Expression(AbstractCompileMode):
89
90 mode = "eval"
91
92 def compile(self):
93 tree = self._get_tree()
94 gen = ExpressionCodeGenerator(tree)
95 self.code = gen.getCode()
96
97class Interactive(AbstractCompileMode):
98
99 mode = "single"
100
101 def compile(self):
102 tree = self._get_tree()
103 gen = InteractiveCodeGenerator(tree)
104 self.code = gen.getCode()
105
106class Module(AbstractCompileMode):
107
108 mode = "exec"
109
110 def compile(self, display=0):
111 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000112 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000113 if display:
114 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000115 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000116 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000117
118 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000119 f.write(self.getPycHeader())
120 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000121
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000122 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000123
124 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000125 # compile.c uses marshal to write a long directly, with
126 # calling the interface that would also generate a 1-byte code
127 # to indicate the type of the value. simplest way to get the
128 # same effect is to call marshal and then skip the code.
Neal Norwitza312c3a2002-06-06 18:30:10 +0000129 mtime = os.path.getmtime(self.filename)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000130 mtime = struct.pack('<i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000131 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000132
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000133class LocalNameFinder:
134 """Find local names in scope"""
135 def __init__(self, names=()):
136 self.names = misc.Set()
137 self.globals = misc.Set()
138 for name in names:
139 self.names.add(name)
140
141 # XXX list comprehensions and for loops
142
143 def getLocals(self):
144 for elt in self.globals.elements():
145 if self.names.has_elt(elt):
146 self.names.remove(elt)
147 return self.names
148
149 def visitDict(self, node):
150 pass
151
152 def visitGlobal(self, node):
153 for name in node.names:
154 self.globals.add(name)
155
156 def visitFunction(self, node):
157 self.names.add(node.name)
158
159 def visitLambda(self, node):
160 pass
161
162 def visitImport(self, node):
163 for name, alias in node.names:
164 self.names.add(alias or name)
165
166 def visitFrom(self, node):
167 for name, alias in node.names:
168 self.names.add(alias or name)
169
170 def visitClass(self, node):
171 self.names.add(node.name)
172
173 def visitAssName(self, node):
174 self.names.add(node.name)
175
Jeremy Hylton2afff322001-08-27 21:51:52 +0000176def is_constant_false(node):
177 if isinstance(node, ast.Const):
178 if not node.value:
179 return 1
180 return 0
181
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000182class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000183 """Defines basic code generator for Python bytecode
184
185 This class is an abstract base class. Concrete subclasses must
186 define an __init__() that defines self.graph and then calls the
187 __init__() defined in this class.
188
189 The concrete class must also define the class attributes
190 NameFinder, FunctionGen, and ClassGen. These attributes can be
191 defined in the initClass() method, which is a hook for
192 initializing these methods after all the classes have been
Tim Peterse0c446b2001-10-18 21:57:37 +0000193 defined.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000194 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000195
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000196 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000197 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000198 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000199
Jeremy Hylton37c93512001-09-17 18:03:55 +0000200 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000201 if self.__initialized is None:
202 self.initClass()
203 self.__class__.__initialized = 1
204 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000205 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000206 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000207 self.curStack = 0
208 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000209 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000210 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000211 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000212
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000213 # XXX set flags based on future features
214 futures = self.get_module().futures
215 for feature in futures:
216 if feature == "division":
217 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000218 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000219 elif feature == "generators":
220 self.graph.setFlag(CO_GENERATOR_ALLOWED)
221
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):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000371 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000372 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000373 walk(node.code, gen)
374 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000375 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000376 for default in node.defaults:
377 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000378 frees = gen.scope.get_free_vars()
379 if frees:
380 for name in frees:
381 self.emit('LOAD_CLOSURE', name)
382 self.emit('LOAD_CONST', gen)
383 self.emit('MAKE_CLOSURE', len(node.defaults))
384 else:
385 self.emit('LOAD_CONST', gen)
386 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000387
388 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000389 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000390 self.get_module())
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000391 walk(node.code, gen)
392 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000393 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000394 self.emit('LOAD_CONST', node.name)
395 for base in node.bases:
396 self.visit(base)
397 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000398 frees = gen.scope.get_free_vars()
399 for name in frees:
400 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000401 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000402 if frees:
403 self.emit('MAKE_CLOSURE', 0)
404 else:
405 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000406 self.emit('CALL_FUNCTION', 0)
407 self.emit('BUILD_CLASS')
408 self.storeName(node.name)
409
410 # The rest are standard visitor methods
411
412 # The next few implement control-flow statements
413
414 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000415 end = self.newBlock()
416 numtests = len(node.tests)
417 for i in range(numtests):
418 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000419 if is_constant_false(test):
420 # XXX will need to check generator stuff here
421 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000422 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000423 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000424 nextTest = self.newBlock()
425 self.emit('JUMP_IF_FALSE', nextTest)
426 self.nextBlock()
427 self.emit('POP_TOP')
428 self.visit(suite)
429 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000430 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000431 self.emit('POP_TOP')
432 if node.else_:
433 self.visit(node.else_)
434 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000435
436 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000437 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000438
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000439 loop = self.newBlock()
440 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000441
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000442 after = self.newBlock()
443 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000444
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000445 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000446 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000447
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000448 self.set_lineno(node, force=True)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000449 self.visit(node.test)
450 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000451
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000452 self.nextBlock()
453 self.emit('POP_TOP')
454 self.visit(node.body)
455 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000456
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000457 self.startBlock(else_) # or just the POPs if not else clause
458 self.emit('POP_TOP')
459 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000460 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000461 if node.else_:
462 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000463 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000464
465 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000466 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000467 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000468 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000469 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000470
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000471 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000472 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000473 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000474 self.emit('GET_ITER')
475
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000476 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000477 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000478 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479 self.visit(node.assign)
480 self.visit(node.body)
481 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000482 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000484 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000485 if node.else_:
486 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000487 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000488
489 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000490 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000491 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000492 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000493 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000494 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000495
496 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000497 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000498 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000499 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000500 kind, block = self.setups.top()
501 if kind == LOOP:
502 self.set_lineno(node)
503 self.emit('JUMP_ABSOLUTE', block)
504 self.nextBlock()
505 elif kind == EXCEPT or kind == TRY_FINALLY:
506 self.set_lineno(node)
507 # find the block that starts the loop
508 top = len(self.setups)
509 while top > 0:
510 top = top - 1
511 kind, loop_block = self.setups[top]
512 if kind == LOOP:
513 break
514 if kind != LOOP:
515 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000516 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000517 self.emit('CONTINUE_LOOP', loop_block)
518 self.nextBlock()
519 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000520 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000521 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000522
523 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000524 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000525 for child in node.nodes[:-1]:
526 self.visit(child)
527 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000528 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000529 self.emit('POP_TOP')
530 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000531 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000532
533 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000534 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000535
536 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000537 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000538
539 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000540 self.visit(node.expr)
541 cleanup = self.newBlock()
542 for op, code in node.ops[:-1]:
543 self.visit(code)
544 self.emit('DUP_TOP')
545 self.emit('ROT_THREE')
546 self.emit('COMPARE_OP', op)
547 self.emit('JUMP_IF_FALSE', cleanup)
548 self.nextBlock()
549 self.emit('POP_TOP')
550 # now do the last comparison
551 if node.ops:
552 op, code = node.ops[-1]
553 self.visit(code)
554 self.emit('COMPARE_OP', op)
555 if len(node.ops) > 1:
556 end = self.newBlock()
557 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000558 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000559 self.emit('ROT_TWO')
560 self.emit('POP_TOP')
561 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000562
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000563 # list comprehensions
564 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000565
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000566 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000567 self.set_lineno(node)
568 # setup list
569 append = "$append%d" % self.__list_count
570 self.__list_count = self.__list_count + 1
571 self.emit('BUILD_LIST', 0)
572 self.emit('DUP_TOP')
573 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000574 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000575
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000576 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000577 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000578 start, anchor = self.visit(for_)
579 cont = None
580 for if_ in for_.ifs:
581 if cont is None:
582 cont = self.newBlock()
583 self.visit(if_, cont)
584 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000585
Jeremy Hylton13d70942001-04-12 21:04:43 +0000586 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000587 self.visit(node.expr)
588 self.emit('CALL_FUNCTION', 1)
589 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000590
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000591 for start, cont, anchor in stack:
592 if cont:
593 skip_one = self.newBlock()
594 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000595 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000596 self.emit('POP_TOP')
597 self.nextBlock(skip_one)
598 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000599 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000600 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000601
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000602 self.__list_count = self.__list_count - 1
603
604 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000605 start = self.newBlock()
606 anchor = self.newBlock()
607
608 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000609 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000610 self.nextBlock(start)
Jeremy Hylton18565412002-12-31 18:26:17 +0000611 self.set_lineno(node, force=True)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000612 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000613 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000614 self.visit(node.assign)
615 return start, anchor
616
617 def visitListCompIf(self, node, branch):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000618 self.set_lineno(node, force=True)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000619 self.visit(node.test)
620 self.emit('JUMP_IF_FALSE', branch)
621 self.newBlock()
622 self.emit('POP_TOP')
623
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000624 # exception related
625
626 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000627 # XXX would be interesting to implement this via a
628 # transformation of the AST before this stage
629 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000630 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000631 # XXX __debug__ and AssertionError appear to be special cases
632 # -- they are always loaded as globals even if there are local
633 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000634 self.emit('LOAD_GLOBAL', '__debug__')
635 self.emit('JUMP_IF_FALSE', end)
636 self.nextBlock()
637 self.emit('POP_TOP')
638 self.visit(node.test)
639 self.emit('JUMP_IF_TRUE', end)
640 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000641 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000642 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000643 if node.fail:
644 self.visit(node.fail)
645 self.emit('RAISE_VARARGS', 2)
646 else:
647 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000648 self.nextBlock(end)
649 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000650
651 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000652 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000653 n = 0
654 if node.expr1:
655 self.visit(node.expr1)
656 n = n + 1
657 if node.expr2:
658 self.visit(node.expr2)
659 n = n + 1
660 if node.expr3:
661 self.visit(node.expr3)
662 n = n + 1
663 self.emit('RAISE_VARARGS', n)
664
665 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000666 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000667 handlers = self.newBlock()
668 end = self.newBlock()
669 if node.else_:
670 lElse = self.newBlock()
671 else:
672 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000673 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000674 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000675 self.nextBlock(body)
676 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000677 self.visit(node.body)
678 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000679 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000680 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000681 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000682
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000683 last = len(node.handlers) - 1
684 for i in range(len(node.handlers)):
685 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000686 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000687 if expr:
688 self.emit('DUP_TOP')
689 self.visit(expr)
690 self.emit('COMPARE_OP', 'exception match')
691 next = self.newBlock()
692 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000693 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000694 self.emit('POP_TOP')
695 self.emit('POP_TOP')
696 if target:
697 self.visit(target)
698 else:
699 self.emit('POP_TOP')
700 self.emit('POP_TOP')
701 self.visit(body)
702 self.emit('JUMP_FORWARD', end)
703 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000704 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000705 else:
706 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000707 if expr: # XXX
708 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000709 self.emit('END_FINALLY')
710 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000711 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000712 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000713 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000714
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000715 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000716 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000717 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000718 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000719 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000720 self.nextBlock(body)
721 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000722 self.visit(node.body)
723 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000724 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000725 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000726 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000727 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000728 self.visit(node.final)
729 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000730 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000731
732 # misc
733
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000734 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000735 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000736 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000737 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000738
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000739 def visitConst(self, node):
740 self.emit('LOAD_CONST', node.value)
741
742 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000743 self.emit('LOAD_CONST', node.name)
744 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000745
746 def visitGlobal(self, node):
747 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000748 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000749
750 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000751 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000752 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000753
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000754 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000755 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000756
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000757 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000758 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000759 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000760 if VERSION > 1:
761 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000762 self.emit('IMPORT_NAME', name)
Neal Norwitza312c3a2002-06-06 18:30:10 +0000763 mod = name.split(".")[0]
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000764 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000765
766 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000767 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000768 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000769 if VERSION > 1:
770 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000771 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000772 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000773 if VERSION > 1:
774 if name == '*':
775 self.namespace = 0
776 self.emit('IMPORT_STAR')
777 # There can only be one name w/ from ... import *
778 assert len(node.names) == 1
779 return
780 else:
781 self.emit('IMPORT_FROM', name)
782 self._resolveDots(name)
783 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000784 else:
785 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000786 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000787
Jeremy Hylton20516082000-09-01 20:33:26 +0000788 def _resolveDots(self, name):
Neal Norwitza312c3a2002-06-06 18:30:10 +0000789 elts = name.split(".")
Jeremy Hylton20516082000-09-01 20:33:26 +0000790 if len(elts) == 1:
791 return
792 for elt in elts[1:]:
793 self.emit('LOAD_ATTR', elt)
794
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000795 def visitGetattr(self, node):
796 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000797 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000798
799 # next five implement assignments
800
801 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000802 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000803 self.visit(node.expr)
804 dups = len(node.nodes) - 1
805 for i in range(len(node.nodes)):
806 elt = node.nodes[i]
807 if i < dups:
808 self.emit('DUP_TOP')
809 if isinstance(elt, ast.Node):
810 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000811
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000812 def visitAssName(self, node):
813 if node.flags == 'OP_ASSIGN':
814 self.storeName(node.name)
815 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000816 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000817 self.delName(node.name)
818 else:
819 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000820
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000821 def visitAssAttr(self, node):
822 self.visit(node.expr)
823 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000824 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000825 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000826 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000827 else:
828 print "warning: unexpected flags:", node.flags
829 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000830
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000831 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000832 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000833 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000834 for child in node.nodes:
835 self.visit(child)
836
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000837 if VERSION > 1:
838 visitAssTuple = _visitAssSequence
839 visitAssList = _visitAssSequence
840 else:
841 def visitAssTuple(self, node):
842 self._visitAssSequence(node, 'UNPACK_TUPLE')
843
844 def visitAssList(self, node):
845 self._visitAssSequence(node, 'UNPACK_LIST')
846
847 # augmented assignment
848
849 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000850 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000851 aug_node = wrap_aug(node.node)
852 self.visit(aug_node, "load")
853 self.visit(node.expr)
854 self.emit(self._augmented_opcode[node.op])
855 self.visit(aug_node, "store")
856
857 _augmented_opcode = {
858 '+=' : 'INPLACE_ADD',
859 '-=' : 'INPLACE_SUBTRACT',
860 '*=' : 'INPLACE_MULTIPLY',
861 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000862 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000863 '%=' : 'INPLACE_MODULO',
864 '**=': 'INPLACE_POWER',
865 '>>=': 'INPLACE_RSHIFT',
866 '<<=': 'INPLACE_LSHIFT',
867 '&=' : 'INPLACE_AND',
868 '^=' : 'INPLACE_XOR',
869 '|=' : 'INPLACE_OR',
870 }
871
872 def visitAugName(self, node, mode):
873 if mode == "load":
874 self.loadName(node.name)
875 elif mode == "store":
876 self.storeName(node.name)
877
878 def visitAugGetattr(self, node, mode):
879 if mode == "load":
880 self.visit(node.expr)
881 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000882 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000883 elif mode == "store":
884 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000885 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000886
887 def visitAugSlice(self, node, mode):
888 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000889 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000890 elif mode == "store":
891 slice = 0
892 if node.lower:
893 slice = slice | 1
894 if node.upper:
895 slice = slice | 2
896 if slice == 0:
897 self.emit('ROT_TWO')
898 elif slice == 3:
899 self.emit('ROT_FOUR')
900 else:
901 self.emit('ROT_THREE')
902 self.emit('STORE_SLICE+%d' % slice)
903
904 def visitAugSubscript(self, node, mode):
905 if len(node.subs) > 1:
906 raise SyntaxError, "augmented assignment to tuple is not possible"
907 if mode == "load":
908 self.visitSubscript(node, 1)
909 elif mode == "store":
910 self.emit('ROT_THREE')
911 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000912
913 def visitExec(self, node):
914 self.visit(node.expr)
915 if node.locals is None:
916 self.emit('LOAD_CONST', None)
917 else:
918 self.visit(node.locals)
919 if node.globals is None:
920 self.emit('DUP_TOP')
921 else:
922 self.visit(node.globals)
923 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000924
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000925 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000926 pos = 0
927 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000928 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000929 self.visit(node.node)
930 for arg in node.args:
931 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000932 if isinstance(arg, ast.Keyword):
933 kw = kw + 1
934 else:
935 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000936 if node.star_args is not None:
937 self.visit(node.star_args)
938 if node.dstar_args is not None:
939 self.visit(node.dstar_args)
940 have_star = node.star_args is not None
941 have_dstar = node.dstar_args is not None
942 opcode = callfunc_opcode_info[have_star, have_dstar]
943 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000944
Jeremy Hylton2afff322001-08-27 21:51:52 +0000945 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000946 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000947 if node.dest:
948 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000949 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000950 if node.dest:
951 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000952 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000953 if node.dest:
954 self.emit('ROT_TWO')
955 self.emit('PRINT_ITEM_TO')
956 else:
957 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000958 if node.dest and not newline:
959 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000960
961 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000962 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000963 if node.dest:
964 self.emit('PRINT_NEWLINE_TO')
965 else:
966 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000967
968 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000969 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000970 self.visit(node.value)
971 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000972
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000973 def visitYield(self, node):
974 self.set_lineno(node)
975 self.visit(node.value)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000976 self.emit('YIELD_VALUE')
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000977
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000978 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000979
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000980 def visitSlice(self, node, aug_flag=None):
981 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000982 self.visit(node.expr)
983 slice = 0
984 if node.lower:
985 self.visit(node.lower)
986 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000987 if node.upper:
988 self.visit(node.upper)
989 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000990 if aug_flag:
991 if slice == 0:
992 self.emit('DUP_TOP')
993 elif slice == 3:
994 self.emit('DUP_TOPX', 3)
995 else:
996 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000997 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000998 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000999 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001000 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001001 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001002 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001003 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001004 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001005 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001006
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001007 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001008 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001009 for sub in node.subs:
1010 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001011 if aug_flag:
1012 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001013 if len(node.subs) > 1:
1014 self.emit('BUILD_TUPLE', len(node.subs))
1015 if node.flags == 'OP_APPLY':
1016 self.emit('BINARY_SUBSCR')
1017 elif node.flags == 'OP_ASSIGN':
1018 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001019 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001020 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001021
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001022 # binary ops
1023
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001024 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001025 self.visit(node.left)
1026 self.visit(node.right)
1027 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001028
1029 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001030 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001031
1032 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001033 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001034
1035 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001036 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001037
1038 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001039 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001040
Jeremy Hylton94afe322001-08-29 18:14:39 +00001041 def visitFloorDiv(self, node):
1042 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1043
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001044 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001045 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001046
Jeremy Hylton126960b2000-02-14 21:33:10 +00001047 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001048 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001049
1050 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001051 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001052
1053 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001054 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001055
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001056 # unary ops
1057
1058 def unaryOp(self, node, op):
1059 self.visit(node.expr)
1060 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001061
Jeremy Hylton126960b2000-02-14 21:33:10 +00001062 def visitInvert(self, node):
1063 return self.unaryOp(node, 'UNARY_INVERT')
1064
Jeremy Hylton40245602000-02-08 21:15:48 +00001065 def visitUnarySub(self, node):
1066 return self.unaryOp(node, 'UNARY_NEGATIVE')
1067
1068 def visitUnaryAdd(self, node):
1069 return self.unaryOp(node, 'UNARY_POSITIVE')
1070
1071 def visitUnaryInvert(self, node):
1072 return self.unaryOp(node, 'UNARY_INVERT')
1073
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001074 def visitNot(self, node):
1075 return self.unaryOp(node, 'UNARY_NOT')
1076
Jeremy Hylton40245602000-02-08 21:15:48 +00001077 def visitBackquote(self, node):
1078 return self.unaryOp(node, 'UNARY_CONVERT')
1079
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001080 # bit ops
1081
Jeremy Hyltona5058122000-02-14 14:14:29 +00001082 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001083 self.visit(nodes[0])
1084 for node in nodes[1:]:
1085 self.visit(node)
1086 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001087
1088 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001089 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001090
1091 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001092 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001093
1094 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001095 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001096
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001097 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001098
Jeremy Hyltona5058122000-02-14 14:14:29 +00001099 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001100 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001101
Jeremy Hylton40245602000-02-08 21:15:48 +00001102 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001103 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001104 for elt in node.nodes:
1105 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001106 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001107
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001108 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001109 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001110 for elt in node.nodes:
1111 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001112 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001113
1114 def visitSliceobj(self, node):
1115 for child in node.nodes:
1116 self.visit(child)
1117 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001118
Jeremy Hyltona5058122000-02-14 14:14:29 +00001119 def visitDict(self, node):
Jeremy Hylton18565412002-12-31 18:26:17 +00001120 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001121 self.emit('BUILD_MAP', 0)
1122 for k, v in node.items:
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001123 self.emit('DUP_TOP')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001124 self.visit(k)
Gustavo Niemeyer78429a62002-12-16 13:54:02 +00001125 self.visit(v)
1126 self.emit('ROT_THREE')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001127 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001128
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001129class NestedScopeMixin:
1130 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001131 def initClass(self):
1132 self.__class__.NameFinder = LocalNameFinder
1133 self.__class__.FunctionGen = FunctionCodeGenerator
1134 self.__class__.ClassGen = ClassCodeGenerator
1135
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001136class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001137 __super_init = CodeGenerator.__init__
1138
1139 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001140
Jeremy Hylton37c93512001-09-17 18:03:55 +00001141 def __init__(self, tree):
1142 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001143 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001144 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001145 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001146
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001147 def get_module(self):
1148 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001149
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001150class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1151 __super_init = CodeGenerator.__init__
1152
1153 scopes = None
1154 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001155
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001156 def __init__(self, tree):
1157 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1158 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001159 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001160
1161 def get_module(self):
1162 return self
1163
1164class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1165
1166 __super_init = CodeGenerator.__init__
1167
1168 scopes = None
1169 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001170
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001171 def __init__(self, tree):
1172 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1173 self.__super_init()
1174 self.set_lineno(tree)
1175 walk(tree, self)
1176 self.emit('RETURN_VALUE')
1177
1178 def get_module(self):
1179 return self
Tim Peterse4418602002-02-16 07:34:19 +00001180
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001181 def visitDiscard(self, node):
1182 # XXX Discard means it's an expression. Perhaps this is a bad
1183 # name.
1184 self.visit(node.expr)
1185 self.emit('PRINT_EXPR')
1186
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001187class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001188 optimized = 1
1189 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001190
Jeremy Hylton37c93512001-09-17 18:03:55 +00001191 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001192 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001193 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001194 if isLambda:
1195 klass = FunctionCodeGenerator
1196 name = "<lambda.%d>" % klass.lambdaCount
1197 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001198 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001199 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001200 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001201 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1202 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001203 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001204 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001205
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001206 if not isLambda and func.doc:
1207 self.setDocstring(func.doc)
1208
Jeremy Hylton2afff322001-08-27 21:51:52 +00001209 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001210 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001211 if func.varargs:
1212 self.graph.setFlag(CO_VARARGS)
1213 if func.kwargs:
1214 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001215 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001216 if hasTupleArg:
1217 self.generateArgUnpack(func.argnames)
1218
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001219 def get_module(self):
1220 return self.module
1221
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001222 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001223 self.graph.startExitBlock()
1224 if not self.isLambda:
1225 self.emit('LOAD_CONST', None)
1226 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001227
1228 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001229 for i in range(len(args)):
1230 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001231 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001232 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001233 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001234
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001235 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001236 if VERSION > 1:
1237 self.emit('UNPACK_SEQUENCE', len(tup))
1238 else:
1239 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001240 for elt in tup:
1241 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001242 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001243 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001244 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001245
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001246 unpackTuple = unpackSequence
1247
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001248class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001249 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001250 super_init = CodeGenerator.__init__ # call be other init
1251 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001252
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001253 __super_init = AbstractFunctionCode.__init__
1254
Jeremy Hylton37c93512001-09-17 18:03:55 +00001255 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001256 self.scopes = scopes
1257 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001258 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001259 self.graph.setFreeVars(self.scope.get_free_vars())
1260 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001261 if self.scope.generator is not None:
1262 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001263
1264class AbstractClassCode:
1265
Jeremy Hylton37c93512001-09-17 18:03:55 +00001266 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001267 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001268 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001269 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001270 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001271 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001272 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001273 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001274 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001275 if klass.doc:
1276 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001277
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001278 def get_module(self):
1279 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001280
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001281 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001282 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001283 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001284 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001285
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001286class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001287 super_init = CodeGenerator.__init__
1288 scopes = None
1289
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001290 __super_init = AbstractClassCode.__init__
1291
Jeremy Hylton37c93512001-09-17 18:03:55 +00001292 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001293 self.scopes = scopes
1294 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001295 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001296 self.graph.setFreeVars(self.scope.get_free_vars())
1297 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001298 self.set_lineno(klass)
1299 self.emit("LOAD_GLOBAL", "__name__")
1300 self.storeName("__module__")
1301 if klass.doc:
1302 self.emit("LOAD_CONST", klass.doc)
1303 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001304
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001305def generateArgList(arglist):
1306 """Generate an arg list marking TupleArgs"""
1307 args = []
1308 extra = []
1309 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001310 for i in range(len(arglist)):
1311 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001312 if type(elt) == types.StringType:
1313 args.append(elt)
1314 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001315 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001316 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001317 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001318 else:
1319 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001320 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001321
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001322def findOp(node):
1323 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1324 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001325 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001326 return v.op
1327
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001328class OpFinder:
1329 def __init__(self):
1330 self.op = None
1331 def visitAssName(self, node):
1332 if self.op is None:
1333 self.op = node.flags
1334 elif self.op != node.flags:
1335 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001336 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001337 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001338
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001339class Delegator:
1340 """Base class to support delegation for augmented assignment nodes
1341
1342 To generator code for augmented assignments, we use the following
1343 wrapper classes. In visitAugAssign, the left-hand expression node
1344 is visited twice. The first time the visit uses the normal method
1345 for that node . The second time the visit uses a different method
1346 that generates the appropriate code to perform the assignment.
1347 These delegator classes wrap the original AST nodes in order to
1348 support the variant visit methods.
1349 """
1350 def __init__(self, obj):
1351 self.obj = obj
1352
1353 def __getattr__(self, attr):
1354 return getattr(self.obj, attr)
1355
1356class AugGetattr(Delegator):
1357 pass
1358
1359class AugName(Delegator):
1360 pass
1361
1362class AugSlice(Delegator):
1363 pass
1364
1365class AugSubscript(Delegator):
1366 pass
1367
1368wrapper = {
1369 ast.Getattr: AugGetattr,
1370 ast.Name: AugName,
1371 ast.Slice: AugSlice,
1372 ast.Subscript: AugSubscript,
1373 }
1374
1375def wrap_aug(node):
1376 return wrapper[node.__class__](node)
1377
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001378if __name__ == "__main__":
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001379 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001380 compileFile(file)