blob: 04c115a7c3448f19cbbe54ea540b9cdb48a447bf [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
Jeremy Hylton37c93512001-09-17 18:03:55 +000011from compiler import ast, parse, walk, syntax
Jeremy Hylton364f9b92001-04-12 06:40:42 +000012from compiler import pyassem, misc, future, symbols
13from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
Jeremy Hylton71ebc332001-08-30 20:25:55 +000014from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
Jeremy Hylton1e99a772001-09-14 22:49:08 +000015 CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
Jeremy Hylton71ebc332001-08-30 20:25:55 +000016from compiler.pyassem import TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000017
Jeremy Hylton9c048f92000-10-13 21:58:13 +000018# Do we have Python 1.x or Python 2.x?
19try:
20 VERSION = sys.version_info[0]
21except AttributeError:
22 VERSION = 1
23
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000024callfunc_opcode_info = {
25 # (Have *args, Have **args) : opcode
26 (0,0) : "CALL_FUNCTION",
27 (1,0) : "CALL_FUNCTION_VAR",
28 (0,1) : "CALL_FUNCTION_KW",
29 (1,1) : "CALL_FUNCTION_VAR_KW",
30}
31
Jeremy Hyltone4685ec2001-08-29 22:30:09 +000032LOOP = 1
33EXCEPT = 2
34TRY_FINALLY = 3
35END_FINALLY = 4
36
Jeremy Hylton1e99a772001-09-14 22:49:08 +000037class BlockStack(misc.Stack):
38 __super_init = misc.Stack.__init__
39
40 def __init__(self):
41 self.__super_init(self)
42 self.loop = None
43
Jeremy Hylton9c048f92000-10-13 21:58:13 +000044def compile(filename, display=0):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000045 f = open(filename)
46 buf = f.read()
47 f.close()
48 mod = Module(buf, filename)
Jeremy Hylton37c93512001-09-17 18:03:55 +000049 try:
50 mod.compile(display)
51 except SyntaxError, err:
52 print "SyntaxError:", err
53 else:
54 f = open(filename + "c", "wb")
55 mod.dump(f)
56 f.close()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000057
58class Module:
59 def __init__(self, source, filename):
Jeremy Hylton2afff322001-08-27 21:51:52 +000060 self.filename = os.path.abspath(filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000061 self.source = source
62 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000063
Jeremy Hylton9c048f92000-10-13 21:58:13 +000064 def compile(self, display=0):
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000065 tree = parse(self.source)
Jeremy Hylton37c93512001-09-17 18:03:55 +000066 misc.set_filename(self.filename, tree)
67 syntax.check(tree)
68 gen = ModuleCodeGenerator(tree)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000069 if display:
70 import pprint
Jeremy Hylton80e29bd2001-04-09 04:28:48 +000071 print pprint.pprint(tree)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000072 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000073
74 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000075 f.write(self.getPycHeader())
76 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000077
Jeremy Hylton9c048f92000-10-13 21:58:13 +000078 MAGIC = imp.get_magic()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000079
80 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000081 # compile.c uses marshal to write a long directly, with
82 # calling the interface that would also generate a 1-byte code
83 # to indicate the type of the value. simplest way to get the
84 # same effect is to call marshal and then skip the code.
Thomas Wouters46cc7c02000-08-12 20:32:46 +000085 mtime = os.stat(self.filename)[stat.ST_MTIME]
86 mtime = struct.pack('i', mtime)
Jeremy Hylton9c048f92000-10-13 21:58:13 +000087 return self.MAGIC + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000088
Jeremy Hylton364f9b92001-04-12 06:40:42 +000089class LocalNameFinder:
90 """Find local names in scope"""
91 def __init__(self, names=()):
92 self.names = misc.Set()
93 self.globals = misc.Set()
94 for name in names:
95 self.names.add(name)
96
97 # XXX list comprehensions and for loops
98
99 def getLocals(self):
100 for elt in self.globals.elements():
101 if self.names.has_elt(elt):
102 self.names.remove(elt)
103 return self.names
104
105 def visitDict(self, node):
106 pass
107
108 def visitGlobal(self, node):
109 for name in node.names:
110 self.globals.add(name)
111
112 def visitFunction(self, node):
113 self.names.add(node.name)
114
115 def visitLambda(self, node):
116 pass
117
118 def visitImport(self, node):
119 for name, alias in node.names:
120 self.names.add(alias or name)
121
122 def visitFrom(self, node):
123 for name, alias in node.names:
124 self.names.add(alias or name)
125
126 def visitClass(self, node):
127 self.names.add(node.name)
128
129 def visitAssName(self, node):
130 self.names.add(node.name)
131
Jeremy Hylton2afff322001-08-27 21:51:52 +0000132def is_constant_false(node):
133 if isinstance(node, ast.Const):
134 if not node.value:
135 return 1
136 return 0
137
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000138class CodeGenerator:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000139 """Defines basic code generator for Python bytecode
140
141 This class is an abstract base class. Concrete subclasses must
142 define an __init__() that defines self.graph and then calls the
143 __init__() defined in this class.
144
145 The concrete class must also define the class attributes
146 NameFinder, FunctionGen, and ClassGen. These attributes can be
147 defined in the initClass() method, which is a hook for
148 initializing these methods after all the classes have been
149 defined.
150 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000151
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000152 optimized = 0 # is namespace access optimized?
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000153 __initialized = None
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000154 class_name = None # provide default for instance variable
Jeremy Hylton3050d512000-02-12 00:12:38 +0000155
Jeremy Hylton37c93512001-09-17 18:03:55 +0000156 def __init__(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000157 if self.__initialized is None:
158 self.initClass()
159 self.__class__.__initialized = 1
160 self.checkClass()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000161 self.locals = misc.Stack()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000162 self.setups = misc.Stack()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000163 self.curStack = 0
164 self.maxStack = 0
Jeremy Hylton92f39722000-09-01 20:47:37 +0000165 self.last_lineno = None
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000166 self._setupGraphDelegation()
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000167 self._div_op = "BINARY_DIVIDE"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000168
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000169 # XXX set flags based on future features
170 futures = self.get_module().futures
171 for feature in futures:
172 if feature == "division":
173 self.graph.setFlag(CO_FUTURE_DIVISION)
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000174 self._div_op = "BINARY_TRUE_DIVIDE"
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000175 elif feature == "generators":
176 self.graph.setFlag(CO_GENERATOR_ALLOWED)
177
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000178 def initClass(self):
179 """This method is called once for each class"""
180
181 def checkClass(self):
182 """Verify that class is constructed correctly"""
183 try:
184 assert hasattr(self, 'graph')
185 assert getattr(self, 'NameFinder')
186 assert getattr(self, 'FunctionGen')
187 assert getattr(self, 'ClassGen')
188 except AssertionError, msg:
189 intro = "Bad class construction for %s" % self.__class__.__name__
190 raise AssertionError, intro
191
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000192 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000193 self.emit = self.graph.emit
194 self.newBlock = self.graph.newBlock
195 self.startBlock = self.graph.startBlock
196 self.nextBlock = self.graph.nextBlock
197 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +0000198
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000199 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000200 """Return a code object"""
201 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000202
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000203 def mangle(self, name):
204 if self.class_name is not None:
205 return misc.mangle(name, self.class_name)
206 else:
207 return name
208
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000209 def parseSymbols(self, tree):
210 s = symbols.SymbolVisitor()
211 walk(tree, s)
212 return s.scopes
213
214 def get_module(self):
215 raise RuntimeError, "should be implemented by subclasses"
216
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000217 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +0000218
Jeremy Hylton40245602000-02-08 21:15:48 +0000219 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000220 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000221
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000222 def storeName(self, name):
223 self._nameOp('STORE', name)
224
225 def loadName(self, name):
226 self._nameOp('LOAD', name)
227
228 def delName(self, name):
229 self._nameOp('DELETE', name)
230
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000231 def _nameOp(self, prefix, name):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000232 name = self.mangle(name)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000233 scope = self.scope.check_name(name)
234 if scope == SC_LOCAL:
235 if not self.optimized:
236 self.emit(prefix + '_NAME', name)
237 else:
238 self.emit(prefix + '_FAST', name)
239 elif scope == SC_GLOBAL:
240 if not self.optimized:
241 self.emit(prefix + '_NAME', name)
242 else:
243 self.emit(prefix + '_GLOBAL', name)
244 elif scope == SC_FREE or scope == SC_CELL:
245 self.emit(prefix + '_DEREF', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000246 else:
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000247 raise RuntimeError, "unsupported scope for var %s: %d" % \
248 (name, scope)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000249
Jeremy Hylton13d70942001-04-12 21:04:43 +0000250 def _implicitNameOp(self, prefix, name):
251 """Emit name ops for names generated implicitly by for loops
252
253 The interpreter generates names that start with a period or
254 dollar sign. The symbol table ignores these names because
255 they aren't present in the program text.
256 """
257 if self.optimized:
258 self.emit(prefix + '_FAST', name)
259 else:
260 self.emit(prefix + '_NAME', name)
261
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000262 def set_lineno(self, node, force=0):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000263 """Emit SET_LINENO if node has lineno attribute and it is
264 different than the last lineno emitted.
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000265
266 Returns true if SET_LINENO was emitted.
267
268 There are no rules for when an AST node should have a lineno
269 attribute. The transformer and AST code need to be reviewed
270 and a consistent policy implemented and documented. Until
271 then, this method works around missing line numbers.
272 """
273 lineno = getattr(node, 'lineno', None)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000274 if lineno is not None and (lineno != self.last_lineno
275 or force):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000276 self.emit('SET_LINENO', lineno)
Jeremy Hylton92f39722000-09-01 20:47:37 +0000277 self.last_lineno = lineno
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000278 return 1
279 return 0
280
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000281 # The first few visitor methods handle nodes that generator new
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000282 # code objects. They use class attributes to determine what
283 # specialized code generators to use.
284
285 NameFinder = LocalNameFinder
286 FunctionGen = None
287 ClassGen = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000288
289 def visitModule(self, node):
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000290 self.scopes = self.parseSymbols(node)
291 self.scope = self.scopes[node]
Jeremy Hylton13d70942001-04-12 21:04:43 +0000292 self.emit('SET_LINENO', 0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000293 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000294 self.emit('LOAD_CONST', node.doc)
295 self.storeName('__doc__')
296 lnf = walk(node.node, self.NameFinder(), verbose=0)
297 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000298 self.visit(node.node)
299 self.emit('LOAD_CONST', None)
300 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000301
302 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000303 self._visitFuncOrLambda(node, isLambda=0)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000304 if node.doc:
305 self.setDocstring(node.doc)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000306 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000307
308 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000309 self._visitFuncOrLambda(node, isLambda=1)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000310
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000311 def _visitFuncOrLambda(self, node, isLambda=0):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000312 gen = self.FunctionGen(node, self.scopes, isLambda,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000313 self.class_name, self.get_module())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000314 walk(node.code, gen)
315 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000316 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000317 for default in node.defaults:
318 self.visit(default)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000319 frees = gen.scope.get_free_vars()
320 if frees:
321 for name in frees:
322 self.emit('LOAD_CLOSURE', name)
323 self.emit('LOAD_CONST', gen)
324 self.emit('MAKE_CLOSURE', len(node.defaults))
325 else:
326 self.emit('LOAD_CONST', gen)
327 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000328
329 def visitClass(self, node):
Jeremy Hylton37c93512001-09-17 18:03:55 +0000330 gen = self.ClassGen(node, self.scopes,
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000331 self.get_module())
Jeremy Hylton9ab019b2001-04-11 16:24:30 +0000332 if node.doc:
Jeremy Hylton2afff322001-08-27 21:51:52 +0000333 self.emit('LOAD_CONST', node.doc)
334 self.storeName('__doc__')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000335 walk(node.code, gen)
336 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000337 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000338 self.emit('LOAD_CONST', node.name)
339 for base in node.bases:
340 self.visit(base)
341 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000342 frees = gen.scope.get_free_vars()
343 for name in frees:
344 self.emit('LOAD_CLOSURE', name)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000345 self.emit('LOAD_CONST', gen)
Jeremy Hylton1e99a772001-09-14 22:49:08 +0000346 if frees:
347 self.emit('MAKE_CLOSURE', 0)
348 else:
349 self.emit('MAKE_FUNCTION', 0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000350 self.emit('CALL_FUNCTION', 0)
351 self.emit('BUILD_CLASS')
352 self.storeName(node.name)
353
354 # The rest are standard visitor methods
355
356 # The next few implement control-flow statements
357
358 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000359 end = self.newBlock()
360 numtests = len(node.tests)
361 for i in range(numtests):
362 test, suite = node.tests[i]
Jeremy Hylton2afff322001-08-27 21:51:52 +0000363 if is_constant_false(test):
364 # XXX will need to check generator stuff here
365 continue
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000366 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000367 self.visit(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000368 nextTest = self.newBlock()
369 self.emit('JUMP_IF_FALSE', nextTest)
370 self.nextBlock()
371 self.emit('POP_TOP')
372 self.visit(suite)
373 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000374 self.startBlock(nextTest)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000375 self.emit('POP_TOP')
376 if node.else_:
377 self.visit(node.else_)
378 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000379
380 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000381 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000382
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000383 loop = self.newBlock()
384 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000385
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000386 after = self.newBlock()
387 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000388
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000389 self.nextBlock(loop)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000390 self.setups.push((LOOP, loop))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000391
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000392 self.set_lineno(node, force=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000393 self.visit(node.test)
394 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000395
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000396 self.nextBlock()
397 self.emit('POP_TOP')
398 self.visit(node.body)
399 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000400
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000401 self.startBlock(else_) # or just the POPs if not else clause
402 self.emit('POP_TOP')
403 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000404 self.setups.pop()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000405 if node.else_:
406 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000407 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000408
409 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000410 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000411 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000412 after = self.newBlock()
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000413 self.setups.push((LOOP, start))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000414
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000415 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000416 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000417 self.visit(node.list)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000418 self.emit('GET_ITER')
419
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000420 self.nextBlock(start)
Jeremy Hyltonbb0bae62001-04-12 21:54:41 +0000421 self.set_lineno(node, force=1)
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000422 self.emit('FOR_ITER', anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000423 self.visit(node.assign)
424 self.visit(node.body)
425 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton2ac9c3e2001-08-28 17:28:33 +0000426 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000427 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000428 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000429 if node.else_:
430 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000431 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000432
433 def visitBreak(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000434 if not self.setups:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000435 raise SyntaxError, "'break' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000436 (node.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000437 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000438 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000439
440 def visitContinue(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000441 if not self.setups:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000442 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000443 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000444 kind, block = self.setups.top()
445 if kind == LOOP:
446 self.set_lineno(node)
447 self.emit('JUMP_ABSOLUTE', block)
448 self.nextBlock()
449 elif kind == EXCEPT or kind == TRY_FINALLY:
450 self.set_lineno(node)
451 # find the block that starts the loop
452 top = len(self.setups)
453 while top > 0:
454 top = top - 1
455 kind, loop_block = self.setups[top]
456 if kind == LOOP:
457 break
458 if kind != LOOP:
459 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Jeremy Hylton37c93512001-09-17 18:03:55 +0000460 (node.filename, node.lineno)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000461 self.emit('CONTINUE_LOOP', loop_block)
462 self.nextBlock()
463 elif kind == END_FINALLY:
464 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
Jeremy Hylton37c93512001-09-17 18:03:55 +0000465 raise SyntaxError, msg % (node.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000466
467 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000468 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000469 for child in node.nodes[:-1]:
470 self.visit(child)
471 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000472 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000473 self.emit('POP_TOP')
474 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000475 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000476
477 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000478 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000479
480 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000481 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000482
483 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000484 self.visit(node.expr)
485 cleanup = self.newBlock()
486 for op, code in node.ops[:-1]:
487 self.visit(code)
488 self.emit('DUP_TOP')
489 self.emit('ROT_THREE')
490 self.emit('COMPARE_OP', op)
491 self.emit('JUMP_IF_FALSE', cleanup)
492 self.nextBlock()
493 self.emit('POP_TOP')
494 # now do the last comparison
495 if node.ops:
496 op, code = node.ops[-1]
497 self.visit(code)
498 self.emit('COMPARE_OP', op)
499 if len(node.ops) > 1:
500 end = self.newBlock()
501 self.emit('JUMP_FORWARD', end)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000502 self.startBlock(cleanup)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000503 self.emit('ROT_TWO')
504 self.emit('POP_TOP')
505 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000506
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000507 # list comprehensions
508 __list_count = 0
509
510 def visitListComp(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000511 self.set_lineno(node)
512 # setup list
513 append = "$append%d" % self.__list_count
514 self.__list_count = self.__list_count + 1
515 self.emit('BUILD_LIST', 0)
516 self.emit('DUP_TOP')
517 self.emit('LOAD_ATTR', 'append')
Jeremy Hylton13d70942001-04-12 21:04:43 +0000518 self._implicitNameOp('STORE', append)
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000519
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000520 stack = []
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000521 for i, for_ in zip(range(len(node.quals)), node.quals):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000522 start, anchor = self.visit(for_)
523 cont = None
524 for if_ in for_.ifs:
525 if cont is None:
526 cont = self.newBlock()
527 self.visit(if_, cont)
528 stack.insert(0, (start, cont, anchor))
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000529
Jeremy Hylton13d70942001-04-12 21:04:43 +0000530 self._implicitNameOp('LOAD', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000531 self.visit(node.expr)
532 self.emit('CALL_FUNCTION', 1)
533 self.emit('POP_TOP')
534
535 for start, cont, anchor in stack:
536 if cont:
537 skip_one = self.newBlock()
538 self.emit('JUMP_FORWARD', skip_one)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000539 self.startBlock(cont)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000540 self.emit('POP_TOP')
541 self.nextBlock(skip_one)
542 self.emit('JUMP_ABSOLUTE', start)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000543 self.startBlock(anchor)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000544 self._implicitNameOp('DELETE', append)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000545
546 self.__list_count = self.__list_count - 1
547
548 def visitListCompFor(self, node):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000549 start = self.newBlock()
550 anchor = self.newBlock()
551
552 self.visit(node.list)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000553 self.emit('GET_ITER')
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000554 self.nextBlock(start)
Jeremy Hylton13d70942001-04-12 21:04:43 +0000555 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton71ebc332001-08-30 20:25:55 +0000556 self.emit('FOR_ITER', anchor)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000557 self.nextBlock()
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000558 self.visit(node.assign)
559 return start, anchor
560
561 def visitListCompIf(self, node, branch):
Jeremy Hylton542b11a2001-04-12 20:21:39 +0000562 self.set_lineno(node, force=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000563 self.visit(node.test)
564 self.emit('JUMP_IF_FALSE', branch)
565 self.newBlock()
566 self.emit('POP_TOP')
567
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000568 # exception related
569
570 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000571 # XXX would be interesting to implement this via a
572 # transformation of the AST before this stage
573 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000574 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000575 # XXX __debug__ and AssertionError appear to be special cases
576 # -- they are always loaded as globals even if there are local
577 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000578 self.emit('LOAD_GLOBAL', '__debug__')
579 self.emit('JUMP_IF_FALSE', end)
580 self.nextBlock()
581 self.emit('POP_TOP')
582 self.visit(node.test)
583 self.emit('JUMP_IF_TRUE', end)
584 self.nextBlock()
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000585 self.emit('POP_TOP')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000586 self.emit('LOAD_GLOBAL', 'AssertionError')
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000587 if node.fail:
588 self.visit(node.fail)
589 self.emit('RAISE_VARARGS', 2)
590 else:
591 self.emit('RAISE_VARARGS', 1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000592 self.nextBlock(end)
593 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000594
595 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000596 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000597 n = 0
598 if node.expr1:
599 self.visit(node.expr1)
600 n = n + 1
601 if node.expr2:
602 self.visit(node.expr2)
603 n = n + 1
604 if node.expr3:
605 self.visit(node.expr3)
606 n = n + 1
607 self.emit('RAISE_VARARGS', n)
608
609 def visitTryExcept(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000610 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000611 handlers = self.newBlock()
612 end = self.newBlock()
613 if node.else_:
614 lElse = self.newBlock()
615 else:
616 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000617 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000618 self.emit('SETUP_EXCEPT', handlers)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000619 self.nextBlock(body)
620 self.setups.push((EXCEPT, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000621 self.visit(node.body)
622 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000623 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000624 self.emit('JUMP_FORWARD', lElse)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000625 self.startBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000626
627 last = len(node.handlers) - 1
628 for i in range(len(node.handlers)):
629 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000630 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000631 if expr:
632 self.emit('DUP_TOP')
633 self.visit(expr)
634 self.emit('COMPARE_OP', 'exception match')
635 next = self.newBlock()
636 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000637 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000638 self.emit('POP_TOP')
639 self.emit('POP_TOP')
640 if target:
641 self.visit(target)
642 else:
643 self.emit('POP_TOP')
644 self.emit('POP_TOP')
645 self.visit(body)
646 self.emit('JUMP_FORWARD', end)
647 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000648 self.nextBlock(next)
Jeremy Hylton314e3fb2000-11-06 03:43:11 +0000649 else:
650 self.nextBlock()
Jeremy Hyltonf3545752001-08-28 16:35:18 +0000651 if expr: # XXX
652 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000653 self.emit('END_FINALLY')
654 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000655 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000656 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000657 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000658
659 def visitTryFinally(self, node):
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000660 body = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000661 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000662 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000663 self.emit('SETUP_FINALLY', final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000664 self.nextBlock(body)
665 self.setups.push((TRY_FINALLY, body))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000666 self.visit(node.body)
667 self.emit('POP_BLOCK')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000668 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000669 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000670 self.nextBlock(final)
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000671 self.setups.push((END_FINALLY, final))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000672 self.visit(node.final)
673 self.emit('END_FINALLY')
Jeremy Hyltone4685ec2001-08-29 22:30:09 +0000674 self.setups.pop()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000675
676 # misc
677
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000678 def visitDiscard(self, node):
Jeremy Hylton01d12932001-04-11 16:36:25 +0000679 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000680 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000681 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000682
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000683 def visitConst(self, node):
684 self.emit('LOAD_CONST', node.value)
685
686 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000687 self.emit('LOAD_CONST', node.name)
688 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000689
690 def visitGlobal(self, node):
691 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000692 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000693
694 def visitName(self, node):
Jeremy Hylton92f39722000-09-01 20:47:37 +0000695 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000696 self.loadName(node.name)
697
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000698 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000699 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000700
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000701 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000702 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000703 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000704 if VERSION > 1:
705 self.emit('LOAD_CONST', None)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000706 self.emit('IMPORT_NAME', name)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000707 mod = string.split(name, ".")[0]
708 self.storeName(alias or mod)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000709
710 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000711 self.set_lineno(node)
Jeremy Hylton20516082000-09-01 20:33:26 +0000712 fromlist = map(lambda (name, alias): name, node.names)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000713 if VERSION > 1:
714 self.emit('LOAD_CONST', tuple(fromlist))
Jeremy Hyltona5058122000-02-14 14:14:29 +0000715 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton20516082000-09-01 20:33:26 +0000716 for name, alias in node.names:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000717 if VERSION > 1:
718 if name == '*':
719 self.namespace = 0
720 self.emit('IMPORT_STAR')
721 # There can only be one name w/ from ... import *
722 assert len(node.names) == 1
723 return
724 else:
725 self.emit('IMPORT_FROM', name)
726 self._resolveDots(name)
727 self.storeName(alias or name)
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000728 else:
729 self.emit('IMPORT_FROM', name)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000730 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000731
Jeremy Hylton20516082000-09-01 20:33:26 +0000732 def _resolveDots(self, name):
733 elts = string.split(name, ".")
734 if len(elts) == 1:
735 return
736 for elt in elts[1:]:
737 self.emit('LOAD_ATTR', elt)
738
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000739 def visitGetattr(self, node):
740 self.visit(node.expr)
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000741 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000742
743 # next five implement assignments
744
745 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000746 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000747 self.visit(node.expr)
748 dups = len(node.nodes) - 1
749 for i in range(len(node.nodes)):
750 elt = node.nodes[i]
751 if i < dups:
752 self.emit('DUP_TOP')
753 if isinstance(elt, ast.Node):
754 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000755
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000756 def visitAssName(self, node):
757 if node.flags == 'OP_ASSIGN':
758 self.storeName(node.name)
759 elif node.flags == 'OP_DELETE':
Jeremy Hylton94afe322001-08-29 18:14:39 +0000760 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000761 self.delName(node.name)
762 else:
763 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000764
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000765 def visitAssAttr(self, node):
766 self.visit(node.expr)
767 if node.flags == 'OP_ASSIGN':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000768 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000769 elif node.flags == 'OP_DELETE':
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000770 self.emit('DELETE_ATTR', self.mangle(node.attrname))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000771 else:
772 print "warning: unexpected flags:", node.flags
773 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000774
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000775 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000776 if findOp(node) != 'OP_DELETE':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000777 self.emit(op, len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000778 for child in node.nodes:
779 self.visit(child)
780
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000781 if VERSION > 1:
782 visitAssTuple = _visitAssSequence
783 visitAssList = _visitAssSequence
784 else:
785 def visitAssTuple(self, node):
786 self._visitAssSequence(node, 'UNPACK_TUPLE')
787
788 def visitAssList(self, node):
789 self._visitAssSequence(node, 'UNPACK_LIST')
790
791 # augmented assignment
792
793 def visitAugAssign(self, node):
Jeremy Hylton80ea40d2001-08-27 21:58:09 +0000794 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000795 aug_node = wrap_aug(node.node)
796 self.visit(aug_node, "load")
797 self.visit(node.expr)
798 self.emit(self._augmented_opcode[node.op])
799 self.visit(aug_node, "store")
800
801 _augmented_opcode = {
802 '+=' : 'INPLACE_ADD',
803 '-=' : 'INPLACE_SUBTRACT',
804 '*=' : 'INPLACE_MULTIPLY',
805 '/=' : 'INPLACE_DIVIDE',
Jeremy Hylton94afe322001-08-29 18:14:39 +0000806 '//=': 'INPLACE_FLOOR_DIVIDE',
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000807 '%=' : 'INPLACE_MODULO',
808 '**=': 'INPLACE_POWER',
809 '>>=': 'INPLACE_RSHIFT',
810 '<<=': 'INPLACE_LSHIFT',
811 '&=' : 'INPLACE_AND',
812 '^=' : 'INPLACE_XOR',
813 '|=' : 'INPLACE_OR',
814 }
815
816 def visitAugName(self, node, mode):
817 if mode == "load":
818 self.loadName(node.name)
819 elif mode == "store":
820 self.storeName(node.name)
821
822 def visitAugGetattr(self, node, mode):
823 if mode == "load":
824 self.visit(node.expr)
825 self.emit('DUP_TOP')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000826 self.emit('LOAD_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000827 elif mode == "store":
828 self.emit('ROT_TWO')
Jeremy Hyltonc59e2202001-08-27 22:56:16 +0000829 self.emit('STORE_ATTR', self.mangle(node.attrname))
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000830
831 def visitAugSlice(self, node, mode):
832 if mode == "load":
Jeremy Hylton84ec1f92001-04-11 16:43:13 +0000833 self.visitSlice(node, 1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000834 elif mode == "store":
835 slice = 0
836 if node.lower:
837 slice = slice | 1
838 if node.upper:
839 slice = slice | 2
840 if slice == 0:
841 self.emit('ROT_TWO')
842 elif slice == 3:
843 self.emit('ROT_FOUR')
844 else:
845 self.emit('ROT_THREE')
846 self.emit('STORE_SLICE+%d' % slice)
847
848 def visitAugSubscript(self, node, mode):
849 if len(node.subs) > 1:
850 raise SyntaxError, "augmented assignment to tuple is not possible"
851 if mode == "load":
852 self.visitSubscript(node, 1)
853 elif mode == "store":
854 self.emit('ROT_THREE')
855 self.emit('STORE_SUBSCR')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000856
857 def visitExec(self, node):
858 self.visit(node.expr)
859 if node.locals is None:
860 self.emit('LOAD_CONST', None)
861 else:
862 self.visit(node.locals)
863 if node.globals is None:
864 self.emit('DUP_TOP')
865 else:
866 self.visit(node.globals)
867 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000868
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000869 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000870 pos = 0
871 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000872 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000873 self.visit(node.node)
874 for arg in node.args:
875 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000876 if isinstance(arg, ast.Keyword):
877 kw = kw + 1
878 else:
879 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000880 if node.star_args is not None:
881 self.visit(node.star_args)
882 if node.dstar_args is not None:
883 self.visit(node.dstar_args)
884 have_star = node.star_args is not None
885 have_dstar = node.dstar_args is not None
886 opcode = callfunc_opcode_info[have_star, have_dstar]
887 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000888
Jeremy Hylton2afff322001-08-27 21:51:52 +0000889 def visitPrint(self, node, newline=0):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000890 self.set_lineno(node)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000891 if node.dest:
892 self.visit(node.dest)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000893 for child in node.nodes:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000894 if node.dest:
895 self.emit('DUP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000896 self.visit(child)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000897 if node.dest:
898 self.emit('ROT_TWO')
899 self.emit('PRINT_ITEM_TO')
900 else:
901 self.emit('PRINT_ITEM')
Jeremy Hylton2afff322001-08-27 21:51:52 +0000902 if node.dest and not newline:
903 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000904
905 def visitPrintnl(self, node):
Jeremy Hylton2afff322001-08-27 21:51:52 +0000906 self.visitPrint(node, newline=1)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000907 if node.dest:
908 self.emit('PRINT_NEWLINE_TO')
909 else:
910 self.emit('PRINT_NEWLINE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000911
912 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000913 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000914 self.visit(node.value)
915 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000916
Jeremy Hylton1048aa92001-09-14 23:17:55 +0000917 def visitYield(self, node):
918 self.set_lineno(node)
919 self.visit(node.value)
920 self.emit('YIELD_STMT')
921
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000922 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000923
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000924 def visitSlice(self, node, aug_flag=None):
925 # aug_flag is used by visitAugSlice
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000926 self.visit(node.expr)
927 slice = 0
928 if node.lower:
929 self.visit(node.lower)
930 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000931 if node.upper:
932 self.visit(node.upper)
933 slice = slice | 2
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000934 if aug_flag:
935 if slice == 0:
936 self.emit('DUP_TOP')
937 elif slice == 3:
938 self.emit('DUP_TOPX', 3)
939 else:
940 self.emit('DUP_TOPX', 2)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000941 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000942 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000943 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000944 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000945 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000946 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000947 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000948 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000949 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000950
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000951 def visitSubscript(self, node, aug_flag=None):
Jeremy Hylton40245602000-02-08 21:15:48 +0000952 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000953 for sub in node.subs:
954 self.visit(sub)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000955 if aug_flag:
956 self.emit('DUP_TOPX', 2)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000957 if len(node.subs) > 1:
958 self.emit('BUILD_TUPLE', len(node.subs))
959 if node.flags == 'OP_APPLY':
960 self.emit('BINARY_SUBSCR')
961 elif node.flags == 'OP_ASSIGN':
962 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000963 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000964 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000965
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000966 # binary ops
967
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000968 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000969 self.visit(node.left)
970 self.visit(node.right)
971 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000972
973 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000974 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000975
976 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000977 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000978
979 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000980 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000981
982 def visitDiv(self, node):
Jeremy Hyltonaee0bfe2001-09-17 16:41:02 +0000983 return self.binaryOp(node, self._div_op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000984
Jeremy Hylton94afe322001-08-29 18:14:39 +0000985 def visitFloorDiv(self, node):
986 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
987
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000988 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000989 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000990
Jeremy Hylton126960b2000-02-14 21:33:10 +0000991 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000992 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000993
994 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000995 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000996
997 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000998 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000999
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001000 # unary ops
1001
1002 def unaryOp(self, node, op):
1003 self.visit(node.expr)
1004 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001005
Jeremy Hylton126960b2000-02-14 21:33:10 +00001006 def visitInvert(self, node):
1007 return self.unaryOp(node, 'UNARY_INVERT')
1008
Jeremy Hylton40245602000-02-08 21:15:48 +00001009 def visitUnarySub(self, node):
1010 return self.unaryOp(node, 'UNARY_NEGATIVE')
1011
1012 def visitUnaryAdd(self, node):
1013 return self.unaryOp(node, 'UNARY_POSITIVE')
1014
1015 def visitUnaryInvert(self, node):
1016 return self.unaryOp(node, 'UNARY_INVERT')
1017
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001018 def visitNot(self, node):
1019 return self.unaryOp(node, 'UNARY_NOT')
1020
Jeremy Hylton40245602000-02-08 21:15:48 +00001021 def visitBackquote(self, node):
1022 return self.unaryOp(node, 'UNARY_CONVERT')
1023
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00001024 # bit ops
1025
Jeremy Hyltona5058122000-02-14 14:14:29 +00001026 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001027 self.visit(nodes[0])
1028 for node in nodes[1:]:
1029 self.visit(node)
1030 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001031
1032 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001033 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001034
1035 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001036 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001037
1038 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001039 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001040
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001041 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +00001042
Jeremy Hyltona5058122000-02-14 14:14:29 +00001043 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001044 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001045
Jeremy Hylton40245602000-02-08 21:15:48 +00001046 def visitTuple(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001047 self.set_lineno(node)
Jeremy Hylton40245602000-02-08 21:15:48 +00001048 for elt in node.nodes:
1049 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001050 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001051
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001052 def visitList(self, node):
Jeremy Hylton19367452001-08-29 20:57:43 +00001053 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001054 for elt in node.nodes:
1055 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +00001056 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001057
1058 def visitSliceobj(self, node):
1059 for child in node.nodes:
1060 self.visit(child)
1061 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +00001062
Jeremy Hyltona5058122000-02-14 14:14:29 +00001063 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001064 lineno = getattr(node, 'lineno', None)
1065 if lineno:
Jeremy Hylton19367452001-08-29 20:57:43 +00001066 self.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001067 self.emit('BUILD_MAP', 0)
1068 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001069 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001070 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001071 self.emit('SET_LINENO', lineno2)
1072 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001073 self.emit('DUP_TOP')
1074 self.visit(v)
1075 self.emit('ROT_TWO')
1076 self.visit(k)
1077 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +00001078
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001079class NestedScopeMixin:
1080 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001081 def initClass(self):
1082 self.__class__.NameFinder = LocalNameFinder
1083 self.__class__.FunctionGen = FunctionCodeGenerator
1084 self.__class__.ClassGen = ClassCodeGenerator
1085
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001086class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001087 __super_init = CodeGenerator.__init__
1088
1089 scopes = None
1090
Jeremy Hylton37c93512001-09-17 18:03:55 +00001091 def __init__(self, tree):
1092 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001093 self.futures = future.find_futures(tree)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001094 self.__super_init()
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001095 walk(tree, self)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001096
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001097 def get_module(self):
1098 return self
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001099
1100class AbstractFunctionCode:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001101 optimized = 1
1102 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001103
Jeremy Hylton37c93512001-09-17 18:03:55 +00001104 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001105 self.class_name = class_name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001106 self.module = mod
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001107 if isLambda:
1108 klass = FunctionCodeGenerator
1109 name = "<lambda.%d>" % klass.lambdaCount
1110 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +00001111 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001112 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001113 args, hasTupleArg = generateArgList(func.argnames)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001114 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001115 optimized=1)
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001116 self.isLambda = isLambda
Jeremy Hylton37c93512001-09-17 18:03:55 +00001117 self.super_init()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001118
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001119 if not isLambda and func.doc:
1120 self.setDocstring(func.doc)
1121
Jeremy Hylton2afff322001-08-27 21:51:52 +00001122 lnf = walk(func.code, self.NameFinder(args), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001123 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001124 if func.varargs:
1125 self.graph.setFlag(CO_VARARGS)
1126 if func.kwargs:
1127 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +00001128 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001129 if hasTupleArg:
1130 self.generateArgUnpack(func.argnames)
1131
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001132 def get_module(self):
1133 return self.module
1134
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001135 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001136 self.graph.startExitBlock()
1137 if not self.isLambda:
1138 self.emit('LOAD_CONST', None)
1139 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001140
1141 def generateArgUnpack(self, args):
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001142 for i in range(len(args)):
1143 arg = args[i]
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001144 if type(arg) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001145 self.emit('LOAD_FAST', '.%d' % (i * 2))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001146 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001147
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001148 def unpackSequence(self, tup):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001149 if VERSION > 1:
1150 self.emit('UNPACK_SEQUENCE', len(tup))
1151 else:
1152 self.emit('UNPACK_TUPLE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001153 for elt in tup:
1154 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001155 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001156 else:
Jeremy Hylton3f76b7e2001-04-12 06:52:27 +00001157 self._nameOp('STORE', elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001158
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001159 unpackTuple = unpackSequence
1160
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001161class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001162 CodeGenerator):
1163 super_init = CodeGenerator.__init__ # call be other init
1164 scopes = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001165
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001166 __super_init = AbstractFunctionCode.__init__
1167
Jeremy Hylton37c93512001-09-17 18:03:55 +00001168 def __init__(self, func, scopes, isLambda, class_name, mod):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001169 self.scopes = scopes
1170 self.scope = scopes[func]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001171 self.__super_init(func, scopes, isLambda, class_name, mod)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001172 self.graph.setFreeVars(self.scope.get_free_vars())
1173 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001174 if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
1175 if self.scope.generator is not None:
1176 self.graph.setFlag(CO_GENERATOR)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001177
1178class AbstractClassCode:
1179
Jeremy Hylton37c93512001-09-17 18:03:55 +00001180 def __init__(self, klass, scopes, module):
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00001181 self.class_name = klass.name
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001182 self.module = module
Jeremy Hylton37c93512001-09-17 18:03:55 +00001183 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
Jeremy Hylton94afe322001-08-29 18:14:39 +00001184 optimized=0, klass=1)
Jeremy Hylton37c93512001-09-17 18:03:55 +00001185 self.super_init()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001186 lnf = walk(klass.code, self.NameFinder(), verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001187 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001188 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton9ab019b2001-04-11 16:24:30 +00001189 if klass.doc:
1190 self.setDocstring(klass.doc)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001191
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001192 def get_module(self):
1193 return self.module
Jeremy Hylton660cc772001-04-12 06:49:00 +00001194
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001195 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001196 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001197 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001198 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001199
Jeremy Hylton1e99a772001-09-14 22:49:08 +00001200class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001201 super_init = CodeGenerator.__init__
1202 scopes = None
1203
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001204 __super_init = AbstractClassCode.__init__
1205
Jeremy Hylton37c93512001-09-17 18:03:55 +00001206 def __init__(self, klass, scopes, module):
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001207 self.scopes = scopes
1208 self.scope = scopes[klass]
Jeremy Hylton37c93512001-09-17 18:03:55 +00001209 self.__super_init(klass, scopes, module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001210 self.graph.setFreeVars(self.scope.get_free_vars())
1211 self.graph.setCellVars(self.scope.get_cell_vars())
Jeremy Hylton2afff322001-08-27 21:51:52 +00001212## self.graph.setFlag(CO_NESTED)
Jeremy Hylton364f9b92001-04-12 06:40:42 +00001213
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001214def generateArgList(arglist):
1215 """Generate an arg list marking TupleArgs"""
1216 args = []
1217 extra = []
1218 count = 0
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001219 for i in range(len(arglist)):
1220 elt = arglist[i]
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001221 if type(elt) == types.StringType:
1222 args.append(elt)
1223 elif type(elt) == types.TupleType:
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001224 args.append(TupleArg(i * 2, elt))
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001225 extra.extend(misc.flatten(elt))
Jeremy Hyltonbfb0cf82001-04-12 17:33:34 +00001226 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001227 else:
1228 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001229 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +00001230
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001231def findOp(node):
1232 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
1233 v = OpFinder()
Jeremy Hylton2afff322001-08-27 21:51:52 +00001234 walk(node, v, verbose=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001235 return v.op
1236
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001237class OpFinder:
1238 def __init__(self):
1239 self.op = None
1240 def visitAssName(self, node):
1241 if self.op is None:
1242 self.op = node.flags
1243 elif self.op != node.flags:
1244 raise ValueError, "mixed ops in stmt"
Jeremy Hylton614e87f2001-04-12 20:24:26 +00001245 visitAssAttr = visitAssName
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001246
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001247class Delegator:
1248 """Base class to support delegation for augmented assignment nodes
1249
1250 To generator code for augmented assignments, we use the following
1251 wrapper classes. In visitAugAssign, the left-hand expression node
1252 is visited twice. The first time the visit uses the normal method
1253 for that node . The second time the visit uses a different method
1254 that generates the appropriate code to perform the assignment.
1255 These delegator classes wrap the original AST nodes in order to
1256 support the variant visit methods.
1257 """
1258 def __init__(self, obj):
1259 self.obj = obj
1260
1261 def __getattr__(self, attr):
1262 return getattr(self.obj, attr)
1263
1264class AugGetattr(Delegator):
1265 pass
1266
1267class AugName(Delegator):
1268 pass
1269
1270class AugSlice(Delegator):
1271 pass
1272
1273class AugSubscript(Delegator):
1274 pass
1275
1276wrapper = {
1277 ast.Getattr: AugGetattr,
1278 ast.Name: AugName,
1279 ast.Slice: AugSlice,
1280 ast.Subscript: AugSubscript,
1281 }
1282
1283def wrap_aug(node):
1284 return wrapper[node.__class__](node)
1285
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001286if __name__ == "__main__":
1287 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00001288
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00001289 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +00001290 compile(file)