blob: e55ee902493d4b8d7b6ca8df74f16abec77bd1de [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
11from compiler import ast, parse, walk
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
14from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
15 CO_NESTED, TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000016
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 Hylton9c048f92000-10-13 21:58:13 +000036def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000037 f = open(filename)
38 buf = f.read()
39 f.close()
40 mod = Module(buf, filename)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000041 mod.compile(display)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000042 f = open(filename + "c", "wb")
43 mod.dump(f)
44 f.close()
45
46class Module:
47 def __init__(self, source, filename):
Jeremy Hylton2afff322001-08-27 21:51:52 +000048 self.filename = os.path.abspath(filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000049 self.source = source
50 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000051
Jeremy Hylton9c048f92000-10-13 21:58:13 +000052 def compile(self, display=0):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000053 tree = parse(self.source)
Jeremy Hylton2afff322001-08-27 21:51:52 +000054 gen = NestedScopeModuleCodeGenerator(self.filename)
55 walk(tree, gen, verbose=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000056 if display:
57 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000058 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000059 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000060
61 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000062 f.write(self.getPycHeader())
63 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000064
Jeremy Hylton9c048f92000-10-13 21:58:13 +000065 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000066
67 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000068 # compile.c uses marshal to write a long directly, with
69 # calling the interface that would also generate a 1-byte code
70 # to indicate the type of the value. simplest way to get the
71 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000072 mtime = os.stat(self.filename)[stat.ST_MTIME]
73 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000074 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000075
Jeremy Hylton364f9b92001-04-12 06:40:42 +000076class LocalNameFinder:
77 """Find local names in scope"""
78 def __init__(self, names=()):
79 self.names = misc.Set()
80 self.globals = misc.Set()
81 for name in names:
82 self.names.add(name)
83
84 # XXX list comprehensions and for loops
85
86 def getLocals(self):
87 for elt in self.globals.elements():
88 if self.names.has_elt(elt):
89 self.names.remove(elt)
90 return self.names
91
92 def visitDict(self, node):
93 pass
94
95 def visitGlobal(self, node):
96 for name in node.names:
97 self.globals.add(name)
98
99 def visitFunction(self, node):
100 self.names.add(node.name)
101
102 def visitLambda(self, node):
103 pass
104
105 def visitImport(self, node):
106 for name, alias in node.names:
107 self.names.add(alias or name)
108
109 def visitFrom(self, node):
110 for name, alias in node.names:
111 self.names.add(alias or name)
112
113 def visitClass(self, node):
114 self.names.add(node.name)
115
116 def visitAssName(self, node):
117 self.names.add(node.name)
118
Jeremy Hylton2afff322001-08-27 21:51:52 +0000119def is_constant_false(node):
120 if isinstance(node, ast.Const):
121 if not node.value:
122 return 1
123 return 0
124
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000125class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000126 """Defines basic code generator for Python bytecode
127
128 This class is an abstract base class. Concrete subclasses must
129 define an __init__() that defines self.graph and then calls the
130 __init__() defined in this class.
131
132 The concrete class must also define the class attributes
133 NameFinder, FunctionGen, and ClassGen. These attributes can be
134 defined in the initClass() method, which is a hook for
135 initializing these methods after all the classes have been
136 defined.
137 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000138
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000139 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000140 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000141 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000142
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000143 def __init__(self, filename):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000144 if self.__initialized is None:
145 self.initClass()
146 self.__class__.__initialized = 1
147 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000148 self.filename = filename
149 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000150 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000151 self.curStack = 0
152 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000153 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000154 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000155
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000156 def initClass(self):
157 """This method is called once for each class"""
158
159 def checkClass(self):
160 """Verify that class is constructed correctly"""
161 try:
162 assert hasattr(self, 'graph')
163 assert getattr(self, 'NameFinder')
164 assert getattr(self, 'FunctionGen')
165 assert getattr(self, 'ClassGen')
166 except AssertionError, msg:
167 intro = "Bad class construction for %s" % self.__class__.__name__
168 raise AssertionError, intro
169
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000170 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000171 self.emit = self.graph.emit
172 self.newBlock = self.graph.newBlock
173 self.startBlock = self.graph.startBlock
174 self.nextBlock = self.graph.nextBlock
175 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000176
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000177 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000178 """Return a code object"""
179 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000180
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000181 def mangle(self, name):
182 if self.class_name is not None:
183 return misc.mangle(name, self.class_name)
184 else:
185 return name
186
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000187 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000188
Jeremy Hylton40245602000-02-08 21:15:48 +0000189 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000190 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000191
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000192 def storeName(self, name):
193 self._nameOp('STORE', name)
194
195 def loadName(self, name):
196 self._nameOp('LOAD', name)
197
198 def delName(self, name):
199 self._nameOp('DELETE', name)
200
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000201 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000202 name = self.mangle(name)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000203 if not self.optimized:
204 self.emit(prefix + '_NAME', name)
205 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000206 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000207 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000208 else:
209 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000210
Jeremy Hylton13d70942001-04-12 21:04:43 +0000211 def _implicitNameOp(self, prefix, name):
212 """Emit name ops for names generated implicitly by for loops
213
214 The interpreter generates names that start with a period or
215 dollar sign. The symbol table ignores these names because
216 they aren't present in the program text.
217 """
218 if self.optimized:
219 self.emit(prefix + '_FAST', name)
220 else:
221 self.emit(prefix + '_NAME', name)
222
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000223 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000224 """Emit SET_LINENO if node has lineno attribute and it is
225 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000226
227 Returns true if SET_LINENO was emitted.
228
229 There are no rules for when an AST node should have a lineno
230 attribute. The transformer and AST code need to be reviewed
231 and a consistent policy implemented and documented. Until
232 then, this method works around missing line numbers.
233 """
234 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000235 if lineno is not None and (lineno != self.last_lineno
236 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000237 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000238 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000239 return 1
240 return 0
241
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000242 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000243 # code objects. They use class attributes to determine what
244 # specialized code generators to use.
245
246 NameFinder = LocalNameFinder
247 FunctionGen = None
248 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000249
250 def visitModule(self, node):
Jeremy Hylton13d70942001-04-12 21:04:43 +0000251 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000252 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000253 self.emit('LOAD_CONST', node.doc)
254 self.storeName('__doc__')
255 lnf = walk(node.node, self.NameFinder(), verbose=0)
256 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000257 self.visit(node.node)
258 self.emit('LOAD_CONST', None)
259 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000260
261 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000262 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000263 if node.doc:
264 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000265 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000266
267 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000268 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000269
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000270 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000271 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
272 self.class_name)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000273 walk(node.code, gen)
274 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000275 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000276 for default in node.defaults:
277 self.visit(default)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000278 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000279 self.emit('MAKE_FUNCTION', len(node.defaults))
280
281 def visitClass(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000282 gen = self.ClassGen(node, self.filename, self.scopes)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000283 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000284 self.emit('LOAD_CONST', node.doc)
285 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000286 walk(node.code, gen)
287 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000288 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000289 self.emit('LOAD_CONST', node.name)
290 for base in node.bases:
291 self.visit(base)
292 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000293 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000294 self.emit('MAKE_FUNCTION', 0)
295 self.emit('CALL_FUNCTION', 0)
296 self.emit('BUILD_CLASS')
297 self.storeName(node.name)
298
299 # The rest are standard visitor methods
300
301 # The next few implement control-flow statements
302
303 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000304 end = self.newBlock()
305 numtests = len(node.tests)
306 for i in range(numtests):
307 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000308 if is_constant_false(test):
309 # XXX will need to check generator stuff here
310 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000311 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000312 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000313 nextTest = self.newBlock()
314 self.emit('JUMP_IF_FALSE', nextTest)
315 self.nextBlock()
316 self.emit('POP_TOP')
317 self.visit(suite)
318 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000319 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000320 self.emit('POP_TOP')
321 if node.else_:
322 self.visit(node.else_)
323 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000324
325 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000326 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000327
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000328 loop = self.newBlock()
329 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000330
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000331 after = self.newBlock()
332 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000333
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000334 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000335 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000336
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000337 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000338 self.visit(node.test)
339 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000340
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000341 self.nextBlock()
342 self.emit('POP_TOP')
343 self.visit(node.body)
344 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000345
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000346 self.startBlock(else_) # or just the POPs if not else clause
347 self.emit('POP_TOP')
348 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000349 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000350 if node.else_:
351 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000352 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000353
354 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000355 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000356 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000357 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000358 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000359
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000360 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000361 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000362 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000363 self.emit('GET_ITER')
364
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000365 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000366 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000367 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000368 self.visit(node.assign)
369 self.visit(node.body)
370 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000371 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000372 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000373 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000374 if node.else_:
375 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000376 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000377
378 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000379 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000380 raise SyntaxError, "'break' outside loop (%s, %d)" % \
381 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000382 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000383 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000384
385 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000386 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000387 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000388 (self.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000389 kind, block = self.setups.top()
390 if kind == LOOP:
391 self.set_lineno(node)
392 self.emit('JUMP_ABSOLUTE', block)
393 self.nextBlock()
394 elif kind == EXCEPT or kind == TRY_FINALLY:
395 self.set_lineno(node)
396 # find the block that starts the loop
397 top = len(self.setups)
398 while top > 0:
399 top = top - 1
400 kind, loop_block = self.setups[top]
401 if kind == LOOP:
402 break
403 if kind != LOOP:
404 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
405 (self.filename, node.lineno)
406 self.emit('CONTINUE_LOOP', loop_block)
407 self.nextBlock()
408 elif kind == END_FINALLY:
409 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
410 raise SyntaxError, msg % (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000411
412 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000413 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000414 for child in node.nodes[:-1]:
415 self.visit(child)
416 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000417 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000418 self.emit('POP_TOP')
419 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000420 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000421
422 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000423 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000424
425 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000426 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000427
428 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000429 self.visit(node.expr)
430 cleanup = self.newBlock()
431 for op, code in node.ops[:-1]:
432 self.visit(code)
433 self.emit('DUP_TOP')
434 self.emit('ROT_THREE')
435 self.emit('COMPARE_OP', op)
436 self.emit('JUMP_IF_FALSE', cleanup)
437 self.nextBlock()
438 self.emit('POP_TOP')
439 # now do the last comparison
440 if node.ops:
441 op, code = node.ops[-1]
442 self.visit(code)
443 self.emit('COMPARE_OP', op)
444 if len(node.ops) > 1:
445 end = self.newBlock()
446 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000447 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000448 self.emit('ROT_TWO')
449 self.emit('POP_TOP')
450 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000451
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000452 # list comprehensions
453 __list_count = 0
454
455 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000456 self.set_lineno(node)
457 # setup list
458 append = "$append%d" % self.__list_count
459 self.__list_count = self.__list_count + 1
460 self.emit('BUILD_LIST', 0)
461 self.emit('DUP_TOP')
462 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000463 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000464
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000465 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000466 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000467 start, anchor = self.visit(for_)
468 cont = None
469 for if_ in for_.ifs:
470 if cont is None:
471 cont = self.newBlock()
472 self.visit(if_, cont)
473 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000474
Jeremy Hylton13d70942001-04-12 21:04:43 +0000475 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000476 self.visit(node.expr)
477 self.emit('CALL_FUNCTION', 1)
478 self.emit('POP_TOP')
479
480 for start, cont, anchor in stack:
481 if cont:
482 skip_one = self.newBlock()
483 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000484 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000485 self.emit('POP_TOP')
486 self.nextBlock(skip_one)
487 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000488 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000489 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000490
491 self.__list_count = self.__list_count - 1
492
493 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000494 start = self.newBlock()
495 anchor = self.newBlock()
496
497 self.visit(node.list)
498 self.visit(ast.Const(0))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000499 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000500 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000501 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000502 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000503 self.visit(node.assign)
504 return start, anchor
505
506 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000507 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000508 self.visit(node.test)
509 self.emit('JUMP_IF_FALSE', branch)
510 self.newBlock()
511 self.emit('POP_TOP')
512
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000513 # exception related
514
515 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000516 # XXX would be interesting to implement this via a
517 # transformation of the AST before this stage
518 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000519 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000520 # XXX __debug__ and AssertionError appear to be special cases
521 # -- they are always loaded as globals even if there are local
522 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000523 self.emit('LOAD_GLOBAL', '__debug__')
524 self.emit('JUMP_IF_FALSE', end)
525 self.nextBlock()
526 self.emit('POP_TOP')
527 self.visit(node.test)
528 self.emit('JUMP_IF_TRUE', end)
529 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000530 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000531 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000532 if node.fail:
533 self.visit(node.fail)
534 self.emit('RAISE_VARARGS', 2)
535 else:
536 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000537 self.nextBlock(end)
538 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000539
540 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000541 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000542 n = 0
543 if node.expr1:
544 self.visit(node.expr1)
545 n = n + 1
546 if node.expr2:
547 self.visit(node.expr2)
548 n = n + 1
549 if node.expr3:
550 self.visit(node.expr3)
551 n = n + 1
552 self.emit('RAISE_VARARGS', n)
553
554 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000555 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000556 handlers = self.newBlock()
557 end = self.newBlock()
558 if node.else_:
559 lElse = self.newBlock()
560 else:
561 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000562 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000563 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000564 self.nextBlock(body)
565 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000566 self.visit(node.body)
567 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000568 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000569 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000570 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000571
572 last = len(node.handlers) - 1
573 for i in range(len(node.handlers)):
574 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000575 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000576 if expr:
577 self.emit('DUP_TOP')
578 self.visit(expr)
579 self.emit('COMPARE_OP', 'exception match')
580 next = self.newBlock()
581 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000582 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000583 self.emit('POP_TOP')
584 self.emit('POP_TOP')
585 if target:
586 self.visit(target)
587 else:
588 self.emit('POP_TOP')
589 self.emit('POP_TOP')
590 self.visit(body)
591 self.emit('JUMP_FORWARD', end)
592 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000593 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000594 else:
595 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000596 if expr: # XXX
597 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000598 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000599 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000600 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000601 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000602 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000603 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000604
605 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000606 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000607 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000608 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000609 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000610 self.nextBlock(body)
611 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000612 self.visit(node.body)
613 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000614 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000615 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000616 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000617 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000618 self.visit(node.final)
619 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000620 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000621
622 # misc
623
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000624 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000625 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000626 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000627 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000628
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000629 def visitConst(self, node):
630 self.emit('LOAD_CONST', node.value)
631
632 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000633 self.emit('LOAD_CONST', node.name)
634 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000635
636 def visitGlobal(self, node):
637 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000638 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000639
640 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000641 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000642 self.loadName(node.name)
643
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000644 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000645 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000646
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000647 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000648 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000649 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000650 if VERSION > 1:
651 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000652 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000653 mod = string.split(name, ".")[0]
654 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000655
656 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000657 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000658 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000659 if VERSION > 1:
660 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000661 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000662 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000663 if VERSION > 1:
664 if name == '*':
665 self.namespace = 0
666 self.emit('IMPORT_STAR')
667 # There can only be one name w/ from ... import *
668 assert len(node.names) == 1
669 return
670 else:
671 self.emit('IMPORT_FROM', name)
672 self._resolveDots(name)
673 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000674 else:
675 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000676 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000677
Jeremy Hylton20516082000-09-01 20:33:26 +0000678 def _resolveDots(self, name):
679 elts = string.split(name, ".")
680 if len(elts) == 1:
681 return
682 for elt in elts[1:]:
683 self.emit('LOAD_ATTR', elt)
684
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000685 def visitGetattr(self, node):
686 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000687 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000688
689 # next five implement assignments
690
691 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000692 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000693 self.visit(node.expr)
694 dups = len(node.nodes) - 1
695 for i in range(len(node.nodes)):
696 elt = node.nodes[i]
697 if i < dups:
698 self.emit('DUP_TOP')
699 if isinstance(elt, ast.Node):
700 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000701
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 def visitAssName(self, node):
703 if node.flags == 'OP_ASSIGN':
704 self.storeName(node.name)
705 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000706 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000707 self.delName(node.name)
708 else:
709 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000710
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000711 def visitAssAttr(self, node):
712 self.visit(node.expr)
713 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000714 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000715 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000716 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000717 else:
718 print "warning: unexpected flags:", node.flags
719 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000720
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000721 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000722 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000723 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724 for child in node.nodes:
725 self.visit(child)
726
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000727 if VERSION > 1:
728 visitAssTuple = _visitAssSequence
729 visitAssList = _visitAssSequence
730 else:
731 def visitAssTuple(self, node):
732 self._visitAssSequence(node, 'UNPACK_TUPLE')
733
734 def visitAssList(self, node):
735 self._visitAssSequence(node, 'UNPACK_LIST')
736
737 # augmented assignment
738
739 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000740 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000741 aug_node = wrap_aug(node.node)
742 self.visit(aug_node, "load")
743 self.visit(node.expr)
744 self.emit(self._augmented_opcode[node.op])
745 self.visit(aug_node, "store")
746
747 _augmented_opcode = {
748 '+=' : 'INPLACE_ADD',
749 '-=' : 'INPLACE_SUBTRACT',
750 '*=' : 'INPLACE_MULTIPLY',
751 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000752 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000753 '%=' : 'INPLACE_MODULO',
754 '**=': 'INPLACE_POWER',
755 '>>=': 'INPLACE_RSHIFT',
756 '<<=': 'INPLACE_LSHIFT',
757 '&=' : 'INPLACE_AND',
758 '^=' : 'INPLACE_XOR',
759 '|=' : 'INPLACE_OR',
760 }
761
762 def visitAugName(self, node, mode):
763 if mode == "load":
764 self.loadName(node.name)
765 elif mode == "store":
766 self.storeName(node.name)
767
768 def visitAugGetattr(self, node, mode):
769 if mode == "load":
770 self.visit(node.expr)
771 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000772 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000773 elif mode == "store":
774 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000775 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000776
777 def visitAugSlice(self, node, mode):
778 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000779 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000780 elif mode == "store":
781 slice = 0
782 if node.lower:
783 slice = slice | 1
784 if node.upper:
785 slice = slice | 2
786 if slice == 0:
787 self.emit('ROT_TWO')
788 elif slice == 3:
789 self.emit('ROT_FOUR')
790 else:
791 self.emit('ROT_THREE')
792 self.emit('STORE_SLICE+%d' % slice)
793
794 def visitAugSubscript(self, node, mode):
795 if len(node.subs) > 1:
796 raise SyntaxError, "augmented assignment to tuple is not possible"
797 if mode == "load":
798 self.visitSubscript(node, 1)
799 elif mode == "store":
800 self.emit('ROT_THREE')
801 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000802
803 def visitExec(self, node):
804 self.visit(node.expr)
805 if node.locals is None:
806 self.emit('LOAD_CONST', None)
807 else:
808 self.visit(node.locals)
809 if node.globals is None:
810 self.emit('DUP_TOP')
811 else:
812 self.visit(node.globals)
813 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000814
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000815 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000816 pos = 0
817 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000818 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000819 self.visit(node.node)
820 for arg in node.args:
821 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000822 if isinstance(arg, ast.Keyword):
823 kw = kw + 1
824 else:
825 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000826 if node.star_args is not None:
827 self.visit(node.star_args)
828 if node.dstar_args is not None:
829 self.visit(node.dstar_args)
830 have_star = node.star_args is not None
831 have_dstar = node.dstar_args is not None
832 opcode = callfunc_opcode_info[have_star, have_dstar]
833 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000834
Jeremy Hylton2afff322001-08-27 21:51:52 +0000835 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000836 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000837 if node.dest:
838 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000839 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000840 if node.dest:
841 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000842 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000843 if node.dest:
844 self.emit('ROT_TWO')
845 self.emit('PRINT_ITEM_TO')
846 else:
847 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000848 if node.dest and not newline:
849 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000850
851 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000852 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000853 if node.dest:
854 self.emit('PRINT_NEWLINE_TO')
855 else:
856 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000857
858 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000859 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000860 self.visit(node.value)
861 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000862
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000863 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000864
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000865 def visitSlice(self, node, aug_flag=None):
866 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000867 self.visit(node.expr)
868 slice = 0
869 if node.lower:
870 self.visit(node.lower)
871 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000872 if node.upper:
873 self.visit(node.upper)
874 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000875 if aug_flag:
876 if slice == 0:
877 self.emit('DUP_TOP')
878 elif slice == 3:
879 self.emit('DUP_TOPX', 3)
880 else:
881 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000882 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000883 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000884 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000885 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000886 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000887 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000888 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000889 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000890 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000891
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000892 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000893 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000894 for sub in node.subs:
895 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000896 if aug_flag:
897 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000898 if len(node.subs) > 1:
899 self.emit('BUILD_TUPLE', len(node.subs))
900 if node.flags == 'OP_APPLY':
901 self.emit('BINARY_SUBSCR')
902 elif node.flags == 'OP_ASSIGN':
903 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000904 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000905 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000906
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000907 # binary ops
908
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000909 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000910 self.visit(node.left)
911 self.visit(node.right)
912 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000913
914 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000915 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000916
917 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000918 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000919
920 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000921 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000922
923 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000924 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000925
Jeremy Hylton94afe322001-08-29 18:14:39 +0000926 def visitFloorDiv(self, node):
927 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
928
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000929 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000930 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000931
Jeremy Hylton126960b2000-02-14 21:33:10 +0000932 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000933 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000934
935 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000936 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000937
938 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000939 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000940
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000941 # unary ops
942
943 def unaryOp(self, node, op):
944 self.visit(node.expr)
945 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000946
Jeremy Hylton126960b2000-02-14 21:33:10 +0000947 def visitInvert(self, node):
948 return self.unaryOp(node, 'UNARY_INVERT')
949
Jeremy Hylton40245602000-02-08 21:15:48 +0000950 def visitUnarySub(self, node):
951 return self.unaryOp(node, 'UNARY_NEGATIVE')
952
953 def visitUnaryAdd(self, node):
954 return self.unaryOp(node, 'UNARY_POSITIVE')
955
956 def visitUnaryInvert(self, node):
957 return self.unaryOp(node, 'UNARY_INVERT')
958
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000959 def visitNot(self, node):
960 return self.unaryOp(node, 'UNARY_NOT')
961
Jeremy Hylton40245602000-02-08 21:15:48 +0000962 def visitBackquote(self, node):
963 return self.unaryOp(node, 'UNARY_CONVERT')
964
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000965 # bit ops
966
Jeremy Hyltona5058122000-02-14 14:14:29 +0000967 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000968 self.visit(nodes[0])
969 for node in nodes[1:]:
970 self.visit(node)
971 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000972
973 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000974 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000975
976 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000977 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000978
979 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000980 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000981
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000982 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000983
Jeremy Hyltona5058122000-02-14 14:14:29 +0000984 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000985 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000986
Jeremy Hylton40245602000-02-08 21:15:48 +0000987 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000988 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +0000989 for elt in node.nodes:
990 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000991 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000992
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000993 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000994 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000995 for elt in node.nodes:
996 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000997 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000998
999 def visitSliceobj(self, node):
1000 for child in node.nodes:
1001 self.visit(child)
1002 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001003
Jeremy Hyltona5058122000-02-14 14:14:29 +00001004 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001005 lineno = getattr(node, 'lineno', None)
1006 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001007 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001008 self.emit('BUILD_MAP', 0)
1009 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001010 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001011 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001012 self.emit('SET_LINENO', lineno2)
1013 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001014 self.emit('DUP_TOP')
1015 self.visit(v)
1016 self.emit('ROT_TWO')
1017 self.visit(k)
1018 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001019
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001020class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001021 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001022 __super_visitClass = CodeGenerator.visitClass
1023 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
1024
1025 def parseSymbols(self, tree):
1026 s = symbols.SymbolVisitor()
1027 walk(tree, s)
1028 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001029
1030 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001031 self.scopes = self.parseSymbols(node)
1032 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001033 self.__super_visitModule(node)
1034
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001035 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001036 name = self.mangle(name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001037 scope = self.scope.check_name(name)
1038 if scope == SC_LOCAL:
1039 if not self.optimized:
1040 self.emit(prefix + '_NAME', name)
1041 else:
1042 self.emit(prefix + '_FAST', name)
1043 elif scope == SC_GLOBAL:
Jeremy Hyltonf3545752001-08-28 16:35:18 +00001044 if not self.optimized:
1045 self.emit(prefix + '_NAME', name)
1046 else:
1047 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001048 elif scope == SC_FREE or scope == SC_CELL:
1049 self.emit(prefix + '_DEREF', name)
1050 else:
1051 raise RuntimeError, "unsupported scope for var %s: %d" % \
1052 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001053
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001054 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001055 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1056 self.class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001057 walk(node.code, gen)
1058 gen.finish()
1059 self.set_lineno(node)
1060 for default in node.defaults:
1061 self.visit(default)
1062 frees = gen.scope.get_free_vars()
1063 if frees:
1064 for name in frees:
1065 self.emit('LOAD_CLOSURE', name)
1066 self.emit('LOAD_CONST', gen)
1067 self.emit('MAKE_CLOSURE', len(node.defaults))
1068 else:
1069 self.emit('LOAD_CONST', gen)
1070 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001071
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001072 def visitClass(self, node):
1073 gen = self.ClassGen(node, self.filename, self.scopes)
1074 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001075 self.emit('LOAD_CONST', node.doc)
1076 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001077 walk(node.code, gen)
1078 gen.finish()
1079 self.set_lineno(node)
1080 self.emit('LOAD_CONST', node.name)
1081 for base in node.bases:
1082 self.visit(base)
1083 self.emit('BUILD_TUPLE', len(node.bases))
1084 frees = gen.scope.get_free_vars()
1085 for name in frees:
1086 self.emit('LOAD_CLOSURE', name)
1087 self.emit('LOAD_CONST', gen)
1088 if frees:
1089 self.emit('MAKE_CLOSURE', 0)
1090 else:
1091 self.emit('MAKE_FUNCTION', 0)
1092 self.emit('CALL_FUNCTION', 0)
1093 self.emit('BUILD_CLASS')
1094 self.storeName(node.name)
1095
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001096
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001097class LGBScopeMixin:
1098 """Defines initClass() for Python 2.1-compatible scoping"""
1099 def initClass(self):
1100 self.__class__.NameFinder = LocalNameFinder
1101 self.__class__.FunctionGen = FunctionCodeGenerator
1102 self.__class__.ClassGen = ClassCodeGenerator
1103
1104class NestedScopeMixin:
1105 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1106 def initClass(self):
1107 self.__class__.NameFinder = LocalNameFinder
1108 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1109 self.__class__.ClassGen = NestedClassCodeGenerator
1110
1111class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1112 __super_init = CodeGenerator.__init__
1113
1114 scopes = None
1115
1116 def __init__(self, filename):
1117 self.graph = pyassem.PyFlowGraph("<module>", filename)
1118 self.__super_init(filename)
1119
1120class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1121 NestedScopeCodeGenerator):
1122 __super_init = CodeGenerator.__init__
1123
1124 def __init__(self, filename):
1125 self.graph = pyassem.PyFlowGraph("<module>", filename)
1126 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001127## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001128
1129class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001130 optimized = 1
1131 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001132
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001133 def __init__(self, func, filename, scopes, isLambda, class_name):
1134 self.class_name = class_name
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001135 if isLambda:
1136 klass = FunctionCodeGenerator
1137 name = "<lambda.%d>" % klass.lambdaCount
1138 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001139 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001140 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001141 args, hasTupleArg = generateArgList(func.argnames)
1142 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001143 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001144 self.isLambda = isLambda
1145 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001146
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001147 if not isLambda and func.doc:
1148 self.setDocstring(func.doc)
1149
Jeremy Hylton2afff322001-08-27 21:51:52 +00001150 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001151 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001152 if func.varargs:
1153 self.graph.setFlag(CO_VARARGS)
1154 if func.kwargs:
1155 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001156 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001157 if hasTupleArg:
1158 self.generateArgUnpack(func.argnames)
1159
1160 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001161 self.graph.startExitBlock()
1162 if not self.isLambda:
1163 self.emit('LOAD_CONST', None)
1164 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001165
1166 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001167 for i in range(len(args)):
1168 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001169 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001170 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001171 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001172
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001173 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001174 if VERSION > 1:
1175 self.emit('UNPACK_SEQUENCE', len(tup))
1176 else:
1177 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001178 for elt in tup:
1179 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001180 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001181 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001182 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001183
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001184 unpackTuple = unpackSequence
1185
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001186class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1187 CodeGenerator):
1188 super_init = CodeGenerator.__init__ # call be other init
1189 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001190
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001191class NestedFunctionCodeGenerator(AbstractFunctionCode,
1192 NestedScopeMixin,
1193 NestedScopeCodeGenerator):
1194 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1195 __super_init = AbstractFunctionCode.__init__
1196
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001197 def __init__(self, func, filename, scopes, isLambda, class_name):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001198 self.scopes = scopes
1199 self.scope = scopes[func]
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001200 self.__super_init(func, filename, scopes, isLambda, class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001201 self.graph.setFreeVars(self.scope.get_free_vars())
1202 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001203## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001204
1205class AbstractClassCode:
1206
1207 def __init__(self, klass, filename, scopes):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001208 self.class_name = klass.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001209 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001210 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001211 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001212 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001213 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001214 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001215 if klass.doc:
1216 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001217
Jeremy Hylton660cc772001-04-12 06:49:00 +00001218 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001219 name = self.mangle(name)
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001220 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001221 self.emit(prefix + '_NAME', name)
1222
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001223 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001224 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001225 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001226 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001227
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001228class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1229 super_init = CodeGenerator.__init__
1230 scopes = None
1231
1232class NestedClassCodeGenerator(AbstractClassCode,
1233 NestedScopeMixin,
1234 NestedScopeCodeGenerator):
1235 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1236 __super_init = AbstractClassCode.__init__
1237
1238 def __init__(self, klass, filename, scopes):
1239 self.scopes = scopes
1240 self.scope = scopes[klass]
1241 self.__super_init(klass, filename, scopes)
1242 self.graph.setFreeVars(self.scope.get_free_vars())
1243 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001244## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001245
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001246def generateArgList(arglist):
1247 """Generate an arg list marking TupleArgs"""
1248 args = []
1249 extra = []
1250 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001251 for i in range(len(arglist)):
1252 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001253 if type(elt) == types.StringType:
1254 args.append(elt)
1255 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001256 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001257 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001258 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001259 else:
1260 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001261 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001262
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001263def findOp(node):
1264 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1265 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001266 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001267 return v.op
1268
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001269class OpFinder:
1270 def __init__(self):
1271 self.op = None
1272 def visitAssName(self, node):
1273 if self.op is None:
1274 self.op = node.flags
1275 elif self.op != node.flags:
1276 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001277 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001278
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001279class Delegator:
1280 """Base class to support delegation for augmented assignment nodes
1281
1282 To generator code for augmented assignments, we use the following
1283 wrapper classes. In visitAugAssign, the left-hand expression node
1284 is visited twice. The first time the visit uses the normal method
1285 for that node . The second time the visit uses a different method
1286 that generates the appropriate code to perform the assignment.
1287 These delegator classes wrap the original AST nodes in order to
1288 support the variant visit methods.
1289 """
1290 def __init__(self, obj):
1291 self.obj = obj
1292
1293 def __getattr__(self, attr):
1294 return getattr(self.obj, attr)
1295
1296class AugGetattr(Delegator):
1297 pass
1298
1299class AugName(Delegator):
1300 pass
1301
1302class AugSlice(Delegator):
1303 pass
1304
1305class AugSubscript(Delegator):
1306 pass
1307
1308wrapper = {
1309 ast.Getattr: AugGetattr,
1310 ast.Name: AugName,
1311 ast.Slice: AugSlice,
1312 ast.Subscript: AugSubscript,
1313 }
1314
1315def wrap_aug(node):
1316 return wrapper[node.__class__](node)
1317
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001318if __name__ == "__main__":
1319 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001320
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001321 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001322 compile(file)