blob: 7a089f09b35a7400198562f5afe7f54ae2f93ae3 [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')
599 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000600 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000601 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000602 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000603
604 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000605 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000606 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000607 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000608 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000609 self.nextBlock(body)
610 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000611 self.visit(node.body)
612 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000613 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000614 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000615 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000616 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000617 self.visit(node.final)
618 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000619 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000620
621 # misc
622
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000623 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000624 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000625 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000626 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000627
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000628 def visitConst(self, node):
629 self.emit('LOAD_CONST', node.value)
630
631 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000632 self.emit('LOAD_CONST', node.name)
633 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000634
635 def visitGlobal(self, node):
636 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000637 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000638
639 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000640 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000641 self.loadName(node.name)
642
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000643 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000644 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000645
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000646 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000647 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000648 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000649 if VERSION > 1:
650 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000651 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000652 mod = string.split(name, ".")[0]
653 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000654
655 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000656 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000657 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000658 if VERSION > 1:
659 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000660 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000661 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000662 if VERSION > 1:
663 if name == '*':
664 self.namespace = 0
665 self.emit('IMPORT_STAR')
666 # There can only be one name w/ from ... import *
667 assert len(node.names) == 1
668 return
669 else:
670 self.emit('IMPORT_FROM', name)
671 self._resolveDots(name)
672 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000673 else:
674 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000675 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000676
Jeremy Hylton20516082000-09-01 20:33:26 +0000677 def _resolveDots(self, name):
678 elts = string.split(name, ".")
679 if len(elts) == 1:
680 return
681 for elt in elts[1:]:
682 self.emit('LOAD_ATTR', elt)
683
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000684 def visitGetattr(self, node):
685 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000686 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000687
688 # next five implement assignments
689
690 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000691 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000692 self.visit(node.expr)
693 dups = len(node.nodes) - 1
694 for i in range(len(node.nodes)):
695 elt = node.nodes[i]
696 if i < dups:
697 self.emit('DUP_TOP')
698 if isinstance(elt, ast.Node):
699 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000700
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000701 def visitAssName(self, node):
702 if node.flags == 'OP_ASSIGN':
703 self.storeName(node.name)
704 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000705 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000706 self.delName(node.name)
707 else:
708 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000709
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000710 def visitAssAttr(self, node):
711 self.visit(node.expr)
712 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000713 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000714 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000715 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000716 else:
717 print "warning: unexpected flags:", node.flags
718 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000719
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000720 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000722 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000723 for child in node.nodes:
724 self.visit(child)
725
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000726 if VERSION > 1:
727 visitAssTuple = _visitAssSequence
728 visitAssList = _visitAssSequence
729 else:
730 def visitAssTuple(self, node):
731 self._visitAssSequence(node, 'UNPACK_TUPLE')
732
733 def visitAssList(self, node):
734 self._visitAssSequence(node, 'UNPACK_LIST')
735
736 # augmented assignment
737
738 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000739 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000740 aug_node = wrap_aug(node.node)
741 self.visit(aug_node, "load")
742 self.visit(node.expr)
743 self.emit(self._augmented_opcode[node.op])
744 self.visit(aug_node, "store")
745
746 _augmented_opcode = {
747 '+=' : 'INPLACE_ADD',
748 '-=' : 'INPLACE_SUBTRACT',
749 '*=' : 'INPLACE_MULTIPLY',
750 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000751 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000752 '%=' : 'INPLACE_MODULO',
753 '**=': 'INPLACE_POWER',
754 '>>=': 'INPLACE_RSHIFT',
755 '<<=': 'INPLACE_LSHIFT',
756 '&=' : 'INPLACE_AND',
757 '^=' : 'INPLACE_XOR',
758 '|=' : 'INPLACE_OR',
759 }
760
761 def visitAugName(self, node, mode):
762 if mode == "load":
763 self.loadName(node.name)
764 elif mode == "store":
765 self.storeName(node.name)
766
767 def visitAugGetattr(self, node, mode):
768 if mode == "load":
769 self.visit(node.expr)
770 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000771 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000772 elif mode == "store":
773 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000774 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000775
776 def visitAugSlice(self, node, mode):
777 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000778 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000779 elif mode == "store":
780 slice = 0
781 if node.lower:
782 slice = slice | 1
783 if node.upper:
784 slice = slice | 2
785 if slice == 0:
786 self.emit('ROT_TWO')
787 elif slice == 3:
788 self.emit('ROT_FOUR')
789 else:
790 self.emit('ROT_THREE')
791 self.emit('STORE_SLICE+%d' % slice)
792
793 def visitAugSubscript(self, node, mode):
794 if len(node.subs) > 1:
795 raise SyntaxError, "augmented assignment to tuple is not possible"
796 if mode == "load":
797 self.visitSubscript(node, 1)
798 elif mode == "store":
799 self.emit('ROT_THREE')
800 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000801
802 def visitExec(self, node):
803 self.visit(node.expr)
804 if node.locals is None:
805 self.emit('LOAD_CONST', None)
806 else:
807 self.visit(node.locals)
808 if node.globals is None:
809 self.emit('DUP_TOP')
810 else:
811 self.visit(node.globals)
812 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000813
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000814 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000815 pos = 0
816 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000817 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000818 self.visit(node.node)
819 for arg in node.args:
820 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000821 if isinstance(arg, ast.Keyword):
822 kw = kw + 1
823 else:
824 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000825 if node.star_args is not None:
826 self.visit(node.star_args)
827 if node.dstar_args is not None:
828 self.visit(node.dstar_args)
829 have_star = node.star_args is not None
830 have_dstar = node.dstar_args is not None
831 opcode = callfunc_opcode_info[have_star, have_dstar]
832 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000833
Jeremy Hylton2afff322001-08-27 21:51:52 +0000834 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000835 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000836 if node.dest:
837 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000838 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000839 if node.dest:
840 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000841 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000842 if node.dest:
843 self.emit('ROT_TWO')
844 self.emit('PRINT_ITEM_TO')
845 else:
846 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000847 if node.dest and not newline:
848 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000849
850 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000851 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000852 if node.dest:
853 self.emit('PRINT_NEWLINE_TO')
854 else:
855 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000856
857 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000858 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000859 self.visit(node.value)
860 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000861
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000862 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000863
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000864 def visitSlice(self, node, aug_flag=None):
865 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000866 self.visit(node.expr)
867 slice = 0
868 if node.lower:
869 self.visit(node.lower)
870 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000871 if node.upper:
872 self.visit(node.upper)
873 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000874 if aug_flag:
875 if slice == 0:
876 self.emit('DUP_TOP')
877 elif slice == 3:
878 self.emit('DUP_TOPX', 3)
879 else:
880 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000881 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000882 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000883 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000884 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000885 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000886 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000887 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000888 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000889 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000890
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000891 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000892 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000893 for sub in node.subs:
894 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000895 if aug_flag:
896 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000897 if len(node.subs) > 1:
898 self.emit('BUILD_TUPLE', len(node.subs))
899 if node.flags == 'OP_APPLY':
900 self.emit('BINARY_SUBSCR')
901 elif node.flags == 'OP_ASSIGN':
902 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000903 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000904 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000905
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000906 # binary ops
907
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000908 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000909 self.visit(node.left)
910 self.visit(node.right)
911 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000912
913 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000914 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000915
916 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000917 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000918
919 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000920 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000921
922 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000923 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000924
Jeremy Hylton94afe322001-08-29 18:14:39 +0000925 def visitFloorDiv(self, node):
926 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
927
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000928 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000929 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000930
Jeremy Hylton126960b2000-02-14 21:33:10 +0000931 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000932 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000933
934 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000935 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000936
937 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000938 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000939
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000940 # unary ops
941
942 def unaryOp(self, node, op):
943 self.visit(node.expr)
944 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000945
Jeremy Hylton126960b2000-02-14 21:33:10 +0000946 def visitInvert(self, node):
947 return self.unaryOp(node, 'UNARY_INVERT')
948
Jeremy Hylton40245602000-02-08 21:15:48 +0000949 def visitUnarySub(self, node):
950 return self.unaryOp(node, 'UNARY_NEGATIVE')
951
952 def visitUnaryAdd(self, node):
953 return self.unaryOp(node, 'UNARY_POSITIVE')
954
955 def visitUnaryInvert(self, node):
956 return self.unaryOp(node, 'UNARY_INVERT')
957
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000958 def visitNot(self, node):
959 return self.unaryOp(node, 'UNARY_NOT')
960
Jeremy Hylton40245602000-02-08 21:15:48 +0000961 def visitBackquote(self, node):
962 return self.unaryOp(node, 'UNARY_CONVERT')
963
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000964 # bit ops
965
Jeremy Hyltona5058122000-02-14 14:14:29 +0000966 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000967 self.visit(nodes[0])
968 for node in nodes[1:]:
969 self.visit(node)
970 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000971
972 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000973 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000974
975 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000976 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000977
978 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000979 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000980
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000981 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000982
Jeremy Hyltona5058122000-02-14 14:14:29 +0000983 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000984 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000985
Jeremy Hylton40245602000-02-08 21:15:48 +0000986 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000987 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +0000988 for elt in node.nodes:
989 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000990 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000991
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000992 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +0000993 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000994 for elt in node.nodes:
995 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000996 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000997
998 def visitSliceobj(self, node):
999 for child in node.nodes:
1000 self.visit(child)
1001 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001002
Jeremy Hyltona5058122000-02-14 14:14:29 +00001003 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001004 lineno = getattr(node, 'lineno', None)
1005 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001006 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001007 self.emit('BUILD_MAP', 0)
1008 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001009 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001010 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001011 self.emit('SET_LINENO', lineno2)
1012 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001013 self.emit('DUP_TOP')
1014 self.visit(v)
1015 self.emit('ROT_TWO')
1016 self.visit(k)
1017 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001018
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001019class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001020 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001021 __super_visitClass = CodeGenerator.visitClass
1022 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
1023
1024 def parseSymbols(self, tree):
1025 s = symbols.SymbolVisitor()
1026 walk(tree, s)
1027 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001028
1029 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001030 self.scopes = self.parseSymbols(node)
1031 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +00001032 self.__super_visitModule(node)
1033
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001034 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001035 name = self.mangle(name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001036 scope = self.scope.check_name(name)
1037 if scope == SC_LOCAL:
1038 if not self.optimized:
1039 self.emit(prefix + '_NAME', name)
1040 else:
1041 self.emit(prefix + '_FAST', name)
1042 elif scope == SC_GLOBAL:
Jeremy Hyltonf3545752001-08-28 16:35:18 +00001043 if not self.optimized:
1044 self.emit(prefix + '_NAME', name)
1045 else:
1046 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001047 elif scope == SC_FREE or scope == SC_CELL:
1048 self.emit(prefix + '_DEREF', name)
1049 else:
1050 raise RuntimeError, "unsupported scope for var %s: %d" % \
1051 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001052
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001053 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001054 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
1055 self.class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001056 walk(node.code, gen)
1057 gen.finish()
1058 self.set_lineno(node)
1059 for default in node.defaults:
1060 self.visit(default)
1061 frees = gen.scope.get_free_vars()
1062 if frees:
1063 for name in frees:
1064 self.emit('LOAD_CLOSURE', name)
1065 self.emit('LOAD_CONST', gen)
1066 self.emit('MAKE_CLOSURE', len(node.defaults))
1067 else:
1068 self.emit('LOAD_CONST', gen)
1069 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001070
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001071 def visitClass(self, node):
1072 gen = self.ClassGen(node, self.filename, self.scopes)
1073 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001074 self.emit('LOAD_CONST', node.doc)
1075 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001076 walk(node.code, gen)
1077 gen.finish()
1078 self.set_lineno(node)
1079 self.emit('LOAD_CONST', node.name)
1080 for base in node.bases:
1081 self.visit(base)
1082 self.emit('BUILD_TUPLE', len(node.bases))
1083 frees = gen.scope.get_free_vars()
1084 for name in frees:
1085 self.emit('LOAD_CLOSURE', name)
1086 self.emit('LOAD_CONST', gen)
1087 if frees:
1088 self.emit('MAKE_CLOSURE', 0)
1089 else:
1090 self.emit('MAKE_FUNCTION', 0)
1091 self.emit('CALL_FUNCTION', 0)
1092 self.emit('BUILD_CLASS')
1093 self.storeName(node.name)
1094
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001095
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001096class LGBScopeMixin:
1097 """Defines initClass() for Python 2.1-compatible scoping"""
1098 def initClass(self):
1099 self.__class__.NameFinder = LocalNameFinder
1100 self.__class__.FunctionGen = FunctionCodeGenerator
1101 self.__class__.ClassGen = ClassCodeGenerator
1102
1103class NestedScopeMixin:
1104 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1105 def initClass(self):
1106 self.__class__.NameFinder = LocalNameFinder
1107 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1108 self.__class__.ClassGen = NestedClassCodeGenerator
1109
1110class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1111 __super_init = CodeGenerator.__init__
1112
1113 scopes = None
1114
1115 def __init__(self, filename):
1116 self.graph = pyassem.PyFlowGraph("<module>", filename)
1117 self.__super_init(filename)
1118
1119class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1120 NestedScopeCodeGenerator):
1121 __super_init = CodeGenerator.__init__
1122
1123 def __init__(self, filename):
1124 self.graph = pyassem.PyFlowGraph("<module>", filename)
1125 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001126## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001127
1128class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001129 optimized = 1
1130 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001131
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001132 def __init__(self, func, filename, scopes, isLambda, class_name):
1133 self.class_name = class_name
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001134 if isLambda:
1135 klass = FunctionCodeGenerator
1136 name = "<lambda.%d>" % klass.lambdaCount
1137 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001138 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001139 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001140 args, hasTupleArg = generateArgList(func.argnames)
1141 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001142 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001143 self.isLambda = isLambda
1144 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001145
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001146 if not isLambda and func.doc:
1147 self.setDocstring(func.doc)
1148
Jeremy Hylton2afff322001-08-27 21:51:52 +00001149 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001150 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001151 if func.varargs:
1152 self.graph.setFlag(CO_VARARGS)
1153 if func.kwargs:
1154 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001155 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001156 if hasTupleArg:
1157 self.generateArgUnpack(func.argnames)
1158
1159 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001160 self.graph.startExitBlock()
1161 if not self.isLambda:
1162 self.emit('LOAD_CONST', None)
1163 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001164
1165 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001166 for i in range(len(args)):
1167 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001168 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001169 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001170 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001171
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001172 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001173 if VERSION > 1:
1174 self.emit('UNPACK_SEQUENCE', len(tup))
1175 else:
1176 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001177 for elt in tup:
1178 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001179 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001180 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001181 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001182
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001183 unpackTuple = unpackSequence
1184
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001185class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1186 CodeGenerator):
1187 super_init = CodeGenerator.__init__ # call be other init
1188 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001189
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001190class NestedFunctionCodeGenerator(AbstractFunctionCode,
1191 NestedScopeMixin,
1192 NestedScopeCodeGenerator):
1193 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1194 __super_init = AbstractFunctionCode.__init__
1195
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001196 def __init__(self, func, filename, scopes, isLambda, class_name):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001197 self.scopes = scopes
1198 self.scope = scopes[func]
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001199 self.__super_init(func, filename, scopes, isLambda, class_name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001200 self.graph.setFreeVars(self.scope.get_free_vars())
1201 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001202## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001203
1204class AbstractClassCode:
1205
1206 def __init__(self, klass, filename, scopes):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001207 self.class_name = klass.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001208 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001209 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001210 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001211 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001212 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001213 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001214 if klass.doc:
1215 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001216
Jeremy Hylton660cc772001-04-12 06:49:00 +00001217 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001218 name = self.mangle(name)
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001219 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001220 self.emit(prefix + '_NAME', name)
1221
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001222 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001223 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001224 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001225 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001226
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001227class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1228 super_init = CodeGenerator.__init__
1229 scopes = None
1230
1231class NestedClassCodeGenerator(AbstractClassCode,
1232 NestedScopeMixin,
1233 NestedScopeCodeGenerator):
1234 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1235 __super_init = AbstractClassCode.__init__
1236
1237 def __init__(self, klass, filename, scopes):
1238 self.scopes = scopes
1239 self.scope = scopes[klass]
1240 self.__super_init(klass, filename, scopes)
1241 self.graph.setFreeVars(self.scope.get_free_vars())
1242 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001243## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001244
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001245def generateArgList(arglist):
1246 """Generate an arg list marking TupleArgs"""
1247 args = []
1248 extra = []
1249 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001250 for i in range(len(arglist)):
1251 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001252 if type(elt) == types.StringType:
1253 args.append(elt)
1254 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001255 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001256 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001257 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001258 else:
1259 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001260 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001261
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001262def findOp(node):
1263 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1264 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001265 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001266 return v.op
1267
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001268class OpFinder:
1269 def __init__(self):
1270 self.op = None
1271 def visitAssName(self, node):
1272 if self.op is None:
1273 self.op = node.flags
1274 elif self.op != node.flags:
1275 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001276 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001277
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001278class Delegator:
1279 """Base class to support delegation for augmented assignment nodes
1280
1281 To generator code for augmented assignments, we use the following
1282 wrapper classes. In visitAugAssign, the left-hand expression node
1283 is visited twice. The first time the visit uses the normal method
1284 for that node . The second time the visit uses a different method
1285 that generates the appropriate code to perform the assignment.
1286 These delegator classes wrap the original AST nodes in order to
1287 support the variant visit methods.
1288 """
1289 def __init__(self, obj):
1290 self.obj = obj
1291
1292 def __getattr__(self, attr):
1293 return getattr(self.obj, attr)
1294
1295class AugGetattr(Delegator):
1296 pass
1297
1298class AugName(Delegator):
1299 pass
1300
1301class AugSlice(Delegator):
1302 pass
1303
1304class AugSubscript(Delegator):
1305 pass
1306
1307wrapper = {
1308 ast.Getattr: AugGetattr,
1309 ast.Name: AugName,
1310 ast.Slice: AugSlice,
1311 ast.Subscript: AugSubscript,
1312 }
1313
1314def wrap_aug(node):
1315 return wrapper[node.__class__](node)
1316
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001317if __name__ == "__main__":
1318 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001319
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001320 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001321 compile(file)