blob: b2d55d98696b5d40a2b4e54f41e895329aea1754 [file] [log] [blame]
Jeremy Hylton8b6323d2000-02-04 00:28:21 +00001"""Python bytecode generator
2
3Currently contains generic ASTVisitor code, a LocalNameFinder, and a
4CodeGenerator. Eventually, this will get split into the ASTVisitor as
5a generic tool and CodeGenerator as a specific tool.
6"""
7
Jeremy Hylton7fab23e2000-03-06 19:10:54 +00008from compiler import parseFile, ast, visitor, walk, parse
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +00009from pyassem import StackRef, PyAssembler, TupleArg
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000010import dis
11import misc
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +000012import marshal
13import new
14import string
Jeremy Hylton53187f32000-02-08 19:01:29 +000015import sys
16import os
17import stat
18import struct
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +000019import types
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000020
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000021class CodeGenerator:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +000022 """Generate bytecode for the Python VM"""
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000023
Jeremy Hylton3050d512000-02-12 00:12:38 +000024 OPTIMIZED = 1
25
Jeremy Hyltona5058122000-02-14 14:14:29 +000026 # XXX should clean up initialization and generateXXX funcs
Jeremy Hylton3050d512000-02-12 00:12:38 +000027 def __init__(self, filename="<?>"):
Jeremy Hylton53187f32000-02-08 19:01:29 +000028 self.filename = filename
Jeremy Hylton873bdc12000-02-17 17:56:29 +000029 self.code = PyAssembler()
Jeremy Hylton53187f32000-02-08 19:01:29 +000030 self.code.setFlags(0)
Jeremy Hylton873bdc12000-02-17 17:56:29 +000031 self.locals = misc.Stack()
Jeremy Hylton4eb504c2000-02-10 20:55:50 +000032 self.loops = misc.Stack()
Jeremy Hylton3050d512000-02-12 00:12:38 +000033 self.namespace = 0
Jeremy Hylton53187f32000-02-08 19:01:29 +000034 self.curStack = 0
35 self.maxStack = 0
36
Jeremy Hyltona5058122000-02-14 14:14:29 +000037 def emit(self, *args):
Jeremy Hylton873bdc12000-02-17 17:56:29 +000038 # XXX could just use self.emit = self.code.emit
39 apply(self.code.emit, args)
Jeremy Hyltona5058122000-02-14 14:14:29 +000040
Jeremy Hylton3050d512000-02-12 00:12:38 +000041 def _generateFunctionOrLambdaCode(self, func):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000042 self.name = func.name
Jeremy Hylton873bdc12000-02-17 17:56:29 +000043
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +000044 # keep a lookout for 'def foo((x,y)):'
45 args, hasTupleArg = self.generateArglist(func.argnames)
46
Jeremy Hylton873bdc12000-02-17 17:56:29 +000047 self.code = PyAssembler(args=args, name=func.name,
48 filename=self.filename)
Jeremy Hylton3050d512000-02-12 00:12:38 +000049 self.namespace = self.OPTIMIZED
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000050 if func.varargs:
51 self.code.setVarArgs()
52 if func.kwargs:
53 self.code.setKWArgs()
54 lnf = walk(func.code, LocalNameFinder(args), 0)
55 self.locals.push(lnf.getLocals())
Jeremy Hylton873bdc12000-02-17 17:56:29 +000056 self.emit('SET_LINENO', func.lineno)
57 if hasTupleArg:
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +000058 self.generateArgUnpack(func.argnames)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000059 walk(func.code, self)
Jeremy Hylton76d01b82000-02-11 20:27:07 +000060
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +000061 def generateArglist(self, arglist):
62 args = []
63 extra = []
64 count = 0
65 for elt in arglist:
66 if type(elt) == types.StringType:
67 args.append(elt)
68 elif type(elt) == types.TupleType:
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +000069 args.append(TupleArg(count, elt))
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +000070 count = count + 1
71 extra.extend(misc.flatten(elt))
72 else:
73 raise ValueError, "unexpect argument type:", elt
74 return args + extra, count
75
76 def generateArgUnpack(self, args):
77 count = 0
78 for arg in args:
79 if type(arg) == types.TupleType:
80 self.emit('LOAD_FAST', '.nested%d' % count)
81 count = count + 1
82 self.unpackTuple(arg)
83
84 def unpackTuple(self, tup):
85 self.emit('UNPACK_TUPLE', len(tup))
86 for elt in tup:
87 if type(elt) == types.TupleType:
88 self.unpackTuple(elt)
89 else:
90 self.emit('STORE_FAST', elt)
91
Jeremy Hylton3050d512000-02-12 00:12:38 +000092 def generateFunctionCode(self, func):
Jeremy Hylton76d01b82000-02-11 20:27:07 +000093 """Generate code for a function body"""
Jeremy Hylton3050d512000-02-12 00:12:38 +000094 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +000095 self.emit('LOAD_CONST', None)
96 self.emit('RETURN_VALUE')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000097
Jeremy Hylton3050d512000-02-12 00:12:38 +000098 def generateLambdaCode(self, func):
99 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000100 self.emit('RETURN_VALUE')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000101
102 def generateClassCode(self, klass):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000103 self.code = PyAssembler(name=klass.name,
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000104 filename=self.filename)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000105 self.emit('SET_LINENO', klass.lineno)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000106 lnf = walk(klass.code, LocalNameFinder(), 0)
107 self.locals.push(lnf.getLocals())
108 walk(klass.code, self)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000109 self.emit('LOAD_LOCALS')
110 self.emit('RETURN_VALUE')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000111
Jeremy Hyltona5058122000-02-14 14:14:29 +0000112 def asConst(self):
113 """Create a Python code object."""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000114 if self.namespace == self.OPTIMIZED:
115 self.code.setOptimized()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000116 return self.code.makeCodeObject()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000117
Jeremy Hylton40245602000-02-08 21:15:48 +0000118 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000119 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000120
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000121 def _nameOp(self, prefix, name):
122 if self.isLocalName(name):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000123 if self.namespace == self.OPTIMIZED:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000124 self.emit(prefix + '_FAST', name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000125 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000126 self.emit(prefix + '_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000127 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000128 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000129
130 def storeName(self, name):
131 self._nameOp('STORE', name)
132
133 def loadName(self, name):
134 self._nameOp('LOAD', name)
135
136 def delName(self, name):
137 self._nameOp('DELETE', name)
138
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000139 def visitNULL(self, node):
140 """Method exists only to stop warning in -v mode"""
141 pass
142
143 visitStmt = visitNULL
144 visitGlobal = visitNULL
145
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000146 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000147 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000148 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000149 return 1
150
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000151 def visitPass(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000152 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000153
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000154 def visitModule(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000155 lnf = walk(node.node, LocalNameFinder(), 0)
156 self.locals.push(lnf.getLocals())
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000157 self.visit(node.node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000158 self.emit('LOAD_CONST', None)
159 self.emit('RETURN_VALUE')
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000160 return 1
161
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000162 def visitImport(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000163 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000164 for name in node.names:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000165 self.emit('IMPORT_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000166 self.storeName(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000167
168 def visitFrom(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000169 self.emit('SET_LINENO', node.lineno)
170 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000171 for name in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000172 if name == '*':
173 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000174 self.emit('IMPORT_FROM', name)
175 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000176
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000177 def visitClass(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000178 self.emit('SET_LINENO', node.lineno)
179 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000180 for base in node.bases:
181 self.visit(base)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000182 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton3050d512000-02-12 00:12:38 +0000183 classBody = CodeGenerator(self.filename)
184 classBody.generateClassCode(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000185 self.emit('LOAD_CONST', classBody)
186 self.emit('MAKE_FUNCTION', 0)
187 self.emit('CALL_FUNCTION', 0)
188 self.emit('BUILD_CLASS')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000189 self.storeName(node.name)
190 return 1
191
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000192 def _visitFuncOrLambda(self, node, kind):
193 """Code common to Function and Lambda nodes"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000194 codeBody = CodeGenerator(self.filename)
195 getattr(codeBody, 'generate%sCode' % kind)(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000196 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000197 for default in node.defaults:
198 self.visit(default)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000199 self.emit('LOAD_CONST', codeBody)
200 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000201
202 def visitFunction(self, node):
203 self._visitFuncOrLambda(node, 'Function')
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000204 self.storeName(node.name)
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000205 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000206
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000207 def visitLambda(self, node):
208 node.name = '<lambda>'
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000209 self._visitFuncOrLambda(node, 'Lambda')
210 return 1
211
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000212 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000213 pos = 0
214 kw = 0
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000215 if hasattr(node, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000216 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000217 self.visit(node.node)
218 for arg in node.args:
219 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000220 if isinstance(arg, ast.Keyword):
221 kw = kw + 1
222 else:
223 pos = pos + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000224 self.emit('CALL_FUNCTION', kw << 8 | pos)
225 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000226
Jeremy Hylton3050d512000-02-12 00:12:38 +0000227 def visitKeyword(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000228 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000229 self.visit(node.expr)
230 return 1
231
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000232 def visitIf(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000233 after = StackRef()
234 for test, suite in node.tests:
Jeremy Hylton40245602000-02-08 21:15:48 +0000235 if hasattr(test, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000236 self.emit('SET_LINENO', test.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000237 else:
238 print "warning", "no line number"
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000239 self.visit(test)
240 dest = StackRef()
241 self.emit('JUMP_IF_FALSE', dest)
242 self.emit('POP_TOP')
243 self.visit(suite)
244 self.emit('JUMP_FORWARD', after)
245 dest.bind(self.code.getCurInst())
246 self.emit('POP_TOP')
247 if node.else_:
248 self.visit(node.else_)
249 after.bind(self.code.getCurInst())
250 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000251
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000252 def startLoop(self):
253 l = Loop()
254 self.loops.push(l)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000255 self.emit('SETUP_LOOP', l.extentAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000256 return l
257
258 def finishLoop(self):
259 l = self.loops.pop()
260 i = self.code.getCurInst()
261 l.extentAnchor.bind(self.code.getCurInst())
262
Jeremy Hylton40245602000-02-08 21:15:48 +0000263 def visitFor(self, node):
264 # three refs needed
Jeremy Hylton40245602000-02-08 21:15:48 +0000265 anchor = StackRef()
Jeremy Hylton40245602000-02-08 21:15:48 +0000266
Jeremy Hyltona5058122000-02-14 14:14:29 +0000267 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000268 l = self.startLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000269 self.visit(node.list)
270 self.visit(ast.Const(0))
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000271 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000272 self.emit('SET_LINENO', node.lineno)
273 self.emit('FOR_LOOP', anchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000274 self.visit(node.assign)
275 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000276 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000277 anchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000278 self.emit('POP_BLOCK')
Jeremy Hylton40245602000-02-08 21:15:48 +0000279 if node.else_:
280 self.visit(node.else_)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000281 self.finishLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000282 return 1
283
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000284 def visitWhile(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000285 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000286 l = self.startLoop()
287 if node.else_:
288 lElse = StackRef()
289 else:
290 lElse = l.breakAnchor
291 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000292 if hasattr(node.test, 'lineno'):
293 self.emit('SET_LINENO', node.test.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000294 self.visit(node.test)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000295 self.emit('JUMP_IF_FALSE', lElse)
296 self.emit('POP_TOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000297 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000298 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000299 # note that lElse may be an alias for l.breakAnchor
300 lElse.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000301 self.emit('POP_TOP')
302 self.emit('POP_BLOCK')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000303 if node.else_:
304 self.visit(node.else_)
305 self.finishLoop()
306 return 1
307
308 def visitBreak(self, node):
309 if not self.loops:
310 raise SyntaxError, "'break' outside loop"
Jeremy Hyltona5058122000-02-14 14:14:29 +0000311 self.emit('SET_LINENO', node.lineno)
312 self.emit('BREAK_LOOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000313
314 def visitContinue(self, node):
315 if not self.loops:
316 raise SyntaxError, "'continue' outside loop"
317 l = self.loops.top()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000318 self.emit('SET_LINENO', node.lineno)
319 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000320
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000321 def visitTryExcept(self, node):
322 # XXX need to figure out exactly what is on the stack when an
323 # exception is raised and the first handler is checked
324 handlers = StackRef()
325 end = StackRef()
326 if node.else_:
327 lElse = StackRef()
328 else:
329 lElse = end
330 self.emit('SET_LINENO', node.lineno)
331 self.emit('SETUP_EXCEPT', handlers)
332 self.visit(node.body)
333 self.emit('POP_BLOCK')
334 self.emit('JUMP_FORWARD', lElse)
335 handlers.bind(self.code.getCurInst())
336
337 last = len(node.handlers) - 1
338 for i in range(len(node.handlers)):
339 expr, target, body = node.handlers[i]
340 if hasattr(expr, 'lineno'):
341 self.emit('SET_LINENO', expr.lineno)
342 if expr:
343 self.emit('DUP_TOP')
344 self.visit(expr)
345 self.emit('COMPARE_OP', "exception match")
346 next = StackRef()
347 self.emit('JUMP_IF_FALSE', next)
348 self.emit('POP_TOP')
349 self.emit('POP_TOP')
350 if target:
351 self.visit(target)
352 else:
353 self.emit('POP_TOP')
354 self.emit('POP_TOP')
355 self.visit(body)
356 self.emit('JUMP_FORWARD', end)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000357 if expr:
358 next.bind(self.code.getCurInst())
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000359 self.emit('POP_TOP')
360 self.emit('END_FINALLY')
361 if node.else_:
362 lElse.bind(self.code.getCurInst())
363 self.visit(node.else_)
364 end.bind(self.code.getCurInst())
365 return 1
366
367 def visitTryFinally(self, node):
368 final = StackRef()
369 self.emit('SET_LINENO', node.lineno)
370 self.emit('SETUP_FINALLY', final)
371 self.visit(node.body)
372 self.emit('POP_BLOCK')
373 self.emit('LOAD_CONST', None)
374 final.bind(self.code.getCurInst())
375 self.visit(node.final)
376 self.emit('END_FINALLY')
377 return 1
378
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000379 def visitCompare(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000380 """Comment from compile.c follows:
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000381
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000382 The following code is generated for all but the last
383 comparison in a chain:
384
385 label: on stack: opcode: jump to:
386
387 a <code to load b>
388 a, b DUP_TOP
389 a, b, b ROT_THREE
390 b, a, b COMPARE_OP
391 b, 0-or-1 JUMP_IF_FALSE L1
392 b, 1 POP_TOP
393 b
394
395 We are now ready to repeat this sequence for the next
396 comparison in the chain.
397
398 For the last we generate:
399
400 b <code to load c>
401 b, c COMPARE_OP
402 0-or-1
403
404 If there were any jumps to L1 (i.e., there was more than one
405 comparison), we generate:
406
407 0-or-1 JUMP_FORWARD L2
408 L1: b, 0 ROT_TWO
409 0, b POP_TOP
410 0
411 L2: 0-or-1
412 """
413 self.visit(node.expr)
414 # if refs are never emitted, subsequent bind call has no effect
415 l1 = StackRef()
416 l2 = StackRef()
417 for op, code in node.ops[:-1]:
418 # emit every comparison except the last
419 self.visit(code)
420 self.emit('DUP_TOP')
421 self.emit('ROT_THREE')
422 self.emit('COMPARE_OP', op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000423 # dupTop and compareOp cancel stack effect
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000424 self.emit('JUMP_IF_FALSE', l1)
425 self.emit('POP_TOP')
426 if node.ops:
427 # emit the last comparison
428 op, code = node.ops[-1]
429 self.visit(code)
430 self.emit('COMPARE_OP', op)
431 if len(node.ops) > 1:
432 self.emit('JUMP_FORWARD', l2)
433 l1.bind(self.code.getCurInst())
434 self.emit('ROT_TWO')
435 self.emit('POP_TOP')
436 l2.bind(self.code.getCurInst())
437 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000438
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000439 def visitGetattr(self, node):
440 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000441 self.emit('LOAD_ATTR', node.attrname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000442 return 1
443
444 def visitSubscript(self, node):
445 self.visit(node.expr)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000446 for sub in node.subs:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000447 self.visit(sub)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000448 if len(node.subs) > 1:
449 self.emit('BUILD_TUPLE', len(node.subs))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000450 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000451 self.emit('BINARY_SUBSCR')
452 elif node.flags == 'OP_ASSIGN':
453 self.emit('STORE_SUBSCR')
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000454 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000455 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000456 return 1
457
458 def visitSlice(self, node):
459 self.visit(node.expr)
460 slice = 0
461 if node.lower:
462 self.visit(node.lower)
463 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000464 if node.upper:
465 self.visit(node.upper)
466 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000467 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000468 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000469 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000470 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000471 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000472 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000473 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000474 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000475 raise
476 return 1
477
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000478 def visitSliceobj(self, node):
479 for child in node.nodes:
480 print child
481 self.visit(child)
482 self.emit('BUILD_SLICE', len(node.nodes))
483 return 1
484
Jeremy Hylton40245602000-02-08 21:15:48 +0000485 def visitAssign(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000486 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000487 self.visit(node.expr)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000488 dups = len(node.nodes) - 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000489 for i in range(len(node.nodes)):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000490 elt = node.nodes[i]
491 if i < dups:
492 self.emit('DUP_TOP')
Jeremy Hylton40245602000-02-08 21:15:48 +0000493 if isinstance(elt, ast.Node):
494 self.visit(elt)
495 return 1
496
497 def visitAssName(self, node):
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000498 if node.flags == 'OP_ASSIGN':
499 self.storeName(node.name)
500 elif node.flags == 'OP_DELETE':
501 self.delName(node.name)
502 else:
Jeremy Hylton40245602000-02-08 21:15:48 +0000503 print "oops", node.flags
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000504 return 1
Jeremy Hylton40245602000-02-08 21:15:48 +0000505
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000506 def visitAssAttr(self, node):
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000507 self.visit(node.expr)
508 if node.flags == 'OP_ASSIGN':
509 self.emit('STORE_ATTR', node.attrname)
510 elif node.flags == 'OP_DELETE':
511 self.emit('DELETE_ATTR', node.attrname)
512 else:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000513 print "warning: unexpected flags:", node.flags
514 print node
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000515 return 1
516
517 def visitAssTuple(self, node):
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000518 if findOp(node) != 'OP_DELETE':
519 self.emit('UNPACK_TUPLE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000520 for child in node.nodes:
521 self.visit(child)
522 return 1
523
524 visitAssList = visitAssTuple
525
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000526 # binary ops
527
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000528 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000529 self.visit(node.left)
530 self.visit(node.right)
531 self.emit(op)
532 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000533
534 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000535 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000536
537 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000538 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000539
540 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000541 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000542
543 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000544 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000545
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000546 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000547 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000548
Jeremy Hylton126960b2000-02-14 21:33:10 +0000549 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000550 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000551
552 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000553 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000554
555 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000556 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000557
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000558 # unary ops
559
560 def unaryOp(self, node, op):
561 self.visit(node.expr)
562 self.emit(op)
563 return 1
564
Jeremy Hylton126960b2000-02-14 21:33:10 +0000565 def visitInvert(self, node):
566 return self.unaryOp(node, 'UNARY_INVERT')
567
Jeremy Hylton40245602000-02-08 21:15:48 +0000568 def visitUnarySub(self, node):
569 return self.unaryOp(node, 'UNARY_NEGATIVE')
570
571 def visitUnaryAdd(self, node):
572 return self.unaryOp(node, 'UNARY_POSITIVE')
573
574 def visitUnaryInvert(self, node):
575 return self.unaryOp(node, 'UNARY_INVERT')
576
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000577 def visitNot(self, node):
578 return self.unaryOp(node, 'UNARY_NOT')
579
Jeremy Hylton40245602000-02-08 21:15:48 +0000580 def visitBackquote(self, node):
581 return self.unaryOp(node, 'UNARY_CONVERT')
582
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000583 # bit ops
584
Jeremy Hyltona5058122000-02-14 14:14:29 +0000585 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000586 self.visit(nodes[0])
587 for node in nodes[1:]:
588 self.visit(node)
589 self.emit(op)
590 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000591
592 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000593 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000594
595 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000596 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000597
598 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000599 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000600
Jeremy Hyltona5058122000-02-14 14:14:29 +0000601 def visitAssert(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000602 # XXX __debug__ and AssertionError appear to be special cases
603 # -- they are always loaded as globals even if there are local
604 # names. I guess this is a sort of renaming op.
605 skip = StackRef()
606 self.emit('SET_LINENO', node.lineno)
607 self.emit('LOAD_GLOBAL', '__debug__')
608 self.emit('JUMP_IF_FALSE', skip)
609 self.emit('POP_TOP')
610 self.visit(node.test)
611 self.emit('JUMP_IF_TRUE', skip)
612 self.emit('LOAD_GLOBAL', 'AssertionError')
613 self.visit(node.fail)
614 self.emit('RAISE_VARARGS', 2)
615 skip.bind(self.code.getCurInst())
616 self.emit('POP_TOP')
617 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000618
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000619 def visitTest(self, node, jump):
620 end = StackRef()
621 for child in node.nodes[:-1]:
622 self.visit(child)
623 self.emit(jump, end)
624 self.emit('POP_TOP')
625 self.visit(node.nodes[-1])
626 end.bind(self.code.getCurInst())
627 return 1
628
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000629 def visitAnd(self, node):
630 return self.visitTest(node, 'JUMP_IF_FALSE')
631
632 def visitOr(self, node):
633 return self.visitTest(node, 'JUMP_IF_TRUE')
634
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000635 def visitName(self, node):
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000636 self.loadName(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000637
638 def visitConst(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000639 self.emit('LOAD_CONST', node.value)
Jeremy Hylton40245602000-02-08 21:15:48 +0000640 return 1
641
Jeremy Hyltona5058122000-02-14 14:14:29 +0000642 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000643 self.emit('LOAD_CONST', Ellipsis)
644 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000645
Jeremy Hylton40245602000-02-08 21:15:48 +0000646 def visitTuple(self, node):
647 for elt in node.nodes:
648 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000649 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton40245602000-02-08 21:15:48 +0000650 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000651
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000652 def visitList(self, node):
653 for elt in node.nodes:
654 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000655 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000656 return 1
657
Jeremy Hyltona5058122000-02-14 14:14:29 +0000658 def visitDict(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000659 self.emit('BUILD_MAP', 0)
660 for k, v in node.items:
661 # XXX need to add set lineno when there aren't constants
662 self.emit('DUP_TOP')
663 self.visit(v)
664 self.emit('ROT_TWO')
665 self.visit(k)
666 self.emit('STORE_SUBSCR')
667 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000668
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000669 def visitReturn(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000670 self.emit('SET_LINENO', node.lineno)
671 self.visit(node.value)
672 self.emit('RETURN_VALUE')
673 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000674
675 def visitRaise(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000676 self.emit('SET_LINENO', node.lineno)
677 n = 0
678 if node.expr1:
679 self.visit(node.expr1)
680 n = n + 1
681 if node.expr2:
682 self.visit(node.expr2)
683 n = n + 1
684 if node.expr3:
685 self.visit(node.expr3)
686 n = n + 1
687 self.emit('RAISE_VARARGS', n)
688 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000689
690 def visitPrint(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000691 self.emit('SET_LINENO', node.lineno)
692 for child in node.nodes:
693 self.visit(child)
694 self.emit('PRINT_ITEM')
695 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000696
697 def visitPrintnl(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000698 self.visitPrint(node)
699 self.emit('PRINT_NEWLINE')
700 return 1
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000701
Jeremy Hyltona5058122000-02-14 14:14:29 +0000702 def visitExec(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000703 self.visit(node.expr)
704 if node.locals is None:
705 self.emit('LOAD_CONST', None)
706 else:
707 self.visit(node.locals)
708 if node.globals is None:
709 self.emit('DUP_TOP')
710 else:
711 self.visit(node.globals)
712 self.emit('EXEC_STMT')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000713 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000714
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000715class LocalNameFinder:
716 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000717 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000718 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000719 for name in names:
720 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000721
722 def getLocals(self):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000723 for elt in self.globals.items():
724 if self.names.has_elt(elt):
725 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000726 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000727
Jeremy Hyltona5058122000-02-14 14:14:29 +0000728 def visitDict(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000729 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000730
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000731 def visitGlobal(self, node):
732 for name in node.names:
733 self.globals.add(name)
734 return 1
735
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000736 def visitFunction(self, node):
737 self.names.add(node.name)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000738 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000739
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000740 def visitLambda(self, node):
741 return 1
742
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000743 def visitImport(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000744 for name in node.names:
745 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000746
747 def visitFrom(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000748 for name in node.names:
749 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000750
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000751 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000752 self.names.add(node.name)
753 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000754
755 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000756 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000757
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000758class OpFinder:
759 def __init__(self):
760 self.op = None
761 def visitAssName(self, node):
762 if self.op is None:
763 self.op = node.flags
764 elif self.op != node.flags:
765 raise ValueError, "mixed ops in stmt"
766
767def findOp(node):
768 v = OpFinder()
769 walk(node, v)
770 return v.op
771
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000772class Loop:
773 def __init__(self):
774 self.startAnchor = StackRef()
775 self.breakAnchor = StackRef()
776 self.extentAnchor = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000777
Jeremy Hylton53187f32000-02-08 19:01:29 +0000778class CompiledModule:
779 """Store the code object for a compiled module
780
781 XXX Not clear how the code objects will be stored. Seems possible
782 that a single code attribute is sufficient, because it will
783 contains references to all the need code objects. That might be
784 messy, though.
785 """
786 MAGIC = (20121 | (ord('\r')<<16) | (ord('\n')<<24))
787
788 def __init__(self, source, filename):
789 self.source = source
790 self.filename = filename
791
792 def compile(self):
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000793 self.ast = parse(self.source)
Jeremy Hylton53187f32000-02-08 19:01:29 +0000794 cg = CodeGenerator(self.filename)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000795 walk(self.ast, cg)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000796 self.code = cg.asConst()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000797
798 def dump(self, path):
799 """create a .pyc file"""
800 f = open(path, 'wb')
801 f.write(self._pyc_header())
802 marshal.dump(self.code, f)
803 f.close()
804
805 def _pyc_header(self):
806 # compile.c uses marshal to write a long directly, with
807 # calling the interface that would also generate a 1-byte code
808 # to indicate the type of the value. simplest way to get the
809 # same effect is to call marshal and then skip the code.
810 magic = marshal.dumps(self.MAGIC)[1:]
811 mtime = os.stat(self.filename)[stat.ST_MTIME]
812 mtime = struct.pack('i', mtime)
813 return magic + mtime
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000814
815def compile(filename):
816 buf = open(filename).read()
817 mod = CompiledModule(buf, filename)
818 mod.compile()
819 mod.dump(filename + 'c')
820