blob: 67a1033e1316d3003f8ed2f512a2fa1943d7aa6a [file] [log] [blame]
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001import imp
Jeremy Hylton53187f32000-02-08 19:01:29 +00002import os
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00003import marshal
Jeremy Hylton53187f32000-02-08 19:01:29 +00004import stat
Jeremy Hylton20516082000-09-01 20:33:26 +00005import string
Jeremy Hylton53187f32000-02-08 19:01:29 +00006import struct
Jeremy Hylton9c048f92000-10-13 21:58:13 +00007import sys
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00008import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00009from cStringIO import StringIO
10
11from compiler import ast, parse, walk
Jeremy Hylton364f9b92001-04-12 06:40:42 +000012from compiler import pyassem, misc, future, symbols
13from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
14from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
15 CO_NESTED, TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000016
Jeremy Hylton9c048f92000-10-13 21:58:13 +000017# Do we have Python 1.x or Python 2.x?
18try:
19 VERSION = sys.version_info[0]
20except AttributeError:
21 VERSION = 1
22
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000023callfunc_opcode_info = {
24 # (Have *args, Have **args) : opcode
25 (0,0) : "CALL_FUNCTION",
26 (1,0) : "CALL_FUNCTION_VAR",
27 (0,1) : "CALL_FUNCTION_KW",
28 (1,1) : "CALL_FUNCTION_VAR_KW",
29}
30
Jeremy Hylton9c048f92000-10-13 21:58:13 +000031def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000032 f = open(filename)
33 buf = f.read()
34 f.close()
35 mod = Module(buf, filename)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000036 mod.compile(display)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000037 f = open(filename + "c", "wb")
38 mod.dump(f)
39 f.close()
40
41class Module:
42 def __init__(self, source, filename):
Jeremy Hylton2afff322001-08-27 21:51:52 +000043 self.filename = os.path.abspath(filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000044 self.source = source
45 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000046
Jeremy Hylton9c048f92000-10-13 21:58:13 +000047 def compile(self, display=0):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000048 tree = parse(self.source)
Jeremy Hylton2afff322001-08-27 21:51:52 +000049 gen = NestedScopeModuleCodeGenerator(self.filename)
50 walk(tree, gen, verbose=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000051 if display:
52 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000053 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000054 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000055
56 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000057 f.write(self.getPycHeader())
58 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000059
Jeremy Hylton9c048f92000-10-13 21:58:13 +000060 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000061
62 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000063 # compile.c uses marshal to write a long directly, with
64 # calling the interface that would also generate a 1-byte code
65 # to indicate the type of the value. simplest way to get the
66 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000067 mtime = os.stat(self.filename)[stat.ST_MTIME]
68 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000069 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000070
Jeremy Hylton364f9b92001-04-12 06:40:42 +000071class LocalNameFinder:
72 """Find local names in scope"""
73 def __init__(self, names=()):
74 self.names = misc.Set()
75 self.globals = misc.Set()
76 for name in names:
77 self.names.add(name)
78
79 # XXX list comprehensions and for loops
80
81 def getLocals(self):
82 for elt in self.globals.elements():
83 if self.names.has_elt(elt):
84 self.names.remove(elt)
85 return self.names
86
87 def visitDict(self, node):
88 pass
89
90 def visitGlobal(self, node):
91 for name in node.names:
92 self.globals.add(name)
93
94 def visitFunction(self, node):
95 self.names.add(node.name)
96
97 def visitLambda(self, node):
98 pass
99
100 def visitImport(self, node):
101 for name, alias in node.names:
102 self.names.add(alias or name)
103
104 def visitFrom(self, node):
105 for name, alias in node.names:
106 self.names.add(alias or name)
107
108 def visitClass(self, node):
109 self.names.add(node.name)
110
111 def visitAssName(self, node):
112 self.names.add(node.name)
113
Jeremy Hylton2afff322001-08-27 21:51:52 +0000114def is_constant_false(node):
115 if isinstance(node, ast.Const):
116 if not node.value:
117 return 1
118 return 0
119
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000120class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000121 """Defines basic code generator for Python bytecode
122
123 This class is an abstract base class. Concrete subclasses must
124 define an __init__() that defines self.graph and then calls the
125 __init__() defined in this class.
126
127 The concrete class must also define the class attributes
128 NameFinder, FunctionGen, and ClassGen. These attributes can be
129 defined in the initClass() method, which is a hook for
130 initializing these methods after all the classes have been
131 defined.
132 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000133
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000134 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000135 __initialized = None
Jeremy Hylton3050d512000-02-12 00:12:38 +0000136
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000137 def __init__(self, filename):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000138 if self.__initialized is None:
139 self.initClass()
140 self.__class__.__initialized = 1
141 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000142 self.filename = filename
143 self.locals = misc.Stack()
144 self.loops = misc.Stack()
145 self.curStack = 0
146 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000147 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000148 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000149
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000150 def initClass(self):
151 """This method is called once for each class"""
152
153 def checkClass(self):
154 """Verify that class is constructed correctly"""
155 try:
156 assert hasattr(self, 'graph')
157 assert getattr(self, 'NameFinder')
158 assert getattr(self, 'FunctionGen')
159 assert getattr(self, 'ClassGen')
160 except AssertionError, msg:
161 intro = "Bad class construction for %s" % self.__class__.__name__
162 raise AssertionError, intro
163
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000164 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000165 self.emit = self.graph.emit
166 self.newBlock = self.graph.newBlock
167 self.startBlock = self.graph.startBlock
168 self.nextBlock = self.graph.nextBlock
169 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000170
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000171 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000172 """Return a code object"""
173 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000174
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000175 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000176
Jeremy Hylton40245602000-02-08 21:15:48 +0000177 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000178 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000179
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000180 def storeName(self, name):
181 self._nameOp('STORE', name)
182
183 def loadName(self, name):
184 self._nameOp('LOAD', name)
185
186 def delName(self, name):
187 self._nameOp('DELETE', name)
188
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000189 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000190 if not self.optimized:
191 self.emit(prefix + '_NAME', name)
192 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000193 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000194 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000195 else:
196 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000197
Jeremy Hylton13d70942001-04-12 21:04:43 +0000198 def _implicitNameOp(self, prefix, name):
199 """Emit name ops for names generated implicitly by for loops
200
201 The interpreter generates names that start with a period or
202 dollar sign. The symbol table ignores these names because
203 they aren't present in the program text.
204 """
205 if self.optimized:
206 self.emit(prefix + '_FAST', name)
207 else:
208 self.emit(prefix + '_NAME', name)
209
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000210 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000211 """Emit SET_LINENO if node has lineno attribute and it is
212 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000213
214 Returns true if SET_LINENO was emitted.
215
216 There are no rules for when an AST node should have a lineno
217 attribute. The transformer and AST code need to be reviewed
218 and a consistent policy implemented and documented. Until
219 then, this method works around missing line numbers.
220 """
221 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000222 if lineno is not None and (lineno != self.last_lineno
223 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000224 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000225 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000226 return 1
227 return 0
228
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000229 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000230 # code objects. They use class attributes to determine what
231 # specialized code generators to use.
232
233 NameFinder = LocalNameFinder
234 FunctionGen = None
235 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236
237 def visitModule(self, node):
Jeremy Hylton13d70942001-04-12 21:04:43 +0000238 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000239 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000240 self.emit('LOAD_CONST', node.doc)
241 self.storeName('__doc__')
242 lnf = walk(node.node, self.NameFinder(), verbose=0)
243 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000244 self.visit(node.node)
245 self.emit('LOAD_CONST', None)
246 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000247
248 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000249 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000250 if node.doc:
251 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000252 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000253
254 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000255 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000256
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000257 def _visitFuncOrLambda(self, node, isLambda=0):
258 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000259 walk(node.code, gen)
260 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000261 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000262 for default in node.defaults:
263 self.visit(default)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000264 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000265 self.emit('MAKE_FUNCTION', len(node.defaults))
266
267 def visitClass(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000268 gen = self.ClassGen(node, self.filename, self.scopes)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000269 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000270 self.emit('LOAD_CONST', node.doc)
271 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000272 walk(node.code, gen)
273 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000274 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000275 self.emit('LOAD_CONST', node.name)
276 for base in node.bases:
277 self.visit(base)
278 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000279 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000280 self.emit('MAKE_FUNCTION', 0)
281 self.emit('CALL_FUNCTION', 0)
282 self.emit('BUILD_CLASS')
283 self.storeName(node.name)
284
285 # The rest are standard visitor methods
286
287 # The next few implement control-flow statements
288
289 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000290 end = self.newBlock()
291 numtests = len(node.tests)
292 for i in range(numtests):
293 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000294 if is_constant_false(test):
295 # XXX will need to check generator stuff here
296 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000297 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000298 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000299 nextTest = self.newBlock()
300 self.emit('JUMP_IF_FALSE', nextTest)
301 self.nextBlock()
302 self.emit('POP_TOP')
303 self.visit(suite)
304 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000305 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000306 self.emit('POP_TOP')
307 if node.else_:
308 self.visit(node.else_)
309 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000310
311 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000312 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000313
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000314 loop = self.newBlock()
315 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000316
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000317 after = self.newBlock()
318 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000319
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000320 self.nextBlock(loop)
321 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000322
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000323 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000324 self.visit(node.test)
325 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000326
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000327 self.nextBlock()
328 self.emit('POP_TOP')
329 self.visit(node.body)
330 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000331
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000332 self.startBlock(else_) # or just the POPs if not else clause
333 self.emit('POP_TOP')
334 self.emit('POP_BLOCK')
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000335 self.loops.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000336 if node.else_:
337 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000338 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000339
340 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000341 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000342 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000343 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000344 self.loops.push(start)
345
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000346 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000347 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000348 self.visit(node.list)
349 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000350 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000351 self.set_lineno(node, force=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000352 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000353 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000354 self.visit(node.assign)
355 self.visit(node.body)
356 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000357 self.startBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000358 self.emit('POP_BLOCK')
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000359 self.loops.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000360 if node.else_:
361 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000362 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000363
364 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000365 if not self.loops:
366 raise SyntaxError, "'break' outside loop (%s, %d)" % \
367 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000368 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000369 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000370
371 def visitContinue(self, node):
372 if not self.loops:
373 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000374 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000375 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000376 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000377 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000378 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000379
380 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000381 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000382 for child in node.nodes[:-1]:
383 self.visit(child)
384 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000385 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000386 self.emit('POP_TOP')
387 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000388 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000389
390 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000391 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000392
393 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000394 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000395
396 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000397 self.visit(node.expr)
398 cleanup = self.newBlock()
399 for op, code in node.ops[:-1]:
400 self.visit(code)
401 self.emit('DUP_TOP')
402 self.emit('ROT_THREE')
403 self.emit('COMPARE_OP', op)
404 self.emit('JUMP_IF_FALSE', cleanup)
405 self.nextBlock()
406 self.emit('POP_TOP')
407 # now do the last comparison
408 if node.ops:
409 op, code = node.ops[-1]
410 self.visit(code)
411 self.emit('COMPARE_OP', op)
412 if len(node.ops) > 1:
413 end = self.newBlock()
414 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000415 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000416 self.emit('ROT_TWO')
417 self.emit('POP_TOP')
418 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000419
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000420 # list comprehensions
421 __list_count = 0
422
423 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000424 self.set_lineno(node)
425 # setup list
426 append = "$append%d" % self.__list_count
427 self.__list_count = self.__list_count + 1
428 self.emit('BUILD_LIST', 0)
429 self.emit('DUP_TOP')
430 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000431 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000432
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000433 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000434 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000435 start, anchor = self.visit(for_)
436 cont = None
437 for if_ in for_.ifs:
438 if cont is None:
439 cont = self.newBlock()
440 self.visit(if_, cont)
441 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000442
Jeremy Hylton13d70942001-04-12 21:04:43 +0000443 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000444 self.visit(node.expr)
445 self.emit('CALL_FUNCTION', 1)
446 self.emit('POP_TOP')
447
448 for start, cont, anchor in stack:
449 if cont:
450 skip_one = self.newBlock()
451 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000452 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000453 self.emit('POP_TOP')
454 self.nextBlock(skip_one)
455 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000456 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000457 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000458
459 self.__list_count = self.__list_count - 1
460
461 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000462 start = self.newBlock()
463 anchor = self.newBlock()
464
465 self.visit(node.list)
466 self.visit(ast.Const(0))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000467 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000468 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000469 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000470 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000471 self.visit(node.assign)
472 return start, anchor
473
474 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000475 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000476 self.visit(node.test)
477 self.emit('JUMP_IF_FALSE', branch)
478 self.newBlock()
479 self.emit('POP_TOP')
480
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000481 # exception related
482
483 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000484 # XXX would be interesting to implement this via a
485 # transformation of the AST before this stage
486 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000487 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000488 # XXX __debug__ and AssertionError appear to be special cases
489 # -- they are always loaded as globals even if there are local
490 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000491 self.emit('LOAD_GLOBAL', '__debug__')
492 self.emit('JUMP_IF_FALSE', end)
493 self.nextBlock()
494 self.emit('POP_TOP')
495 self.visit(node.test)
496 self.emit('JUMP_IF_TRUE', end)
497 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000498 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000499 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000500 if node.fail:
501 self.visit(node.fail)
502 self.emit('RAISE_VARARGS', 2)
503 else:
504 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000505 self.nextBlock(end)
506 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000507
508 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000509 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000510 n = 0
511 if node.expr1:
512 self.visit(node.expr1)
513 n = n + 1
514 if node.expr2:
515 self.visit(node.expr2)
516 n = n + 1
517 if node.expr3:
518 self.visit(node.expr3)
519 n = n + 1
520 self.emit('RAISE_VARARGS', n)
521
522 def visitTryExcept(self, node):
523 handlers = self.newBlock()
524 end = self.newBlock()
525 if node.else_:
526 lElse = self.newBlock()
527 else:
528 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000529 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000530 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000531 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000532 self.visit(node.body)
533 self.emit('POP_BLOCK')
534 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000535 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000536
537 last = len(node.handlers) - 1
538 for i in range(len(node.handlers)):
539 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000540 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000541 if expr:
542 self.emit('DUP_TOP')
543 self.visit(expr)
544 self.emit('COMPARE_OP', 'exception match')
545 next = self.newBlock()
546 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000547 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000548 self.emit('POP_TOP')
549 self.emit('POP_TOP')
550 if target:
551 self.visit(target)
552 else:
553 self.emit('POP_TOP')
554 self.emit('POP_TOP')
555 self.visit(body)
556 self.emit('JUMP_FORWARD', end)
557 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000558 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000559 else:
560 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000561 self.emit('POP_TOP')
562 self.emit('END_FINALLY')
563 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000564 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000565 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000566 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000567
568 def visitTryFinally(self, node):
569 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000570 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000571 self.emit('SETUP_FINALLY', final)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000572 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000573 self.visit(node.body)
574 self.emit('POP_BLOCK')
575 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000576 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000577 self.visit(node.final)
578 self.emit('END_FINALLY')
579
580 # misc
581
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000582 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000583 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000584 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000585 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000586
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000587 def visitConst(self, node):
588 self.emit('LOAD_CONST', node.value)
589
590 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000591 self.emit('LOAD_CONST', node.name)
592 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000593
594 def visitGlobal(self, node):
595 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000596 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000597
598 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000599 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000600 self.loadName(node.name)
601
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000602 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000603 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000604
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000605 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000606 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000607 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000608 if VERSION > 1:
609 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000610 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000611 mod = string.split(name, ".")[0]
612 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000613
614 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000615 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000616 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000617 if VERSION > 1:
618 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000619 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000620 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000621 if VERSION > 1:
622 if name == '*':
623 self.namespace = 0
624 self.emit('IMPORT_STAR')
625 # There can only be one name w/ from ... import *
626 assert len(node.names) == 1
627 return
628 else:
629 self.emit('IMPORT_FROM', name)
630 self._resolveDots(name)
631 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000632 else:
633 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000634 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000635
Jeremy Hylton20516082000-09-01 20:33:26 +0000636 def _resolveDots(self, name):
637 elts = string.split(name, ".")
638 if len(elts) == 1:
639 return
640 for elt in elts[1:]:
641 self.emit('LOAD_ATTR', elt)
642
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000643 def visitGetattr(self, node):
644 self.visit(node.expr)
645 self.emit('LOAD_ATTR', node.attrname)
646
647 # next five implement assignments
648
649 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000650 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000651 self.visit(node.expr)
652 dups = len(node.nodes) - 1
653 for i in range(len(node.nodes)):
654 elt = node.nodes[i]
655 if i < dups:
656 self.emit('DUP_TOP')
657 if isinstance(elt, ast.Node):
658 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000659
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000660 def visitAssName(self, node):
661 if node.flags == 'OP_ASSIGN':
662 self.storeName(node.name)
663 elif node.flags == 'OP_DELETE':
664 self.delName(node.name)
665 else:
666 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000667
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000668 def visitAssAttr(self, node):
669 self.visit(node.expr)
670 if node.flags == 'OP_ASSIGN':
671 self.emit('STORE_ATTR', node.attrname)
672 elif node.flags == 'OP_DELETE':
673 self.emit('DELETE_ATTR', node.attrname)
674 else:
675 print "warning: unexpected flags:", node.flags
676 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000677
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000678 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000679 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000680 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000681 for child in node.nodes:
682 self.visit(child)
683
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000684 if VERSION > 1:
685 visitAssTuple = _visitAssSequence
686 visitAssList = _visitAssSequence
687 else:
688 def visitAssTuple(self, node):
689 self._visitAssSequence(node, 'UNPACK_TUPLE')
690
691 def visitAssList(self, node):
692 self._visitAssSequence(node, 'UNPACK_LIST')
693
694 # augmented assignment
695
696 def visitAugAssign(self, node):
697 aug_node = wrap_aug(node.node)
698 self.visit(aug_node, "load")
699 self.visit(node.expr)
700 self.emit(self._augmented_opcode[node.op])
701 self.visit(aug_node, "store")
702
703 _augmented_opcode = {
704 '+=' : 'INPLACE_ADD',
705 '-=' : 'INPLACE_SUBTRACT',
706 '*=' : 'INPLACE_MULTIPLY',
707 '/=' : 'INPLACE_DIVIDE',
708 '%=' : 'INPLACE_MODULO',
709 '**=': 'INPLACE_POWER',
710 '>>=': 'INPLACE_RSHIFT',
711 '<<=': 'INPLACE_LSHIFT',
712 '&=' : 'INPLACE_AND',
713 '^=' : 'INPLACE_XOR',
714 '|=' : 'INPLACE_OR',
715 }
716
717 def visitAugName(self, node, mode):
718 if mode == "load":
719 self.loadName(node.name)
720 elif mode == "store":
721 self.storeName(node.name)
722
723 def visitAugGetattr(self, node, mode):
724 if mode == "load":
725 self.visit(node.expr)
726 self.emit('DUP_TOP')
727 self.emit('LOAD_ATTR', node.attrname)
728 elif mode == "store":
729 self.emit('ROT_TWO')
730 self.emit('STORE_ATTR', node.attrname)
731
732 def visitAugSlice(self, node, mode):
733 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000734 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000735 elif mode == "store":
736 slice = 0
737 if node.lower:
738 slice = slice | 1
739 if node.upper:
740 slice = slice | 2
741 if slice == 0:
742 self.emit('ROT_TWO')
743 elif slice == 3:
744 self.emit('ROT_FOUR')
745 else:
746 self.emit('ROT_THREE')
747 self.emit('STORE_SLICE+%d' % slice)
748
749 def visitAugSubscript(self, node, mode):
750 if len(node.subs) > 1:
751 raise SyntaxError, "augmented assignment to tuple is not possible"
752 if mode == "load":
753 self.visitSubscript(node, 1)
754 elif mode == "store":
755 self.emit('ROT_THREE')
756 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000757
758 def visitExec(self, node):
759 self.visit(node.expr)
760 if node.locals is None:
761 self.emit('LOAD_CONST', None)
762 else:
763 self.visit(node.locals)
764 if node.globals is None:
765 self.emit('DUP_TOP')
766 else:
767 self.visit(node.globals)
768 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000769
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000770 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000771 pos = 0
772 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000773 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000774 self.visit(node.node)
775 for arg in node.args:
776 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000777 if isinstance(arg, ast.Keyword):
778 kw = kw + 1
779 else:
780 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000781 if node.star_args is not None:
782 self.visit(node.star_args)
783 if node.dstar_args is not None:
784 self.visit(node.dstar_args)
785 have_star = node.star_args is not None
786 have_dstar = node.dstar_args is not None
787 opcode = callfunc_opcode_info[have_star, have_dstar]
788 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000789
Jeremy Hylton2afff322001-08-27 21:51:52 +0000790 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000791 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000792 if node.dest:
793 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000794 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000795 if node.dest:
796 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000797 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000798 if node.dest:
799 self.emit('ROT_TWO')
800 self.emit('PRINT_ITEM_TO')
801 else:
802 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000803 if node.dest and not newline:
804 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000805
806 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000807 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000808 if node.dest:
809 self.emit('PRINT_NEWLINE_TO')
810 else:
811 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000812
813 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000814 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000815 self.visit(node.value)
816 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000817
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000818 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000819
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000820 def visitSlice(self, node, aug_flag=None):
821 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000822 self.visit(node.expr)
823 slice = 0
824 if node.lower:
825 self.visit(node.lower)
826 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000827 if node.upper:
828 self.visit(node.upper)
829 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000830 if aug_flag:
831 if slice == 0:
832 self.emit('DUP_TOP')
833 elif slice == 3:
834 self.emit('DUP_TOPX', 3)
835 else:
836 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000837 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000838 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000839 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000840 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000841 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000842 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000843 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000844 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000845 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000846
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000847 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000848 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000849 for sub in node.subs:
850 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000851 if aug_flag:
852 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000853 if len(node.subs) > 1:
854 self.emit('BUILD_TUPLE', len(node.subs))
855 if node.flags == 'OP_APPLY':
856 self.emit('BINARY_SUBSCR')
857 elif node.flags == 'OP_ASSIGN':
858 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000859 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000860 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000861
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000862 # binary ops
863
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000864 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000865 self.visit(node.left)
866 self.visit(node.right)
867 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000868
869 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000870 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000871
872 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000873 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000874
875 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000876 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000877
878 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000879 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000880
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000881 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000882 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000883
Jeremy Hylton126960b2000-02-14 21:33:10 +0000884 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000885 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000886
887 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000888 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000889
890 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000891 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000892
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000893 # unary ops
894
895 def unaryOp(self, node, op):
896 self.visit(node.expr)
897 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000898
Jeremy Hylton126960b2000-02-14 21:33:10 +0000899 def visitInvert(self, node):
900 return self.unaryOp(node, 'UNARY_INVERT')
901
Jeremy Hylton40245602000-02-08 21:15:48 +0000902 def visitUnarySub(self, node):
903 return self.unaryOp(node, 'UNARY_NEGATIVE')
904
905 def visitUnaryAdd(self, node):
906 return self.unaryOp(node, 'UNARY_POSITIVE')
907
908 def visitUnaryInvert(self, node):
909 return self.unaryOp(node, 'UNARY_INVERT')
910
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000911 def visitNot(self, node):
912 return self.unaryOp(node, 'UNARY_NOT')
913
Jeremy Hylton40245602000-02-08 21:15:48 +0000914 def visitBackquote(self, node):
915 return self.unaryOp(node, 'UNARY_CONVERT')
916
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000917 # bit ops
918
Jeremy Hyltona5058122000-02-14 14:14:29 +0000919 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000920 self.visit(nodes[0])
921 for node in nodes[1:]:
922 self.visit(node)
923 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000924
925 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000926 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000927
928 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000929 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000930
931 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000932 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000933
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000934 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000935
Jeremy Hyltona5058122000-02-14 14:14:29 +0000936 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000937 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000938
Jeremy Hylton40245602000-02-08 21:15:48 +0000939 def visitTuple(self, node):
940 for elt in node.nodes:
941 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000942 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000943
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000944 def visitList(self, node):
945 for elt in node.nodes:
946 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000947 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000948
949 def visitSliceobj(self, node):
950 for child in node.nodes:
951 self.visit(child)
952 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000953
Jeremy Hyltona5058122000-02-14 14:14:29 +0000954 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000955 lineno = getattr(node, 'lineno', None)
956 if lineno:
957 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000958 self.emit('BUILD_MAP', 0)
959 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000960 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000961 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000962 self.emit('SET_LINENO', lineno2)
963 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000964 self.emit('DUP_TOP')
965 self.visit(v)
966 self.emit('ROT_TWO')
967 self.visit(k)
968 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000969
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000970class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000971 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000972 __super_visitClass = CodeGenerator.visitClass
973 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
974
975 def parseSymbols(self, tree):
976 s = symbols.SymbolVisitor()
977 walk(tree, s)
978 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000979
980 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000981 self.scopes = self.parseSymbols(node)
982 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000983 self.__super_visitModule(node)
984
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000985 def _nameOp(self, prefix, name):
986 scope = self.scope.check_name(name)
987 if scope == SC_LOCAL:
988 if not self.optimized:
989 self.emit(prefix + '_NAME', name)
990 else:
991 self.emit(prefix + '_FAST', name)
992 elif scope == SC_GLOBAL:
993 self.emit(prefix + '_GLOBAL', name)
994 elif scope == SC_FREE or scope == SC_CELL:
995 self.emit(prefix + '_DEREF', name)
996 else:
997 raise RuntimeError, "unsupported scope for var %s: %d" % \
998 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000999
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001000 def _visitFuncOrLambda(self, node, isLambda=0):
1001 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
1002 walk(node.code, gen)
1003 gen.finish()
1004 self.set_lineno(node)
1005 for default in node.defaults:
1006 self.visit(default)
1007 frees = gen.scope.get_free_vars()
1008 if frees:
1009 for name in frees:
1010 self.emit('LOAD_CLOSURE', name)
1011 self.emit('LOAD_CONST', gen)
1012 self.emit('MAKE_CLOSURE', len(node.defaults))
1013 else:
1014 self.emit('LOAD_CONST', gen)
1015 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001016
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001017 def visitClass(self, node):
1018 gen = self.ClassGen(node, self.filename, self.scopes)
1019 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +00001020 self.emit('LOAD_CONST', node.doc)
1021 self.storeName('__doc__')
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001022 walk(node.code, gen)
1023 gen.finish()
1024 self.set_lineno(node)
1025 self.emit('LOAD_CONST', node.name)
1026 for base in node.bases:
1027 self.visit(base)
1028 self.emit('BUILD_TUPLE', len(node.bases))
1029 frees = gen.scope.get_free_vars()
1030 for name in frees:
1031 self.emit('LOAD_CLOSURE', name)
1032 self.emit('LOAD_CONST', gen)
1033 if frees:
1034 self.emit('MAKE_CLOSURE', 0)
1035 else:
1036 self.emit('MAKE_FUNCTION', 0)
1037 self.emit('CALL_FUNCTION', 0)
1038 self.emit('BUILD_CLASS')
1039 self.storeName(node.name)
1040
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001041
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001042class LGBScopeMixin:
1043 """Defines initClass() for Python 2.1-compatible scoping"""
1044 def initClass(self):
1045 self.__class__.NameFinder = LocalNameFinder
1046 self.__class__.FunctionGen = FunctionCodeGenerator
1047 self.__class__.ClassGen = ClassCodeGenerator
1048
1049class NestedScopeMixin:
1050 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1051 def initClass(self):
1052 self.__class__.NameFinder = LocalNameFinder
1053 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1054 self.__class__.ClassGen = NestedClassCodeGenerator
1055
1056class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1057 __super_init = CodeGenerator.__init__
1058
1059 scopes = None
1060
1061 def __init__(self, filename):
1062 self.graph = pyassem.PyFlowGraph("<module>", filename)
1063 self.__super_init(filename)
1064
1065class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1066 NestedScopeCodeGenerator):
1067 __super_init = CodeGenerator.__init__
1068
1069 def __init__(self, filename):
1070 self.graph = pyassem.PyFlowGraph("<module>", filename)
1071 self.__super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001072## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001073
1074class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001075 optimized = 1
1076 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001077
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001078 def __init__(self, func, filename, scopes, isLambda):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001079 if isLambda:
1080 klass = FunctionCodeGenerator
1081 name = "<lambda.%d>" % klass.lambdaCount
1082 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001083 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001084 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001085 args, hasTupleArg = generateArgList(func.argnames)
1086 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001087 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001088 self.isLambda = isLambda
1089 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001090
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001091 if not isLambda and func.doc:
1092 self.setDocstring(func.doc)
1093
Jeremy Hylton2afff322001-08-27 21:51:52 +00001094 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001095 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001096 if func.varargs:
1097 self.graph.setFlag(CO_VARARGS)
1098 if func.kwargs:
1099 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001100 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001101 if hasTupleArg:
1102 self.generateArgUnpack(func.argnames)
1103
1104 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001105 self.graph.startExitBlock()
1106 if not self.isLambda:
1107 self.emit('LOAD_CONST', None)
1108 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001109
1110 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001111 for i in range(len(args)):
1112 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001113 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001114 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001115 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001116
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001117 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001118 if VERSION > 1:
1119 self.emit('UNPACK_SEQUENCE', len(tup))
1120 else:
1121 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001122 for elt in tup:
1123 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001124 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001125 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001126 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001127
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001128 unpackTuple = unpackSequence
1129
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001130class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1131 CodeGenerator):
1132 super_init = CodeGenerator.__init__ # call be other init
1133 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001134
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001135class NestedFunctionCodeGenerator(AbstractFunctionCode,
1136 NestedScopeMixin,
1137 NestedScopeCodeGenerator):
1138 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1139 __super_init = AbstractFunctionCode.__init__
1140
1141 def __init__(self, func, filename, scopes, isLambda):
1142 self.scopes = scopes
1143 self.scope = scopes[func]
1144 self.__super_init(func, filename, scopes, isLambda)
1145 self.graph.setFreeVars(self.scope.get_free_vars())
1146 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001147## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001148
1149class AbstractClassCode:
1150
1151 def __init__(self, klass, filename, scopes):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001152 self.graph = pyassem.PyFlowGraph(klass.name, filename,
1153 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001154 self.super_init(filename)
Jeremy Hylton2afff322001-08-27 21:51:52 +00001155 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001156 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001157 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001158 if klass.doc:
1159 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001160
Jeremy Hylton660cc772001-04-12 06:49:00 +00001161 def _nameOp(self, prefix, name):
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001162 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001163 self.emit(prefix + '_NAME', name)
1164
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001165 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001166 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001167 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001168 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001169
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001170class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1171 super_init = CodeGenerator.__init__
1172 scopes = None
1173
1174class NestedClassCodeGenerator(AbstractClassCode,
1175 NestedScopeMixin,
1176 NestedScopeCodeGenerator):
1177 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1178 __super_init = AbstractClassCode.__init__
1179
1180 def __init__(self, klass, filename, scopes):
1181 self.scopes = scopes
1182 self.scope = scopes[klass]
1183 self.__super_init(klass, filename, scopes)
1184 self.graph.setFreeVars(self.scope.get_free_vars())
1185 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001186## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001187
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001188def generateArgList(arglist):
1189 """Generate an arg list marking TupleArgs"""
1190 args = []
1191 extra = []
1192 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001193 for i in range(len(arglist)):
1194 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001195 if type(elt) == types.StringType:
1196 args.append(elt)
1197 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001198 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001199 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001200 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001201 else:
1202 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001203 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001204
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001205def findOp(node):
1206 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1207 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001208 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001209 return v.op
1210
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001211class OpFinder:
1212 def __init__(self):
1213 self.op = None
1214 def visitAssName(self, node):
1215 if self.op is None:
1216 self.op = node.flags
1217 elif self.op != node.flags:
1218 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001219 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001220
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001221class Delegator:
1222 """Base class to support delegation for augmented assignment nodes
1223
1224 To generator code for augmented assignments, we use the following
1225 wrapper classes. In visitAugAssign, the left-hand expression node
1226 is visited twice. The first time the visit uses the normal method
1227 for that node . The second time the visit uses a different method
1228 that generates the appropriate code to perform the assignment.
1229 These delegator classes wrap the original AST nodes in order to
1230 support the variant visit methods.
1231 """
1232 def __init__(self, obj):
1233 self.obj = obj
1234
1235 def __getattr__(self, attr):
1236 return getattr(self.obj, attr)
1237
1238class AugGetattr(Delegator):
1239 pass
1240
1241class AugName(Delegator):
1242 pass
1243
1244class AugSlice(Delegator):
1245 pass
1246
1247class AugSubscript(Delegator):
1248 pass
1249
1250wrapper = {
1251 ast.Getattr: AugGetattr,
1252 ast.Name: AugName,
1253 ast.Slice: AugSlice,
1254 ast.Subscript: AugSubscript,
1255 }
1256
1257def wrap_aug(node):
1258 return wrapper[node.__class__](node)
1259
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001260if __name__ == "__main__":
1261 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001262
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001263 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001264 compile(file)