blob: e9120ccd2828bcfe592bdd51534324e71ae8cf43 [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 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:
206 args.append(".nested%d" % count)
207 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>'
346 node.varargs = node.kwargs = None
347 self._visitFuncOrLambda(node, 'Lambda')
348 return 1
349
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000350 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000351 pos = 0
352 kw = 0
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000353 if hasattr(node, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000354 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000355 self.visit(node.node)
356 for arg in node.args:
357 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000358 if isinstance(arg, ast.Keyword):
359 kw = kw + 1
360 else:
361 pos = pos + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000362 self.emit('CALL_FUNCTION', kw << 8 | pos)
363 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000364
Jeremy Hylton3050d512000-02-12 00:12:38 +0000365 def visitKeyword(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000366 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000367 self.visit(node.expr)
368 return 1
369
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000370 def visitIf(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000371 after = StackRef()
372 for test, suite in node.tests:
Jeremy Hylton40245602000-02-08 21:15:48 +0000373 if hasattr(test, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000374 self.emit('SET_LINENO', test.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000375 else:
376 print "warning", "no line number"
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000377 self.visit(test)
378 dest = StackRef()
379 self.emit('JUMP_IF_FALSE', dest)
380 self.emit('POP_TOP')
381 self.visit(suite)
382 self.emit('JUMP_FORWARD', after)
383 dest.bind(self.code.getCurInst())
384 self.emit('POP_TOP')
385 if node.else_:
386 self.visit(node.else_)
387 after.bind(self.code.getCurInst())
388 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000389
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000390 def startLoop(self):
391 l = Loop()
392 self.loops.push(l)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000393 self.emit('SETUP_LOOP', l.extentAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000394 return l
395
396 def finishLoop(self):
397 l = self.loops.pop()
398 i = self.code.getCurInst()
399 l.extentAnchor.bind(self.code.getCurInst())
400
Jeremy Hylton40245602000-02-08 21:15:48 +0000401 def visitFor(self, node):
402 # three refs needed
Jeremy Hylton40245602000-02-08 21:15:48 +0000403 anchor = StackRef()
Jeremy Hylton40245602000-02-08 21:15:48 +0000404
Jeremy Hyltona5058122000-02-14 14:14:29 +0000405 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000406 l = self.startLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000407 self.visit(node.list)
408 self.visit(ast.Const(0))
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000409 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000410 self.emit('SET_LINENO', node.lineno)
411 self.emit('FOR_LOOP', anchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000412 self.visit(node.assign)
413 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000414 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000415 anchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000416 self.emit('POP_BLOCK')
Jeremy Hylton40245602000-02-08 21:15:48 +0000417 if node.else_:
418 self.visit(node.else_)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000419 self.finishLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000420 return 1
421
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000422 def visitWhile(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000423 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000424 l = self.startLoop()
425 if node.else_:
426 lElse = StackRef()
427 else:
428 lElse = l.breakAnchor
429 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000430 if hasattr(node.test, 'lineno'):
431 self.emit('SET_LINENO', node.test.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000432 self.visit(node.test)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000433 self.emit('JUMP_IF_FALSE', lElse)
434 self.emit('POP_TOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000435 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000436 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000437 # note that lElse may be an alias for l.breakAnchor
438 lElse.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000439 self.emit('POP_TOP')
440 self.emit('POP_BLOCK')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000441 if node.else_:
442 self.visit(node.else_)
443 self.finishLoop()
444 return 1
445
446 def visitBreak(self, node):
447 if not self.loops:
448 raise SyntaxError, "'break' outside loop"
Jeremy Hyltona5058122000-02-14 14:14:29 +0000449 self.emit('SET_LINENO', node.lineno)
450 self.emit('BREAK_LOOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000451
452 def visitContinue(self, node):
453 if not self.loops:
454 raise SyntaxError, "'continue' outside loop"
455 l = self.loops.top()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000456 self.emit('SET_LINENO', node.lineno)
457 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000458
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000459 def visitTryExcept(self, node):
460 # XXX need to figure out exactly what is on the stack when an
461 # exception is raised and the first handler is checked
462 handlers = StackRef()
463 end = StackRef()
464 if node.else_:
465 lElse = StackRef()
466 else:
467 lElse = end
468 self.emit('SET_LINENO', node.lineno)
469 self.emit('SETUP_EXCEPT', handlers)
470 self.visit(node.body)
471 self.emit('POP_BLOCK')
472 self.emit('JUMP_FORWARD', lElse)
473 handlers.bind(self.code.getCurInst())
474
475 last = len(node.handlers) - 1
476 for i in range(len(node.handlers)):
477 expr, target, body = node.handlers[i]
478 if hasattr(expr, 'lineno'):
479 self.emit('SET_LINENO', expr.lineno)
480 if expr:
481 self.emit('DUP_TOP')
482 self.visit(expr)
483 self.emit('COMPARE_OP', "exception match")
484 next = StackRef()
485 self.emit('JUMP_IF_FALSE', next)
486 self.emit('POP_TOP')
487 self.emit('POP_TOP')
488 if target:
489 self.visit(target)
490 else:
491 self.emit('POP_TOP')
492 self.emit('POP_TOP')
493 self.visit(body)
494 self.emit('JUMP_FORWARD', end)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000495 if expr:
496 next.bind(self.code.getCurInst())
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000497 self.emit('POP_TOP')
498 self.emit('END_FINALLY')
499 if node.else_:
500 lElse.bind(self.code.getCurInst())
501 self.visit(node.else_)
502 end.bind(self.code.getCurInst())
503 return 1
504
505 def visitTryFinally(self, node):
506 final = StackRef()
507 self.emit('SET_LINENO', node.lineno)
508 self.emit('SETUP_FINALLY', final)
509 self.visit(node.body)
510 self.emit('POP_BLOCK')
511 self.emit('LOAD_CONST', None)
512 final.bind(self.code.getCurInst())
513 self.visit(node.final)
514 self.emit('END_FINALLY')
515 return 1
516
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000517 def visitCompare(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000518 """Comment from compile.c follows:
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000519
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000520 The following code is generated for all but the last
521 comparison in a chain:
522
523 label: on stack: opcode: jump to:
524
525 a <code to load b>
526 a, b DUP_TOP
527 a, b, b ROT_THREE
528 b, a, b COMPARE_OP
529 b, 0-or-1 JUMP_IF_FALSE L1
530 b, 1 POP_TOP
531 b
532
533 We are now ready to repeat this sequence for the next
534 comparison in the chain.
535
536 For the last we generate:
537
538 b <code to load c>
539 b, c COMPARE_OP
540 0-or-1
541
542 If there were any jumps to L1 (i.e., there was more than one
543 comparison), we generate:
544
545 0-or-1 JUMP_FORWARD L2
546 L1: b, 0 ROT_TWO
547 0, b POP_TOP
548 0
549 L2: 0-or-1
550 """
551 self.visit(node.expr)
552 # if refs are never emitted, subsequent bind call has no effect
553 l1 = StackRef()
554 l2 = StackRef()
555 for op, code in node.ops[:-1]:
556 # emit every comparison except the last
557 self.visit(code)
558 self.emit('DUP_TOP')
559 self.emit('ROT_THREE')
560 self.emit('COMPARE_OP', op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000561 # dupTop and compareOp cancel stack effect
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000562 self.emit('JUMP_IF_FALSE', l1)
563 self.emit('POP_TOP')
564 if node.ops:
565 # emit the last comparison
566 op, code = node.ops[-1]
567 self.visit(code)
568 self.emit('COMPARE_OP', op)
569 if len(node.ops) > 1:
570 self.emit('JUMP_FORWARD', l2)
571 l1.bind(self.code.getCurInst())
572 self.emit('ROT_TWO')
573 self.emit('POP_TOP')
574 l2.bind(self.code.getCurInst())
575 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000576
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000577 def visitGetattr(self, node):
578 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000579 self.emit('LOAD_ATTR', node.attrname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000580 return 1
581
582 def visitSubscript(self, node):
583 self.visit(node.expr)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000584 for sub in node.subs:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000585 self.visit(sub)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000586 if len(node.subs) > 1:
587 self.emit('BUILD_TUPLE', len(node.subs))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000588 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000589 self.emit('BINARY_SUBSCR')
590 elif node.flags == 'OP_ASSIGN':
591 self.emit('STORE_SUBSCR')
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000592 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000593 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000594 return 1
595
596 def visitSlice(self, node):
597 self.visit(node.expr)
598 slice = 0
599 if node.lower:
600 self.visit(node.lower)
601 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000602 if node.upper:
603 self.visit(node.upper)
604 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000605 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000606 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000607 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000608 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000609 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000610 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000611 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000612 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000613 raise
614 return 1
615
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000616 def visitSliceobj(self, node):
617 for child in node.nodes:
618 print child
619 self.visit(child)
620 self.emit('BUILD_SLICE', len(node.nodes))
621 return 1
622
Jeremy Hylton40245602000-02-08 21:15:48 +0000623 def visitAssign(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000624 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000625 self.visit(node.expr)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000626 dups = len(node.nodes) - 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000627 for i in range(len(node.nodes)):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000628 elt = node.nodes[i]
629 if i < dups:
630 self.emit('DUP_TOP')
Jeremy Hylton40245602000-02-08 21:15:48 +0000631 if isinstance(elt, ast.Node):
632 self.visit(elt)
633 return 1
634
635 def visitAssName(self, node):
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000636 # XXX handle OP_DELETE
Jeremy Hylton40245602000-02-08 21:15:48 +0000637 if node.flags != 'OP_ASSIGN':
638 print "oops", node.flags
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000639 self.storeName(node.name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000640
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000641 def visitAssAttr(self, node):
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000642 self.visit(node.expr)
643 if node.flags == 'OP_ASSIGN':
644 self.emit('STORE_ATTR', node.attrname)
645 elif node.flags == 'OP_DELETE':
646 self.emit('DELETE_ATTR', node.attrname)
647 else:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000648 print "warning: unexpected flags:", node.flags
649 print node
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000650 return 1
651
652 def visitAssTuple(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000653 self.emit('UNPACK_TUPLE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000654 for child in node.nodes:
655 self.visit(child)
656 return 1
657
658 visitAssList = visitAssTuple
659
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000660 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000661 self.visit(node.left)
662 self.visit(node.right)
663 self.emit(op)
664 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000665
Jeremy Hylton40245602000-02-08 21:15:48 +0000666 def unaryOp(self, node, op):
667 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000668 self.emit(op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000669 return 1
670
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000671 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000672 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000673
674 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000675 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000676
677 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000678 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000679
680 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000681 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000682
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000683 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000684 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000685
Jeremy Hylton126960b2000-02-14 21:33:10 +0000686 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000687 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000688
689 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000690 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000691
692 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000693 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000694
695 def visitInvert(self, node):
696 return self.unaryOp(node, 'UNARY_INVERT')
697
Jeremy Hylton40245602000-02-08 21:15:48 +0000698 def visitUnarySub(self, node):
699 return self.unaryOp(node, 'UNARY_NEGATIVE')
700
701 def visitUnaryAdd(self, node):
702 return self.unaryOp(node, 'UNARY_POSITIVE')
703
704 def visitUnaryInvert(self, node):
705 return self.unaryOp(node, 'UNARY_INVERT')
706
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000707 def visitNot(self, node):
708 return self.unaryOp(node, 'UNARY_NOT')
709
Jeremy Hylton40245602000-02-08 21:15:48 +0000710 def visitBackquote(self, node):
711 return self.unaryOp(node, 'UNARY_CONVERT')
712
Jeremy Hyltona5058122000-02-14 14:14:29 +0000713 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000714 self.visit(nodes[0])
715 for node in nodes[1:]:
716 self.visit(node)
717 self.emit(op)
718 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000719
720 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000721 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000722
723 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000724 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000725
726 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000727 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000728
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000729 def visitTest(self, node, jump):
730 end = StackRef()
731 for child in node.nodes[:-1]:
732 self.visit(child)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000733 self.emit(jump, end)
734 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000735 self.visit(node.nodes[-1])
736 end.bind(self.code.getCurInst())
737 return 1
738
Jeremy Hyltona5058122000-02-14 14:14:29 +0000739 def visitAssert(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000740 # XXX __debug__ and AssertionError appear to be special cases
741 # -- they are always loaded as globals even if there are local
742 # names. I guess this is a sort of renaming op.
743 skip = StackRef()
744 self.emit('SET_LINENO', node.lineno)
745 self.emit('LOAD_GLOBAL', '__debug__')
746 self.emit('JUMP_IF_FALSE', skip)
747 self.emit('POP_TOP')
748 self.visit(node.test)
749 self.emit('JUMP_IF_TRUE', skip)
750 self.emit('LOAD_GLOBAL', 'AssertionError')
751 self.visit(node.fail)
752 self.emit('RAISE_VARARGS', 2)
753 skip.bind(self.code.getCurInst())
754 self.emit('POP_TOP')
755 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000756
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000757 def visitAnd(self, node):
758 return self.visitTest(node, 'JUMP_IF_FALSE')
759
760 def visitOr(self, node):
761 return self.visitTest(node, 'JUMP_IF_TRUE')
762
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000763 def visitName(self, node):
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000764 self.loadName(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000765
766 def visitConst(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000767 self.emit('LOAD_CONST', node.value)
Jeremy Hylton40245602000-02-08 21:15:48 +0000768 return 1
769
Jeremy Hyltona5058122000-02-14 14:14:29 +0000770 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000771 self.emit('LOAD_CONST', Ellipsis)
772 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000773
Jeremy Hylton40245602000-02-08 21:15:48 +0000774 def visitTuple(self, node):
775 for elt in node.nodes:
776 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000777 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton40245602000-02-08 21:15:48 +0000778 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000779
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000780 def visitList(self, node):
781 for elt in node.nodes:
782 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000783 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000784 return 1
785
Jeremy Hyltona5058122000-02-14 14:14:29 +0000786 def visitDict(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000787 self.emit('BUILD_MAP', 0)
788 for k, v in node.items:
789 # XXX need to add set lineno when there aren't constants
790 self.emit('DUP_TOP')
791 self.visit(v)
792 self.emit('ROT_TWO')
793 self.visit(k)
794 self.emit('STORE_SUBSCR')
795 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000796
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000797 def visitReturn(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000798 self.emit('SET_LINENO', node.lineno)
799 self.visit(node.value)
800 self.emit('RETURN_VALUE')
801 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000802
803 def visitRaise(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000804 self.emit('SET_LINENO', node.lineno)
805 n = 0
806 if node.expr1:
807 self.visit(node.expr1)
808 n = n + 1
809 if node.expr2:
810 self.visit(node.expr2)
811 n = n + 1
812 if node.expr3:
813 self.visit(node.expr3)
814 n = n + 1
815 self.emit('RAISE_VARARGS', n)
816 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000817
818 def visitPrint(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000819 self.emit('SET_LINENO', node.lineno)
820 for child in node.nodes:
821 self.visit(child)
822 self.emit('PRINT_ITEM')
823 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000824
825 def visitPrintnl(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000826 self.visitPrint(node)
827 self.emit('PRINT_NEWLINE')
828 return 1
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000829
Jeremy Hyltona5058122000-02-14 14:14:29 +0000830 def visitExec(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000831 self.visit(node.expr)
832 if node.locals is None:
833 self.emit('LOAD_CONST', None)
834 else:
835 self.visit(node.locals)
836 if node.globals is None:
837 self.emit('DUP_TOP')
838 else:
839 self.visit(node.globals)
840 self.emit('EXEC_STMT')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000841
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000842class LocalNameFinder:
843 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000844 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000845 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000846 for name in names:
847 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000848
849 def getLocals(self):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000850 for elt in self.globals.items():
851 if self.names.has_elt(elt):
852 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000853 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000854
Jeremy Hyltona5058122000-02-14 14:14:29 +0000855 def visitDict(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000856 return 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000857
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000858 def visitGlobal(self, node):
859 for name in node.names:
860 self.globals.add(name)
861 return 1
862
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000863 def visitFunction(self, node):
864 self.names.add(node.name)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000865 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000866
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000867 def visitLambda(self, node):
868 return 1
869
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000870 def visitImport(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000871 for name in node.names:
872 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000873
874 def visitFrom(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 visitClassdef(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000879 self.names.add(node.name)
880 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000881
882 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000883 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000884
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000885class Loop:
886 def __init__(self):
887 self.startAnchor = StackRef()
888 self.breakAnchor = StackRef()
889 self.extentAnchor = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000890
Jeremy Hylton53187f32000-02-08 19:01:29 +0000891class CompiledModule:
892 """Store the code object for a compiled module
893
894 XXX Not clear how the code objects will be stored. Seems possible
895 that a single code attribute is sufficient, because it will
896 contains references to all the need code objects. That might be
897 messy, though.
898 """
899 MAGIC = (20121 | (ord('\r')<<16) | (ord('\n')<<24))
900
901 def __init__(self, source, filename):
902 self.source = source
903 self.filename = filename
904
905 def compile(self):
906 t = transformer.Transformer()
907 self.ast = t.parsesuite(self.source)
908 cg = CodeGenerator(self.filename)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000909 walk(self.ast, cg)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000910 self.code = cg.asConst()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000911
912 def dump(self, path):
913 """create a .pyc file"""
914 f = open(path, 'wb')
915 f.write(self._pyc_header())
916 marshal.dump(self.code, f)
917 f.close()
918
919 def _pyc_header(self):
920 # compile.c uses marshal to write a long directly, with
921 # calling the interface that would also generate a 1-byte code
922 # to indicate the type of the value. simplest way to get the
923 # same effect is to call marshal and then skip the code.
924 magic = marshal.dumps(self.MAGIC)[1:]
925 mtime = os.stat(self.filename)[stat.ST_MTIME]
926 mtime = struct.pack('i', mtime)
927 return magic + mtime
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000928
929def compile(filename):
930 buf = open(filename).read()
931 mod = CompiledModule(buf, filename)
932 mod.compile()
933 mod.dump(filename + 'c')
934
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000935if __name__ == "__main__":
Jeremy Hylton40245602000-02-08 21:15:48 +0000936 import getopt
937
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000938 VERBOSE = 0
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000939 opts, args = getopt.getopt(sys.argv[1:], 'vq')
Jeremy Hylton40245602000-02-08 21:15:48 +0000940 for k, v in opts:
941 if k == '-v':
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000942 VERBOSE = 1
Jeremy Hylton40245602000-02-08 21:15:48 +0000943 ASTVisitor.VERBOSE = ASTVisitor.VERBOSE + 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000944 if k == '-q':
945 f = open('/dev/null', 'wb')
946 sys.stdout = f
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000947 if not args:
948 print "no files to compile"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000949 else:
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000950 for filename in args:
951 if VERBOSE:
952 print filename
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000953 compile(filename)