blob: 4587bf4f3137c428234c5eac65d7fb6b4b5d47a5 [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 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
21def parse(path):
22 f = open(path)
23 src = f.read()
24 f.close()
25 t = transformer.Transformer()
26 return t.parsesuite(src)
27
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000028def walk(tree, visitor, verbose=None, walker=None):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000029 if walker:
30 w = walker()
31 else:
32 w = ASTVisitor()
Jeremy Hylton40245602000-02-08 21:15:48 +000033 if verbose is not None:
34 w.VERBOSE = verbose
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000035 w.preorder(tree, visitor)
36 return w.visitor
37
Jeremy Hylton5e0ce532000-02-10 00:47:08 +000038def dumpNode(node):
39 print node.__class__
40 for attr in dir(node):
41 if attr[0] != '_':
42 print "\t", "%-10.10s" % attr, getattr(node, attr)
43
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000044class ASTVisitor:
45 """Performs a depth-first walk of the AST
46
47 The ASTVisitor will walk the AST, performing either a preorder or
48 postorder traversal depending on which method is called.
49
50 methods:
51 preorder(tree, visitor)
52 postorder(tree, visitor)
53 tree: an instance of ast.Node
54 visitor: an instance with visitXXX methods
55
56 The ASTVisitor is responsible for walking over the tree in the
57 correct order. For each node, it checks the visitor argument for
58 a method named 'visitNodeType' where NodeType is the name of the
59 node's class, e.g. Classdef. If the method exists, it is called
60 with the node as its sole argument.
61
62 The visitor method for a particular node type can control how
63 child nodes are visited during a preorder walk. (It can't control
64 the order during a postorder walk, because it is called _after_
65 the walk has occurred.) The ASTVisitor modifies the visitor
66 argument by adding a visit method to the visitor; this method can
67 be used to visit a particular child node. If the visitor method
68 returns a true value, the ASTVisitor will not traverse the child
69 nodes.
70
71 XXX The interface for controlling the preorder walk needs to be
72 re-considered. The current interface is convenient for visitors
73 that mostly let the ASTVisitor do everything. For something like
74 a code generator, where you want to walk to occur in a specific
75 order, it's a pain to add "return 1" to the end of each method.
76
77 XXX Perhaps I can use a postorder walk for the code generator?
78 """
79
Jeremy Hylton40245602000-02-08 21:15:48 +000080 VERBOSE = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000081
82 def __init__(self):
Jeremy Hylton873bdc12000-02-17 17:56:29 +000083 self.node = None
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000084
85 def preorder(self, tree, visitor):
86 """Do preorder walk of tree using visitor"""
87 self.visitor = visitor
88 visitor.visit = self._preorder
89 self._preorder(tree)
90
91 def _preorder(self, node):
92 stop = self.dispatch(node)
93 if stop:
94 return
95 for child in node.getChildren():
96 if isinstance(child, ast.Node):
97 self._preorder(child)
98
99 def postorder(self, tree, visitor):
100 """Do preorder walk of tree using visitor"""
101 self.visitor = visitor
102 visitor.visit = self._postorder
103 self._postorder(tree)
104
105 def _postorder(self, tree):
106 for child in node.getChildren():
107 if isinstance(child, ast.Node):
108 self._preorder(child)
109 self.dispatch(node)
110
111 def dispatch(self, node):
112 self.node = node
113 className = node.__class__.__name__
114 meth = getattr(self.visitor, 'visit' + className, None)
Jeremy Hylton40245602000-02-08 21:15:48 +0000115 if self.VERBOSE > 0:
116 if self.VERBOSE == 1:
117 if meth is None:
118 print "dispatch", className
119 else:
120 print "dispatch", className, (meth and meth.__name__ or '')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000121 if meth:
122 return meth(node)
123
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000124class ExampleASTVisitor(ASTVisitor):
Jeremy Hylton9e1cd682000-02-14 23:57:56 +0000125 """Prints examples of the nodes that aren't visited
126
127 This visitor-driver is only useful for development, when it's
128 helpful to develop a visitor incremently, and get feedback on what
129 you still have to do.
130 """
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000131 examples = {}
132
133 def dispatch(self, node):
134 self.node = node
135 className = node.__class__.__name__
136 meth = getattr(self.visitor, 'visit' + className, None)
137 if self.VERBOSE > 0:
138 if self.VERBOSE == 1:
139 if meth is None:
140 print "dispatch", className
141 else:
142 print "dispatch", className, (meth and meth.__name__ or '')
143 if meth:
144 return meth(node)
145 else:
146 klass = node.__class__
147 if self.VERBOSE < 2:
148 if self.examples.has_key(klass):
149 return
150 self.examples[klass] = klass
151 print
152 print klass
153 for attr in dir(node):
154 if attr[0] != '_':
155 print "\t", "%-12.12s" % attr, getattr(node, attr)
156 print
157
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000158class CodeGenerator:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000159 """Generate bytecode for the Python VM"""
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 Hylton873bdc12000-02-17 17:56:29 +0000166 self.code = PyAssembler()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000167 self.code.setFlags(0)
Jeremy Hylton873bdc12000-02-17 17:56:29 +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):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000175 # XXX could just use self.emit = self.code.emit
176 apply(self.code.emit, args)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000177
Jeremy Hylton3050d512000-02-12 00:12:38 +0000178 def _generateFunctionOrLambdaCode(self, func):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000179 self.name = func.name
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000180
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000181 # keep a lookout for 'def foo((x,y)):'
182 args, hasTupleArg = self.generateArglist(func.argnames)
183
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000184 self.code = PyAssembler(args=args, name=func.name,
185 filename=self.filename)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000186 self.namespace = self.OPTIMIZED
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000187 if func.varargs:
188 self.code.setVarArgs()
189 if func.kwargs:
190 self.code.setKWArgs()
191 lnf = walk(func.code, LocalNameFinder(args), 0)
192 self.locals.push(lnf.getLocals())
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000193 self.emit('SET_LINENO', func.lineno)
194 if hasTupleArg:
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000195 self.generateArgUnpack(func.argnames)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000196 walk(func.code, self)
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000197
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000198 def generateArglist(self, arglist):
199 args = []
200 extra = []
201 count = 0
202 for elt in arglist:
203 if type(elt) == types.StringType:
204 args.append(elt)
205 elif type(elt) == types.TupleType:
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000206 args.append(TupleArg(count, elt))
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000207 count = count + 1
208 extra.extend(misc.flatten(elt))
209 else:
210 raise ValueError, "unexpect argument type:", elt
211 return args + extra, count
212
213 def generateArgUnpack(self, args):
214 count = 0
215 for arg in args:
216 if type(arg) == types.TupleType:
217 self.emit('LOAD_FAST', '.nested%d' % count)
218 count = count + 1
219 self.unpackTuple(arg)
220
221 def unpackTuple(self, tup):
222 self.emit('UNPACK_TUPLE', len(tup))
223 for elt in tup:
224 if type(elt) == types.TupleType:
225 self.unpackTuple(elt)
226 else:
227 self.emit('STORE_FAST', elt)
228
Jeremy Hylton3050d512000-02-12 00:12:38 +0000229 def generateFunctionCode(self, func):
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000230 """Generate code for a function body"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000231 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000232 self.emit('LOAD_CONST', None)
233 self.emit('RETURN_VALUE')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000234
Jeremy Hylton3050d512000-02-12 00:12:38 +0000235 def generateLambdaCode(self, func):
236 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000237 self.emit('RETURN_VALUE')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000238
239 def generateClassCode(self, klass):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000240 self.code = PyAssembler(name=klass.name,
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000241 filename=self.filename)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000242 self.emit('SET_LINENO', klass.lineno)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000243 lnf = walk(klass.code, LocalNameFinder(), 0)
244 self.locals.push(lnf.getLocals())
245 walk(klass.code, self)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000246 self.emit('LOAD_LOCALS')
247 self.emit('RETURN_VALUE')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000248
Jeremy Hyltona5058122000-02-14 14:14:29 +0000249 def asConst(self):
250 """Create a Python code object."""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000251 if self.namespace == self.OPTIMIZED:
252 self.code.setOptimized()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000253 return self.code.makeCodeObject()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000254
Jeremy Hylton40245602000-02-08 21:15:48 +0000255 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000256 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000257
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000258 def _nameOp(self, prefix, name):
259 if self.isLocalName(name):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000260 if self.namespace == self.OPTIMIZED:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000261 self.emit(prefix + '_FAST', name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000262 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000263 self.emit(prefix + '_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000264 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000265 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000266
267 def storeName(self, name):
268 self._nameOp('STORE', name)
269
270 def loadName(self, name):
271 self._nameOp('LOAD', name)
272
273 def delName(self, name):
274 self._nameOp('DELETE', name)
275
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000276 def visitNULL(self, node):
277 """Method exists only to stop warning in -v mode"""
278 pass
279
280 visitStmt = visitNULL
281 visitGlobal = visitNULL
282
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000283 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000284 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000285 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000286 return 1
287
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000288 def visitPass(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000289 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000290
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000291 def visitModule(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000292 lnf = walk(node.node, LocalNameFinder(), 0)
293 self.locals.push(lnf.getLocals())
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000294 self.visit(node.node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000295 self.emit('LOAD_CONST', None)
296 self.emit('RETURN_VALUE')
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000297 return 1
298
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000299 def visitImport(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000300 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000301 for name in node.names:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000302 self.emit('IMPORT_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000303 self.storeName(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000304
305 def visitFrom(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000306 self.emit('SET_LINENO', node.lineno)
307 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000308 for name in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000309 if name == '*':
310 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000311 self.emit('IMPORT_FROM', name)
312 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000313
Jeremy Hylton3050d512000-02-12 00:12:38 +0000314 def visitClassdef(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000315 self.emit('SET_LINENO', node.lineno)
316 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000317 for base in node.bases:
318 self.visit(base)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000319 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton3050d512000-02-12 00:12:38 +0000320 classBody = CodeGenerator(self.filename)
321 classBody.generateClassCode(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000322 self.emit('LOAD_CONST', classBody)
323 self.emit('MAKE_FUNCTION', 0)
324 self.emit('CALL_FUNCTION', 0)
325 self.emit('BUILD_CLASS')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000326 self.storeName(node.name)
327 return 1
328
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000329 def _visitFuncOrLambda(self, node, kind):
330 """Code common to Function and Lambda nodes"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000331 codeBody = CodeGenerator(self.filename)
332 getattr(codeBody, 'generate%sCode' % kind)(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000333 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000334 for default in node.defaults:
335 self.visit(default)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000336 self.emit('LOAD_CONST', codeBody)
337 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000338
339 def visitFunction(self, node):
340 self._visitFuncOrLambda(node, 'Function')
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000341 self.storeName(node.name)
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000342 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000343
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000344 def visitLambda(self, node):
345 node.name = '<lambda>'
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000346 self._visitFuncOrLambda(node, 'Lambda')
347 return 1
348
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000349 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000350 pos = 0
351 kw = 0
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000352 if hasattr(node, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000353 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000354 self.visit(node.node)
355 for arg in node.args:
356 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000357 if isinstance(arg, ast.Keyword):
358 kw = kw + 1
359 else:
360 pos = pos + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000361 self.emit('CALL_FUNCTION', kw << 8 | pos)
362 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000363
Jeremy Hylton3050d512000-02-12 00:12:38 +0000364 def visitKeyword(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000365 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000366 self.visit(node.expr)
367 return 1
368
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000369 def visitIf(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000370 after = StackRef()
371 for test, suite in node.tests:
Jeremy Hylton40245602000-02-08 21:15:48 +0000372 if hasattr(test, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000373 self.emit('SET_LINENO', test.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000374 else:
375 print "warning", "no line number"
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000376 self.visit(test)
377 dest = StackRef()
378 self.emit('JUMP_IF_FALSE', dest)
379 self.emit('POP_TOP')
380 self.visit(suite)
381 self.emit('JUMP_FORWARD', after)
382 dest.bind(self.code.getCurInst())
383 self.emit('POP_TOP')
384 if node.else_:
385 self.visit(node.else_)
386 after.bind(self.code.getCurInst())
387 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000388
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000389 def startLoop(self):
390 l = Loop()
391 self.loops.push(l)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000392 self.emit('SETUP_LOOP', l.extentAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000393 return l
394
395 def finishLoop(self):
396 l = self.loops.pop()
397 i = self.code.getCurInst()
398 l.extentAnchor.bind(self.code.getCurInst())
399
Jeremy Hylton40245602000-02-08 21:15:48 +0000400 def visitFor(self, node):
401 # three refs needed
Jeremy Hylton40245602000-02-08 21:15:48 +0000402 anchor = StackRef()
Jeremy Hylton40245602000-02-08 21:15:48 +0000403
Jeremy Hyltona5058122000-02-14 14:14:29 +0000404 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000405 l = self.startLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000406 self.visit(node.list)
407 self.visit(ast.Const(0))
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000408 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000409 self.emit('SET_LINENO', node.lineno)
410 self.emit('FOR_LOOP', anchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000411 self.visit(node.assign)
412 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000413 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000414 anchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000415 self.emit('POP_BLOCK')
Jeremy Hylton40245602000-02-08 21:15:48 +0000416 if node.else_:
417 self.visit(node.else_)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000418 self.finishLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000419 return 1
420
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000421 def visitWhile(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000422 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000423 l = self.startLoop()
424 if node.else_:
425 lElse = StackRef()
426 else:
427 lElse = l.breakAnchor
428 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000429 if hasattr(node.test, 'lineno'):
430 self.emit('SET_LINENO', node.test.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000431 self.visit(node.test)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000432 self.emit('JUMP_IF_FALSE', lElse)
433 self.emit('POP_TOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000434 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000435 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000436 # note that lElse may be an alias for l.breakAnchor
437 lElse.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000438 self.emit('POP_TOP')
439 self.emit('POP_BLOCK')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000440 if node.else_:
441 self.visit(node.else_)
442 self.finishLoop()
443 return 1
444
445 def visitBreak(self, node):
446 if not self.loops:
447 raise SyntaxError, "'break' outside loop"
Jeremy Hyltona5058122000-02-14 14:14:29 +0000448 self.emit('SET_LINENO', node.lineno)
449 self.emit('BREAK_LOOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000450
451 def visitContinue(self, node):
452 if not self.loops:
453 raise SyntaxError, "'continue' outside loop"
454 l = self.loops.top()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000455 self.emit('SET_LINENO', node.lineno)
456 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000457
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000458 def visitTryExcept(self, node):
459 # XXX need to figure out exactly what is on the stack when an
460 # exception is raised and the first handler is checked
461 handlers = StackRef()
462 end = StackRef()
463 if node.else_:
464 lElse = StackRef()
465 else:
466 lElse = end
467 self.emit('SET_LINENO', node.lineno)
468 self.emit('SETUP_EXCEPT', handlers)
469 self.visit(node.body)
470 self.emit('POP_BLOCK')
471 self.emit('JUMP_FORWARD', lElse)
472 handlers.bind(self.code.getCurInst())
473
474 last = len(node.handlers) - 1
475 for i in range(len(node.handlers)):
476 expr, target, body = node.handlers[i]
477 if hasattr(expr, 'lineno'):
478 self.emit('SET_LINENO', expr.lineno)
479 if expr:
480 self.emit('DUP_TOP')
481 self.visit(expr)
482 self.emit('COMPARE_OP', "exception match")
483 next = StackRef()
484 self.emit('JUMP_IF_FALSE', next)
485 self.emit('POP_TOP')
486 self.emit('POP_TOP')
487 if target:
488 self.visit(target)
489 else:
490 self.emit('POP_TOP')
491 self.emit('POP_TOP')
492 self.visit(body)
493 self.emit('JUMP_FORWARD', end)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000494 if expr:
495 next.bind(self.code.getCurInst())
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000496 self.emit('POP_TOP')
497 self.emit('END_FINALLY')
498 if node.else_:
499 lElse.bind(self.code.getCurInst())
500 self.visit(node.else_)
501 end.bind(self.code.getCurInst())
502 return 1
503
504 def visitTryFinally(self, node):
505 final = StackRef()
506 self.emit('SET_LINENO', node.lineno)
507 self.emit('SETUP_FINALLY', final)
508 self.visit(node.body)
509 self.emit('POP_BLOCK')
510 self.emit('LOAD_CONST', None)
511 final.bind(self.code.getCurInst())
512 self.visit(node.final)
513 self.emit('END_FINALLY')
514 return 1
515
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000516 def visitCompare(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000517 """Comment from compile.c follows:
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000518
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000519 The following code is generated for all but the last
520 comparison in a chain:
521
522 label: on stack: opcode: jump to:
523
524 a <code to load b>
525 a, b DUP_TOP
526 a, b, b ROT_THREE
527 b, a, b COMPARE_OP
528 b, 0-or-1 JUMP_IF_FALSE L1
529 b, 1 POP_TOP
530 b
531
532 We are now ready to repeat this sequence for the next
533 comparison in the chain.
534
535 For the last we generate:
536
537 b <code to load c>
538 b, c COMPARE_OP
539 0-or-1
540
541 If there were any jumps to L1 (i.e., there was more than one
542 comparison), we generate:
543
544 0-or-1 JUMP_FORWARD L2
545 L1: b, 0 ROT_TWO
546 0, b POP_TOP
547 0
548 L2: 0-or-1
549 """
550 self.visit(node.expr)
551 # if refs are never emitted, subsequent bind call has no effect
552 l1 = StackRef()
553 l2 = StackRef()
554 for op, code in node.ops[:-1]:
555 # emit every comparison except the last
556 self.visit(code)
557 self.emit('DUP_TOP')
558 self.emit('ROT_THREE')
559 self.emit('COMPARE_OP', op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000560 # dupTop and compareOp cancel stack effect
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000561 self.emit('JUMP_IF_FALSE', l1)
562 self.emit('POP_TOP')
563 if node.ops:
564 # emit the last comparison
565 op, code = node.ops[-1]
566 self.visit(code)
567 self.emit('COMPARE_OP', op)
568 if len(node.ops) > 1:
569 self.emit('JUMP_FORWARD', l2)
570 l1.bind(self.code.getCurInst())
571 self.emit('ROT_TWO')
572 self.emit('POP_TOP')
573 l2.bind(self.code.getCurInst())
574 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000575
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000576 def visitGetattr(self, node):
577 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000578 self.emit('LOAD_ATTR', node.attrname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000579 return 1
580
581 def visitSubscript(self, node):
582 self.visit(node.expr)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000583 for sub in node.subs:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000584 self.visit(sub)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000585 if len(node.subs) > 1:
586 self.emit('BUILD_TUPLE', len(node.subs))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000587 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000588 self.emit('BINARY_SUBSCR')
589 elif node.flags == 'OP_ASSIGN':
590 self.emit('STORE_SUBSCR')
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000591 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000592 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000593 return 1
594
595 def visitSlice(self, node):
596 self.visit(node.expr)
597 slice = 0
598 if node.lower:
599 self.visit(node.lower)
600 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000601 if node.upper:
602 self.visit(node.upper)
603 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000604 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000605 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000606 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000607 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000608 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000609 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000610 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000611 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000612 raise
613 return 1
614
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000615 def visitSliceobj(self, node):
616 for child in node.nodes:
617 print child
618 self.visit(child)
619 self.emit('BUILD_SLICE', len(node.nodes))
620 return 1
621
Jeremy Hylton40245602000-02-08 21:15:48 +0000622 def visitAssign(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000623 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000624 self.visit(node.expr)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000625 dups = len(node.nodes) - 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000626 for i in range(len(node.nodes)):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000627 elt = node.nodes[i]
628 if i < dups:
629 self.emit('DUP_TOP')
Jeremy Hylton40245602000-02-08 21:15:48 +0000630 if isinstance(elt, ast.Node):
631 self.visit(elt)
632 return 1
633
634 def visitAssName(self, node):
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000635 if node.flags == 'OP_ASSIGN':
636 self.storeName(node.name)
637 elif node.flags == 'OP_DELETE':
638 self.delName(node.name)
639 else:
Jeremy Hylton40245602000-02-08 21:15:48 +0000640 print "oops", node.flags
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000641 return 1
Jeremy Hylton40245602000-02-08 21:15:48 +0000642
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000643 def visitAssAttr(self, node):
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000644 self.visit(node.expr)
645 if node.flags == 'OP_ASSIGN':
646 self.emit('STORE_ATTR', node.attrname)
647 elif node.flags == 'OP_DELETE':
648 self.emit('DELETE_ATTR', node.attrname)
649 else:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000650 print "warning: unexpected flags:", node.flags
651 print node
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000652 return 1
653
654 def visitAssTuple(self, node):
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000655 if findOp(node) != 'OP_DELETE':
656 self.emit('UNPACK_TUPLE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000657 for child in node.nodes:
658 self.visit(child)
659 return 1
660
661 visitAssList = visitAssTuple
662
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000663 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000664 self.visit(node.left)
665 self.visit(node.right)
666 self.emit(op)
667 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000668
Jeremy Hylton40245602000-02-08 21:15:48 +0000669 def unaryOp(self, node, op):
670 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000671 self.emit(op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000672 return 1
673
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000674 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000675 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000676
677 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000678 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000679
680 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000681 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000682
683 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000684 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000685
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000686 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000687 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000688
Jeremy Hylton126960b2000-02-14 21:33:10 +0000689 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000690 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000691
692 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000693 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000694
695 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000696 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000697
698 def visitInvert(self, node):
699 return self.unaryOp(node, 'UNARY_INVERT')
700
Jeremy Hylton40245602000-02-08 21:15:48 +0000701 def visitUnarySub(self, node):
702 return self.unaryOp(node, 'UNARY_NEGATIVE')
703
704 def visitUnaryAdd(self, node):
705 return self.unaryOp(node, 'UNARY_POSITIVE')
706
707 def visitUnaryInvert(self, node):
708 return self.unaryOp(node, 'UNARY_INVERT')
709
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000710 def visitNot(self, node):
711 return self.unaryOp(node, 'UNARY_NOT')
712
Jeremy Hylton40245602000-02-08 21:15:48 +0000713 def visitBackquote(self, node):
714 return self.unaryOp(node, 'UNARY_CONVERT')
715
Jeremy Hyltona5058122000-02-14 14:14:29 +0000716 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000717 self.visit(nodes[0])
718 for node in nodes[1:]:
719 self.visit(node)
720 self.emit(op)
721 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000722
723 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000724 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000725
726 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000727 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000728
729 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000730 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000731
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000732 def visitTest(self, node, jump):
733 end = StackRef()
734 for child in node.nodes[:-1]:
735 self.visit(child)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000736 self.emit(jump, end)
737 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000738 self.visit(node.nodes[-1])
739 end.bind(self.code.getCurInst())
740 return 1
741
Jeremy Hyltona5058122000-02-14 14:14:29 +0000742 def visitAssert(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000743 # XXX __debug__ and AssertionError appear to be special cases
744 # -- they are always loaded as globals even if there are local
745 # names. I guess this is a sort of renaming op.
746 skip = StackRef()
747 self.emit('SET_LINENO', node.lineno)
748 self.emit('LOAD_GLOBAL', '__debug__')
749 self.emit('JUMP_IF_FALSE', skip)
750 self.emit('POP_TOP')
751 self.visit(node.test)
752 self.emit('JUMP_IF_TRUE', skip)
753 self.emit('LOAD_GLOBAL', 'AssertionError')
754 self.visit(node.fail)
755 self.emit('RAISE_VARARGS', 2)
756 skip.bind(self.code.getCurInst())
757 self.emit('POP_TOP')
758 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000759
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000760 def visitAnd(self, node):
761 return self.visitTest(node, 'JUMP_IF_FALSE')
762
763 def visitOr(self, node):
764 return self.visitTest(node, 'JUMP_IF_TRUE')
765
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000766 def visitName(self, node):
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000767 self.loadName(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000768
769 def visitConst(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000770 self.emit('LOAD_CONST', node.value)
Jeremy Hylton40245602000-02-08 21:15:48 +0000771 return 1
772
Jeremy Hyltona5058122000-02-14 14:14:29 +0000773 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000774 self.emit('LOAD_CONST', Ellipsis)
775 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000776
Jeremy Hylton40245602000-02-08 21:15:48 +0000777 def visitTuple(self, node):
778 for elt in node.nodes:
779 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000780 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton40245602000-02-08 21:15:48 +0000781 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000782
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000783 def visitList(self, node):
784 for elt in node.nodes:
785 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000786 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000787 return 1
788
Jeremy Hyltona5058122000-02-14 14:14:29 +0000789 def visitDict(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000790 self.emit('BUILD_MAP', 0)
791 for k, v in node.items:
792 # XXX need to add set lineno when there aren't constants
793 self.emit('DUP_TOP')
794 self.visit(v)
795 self.emit('ROT_TWO')
796 self.visit(k)
797 self.emit('STORE_SUBSCR')
798 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000799
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000800 def visitReturn(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000801 self.emit('SET_LINENO', node.lineno)
802 self.visit(node.value)
803 self.emit('RETURN_VALUE')
804 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000805
806 def visitRaise(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000807 self.emit('SET_LINENO', node.lineno)
808 n = 0
809 if node.expr1:
810 self.visit(node.expr1)
811 n = n + 1
812 if node.expr2:
813 self.visit(node.expr2)
814 n = n + 1
815 if node.expr3:
816 self.visit(node.expr3)
817 n = n + 1
818 self.emit('RAISE_VARARGS', n)
819 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000820
821 def visitPrint(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000822 self.emit('SET_LINENO', node.lineno)
823 for child in node.nodes:
824 self.visit(child)
825 self.emit('PRINT_ITEM')
826 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000827
828 def visitPrintnl(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000829 self.visitPrint(node)
830 self.emit('PRINT_NEWLINE')
831 return 1
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000832
Jeremy Hyltona5058122000-02-14 14:14:29 +0000833 def visitExec(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000834 self.visit(node.expr)
835 if node.locals is None:
836 self.emit('LOAD_CONST', None)
837 else:
838 self.visit(node.locals)
839 if node.globals is None:
840 self.emit('DUP_TOP')
841 else:
842 self.visit(node.globals)
843 self.emit('EXEC_STMT')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000844 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000845
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000846class LocalNameFinder:
847 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000848 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000849 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000850 for name in names:
851 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000852
853 def getLocals(self):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000854 for elt in self.globals.items():
855 if self.names.has_elt(elt):
856 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000857 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000858
Jeremy Hyltona5058122000-02-14 14:14:29 +0000859 def visitDict(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000860 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000861
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000862 def visitGlobal(self, node):
863 for name in node.names:
864 self.globals.add(name)
865 return 1
866
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000867 def visitFunction(self, node):
868 self.names.add(node.name)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000869 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000870
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000871 def visitLambda(self, node):
872 return 1
873
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000874 def visitImport(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000875 for name in node.names:
876 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000877
878 def visitFrom(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000879 for name in node.names:
880 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000881
882 def visitClassdef(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000883 self.names.add(node.name)
884 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000885
886 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000887 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000888
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000889class OpFinder:
890 def __init__(self):
891 self.op = None
892 def visitAssName(self, node):
893 if self.op is None:
894 self.op = node.flags
895 elif self.op != node.flags:
896 raise ValueError, "mixed ops in stmt"
897
898def findOp(node):
899 v = OpFinder()
900 walk(node, v)
901 return v.op
902
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000903class Loop:
904 def __init__(self):
905 self.startAnchor = StackRef()
906 self.breakAnchor = StackRef()
907 self.extentAnchor = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000908
Jeremy Hylton53187f32000-02-08 19:01:29 +0000909class CompiledModule:
910 """Store the code object for a compiled module
911
912 XXX Not clear how the code objects will be stored. Seems possible
913 that a single code attribute is sufficient, because it will
914 contains references to all the need code objects. That might be
915 messy, though.
916 """
917 MAGIC = (20121 | (ord('\r')<<16) | (ord('\n')<<24))
918
919 def __init__(self, source, filename):
920 self.source = source
921 self.filename = filename
922
923 def compile(self):
924 t = transformer.Transformer()
925 self.ast = t.parsesuite(self.source)
926 cg = CodeGenerator(self.filename)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000927 walk(self.ast, cg)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000928 self.code = cg.asConst()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000929
930 def dump(self, path):
931 """create a .pyc file"""
932 f = open(path, 'wb')
933 f.write(self._pyc_header())
934 marshal.dump(self.code, f)
935 f.close()
936
937 def _pyc_header(self):
938 # compile.c uses marshal to write a long directly, with
939 # calling the interface that would also generate a 1-byte code
940 # to indicate the type of the value. simplest way to get the
941 # same effect is to call marshal and then skip the code.
942 magic = marshal.dumps(self.MAGIC)[1:]
943 mtime = os.stat(self.filename)[stat.ST_MTIME]
944 mtime = struct.pack('i', mtime)
945 return magic + mtime
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000946
947def compile(filename):
948 buf = open(filename).read()
949 mod = CompiledModule(buf, filename)
950 mod.compile()
951 mod.dump(filename + 'c')
952
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000953if __name__ == "__main__":
Jeremy Hylton40245602000-02-08 21:15:48 +0000954 import getopt
955
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000956 VERBOSE = 0
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000957 opts, args = getopt.getopt(sys.argv[1:], 'vq')
Jeremy Hylton40245602000-02-08 21:15:48 +0000958 for k, v in opts:
959 if k == '-v':
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000960 VERBOSE = 1
Jeremy Hylton40245602000-02-08 21:15:48 +0000961 ASTVisitor.VERBOSE = ASTVisitor.VERBOSE + 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000962 if k == '-q':
963 f = open('/dev/null', 'wb')
964 sys.stdout = f
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000965 if not args:
966 print "no files to compile"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000967 else:
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000968 for filename in args:
969 if VERBOSE:
970 print filename
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000971 compile(filename)