blob: c107a085bd9da9a4cffcf6986edcd86516c56855 [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 stat
Jeremy Hylton20516082000-09-01 20:33:26 +00005import string
Jeremy Hylton53187f32000-02-08 19:01:29 +00006import struct
Jeremy Hylton9c048f92000-10-13 21:58:13 +00007import sys
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00008import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00009from cStringIO import StringIO
10
Jeremy Hylton37c93512001-09-17 18:03:55 +000011from compiler import ast, parse, walk, syntax
Jeremy Hylton364f9b92001-04-12 06:40:42 +000012from compiler import pyassem, misc, future, symbols
13from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000015 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000016from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000017
Jeremy Hylton9c048f92000-10-13 21:58:13 +000018# Do we have Python 1.x or Python 2.x?
19try:
20 VERSION = sys.version_info[0]
21except AttributeError:
22 VERSION = 1
23
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000024callfunc_opcode_info = {
25 # (Have *args, Have **args) : opcode
26 (0,0) : "CALL_FUNCTION",
27 (1,0) : "CALL_FUNCTION_VAR",
28 (0,1) : "CALL_FUNCTION_KW",
29 (1,1) : "CALL_FUNCTION_VAR_KW",
30}
31
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000032LOOP = 1
33EXCEPT = 2
34TRY_FINALLY = 3
35END_FINALLY = 4
36
Barry Warsaw52acb492001-12-21 20:04:22 +000037# XXX this doesn't seem to be used
Jeremy Hylton1e99a772001-09-14 22:49:08 +000038class BlockStack(misc.Stack):
39 __super_init = misc.Stack.__init__
Tim Peterse0c446b2001-10-18 21:57:37 +000040
Jeremy Hylton1e99a772001-09-14 22:49:08 +000041 def __init__(self):
42 self.__super_init(self)
43 self.loop = None
44
Jeremy Hylton9dca3642001-09-17 21:02:51 +000045def compileFile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000046 f = open(filename)
47 buf = f.read()
48 f.close()
49 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000050 try:
51 mod.compile(display)
52 except SyntaxError, err:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000053 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000054 else:
55 f = open(filename + "c", "wb")
56 mod.dump(f)
57 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000058
Jeremy Hylton9dca3642001-09-17 21:02:51 +000059def compile(source, filename, mode, flags=None, dont_inherit=None):
60 """Replacement for builtin compile() function"""
61 if flags is not None or dont_inherit is not None:
62 raise RuntimeError, "not implemented yet"
Tim Peterse0c446b2001-10-18 21:57:37 +000063
Jeremy Hylton9dca3642001-09-17 21:02:51 +000064 if mode == "single":
65 gen = Interactive(source, filename)
66 elif mode == "exec":
67 gen = Module(source, filename)
68 elif mode == "eval":
69 gen = Expression(source, filename)
70 else:
71 raise ValueError("compile() 3rd arg must be 'exec' or "
72 "'eval' or 'single'")
73 gen.compile()
74 return gen.code
75
76class AbstractCompileMode:
77
78 mode = None # defined by subclass
79
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000080 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000081 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000082 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000083 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000084
Jeremy Hylton9dca3642001-09-17 21:02:51 +000085 def _get_tree(self):
86 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000087 misc.set_filename(self.filename, tree)
88 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000089 return tree
90
91 def compile(self):
92 pass # implemented by subclass
93
94 def getCode(self):
95 return self.code
96
97class Expression(AbstractCompileMode):
98
99 mode = "eval"
100
101 def compile(self):
102 tree = self._get_tree()
103 gen = ExpressionCodeGenerator(tree)
104 self.code = gen.getCode()
105
106class Interactive(AbstractCompileMode):
107
108 mode = "single"
109
110 def compile(self):
111 tree = self._get_tree()
112 gen = InteractiveCodeGenerator(tree)
113 self.code = gen.getCode()
114
115class Module(AbstractCompileMode):
116
117 mode = "exec"
118
119 def compile(self, display=0):
120 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000121 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000122 if display:
123 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000124 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000125 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000126
127 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000128 f.write(self.getPycHeader())
129 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000130
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000131 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000132
133 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000134 # compile.c uses marshal to write a long directly, with
135 # calling the interface that would also generate a 1-byte code
136 # to indicate the type of the value. simplest way to get the
137 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000138 mtime = os.stat(self.filename)[stat.ST_MTIME]
139 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000140 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000141
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000142class LocalNameFinder:
143 """Find local names in scope"""
144 def __init__(self, names=()):
145 self.names = misc.Set()
146 self.globals = misc.Set()
147 for name in names:
148 self.names.add(name)
149
150 # XXX list comprehensions and for loops
151
152 def getLocals(self):
153 for elt in self.globals.elements():
154 if self.names.has_elt(elt):
155 self.names.remove(elt)
156 return self.names
157
158 def visitDict(self, node):
159 pass
160
161 def visitGlobal(self, node):
162 for name in node.names:
163 self.globals.add(name)
164
165 def visitFunction(self, node):
166 self.names.add(node.name)
167
168 def visitLambda(self, node):
169 pass
170
171 def visitImport(self, node):
172 for name, alias in node.names:
173 self.names.add(alias or name)
174
175 def visitFrom(self, node):
176 for name, alias in node.names:
177 self.names.add(alias or name)
178
179 def visitClass(self, node):
180 self.names.add(node.name)
181
182 def visitAssName(self, node):
183 self.names.add(node.name)
184
Jeremy Hylton2afff322001-08-27 21:51:52 +0000185def is_constant_false(node):
186 if isinstance(node, ast.Const):
187 if not node.value:
188 return 1
189 return 0
190
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000191class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000192 """Defines basic code generator for Python bytecode
193
194 This class is an abstract base class. Concrete subclasses must
195 define an __init__() that defines self.graph and then calls the
196 __init__() defined in this class.
197
198 The concrete class must also define the class attributes
199 NameFinder, FunctionGen, and ClassGen. These attributes can be
200 defined in the initClass() method, which is a hook for
201 initializing these methods after all the classes have been
Tim Peterse0c446b2001-10-18 21:57:37 +0000202 defined.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000203 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000204
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000205 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000206 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000207 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000208
Jeremy Hylton37c93512001-09-17 18:03:55 +0000209 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000210 if self.__initialized is None:
211 self.initClass()
212 self.__class__.__initialized = 1
213 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000214 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000215 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000216 self.curStack = 0
217 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000218 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000219 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000220 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000221
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000222 # XXX set flags based on future features
223 futures = self.get_module().futures
224 for feature in futures:
225 if feature == "division":
226 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000227 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000228 elif feature == "generators":
229 self.graph.setFlag(CO_GENERATOR_ALLOWED)
230
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000231 def initClass(self):
232 """This method is called once for each class"""
233
234 def checkClass(self):
235 """Verify that class is constructed correctly"""
236 try:
237 assert hasattr(self, 'graph')
238 assert getattr(self, 'NameFinder')
239 assert getattr(self, 'FunctionGen')
240 assert getattr(self, 'ClassGen')
241 except AssertionError, msg:
242 intro = "Bad class construction for %s" % self.__class__.__name__
243 raise AssertionError, intro
244
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000245 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000246 self.emit = self.graph.emit
247 self.newBlock = self.graph.newBlock
248 self.startBlock = self.graph.startBlock
249 self.nextBlock = self.graph.nextBlock
250 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000251
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000252 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000253 """Return a code object"""
254 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000255
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000256 def mangle(self, name):
257 if self.class_name is not None:
258 return misc.mangle(name, self.class_name)
259 else:
260 return name
261
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000262 def parseSymbols(self, tree):
263 s = symbols.SymbolVisitor()
264 walk(tree, s)
265 return s.scopes
266
267 def get_module(self):
268 raise RuntimeError, "should be implemented by subclasses"
269
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000270 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000271
Jeremy Hylton40245602000-02-08 21:15:48 +0000272 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000273 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000274
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000275 def storeName(self, name):
276 self._nameOp('STORE', name)
277
278 def loadName(self, name):
279 self._nameOp('LOAD', name)
280
281 def delName(self, name):
282 self._nameOp('DELETE', name)
283
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000284 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000285 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000286 scope = self.scope.check_name(name)
287 if scope == SC_LOCAL:
288 if not self.optimized:
289 self.emit(prefix + '_NAME', name)
290 else:
291 self.emit(prefix + '_FAST', name)
292 elif scope == SC_GLOBAL:
293 if not self.optimized:
294 self.emit(prefix + '_NAME', name)
295 else:
296 self.emit(prefix + '_GLOBAL', name)
297 elif scope == SC_FREE or scope == SC_CELL:
298 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000299 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000300 raise RuntimeError, "unsupported scope for var %s: %d" % \
301 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000302
Jeremy Hylton13d70942001-04-12 21:04:43 +0000303 def _implicitNameOp(self, prefix, name):
304 """Emit name ops for names generated implicitly by for loops
305
306 The interpreter generates names that start with a period or
307 dollar sign. The symbol table ignores these names because
308 they aren't present in the program text.
309 """
310 if self.optimized:
311 self.emit(prefix + '_FAST', name)
312 else:
313 self.emit(prefix + '_NAME', name)
314
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000315 def set_lineno(self, node, force=0):
Tim Peterse0c446b2001-10-18 21:57:37 +0000316 """Emit SET_LINENO if node has lineno attribute and it is
Jeremy Hylton92f39722000-09-01 20:47:37 +0000317 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000318
319 Returns true if SET_LINENO was emitted.
320
321 There are no rules for when an AST node should have a lineno
322 attribute. The transformer and AST code need to be reviewed
323 and a consistent policy implemented and documented. Until
324 then, this method works around missing line numbers.
325 """
326 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000327 if lineno is not None and (lineno != self.last_lineno
328 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000329 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000330 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000331 return 1
332 return 0
333
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000334 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000335 # code objects. They use class attributes to determine what
336 # specialized code generators to use.
337
338 NameFinder = LocalNameFinder
339 FunctionGen = None
340 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000341
342 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000343 self.scopes = self.parseSymbols(node)
344 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000345 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000346 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000347 self.emit('LOAD_CONST', node.doc)
348 self.storeName('__doc__')
349 lnf = walk(node.node, self.NameFinder(), verbose=0)
350 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000351 self.visit(node.node)
352 self.emit('LOAD_CONST', None)
353 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000354
Barry Warsaw52acb492001-12-21 20:04:22 +0000355 def visitExpression(self, node):
356 self.set_lineno(node)
357 self.scopes = self.parseSymbols(node)
358 self.scope = self.scopes[node]
359 self.visit(node.node)
360 self.emit('RETURN_VALUE')
361
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000362 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000363 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000364 if node.doc:
365 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000366 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000367
368 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000369 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000370
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000371 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000372 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000373 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000374 walk(node.code, gen)
375 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000376 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000377 for default in node.defaults:
378 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000379 frees = gen.scope.get_free_vars()
380 if frees:
381 for name in frees:
382 self.emit('LOAD_CLOSURE', name)
383 self.emit('LOAD_CONST', gen)
384 self.emit('MAKE_CLOSURE', len(node.defaults))
385 else:
386 self.emit('LOAD_CONST', gen)
387 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000388
389 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000390 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000391 self.get_module())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000392 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000393 self.emit('LOAD_CONST', node.doc)
394 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000395 walk(node.code, gen)
396 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000397 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000398 self.emit('LOAD_CONST', node.name)
399 for base in node.bases:
400 self.visit(base)
401 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000402 frees = gen.scope.get_free_vars()
403 for name in frees:
404 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000405 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000406 if frees:
407 self.emit('MAKE_CLOSURE', 0)
408 else:
409 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000410 self.emit('CALL_FUNCTION', 0)
411 self.emit('BUILD_CLASS')
412 self.storeName(node.name)
413
414 # The rest are standard visitor methods
415
416 # The next few implement control-flow statements
417
418 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000419 end = self.newBlock()
420 numtests = len(node.tests)
421 for i in range(numtests):
422 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000423 if is_constant_false(test):
424 # XXX will need to check generator stuff here
425 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000426 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000427 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000428 nextTest = self.newBlock()
429 self.emit('JUMP_IF_FALSE', nextTest)
430 self.nextBlock()
431 self.emit('POP_TOP')
432 self.visit(suite)
433 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000434 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000435 self.emit('POP_TOP')
436 if node.else_:
437 self.visit(node.else_)
438 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000439
440 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000441 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000442
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000443 loop = self.newBlock()
444 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000445
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000446 after = self.newBlock()
447 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000448
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000449 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000450 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000451
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000452 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000453 self.visit(node.test)
454 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000455
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000456 self.nextBlock()
457 self.emit('POP_TOP')
458 self.visit(node.body)
459 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000460
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000461 self.startBlock(else_) # or just the POPs if not else clause
462 self.emit('POP_TOP')
463 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000464 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000465 if node.else_:
466 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000467 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000468
469 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000470 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000471 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000472 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000473 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000474
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000475 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000476 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000477 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000478 self.emit('GET_ITER')
479
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000480 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000481 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000482 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 self.visit(node.assign)
484 self.visit(node.body)
485 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000486 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000487 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000488 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000489 if node.else_:
490 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000491 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000492
493 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000494 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000495 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000496 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000497 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000498 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000499
500 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000501 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000502 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000503 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000504 kind, block = self.setups.top()
505 if kind == LOOP:
506 self.set_lineno(node)
507 self.emit('JUMP_ABSOLUTE', block)
508 self.nextBlock()
509 elif kind == EXCEPT or kind == TRY_FINALLY:
510 self.set_lineno(node)
511 # find the block that starts the loop
512 top = len(self.setups)
513 while top > 0:
514 top = top - 1
515 kind, loop_block = self.setups[top]
516 if kind == LOOP:
517 break
518 if kind != LOOP:
519 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000520 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000521 self.emit('CONTINUE_LOOP', loop_block)
522 self.nextBlock()
523 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000524 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000525 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000526
527 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000528 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000529 for child in node.nodes[:-1]:
530 self.visit(child)
531 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000532 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000533 self.emit('POP_TOP')
534 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000535 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000536
537 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000538 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000539
540 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000541 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000542
543 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000544 self.visit(node.expr)
545 cleanup = self.newBlock()
546 for op, code in node.ops[:-1]:
547 self.visit(code)
548 self.emit('DUP_TOP')
549 self.emit('ROT_THREE')
550 self.emit('COMPARE_OP', op)
551 self.emit('JUMP_IF_FALSE', cleanup)
552 self.nextBlock()
553 self.emit('POP_TOP')
554 # now do the last comparison
555 if node.ops:
556 op, code = node.ops[-1]
557 self.visit(code)
558 self.emit('COMPARE_OP', op)
559 if len(node.ops) > 1:
560 end = self.newBlock()
561 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000562 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000563 self.emit('ROT_TWO')
564 self.emit('POP_TOP')
565 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000566
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000567 # list comprehensions
568 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000569
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000570 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000571 self.set_lineno(node)
572 # setup list
573 append = "$append%d" % self.__list_count
574 self.__list_count = self.__list_count + 1
575 self.emit('BUILD_LIST', 0)
576 self.emit('DUP_TOP')
577 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000578 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000579
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000580 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000581 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000582 start, anchor = self.visit(for_)
583 cont = None
584 for if_ in for_.ifs:
585 if cont is None:
586 cont = self.newBlock()
587 self.visit(if_, cont)
588 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000589
Jeremy Hylton13d70942001-04-12 21:04:43 +0000590 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000591 self.visit(node.expr)
592 self.emit('CALL_FUNCTION', 1)
593 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000594
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000595 for start, cont, anchor in stack:
596 if cont:
597 skip_one = self.newBlock()
598 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000599 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000600 self.emit('POP_TOP')
601 self.nextBlock(skip_one)
602 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000603 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000604 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000605
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000606 self.__list_count = self.__list_count - 1
607
608 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000609 start = self.newBlock()
610 anchor = self.newBlock()
611
612 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000613 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000614 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000615 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000616 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000617 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000618 self.visit(node.assign)
619 return start, anchor
620
621 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000622 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000623 self.visit(node.test)
624 self.emit('JUMP_IF_FALSE', branch)
625 self.newBlock()
626 self.emit('POP_TOP')
627
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000628 # exception related
629
630 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000631 # XXX would be interesting to implement this via a
632 # transformation of the AST before this stage
633 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000634 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000635 # XXX __debug__ and AssertionError appear to be special cases
636 # -- they are always loaded as globals even if there are local
637 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000638 self.emit('LOAD_GLOBAL', '__debug__')
639 self.emit('JUMP_IF_FALSE', end)
640 self.nextBlock()
641 self.emit('POP_TOP')
642 self.visit(node.test)
643 self.emit('JUMP_IF_TRUE', end)
644 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000645 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000646 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000647 if node.fail:
648 self.visit(node.fail)
649 self.emit('RAISE_VARARGS', 2)
650 else:
651 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000652 self.nextBlock(end)
653 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000654
655 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000656 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000657 n = 0
658 if node.expr1:
659 self.visit(node.expr1)
660 n = n + 1
661 if node.expr2:
662 self.visit(node.expr2)
663 n = n + 1
664 if node.expr3:
665 self.visit(node.expr3)
666 n = n + 1
667 self.emit('RAISE_VARARGS', n)
668
669 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000670 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000671 handlers = self.newBlock()
672 end = self.newBlock()
673 if node.else_:
674 lElse = self.newBlock()
675 else:
676 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000677 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000678 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000679 self.nextBlock(body)
680 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000681 self.visit(node.body)
682 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000683 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000684 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000685 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000686
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000687 last = len(node.handlers) - 1
688 for i in range(len(node.handlers)):
689 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000690 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000691 if expr:
692 self.emit('DUP_TOP')
693 self.visit(expr)
694 self.emit('COMPARE_OP', 'exception match')
695 next = self.newBlock()
696 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000697 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000698 self.emit('POP_TOP')
699 self.emit('POP_TOP')
700 if target:
701 self.visit(target)
702 else:
703 self.emit('POP_TOP')
704 self.emit('POP_TOP')
705 self.visit(body)
706 self.emit('JUMP_FORWARD', end)
707 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000708 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000709 else:
710 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000711 if expr: # XXX
712 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000713 self.emit('END_FINALLY')
714 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000715 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000716 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000717 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000718
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000719 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000720 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000722 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000723 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000724 self.nextBlock(body)
725 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000726 self.visit(node.body)
727 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000728 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000729 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000730 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000731 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000732 self.visit(node.final)
733 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000734 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000735
736 # misc
737
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000738 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000739 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000740 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000741 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000742
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000743 def visitConst(self, node):
744 self.emit('LOAD_CONST', node.value)
745
746 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000747 self.emit('LOAD_CONST', node.name)
748 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000749
750 def visitGlobal(self, node):
751 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000752 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000753
754 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000755 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000756 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000757
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000758 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000759 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000760
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000761 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000762 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000763 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000764 if VERSION > 1:
765 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000766 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000767 mod = string.split(name, ".")[0]
768 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000769
770 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000771 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000772 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000773 if VERSION > 1:
774 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000775 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000776 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000777 if VERSION > 1:
778 if name == '*':
779 self.namespace = 0
780 self.emit('IMPORT_STAR')
781 # There can only be one name w/ from ... import *
782 assert len(node.names) == 1
783 return
784 else:
785 self.emit('IMPORT_FROM', name)
786 self._resolveDots(name)
787 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000788 else:
789 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000790 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000791
Jeremy Hylton20516082000-09-01 20:33:26 +0000792 def _resolveDots(self, name):
793 elts = string.split(name, ".")
794 if len(elts) == 1:
795 return
796 for elt in elts[1:]:
797 self.emit('LOAD_ATTR', elt)
798
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000799 def visitGetattr(self, node):
800 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000801 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000802
803 # next five implement assignments
804
805 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000806 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000807 self.visit(node.expr)
808 dups = len(node.nodes) - 1
809 for i in range(len(node.nodes)):
810 elt = node.nodes[i]
811 if i < dups:
812 self.emit('DUP_TOP')
813 if isinstance(elt, ast.Node):
814 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000815
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000816 def visitAssName(self, node):
817 if node.flags == 'OP_ASSIGN':
818 self.storeName(node.name)
819 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000820 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000821 self.delName(node.name)
822 else:
823 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000824
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000825 def visitAssAttr(self, node):
826 self.visit(node.expr)
827 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000828 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000829 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000830 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000831 else:
832 print "warning: unexpected flags:", node.flags
833 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000834
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000835 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000836 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000837 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000838 for child in node.nodes:
839 self.visit(child)
840
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000841 if VERSION > 1:
842 visitAssTuple = _visitAssSequence
843 visitAssList = _visitAssSequence
844 else:
845 def visitAssTuple(self, node):
846 self._visitAssSequence(node, 'UNPACK_TUPLE')
847
848 def visitAssList(self, node):
849 self._visitAssSequence(node, 'UNPACK_LIST')
850
851 # augmented assignment
852
853 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000854 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000855 aug_node = wrap_aug(node.node)
856 self.visit(aug_node, "load")
857 self.visit(node.expr)
858 self.emit(self._augmented_opcode[node.op])
859 self.visit(aug_node, "store")
860
861 _augmented_opcode = {
862 '+=' : 'INPLACE_ADD',
863 '-=' : 'INPLACE_SUBTRACT',
864 '*=' : 'INPLACE_MULTIPLY',
865 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000866 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000867 '%=' : 'INPLACE_MODULO',
868 '**=': 'INPLACE_POWER',
869 '>>=': 'INPLACE_RSHIFT',
870 '<<=': 'INPLACE_LSHIFT',
871 '&=' : 'INPLACE_AND',
872 '^=' : 'INPLACE_XOR',
873 '|=' : 'INPLACE_OR',
874 }
875
876 def visitAugName(self, node, mode):
877 if mode == "load":
878 self.loadName(node.name)
879 elif mode == "store":
880 self.storeName(node.name)
881
882 def visitAugGetattr(self, node, mode):
883 if mode == "load":
884 self.visit(node.expr)
885 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000886 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000887 elif mode == "store":
888 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000889 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000890
891 def visitAugSlice(self, node, mode):
892 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000893 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000894 elif mode == "store":
895 slice = 0
896 if node.lower:
897 slice = slice | 1
898 if node.upper:
899 slice = slice | 2
900 if slice == 0:
901 self.emit('ROT_TWO')
902 elif slice == 3:
903 self.emit('ROT_FOUR')
904 else:
905 self.emit('ROT_THREE')
906 self.emit('STORE_SLICE+%d' % slice)
907
908 def visitAugSubscript(self, node, mode):
909 if len(node.subs) > 1:
910 raise SyntaxError, "augmented assignment to tuple is not possible"
911 if mode == "load":
912 self.visitSubscript(node, 1)
913 elif mode == "store":
914 self.emit('ROT_THREE')
915 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000916
917 def visitExec(self, node):
918 self.visit(node.expr)
919 if node.locals is None:
920 self.emit('LOAD_CONST', None)
921 else:
922 self.visit(node.locals)
923 if node.globals is None:
924 self.emit('DUP_TOP')
925 else:
926 self.visit(node.globals)
927 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000928
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000929 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000930 pos = 0
931 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000932 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000933 self.visit(node.node)
934 for arg in node.args:
935 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000936 if isinstance(arg, ast.Keyword):
937 kw = kw + 1
938 else:
939 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000940 if node.star_args is not None:
941 self.visit(node.star_args)
942 if node.dstar_args is not None:
943 self.visit(node.dstar_args)
944 have_star = node.star_args is not None
945 have_dstar = node.dstar_args is not None
946 opcode = callfunc_opcode_info[have_star, have_dstar]
947 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000948
Jeremy Hylton2afff322001-08-27 21:51:52 +0000949 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000950 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000951 if node.dest:
952 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000953 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000954 if node.dest:
955 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000956 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000957 if node.dest:
958 self.emit('ROT_TWO')
959 self.emit('PRINT_ITEM_TO')
960 else:
961 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000962 if node.dest and not newline:
963 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000964
965 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000966 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000967 if node.dest:
968 self.emit('PRINT_NEWLINE_TO')
969 else:
970 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000971
972 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000973 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000974 self.visit(node.value)
975 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000976
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000977 def visitYield(self, node):
978 self.set_lineno(node)
979 self.visit(node.value)
980 self.emit('YIELD_STMT')
981
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000982 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000983
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000984 def visitSlice(self, node, aug_flag=None):
985 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000986 self.visit(node.expr)
987 slice = 0
988 if node.lower:
989 self.visit(node.lower)
990 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000991 if node.upper:
992 self.visit(node.upper)
993 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000994 if aug_flag:
995 if slice == 0:
996 self.emit('DUP_TOP')
997 elif slice == 3:
998 self.emit('DUP_TOPX', 3)
999 else:
1000 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001001 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001002 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001003 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001004 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001005 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +00001006 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001007 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +00001008 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001009 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001010
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001011 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +00001012 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001013 for sub in node.subs:
1014 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001015 if aug_flag:
1016 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001017 if len(node.subs) > 1:
1018 self.emit('BUILD_TUPLE', len(node.subs))
1019 if node.flags == 'OP_APPLY':
1020 self.emit('BINARY_SUBSCR')
1021 elif node.flags == 'OP_ASSIGN':
1022 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001023 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001024 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001025
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001026 # binary ops
1027
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001028 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001029 self.visit(node.left)
1030 self.visit(node.right)
1031 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001032
1033 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001034 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001035
1036 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001037 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001038
1039 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001040 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001041
1042 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +00001043 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001044
Jeremy Hylton94afe322001-08-29 18:14:39 +00001045 def visitFloorDiv(self, node):
1046 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1047
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001048 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001049 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001050
Jeremy Hylton126960b2000-02-14 21:33:10 +00001051 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001052 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001053
1054 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001055 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001056
1057 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001058 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +00001059
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001060 # unary ops
1061
1062 def unaryOp(self, node, op):
1063 self.visit(node.expr)
1064 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001065
Jeremy Hylton126960b2000-02-14 21:33:10 +00001066 def visitInvert(self, node):
1067 return self.unaryOp(node, 'UNARY_INVERT')
1068
Jeremy Hylton40245602000-02-08 21:15:48 +00001069 def visitUnarySub(self, node):
1070 return self.unaryOp(node, 'UNARY_NEGATIVE')
1071
1072 def visitUnaryAdd(self, node):
1073 return self.unaryOp(node, 'UNARY_POSITIVE')
1074
1075 def visitUnaryInvert(self, node):
1076 return self.unaryOp(node, 'UNARY_INVERT')
1077
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001078 def visitNot(self, node):
1079 return self.unaryOp(node, 'UNARY_NOT')
1080
Jeremy Hylton40245602000-02-08 21:15:48 +00001081 def visitBackquote(self, node):
1082 return self.unaryOp(node, 'UNARY_CONVERT')
1083
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001084 # bit ops
1085
Jeremy Hyltona5058122000-02-14 14:14:29 +00001086 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001087 self.visit(nodes[0])
1088 for node in nodes[1:]:
1089 self.visit(node)
1090 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001091
1092 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001093 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001094
1095 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001096 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001097
1098 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001099 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001100
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001101 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001102
Jeremy Hyltona5058122000-02-14 14:14:29 +00001103 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001104 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001105
Jeremy Hylton40245602000-02-08 21:15:48 +00001106 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001107 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001108 for elt in node.nodes:
1109 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001110 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001111
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001112 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001113 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001114 for elt in node.nodes:
1115 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001116 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001117
1118 def visitSliceobj(self, node):
1119 for child in node.nodes:
1120 self.visit(child)
1121 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001122
Jeremy Hyltona5058122000-02-14 14:14:29 +00001123 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001124 lineno = getattr(node, 'lineno', None)
1125 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001126 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001127 self.emit('BUILD_MAP', 0)
1128 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001129 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001130 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001131 self.emit('SET_LINENO', lineno2)
1132 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001133 self.emit('DUP_TOP')
1134 self.visit(v)
1135 self.emit('ROT_TWO')
1136 self.visit(k)
1137 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001138
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001139class NestedScopeMixin:
1140 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001141 def initClass(self):
1142 self.__class__.NameFinder = LocalNameFinder
1143 self.__class__.FunctionGen = FunctionCodeGenerator
1144 self.__class__.ClassGen = ClassCodeGenerator
1145
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001146class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001147 __super_init = CodeGenerator.__init__
1148
1149 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001150
Jeremy Hylton37c93512001-09-17 18:03:55 +00001151 def __init__(self, tree):
1152 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001153 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001154 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001155 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001156
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001157 def get_module(self):
1158 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001159
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001160class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1161 __super_init = CodeGenerator.__init__
1162
1163 scopes = None
1164 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001165
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001166 def __init__(self, tree):
1167 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1168 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001169 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001170
1171 def get_module(self):
1172 return self
1173
1174class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1175
1176 __super_init = CodeGenerator.__init__
1177
1178 scopes = None
1179 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001180
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001181 def __init__(self, tree):
1182 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1183 self.__super_init()
1184 self.set_lineno(tree)
1185 walk(tree, self)
1186 self.emit('RETURN_VALUE')
1187
1188 def get_module(self):
1189 return self
Tim Peterse4418602002-02-16 07:34:19 +00001190
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001191 def visitDiscard(self, node):
1192 # XXX Discard means it's an expression. Perhaps this is a bad
1193 # name.
1194 self.visit(node.expr)
1195 self.emit('PRINT_EXPR')
1196
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001197class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001198 optimized = 1
1199 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001200
Jeremy Hylton37c93512001-09-17 18:03:55 +00001201 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001202 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001203 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001204 if isLambda:
1205 klass = FunctionCodeGenerator
1206 name = "<lambda.%d>" % klass.lambdaCount
1207 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001208 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001209 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001210 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001211 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1212 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001213 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001214 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001215
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001216 if not isLambda and func.doc:
1217 self.setDocstring(func.doc)
1218
Jeremy Hylton2afff322001-08-27 21:51:52 +00001219 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001220 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001221 if func.varargs:
1222 self.graph.setFlag(CO_VARARGS)
1223 if func.kwargs:
1224 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001225 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001226 if hasTupleArg:
1227 self.generateArgUnpack(func.argnames)
1228
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001229 def get_module(self):
1230 return self.module
1231
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001232 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001233 self.graph.startExitBlock()
1234 if not self.isLambda:
1235 self.emit('LOAD_CONST', None)
1236 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001237
1238 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001239 for i in range(len(args)):
1240 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001241 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001242 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001243 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001244
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001245 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001246 if VERSION > 1:
1247 self.emit('UNPACK_SEQUENCE', len(tup))
1248 else:
1249 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001250 for elt in tup:
1251 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001252 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001253 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001254 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001255
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001256 unpackTuple = unpackSequence
1257
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001258class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001259 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001260 super_init = CodeGenerator.__init__ # call be other init
1261 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001262
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001263 __super_init = AbstractFunctionCode.__init__
1264
Jeremy Hylton37c93512001-09-17 18:03:55 +00001265 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001266 self.scopes = scopes
1267 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001268 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001269 self.graph.setFreeVars(self.scope.get_free_vars())
1270 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001271 if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
1272 if self.scope.generator is not None:
1273 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001274
1275class AbstractClassCode:
1276
Jeremy Hylton37c93512001-09-17 18:03:55 +00001277 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001278 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001279 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001280 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001281 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001282 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001283 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001284 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001285 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001286 if klass.doc:
1287 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001288
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001289 def get_module(self):
1290 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001291
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001292 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001293 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001294 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001295 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001296
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001297class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001298 super_init = CodeGenerator.__init__
1299 scopes = None
1300
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001301 __super_init = AbstractClassCode.__init__
1302
Jeremy Hylton37c93512001-09-17 18:03:55 +00001303 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001304 self.scopes = scopes
1305 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001306 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001307 self.graph.setFreeVars(self.scope.get_free_vars())
1308 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001309
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001310def generateArgList(arglist):
1311 """Generate an arg list marking TupleArgs"""
1312 args = []
1313 extra = []
1314 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001315 for i in range(len(arglist)):
1316 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001317 if type(elt) == types.StringType:
1318 args.append(elt)
1319 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001320 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001321 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001322 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001323 else:
1324 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001325 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001326
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001327def findOp(node):
1328 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1329 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001330 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001331 return v.op
1332
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001333class OpFinder:
1334 def __init__(self):
1335 self.op = None
1336 def visitAssName(self, node):
1337 if self.op is None:
1338 self.op = node.flags
1339 elif self.op != node.flags:
1340 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001341 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001342 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001343
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001344class Delegator:
1345 """Base class to support delegation for augmented assignment nodes
1346
1347 To generator code for augmented assignments, we use the following
1348 wrapper classes. In visitAugAssign, the left-hand expression node
1349 is visited twice. The first time the visit uses the normal method
1350 for that node . The second time the visit uses a different method
1351 that generates the appropriate code to perform the assignment.
1352 These delegator classes wrap the original AST nodes in order to
1353 support the variant visit methods.
1354 """
1355 def __init__(self, obj):
1356 self.obj = obj
1357
1358 def __getattr__(self, attr):
1359 return getattr(self.obj, attr)
1360
1361class AugGetattr(Delegator):
1362 pass
1363
1364class AugName(Delegator):
1365 pass
1366
1367class AugSlice(Delegator):
1368 pass
1369
1370class AugSubscript(Delegator):
1371 pass
1372
1373wrapper = {
1374 ast.Getattr: AugGetattr,
1375 ast.Name: AugName,
1376 ast.Slice: AugSlice,
1377 ast.Subscript: AugSubscript,
1378 }
1379
1380def wrap_aug(node):
1381 return wrapper[node.__class__](node)
1382
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001383if __name__ == "__main__":
1384 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001385
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001386 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001387 compileFile(file)