blob: 9b9ee16dffa63b5a039abba82d88a94ded91d46f [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):
83 self.node = None
84
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 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
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000181
182 # keep a lookout for 'def foo((x,y)):'
183 args, hasTupleArg = self.generateArglist(func.argnames)
184
Jeremy Hyltona5058122000-02-14 14:14:29 +0000185 self.code = PyAssembler(args=args, name=func.name,
Jeremy Hylton3050d512000-02-12 00:12:38 +0000186 filename=filename)
187 self.namespace = self.OPTIMIZED
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000188 if func.varargs:
189 self.code.setVarArgs()
190 if func.kwargs:
191 self.code.setKWArgs()
192 lnf = walk(func.code, LocalNameFinder(args), 0)
193 self.locals.push(lnf.getLocals())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000194 self.emit('SET_LINENO', func.lineno)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000195 if hasTupleArg:
196 self.generateArgUnpack(func.argnames)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000197 walk(func.code, self)
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000198
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000199 def generateArglist(self, arglist):
200 args = []
201 extra = []
202 count = 0
203 for elt in arglist:
204 if type(elt) == types.StringType:
205 args.append(elt)
206 elif type(elt) == types.TupleType:
207 args.append(".nested%d" % count)
208 count = count + 1
209 extra.extend(misc.flatten(elt))
210 else:
211 raise ValueError, "unexpect argument type:", elt
212 return args + extra, count
213
214 def generateArgUnpack(self, args):
215 count = 0
216 for arg in args:
217 if type(arg) == types.TupleType:
218 self.emit('LOAD_FAST', '.nested%d' % count)
219 count = count + 1
220 self.unpackTuple(arg)
221
222 def unpackTuple(self, tup):
223 self.emit('UNPACK_TUPLE', len(tup))
224 for elt in tup:
225 if type(elt) == types.TupleType:
226 self.unpackTuple(elt)
227 else:
228 self.emit('STORE_FAST', elt)
229
Jeremy Hylton3050d512000-02-12 00:12:38 +0000230 def generateFunctionCode(self, func):
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000231 """Generate code for a function body"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000232 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000233 self.emit('LOAD_CONST', None)
234 self.emit('RETURN_VALUE')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000235
Jeremy Hylton3050d512000-02-12 00:12:38 +0000236 def generateLambdaCode(self, func):
237 self._generateFunctionOrLambdaCode(func)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000238 self.emit('RETURN_VALUE')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000239
240 def generateClassCode(self, klass):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000241 self.code = PyAssembler(name=klass.name,
Jeremy Hylton3050d512000-02-12 00:12:38 +0000242 filename=filename)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000243 self.emit('SET_LINENO', klass.lineno)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000244 lnf = walk(klass.code, LocalNameFinder(), 0)
245 self.locals.push(lnf.getLocals())
246 walk(klass.code, self)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000247 self.emit('LOAD_LOCALS')
248 self.emit('RETURN_VALUE')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000249
Jeremy Hyltona5058122000-02-14 14:14:29 +0000250 def asConst(self):
251 """Create a Python code object."""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000252 if self.namespace == self.OPTIMIZED:
253 self.code.setOptimized()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000254 return self.code.makeCodeObject()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000255
Jeremy Hylton40245602000-02-08 21:15:48 +0000256 def isLocalName(self, name):
257 return self.locals.top().has_elt(name)
258
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000259 def _nameOp(self, prefix, name):
260 if self.isLocalName(name):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000261 if self.namespace == self.OPTIMIZED:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000262 self.emit(prefix + '_FAST', name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000263 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000264 self.emit(prefix + '_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000265 else:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000266 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000267
268 def storeName(self, name):
269 self._nameOp('STORE', name)
270
271 def loadName(self, name):
272 self._nameOp('LOAD', name)
273
274 def delName(self, name):
275 self._nameOp('DELETE', name)
276
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000277 def visitNULL(self, node):
278 """Method exists only to stop warning in -v mode"""
279 pass
280
281 visitStmt = visitNULL
282 visitGlobal = visitNULL
283
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000284 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000285 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000286 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000287 return 1
288
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000289 def visitPass(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000290 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000291
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000292 def visitModule(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000293 lnf = walk(node.node, LocalNameFinder(), 0)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000294 self.locals.push(lnf.getLocals())
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000295 self.visit(node.node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000296 self.emit('LOAD_CONST', None)
297 self.emit('RETURN_VALUE')
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000298 return 1
299
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000300 def visitImport(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000301 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000302 for name in node.names:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000303 self.emit('IMPORT_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000304 self.storeName(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000305
306 def visitFrom(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000307 self.emit('SET_LINENO', node.lineno)
308 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000309 for name in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000310 if name == '*':
311 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000312 self.emit('IMPORT_FROM', name)
313 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000314
Jeremy Hylton3050d512000-02-12 00:12:38 +0000315 def visitClassdef(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000316 self.emit('SET_LINENO', node.lineno)
317 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000318 for base in node.bases:
319 self.visit(base)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000320 self.emit('BUILD_TUPLE', len(node.bases))
Jeremy Hylton3050d512000-02-12 00:12:38 +0000321 classBody = CodeGenerator(self.filename)
322 classBody.generateClassCode(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000323 self.emit('LOAD_CONST', classBody)
324 self.emit('MAKE_FUNCTION', 0)
325 self.emit('CALL_FUNCTION', 0)
326 self.emit('BUILD_CLASS')
Jeremy Hylton3050d512000-02-12 00:12:38 +0000327 self.storeName(node.name)
328 return 1
329
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000330 def _visitFuncOrLambda(self, node, kind):
331 """Code common to Function and Lambda nodes"""
Jeremy Hylton3050d512000-02-12 00:12:38 +0000332 codeBody = CodeGenerator(self.filename)
333 getattr(codeBody, 'generate%sCode' % kind)(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000334 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000335 for default in node.defaults:
336 self.visit(default)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000337 self.emit('LOAD_CONST', codeBody)
338 self.emit('MAKE_FUNCTION', len(node.defaults))
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000339
340 def visitFunction(self, node):
341 self._visitFuncOrLambda(node, 'Function')
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000342 self.storeName(node.name)
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000343 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000344
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000345 def visitLambda(self, node):
346 node.name = '<lambda>'
347 node.varargs = node.kwargs = None
348 self._visitFuncOrLambda(node, 'Lambda')
349 return 1
350
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000351 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000352 pos = 0
353 kw = 0
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000354 if hasattr(node, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000355 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000356 self.visit(node.node)
357 for arg in node.args:
358 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000359 if isinstance(arg, ast.Keyword):
360 kw = kw + 1
361 else:
362 pos = pos + 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000363 self.emit('CALL_FUNCTION', kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000364 return 1
365
Jeremy Hylton3050d512000-02-12 00:12:38 +0000366 def visitKeyword(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000367 self.emit('LOAD_CONST', node.name)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000368 self.visit(node.expr)
369 return 1
370
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000371 def visitIf(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000372 after = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000373 for test, suite in node.tests:
Jeremy Hylton40245602000-02-08 21:15:48 +0000374 if hasattr(test, 'lineno'):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000375 self.emit('SET_LINENO', test.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000376 else:
377 print "warning", "no line number"
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000378 self.visit(test)
Jeremy Hylton40245602000-02-08 21:15:48 +0000379 dest = StackRef()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000380 self.emit('JUMP_IF_FALSE', dest)
381 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000382 self.visit(suite)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000383 self.emit('JUMP_FORWARD', after)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000384 dest.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000385 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000386 if node.else_:
387 self.visit(node.else_)
388 after.bind(self.code.getCurInst())
389 return 1
390
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000391 def startLoop(self):
392 l = Loop()
393 self.loops.push(l)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000394 self.emit('SETUP_LOOP', l.extentAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000395 return l
396
397 def finishLoop(self):
398 l = self.loops.pop()
399 i = self.code.getCurInst()
400 l.extentAnchor.bind(self.code.getCurInst())
401
Jeremy Hylton40245602000-02-08 21:15:48 +0000402 def visitFor(self, node):
403 # three refs needed
Jeremy Hylton40245602000-02-08 21:15:48 +0000404 anchor = StackRef()
Jeremy Hylton40245602000-02-08 21:15:48 +0000405
Jeremy Hyltona5058122000-02-14 14:14:29 +0000406 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000407 l = self.startLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000408 self.visit(node.list)
409 self.visit(ast.Const(0))
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000410 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000411 self.emit('SET_LINENO', node.lineno)
412 self.emit('FOR_LOOP', anchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000413 self.visit(node.assign)
414 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000415 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton40245602000-02-08 21:15:48 +0000416 anchor.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000417 self.emit('POP_BLOCK')
Jeremy Hylton40245602000-02-08 21:15:48 +0000418 if node.else_:
419 self.visit(node.else_)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000420 self.finishLoop()
Jeremy Hylton40245602000-02-08 21:15:48 +0000421 return 1
422
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000423 def visitWhile(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000424 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000425 l = self.startLoop()
426 if node.else_:
427 lElse = StackRef()
428 else:
429 lElse = l.breakAnchor
430 l.startAnchor.bind(self.code.getCurInst())
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000431 if hasattr(node.test, 'lineno'):
432 self.emit('SET_LINENO', node.test.lineno)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000433 self.visit(node.test)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000434 self.emit('JUMP_IF_FALSE', lElse)
435 self.emit('POP_TOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000436 self.visit(node.body)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000437 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000438 # note that lElse may be an alias for l.breakAnchor
439 lElse.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000440 self.emit('POP_TOP')
441 self.emit('POP_BLOCK')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000442 if node.else_:
443 self.visit(node.else_)
444 self.finishLoop()
445 return 1
446
447 def visitBreak(self, node):
448 if not self.loops:
449 raise SyntaxError, "'break' outside loop"
Jeremy Hyltona5058122000-02-14 14:14:29 +0000450 self.emit('SET_LINENO', node.lineno)
451 self.emit('BREAK_LOOP')
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000452
453 def visitContinue(self, node):
454 if not self.loops:
455 raise SyntaxError, "'continue' outside loop"
456 l = self.loops.top()
Jeremy Hyltona5058122000-02-14 14:14:29 +0000457 self.emit('SET_LINENO', node.lineno)
458 self.emit('JUMP_ABSOLUTE', l.startAnchor)
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000459
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000460 def visitTryExcept(self, node):
461 # XXX need to figure out exactly what is on the stack when an
462 # exception is raised and the first handler is checked
463 handlers = StackRef()
464 end = StackRef()
465 if node.else_:
466 lElse = StackRef()
467 else:
468 lElse = end
469 self.emit('SET_LINENO', node.lineno)
470 self.emit('SETUP_EXCEPT', handlers)
471 self.visit(node.body)
472 self.emit('POP_BLOCK')
473 self.emit('JUMP_FORWARD', lElse)
474 handlers.bind(self.code.getCurInst())
475
476 last = len(node.handlers) - 1
477 for i in range(len(node.handlers)):
478 expr, target, body = node.handlers[i]
479 if hasattr(expr, 'lineno'):
480 self.emit('SET_LINENO', expr.lineno)
481 if expr:
482 self.emit('DUP_TOP')
483 self.visit(expr)
484 self.emit('COMPARE_OP', "exception match")
485 next = StackRef()
486 self.emit('JUMP_IF_FALSE', next)
487 self.emit('POP_TOP')
488 self.emit('POP_TOP')
489 if target:
490 self.visit(target)
491 else:
492 self.emit('POP_TOP')
493 self.emit('POP_TOP')
494 self.visit(body)
495 self.emit('JUMP_FORWARD', end)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000496 if expr:
497 next.bind(self.code.getCurInst())
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000498 self.emit('POP_TOP')
499 self.emit('END_FINALLY')
500 if node.else_:
501 lElse.bind(self.code.getCurInst())
502 self.visit(node.else_)
503 end.bind(self.code.getCurInst())
504 return 1
505
506 def visitTryFinally(self, node):
507 final = StackRef()
508 self.emit('SET_LINENO', node.lineno)
509 self.emit('SETUP_FINALLY', final)
510 self.visit(node.body)
511 self.emit('POP_BLOCK')
512 self.emit('LOAD_CONST', None)
513 final.bind(self.code.getCurInst())
514 self.visit(node.final)
515 self.emit('END_FINALLY')
516 return 1
517
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000518 def visitCompare(self, node):
519 """Comment from compile.c follows:
520
521 The following code is generated for all but the last
522 comparison in a chain:
523
524 label: on stack: opcode: jump to:
525
526 a <code to load b>
527 a, b DUP_TOP
528 a, b, b ROT_THREE
529 b, a, b COMPARE_OP
530 b, 0-or-1 JUMP_IF_FALSE L1
531 b, 1 POP_TOP
532 b
533
534 We are now ready to repeat this sequence for the next
535 comparison in the chain.
536
537 For the last we generate:
538
539 b <code to load c>
540 b, c COMPARE_OP
541 0-or-1
542
543 If there were any jumps to L1 (i.e., there was more than one
544 comparison), we generate:
545
546 0-or-1 JUMP_FORWARD L2
547 L1: b, 0 ROT_TWO
548 0, b POP_TOP
549 0
550 L2: 0-or-1
551 """
552 self.visit(node.expr)
553 # if refs are never emitted, subsequent bind call has no effect
Jeremy Hylton40245602000-02-08 21:15:48 +0000554 l1 = StackRef()
555 l2 = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000556 for op, code in node.ops[:-1]:
557 # emit every comparison except the last
558 self.visit(code)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000559 self.emit('DUP_TOP')
560 self.emit('ROT_THREE')
561 self.emit('COMPARE_OP', op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000562 # dupTop and compareOp cancel stack effect
Jeremy Hyltona5058122000-02-14 14:14:29 +0000563 self.emit('JUMP_IF_FALSE', l1)
564 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000565 if node.ops:
566 # emit the last comparison
567 op, code = node.ops[-1]
568 self.visit(code)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000569 self.emit('COMPARE_OP', op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000570 if len(node.ops) > 1:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000571 self.emit('JUMP_FORWARD', l2)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000572 l1.bind(self.code.getCurInst())
Jeremy Hyltona5058122000-02-14 14:14:29 +0000573 self.emit('ROT_TWO')
574 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000575 l2.bind(self.code.getCurInst())
576 return 1
577
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000578 def visitGetattr(self, node):
579 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000580 self.emit('LOAD_ATTR', node.attrname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000581 return 1
582
583 def visitSubscript(self, node):
584 self.visit(node.expr)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000585 for sub in node.subs:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000586 self.visit(sub)
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000587 if len(node.subs) > 1:
588 self.emit('BUILD_TUPLE', len(node.subs))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000589 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000590 self.emit('BINARY_SUBSCR')
591 elif node.flags == 'OP_ASSIGN':
592 self.emit('STORE_SUBSCR')
593 elif node.flags == 'OP_DELETE':
594 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000595 return 1
596
597 def visitSlice(self, node):
598 self.visit(node.expr)
599 slice = 0
600 if node.lower:
601 self.visit(node.lower)
602 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000603 if node.upper:
604 self.visit(node.upper)
605 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000606 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000607 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000608 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000609 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000610 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000611 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000612 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000613 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000614 raise
615 return 1
616
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000617 def visitSliceobj(self, node):
618 for child in node.nodes:
619 print child
620 self.visit(child)
621 self.emit('BUILD_SLICE', len(node.nodes))
622 return 1
623
Jeremy Hylton40245602000-02-08 21:15:48 +0000624 def visitAssign(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000625 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton40245602000-02-08 21:15:48 +0000626 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000627 dups = len(node.nodes) - 1
628 for i in range(len(node.nodes)):
629 elt = node.nodes[i]
630 if i < dups:
631 self.emit('DUP_TOP')
Jeremy Hylton40245602000-02-08 21:15:48 +0000632 if isinstance(elt, ast.Node):
633 self.visit(elt)
634 return 1
635
636 def visitAssName(self, node):
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000637 # XXX handle OP_DELETE
Jeremy Hylton40245602000-02-08 21:15:48 +0000638 if node.flags != 'OP_ASSIGN':
639 print "oops", node.flags
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000640 self.storeName(node.name)
Jeremy Hylton40245602000-02-08 21:15:48 +0000641
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000642 def visitAssAttr(self, node):
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000643 self.visit(node.expr)
644 if node.flags == 'OP_ASSIGN':
645 self.emit('STORE_ATTR', node.attrname)
646 elif node.flags == 'OP_DELETE':
647 self.emit('DELETE_ATTR', node.attrname)
648 else:
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000649 print "warning: unexpected flags:", node.flags
650 print node
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000651 return 1
652
653 def visitAssTuple(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000654 self.emit('UNPACK_TUPLE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000655 for child in node.nodes:
656 self.visit(child)
657 return 1
658
659 visitAssList = visitAssTuple
660
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000661 def binaryOp(self, node, op):
662 self.visit(node.left)
663 self.visit(node.right)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000664 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000665 return 1
666
Jeremy Hylton40245602000-02-08 21:15:48 +0000667 def unaryOp(self, node, op):
668 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000669 self.emit(op)
Jeremy Hylton40245602000-02-08 21:15:48 +0000670 return 1
671
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000672 def visitAdd(self, node):
673 return self.binaryOp(node, 'BINARY_ADD')
674
675 def visitSub(self, node):
676 return self.binaryOp(node, 'BINARY_SUBTRACT')
677
678 def visitMul(self, node):
679 return self.binaryOp(node, 'BINARY_MULTIPLY')
680
681 def visitDiv(self, node):
682 return self.binaryOp(node, 'BINARY_DIVIDE')
683
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000684 def visitMod(self, node):
685 return self.binaryOp(node, 'BINARY_MODULO')
686
Jeremy Hylton126960b2000-02-14 21:33:10 +0000687 def visitPower(self, node):
688 return self.binaryOp(node, 'BINARY_POWER')
689
690 def visitLeftShift(self, node):
691 return self.binaryOp(node, 'BINARY_LSHIFT')
692
693 def visitRightShift(self, node):
694 return self.binaryOp(node, 'BINARY_RSHIFT')
695
696 def visitInvert(self, node):
697 return self.unaryOp(node, 'UNARY_INVERT')
698
Jeremy Hylton40245602000-02-08 21:15:48 +0000699 def visitUnarySub(self, node):
700 return self.unaryOp(node, 'UNARY_NEGATIVE')
701
702 def visitUnaryAdd(self, node):
703 return self.unaryOp(node, 'UNARY_POSITIVE')
704
705 def visitUnaryInvert(self, node):
706 return self.unaryOp(node, 'UNARY_INVERT')
707
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000708 def visitNot(self, node):
709 return self.unaryOp(node, 'UNARY_NOT')
710
Jeremy Hylton40245602000-02-08 21:15:48 +0000711 def visitBackquote(self, node):
712 return self.unaryOp(node, 'UNARY_CONVERT')
713
Jeremy Hyltona5058122000-02-14 14:14:29 +0000714 def bitOp(self, nodes, op):
715 self.visit(nodes[0])
716 for node in nodes[1:]:
717 self.visit(node)
718 self.emit(op)
719 return 1
720
721 def visitBitand(self, node):
722 return self.bitOp(node.nodes, 'BINARY_AND')
723
724 def visitBitor(self, node):
725 return self.bitOp(node.nodes, 'BINARY_OR')
726
727 def visitBitxor(self, node):
728 return self.bitOp(node.nodes, 'BINARY_XOR')
729
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000730 def visitTest(self, node, jump):
731 end = StackRef()
732 for child in node.nodes[:-1]:
733 self.visit(child)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000734 self.emit(jump, end)
735 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000736 self.visit(node.nodes[-1])
737 end.bind(self.code.getCurInst())
738 return 1
739
Jeremy Hyltona5058122000-02-14 14:14:29 +0000740 def visitAssert(self, node):
741 # XXX __debug__ and AssertionError appear to be special cases
742 # -- they are always loaded as globals even if there are local
743 # names. I guess this is a sort of renaming op.
744 skip = StackRef()
745 self.emit('SET_LINENO', node.lineno)
746 self.emit('LOAD_GLOBAL', '__debug__')
747 self.emit('JUMP_IF_FALSE', skip)
748 self.emit('POP_TOP')
749 self.visit(node.test)
750 self.emit('JUMP_IF_TRUE', skip)
751 self.emit('LOAD_GLOBAL', 'AssertionError')
752 self.visit(node.fail)
753 self.emit('RAISE_VARARGS', 2)
754 skip.bind(self.code.getCurInst())
755 self.emit('POP_TOP')
756 return 1
757
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000758 def visitAnd(self, node):
759 return self.visitTest(node, 'JUMP_IF_FALSE')
760
761 def visitOr(self, node):
762 return self.visitTest(node, 'JUMP_IF_TRUE')
763
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000764 def visitName(self, node):
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000765 self.loadName(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000766
767 def visitConst(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000768 self.emit('LOAD_CONST', node.value)
Jeremy Hylton40245602000-02-08 21:15:48 +0000769 return 1
770
Jeremy Hyltona5058122000-02-14 14:14:29 +0000771 def visitEllipsis(self, node):
772 self.emit('LOAD_CONST', Ellipsis)
773 return 1
774
Jeremy Hylton40245602000-02-08 21:15:48 +0000775 def visitTuple(self, node):
776 for elt in node.nodes:
777 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000778 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton40245602000-02-08 21:15:48 +0000779 return 1
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000780
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000781 def visitList(self, node):
782 for elt in node.nodes:
783 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000784 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000785 return 1
786
Jeremy Hyltona5058122000-02-14 14:14:29 +0000787 def visitDict(self, node):
788 self.emit('BUILD_MAP', 0)
789 for k, v in node.items:
790 # XXX need to add set lineno when there aren't constants
791 self.emit('DUP_TOP')
792 self.visit(v)
793 self.emit('ROT_TWO')
794 self.visit(k)
795 self.emit('STORE_SUBSCR')
796 return 1
797
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000798 def visitReturn(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000799 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000800 self.visit(node.value)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000801 self.emit('RETURN_VALUE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000802 return 1
803
804 def visitRaise(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000805 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000806 n = 0
807 if node.expr1:
808 self.visit(node.expr1)
809 n = n + 1
810 if node.expr2:
811 self.visit(node.expr2)
812 n = n + 1
813 if node.expr3:
814 self.visit(node.expr3)
815 n = n + 1
Jeremy Hyltona5058122000-02-14 14:14:29 +0000816 self.emit('RAISE_VARARGS', n)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000817 return 1
818
819 def visitPrint(self, node):
Jeremy Hyltona5058122000-02-14 14:14:29 +0000820 self.emit('SET_LINENO', node.lineno)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000821 for child in node.nodes:
822 self.visit(child)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000823 self.emit('PRINT_ITEM')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000824 return 1
825
826 def visitPrintnl(self, node):
827 self.visitPrint(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000828 self.emit('PRINT_NEWLINE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000829 return 1
Jeremy Hylton0fdffcf2000-02-04 19:37:35 +0000830
Jeremy Hyltona5058122000-02-14 14:14:29 +0000831 def visitExec(self, node):
832 self.visit(node.expr)
833 if node.locals is None:
834 self.emit('LOAD_CONST', None)
835 else:
836 self.visit(node.locals)
837 if node.globals is None:
838 self.emit('DUP_TOP')
839 else:
840 self.visit(node.globals)
841 self.emit('EXEC_STMT')
842
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000843class LocalNameFinder:
844 def __init__(self, names=()):
845 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000846 self.globals = misc.Set()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000847 for name in names:
848 self.names.add(name)
849
850 def getLocals(self):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000851 for elt in self.globals.items():
852 if self.names.has_elt(elt):
853 self.names.remove(elt)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000854 return self.names
855
Jeremy Hyltona5058122000-02-14 14:14:29 +0000856 def visitDict(self, node):
857 return 1
858
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000859 def visitGlobal(self, node):
860 for name in node.names:
861 self.globals.add(name)
862 return 1
863
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000864 def visitFunction(self, node):
865 self.names.add(node.name)
866 return 1
867
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000868 def visitLambda(self, node):
869 return 1
870
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000871 def visitImport(self, node):
872 for name in node.names:
873 self.names.add(name)
874
875 def visitFrom(self, node):
876 for name in node.names:
877 self.names.add(name)
878
879 def visitClassdef(self, node):
880 self.names.add(node.name)
881 return 1
882
883 def visitAssName(self, node):
884 self.names.add(node.name)
885
Jeremy Hylton4eb504c2000-02-10 20:55:50 +0000886class Loop:
887 def __init__(self):
888 self.startAnchor = StackRef()
889 self.breakAnchor = StackRef()
890 self.extentAnchor = StackRef()
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000891
Jeremy Hylton53187f32000-02-08 19:01:29 +0000892class CompiledModule:
893 """Store the code object for a compiled module
894
895 XXX Not clear how the code objects will be stored. Seems possible
896 that a single code attribute is sufficient, because it will
897 contains references to all the need code objects. That might be
898 messy, though.
899 """
900 MAGIC = (20121 | (ord('\r')<<16) | (ord('\n')<<24))
901
902 def __init__(self, source, filename):
903 self.source = source
904 self.filename = filename
905
906 def compile(self):
907 t = transformer.Transformer()
908 self.ast = t.parsesuite(self.source)
909 cg = CodeGenerator(self.filename)
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000910 walk(self.ast, cg)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000911 self.code = cg.asConst()
Jeremy Hylton53187f32000-02-08 19:01:29 +0000912
913 def dump(self, path):
914 """create a .pyc file"""
915 f = open(path, 'wb')
916 f.write(self._pyc_header())
917 marshal.dump(self.code, f)
918 f.close()
919
920 def _pyc_header(self):
921 # compile.c uses marshal to write a long directly, with
922 # calling the interface that would also generate a 1-byte code
923 # to indicate the type of the value. simplest way to get the
924 # same effect is to call marshal and then skip the code.
925 magic = marshal.dumps(self.MAGIC)[1:]
926 mtime = os.stat(self.filename)[stat.ST_MTIME]
927 mtime = struct.pack('i', mtime)
928 return magic + mtime
929
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000930if __name__ == "__main__":
Jeremy Hylton40245602000-02-08 21:15:48 +0000931 import getopt
932
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000933 VERBOSE = 0
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000934 opts, args = getopt.getopt(sys.argv[1:], 'vq')
Jeremy Hylton40245602000-02-08 21:15:48 +0000935 for k, v in opts:
936 if k == '-v':
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000937 VERBOSE = 1
Jeremy Hylton40245602000-02-08 21:15:48 +0000938 ASTVisitor.VERBOSE = ASTVisitor.VERBOSE + 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000939 if k == '-q':
940 f = open('/dev/null', 'wb')
941 sys.stdout = f
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000942 if not args:
943 print "no files to compile"
Jeremy Hylton53187f32000-02-08 19:01:29 +0000944 else:
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +0000945 for filename in args:
946 if VERBOSE:
947 print filename
948 buf = open(filename).read()
949 mod = CompiledModule(buf, filename)
950 mod.compile()
951 mod.dump(filename + 'c')