blob: a0aa73a7395c2847d59f41b4a86cbb4bd4011ed8 [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 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
Barry Warsaw52acb492001-12-21 20:04:22 +000035# XXX this doesn't seem to be used
Jeremy Hylton1e99a772001-09-14 22:49:08 +000036class BlockStack(misc.Stack):
37 __super_init = misc.Stack.__init__
Tim Peterse0c446b2001-10-18 21:57:37 +000038
Jeremy Hylton1e99a772001-09-14 22:49:08 +000039 def __init__(self):
40 self.__super_init(self)
41 self.loop = None
42
Jeremy Hylton9dca3642001-09-17 21:02:51 +000043def compileFile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000044 f = open(filename)
45 buf = f.read()
46 f.close()
47 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000048 try:
49 mod.compile(display)
50 except SyntaxError, err:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000051 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000052 else:
53 f = open(filename + "c", "wb")
54 mod.dump(f)
55 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000056
Jeremy Hylton9dca3642001-09-17 21:02:51 +000057def compile(source, filename, mode, flags=None, dont_inherit=None):
58 """Replacement for builtin compile() function"""
59 if flags is not None or dont_inherit is not None:
60 raise RuntimeError, "not implemented yet"
Tim Peterse0c446b2001-10-18 21:57:37 +000061
Jeremy Hylton9dca3642001-09-17 21:02:51 +000062 if mode == "single":
63 gen = Interactive(source, filename)
64 elif mode == "exec":
65 gen = Module(source, filename)
66 elif mode == "eval":
67 gen = Expression(source, filename)
68 else:
69 raise ValueError("compile() 3rd arg must be 'exec' or "
70 "'eval' or 'single'")
71 gen.compile()
72 return gen.code
73
74class AbstractCompileMode:
75
76 mode = None # defined by subclass
77
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000078 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000079 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000080 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000081 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000082
Jeremy Hylton9dca3642001-09-17 21:02:51 +000083 def _get_tree(self):
84 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000085 misc.set_filename(self.filename, tree)
86 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000087 return tree
88
89 def compile(self):
90 pass # implemented by subclass
91
92 def getCode(self):
93 return self.code
94
95class Expression(AbstractCompileMode):
96
97 mode = "eval"
98
99 def compile(self):
100 tree = self._get_tree()
101 gen = ExpressionCodeGenerator(tree)
102 self.code = gen.getCode()
103
104class Interactive(AbstractCompileMode):
105
106 mode = "single"
107
108 def compile(self):
109 tree = self._get_tree()
110 gen = InteractiveCodeGenerator(tree)
111 self.code = gen.getCode()
112
113class Module(AbstractCompileMode):
114
115 mode = "exec"
116
117 def compile(self, display=0):
118 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000119 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000120 if display:
121 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000122 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000123 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000124
125 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000126 f.write(self.getPycHeader())
127 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000128
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000129 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000130
131 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000132 # compile.c uses marshal to write a long directly, with
133 # calling the interface that would also generate a 1-byte code
134 # to indicate the type of the value. simplest way to get the
135 # same effect is to call marshal and then skip the code.
Neal Norwitza312c3a2002-06-06 18:30:10 +0000136 mtime = os.path.getmtime(self.filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000137 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000138 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000139
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000140class LocalNameFinder:
141 """Find local names in scope"""
142 def __init__(self, names=()):
143 self.names = misc.Set()
144 self.globals = misc.Set()
145 for name in names:
146 self.names.add(name)
147
148 # XXX list comprehensions and for loops
149
150 def getLocals(self):
151 for elt in self.globals.elements():
152 if self.names.has_elt(elt):
153 self.names.remove(elt)
154 return self.names
155
156 def visitDict(self, node):
157 pass
158
159 def visitGlobal(self, node):
160 for name in node.names:
161 self.globals.add(name)
162
163 def visitFunction(self, node):
164 self.names.add(node.name)
165
166 def visitLambda(self, node):
167 pass
168
169 def visitImport(self, node):
170 for name, alias in node.names:
171 self.names.add(alias or name)
172
173 def visitFrom(self, node):
174 for name, alias in node.names:
175 self.names.add(alias or name)
176
177 def visitClass(self, node):
178 self.names.add(node.name)
179
180 def visitAssName(self, node):
181 self.names.add(node.name)
182
Jeremy Hylton2afff322001-08-27 21:51:52 +0000183def is_constant_false(node):
184 if isinstance(node, ast.Const):
185 if not node.value:
186 return 1
187 return 0
188
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000189class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000190 """Defines basic code generator for Python bytecode
191
192 This class is an abstract base class. Concrete subclasses must
193 define an __init__() that defines self.graph and then calls the
194 __init__() defined in this class.
195
196 The concrete class must also define the class attributes
197 NameFinder, FunctionGen, and ClassGen. These attributes can be
198 defined in the initClass() method, which is a hook for
199 initializing these methods after all the classes have been
Tim Peterse0c446b2001-10-18 21:57:37 +0000200 defined.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000201 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000202
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000203 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000204 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000205 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000206
Jeremy Hylton37c93512001-09-17 18:03:55 +0000207 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000208 if self.__initialized is None:
209 self.initClass()
210 self.__class__.__initialized = 1
211 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000212 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000213 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000214 self.curStack = 0
215 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000216 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000217 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000218 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000219
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000220 # XXX set flags based on future features
221 futures = self.get_module().futures
222 for feature in futures:
223 if feature == "division":
224 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000225 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000226 elif feature == "generators":
227 self.graph.setFlag(CO_GENERATOR_ALLOWED)
228
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000229 def initClass(self):
230 """This method is called once for each class"""
231
232 def checkClass(self):
233 """Verify that class is constructed correctly"""
234 try:
235 assert hasattr(self, 'graph')
236 assert getattr(self, 'NameFinder')
237 assert getattr(self, 'FunctionGen')
238 assert getattr(self, 'ClassGen')
239 except AssertionError, msg:
240 intro = "Bad class construction for %s" % self.__class__.__name__
241 raise AssertionError, intro
242
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000243 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000244 self.emit = self.graph.emit
245 self.newBlock = self.graph.newBlock
246 self.startBlock = self.graph.startBlock
247 self.nextBlock = self.graph.nextBlock
248 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000249
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000250 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000251 """Return a code object"""
252 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000253
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000254 def mangle(self, name):
255 if self.class_name is not None:
256 return misc.mangle(name, self.class_name)
257 else:
258 return name
259
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000260 def parseSymbols(self, tree):
261 s = symbols.SymbolVisitor()
262 walk(tree, s)
263 return s.scopes
264
265 def get_module(self):
266 raise RuntimeError, "should be implemented by subclasses"
267
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000268 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000269
Jeremy Hylton40245602000-02-08 21:15:48 +0000270 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000271 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000272
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000273 def storeName(self, name):
274 self._nameOp('STORE', name)
275
276 def loadName(self, name):
277 self._nameOp('LOAD', name)
278
279 def delName(self, name):
280 self._nameOp('DELETE', name)
281
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000282 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000283 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000284 scope = self.scope.check_name(name)
285 if scope == SC_LOCAL:
286 if not self.optimized:
287 self.emit(prefix + '_NAME', name)
288 else:
289 self.emit(prefix + '_FAST', name)
290 elif scope == SC_GLOBAL:
291 if not self.optimized:
292 self.emit(prefix + '_NAME', name)
293 else:
294 self.emit(prefix + '_GLOBAL', name)
295 elif scope == SC_FREE or scope == SC_CELL:
296 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000297 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000298 raise RuntimeError, "unsupported scope for var %s: %d" % \
299 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000300
Jeremy Hylton13d70942001-04-12 21:04:43 +0000301 def _implicitNameOp(self, prefix, name):
302 """Emit name ops for names generated implicitly by for loops
303
304 The interpreter generates names that start with a period or
305 dollar sign. The symbol table ignores these names because
306 they aren't present in the program text.
307 """
308 if self.optimized:
309 self.emit(prefix + '_FAST', name)
310 else:
311 self.emit(prefix + '_NAME', name)
312
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000313 def set_lineno(self, node, force=0):
Tim Peterse0c446b2001-10-18 21:57:37 +0000314 """Emit SET_LINENO if node has lineno attribute and it is
Jeremy Hylton92f39722000-09-01 20:47:37 +0000315 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000316
317 Returns true if SET_LINENO was emitted.
318
319 There are no rules for when an AST node should have a lineno
320 attribute. The transformer and AST code need to be reviewed
321 and a consistent policy implemented and documented. Until
322 then, this method works around missing line numbers.
323 """
324 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000325 if lineno is not None and (lineno != self.last_lineno
326 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000327 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000328 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000329 return 1
330 return 0
331
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000332 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000333 # code objects. They use class attributes to determine what
334 # specialized code generators to use.
335
336 NameFinder = LocalNameFinder
337 FunctionGen = None
338 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000339
340 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000341 self.scopes = self.parseSymbols(node)
342 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000343 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000344 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000345 self.emit('LOAD_CONST', node.doc)
346 self.storeName('__doc__')
347 lnf = walk(node.node, self.NameFinder(), verbose=0)
348 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000349 self.visit(node.node)
350 self.emit('LOAD_CONST', None)
351 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000352
Barry Warsaw52acb492001-12-21 20:04:22 +0000353 def visitExpression(self, node):
354 self.set_lineno(node)
355 self.scopes = self.parseSymbols(node)
356 self.scope = self.scopes[node]
357 self.visit(node.node)
358 self.emit('RETURN_VALUE')
359
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000360 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000361 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000362 if node.doc:
363 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000364 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000365
366 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000367 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000368
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000369 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000370 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000371 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000372 walk(node.code, gen)
373 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000374 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000375 for default in node.defaults:
376 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000377 frees = gen.scope.get_free_vars()
378 if frees:
379 for name in frees:
380 self.emit('LOAD_CLOSURE', name)
381 self.emit('LOAD_CONST', gen)
382 self.emit('MAKE_CLOSURE', len(node.defaults))
383 else:
384 self.emit('LOAD_CONST', gen)
385 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000386
387 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000388 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000389 self.get_module())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000390 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000391 self.emit('LOAD_CONST', node.doc)
392 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000393 walk(node.code, gen)
394 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000395 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000396 self.emit('LOAD_CONST', node.name)
397 for base in node.bases:
398 self.visit(base)
399 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000400 frees = gen.scope.get_free_vars()
401 for name in frees:
402 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000403 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000404 if frees:
405 self.emit('MAKE_CLOSURE', 0)
406 else:
407 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000408 self.emit('CALL_FUNCTION', 0)
409 self.emit('BUILD_CLASS')
410 self.storeName(node.name)
411
412 # The rest are standard visitor methods
413
414 # The next few implement control-flow statements
415
416 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000417 end = self.newBlock()
418 numtests = len(node.tests)
419 for i in range(numtests):
420 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000421 if is_constant_false(test):
422 # XXX will need to check generator stuff here
423 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000424 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000425 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000426 nextTest = self.newBlock()
427 self.emit('JUMP_IF_FALSE', nextTest)
428 self.nextBlock()
429 self.emit('POP_TOP')
430 self.visit(suite)
431 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000432 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000433 self.emit('POP_TOP')
434 if node.else_:
435 self.visit(node.else_)
436 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000437
438 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000439 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000440
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000441 loop = self.newBlock()
442 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000443
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000444 after = self.newBlock()
445 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000446
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000447 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000448 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000449
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000450 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000451 self.visit(node.test)
452 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000453
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000454 self.nextBlock()
455 self.emit('POP_TOP')
456 self.visit(node.body)
457 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000458
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000459 self.startBlock(else_) # or just the POPs if not else clause
460 self.emit('POP_TOP')
461 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000462 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000463 if node.else_:
464 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000465 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000466
467 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000468 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000469 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000470 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000471 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000472
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000473 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000474 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000475 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000476 self.emit('GET_ITER')
477
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000478 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000479 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000480 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000481 self.visit(node.assign)
482 self.visit(node.body)
483 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000484 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000485 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000486 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000487 if node.else_:
488 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000489 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000490
491 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000492 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000493 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000494 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000495 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000496 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000497
498 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000499 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000500 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000501 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000502 kind, block = self.setups.top()
503 if kind == LOOP:
504 self.set_lineno(node)
505 self.emit('JUMP_ABSOLUTE', block)
506 self.nextBlock()
507 elif kind == EXCEPT or kind == TRY_FINALLY:
508 self.set_lineno(node)
509 # find the block that starts the loop
510 top = len(self.setups)
511 while top > 0:
512 top = top - 1
513 kind, loop_block = self.setups[top]
514 if kind == LOOP:
515 break
516 if kind != LOOP:
517 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000518 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000519 self.emit('CONTINUE_LOOP', loop_block)
520 self.nextBlock()
521 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000522 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000523 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000524
525 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000526 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000527 for child in node.nodes[:-1]:
528 self.visit(child)
529 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000530 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000531 self.emit('POP_TOP')
532 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000533 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000534
535 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000536 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000537
538 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000539 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000540
541 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000542 self.visit(node.expr)
543 cleanup = self.newBlock()
544 for op, code in node.ops[:-1]:
545 self.visit(code)
546 self.emit('DUP_TOP')
547 self.emit('ROT_THREE')
548 self.emit('COMPARE_OP', op)
549 self.emit('JUMP_IF_FALSE', cleanup)
550 self.nextBlock()
551 self.emit('POP_TOP')
552 # now do the last comparison
553 if node.ops:
554 op, code = node.ops[-1]
555 self.visit(code)
556 self.emit('COMPARE_OP', op)
557 if len(node.ops) > 1:
558 end = self.newBlock()
559 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000560 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000561 self.emit('ROT_TWO')
562 self.emit('POP_TOP')
563 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000564
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000565 # list comprehensions
566 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000567
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000568 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000569 self.set_lineno(node)
570 # setup list
571 append = "$append%d" % self.__list_count
572 self.__list_count = self.__list_count + 1
573 self.emit('BUILD_LIST', 0)
574 self.emit('DUP_TOP')
575 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000576 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000577
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000578 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000579 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000580 start, anchor = self.visit(for_)
581 cont = None
582 for if_ in for_.ifs:
583 if cont is None:
584 cont = self.newBlock()
585 self.visit(if_, cont)
586 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000587
Jeremy Hylton13d70942001-04-12 21:04:43 +0000588 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000589 self.visit(node.expr)
590 self.emit('CALL_FUNCTION', 1)
591 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000592
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000593 for start, cont, anchor in stack:
594 if cont:
595 skip_one = self.newBlock()
596 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000597 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000598 self.emit('POP_TOP')
599 self.nextBlock(skip_one)
600 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000601 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000602 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000603
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000604 self.__list_count = self.__list_count - 1
605
606 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000607 start = self.newBlock()
608 anchor = self.newBlock()
609
610 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000611 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000612 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000613 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000614 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000615 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000616 self.visit(node.assign)
617 return start, anchor
618
619 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000620 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000621 self.visit(node.test)
622 self.emit('JUMP_IF_FALSE', branch)
623 self.newBlock()
624 self.emit('POP_TOP')
625
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000626 # exception related
627
628 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000629 # XXX would be interesting to implement this via a
630 # transformation of the AST before this stage
631 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000632 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000633 # XXX __debug__ and AssertionError appear to be special cases
634 # -- they are always loaded as globals even if there are local
635 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000636 self.emit('LOAD_GLOBAL', '__debug__')
637 self.emit('JUMP_IF_FALSE', end)
638 self.nextBlock()
639 self.emit('POP_TOP')
640 self.visit(node.test)
641 self.emit('JUMP_IF_TRUE', end)
642 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000643 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000644 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000645 if node.fail:
646 self.visit(node.fail)
647 self.emit('RAISE_VARARGS', 2)
648 else:
649 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000650 self.nextBlock(end)
651 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000652
653 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000654 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000655 n = 0
656 if node.expr1:
657 self.visit(node.expr1)
658 n = n + 1
659 if node.expr2:
660 self.visit(node.expr2)
661 n = n + 1
662 if node.expr3:
663 self.visit(node.expr3)
664 n = n + 1
665 self.emit('RAISE_VARARGS', n)
666
667 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000668 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000669 handlers = self.newBlock()
670 end = self.newBlock()
671 if node.else_:
672 lElse = self.newBlock()
673 else:
674 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000675 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000676 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000677 self.nextBlock(body)
678 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000679 self.visit(node.body)
680 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000681 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000682 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000683 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000684
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000685 last = len(node.handlers) - 1
686 for i in range(len(node.handlers)):
687 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000688 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000689 if expr:
690 self.emit('DUP_TOP')
691 self.visit(expr)
692 self.emit('COMPARE_OP', 'exception match')
693 next = self.newBlock()
694 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000695 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000696 self.emit('POP_TOP')
697 self.emit('POP_TOP')
698 if target:
699 self.visit(target)
700 else:
701 self.emit('POP_TOP')
702 self.emit('POP_TOP')
703 self.visit(body)
704 self.emit('JUMP_FORWARD', end)
705 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000706 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000707 else:
708 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000709 if expr: # XXX
710 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000711 self.emit('END_FINALLY')
712 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000713 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000714 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000715 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000716
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000717 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000718 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000719 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000720 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000722 self.nextBlock(body)
723 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724 self.visit(node.body)
725 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000726 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000727 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000728 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000729 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000730 self.visit(node.final)
731 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000732 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000733
734 # misc
735
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000736 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000737 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000738 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000739 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000740
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000741 def visitConst(self, node):
742 self.emit('LOAD_CONST', node.value)
743
744 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000745 self.emit('LOAD_CONST', node.name)
746 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000747
748 def visitGlobal(self, node):
749 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000750 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000751
752 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000753 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000754 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000755
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000756 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000757 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000758
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000759 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000760 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000761 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000762 if VERSION > 1:
763 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000764 self.emit('IMPORT_NAME', name)
Neal Norwitza312c3a2002-06-06 18:30:10 +0000765 mod = name.split(".")[0]
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000766 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000767
768 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000769 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000770 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000771 if VERSION > 1:
772 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000773 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000774 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000775 if VERSION > 1:
776 if name == '*':
777 self.namespace = 0
778 self.emit('IMPORT_STAR')
779 # There can only be one name w/ from ... import *
780 assert len(node.names) == 1
781 return
782 else:
783 self.emit('IMPORT_FROM', name)
784 self._resolveDots(name)
785 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000786 else:
787 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000788 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000789
Jeremy Hylton20516082000-09-01 20:33:26 +0000790 def _resolveDots(self, name):
Neal Norwitza312c3a2002-06-06 18:30:10 +0000791 elts = name.split(".")
Jeremy Hylton20516082000-09-01 20:33:26 +0000792 if len(elts) == 1:
793 return
794 for elt in elts[1:]:
795 self.emit('LOAD_ATTR', elt)
796
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000797 def visitGetattr(self, node):
798 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000799 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000800
801 # next five implement assignments
802
803 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000804 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000805 self.visit(node.expr)
806 dups = len(node.nodes) - 1
807 for i in range(len(node.nodes)):
808 elt = node.nodes[i]
809 if i < dups:
810 self.emit('DUP_TOP')
811 if isinstance(elt, ast.Node):
812 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000813
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000814 def visitAssName(self, node):
815 if node.flags == 'OP_ASSIGN':
816 self.storeName(node.name)
817 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000818 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000819 self.delName(node.name)
820 else:
821 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000822
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000823 def visitAssAttr(self, node):
824 self.visit(node.expr)
825 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000826 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000827 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000828 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000829 else:
830 print "warning: unexpected flags:", node.flags
831 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000832
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000833 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000834 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000835 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000836 for child in node.nodes:
837 self.visit(child)
838
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000839 if VERSION > 1:
840 visitAssTuple = _visitAssSequence
841 visitAssList = _visitAssSequence
842 else:
843 def visitAssTuple(self, node):
844 self._visitAssSequence(node, 'UNPACK_TUPLE')
845
846 def visitAssList(self, node):
847 self._visitAssSequence(node, 'UNPACK_LIST')
848
849 # augmented assignment
850
851 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000852 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000853 aug_node = wrap_aug(node.node)
854 self.visit(aug_node, "load")
855 self.visit(node.expr)
856 self.emit(self._augmented_opcode[node.op])
857 self.visit(aug_node, "store")
858
859 _augmented_opcode = {
860 '+=' : 'INPLACE_ADD',
861 '-=' : 'INPLACE_SUBTRACT',
862 '*=' : 'INPLACE_MULTIPLY',
863 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000864 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000865 '%=' : 'INPLACE_MODULO',
866 '**=': 'INPLACE_POWER',
867 '>>=': 'INPLACE_RSHIFT',
868 '<<=': 'INPLACE_LSHIFT',
869 '&=' : 'INPLACE_AND',
870 '^=' : 'INPLACE_XOR',
871 '|=' : 'INPLACE_OR',
872 }
873
874 def visitAugName(self, node, mode):
875 if mode == "load":
876 self.loadName(node.name)
877 elif mode == "store":
878 self.storeName(node.name)
879
880 def visitAugGetattr(self, node, mode):
881 if mode == "load":
882 self.visit(node.expr)
883 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000884 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000885 elif mode == "store":
886 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000887 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000888
889 def visitAugSlice(self, node, mode):
890 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000891 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000892 elif mode == "store":
893 slice = 0
894 if node.lower:
895 slice = slice | 1
896 if node.upper:
897 slice = slice | 2
898 if slice == 0:
899 self.emit('ROT_TWO')
900 elif slice == 3:
901 self.emit('ROT_FOUR')
902 else:
903 self.emit('ROT_THREE')
904 self.emit('STORE_SLICE+%d' % slice)
905
906 def visitAugSubscript(self, node, mode):
907 if len(node.subs) > 1:
908 raise SyntaxError, "augmented assignment to tuple is not possible"
909 if mode == "load":
910 self.visitSubscript(node, 1)
911 elif mode == "store":
912 self.emit('ROT_THREE')
913 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000914
915 def visitExec(self, node):
916 self.visit(node.expr)
917 if node.locals is None:
918 self.emit('LOAD_CONST', None)
919 else:
920 self.visit(node.locals)
921 if node.globals is None:
922 self.emit('DUP_TOP')
923 else:
924 self.visit(node.globals)
925 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000926
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000927 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000928 pos = 0
929 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000930 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000931 self.visit(node.node)
932 for arg in node.args:
933 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000934 if isinstance(arg, ast.Keyword):
935 kw = kw + 1
936 else:
937 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000938 if node.star_args is not None:
939 self.visit(node.star_args)
940 if node.dstar_args is not None:
941 self.visit(node.dstar_args)
942 have_star = node.star_args is not None
943 have_dstar = node.dstar_args is not None
944 opcode = callfunc_opcode_info[have_star, have_dstar]
945 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000946
Jeremy Hylton2afff322001-08-27 21:51:52 +0000947 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000948 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000949 if node.dest:
950 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000951 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000952 if node.dest:
953 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000954 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000955 if node.dest:
956 self.emit('ROT_TWO')
957 self.emit('PRINT_ITEM_TO')
958 else:
959 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000960 if node.dest and not newline:
961 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000962
963 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000964 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000965 if node.dest:
966 self.emit('PRINT_NEWLINE_TO')
967 else:
968 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000969
970 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000971 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000972 self.visit(node.value)
973 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000974
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000975 def visitYield(self, node):
976 self.set_lineno(node)
977 self.visit(node.value)
978 self.emit('YIELD_STMT')
979
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000980 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000981
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000982 def visitSlice(self, node, aug_flag=None):
983 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000984 self.visit(node.expr)
985 slice = 0
986 if node.lower:
987 self.visit(node.lower)
988 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000989 if node.upper:
990 self.visit(node.upper)
991 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000992 if aug_flag:
993 if slice == 0:
994 self.emit('DUP_TOP')
995 elif slice == 3:
996 self.emit('DUP_TOPX', 3)
997 else:
998 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000999 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001000 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001001 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001002 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001003 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001004 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001005 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001006 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001007 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001008
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001009 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001010 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001011 for sub in node.subs:
1012 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001013 if aug_flag:
1014 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001015 if len(node.subs) > 1:
1016 self.emit('BUILD_TUPLE', len(node.subs))
1017 if node.flags == 'OP_APPLY':
1018 self.emit('BINARY_SUBSCR')
1019 elif node.flags == 'OP_ASSIGN':
1020 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001021 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001022 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001023
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001024 # binary ops
1025
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001026 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001027 self.visit(node.left)
1028 self.visit(node.right)
1029 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001030
1031 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001032 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001033
1034 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001035 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001036
1037 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001038 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001039
1040 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001041 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001042
Jeremy Hylton94afe322001-08-29 18:14:39 +00001043 def visitFloorDiv(self, node):
1044 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1045
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001046 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001047 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001048
Jeremy Hylton126960b2000-02-14 21:33:10 +00001049 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001050 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001051
1052 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001053 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001054
1055 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001056 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001057
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001058 # unary ops
1059
1060 def unaryOp(self, node, op):
1061 self.visit(node.expr)
1062 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001063
Jeremy Hylton126960b2000-02-14 21:33:10 +00001064 def visitInvert(self, node):
1065 return self.unaryOp(node, 'UNARY_INVERT')
1066
Jeremy Hylton40245602000-02-08 21:15:48 +00001067 def visitUnarySub(self, node):
1068 return self.unaryOp(node, 'UNARY_NEGATIVE')
1069
1070 def visitUnaryAdd(self, node):
1071 return self.unaryOp(node, 'UNARY_POSITIVE')
1072
1073 def visitUnaryInvert(self, node):
1074 return self.unaryOp(node, 'UNARY_INVERT')
1075
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001076 def visitNot(self, node):
1077 return self.unaryOp(node, 'UNARY_NOT')
1078
Jeremy Hylton40245602000-02-08 21:15:48 +00001079 def visitBackquote(self, node):
1080 return self.unaryOp(node, 'UNARY_CONVERT')
1081
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001082 # bit ops
1083
Jeremy Hyltona5058122000-02-14 14:14:29 +00001084 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001085 self.visit(nodes[0])
1086 for node in nodes[1:]:
1087 self.visit(node)
1088 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001089
1090 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001091 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001092
1093 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001094 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001095
1096 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001097 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001098
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001099 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001100
Jeremy Hyltona5058122000-02-14 14:14:29 +00001101 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001102 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001103
Jeremy Hylton40245602000-02-08 21:15:48 +00001104 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001105 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001106 for elt in node.nodes:
1107 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001108 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001109
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001110 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001111 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001112 for elt in node.nodes:
1113 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001114 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001115
1116 def visitSliceobj(self, node):
1117 for child in node.nodes:
1118 self.visit(child)
1119 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001120
Jeremy Hyltona5058122000-02-14 14:14:29 +00001121 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001122 lineno = getattr(node, 'lineno', None)
1123 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001124 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001125 self.emit('BUILD_MAP', 0)
1126 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001127 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001128 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001129 self.emit('SET_LINENO', lineno2)
1130 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001131 self.emit('DUP_TOP')
1132 self.visit(v)
1133 self.emit('ROT_TWO')
1134 self.visit(k)
1135 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001136
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001137class NestedScopeMixin:
1138 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001139 def initClass(self):
1140 self.__class__.NameFinder = LocalNameFinder
1141 self.__class__.FunctionGen = FunctionCodeGenerator
1142 self.__class__.ClassGen = ClassCodeGenerator
1143
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001144class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001145 __super_init = CodeGenerator.__init__
1146
1147 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001148
Jeremy Hylton37c93512001-09-17 18:03:55 +00001149 def __init__(self, tree):
1150 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001151 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001152 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001153 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001154
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001155 def get_module(self):
1156 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001157
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001158class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1159 __super_init = CodeGenerator.__init__
1160
1161 scopes = None
1162 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001163
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001164 def __init__(self, tree):
1165 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1166 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001167 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001168
1169 def get_module(self):
1170 return self
1171
1172class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1173
1174 __super_init = CodeGenerator.__init__
1175
1176 scopes = None
1177 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001178
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001179 def __init__(self, tree):
1180 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1181 self.__super_init()
1182 self.set_lineno(tree)
1183 walk(tree, self)
1184 self.emit('RETURN_VALUE')
1185
1186 def get_module(self):
1187 return self
Tim Peterse4418602002-02-16 07:34:19 +00001188
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001189 def visitDiscard(self, node):
1190 # XXX Discard means it's an expression. Perhaps this is a bad
1191 # name.
1192 self.visit(node.expr)
1193 self.emit('PRINT_EXPR')
1194
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001195class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001196 optimized = 1
1197 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001198
Jeremy Hylton37c93512001-09-17 18:03:55 +00001199 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001200 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001201 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001202 if isLambda:
1203 klass = FunctionCodeGenerator
1204 name = "<lambda.%d>" % klass.lambdaCount
1205 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001206 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001207 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001208 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001209 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1210 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001211 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001212 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001213
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001214 if not isLambda and func.doc:
1215 self.setDocstring(func.doc)
1216
Jeremy Hylton2afff322001-08-27 21:51:52 +00001217 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001218 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001219 if func.varargs:
1220 self.graph.setFlag(CO_VARARGS)
1221 if func.kwargs:
1222 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001223 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001224 if hasTupleArg:
1225 self.generateArgUnpack(func.argnames)
1226
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001227 def get_module(self):
1228 return self.module
1229
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001230 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001231 self.graph.startExitBlock()
1232 if not self.isLambda:
1233 self.emit('LOAD_CONST', None)
1234 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001235
1236 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001237 for i in range(len(args)):
1238 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001239 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001240 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001241 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001242
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001243 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001244 if VERSION > 1:
1245 self.emit('UNPACK_SEQUENCE', len(tup))
1246 else:
1247 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001248 for elt in tup:
1249 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001250 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001251 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001252 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001253
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001254 unpackTuple = unpackSequence
1255
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001256class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001257 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001258 super_init = CodeGenerator.__init__ # call be other init
1259 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001260
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001261 __super_init = AbstractFunctionCode.__init__
1262
Jeremy Hylton37c93512001-09-17 18:03:55 +00001263 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001264 self.scopes = scopes
1265 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001266 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001267 self.graph.setFreeVars(self.scope.get_free_vars())
1268 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001269 if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
1270 if self.scope.generator is not None:
1271 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001272
1273class AbstractClassCode:
1274
Jeremy Hylton37c93512001-09-17 18:03:55 +00001275 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001276 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001277 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001278 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001279 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001280 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001281 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001282 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001283 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001284 if klass.doc:
1285 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001286
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001287 def get_module(self):
1288 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001289
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001290 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001291 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001292 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001293 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001294
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001295class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001296 super_init = CodeGenerator.__init__
1297 scopes = None
1298
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001299 __super_init = AbstractClassCode.__init__
1300
Jeremy Hylton37c93512001-09-17 18:03:55 +00001301 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001302 self.scopes = scopes
1303 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001304 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001305 self.graph.setFreeVars(self.scope.get_free_vars())
1306 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001307
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001308def generateArgList(arglist):
1309 """Generate an arg list marking TupleArgs"""
1310 args = []
1311 extra = []
1312 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001313 for i in range(len(arglist)):
1314 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001315 if type(elt) == types.StringType:
1316 args.append(elt)
1317 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001318 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001319 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001320 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001321 else:
1322 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001323 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001324
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001325def findOp(node):
1326 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1327 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001328 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001329 return v.op
1330
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001331class OpFinder:
1332 def __init__(self):
1333 self.op = None
1334 def visitAssName(self, node):
1335 if self.op is None:
1336 self.op = node.flags
1337 elif self.op != node.flags:
1338 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001339 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001340 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001341
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001342class Delegator:
1343 """Base class to support delegation for augmented assignment nodes
1344
1345 To generator code for augmented assignments, we use the following
1346 wrapper classes. In visitAugAssign, the left-hand expression node
1347 is visited twice. The first time the visit uses the normal method
1348 for that node . The second time the visit uses a different method
1349 that generates the appropriate code to perform the assignment.
1350 These delegator classes wrap the original AST nodes in order to
1351 support the variant visit methods.
1352 """
1353 def __init__(self, obj):
1354 self.obj = obj
1355
1356 def __getattr__(self, attr):
1357 return getattr(self.obj, attr)
1358
1359class AugGetattr(Delegator):
1360 pass
1361
1362class AugName(Delegator):
1363 pass
1364
1365class AugSlice(Delegator):
1366 pass
1367
1368class AugSubscript(Delegator):
1369 pass
1370
1371wrapper = {
1372 ast.Getattr: AugGetattr,
1373 ast.Name: AugName,
1374 ast.Slice: AugSlice,
1375 ast.Subscript: AugSubscript,
1376 }
1377
1378def wrap_aug(node):
1379 return wrapper[node.__class__](node)
1380
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001381if __name__ == "__main__":
1382 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001383
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001384 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001385 compileFile(file)