blob: 0097482447c344ffc7c421a0a5192efb2697b322 [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
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000015 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000016from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000017
Jeremy Hylton9c048f92000-10-13 21:58:13 +000018# Do we have Python 1.x or Python 2.x?
19try:
20 VERSION = sys.version_info[0]
21except AttributeError:
22 VERSION = 1
23
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000024callfunc_opcode_info = {
25 # (Have *args, Have **args) : opcode
26 (0,0) : "CALL_FUNCTION",
27 (1,0) : "CALL_FUNCTION_VAR",
28 (0,1) : "CALL_FUNCTION_KW",
29 (1,1) : "CALL_FUNCTION_VAR_KW",
30}
31
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000032LOOP = 1
33EXCEPT = 2
34TRY_FINALLY = 3
35END_FINALLY = 4
36
Jeremy Hylton1e99a772001-09-14 22:49:08 +000037class BlockStack(misc.Stack):
38 __super_init = misc.Stack.__init__
39
40 def __init__(self):
41 self.__super_init(self)
42 self.loop = None
43
44
45
Jeremy Hylton9c048f92000-10-13 21:58:13 +000046def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000047 f = open(filename)
48 buf = f.read()
49 f.close()
50 mod = Module(buf, filename)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000051 mod.compile(display)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000052 f = open(filename + "c", "wb")
53 mod.dump(f)
54 f.close()
55
56class Module:
57 def __init__(self, source, filename):
Jeremy Hylton2afff322001-08-27 21:51:52 +000058 self.filename = os.path.abspath(filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000059 self.source = source
60 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000061
Jeremy Hylton9c048f92000-10-13 21:58:13 +000062 def compile(self, display=0):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000063 tree = parse(self.source)
Jeremy Hylton1e99a772001-09-14 22:49:08 +000064 gen = ModuleCodeGenerator(self.filename, tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000065 if display:
66 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000067 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000068 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000069
70 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000071 f.write(self.getPycHeader())
72 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000073
Jeremy Hylton9c048f92000-10-13 21:58:13 +000074 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000075
76 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000077 # compile.c uses marshal to write a long directly, with
78 # calling the interface that would also generate a 1-byte code
79 # to indicate the type of the value. simplest way to get the
80 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000081 mtime = os.stat(self.filename)[stat.ST_MTIME]
82 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000083 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000084
Jeremy Hylton364f9b92001-04-12 06:40:42 +000085class LocalNameFinder:
86 """Find local names in scope"""
87 def __init__(self, names=()):
88 self.names = misc.Set()
89 self.globals = misc.Set()
90 for name in names:
91 self.names.add(name)
92
93 # XXX list comprehensions and for loops
94
95 def getLocals(self):
96 for elt in self.globals.elements():
97 if self.names.has_elt(elt):
98 self.names.remove(elt)
99 return self.names
100
101 def visitDict(self, node):
102 pass
103
104 def visitGlobal(self, node):
105 for name in node.names:
106 self.globals.add(name)
107
108 def visitFunction(self, node):
109 self.names.add(node.name)
110
111 def visitLambda(self, node):
112 pass
113
114 def visitImport(self, node):
115 for name, alias in node.names:
116 self.names.add(alias or name)
117
118 def visitFrom(self, node):
119 for name, alias in node.names:
120 self.names.add(alias or name)
121
122 def visitClass(self, node):
123 self.names.add(node.name)
124
125 def visitAssName(self, node):
126 self.names.add(node.name)
127
Jeremy Hylton2afff322001-08-27 21:51:52 +0000128def is_constant_false(node):
129 if isinstance(node, ast.Const):
130 if not node.value:
131 return 1
132 return 0
133
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000134class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000135 """Defines basic code generator for Python bytecode
136
137 This class is an abstract base class. Concrete subclasses must
138 define an __init__() that defines self.graph and then calls the
139 __init__() defined in this class.
140
141 The concrete class must also define the class attributes
142 NameFinder, FunctionGen, and ClassGen. These attributes can be
143 defined in the initClass() method, which is a hook for
144 initializing these methods after all the classes have been
145 defined.
146 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000147
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000148 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000149 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000150 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000151
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000152 def __init__(self, filename):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000153 if self.__initialized is None:
154 self.initClass()
155 self.__class__.__initialized = 1
156 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000157 self.filename = filename
158 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000159 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000160 self.curStack = 0
161 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000162 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000163 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000164
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000165 # XXX set flags based on future features
166 futures = self.get_module().futures
167 for feature in futures:
168 if feature == "division":
169 self.graph.setFlag(CO_FUTURE_DIVISION)
170 elif feature == "generators":
171 self.graph.setFlag(CO_GENERATOR_ALLOWED)
172
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000173 def initClass(self):
174 """This method is called once for each class"""
175
176 def checkClass(self):
177 """Verify that class is constructed correctly"""
178 try:
179 assert hasattr(self, 'graph')
180 assert getattr(self, 'NameFinder')
181 assert getattr(self, 'FunctionGen')
182 assert getattr(self, 'ClassGen')
183 except AssertionError, msg:
184 intro = "Bad class construction for %s" % self.__class__.__name__
185 raise AssertionError, intro
186
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000187 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000188 self.emit = self.graph.emit
189 self.newBlock = self.graph.newBlock
190 self.startBlock = self.graph.startBlock
191 self.nextBlock = self.graph.nextBlock
192 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000193
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000194 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000195 """Return a code object"""
196 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000197
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000198 def mangle(self, name):
199 if self.class_name is not None:
200 return misc.mangle(name, self.class_name)
201 else:
202 return name
203
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000204 def parseSymbols(self, tree):
205 s = symbols.SymbolVisitor()
206 walk(tree, s)
207 return s.scopes
208
209 def get_module(self):
210 raise RuntimeError, "should be implemented by subclasses"
211
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000212 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000213
Jeremy Hylton40245602000-02-08 21:15:48 +0000214 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000215 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000216
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000217 def storeName(self, name):
218 self._nameOp('STORE', name)
219
220 def loadName(self, name):
221 self._nameOp('LOAD', name)
222
223 def delName(self, name):
224 self._nameOp('DELETE', name)
225
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000226 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000227 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000228 scope = self.scope.check_name(name)
229 if scope == SC_LOCAL:
230 if not self.optimized:
231 self.emit(prefix + '_NAME', name)
232 else:
233 self.emit(prefix + '_FAST', name)
234 elif scope == SC_GLOBAL:
235 if not self.optimized:
236 self.emit(prefix + '_NAME', name)
237 else:
238 self.emit(prefix + '_GLOBAL', name)
239 elif scope == SC_FREE or scope == SC_CELL:
240 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000241 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000242 raise RuntimeError, "unsupported scope for var %s: %d" % \
243 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000244
Jeremy Hylton13d70942001-04-12 21:04:43 +0000245 def _implicitNameOp(self, prefix, name):
246 """Emit name ops for names generated implicitly by for loops
247
248 The interpreter generates names that start with a period or
249 dollar sign. The symbol table ignores these names because
250 they aren't present in the program text.
251 """
252 if self.optimized:
253 self.emit(prefix + '_FAST', name)
254 else:
255 self.emit(prefix + '_NAME', name)
256
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000257 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000258 """Emit SET_LINENO if node has lineno attribute and it is
259 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000260
261 Returns true if SET_LINENO was emitted.
262
263 There are no rules for when an AST node should have a lineno
264 attribute. The transformer and AST code need to be reviewed
265 and a consistent policy implemented and documented. Until
266 then, this method works around missing line numbers.
267 """
268 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000269 if lineno is not None and (lineno != self.last_lineno
270 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000271 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000272 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000273 return 1
274 return 0
275
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000276 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000277 # code objects. They use class attributes to determine what
278 # specialized code generators to use.
279
280 NameFinder = LocalNameFinder
281 FunctionGen = None
282 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000283
284 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000285 self.scopes = self.parseSymbols(node)
286 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000287 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000288 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000289 self.emit('LOAD_CONST', node.doc)
290 self.storeName('__doc__')
291 lnf = walk(node.node, self.NameFinder(), verbose=0)
292 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000293 self.visit(node.node)
294 self.emit('LOAD_CONST', None)
295 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000296
297 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000298 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000299 if node.doc:
300 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000301 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000302
303 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000304 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000305
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000306 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000307 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000308 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000309 walk(node.code, gen)
310 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000311 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000312 for default in node.defaults:
313 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000314 frees = gen.scope.get_free_vars()
315 if frees:
316 for name in frees:
317 self.emit('LOAD_CLOSURE', name)
318 self.emit('LOAD_CONST', gen)
319 self.emit('MAKE_CLOSURE', len(node.defaults))
320 else:
321 self.emit('LOAD_CONST', gen)
322 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000323
324 def visitClass(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000325 gen = self.ClassGen(node, self.filename, self.scopes,
326 self.get_module())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000327 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000328 self.emit('LOAD_CONST', node.doc)
329 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000330 walk(node.code, gen)
331 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000332 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000333 self.emit('LOAD_CONST', node.name)
334 for base in node.bases:
335 self.visit(base)
336 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000337 frees = gen.scope.get_free_vars()
338 for name in frees:
339 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000340 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000341 if frees:
342 self.emit('MAKE_CLOSURE', 0)
343 else:
344 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000345 self.emit('CALL_FUNCTION', 0)
346 self.emit('BUILD_CLASS')
347 self.storeName(node.name)
348
349 # The rest are standard visitor methods
350
351 # The next few implement control-flow statements
352
353 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000354 end = self.newBlock()
355 numtests = len(node.tests)
356 for i in range(numtests):
357 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000358 if is_constant_false(test):
359 # XXX will need to check generator stuff here
360 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000361 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000362 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000363 nextTest = self.newBlock()
364 self.emit('JUMP_IF_FALSE', nextTest)
365 self.nextBlock()
366 self.emit('POP_TOP')
367 self.visit(suite)
368 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000369 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000370 self.emit('POP_TOP')
371 if node.else_:
372 self.visit(node.else_)
373 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000374
375 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000376 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000377
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000378 loop = self.newBlock()
379 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000380
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000381 after = self.newBlock()
382 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000383
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000384 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000385 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000386
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000387 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000388 self.visit(node.test)
389 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000390
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000391 self.nextBlock()
392 self.emit('POP_TOP')
393 self.visit(node.body)
394 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000395
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000396 self.startBlock(else_) # or just the POPs if not else clause
397 self.emit('POP_TOP')
398 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000399 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000400 if node.else_:
401 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000402 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000403
404 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000405 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000406 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000407 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000408 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000409
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000410 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000411 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000412 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000413 self.emit('GET_ITER')
414
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000415 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000416 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000417 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000418 self.visit(node.assign)
419 self.visit(node.body)
420 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000421 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000422 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000423 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000424 if node.else_:
425 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000426 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000427
428 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000429 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000430 raise SyntaxError, "'break' outside loop (%s, %d)" % \
431 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000432 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000433 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000434
435 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000436 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000437 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000438 (self.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000439 kind, block = self.setups.top()
440 if kind == LOOP:
441 self.set_lineno(node)
442 self.emit('JUMP_ABSOLUTE', block)
443 self.nextBlock()
444 elif kind == EXCEPT or kind == TRY_FINALLY:
445 self.set_lineno(node)
446 # find the block that starts the loop
447 top = len(self.setups)
448 while top > 0:
449 top = top - 1
450 kind, loop_block = self.setups[top]
451 if kind == LOOP:
452 break
453 if kind != LOOP:
454 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
455 (self.filename, node.lineno)
456 self.emit('CONTINUE_LOOP', loop_block)
457 self.nextBlock()
458 elif kind == END_FINALLY:
459 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
460 raise SyntaxError, msg % (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000461
462 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000463 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000464 for child in node.nodes[:-1]:
465 self.visit(child)
466 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000467 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000468 self.emit('POP_TOP')
469 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000470 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000471
472 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000473 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000474
475 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000476 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000477
478 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000479 self.visit(node.expr)
480 cleanup = self.newBlock()
481 for op, code in node.ops[:-1]:
482 self.visit(code)
483 self.emit('DUP_TOP')
484 self.emit('ROT_THREE')
485 self.emit('COMPARE_OP', op)
486 self.emit('JUMP_IF_FALSE', cleanup)
487 self.nextBlock()
488 self.emit('POP_TOP')
489 # now do the last comparison
490 if node.ops:
491 op, code = node.ops[-1]
492 self.visit(code)
493 self.emit('COMPARE_OP', op)
494 if len(node.ops) > 1:
495 end = self.newBlock()
496 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000497 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000498 self.emit('ROT_TWO')
499 self.emit('POP_TOP')
500 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000501
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000502 # list comprehensions
503 __list_count = 0
504
505 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000506 self.set_lineno(node)
507 # setup list
508 append = "$append%d" % self.__list_count
509 self.__list_count = self.__list_count + 1
510 self.emit('BUILD_LIST', 0)
511 self.emit('DUP_TOP')
512 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000513 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000514
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000515 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000516 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000517 start, anchor = self.visit(for_)
518 cont = None
519 for if_ in for_.ifs:
520 if cont is None:
521 cont = self.newBlock()
522 self.visit(if_, cont)
523 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000524
Jeremy Hylton13d70942001-04-12 21:04:43 +0000525 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000526 self.visit(node.expr)
527 self.emit('CALL_FUNCTION', 1)
528 self.emit('POP_TOP')
529
530 for start, cont, anchor in stack:
531 if cont:
532 skip_one = self.newBlock()
533 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000534 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000535 self.emit('POP_TOP')
536 self.nextBlock(skip_one)
537 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000538 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000539 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000540
541 self.__list_count = self.__list_count - 1
542
543 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000544 start = self.newBlock()
545 anchor = self.newBlock()
546
547 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000548 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000549 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000550 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000551 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000552 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000553 self.visit(node.assign)
554 return start, anchor
555
556 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000557 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000558 self.visit(node.test)
559 self.emit('JUMP_IF_FALSE', branch)
560 self.newBlock()
561 self.emit('POP_TOP')
562
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000563 # exception related
564
565 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000566 # XXX would be interesting to implement this via a
567 # transformation of the AST before this stage
568 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000569 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000570 # XXX __debug__ and AssertionError appear to be special cases
571 # -- they are always loaded as globals even if there are local
572 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000573 self.emit('LOAD_GLOBAL', '__debug__')
574 self.emit('JUMP_IF_FALSE', end)
575 self.nextBlock()
576 self.emit('POP_TOP')
577 self.visit(node.test)
578 self.emit('JUMP_IF_TRUE', end)
579 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000580 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000581 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000582 if node.fail:
583 self.visit(node.fail)
584 self.emit('RAISE_VARARGS', 2)
585 else:
586 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000587 self.nextBlock(end)
588 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000589
590 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000591 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000592 n = 0
593 if node.expr1:
594 self.visit(node.expr1)
595 n = n + 1
596 if node.expr2:
597 self.visit(node.expr2)
598 n = n + 1
599 if node.expr3:
600 self.visit(node.expr3)
601 n = n + 1
602 self.emit('RAISE_VARARGS', n)
603
604 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000605 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000606 handlers = self.newBlock()
607 end = self.newBlock()
608 if node.else_:
609 lElse = self.newBlock()
610 else:
611 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000612 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000613 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000614 self.nextBlock(body)
615 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000616 self.visit(node.body)
617 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000618 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000619 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000620 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000621
622 last = len(node.handlers) - 1
623 for i in range(len(node.handlers)):
624 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000625 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000626 if expr:
627 self.emit('DUP_TOP')
628 self.visit(expr)
629 self.emit('COMPARE_OP', 'exception match')
630 next = self.newBlock()
631 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000632 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000633 self.emit('POP_TOP')
634 self.emit('POP_TOP')
635 if target:
636 self.visit(target)
637 else:
638 self.emit('POP_TOP')
639 self.emit('POP_TOP')
640 self.visit(body)
641 self.emit('JUMP_FORWARD', end)
642 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000643 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000644 else:
645 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000646 if expr: # XXX
647 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000648 self.emit('END_FINALLY')
649 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000650 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000651 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000652 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000653
654 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000655 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000656 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000657 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000658 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000659 self.nextBlock(body)
660 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000661 self.visit(node.body)
662 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000663 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000664 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000665 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000666 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000667 self.visit(node.final)
668 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000669 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000670
671 # misc
672
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000673 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000674 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000675 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000676 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000677
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000678 def visitConst(self, node):
679 self.emit('LOAD_CONST', node.value)
680
681 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000682 self.emit('LOAD_CONST', node.name)
683 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000684
685 def visitGlobal(self, node):
686 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000687 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000688
689 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000690 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000691 self.loadName(node.name)
692
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000693 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000694 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000695
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000696 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000697 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000698 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000699 if VERSION > 1:
700 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000701 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000702 mod = string.split(name, ".")[0]
703 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000704
705 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000706 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000707 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000708 if VERSION > 1:
709 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000710 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000711 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000712 if VERSION > 1:
713 if name == '*':
714 self.namespace = 0
715 self.emit('IMPORT_STAR')
716 # There can only be one name w/ from ... import *
717 assert len(node.names) == 1
718 return
719 else:
720 self.emit('IMPORT_FROM', name)
721 self._resolveDots(name)
722 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000723 else:
724 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000725 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000726
Jeremy Hylton20516082000-09-01 20:33:26 +0000727 def _resolveDots(self, name):
728 elts = string.split(name, ".")
729 if len(elts) == 1:
730 return
731 for elt in elts[1:]:
732 self.emit('LOAD_ATTR', elt)
733
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000734 def visitGetattr(self, node):
735 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000736 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000737
738 # next five implement assignments
739
740 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000741 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000742 self.visit(node.expr)
743 dups = len(node.nodes) - 1
744 for i in range(len(node.nodes)):
745 elt = node.nodes[i]
746 if i < dups:
747 self.emit('DUP_TOP')
748 if isinstance(elt, ast.Node):
749 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000750
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000751 def visitAssName(self, node):
752 if node.flags == 'OP_ASSIGN':
753 self.storeName(node.name)
754 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000755 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000756 self.delName(node.name)
757 else:
758 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000759
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000760 def visitAssAttr(self, node):
761 self.visit(node.expr)
762 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000763 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000764 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000765 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000766 else:
767 print "warning: unexpected flags:", node.flags
768 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000769
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000770 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000771 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000772 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000773 for child in node.nodes:
774 self.visit(child)
775
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000776 if VERSION > 1:
777 visitAssTuple = _visitAssSequence
778 visitAssList = _visitAssSequence
779 else:
780 def visitAssTuple(self, node):
781 self._visitAssSequence(node, 'UNPACK_TUPLE')
782
783 def visitAssList(self, node):
784 self._visitAssSequence(node, 'UNPACK_LIST')
785
786 # augmented assignment
787
788 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000789 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000790 aug_node = wrap_aug(node.node)
791 self.visit(aug_node, "load")
792 self.visit(node.expr)
793 self.emit(self._augmented_opcode[node.op])
794 self.visit(aug_node, "store")
795
796 _augmented_opcode = {
797 '+=' : 'INPLACE_ADD',
798 '-=' : 'INPLACE_SUBTRACT',
799 '*=' : 'INPLACE_MULTIPLY',
800 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000801 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000802 '%=' : 'INPLACE_MODULO',
803 '**=': 'INPLACE_POWER',
804 '>>=': 'INPLACE_RSHIFT',
805 '<<=': 'INPLACE_LSHIFT',
806 '&=' : 'INPLACE_AND',
807 '^=' : 'INPLACE_XOR',
808 '|=' : 'INPLACE_OR',
809 }
810
811 def visitAugName(self, node, mode):
812 if mode == "load":
813 self.loadName(node.name)
814 elif mode == "store":
815 self.storeName(node.name)
816
817 def visitAugGetattr(self, node, mode):
818 if mode == "load":
819 self.visit(node.expr)
820 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000821 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000822 elif mode == "store":
823 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000824 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000825
826 def visitAugSlice(self, node, mode):
827 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000828 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000829 elif mode == "store":
830 slice = 0
831 if node.lower:
832 slice = slice | 1
833 if node.upper:
834 slice = slice | 2
835 if slice == 0:
836 self.emit('ROT_TWO')
837 elif slice == 3:
838 self.emit('ROT_FOUR')
839 else:
840 self.emit('ROT_THREE')
841 self.emit('STORE_SLICE+%d' % slice)
842
843 def visitAugSubscript(self, node, mode):
844 if len(node.subs) > 1:
845 raise SyntaxError, "augmented assignment to tuple is not possible"
846 if mode == "load":
847 self.visitSubscript(node, 1)
848 elif mode == "store":
849 self.emit('ROT_THREE')
850 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000851
852 def visitExec(self, node):
853 self.visit(node.expr)
854 if node.locals is None:
855 self.emit('LOAD_CONST', None)
856 else:
857 self.visit(node.locals)
858 if node.globals is None:
859 self.emit('DUP_TOP')
860 else:
861 self.visit(node.globals)
862 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000863
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000864 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000865 pos = 0
866 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000867 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000868 self.visit(node.node)
869 for arg in node.args:
870 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000871 if isinstance(arg, ast.Keyword):
872 kw = kw + 1
873 else:
874 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000875 if node.star_args is not None:
876 self.visit(node.star_args)
877 if node.dstar_args is not None:
878 self.visit(node.dstar_args)
879 have_star = node.star_args is not None
880 have_dstar = node.dstar_args is not None
881 opcode = callfunc_opcode_info[have_star, have_dstar]
882 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000883
Jeremy Hylton2afff322001-08-27 21:51:52 +0000884 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000885 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000886 if node.dest:
887 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000888 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000889 if node.dest:
890 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000891 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000892 if node.dest:
893 self.emit('ROT_TWO')
894 self.emit('PRINT_ITEM_TO')
895 else:
896 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000897 if node.dest and not newline:
898 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000899
900 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000901 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000902 if node.dest:
903 self.emit('PRINT_NEWLINE_TO')
904 else:
905 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000906
907 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000908 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000909 self.visit(node.value)
910 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000911
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000912 def visitYield(self, node):
913 self.set_lineno(node)
914 self.visit(node.value)
915 self.emit('YIELD_STMT')
916
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000917 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000918
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000919 def visitSlice(self, node, aug_flag=None):
920 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000921 self.visit(node.expr)
922 slice = 0
923 if node.lower:
924 self.visit(node.lower)
925 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000926 if node.upper:
927 self.visit(node.upper)
928 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000929 if aug_flag:
930 if slice == 0:
931 self.emit('DUP_TOP')
932 elif slice == 3:
933 self.emit('DUP_TOPX', 3)
934 else:
935 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000936 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000937 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000938 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000939 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000940 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000941 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000942 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000943 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000944 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000945
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000946 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000947 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000948 for sub in node.subs:
949 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000950 if aug_flag:
951 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000952 if len(node.subs) > 1:
953 self.emit('BUILD_TUPLE', len(node.subs))
954 if node.flags == 'OP_APPLY':
955 self.emit('BINARY_SUBSCR')
956 elif node.flags == 'OP_ASSIGN':
957 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000958 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000959 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000960
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000961 # binary ops
962
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000963 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000964 self.visit(node.left)
965 self.visit(node.right)
966 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000967
968 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000969 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000970
971 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000972 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000973
974 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000975 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000976
977 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000978 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000979
Jeremy Hylton94afe322001-08-29 18:14:39 +0000980 def visitFloorDiv(self, node):
981 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
982
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000983 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000984 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000985
Jeremy Hylton126960b2000-02-14 21:33:10 +0000986 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000987 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000988
989 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000990 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000991
992 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000993 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000994
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000995 # unary ops
996
997 def unaryOp(self, node, op):
998 self.visit(node.expr)
999 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001000
Jeremy Hylton126960b2000-02-14 21:33:10 +00001001 def visitInvert(self, node):
1002 return self.unaryOp(node, 'UNARY_INVERT')
1003
Jeremy Hylton40245602000-02-08 21:15:48 +00001004 def visitUnarySub(self, node):
1005 return self.unaryOp(node, 'UNARY_NEGATIVE')
1006
1007 def visitUnaryAdd(self, node):
1008 return self.unaryOp(node, 'UNARY_POSITIVE')
1009
1010 def visitUnaryInvert(self, node):
1011 return self.unaryOp(node, 'UNARY_INVERT')
1012
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001013 def visitNot(self, node):
1014 return self.unaryOp(node, 'UNARY_NOT')
1015
Jeremy Hylton40245602000-02-08 21:15:48 +00001016 def visitBackquote(self, node):
1017 return self.unaryOp(node, 'UNARY_CONVERT')
1018
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001019 # bit ops
1020
Jeremy Hyltona5058122000-02-14 14:14:29 +00001021 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001022 self.visit(nodes[0])
1023 for node in nodes[1:]:
1024 self.visit(node)
1025 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001026
1027 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001028 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001029
1030 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001031 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001032
1033 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001034 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001035
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001036 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001037
Jeremy Hyltona5058122000-02-14 14:14:29 +00001038 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001039 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001040
Jeremy Hylton40245602000-02-08 21:15:48 +00001041 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001042 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001043 for elt in node.nodes:
1044 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001045 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001046
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001047 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001048 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001049 for elt in node.nodes:
1050 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001051 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001052
1053 def visitSliceobj(self, node):
1054 for child in node.nodes:
1055 self.visit(child)
1056 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001057
Jeremy Hyltona5058122000-02-14 14:14:29 +00001058 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001059 lineno = getattr(node, 'lineno', None)
1060 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001061 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001062 self.emit('BUILD_MAP', 0)
1063 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001064 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001065 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001066 self.emit('SET_LINENO', lineno2)
1067 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001068 self.emit('DUP_TOP')
1069 self.visit(v)
1070 self.emit('ROT_TWO')
1071 self.visit(k)
1072 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001073
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001074class NestedScopeMixin:
1075 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001076 def initClass(self):
1077 self.__class__.NameFinder = LocalNameFinder
1078 self.__class__.FunctionGen = FunctionCodeGenerator
1079 self.__class__.ClassGen = ClassCodeGenerator
1080
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001081class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001082 __super_init = CodeGenerator.__init__
1083
1084 scopes = None
1085
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001086 def __init__(self, filename, tree):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001087 self.graph = pyassem.PyFlowGraph("<module>", filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001088 self.futures = future.find_futures(tree)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001089 self.__super_init(filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001090 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001091
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001092 def get_module(self):
1093 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001094
1095class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001096 optimized = 1
1097 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001098
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001099 def __init__(self, func, filename, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001100 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001101 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001102 if isLambda:
1103 klass = FunctionCodeGenerator
1104 name = "<lambda.%d>" % klass.lambdaCount
1105 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001106 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001107 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001108 args, hasTupleArg = generateArgList(func.argnames)
1109 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001110 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001111 self.isLambda = isLambda
1112 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001113
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001114 if not isLambda and func.doc:
1115 self.setDocstring(func.doc)
1116
Jeremy Hylton2afff322001-08-27 21:51:52 +00001117 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001118 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001119 if func.varargs:
1120 self.graph.setFlag(CO_VARARGS)
1121 if func.kwargs:
1122 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001123 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001124 if hasTupleArg:
1125 self.generateArgUnpack(func.argnames)
1126
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001127 def get_module(self):
1128 return self.module
1129
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001130 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001131 self.graph.startExitBlock()
1132 if not self.isLambda:
1133 self.emit('LOAD_CONST', None)
1134 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001135
1136 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001137 for i in range(len(args)):
1138 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001139 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001140 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001141 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001142
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001143 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001144 if VERSION > 1:
1145 self.emit('UNPACK_SEQUENCE', len(tup))
1146 else:
1147 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001148 for elt in tup:
1149 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001150 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001151 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001152 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001153
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001154 unpackTuple = unpackSequence
1155
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001156class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001157 CodeGenerator):
1158 super_init = CodeGenerator.__init__ # call be other init
1159 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001160
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001161 __super_init = AbstractFunctionCode.__init__
1162
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001163 def __init__(self, func, filename, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001164 self.scopes = scopes
1165 self.scope = scopes[func]
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001166 self.__super_init(func, filename, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001167 self.graph.setFreeVars(self.scope.get_free_vars())
1168 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001169 if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
1170 if self.scope.generator is not None:
1171 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001172
1173class AbstractClassCode:
1174
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001175 def __init__(self, klass, filename, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001176 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001177 self.module = module
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001178 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001179 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001180 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001181 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001182 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001183 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001184 if klass.doc:
1185 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001186
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001187 def get_module(self):
1188 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001189
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001190 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001191 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001192 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001193 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001194
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001195class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001196 super_init = CodeGenerator.__init__
1197 scopes = None
1198
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001199 __super_init = AbstractClassCode.__init__
1200
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001201 def __init__(self, klass, filename, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001202 self.scopes = scopes
1203 self.scope = scopes[klass]
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001204 self.__super_init(klass, filename, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001205 self.graph.setFreeVars(self.scope.get_free_vars())
1206 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001207## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001208
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001209def generateArgList(arglist):
1210 """Generate an arg list marking TupleArgs"""
1211 args = []
1212 extra = []
1213 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001214 for i in range(len(arglist)):
1215 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001216 if type(elt) == types.StringType:
1217 args.append(elt)
1218 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001219 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001220 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001221 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001222 else:
1223 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001224 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001225
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001226def findOp(node):
1227 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1228 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001229 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001230 return v.op
1231
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001232class OpFinder:
1233 def __init__(self):
1234 self.op = None
1235 def visitAssName(self, node):
1236 if self.op is None:
1237 self.op = node.flags
1238 elif self.op != node.flags:
1239 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001240 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001241
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001242class Delegator:
1243 """Base class to support delegation for augmented assignment nodes
1244
1245 To generator code for augmented assignments, we use the following
1246 wrapper classes. In visitAugAssign, the left-hand expression node
1247 is visited twice. The first time the visit uses the normal method
1248 for that node . The second time the visit uses a different method
1249 that generates the appropriate code to perform the assignment.
1250 These delegator classes wrap the original AST nodes in order to
1251 support the variant visit methods.
1252 """
1253 def __init__(self, obj):
1254 self.obj = obj
1255
1256 def __getattr__(self, attr):
1257 return getattr(self.obj, attr)
1258
1259class AugGetattr(Delegator):
1260 pass
1261
1262class AugName(Delegator):
1263 pass
1264
1265class AugSlice(Delegator):
1266 pass
1267
1268class AugSubscript(Delegator):
1269 pass
1270
1271wrapper = {
1272 ast.Getattr: AugGetattr,
1273 ast.Name: AugName,
1274 ast.Slice: AugSlice,
1275 ast.Subscript: AugSubscript,
1276 }
1277
1278def wrap_aug(node):
1279 return wrapper[node.__class__](node)
1280
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001281if __name__ == "__main__":
1282 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001283
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001284 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001285 compile(file)