blob: bfb50597b9aa71e86afbdd16b691584a033a6355 [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 Hylton36cc6a22000-03-16 20:06:59 +0000912 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000913
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000914 def visitSlice(self, node, aug_flag=None):
915 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000916 self.visit(node.expr)
917 slice = 0
918 if node.lower:
919 self.visit(node.lower)
920 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000921 if node.upper:
922 self.visit(node.upper)
923 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000924 if aug_flag:
925 if slice == 0:
926 self.emit('DUP_TOP')
927 elif slice == 3:
928 self.emit('DUP_TOPX', 3)
929 else:
930 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000931 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000932 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000933 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000934 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000935 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000936 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000937 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000938 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000939 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000940
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000941 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000942 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000943 for sub in node.subs:
944 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000945 if aug_flag:
946 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000947 if len(node.subs) > 1:
948 self.emit('BUILD_TUPLE', len(node.subs))
949 if node.flags == 'OP_APPLY':
950 self.emit('BINARY_SUBSCR')
951 elif node.flags == 'OP_ASSIGN':
952 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000953 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000954 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000955
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000956 # binary ops
957
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000958 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000959 self.visit(node.left)
960 self.visit(node.right)
961 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000962
963 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000964 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000965
966 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000967 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000968
969 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000970 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000971
972 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000973 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000974
Jeremy Hylton94afe322001-08-29 18:14:39 +0000975 def visitFloorDiv(self, node):
976 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
977
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000978 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000979 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000980
Jeremy Hylton126960b2000-02-14 21:33:10 +0000981 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000982 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000983
984 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000985 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000986
987 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000988 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000989
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000990 # unary ops
991
992 def unaryOp(self, node, op):
993 self.visit(node.expr)
994 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000995
Jeremy Hylton126960b2000-02-14 21:33:10 +0000996 def visitInvert(self, node):
997 return self.unaryOp(node, 'UNARY_INVERT')
998
Jeremy Hylton40245602000-02-08 21:15:48 +0000999 def visitUnarySub(self, node):
1000 return self.unaryOp(node, 'UNARY_NEGATIVE')
1001
1002 def visitUnaryAdd(self, node):
1003 return self.unaryOp(node, 'UNARY_POSITIVE')
1004
1005 def visitUnaryInvert(self, node):
1006 return self.unaryOp(node, 'UNARY_INVERT')
1007
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001008 def visitNot(self, node):
1009 return self.unaryOp(node, 'UNARY_NOT')
1010
Jeremy Hylton40245602000-02-08 21:15:48 +00001011 def visitBackquote(self, node):
1012 return self.unaryOp(node, 'UNARY_CONVERT')
1013
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001014 # bit ops
1015
Jeremy Hyltona5058122000-02-14 14:14:29 +00001016 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001017 self.visit(nodes[0])
1018 for node in nodes[1:]:
1019 self.visit(node)
1020 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001021
1022 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001023 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001024
1025 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001026 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001027
1028 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001029 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001030
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001031 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001032
Jeremy Hyltona5058122000-02-14 14:14:29 +00001033 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001034 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001035
Jeremy Hylton40245602000-02-08 21:15:48 +00001036 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001037 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001038 for elt in node.nodes:
1039 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001040 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001041
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001042 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001043 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001044 for elt in node.nodes:
1045 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001046 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001047
1048 def visitSliceobj(self, node):
1049 for child in node.nodes:
1050 self.visit(child)
1051 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001052
Jeremy Hyltona5058122000-02-14 14:14:29 +00001053 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001054 lineno = getattr(node, 'lineno', None)
1055 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001056 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001057 self.emit('BUILD_MAP', 0)
1058 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001059 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001060 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001061 self.emit('SET_LINENO', lineno2)
1062 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001063 self.emit('DUP_TOP')
1064 self.visit(v)
1065 self.emit('ROT_TWO')
1066 self.visit(k)
1067 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001068
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001069class NestedScopeMixin:
1070 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001071 def initClass(self):
1072 self.__class__.NameFinder = LocalNameFinder
1073 self.__class__.FunctionGen = FunctionCodeGenerator
1074 self.__class__.ClassGen = ClassCodeGenerator
1075
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001076class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001077 __super_init = CodeGenerator.__init__
1078
1079 scopes = None
1080
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001081 def __init__(self, filename, tree):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001082 self.graph = pyassem.PyFlowGraph("<module>", filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001083 self.futures = future.find_futures(tree)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001084 self.__super_init(filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001085 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001086
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001087 def get_module(self):
1088 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001089
1090class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001091 optimized = 1
1092 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001093
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001094 def __init__(self, func, filename, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001095 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001096 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001097 if isLambda:
1098 klass = FunctionCodeGenerator
1099 name = "<lambda.%d>" % klass.lambdaCount
1100 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001101 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001102 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001103 args, hasTupleArg = generateArgList(func.argnames)
1104 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001105 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001106 self.isLambda = isLambda
1107 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001108
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001109 if not isLambda and func.doc:
1110 self.setDocstring(func.doc)
1111
Jeremy Hylton2afff322001-08-27 21:51:52 +00001112 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001113 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001114 if func.varargs:
1115 self.graph.setFlag(CO_VARARGS)
1116 if func.kwargs:
1117 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001118 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001119 if hasTupleArg:
1120 self.generateArgUnpack(func.argnames)
1121
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001122 def get_module(self):
1123 return self.module
1124
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001125 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001126 self.graph.startExitBlock()
1127 if not self.isLambda:
1128 self.emit('LOAD_CONST', None)
1129 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001130
1131 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001132 for i in range(len(args)):
1133 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001134 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001135 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001136 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001137
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001138 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001139 if VERSION > 1:
1140 self.emit('UNPACK_SEQUENCE', len(tup))
1141 else:
1142 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001143 for elt in tup:
1144 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001145 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001146 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001147 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001148
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001149 unpackTuple = unpackSequence
1150
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001151class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001152 CodeGenerator):
1153 super_init = CodeGenerator.__init__ # call be other init
1154 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001155
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001156 __super_init = AbstractFunctionCode.__init__
1157
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001158 def __init__(self, func, filename, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001159 self.scopes = scopes
1160 self.scope = scopes[func]
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001161 self.__super_init(func, filename, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001162 self.graph.setFreeVars(self.scope.get_free_vars())
1163 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001164 if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
1165 if self.scope.generator is not None:
1166 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001167
1168class AbstractClassCode:
1169
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001170 def __init__(self, klass, filename, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001171 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001172 self.module = module
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001173 self.graph = pyassem.PyFlowGraph(klass.name, filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001174 optimized=0, klass=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001175 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001176 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001177 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001178 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001179 if klass.doc:
1180 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001181
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001182 def get_module(self):
1183 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001184
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001185 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001186 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001187 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001188 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001189
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001190class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001191 super_init = CodeGenerator.__init__
1192 scopes = None
1193
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001194 __super_init = AbstractClassCode.__init__
1195
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001196 def __init__(self, klass, filename, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001197 self.scopes = scopes
1198 self.scope = scopes[klass]
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001199 self.__super_init(klass, filename, scopes, module)
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
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001204def generateArgList(arglist):
1205 """Generate an arg list marking TupleArgs"""
1206 args = []
1207 extra = []
1208 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001209 for i in range(len(arglist)):
1210 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001211 if type(elt) == types.StringType:
1212 args.append(elt)
1213 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001214 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001215 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001216 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001217 else:
1218 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001219 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001220
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001221def findOp(node):
1222 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1223 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001224 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001225 return v.op
1226
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001227class OpFinder:
1228 def __init__(self):
1229 self.op = None
1230 def visitAssName(self, node):
1231 if self.op is None:
1232 self.op = node.flags
1233 elif self.op != node.flags:
1234 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001235 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001236
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001237class Delegator:
1238 """Base class to support delegation for augmented assignment nodes
1239
1240 To generator code for augmented assignments, we use the following
1241 wrapper classes. In visitAugAssign, the left-hand expression node
1242 is visited twice. The first time the visit uses the normal method
1243 for that node . The second time the visit uses a different method
1244 that generates the appropriate code to perform the assignment.
1245 These delegator classes wrap the original AST nodes in order to
1246 support the variant visit methods.
1247 """
1248 def __init__(self, obj):
1249 self.obj = obj
1250
1251 def __getattr__(self, attr):
1252 return getattr(self.obj, attr)
1253
1254class AugGetattr(Delegator):
1255 pass
1256
1257class AugName(Delegator):
1258 pass
1259
1260class AugSlice(Delegator):
1261 pass
1262
1263class AugSubscript(Delegator):
1264 pass
1265
1266wrapper = {
1267 ast.Getattr: AugGetattr,
1268 ast.Name: AugName,
1269 ast.Slice: AugSlice,
1270 ast.Subscript: AugSubscript,
1271 }
1272
1273def wrap_aug(node):
1274 return wrapper[node.__class__](node)
1275
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001276if __name__ == "__main__":
1277 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001278
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001279 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001280 compile(file)