blob: 51ab9bdad7c69b23588b7751cea0b97e1c5a8871 [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
8from p2c import transformer, ast
Jeremy Hyltona5058122000-02-14 14:14:29 +00009from pyassem import StackRef, PyAssembler
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 Hylton8b6323d2000-02-04 00:28:21 +000019
20def parse(path):
21 f = open(path)
22 src = f.read()
23 f.close()
24 t = transformer.Transformer()
25 return t.parsesuite(src)
26
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000027def walk(tree, visitor, verbose=None, walker=None):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000028 if walker:
29 w = walker()
30 else:
31 w = ASTVisitor()
Jeremy Hylton40245602000-02-08 21:15:48 +000032 if verbose is not None:
33 w.VERBOSE = verbose
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000034 w.preorder(tree, visitor)
35 return w.visitor
36
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000037def dumpNode(node):
38 print node.__class__
39 for attr in dir(node):
40 if attr[0] != '_':
41 print "\t", "%-10.10s" % attr, getattr(node, attr)
42
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000043class ASTVisitor:
44 """Performs a depth-first walk of the AST
45
46 The ASTVisitor will walk the AST, performing either a preorder or
47 postorder traversal depending on which method is called.
48
49 methods:
50 preorder(tree, visitor)
51 postorder(tree, visitor)
52 tree: an instance of ast.Node
53 visitor: an instance with visitXXX methods
54
55 The ASTVisitor is responsible for walking over the tree in the
56 correct order. For each node, it checks the visitor argument for
57 a method named 'visitNodeType' where NodeType is the name of the
58 node's class, e.g. Classdef. If the method exists, it is called
59 with the node as its sole argument.
60
61 The visitor method for a particular node type can control how
62 child nodes are visited during a preorder walk. (It can't control
63 the order during a postorder walk, because it is called _after_
64 the walk has occurred.) The ASTVisitor modifies the visitor
65 argument by adding a visit method to the visitor; this method can
66 be used to visit a particular child node. If the visitor method
67 returns a true value, the ASTVisitor will not traverse the child
68 nodes.
69
70 XXX The interface for controlling the preorder walk needs to be
71 re-considered. The current interface is convenient for visitors
72 that mostly let the ASTVisitor do everything. For something like
73 a code generator, where you want to walk to occur in a specific
74 order, it's a pain to add "return 1" to the end of each method.
75
76 XXX Perhaps I can use a postorder walk for the code generator?
77 """
78
Jeremy Hylton40245602000-02-08 21:15:48 +000079 VERBOSE = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000080
81 def __init__(self):
82 self.node = None
83
84 def preorder(self, tree, visitor):
85 """Do preorder walk of tree using visitor"""
86 self.visitor = visitor
87 visitor.visit = self._preorder
88 self._preorder(tree)
89
90 def _preorder(self, node):
91 stop = self.dispatch(node)
92 if stop:
93 return
94 for child in node.getChildren():
95 if isinstance(child, ast.Node):
96 self._preorder(child)
97
98 def postorder(self, tree, visitor):
99 """Do preorder walk of tree using visitor"""
100 self.visitor = visitor
101 visitor.visit = self._postorder
102 self._postorder(tree)
103
104 def _postorder(self, tree):
105 for child in node.getChildren():
106 if isinstance(child, ast.Node):
107 self._preorder(child)
108 self.dispatch(node)
109
110 def dispatch(self, node):
111 self.node = node
112 className = node.__class__.__name__
113 meth = getattr(self.visitor, 'visit' + className, None)
Jeremy Hylton40245602000-02-08 21:15:48 +0000114 if self.VERBOSE > 0:
115 if self.VERBOSE == 1:
116 if meth is None:
117 print "dispatch", className
118 else:
119 print "dispatch", className, (meth and meth.__name__ or '')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000120 if meth:
121 return meth(node)
122
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000123class ExampleASTVisitor(ASTVisitor):
124 """Prints examples of the nodes that aren't visited"""
125 examples = {}
126
127 def dispatch(self, node):
128 self.node = node
129 className = node.__class__.__name__
130 meth = getattr(self.visitor, 'visit' + className, None)
131 if self.VERBOSE > 0:
132 if self.VERBOSE == 1:
133 if meth is None:
134 print "dispatch", className
135 else:
136 print "dispatch", className, (meth and meth.__name__ or '')
137 if meth:
138 return meth(node)
139 else:
140 klass = node.__class__
141 if self.VERBOSE < 2:
142 if self.examples.has_key(klass):
143 return
144 self.examples[klass] = klass
145 print
146 print klass
147 for attr in dir(node):
148 if attr[0] != '_':
149 print "\t", "%-12.12s" % attr, getattr(node, attr)
150 print
151
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000152class CodeGenerator:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000153 """TODO
154
155 EmptyNode
Jeremy Hyltona5058122000-02-14 14:14:29 +0000156 Sliceobj
157 Tryexcept
158 Tryfinally
159 """
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000160
Jeremy Hylton3050d512000-02-12 00:12:38 +0000161 OPTIMIZED = 1
162
Jeremy Hyltona5058122000-02-14 14:14:29 +0000163 # XXX should clean up initialization and generateXXX funcs
Jeremy Hylton3050d512000-02-12 00:12:38 +0000164 def __init__(self, filename="<?>"):
Jeremy Hylton53187f32000-02-08 19:01:29 +0000165 self.filename = filename
Jeremy Hyltona5058122000-02-14 14:14:29 +0000166 self.code = PyAssembler()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000167 self.code.setFlags(0)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000168 self.locals = misc.Stack()
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000169 self.loops = misc.Stack()
Jeremy Hylton3050d512000-02-12 00:12:38 +0000170 self.namespace = 0
Jeremy Hylton53187f32000-02-08 19:01:29 +0000171 self.curStack = 0
172 self.maxStack = 0
173
Jeremy Hyltona5058122000-02-14 14:14:29 +0000174 def emit(self, *args):
175 # XXX could just use self.emit = self.code.emit
176 apply(self.code.emit, args)
177
Jeremy Hylton3050d512000-02-12 00:12:38 +0000178 def _generateFunctionOrLambdaCode(self, func):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000179 self.name = func.name
180 self.filename = filename
181 args = func.argnames
Jeremy Hyltona5058122000-02-14 14:14:29 +0000182 self.code = PyAssembler(args=args, name=func.name,
Jeremy Hylton3050d512000-02-12 00:12:38 +0000183 filename=filename)
184 self.namespace = self.OPTIMIZED
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000185 if func.varargs:
186 self.code.setVarArgs()
187 if func.kwargs:
188 self.code.setKWArgs()
189 lnf = walk(func.code, LocalNameFinder(args), 0)
190 self.locals.push(lnf.getLocals())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000191 self.emit('SET_LINENO', func.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000192 walk(func.code, self)
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000193
Jeremy Hylton3050d512000-02-12 00:12:38 +0000194 def generateFunctionCode(self, func):
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000195 """Generate code for a function body"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000196 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000197 self.emit('LOAD_CONST', None)
198 self.emit('RETURN_VALUE')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000199
Jeremy Hylton3050d512000-02-12 00:12:38 +0000200 def generateLambdaCode(self, func):
201 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000202 self.emit('RETURN_VALUE')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000203
204 def generateClassCode(self, klass):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000205 self.code = PyAssembler(name=klass.name,
Jeremy Hylton3050d512000-02-12 00:12:38 +0000206 filename=filename)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000207 self.emit('SET_LINENO', klass.lineno)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000208 lnf = walk(klass.code, LocalNameFinder(), 0)
209 self.locals.push(lnf.getLocals())
210 walk(klass.code, self)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000211 self.emit('LOAD_LOCALS')
212 self.emit('RETURN_VALUE')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000213
Jeremy Hyltona5058122000-02-14 14:14:29 +0000214 def asConst(self):
215 """Create a Python code object."""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000216 if self.namespace == self.OPTIMIZED:
217 self.code.setOptimized()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000218 return self.code.makeCodeObject()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000219
Jeremy Hylton40245602000-02-08 21:15:48 +0000220 def isLocalName(self, name):
221 return self.locals.top().has_elt(name)
222
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000223 def _nameOp(self, prefix, name):
224 if self.isLocalName(name):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000225 if self.namespace == self.OPTIMIZED:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000226 self.emit(prefix + '_FAST', name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000227 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000228 self.emit(prefix + '_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000229 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000230 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000231
232 def storeName(self, name):
233 self._nameOp('STORE', name)
234
235 def loadName(self, name):
236 self._nameOp('LOAD', name)
237
238 def delName(self, name):
239 self._nameOp('DELETE', name)
240
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000241 def visitNULL(self, node):
242 """Method exists only to stop warning in -v mode"""
243 pass
244
245 visitStmt = visitNULL
246 visitGlobal = visitNULL
247
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000248 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000249 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000250 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000251 return 1
252
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000253 def visitPass(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000254 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000255
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000256 def visitModule(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000257 lnf = walk(node.node, LocalNameFinder(), 0)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000258 self.locals.push(lnf.getLocals())
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000259 self.visit(node.node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000260 self.emit('LOAD_CONST', None)
261 self.emit('RETURN_VALUE')
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000262 return 1
263
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000264 def visitImport(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000265 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000266 for name in node.names:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000267 self.emit('IMPORT_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000268 self.storeName(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000269
270 def visitFrom(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000271 self.emit('SET_LINENO', node.lineno)
272 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000273 for name in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000274 if name == '*':
275 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000276 self.emit('IMPORT_FROM', name)
277 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000278
Jeremy Hylton3050d512000-02-12 00:12:38 +0000279 def visitClassdef(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000280 self.emit('SET_LINENO', node.lineno)
281 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000282 for base in node.bases:
283 self.visit(base)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000284 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton3050d512000-02-12 00:12:38 +0000285 classBody = CodeGenerator(self.filename)
286 classBody.generateClassCode(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000287 self.emit('LOAD_CONST', classBody)
288 self.emit('MAKE_FUNCTION', 0)
289 self.emit('CALL_FUNCTION', 0)
290 self.emit('BUILD_CLASS')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000291 self.storeName(node.name)
292 return 1
293
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000294 def _visitFuncOrLambda(self, node, kind):
295 """Code common to Function and Lambda nodes"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000296 codeBody = CodeGenerator(self.filename)
297 getattr(codeBody, 'generate%sCode' % kind)(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000298 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000299 for default in node.defaults:
300 self.visit(default)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000301 self.emit('LOAD_CONST', codeBody)
302 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000303
304 def visitFunction(self, node):
305 self._visitFuncOrLambda(node, 'Function')
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000306 self.storeName(node.name)
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000307 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000308
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000309 def visitLambda(self, node):
310 node.name = '<lambda>'
311 node.varargs = node.kwargs = None
312 self._visitFuncOrLambda(node, 'Lambda')
313 return 1
314
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000315 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000316 pos = 0
317 kw = 0
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000318 if hasattr(node, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000319 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000320 self.visit(node.node)
321 for arg in node.args:
322 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000323 if isinstance(arg, ast.Keyword):
324 kw = kw + 1
325 else:
326 pos = pos + 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000327 self.emit('CALL_FUNCTION', kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000328 return 1
329
Jeremy Hylton3050d512000-02-12 00:12:38 +0000330 def visitKeyword(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000331 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000332 self.visit(node.expr)
333 return 1
334
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000335 def visitIf(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000336 after = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000337 for test, suite in node.tests:
Jeremy Hylton40245602000-02-08 21:15:48 +0000338 if hasattr(test, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000339 self.emit('SET_LINENO', test.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000340 else:
341 print "warning", "no line number"
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000342 self.visit(test)
Jeremy Hylton40245602000-02-08 21:15:48 +0000343 dest = StackRef()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000344 self.emit('JUMP_IF_FALSE', dest)
345 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000346 self.visit(suite)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000347 self.emit('JUMP_FORWARD', after)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000348 dest.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000349 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000350 if node.else_:
351 self.visit(node.else_)
352 after.bind(self.code.getCurInst())
353 return 1
354
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000355 def startLoop(self):
356 l = Loop()
357 self.loops.push(l)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000358 self.emit('SETUP_LOOP', l.extentAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000359 return l
360
361 def finishLoop(self):
362 l = self.loops.pop()
363 i = self.code.getCurInst()
364 l.extentAnchor.bind(self.code.getCurInst())
365
Jeremy Hylton40245602000-02-08 21:15:48 +0000366 def visitFor(self, node):
367 # three refs needed
Jeremy Hylton40245602000-02-08 21:15:48 +0000368 anchor = StackRef()
Jeremy Hylton40245602000-02-08 21:15:48 +0000369
Jeremy Hyltona5058122000-02-14 14:14:29 +0000370 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000371 l = self.startLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000372 self.visit(node.list)
373 self.visit(ast.Const(0))
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000374 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000375 self.emit('SET_LINENO', node.lineno)
376 self.emit('FOR_LOOP', anchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000377 self.visit(node.assign)
378 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000379 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000380 anchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000381 self.emit('POP_BLOCK')
Jeremy Hylton40245602000-02-08 21:15:48 +0000382 if node.else_:
383 self.visit(node.else_)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000384 self.finishLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000385 return 1
386
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000387 def visitWhile(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000388 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000389 l = self.startLoop()
390 if node.else_:
391 lElse = StackRef()
392 else:
393 lElse = l.breakAnchor
394 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000395 self.emit('SET_LINENO', node.test.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000396 self.visit(node.test)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000397 self.emit('JUMP_IF_FALSE', lElse)
398 self.emit('POP_TOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000399 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000400 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000401 # note that lElse may be an alias for l.breakAnchor
402 lElse.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000403 self.emit('POP_TOP')
404 self.emit('POP_BLOCK')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000405 if node.else_:
406 self.visit(node.else_)
407 self.finishLoop()
408 return 1
409
410 def visitBreak(self, node):
411 if not self.loops:
412 raise SyntaxError, "'break' outside loop"
Jeremy Hyltona5058122000-02-14 14:14:29 +0000413 self.emit('SET_LINENO', node.lineno)
414 self.emit('BREAK_LOOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000415
416 def visitContinue(self, node):
417 if not self.loops:
418 raise SyntaxError, "'continue' outside loop"
419 l = self.loops.top()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000420 self.emit('SET_LINENO', node.lineno)
421 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000422
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000423 def visitCompare(self, node):
424 """Comment from compile.c follows:
425
426 The following code is generated for all but the last
427 comparison in a chain:
428
429 label: on stack: opcode: jump to:
430
431 a <code to load b>
432 a, b DUP_TOP
433 a, b, b ROT_THREE
434 b, a, b COMPARE_OP
435 b, 0-or-1 JUMP_IF_FALSE L1
436 b, 1 POP_TOP
437 b
438
439 We are now ready to repeat this sequence for the next
440 comparison in the chain.
441
442 For the last we generate:
443
444 b <code to load c>
445 b, c COMPARE_OP
446 0-or-1
447
448 If there were any jumps to L1 (i.e., there was more than one
449 comparison), we generate:
450
451 0-or-1 JUMP_FORWARD L2
452 L1: b, 0 ROT_TWO
453 0, b POP_TOP
454 0
455 L2: 0-or-1
456 """
457 self.visit(node.expr)
458 # if refs are never emitted, subsequent bind call has no effect
Jeremy Hylton40245602000-02-08 21:15:48 +0000459 l1 = StackRef()
460 l2 = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000461 for op, code in node.ops[:-1]:
462 # emit every comparison except the last
463 self.visit(code)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000464 self.emit('DUP_TOP')
465 self.emit('ROT_THREE')
466 self.emit('COMPARE_OP', op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000467 # dupTop and compareOp cancel stack effect
Jeremy Hyltona5058122000-02-14 14:14:29 +0000468 self.emit('JUMP_IF_FALSE', l1)
469 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000470 if node.ops:
471 # emit the last comparison
472 op, code = node.ops[-1]
473 self.visit(code)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000474 self.emit('COMPARE_OP', op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000475 if len(node.ops) > 1:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000476 self.emit('JUMP_FORWARD', l2)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000477 l1.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000478 self.emit('ROT_TWO')
479 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000480 l2.bind(self.code.getCurInst())
481 return 1
482
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000483 def visitGetattr(self, node):
484 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000485 self.emit('LOAD_ATTR', node.attrname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000486 return 1
487
488 def visitSubscript(self, node):
489 self.visit(node.expr)
490 for sub in node.subs[:-1]:
491 self.visit(sub)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000492 self.emit('BINARY_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000493 self.visit(node.subs[-1])
494 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000495 self.emit('BINARY_SUBSCR')
496 elif node.flags == 'OP_ASSIGN':
497 self.emit('STORE_SUBSCR')
498 elif node.flags == 'OP_DELETE':
499 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000500
501 return 1
502
503 def visitSlice(self, node):
504 self.visit(node.expr)
505 slice = 0
506 if node.lower:
507 self.visit(node.lower)
508 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000509 if node.upper:
510 self.visit(node.upper)
511 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000512 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000513 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000514 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000515 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000516 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000517 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000518 else:
519 print node.flags
520 raise
521 return 1
522
Jeremy Hylton40245602000-02-08 21:15:48 +0000523 def visitAssign(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000524 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000525 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000526 dups = len(node.nodes) - 1
527 for i in range(len(node.nodes)):
528 elt = node.nodes[i]
529 if i < dups:
530 self.emit('DUP_TOP')
Jeremy Hylton40245602000-02-08 21:15:48 +0000531 if isinstance(elt, ast.Node):
532 self.visit(elt)
533 return 1
534
535 def visitAssName(self, node):
536 if node.flags != 'OP_ASSIGN':
537 print "oops", node.flags
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000538 self.storeName(node.name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000539
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000540 def visitAssAttr(self, node):
541 if node.flags != 'OP_ASSIGN':
542 print "warning: unexpected flags:", node.flags
543 print node
544 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000545 self.emit('STORE_ATTR', node.attrname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000546 return 1
547
548 def visitAssTuple(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000549 self.emit('UNPACK_TUPLE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000550 for child in node.nodes:
551 self.visit(child)
552 return 1
553
554 visitAssList = visitAssTuple
555
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000556 def binaryOp(self, node, op):
557 self.visit(node.left)
558 self.visit(node.right)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000559 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000560 return 1
561
Jeremy Hylton40245602000-02-08 21:15:48 +0000562 def unaryOp(self, node, op):
563 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000564 self.emit(op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000565 return 1
566
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000567 def visitAdd(self, node):
568 return self.binaryOp(node, 'BINARY_ADD')
569
570 def visitSub(self, node):
571 return self.binaryOp(node, 'BINARY_SUBTRACT')
572
573 def visitMul(self, node):
574 return self.binaryOp(node, 'BINARY_MULTIPLY')
575
576 def visitDiv(self, node):
577 return self.binaryOp(node, 'BINARY_DIVIDE')
578
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000579 def visitMod(self, node):
580 return self.binaryOp(node, 'BINARY_MODULO')
581
Jeremy Hylton126960b2000-02-14 21:33:10 +0000582 def visitPower(self, node):
583 return self.binaryOp(node, 'BINARY_POWER')
584
585 def visitLeftShift(self, node):
586 return self.binaryOp(node, 'BINARY_LSHIFT')
587
588 def visitRightShift(self, node):
589 return self.binaryOp(node, 'BINARY_RSHIFT')
590
591 def visitInvert(self, node):
592 return self.unaryOp(node, 'UNARY_INVERT')
593
Jeremy Hylton40245602000-02-08 21:15:48 +0000594 def visitUnarySub(self, node):
595 return self.unaryOp(node, 'UNARY_NEGATIVE')
596
597 def visitUnaryAdd(self, node):
598 return self.unaryOp(node, 'UNARY_POSITIVE')
599
600 def visitUnaryInvert(self, node):
601 return self.unaryOp(node, 'UNARY_INVERT')
602
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000603 def visitNot(self, node):
604 return self.unaryOp(node, 'UNARY_NOT')
605
Jeremy Hylton40245602000-02-08 21:15:48 +0000606 def visitBackquote(self, node):
607 return self.unaryOp(node, 'UNARY_CONVERT')
608
Jeremy Hyltona5058122000-02-14 14:14:29 +0000609 def bitOp(self, nodes, op):
610 self.visit(nodes[0])
611 for node in nodes[1:]:
612 self.visit(node)
613 self.emit(op)
614 return 1
615
616 def visitBitand(self, node):
617 return self.bitOp(node.nodes, 'BINARY_AND')
618
619 def visitBitor(self, node):
620 return self.bitOp(node.nodes, 'BINARY_OR')
621
622 def visitBitxor(self, node):
623 return self.bitOp(node.nodes, 'BINARY_XOR')
624
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000625 def visitTest(self, node, jump):
626 end = StackRef()
627 for child in node.nodes[:-1]:
628 self.visit(child)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000629 self.emit(jump, end)
630 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000631 self.visit(node.nodes[-1])
632 end.bind(self.code.getCurInst())
633 return 1
634
Jeremy Hyltona5058122000-02-14 14:14:29 +0000635 def visitAssert(self, node):
636 # XXX __debug__ and AssertionError appear to be special cases
637 # -- they are always loaded as globals even if there are local
638 # names. I guess this is a sort of renaming op.
639 skip = StackRef()
640 self.emit('SET_LINENO', node.lineno)
641 self.emit('LOAD_GLOBAL', '__debug__')
642 self.emit('JUMP_IF_FALSE', skip)
643 self.emit('POP_TOP')
644 self.visit(node.test)
645 self.emit('JUMP_IF_TRUE', skip)
646 self.emit('LOAD_GLOBAL', 'AssertionError')
647 self.visit(node.fail)
648 self.emit('RAISE_VARARGS', 2)
649 skip.bind(self.code.getCurInst())
650 self.emit('POP_TOP')
651 return 1
652
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000653 def visitAnd(self, node):
654 return self.visitTest(node, 'JUMP_IF_FALSE')
655
656 def visitOr(self, node):
657 return self.visitTest(node, 'JUMP_IF_TRUE')
658
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000659 def visitName(self, node):
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000660 self.loadName(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000661
662 def visitConst(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000663 self.emit('LOAD_CONST', node.value)
Jeremy Hylton40245602000-02-08 21:15:48 +0000664 return 1
665
Jeremy Hyltona5058122000-02-14 14:14:29 +0000666 def visitEllipsis(self, node):
667 self.emit('LOAD_CONST', Ellipsis)
668 return 1
669
Jeremy Hylton40245602000-02-08 21:15:48 +0000670 def visitTuple(self, node):
671 for elt in node.nodes:
672 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000673 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton40245602000-02-08 21:15:48 +0000674 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000675
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000676 def visitList(self, node):
677 for elt in node.nodes:
678 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000679 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000680 return 1
681
Jeremy Hyltona5058122000-02-14 14:14:29 +0000682 def visitDict(self, node):
683 self.emit('BUILD_MAP', 0)
684 for k, v in node.items:
685 # XXX need to add set lineno when there aren't constants
686 self.emit('DUP_TOP')
687 self.visit(v)
688 self.emit('ROT_TWO')
689 self.visit(k)
690 self.emit('STORE_SUBSCR')
691 return 1
692
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000693 def visitReturn(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000694 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000695 self.visit(node.value)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000696 self.emit('RETURN_VALUE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000697 return 1
698
699 def visitRaise(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000700 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000701 n = 0
702 if node.expr1:
703 self.visit(node.expr1)
704 n = n + 1
705 if node.expr2:
706 self.visit(node.expr2)
707 n = n + 1
708 if node.expr3:
709 self.visit(node.expr3)
710 n = n + 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000711 self.emit('RAISE_VARARGS', n)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000712 return 1
713
714 def visitPrint(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000715 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000716 for child in node.nodes:
717 self.visit(child)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000718 self.emit('PRINT_ITEM')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000719 return 1
720
721 def visitPrintnl(self, node):
722 self.visitPrint(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000723 self.emit('PRINT_NEWLINE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000724 return 1
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000725
Jeremy Hyltona5058122000-02-14 14:14:29 +0000726 def visitExec(self, node):
727 self.visit(node.expr)
728 if node.locals is None:
729 self.emit('LOAD_CONST', None)
730 else:
731 self.visit(node.locals)
732 if node.globals is None:
733 self.emit('DUP_TOP')
734 else:
735 self.visit(node.globals)
736 self.emit('EXEC_STMT')
737
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000738class LocalNameFinder:
739 def __init__(self, names=()):
740 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000741 self.globals = misc.Set()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000742 for name in names:
743 self.names.add(name)
744
745 def getLocals(self):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000746 for elt in self.globals.items():
747 if self.names.has_elt(elt):
748 self.names.remove(elt)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000749 return self.names
750
Jeremy Hyltona5058122000-02-14 14:14:29 +0000751 def visitDict(self, node):
752 return 1
753
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000754 def visitGlobal(self, node):
755 for name in node.names:
756 self.globals.add(name)
757 return 1
758
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000759 def visitFunction(self, node):
760 self.names.add(node.name)
761 return 1
762
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000763 def visitLambda(self, node):
764 return 1
765
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000766 def visitImport(self, node):
767 for name in node.names:
768 self.names.add(name)
769
770 def visitFrom(self, node):
771 for name in node.names:
772 self.names.add(name)
773
774 def visitClassdef(self, node):
775 self.names.add(node.name)
776 return 1
777
778 def visitAssName(self, node):
779 self.names.add(node.name)
780
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000781class Loop:
782 def __init__(self):
783 self.startAnchor = StackRef()
784 self.breakAnchor = StackRef()
785 self.extentAnchor = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000786
Jeremy Hylton53187f32000-02-08 19:01:29 +0000787class CompiledModule:
788 """Store the code object for a compiled module
789
790 XXX Not clear how the code objects will be stored. Seems possible
791 that a single code attribute is sufficient, because it will
792 contains references to all the need code objects. That might be
793 messy, though.
794 """
795 MAGIC = (20121 | (ord('\r')<<16) | (ord('\n')<<24))
796
797 def __init__(self, source, filename):
798 self.source = source
799 self.filename = filename
800
801 def compile(self):
802 t = transformer.Transformer()
803 self.ast = t.parsesuite(self.source)
804 cg = CodeGenerator(self.filename)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000805 walk(self.ast, cg, walker=ExampleASTVisitor)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000806 self.code = cg.asConst()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000807
808 def dump(self, path):
809 """create a .pyc file"""
810 f = open(path, 'wb')
811 f.write(self._pyc_header())
812 marshal.dump(self.code, f)
813 f.close()
814
815 def _pyc_header(self):
816 # compile.c uses marshal to write a long directly, with
817 # calling the interface that would also generate a 1-byte code
818 # to indicate the type of the value. simplest way to get the
819 # same effect is to call marshal and then skip the code.
820 magic = marshal.dumps(self.MAGIC)[1:]
821 mtime = os.stat(self.filename)[stat.ST_MTIME]
822 mtime = struct.pack('i', mtime)
823 return magic + mtime
824
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000825if __name__ == "__main__":
Jeremy Hylton40245602000-02-08 21:15:48 +0000826 import getopt
827
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000828 opts, args = getopt.getopt(sys.argv[1:], 'vq')
Jeremy Hylton40245602000-02-08 21:15:48 +0000829 for k, v in opts:
830 if k == '-v':
831 ASTVisitor.VERBOSE = ASTVisitor.VERBOSE + 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000832 if k == '-q':
833 f = open('/dev/null', 'wb')
834 sys.stdout = f
Jeremy Hylton40245602000-02-08 21:15:48 +0000835 if args:
836 filename = args[0]
Jeremy Hylton53187f32000-02-08 19:01:29 +0000837 else:
838 filename = 'test.py'
839 buf = open(filename).read()
840 mod = CompiledModule(buf, filename)
841 mod.compile()
842 mod.dump(filename + 'c')