blob: 009afbd09d06795a7c1a47dff977787b16e98628 [file] [log] [blame]
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001import imp
Jeremy Hylton53187f32000-02-08 19:01:29 +00002import os
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00003import marshal
Jeremy Hylton53187f32000-02-08 19:01:29 +00004import struct
Jeremy Hylton9c048f92000-10-13 21:58:13 +00005import sys
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00006import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00007from cStringIO import StringIO
8
Jeremy Hylton37c93512001-09-17 18:03:55 +00009from compiler import ast, parse, walk, syntax
Jeremy Hylton364f9b92001-04-12 06:40:42 +000010from compiler import pyassem, misc, future, symbols
11from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
Jeremy Hylton71ebc332001-08-30 20:25:55 +000012from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000013 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000015
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000016# XXX The version-specific code can go, since this code only works with 2.x.
Jeremy Hylton9c048f92000-10-13 21:58:13 +000017# Do we have Python 1.x or Python 2.x?
18try:
19 VERSION = sys.version_info[0]
20except AttributeError:
21 VERSION = 1
22
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000023callfunc_opcode_info = {
24 # (Have *args, Have **args) : opcode
25 (0,0) : "CALL_FUNCTION",
26 (1,0) : "CALL_FUNCTION_VAR",
27 (0,1) : "CALL_FUNCTION_KW",
28 (1,1) : "CALL_FUNCTION_VAR_KW",
29}
30
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000031LOOP = 1
32EXCEPT = 2
33TRY_FINALLY = 3
34END_FINALLY = 4
35
Jeremy Hylton9dca3642001-09-17 21:02:51 +000036def compileFile(filename, display=0):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000037 f = open(filename, 'U')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000038 buf = f.read()
39 f.close()
40 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000041 try:
42 mod.compile(display)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +000043 except SyntaxError:
Jeremy Hylton2e4cc7e2001-09-17 19:33:48 +000044 raise
Jeremy Hylton37c93512001-09-17 18:03:55 +000045 else:
46 f = open(filename + "c", "wb")
47 mod.dump(f)
48 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000049
Jeremy Hylton9dca3642001-09-17 21:02:51 +000050def compile(source, filename, mode, flags=None, dont_inherit=None):
51 """Replacement for builtin compile() function"""
52 if flags is not None or dont_inherit is not None:
53 raise RuntimeError, "not implemented yet"
Tim Peterse0c446b2001-10-18 21:57:37 +000054
Jeremy Hylton9dca3642001-09-17 21:02:51 +000055 if mode == "single":
56 gen = Interactive(source, filename)
57 elif mode == "exec":
58 gen = Module(source, filename)
59 elif mode == "eval":
60 gen = Expression(source, filename)
61 else:
62 raise ValueError("compile() 3rd arg must be 'exec' or "
63 "'eval' or 'single'")
64 gen.compile()
65 return gen.code
66
67class AbstractCompileMode:
68
69 mode = None # defined by subclass
70
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000071 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000072 self.source = source
Jeremy Hylton9dca3642001-09-17 21:02:51 +000073 self.filename = filename
Thomas Wouters46cc7c02000-08-12 20:32:46 +000074 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000075
Jeremy Hylton9dca3642001-09-17 21:02:51 +000076 def _get_tree(self):
77 tree = parse(self.source, self.mode)
Jeremy Hylton37c93512001-09-17 18:03:55 +000078 misc.set_filename(self.filename, tree)
79 syntax.check(tree)
Jeremy Hylton9dca3642001-09-17 21:02:51 +000080 return tree
81
82 def compile(self):
83 pass # implemented by subclass
84
85 def getCode(self):
86 return self.code
87
88class Expression(AbstractCompileMode):
89
90 mode = "eval"
91
92 def compile(self):
93 tree = self._get_tree()
94 gen = ExpressionCodeGenerator(tree)
95 self.code = gen.getCode()
96
97class Interactive(AbstractCompileMode):
98
99 mode = "single"
100
101 def compile(self):
102 tree = self._get_tree()
103 gen = InteractiveCodeGenerator(tree)
104 self.code = gen.getCode()
105
106class Module(AbstractCompileMode):
107
108 mode = "exec"
109
110 def compile(self, display=0):
111 tree = self._get_tree()
Jeremy Hylton37c93512001-09-17 18:03:55 +0000112 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000113 if display:
114 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000115 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000116 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000117
118 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000119 f.write(self.getPycHeader())
120 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000121
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000122 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000123
124 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000125 # compile.c uses marshal to write a long directly, with
126 # calling the interface that would also generate a 1-byte code
127 # to indicate the type of the value. simplest way to get the
128 # same effect is to call marshal and then skip the code.
Neal Norwitza312c3a2002-06-06 18:30:10 +0000129 mtime = os.path.getmtime(self.filename)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000130 mtime = struct.pack('<i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000131 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000132
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000133class LocalNameFinder:
134 """Find local names in scope"""
135 def __init__(self, names=()):
136 self.names = misc.Set()
137 self.globals = misc.Set()
138 for name in names:
139 self.names.add(name)
140
141 # XXX list comprehensions and for loops
142
143 def getLocals(self):
144 for elt in self.globals.elements():
145 if self.names.has_elt(elt):
146 self.names.remove(elt)
147 return self.names
148
149 def visitDict(self, node):
150 pass
151
152 def visitGlobal(self, node):
153 for name in node.names:
154 self.globals.add(name)
155
156 def visitFunction(self, node):
157 self.names.add(node.name)
158
159 def visitLambda(self, node):
160 pass
161
162 def visitImport(self, node):
163 for name, alias in node.names:
164 self.names.add(alias or name)
165
166 def visitFrom(self, node):
167 for name, alias in node.names:
168 self.names.add(alias or name)
169
170 def visitClass(self, node):
171 self.names.add(node.name)
172
173 def visitAssName(self, node):
174 self.names.add(node.name)
175
Jeremy Hylton2afff322001-08-27 21:51:52 +0000176def is_constant_false(node):
177 if isinstance(node, ast.Const):
178 if not node.value:
179 return 1
180 return 0
181
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000182class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000183 """Defines basic code generator for Python bytecode
184
185 This class is an abstract base class. Concrete subclasses must
186 define an __init__() that defines self.graph and then calls the
187 __init__() defined in this class.
188
189 The concrete class must also define the class attributes
190 NameFinder, FunctionGen, and ClassGen. These attributes can be
191 defined in the initClass() method, which is a hook for
192 initializing these methods after all the classes have been
Tim Peterse0c446b2001-10-18 21:57:37 +0000193 defined.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000194 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000195
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000196 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000197 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000198 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000199
Jeremy Hylton37c93512001-09-17 18:03:55 +0000200 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000201 if self.__initialized is None:
202 self.initClass()
203 self.__class__.__initialized = 1
204 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000205 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000206 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000207 self.curStack = 0
208 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000209 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000210 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000211 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000212
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000213 # XXX set flags based on future features
214 futures = self.get_module().futures
215 for feature in futures:
216 if feature == "division":
217 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000218 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000219 elif feature == "generators":
220 self.graph.setFlag(CO_GENERATOR_ALLOWED)
221
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000222 def initClass(self):
223 """This method is called once for each class"""
224
225 def checkClass(self):
226 """Verify that class is constructed correctly"""
227 try:
228 assert hasattr(self, 'graph')
229 assert getattr(self, 'NameFinder')
230 assert getattr(self, 'FunctionGen')
231 assert getattr(self, 'ClassGen')
232 except AssertionError, msg:
233 intro = "Bad class construction for %s" % self.__class__.__name__
234 raise AssertionError, intro
235
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000237 self.emit = self.graph.emit
238 self.newBlock = self.graph.newBlock
239 self.startBlock = self.graph.startBlock
240 self.nextBlock = self.graph.nextBlock
241 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000242
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000243 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000244 """Return a code object"""
245 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000246
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000247 def mangle(self, name):
248 if self.class_name is not None:
249 return misc.mangle(name, self.class_name)
250 else:
251 return name
252
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000253 def parseSymbols(self, tree):
254 s = symbols.SymbolVisitor()
255 walk(tree, s)
256 return s.scopes
257
258 def get_module(self):
259 raise RuntimeError, "should be implemented by subclasses"
260
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000261 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000262
Jeremy Hylton40245602000-02-08 21:15:48 +0000263 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000264 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000265
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000266 def storeName(self, name):
267 self._nameOp('STORE', name)
268
269 def loadName(self, name):
270 self._nameOp('LOAD', name)
271
272 def delName(self, name):
273 self._nameOp('DELETE', name)
274
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000275 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000276 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000277 scope = self.scope.check_name(name)
278 if scope == SC_LOCAL:
279 if not self.optimized:
280 self.emit(prefix + '_NAME', name)
281 else:
282 self.emit(prefix + '_FAST', name)
283 elif scope == SC_GLOBAL:
284 if not self.optimized:
285 self.emit(prefix + '_NAME', name)
286 else:
287 self.emit(prefix + '_GLOBAL', name)
288 elif scope == SC_FREE or scope == SC_CELL:
289 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000290 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000291 raise RuntimeError, "unsupported scope for var %s: %d" % \
292 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000293
Jeremy Hylton13d70942001-04-12 21:04:43 +0000294 def _implicitNameOp(self, prefix, name):
295 """Emit name ops for names generated implicitly by for loops
296
297 The interpreter generates names that start with a period or
298 dollar sign. The symbol table ignores these names because
299 they aren't present in the program text.
300 """
301 if self.optimized:
302 self.emit(prefix + '_FAST', name)
303 else:
304 self.emit(prefix + '_NAME', name)
305
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000306 # The set_lineno() function and the explicit emit() calls for
307 # SET_LINENO below are only used to generate the line number table.
308 # As of Python 2.3, the interpreter does not have a SET_LINENO
309 # instruction. pyassem treats SET_LINENO opcodes as a special case.
310
311 def set_lineno(self, node, force=False):
312 """Emit SET_LINENO if necessary.
313
314 The instruction is considered necessary if the node has a
315 lineno attribute and it is different than the last lineno
316 emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000317
318 Returns true if SET_LINENO was emitted.
319
320 There are no rules for when an AST node should have a lineno
321 attribute. The transformer and AST code need to be reviewed
322 and a consistent policy implemented and documented. Until
323 then, this method works around missing line numbers.
324 """
325 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000326 if lineno is not None and (lineno != self.last_lineno
327 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000328 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000329 self.last_lineno = lineno
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000330 return True
331 return False
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000332
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000333 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000334 # code objects. They use class attributes to determine what
335 # specialized code generators to use.
336
337 NameFinder = LocalNameFinder
338 FunctionGen = None
339 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000340
341 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000342 self.scopes = self.parseSymbols(node)
343 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000344 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000345 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000346 self.emit('LOAD_CONST', node.doc)
347 self.storeName('__doc__')
348 lnf = walk(node.node, self.NameFinder(), verbose=0)
349 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000350 self.visit(node.node)
351 self.emit('LOAD_CONST', None)
352 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000353
Barry Warsaw52acb492001-12-21 20:04:22 +0000354 def visitExpression(self, node):
355 self.set_lineno(node)
356 self.scopes = self.parseSymbols(node)
357 self.scope = self.scopes[node]
358 self.visit(node.node)
359 self.emit('RETURN_VALUE')
360
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000361 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000362 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000363 if node.doc:
364 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000365 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000366
367 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000368 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000370 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000371 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000372 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000373 walk(node.code, gen)
374 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000375 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000376 for default in node.defaults:
377 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000378 frees = gen.scope.get_free_vars()
379 if frees:
380 for name in frees:
381 self.emit('LOAD_CLOSURE', name)
382 self.emit('LOAD_CONST', gen)
383 self.emit('MAKE_CLOSURE', len(node.defaults))
384 else:
385 self.emit('LOAD_CONST', gen)
386 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000387
388 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000389 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000390 self.get_module())
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000391 walk(node.code, gen)
392 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000393 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000394 self.emit('LOAD_CONST', node.name)
395 for base in node.bases:
396 self.visit(base)
397 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000398 frees = gen.scope.get_free_vars()
399 for name in frees:
400 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000401 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000402 if frees:
403 self.emit('MAKE_CLOSURE', 0)
404 else:
405 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000406 self.emit('CALL_FUNCTION', 0)
407 self.emit('BUILD_CLASS')
408 self.storeName(node.name)
409
410 # The rest are standard visitor methods
411
412 # The next few implement control-flow statements
413
414 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000415 end = self.newBlock()
416 numtests = len(node.tests)
417 for i in range(numtests):
418 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000419 if is_constant_false(test):
420 # XXX will need to check generator stuff here
421 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000422 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000423 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000424 nextTest = self.newBlock()
425 self.emit('JUMP_IF_FALSE', nextTest)
426 self.nextBlock()
427 self.emit('POP_TOP')
428 self.visit(suite)
429 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000430 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000431 self.emit('POP_TOP')
432 if node.else_:
433 self.visit(node.else_)
434 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000435
436 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000437 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000438
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000439 loop = self.newBlock()
440 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000441
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000442 after = self.newBlock()
443 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000444
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000445 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000446 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000447
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000448 self.set_lineno(node, force=True)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000449 self.visit(node.test)
450 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000451
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000452 self.nextBlock()
453 self.emit('POP_TOP')
454 self.visit(node.body)
455 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000456
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000457 self.startBlock(else_) # or just the POPs if not else clause
458 self.emit('POP_TOP')
459 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000460 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000461 if node.else_:
462 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000463 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000464
465 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000466 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000467 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000468 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000469 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000470
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000471 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000472 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000473 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000474 self.emit('GET_ITER')
475
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000476 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000477 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000478 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479 self.visit(node.assign)
480 self.visit(node.body)
481 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000482 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000483 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000484 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000485 if node.else_:
486 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000487 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000488
489 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000490 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000491 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000492 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000493 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000494 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000495
496 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000497 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000498 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000499 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000500 kind, block = self.setups.top()
501 if kind == LOOP:
502 self.set_lineno(node)
503 self.emit('JUMP_ABSOLUTE', block)
504 self.nextBlock()
505 elif kind == EXCEPT or kind == TRY_FINALLY:
506 self.set_lineno(node)
507 # find the block that starts the loop
508 top = len(self.setups)
509 while top > 0:
510 top = top - 1
511 kind, loop_block = self.setups[top]
512 if kind == LOOP:
513 break
514 if kind != LOOP:
515 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000516 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000517 self.emit('CONTINUE_LOOP', loop_block)
518 self.nextBlock()
519 elif kind == END_FINALLY:
Tim Peterse0c446b2001-10-18 21:57:37 +0000520 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000521 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000522
523 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000524 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000525 for child in node.nodes[:-1]:
526 self.visit(child)
527 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000528 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000529 self.emit('POP_TOP')
530 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000531 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000532
533 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000534 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000535
536 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000537 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000538
539 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000540 self.visit(node.expr)
541 cleanup = self.newBlock()
542 for op, code in node.ops[:-1]:
543 self.visit(code)
544 self.emit('DUP_TOP')
545 self.emit('ROT_THREE')
546 self.emit('COMPARE_OP', op)
547 self.emit('JUMP_IF_FALSE', cleanup)
548 self.nextBlock()
549 self.emit('POP_TOP')
550 # now do the last comparison
551 if node.ops:
552 op, code = node.ops[-1]
553 self.visit(code)
554 self.emit('COMPARE_OP', op)
555 if len(node.ops) > 1:
556 end = self.newBlock()
557 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000558 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000559 self.emit('ROT_TWO')
560 self.emit('POP_TOP')
561 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000562
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000563 # list comprehensions
564 __list_count = 0
Tim Peterse0c446b2001-10-18 21:57:37 +0000565
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000566 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000567 self.set_lineno(node)
568 # setup list
569 append = "$append%d" % self.__list_count
570 self.__list_count = self.__list_count + 1
571 self.emit('BUILD_LIST', 0)
572 self.emit('DUP_TOP')
573 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000574 self._implicitNameOp('STORE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000575
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000576 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000577 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000578 start, anchor = self.visit(for_)
579 cont = None
580 for if_ in for_.ifs:
581 if cont is None:
582 cont = self.newBlock()
583 self.visit(if_, cont)
584 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000585
Jeremy Hylton13d70942001-04-12 21:04:43 +0000586 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000587 self.visit(node.expr)
588 self.emit('CALL_FUNCTION', 1)
589 self.emit('POP_TOP')
Tim Peterse0c446b2001-10-18 21:57:37 +0000590
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000591 for start, cont, anchor in stack:
592 if cont:
593 skip_one = self.newBlock()
594 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000595 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000596 self.emit('POP_TOP')
597 self.nextBlock(skip_one)
598 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000599 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000600 self._implicitNameOp('DELETE', append)
Tim Peterse0c446b2001-10-18 21:57:37 +0000601
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000602 self.__list_count = self.__list_count - 1
603
604 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000605 start = self.newBlock()
606 anchor = self.newBlock()
607
608 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000609 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000610 self.nextBlock(start)
Jeremy Hylton18565412002-12-31 18:26:17 +0000611 self.set_lineno(node, force=True)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000612 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000613 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000614 self.visit(node.assign)
615 return start, anchor
616
617 def visitListCompIf(self, node, branch):
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000618 self.set_lineno(node, force=True)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000619 self.visit(node.test)
620 self.emit('JUMP_IF_FALSE', branch)
621 self.newBlock()
622 self.emit('POP_TOP')
623
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000624 # exception related
625
626 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000627 # XXX would be interesting to implement this via a
628 # transformation of the AST before this stage
629 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000630 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000631 # XXX __debug__ and AssertionError appear to be special cases
632 # -- they are always loaded as globals even if there are local
633 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000634 self.emit('LOAD_GLOBAL', '__debug__')
635 self.emit('JUMP_IF_FALSE', end)
636 self.nextBlock()
637 self.emit('POP_TOP')
638 self.visit(node.test)
639 self.emit('JUMP_IF_TRUE', end)
640 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000641 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000642 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000643 if node.fail:
644 self.visit(node.fail)
645 self.emit('RAISE_VARARGS', 2)
646 else:
647 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000648 self.nextBlock(end)
649 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000650
651 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000652 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000653 n = 0
654 if node.expr1:
655 self.visit(node.expr1)
656 n = n + 1
657 if node.expr2:
658 self.visit(node.expr2)
659 n = n + 1
660 if node.expr3:
661 self.visit(node.expr3)
662 n = n + 1
663 self.emit('RAISE_VARARGS', n)
664
665 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000666 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000667 handlers = self.newBlock()
668 end = self.newBlock()
669 if node.else_:
670 lElse = self.newBlock()
671 else:
672 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000673 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000674 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000675 self.nextBlock(body)
676 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000677 self.visit(node.body)
678 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000679 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000680 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000681 self.startBlock(handlers)
Tim Peterse0c446b2001-10-18 21:57:37 +0000682
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000683 last = len(node.handlers) - 1
684 for i in range(len(node.handlers)):
685 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000686 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000687 if expr:
688 self.emit('DUP_TOP')
689 self.visit(expr)
690 self.emit('COMPARE_OP', 'exception match')
691 next = self.newBlock()
692 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000693 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000694 self.emit('POP_TOP')
695 self.emit('POP_TOP')
696 if target:
697 self.visit(target)
698 else:
699 self.emit('POP_TOP')
700 self.emit('POP_TOP')
701 self.visit(body)
702 self.emit('JUMP_FORWARD', end)
703 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000704 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000705 else:
706 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000707 if expr: # XXX
708 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000709 self.emit('END_FINALLY')
710 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000711 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000712 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000713 self.nextBlock(end)
Tim Peterse0c446b2001-10-18 21:57:37 +0000714
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000715 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000716 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000717 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000718 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000719 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000720 self.nextBlock(body)
721 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000722 self.visit(node.body)
723 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000724 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000725 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000726 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000727 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000728 self.visit(node.final)
729 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000730 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000731
732 # misc
733
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000734 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000735 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000736 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000737 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000738
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000739 def visitConst(self, node):
740 self.emit('LOAD_CONST', node.value)
741
742 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000743 self.emit('LOAD_CONST', node.name)
744 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000745
746 def visitGlobal(self, node):
747 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000748 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000749
750 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000751 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000752 self.loadName(node.name)
Tim Peterse0c446b2001-10-18 21:57:37 +0000753
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000754 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000755 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000756
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000757 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000758 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000759 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000760 if VERSION > 1:
761 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000762 self.emit('IMPORT_NAME', name)
Neal Norwitza312c3a2002-06-06 18:30:10 +0000763 mod = name.split(".")[0]
Michael W. Hudson896e5162003-06-27 12:32:39 +0000764 if alias:
765 self._resolveDots(name)
766 self.storeName(alias)
767 else:
768 self.storeName(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):
Neal Norwitza312c3a2002-06-06 18:30:10 +0000793 elts = name.split(".")
Jeremy Hylton20516082000-09-01 20:33:26 +0000794 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)
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000980 self.emit('YIELD_VALUE')
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000981
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 Hylton18565412002-12-31 18:26:17 +00001124 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001125 self.emit('BUILD_MAP', 0)
1126 for k, v in node.items:
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001127 self.emit('DUP_TOP')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001128 self.visit(k)
Gustavo Niemeyer78429a62002-12-16 13:54:02 +00001129 self.visit(v)
1130 self.emit('ROT_THREE')
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001131 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001132
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001133class NestedScopeMixin:
1134 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001135 def initClass(self):
1136 self.__class__.NameFinder = LocalNameFinder
1137 self.__class__.FunctionGen = FunctionCodeGenerator
1138 self.__class__.ClassGen = ClassCodeGenerator
1139
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001140class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001141 __super_init = CodeGenerator.__init__
1142
1143 scopes = None
Tim Peterse0c446b2001-10-18 21:57:37 +00001144
Jeremy Hylton37c93512001-09-17 18:03:55 +00001145 def __init__(self, tree):
1146 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001147 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001148 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001149 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001150
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001151 def get_module(self):
1152 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001153
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001154class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
1155 __super_init = CodeGenerator.__init__
1156
1157 scopes = None
1158 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001159
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001160 def __init__(self, tree):
1161 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
1162 self.__super_init()
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001163 walk(tree, self)
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001164
1165 def get_module(self):
1166 return self
1167
1168class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1169
1170 __super_init = CodeGenerator.__init__
1171
1172 scopes = None
1173 futures = ()
Tim Peterse0c446b2001-10-18 21:57:37 +00001174
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001175 def __init__(self, tree):
1176 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
1177 self.__super_init()
1178 self.set_lineno(tree)
1179 walk(tree, self)
1180 self.emit('RETURN_VALUE')
1181
1182 def get_module(self):
1183 return self
Tim Peterse4418602002-02-16 07:34:19 +00001184
Jeremy Hylton9dca3642001-09-17 21:02:51 +00001185 def visitDiscard(self, node):
1186 # XXX Discard means it's an expression. Perhaps this is a bad
1187 # name.
1188 self.visit(node.expr)
1189 self.emit('PRINT_EXPR')
1190
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001191class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001192 optimized = 1
1193 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001194
Jeremy Hylton37c93512001-09-17 18:03:55 +00001195 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001196 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001197 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001198 if isLambda:
1199 klass = FunctionCodeGenerator
1200 name = "<lambda.%d>" % klass.lambdaCount
1201 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001202 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001203 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001204 args, hasTupleArg = generateArgList(func.argnames)
Tim Peterse0c446b2001-10-18 21:57:37 +00001205 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1206 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001207 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001208 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001209
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001210 if not isLambda and func.doc:
1211 self.setDocstring(func.doc)
1212
Jeremy Hylton2afff322001-08-27 21:51:52 +00001213 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001214 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001215 if func.varargs:
1216 self.graph.setFlag(CO_VARARGS)
1217 if func.kwargs:
1218 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001219 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001220 if hasTupleArg:
1221 self.generateArgUnpack(func.argnames)
1222
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001223 def get_module(self):
1224 return self.module
1225
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001226 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001227 self.graph.startExitBlock()
1228 if not self.isLambda:
1229 self.emit('LOAD_CONST', None)
1230 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001231
1232 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001233 for i in range(len(args)):
1234 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001235 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001236 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001237 self.unpackSequence(arg)
Tim Peterse0c446b2001-10-18 21:57:37 +00001238
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001239 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001240 if VERSION > 1:
1241 self.emit('UNPACK_SEQUENCE', len(tup))
1242 else:
1243 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001244 for elt in tup:
1245 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001246 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001247 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001248 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001249
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001250 unpackTuple = unpackSequence
1251
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001252class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Tim Peterse0c446b2001-10-18 21:57:37 +00001253 CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001254 super_init = CodeGenerator.__init__ # call be other init
1255 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001256
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001257 __super_init = AbstractFunctionCode.__init__
1258
Jeremy Hylton37c93512001-09-17 18:03:55 +00001259 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001260 self.scopes = scopes
1261 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001262 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001263 self.graph.setFreeVars(self.scope.get_free_vars())
1264 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001265 if self.scope.generator is not None:
1266 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001267
1268class AbstractClassCode:
1269
Jeremy Hylton37c93512001-09-17 18:03:55 +00001270 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001271 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001272 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001273 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001274 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001275 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001276 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001277 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001278 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001279 if klass.doc:
1280 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001281
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001282 def get_module(self):
1283 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001284
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001285 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001286 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001287 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001288 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001289
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001290class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001291 super_init = CodeGenerator.__init__
1292 scopes = None
1293
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001294 __super_init = AbstractClassCode.__init__
1295
Jeremy Hylton37c93512001-09-17 18:03:55 +00001296 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001297 self.scopes = scopes
1298 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001299 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001300 self.graph.setFreeVars(self.scope.get_free_vars())
1301 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +00001302 self.set_lineno(klass)
1303 self.emit("LOAD_GLOBAL", "__name__")
1304 self.storeName("__module__")
1305 if klass.doc:
1306 self.emit("LOAD_CONST", klass.doc)
1307 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001308
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001309def generateArgList(arglist):
1310 """Generate an arg list marking TupleArgs"""
1311 args = []
1312 extra = []
1313 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001314 for i in range(len(arglist)):
1315 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001316 if type(elt) == types.StringType:
1317 args.append(elt)
1318 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001319 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001320 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001321 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001322 else:
1323 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001324 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001325
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001326def findOp(node):
1327 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1328 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001329 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001330 return v.op
1331
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001332class OpFinder:
1333 def __init__(self):
1334 self.op = None
1335 def visitAssName(self, node):
1336 if self.op is None:
1337 self.op = node.flags
1338 elif self.op != node.flags:
1339 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001340 visitAssAttr = visitAssName
Jeremy Hylton6383c2d2001-11-09 16:24:34 +00001341 visitSubscript = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001342
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001343class Delegator:
1344 """Base class to support delegation for augmented assignment nodes
1345
1346 To generator code for augmented assignments, we use the following
1347 wrapper classes. In visitAugAssign, the left-hand expression node
1348 is visited twice. The first time the visit uses the normal method
1349 for that node . The second time the visit uses a different method
1350 that generates the appropriate code to perform the assignment.
1351 These delegator classes wrap the original AST nodes in order to
1352 support the variant visit methods.
1353 """
1354 def __init__(self, obj):
1355 self.obj = obj
1356
1357 def __getattr__(self, attr):
1358 return getattr(self.obj, attr)
1359
1360class AugGetattr(Delegator):
1361 pass
1362
1363class AugName(Delegator):
1364 pass
1365
1366class AugSlice(Delegator):
1367 pass
1368
1369class AugSubscript(Delegator):
1370 pass
1371
1372wrapper = {
1373 ast.Getattr: AugGetattr,
1374 ast.Name: AugName,
1375 ast.Slice: AugSlice,
1376 ast.Subscript: AugSubscript,
1377 }
1378
1379def wrap_aug(node):
1380 return wrapper[node.__class__](node)
1381
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001382if __name__ == "__main__":
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001383 for file in sys.argv[1:]:
Jeremy Hylton57911ae2001-11-27 23:35:10 +00001384 compileFile(file)