blob: c0bbed3f51ac01337e97c9ae085edad16e30a899 [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):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000043 self.filename = filename
44 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 Hylton36cc6a22000-03-16 20:06:59 +000049 root, filename = os.path.split(self.filename)
Jeremy Hylton84ec1f92001-04-11 16:43:13 +000050 if "nested_scopes" in future.find_futures(tree):
Jeremy Hylton364f9b92001-04-12 06:40:42 +000051 gen = NestedScopeModuleCodeGenerator(filename)
Jeremy Hylton84ec1f92001-04-11 16:43:13 +000052 else:
53 gen = ModuleCodeGenerator(filename)
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000054 walk(tree, gen, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000055 if display:
56 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000057 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000058 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000059
60 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000061 f.write(self.getPycHeader())
62 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000063
Jeremy Hylton9c048f92000-10-13 21:58:13 +000064 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000065
66 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000067 # compile.c uses marshal to write a long directly, with
68 # calling the interface that would also generate a 1-byte code
69 # to indicate the type of the value. simplest way to get the
70 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000071 mtime = os.stat(self.filename)[stat.ST_MTIME]
72 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000073 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000074
Jeremy Hylton364f9b92001-04-12 06:40:42 +000075class LocalNameFinder:
76 """Find local names in scope"""
77 def __init__(self, names=()):
78 self.names = misc.Set()
79 self.globals = misc.Set()
80 for name in names:
81 self.names.add(name)
82
83 # XXX list comprehensions and for loops
84
85 def getLocals(self):
86 for elt in self.globals.elements():
87 if self.names.has_elt(elt):
88 self.names.remove(elt)
89 return self.names
90
91 def visitDict(self, node):
92 pass
93
94 def visitGlobal(self, node):
95 for name in node.names:
96 self.globals.add(name)
97
98 def visitFunction(self, node):
99 self.names.add(node.name)
100
101 def visitLambda(self, node):
102 pass
103
104 def visitImport(self, node):
105 for name, alias in node.names:
106 self.names.add(alias or name)
107
108 def visitFrom(self, node):
109 for name, alias in node.names:
110 self.names.add(alias or name)
111
112 def visitClass(self, node):
113 self.names.add(node.name)
114
115 def visitAssName(self, node):
116 self.names.add(node.name)
117
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000118class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000119 """Defines basic code generator for Python bytecode
120
121 This class is an abstract base class. Concrete subclasses must
122 define an __init__() that defines self.graph and then calls the
123 __init__() defined in this class.
124
125 The concrete class must also define the class attributes
126 NameFinder, FunctionGen, and ClassGen. These attributes can be
127 defined in the initClass() method, which is a hook for
128 initializing these methods after all the classes have been
129 defined.
130 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000131
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000132 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000133 __initialized = None
Jeremy Hylton3050d512000-02-12 00:12:38 +0000134
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000135 def __init__(self, filename):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000136 if self.__initialized is None:
137 self.initClass()
138 self.__class__.__initialized = 1
139 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000140 self.filename = filename
141 self.locals = misc.Stack()
142 self.loops = misc.Stack()
143 self.curStack = 0
144 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000145 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000146 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000147
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000148 def initClass(self):
149 """This method is called once for each class"""
150
151 def checkClass(self):
152 """Verify that class is constructed correctly"""
153 try:
154 assert hasattr(self, 'graph')
155 assert getattr(self, 'NameFinder')
156 assert getattr(self, 'FunctionGen')
157 assert getattr(self, 'ClassGen')
158 except AssertionError, msg:
159 intro = "Bad class construction for %s" % self.__class__.__name__
160 raise AssertionError, intro
161
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000162 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000163 self.emit = self.graph.emit
164 self.newBlock = self.graph.newBlock
165 self.startBlock = self.graph.startBlock
166 self.nextBlock = self.graph.nextBlock
167 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000168
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000169 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000170 """Return a code object"""
171 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000172
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000173 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000174
Jeremy Hylton40245602000-02-08 21:15:48 +0000175 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000176 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000177
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000178 def storeName(self, name):
179 self._nameOp('STORE', name)
180
181 def loadName(self, name):
182 self._nameOp('LOAD', name)
183
184 def delName(self, name):
185 self._nameOp('DELETE', name)
186
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000187 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000188 if not self.optimized:
189 self.emit(prefix + '_NAME', name)
190 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000191 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000192 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000193 else:
194 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000195
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000196 def set_lineno(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000197 """Emit SET_LINENO if node has lineno attribute and it is
198 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000199
200 Returns true if SET_LINENO was emitted.
201
202 There are no rules for when an AST node should have a lineno
203 attribute. The transformer and AST code need to be reviewed
204 and a consistent policy implemented and documented. Until
205 then, this method works around missing line numbers.
206 """
207 lineno = getattr(node, 'lineno', None)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000208 if lineno is not None and lineno != self.last_lineno:
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000209 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000210 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000211 return 1
212 return 0
213
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000214 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000215 # code objects. They use class attributes to determine what
216 # specialized code generators to use.
217
218 NameFinder = LocalNameFinder
219 FunctionGen = None
220 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000221
222 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000223 lnf = walk(node.node, self.NameFinder(), 0)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000224 self.locals.push(lnf.getLocals())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000225 if node.doc:
226 self.fixDocstring(node.node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000227 self.visit(node.node)
228 self.emit('LOAD_CONST', None)
229 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000230
231 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000232 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000233 if node.doc:
234 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000235 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236
237 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000238 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000239
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000240 def _visitFuncOrLambda(self, node, isLambda=0):
241 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000242 walk(node.code, gen)
243 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000244 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000245 for default in node.defaults:
246 self.visit(default)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000247 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000248 self.emit('MAKE_FUNCTION', len(node.defaults))
249
250 def visitClass(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000251 gen = self.ClassGen(node, self.filename, self.scopes)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000252 if node.doc:
253 self.fixDocstring(node.code)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000254 walk(node.code, gen)
255 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000256 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000257 self.emit('LOAD_CONST', node.name)
258 for base in node.bases:
259 self.visit(base)
260 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000261 self.emit('LOAD_CONST', gen)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000262 self.emit('MAKE_FUNCTION', 0)
263 self.emit('CALL_FUNCTION', 0)
264 self.emit('BUILD_CLASS')
265 self.storeName(node.name)
266
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000267 def fixDocstring(self, node):
268 """Rewrite the ast for a class with a docstring.
269
270 The AST includes a Discard(Const(docstring)) node. Replace
271 this with an Assign([AssName('__doc__', ...])
272 """
273 assert isinstance(node, ast.Stmt)
274 stmts = node.nodes
275 discard = stmts[0]
276 assert isinstance(discard, ast.Discard)
277 stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
278 discard.expr)
279 stmts[0].lineno = discard.lineno
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000280 # The rest are standard visitor methods
281
282 # The next few implement control-flow statements
283
284 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000285 end = self.newBlock()
286 numtests = len(node.tests)
287 for i in range(numtests):
288 test, suite = node.tests[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000289 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000290 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000291 nextTest = self.newBlock()
292 self.emit('JUMP_IF_FALSE', nextTest)
293 self.nextBlock()
294 self.emit('POP_TOP')
295 self.visit(suite)
296 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000297 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000298 self.emit('POP_TOP')
299 if node.else_:
300 self.visit(node.else_)
301 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000302
303 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000304 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000305
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000306 loop = self.newBlock()
307 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000308
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000309 after = self.newBlock()
310 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000311
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000312 self.nextBlock(loop)
313 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000314
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000315 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000316 self.visit(node.test)
317 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000318
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000319 self.nextBlock()
320 self.emit('POP_TOP')
321 self.visit(node.body)
322 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000323
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000324 self.startBlock(else_) # or just the POPs if not else clause
325 self.emit('POP_TOP')
326 self.emit('POP_BLOCK')
327 if node.else_:
328 self.visit(node.else_)
329 self.loops.pop()
330 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000331
332 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000333 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000334 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000335 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000336 self.loops.push(start)
337
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000338 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000339 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000340 self.visit(node.list)
341 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000342 self.nextBlock(start)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000343 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000344 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000345 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000346 self.visit(node.assign)
347 self.visit(node.body)
348 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000349 self.startBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000350 self.emit('POP_BLOCK')
351 if node.else_:
352 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000353 self.loops.pop()
354 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000355
356 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000357 if not self.loops:
358 raise SyntaxError, "'break' outside loop (%s, %d)" % \
359 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000360 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000361 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000362
363 def visitContinue(self, node):
364 if not self.loops:
365 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000366 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000367 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000368 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000369 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000370 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000371
372 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000373 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000374 for child in node.nodes[:-1]:
375 self.visit(child)
376 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000377 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000378 self.emit('POP_TOP')
379 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000380 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000381
382 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000383 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000384
385 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000386 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000387
388 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000389 self.visit(node.expr)
390 cleanup = self.newBlock()
391 for op, code in node.ops[:-1]:
392 self.visit(code)
393 self.emit('DUP_TOP')
394 self.emit('ROT_THREE')
395 self.emit('COMPARE_OP', op)
396 self.emit('JUMP_IF_FALSE', cleanup)
397 self.nextBlock()
398 self.emit('POP_TOP')
399 # now do the last comparison
400 if node.ops:
401 op, code = node.ops[-1]
402 self.visit(code)
403 self.emit('COMPARE_OP', op)
404 if len(node.ops) > 1:
405 end = self.newBlock()
406 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000407 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000408 self.emit('ROT_TWO')
409 self.emit('POP_TOP')
410 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000411
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000412 # list comprehensions
413 __list_count = 0
414
415 def visitListComp(self, node):
416 # XXX would it be easier to transform the AST into the form it
417 # would have if the list comp were expressed as a series of
418 # for and if stmts and an explicit append?
419 self.set_lineno(node)
420 # setup list
421 append = "$append%d" % self.__list_count
422 self.__list_count = self.__list_count + 1
423 self.emit('BUILD_LIST', 0)
424 self.emit('DUP_TOP')
425 self.emit('LOAD_ATTR', 'append')
426 self.storeName(append)
427 l = len(node.quals)
428 stack = []
429 for i, for_ in zip(range(l), node.quals):
430 start, anchor = self.visit(for_)
431 cont = None
432 for if_ in for_.ifs:
433 if cont is None:
434 cont = self.newBlock()
435 self.visit(if_, cont)
436 stack.insert(0, (start, cont, anchor))
437
438 self.loadName(append)
439 self.visit(node.expr)
440 self.emit('CALL_FUNCTION', 1)
441 self.emit('POP_TOP')
442
443 for start, cont, anchor in stack:
444 if cont:
445 skip_one = self.newBlock()
446 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000447 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000448 self.emit('POP_TOP')
449 self.nextBlock(skip_one)
450 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000451 self.startBlock(anchor)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000452 self.delName(append)
453
454 self.__list_count = self.__list_count - 1
455
456 def visitListCompFor(self, node):
457 self.set_lineno(node)
458 start = self.newBlock()
459 anchor = self.newBlock()
460
461 self.visit(node.list)
462 self.visit(ast.Const(0))
463 self.emit('SET_LINENO', node.lineno)
464 self.nextBlock(start)
465 self.emit('FOR_LOOP', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000466 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000467 self.visit(node.assign)
468 return start, anchor
469
470 def visitListCompIf(self, node, branch):
471 self.set_lineno(node)
472 self.visit(node.test)
473 self.emit('JUMP_IF_FALSE', branch)
474 self.newBlock()
475 self.emit('POP_TOP')
476
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000477 # exception related
478
479 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000480 # XXX would be interesting to implement this via a
481 # transformation of the AST before this stage
482 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000483 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000484 # XXX __debug__ and AssertionError appear to be special cases
485 # -- they are always loaded as globals even if there are local
486 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000487 self.emit('LOAD_GLOBAL', '__debug__')
488 self.emit('JUMP_IF_FALSE', end)
489 self.nextBlock()
490 self.emit('POP_TOP')
491 self.visit(node.test)
492 self.emit('JUMP_IF_TRUE', end)
493 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000494 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000495 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000496 if node.fail:
497 self.visit(node.fail)
498 self.emit('RAISE_VARARGS', 2)
499 else:
500 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000501 self.nextBlock(end)
502 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000503
504 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000505 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000506 n = 0
507 if node.expr1:
508 self.visit(node.expr1)
509 n = n + 1
510 if node.expr2:
511 self.visit(node.expr2)
512 n = n + 1
513 if node.expr3:
514 self.visit(node.expr3)
515 n = n + 1
516 self.emit('RAISE_VARARGS', n)
517
518 def visitTryExcept(self, node):
519 handlers = self.newBlock()
520 end = self.newBlock()
521 if node.else_:
522 lElse = self.newBlock()
523 else:
524 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000525 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000526 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000527 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000528 self.visit(node.body)
529 self.emit('POP_BLOCK')
530 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000531 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000532
533 last = len(node.handlers) - 1
534 for i in range(len(node.handlers)):
535 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000536 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000537 if expr:
538 self.emit('DUP_TOP')
539 self.visit(expr)
540 self.emit('COMPARE_OP', 'exception match')
541 next = self.newBlock()
542 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000543 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000544 self.emit('POP_TOP')
545 self.emit('POP_TOP')
546 if target:
547 self.visit(target)
548 else:
549 self.emit('POP_TOP')
550 self.emit('POP_TOP')
551 self.visit(body)
552 self.emit('JUMP_FORWARD', end)
553 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000554 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000555 else:
556 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000557 self.emit('POP_TOP')
558 self.emit('END_FINALLY')
559 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000560 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000561 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000562 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000563
564 def visitTryFinally(self, node):
565 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000566 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000567 self.emit('SETUP_FINALLY', final)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000568 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000569 self.visit(node.body)
570 self.emit('POP_BLOCK')
571 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000572 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000573 self.visit(node.final)
574 self.emit('END_FINALLY')
575
576 # misc
577
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000578 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000579 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000580 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000581 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000582
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000583 def visitConst(self, node):
584 self.emit('LOAD_CONST', node.value)
585
586 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000587 self.emit('LOAD_CONST', node.name)
588 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000589
590 def visitGlobal(self, node):
591 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000592 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000593
594 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000595 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000596 self.loadName(node.name)
597
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000598 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000599 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000600
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000601 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000602 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000603 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000604 if VERSION > 1:
605 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000606 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000607 mod = string.split(name, ".")[0]
608 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000609
610 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000611 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000612 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000613 if VERSION > 1:
614 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000615 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000616 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000617 if VERSION > 1:
618 if name == '*':
619 self.namespace = 0
620 self.emit('IMPORT_STAR')
621 # There can only be one name w/ from ... import *
622 assert len(node.names) == 1
623 return
624 else:
625 self.emit('IMPORT_FROM', name)
626 self._resolveDots(name)
627 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000628 else:
629 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000630 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000631
Jeremy Hylton20516082000-09-01 20:33:26 +0000632 def _resolveDots(self, name):
633 elts = string.split(name, ".")
634 if len(elts) == 1:
635 return
636 for elt in elts[1:]:
637 self.emit('LOAD_ATTR', elt)
638
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000639 def visitGetattr(self, node):
640 self.visit(node.expr)
641 self.emit('LOAD_ATTR', node.attrname)
642
643 # next five implement assignments
644
645 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000646 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000647 self.visit(node.expr)
648 dups = len(node.nodes) - 1
649 for i in range(len(node.nodes)):
650 elt = node.nodes[i]
651 if i < dups:
652 self.emit('DUP_TOP')
653 if isinstance(elt, ast.Node):
654 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000655
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000656 def visitAssName(self, node):
657 if node.flags == 'OP_ASSIGN':
658 self.storeName(node.name)
659 elif node.flags == 'OP_DELETE':
660 self.delName(node.name)
661 else:
662 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000663
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000664 def visitAssAttr(self, node):
665 self.visit(node.expr)
666 if node.flags == 'OP_ASSIGN':
667 self.emit('STORE_ATTR', node.attrname)
668 elif node.flags == 'OP_DELETE':
669 self.emit('DELETE_ATTR', node.attrname)
670 else:
671 print "warning: unexpected flags:", node.flags
672 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000673
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000674 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000675 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000676 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000677 for child in node.nodes:
678 self.visit(child)
679
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000680 if VERSION > 1:
681 visitAssTuple = _visitAssSequence
682 visitAssList = _visitAssSequence
683 else:
684 def visitAssTuple(self, node):
685 self._visitAssSequence(node, 'UNPACK_TUPLE')
686
687 def visitAssList(self, node):
688 self._visitAssSequence(node, 'UNPACK_LIST')
689
690 # augmented assignment
691
692 def visitAugAssign(self, node):
693 aug_node = wrap_aug(node.node)
694 self.visit(aug_node, "load")
695 self.visit(node.expr)
696 self.emit(self._augmented_opcode[node.op])
697 self.visit(aug_node, "store")
698
699 _augmented_opcode = {
700 '+=' : 'INPLACE_ADD',
701 '-=' : 'INPLACE_SUBTRACT',
702 '*=' : 'INPLACE_MULTIPLY',
703 '/=' : 'INPLACE_DIVIDE',
704 '%=' : 'INPLACE_MODULO',
705 '**=': 'INPLACE_POWER',
706 '>>=': 'INPLACE_RSHIFT',
707 '<<=': 'INPLACE_LSHIFT',
708 '&=' : 'INPLACE_AND',
709 '^=' : 'INPLACE_XOR',
710 '|=' : 'INPLACE_OR',
711 }
712
713 def visitAugName(self, node, mode):
714 if mode == "load":
715 self.loadName(node.name)
716 elif mode == "store":
717 self.storeName(node.name)
718
719 def visitAugGetattr(self, node, mode):
720 if mode == "load":
721 self.visit(node.expr)
722 self.emit('DUP_TOP')
723 self.emit('LOAD_ATTR', node.attrname)
724 elif mode == "store":
725 self.emit('ROT_TWO')
726 self.emit('STORE_ATTR', node.attrname)
727
728 def visitAugSlice(self, node, mode):
729 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000730 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000731 elif mode == "store":
732 slice = 0
733 if node.lower:
734 slice = slice | 1
735 if node.upper:
736 slice = slice | 2
737 if slice == 0:
738 self.emit('ROT_TWO')
739 elif slice == 3:
740 self.emit('ROT_FOUR')
741 else:
742 self.emit('ROT_THREE')
743 self.emit('STORE_SLICE+%d' % slice)
744
745 def visitAugSubscript(self, node, mode):
746 if len(node.subs) > 1:
747 raise SyntaxError, "augmented assignment to tuple is not possible"
748 if mode == "load":
749 self.visitSubscript(node, 1)
750 elif mode == "store":
751 self.emit('ROT_THREE')
752 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000753
754 def visitExec(self, node):
755 self.visit(node.expr)
756 if node.locals is None:
757 self.emit('LOAD_CONST', None)
758 else:
759 self.visit(node.locals)
760 if node.globals is None:
761 self.emit('DUP_TOP')
762 else:
763 self.visit(node.globals)
764 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000765
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000766 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000767 pos = 0
768 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000769 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000770 self.visit(node.node)
771 for arg in node.args:
772 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000773 if isinstance(arg, ast.Keyword):
774 kw = kw + 1
775 else:
776 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000777 if node.star_args is not None:
778 self.visit(node.star_args)
779 if node.dstar_args is not None:
780 self.visit(node.dstar_args)
781 have_star = node.star_args is not None
782 have_dstar = node.dstar_args is not None
783 opcode = callfunc_opcode_info[have_star, have_dstar]
784 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000785
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000786 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000787 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000788 if node.dest:
789 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000790 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000791 if node.dest:
792 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000793 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000794 if node.dest:
795 self.emit('ROT_TWO')
796 self.emit('PRINT_ITEM_TO')
797 else:
798 self.emit('PRINT_ITEM')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000799
800 def visitPrintnl(self, node):
801 self.visitPrint(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000802 if node.dest:
803 self.emit('PRINT_NEWLINE_TO')
804 else:
805 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000806
807 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000808 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000809 self.visit(node.value)
810 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000811
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000812 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000813
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000814 def visitSlice(self, node, aug_flag=None):
815 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000816 self.visit(node.expr)
817 slice = 0
818 if node.lower:
819 self.visit(node.lower)
820 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000821 if node.upper:
822 self.visit(node.upper)
823 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000824 if aug_flag:
825 if slice == 0:
826 self.emit('DUP_TOP')
827 elif slice == 3:
828 self.emit('DUP_TOPX', 3)
829 else:
830 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000831 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000832 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000833 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000834 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000835 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000836 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000837 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000838 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000839 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000840
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000841 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000842 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000843 for sub in node.subs:
844 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000845 if aug_flag:
846 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000847 if len(node.subs) > 1:
848 self.emit('BUILD_TUPLE', len(node.subs))
849 if node.flags == 'OP_APPLY':
850 self.emit('BINARY_SUBSCR')
851 elif node.flags == 'OP_ASSIGN':
852 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000853 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000854 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000855
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000856 # binary ops
857
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000858 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000859 self.visit(node.left)
860 self.visit(node.right)
861 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000862
863 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000864 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000865
866 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000867 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000868
869 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000870 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000871
872 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000873 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000874
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000875 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000876 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000877
Jeremy Hylton126960b2000-02-14 21:33:10 +0000878 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000879 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000880
881 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000882 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000883
884 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000885 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000886
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000887 # unary ops
888
889 def unaryOp(self, node, op):
890 self.visit(node.expr)
891 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000892
Jeremy Hylton126960b2000-02-14 21:33:10 +0000893 def visitInvert(self, node):
894 return self.unaryOp(node, 'UNARY_INVERT')
895
Jeremy Hylton40245602000-02-08 21:15:48 +0000896 def visitUnarySub(self, node):
897 return self.unaryOp(node, 'UNARY_NEGATIVE')
898
899 def visitUnaryAdd(self, node):
900 return self.unaryOp(node, 'UNARY_POSITIVE')
901
902 def visitUnaryInvert(self, node):
903 return self.unaryOp(node, 'UNARY_INVERT')
904
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000905 def visitNot(self, node):
906 return self.unaryOp(node, 'UNARY_NOT')
907
Jeremy Hylton40245602000-02-08 21:15:48 +0000908 def visitBackquote(self, node):
909 return self.unaryOp(node, 'UNARY_CONVERT')
910
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000911 # bit ops
912
Jeremy Hyltona5058122000-02-14 14:14:29 +0000913 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000914 self.visit(nodes[0])
915 for node in nodes[1:]:
916 self.visit(node)
917 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000918
919 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000920 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000921
922 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000923 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000924
925 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000926 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000927
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000928 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000929
Jeremy Hyltona5058122000-02-14 14:14:29 +0000930 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000931 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000932
Jeremy Hylton40245602000-02-08 21:15:48 +0000933 def visitTuple(self, node):
934 for elt in node.nodes:
935 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000936 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000937
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000938 def visitList(self, node):
939 for elt in node.nodes:
940 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000941 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000942
943 def visitSliceobj(self, node):
944 for child in node.nodes:
945 self.visit(child)
946 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000947
Jeremy Hyltona5058122000-02-14 14:14:29 +0000948 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000949 lineno = getattr(node, 'lineno', None)
950 if lineno:
951 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000952 self.emit('BUILD_MAP', 0)
953 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000954 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000955 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000956 self.emit('SET_LINENO', lineno2)
957 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000958 self.emit('DUP_TOP')
959 self.visit(v)
960 self.emit('ROT_TWO')
961 self.visit(k)
962 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000963
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000964class NestedScopeCodeGenerator(CodeGenerator):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000965 __super_visitModule = CodeGenerator.visitModule
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000966 __super_visitClass = CodeGenerator.visitClass
967 __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
968
969 def parseSymbols(self, tree):
970 s = symbols.SymbolVisitor()
971 walk(tree, s)
972 return s.scopes
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000973
974 def visitModule(self, node):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000975 self.scopes = self.parseSymbols(node)
976 self.scope = self.scopes[node]
Jeremy Hylton80e29bd2001-04-09 04:28:48 +0000977 self.__super_visitModule(node)
978
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000979 def _nameOp(self, prefix, name):
980 scope = self.scope.check_name(name)
981 if scope == SC_LOCAL:
982 if not self.optimized:
983 self.emit(prefix + '_NAME', name)
984 else:
985 self.emit(prefix + '_FAST', name)
986 elif scope == SC_GLOBAL:
987 self.emit(prefix + '_GLOBAL', name)
988 elif scope == SC_FREE or scope == SC_CELL:
989 self.emit(prefix + '_DEREF', name)
990 else:
991 raise RuntimeError, "unsupported scope for var %s: %d" % \
992 (name, scope)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000993
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000994 def _visitFuncOrLambda(self, node, isLambda=0):
995 gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
996 walk(node.code, gen)
997 gen.finish()
998 self.set_lineno(node)
999 for default in node.defaults:
1000 self.visit(default)
1001 frees = gen.scope.get_free_vars()
1002 if frees:
1003 for name in frees:
1004 self.emit('LOAD_CLOSURE', name)
1005 self.emit('LOAD_CONST', gen)
1006 self.emit('MAKE_CLOSURE', len(node.defaults))
1007 else:
1008 self.emit('LOAD_CONST', gen)
1009 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton84ec1f92001-04-11 16:43:13 +00001010
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001011 def visitClass(self, node):
1012 gen = self.ClassGen(node, self.filename, self.scopes)
1013 if node.doc:
1014 self.fixDocstring(node.code)
1015 walk(node.code, gen)
1016 gen.finish()
1017 self.set_lineno(node)
1018 self.emit('LOAD_CONST', node.name)
1019 for base in node.bases:
1020 self.visit(base)
1021 self.emit('BUILD_TUPLE', len(node.bases))
1022 frees = gen.scope.get_free_vars()
1023 for name in frees:
1024 self.emit('LOAD_CLOSURE', name)
1025 self.emit('LOAD_CONST', gen)
1026 if frees:
1027 self.emit('MAKE_CLOSURE', 0)
1028 else:
1029 self.emit('MAKE_FUNCTION', 0)
1030 self.emit('CALL_FUNCTION', 0)
1031 self.emit('BUILD_CLASS')
1032 self.storeName(node.name)
1033
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001034
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001035class LGBScopeMixin:
1036 """Defines initClass() for Python 2.1-compatible scoping"""
1037 def initClass(self):
1038 self.__class__.NameFinder = LocalNameFinder
1039 self.__class__.FunctionGen = FunctionCodeGenerator
1040 self.__class__.ClassGen = ClassCodeGenerator
1041
1042class NestedScopeMixin:
1043 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
1044 def initClass(self):
1045 self.__class__.NameFinder = LocalNameFinder
1046 self.__class__.FunctionGen = NestedFunctionCodeGenerator
1047 self.__class__.ClassGen = NestedClassCodeGenerator
1048
1049class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
1050 __super_init = CodeGenerator.__init__
1051
1052 scopes = None
1053
1054 def __init__(self, filename):
1055 self.graph = pyassem.PyFlowGraph("<module>", filename)
1056 self.__super_init(filename)
1057
1058class NestedScopeModuleCodeGenerator(NestedScopeMixin,
1059 NestedScopeCodeGenerator):
1060 __super_init = CodeGenerator.__init__
1061
1062 def __init__(self, filename):
1063 self.graph = pyassem.PyFlowGraph("<module>", filename)
1064 self.__super_init(filename)
1065 self.graph.setFlag(CO_NESTED)
1066
1067class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001068 optimized = 1
1069 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001070
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001071 def __init__(self, func, filename, scopes, isLambda):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001072 if isLambda:
1073 klass = FunctionCodeGenerator
1074 name = "<lambda.%d>" % klass.lambdaCount
1075 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001076 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001077 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001078 args, hasTupleArg = generateArgList(func.argnames)
1079 self.graph = pyassem.PyFlowGraph(name, filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001080 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001081 self.isLambda = isLambda
1082 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001083
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001084 if not isLambda and func.doc:
1085 self.setDocstring(func.doc)
1086
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001087 lnf = walk(func.code, self.NameFinder(args), 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001088 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001089 if func.varargs:
1090 self.graph.setFlag(CO_VARARGS)
1091 if func.kwargs:
1092 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001093 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001094 if hasTupleArg:
1095 self.generateArgUnpack(func.argnames)
1096
1097 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001098 self.graph.startExitBlock()
1099 if not self.isLambda:
1100 self.emit('LOAD_CONST', None)
1101 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001102
1103 def generateArgUnpack(self, args):
1104 count = 0
1105 for arg in args:
1106 if type(arg) == types.TupleType:
1107 self.emit('LOAD_FAST', '.nested%d' % count)
1108 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001109 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001110
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001111 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001112 if VERSION > 1:
1113 self.emit('UNPACK_SEQUENCE', len(tup))
1114 else:
1115 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001116 for elt in tup:
1117 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001118 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001119 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001120 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001121
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001122 unpackTuple = unpackSequence
1123
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001124class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
1125 CodeGenerator):
1126 super_init = CodeGenerator.__init__ # call be other init
1127 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001128
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001129class NestedFunctionCodeGenerator(AbstractFunctionCode,
1130 NestedScopeMixin,
1131 NestedScopeCodeGenerator):
1132 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1133 __super_init = AbstractFunctionCode.__init__
1134
1135 def __init__(self, func, filename, scopes, isLambda):
1136 self.scopes = scopes
1137 self.scope = scopes[func]
1138 self.__super_init(func, filename, scopes, isLambda)
1139 self.graph.setFreeVars(self.scope.get_free_vars())
1140 self.graph.setCellVars(self.scope.get_cell_vars())
1141 self.graph.setFlag(CO_NESTED)
1142
1143class AbstractClassCode:
1144
1145 def __init__(self, klass, filename, scopes):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001146 self.graph = pyassem.PyFlowGraph(klass.name, filename,
1147 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001148 self.super_init(filename)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001149 lnf = walk(klass.code, self.NameFinder(), 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001150 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001151 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001152 if klass.doc:
1153 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001154
Jeremy Hylton660cc772001-04-12 06:49:00 +00001155 def _nameOp(self, prefix, name):
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001156 # Class namespaces are always unoptimized
Jeremy Hylton660cc772001-04-12 06:49:00 +00001157 self.emit(prefix + '_NAME', name)
1158
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001159 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001160 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001161 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001162 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001163
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001164class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
1165 super_init = CodeGenerator.__init__
1166 scopes = None
1167
1168class NestedClassCodeGenerator(AbstractClassCode,
1169 NestedScopeMixin,
1170 NestedScopeCodeGenerator):
1171 super_init = NestedScopeCodeGenerator.__init__ # call be other init
1172 __super_init = AbstractClassCode.__init__
1173
1174 def __init__(self, klass, filename, scopes):
1175 self.scopes = scopes
1176 self.scope = scopes[klass]
1177 self.__super_init(klass, filename, scopes)
1178 self.graph.setFreeVars(self.scope.get_free_vars())
1179 self.graph.setCellVars(self.scope.get_cell_vars())
1180 self.graph.setFlag(CO_NESTED)
1181
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001182def generateArgList(arglist):
1183 """Generate an arg list marking TupleArgs"""
1184 args = []
1185 extra = []
1186 count = 0
1187 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001188 if type(elt) == types.StringType:
1189 args.append(elt)
1190 elif type(elt) == types.TupleType:
1191 args.append(TupleArg(count, elt))
1192 count = count + 1
1193 extra.extend(misc.flatten(elt))
1194 else:
1195 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001196 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001197
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001198def findOp(node):
1199 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1200 v = OpFinder()
1201 walk(node, v, 0)
1202 return v.op
1203
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001204class OpFinder:
1205 def __init__(self):
1206 self.op = None
1207 def visitAssName(self, node):
1208 if self.op is None:
1209 self.op = node.flags
1210 elif self.op != node.flags:
1211 raise ValueError, "mixed ops in stmt"
1212
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001213class Delegator:
1214 """Base class to support delegation for augmented assignment nodes
1215
1216 To generator code for augmented assignments, we use the following
1217 wrapper classes. In visitAugAssign, the left-hand expression node
1218 is visited twice. The first time the visit uses the normal method
1219 for that node . The second time the visit uses a different method
1220 that generates the appropriate code to perform the assignment.
1221 These delegator classes wrap the original AST nodes in order to
1222 support the variant visit methods.
1223 """
1224 def __init__(self, obj):
1225 self.obj = obj
1226
1227 def __getattr__(self, attr):
1228 return getattr(self.obj, attr)
1229
1230class AugGetattr(Delegator):
1231 pass
1232
1233class AugName(Delegator):
1234 pass
1235
1236class AugSlice(Delegator):
1237 pass
1238
1239class AugSubscript(Delegator):
1240 pass
1241
1242wrapper = {
1243 ast.Getattr: AugGetattr,
1244 ast.Name: AugName,
1245 ast.Slice: AugSlice,
1246 ast.Subscript: AugSubscript,
1247 }
1248
1249def wrap_aug(node):
1250 return wrapper[node.__class__](node)
1251
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001252if __name__ == "__main__":
1253 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001254
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001255 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001256 compile(file)