blob: 9d9b9825518250faa126b365b95735f893401c1c [file] [log] [blame]
Jeremy Hylton53187f32000-02-08 19:01:29 +00001import os
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00002import marshal
Jeremy Hylton53187f32000-02-08 19:01:29 +00003import stat
4import struct
Jeremy Hyltonad9a86f2000-02-16 00:55:44 +00005import types
Jeremy Hylton36cc6a22000-03-16 20:06:59 +00006from cStringIO import StringIO
7
8from compiler import ast, parse, walk
9from compiler import pyassem, misc
Thomas Wouters46cc7c02000-08-12 20:32:46 +000010from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, TupleArg
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000011
Jeremy Hyltonbe317e62000-05-02 22:32:59 +000012callfunc_opcode_info = {
13 # (Have *args, Have **args) : opcode
14 (0,0) : "CALL_FUNCTION",
15 (1,0) : "CALL_FUNCTION_VAR",
16 (0,1) : "CALL_FUNCTION_KW",
17 (1,1) : "CALL_FUNCTION_VAR_KW",
18}
19
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000020def compile(filename):
21 f = open(filename)
22 buf = f.read()
23 f.close()
24 mod = Module(buf, filename)
25 mod.compile()
26 f = open(filename + "c", "wb")
27 mod.dump(f)
28 f.close()
29
30class Module:
31 def __init__(self, source, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000032 self.filename = filename
33 self.source = source
34 self.code = None
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000035
36 def compile(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000037 ast = parse(self.source)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000038 root, filename = os.path.split(self.filename)
Thomas Wouters46cc7c02000-08-12 20:32:46 +000039 gen = ModuleCodeGenerator(filename)
40 walk(ast, gen, 1)
41 self.code = gen.getCode()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000042
43 def dump(self, f):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000044 f.write(self.getPycHeader())
45 marshal.dump(self.code, f)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000046
Thomas Wouters46cc7c02000-08-12 20:32:46 +000047 MAGIC = (50811 | (ord('\r')<<16) | (ord('\n')<<24))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000048
49 def getPycHeader(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000050 # compile.c uses marshal to write a long directly, with
51 # calling the interface that would also generate a 1-byte code
52 # to indicate the type of the value. simplest way to get the
53 # same effect is to call marshal and then skip the code.
54 magic = marshal.dumps(self.MAGIC)[1:]
55 mtime = os.stat(self.filename)[stat.ST_MTIME]
56 mtime = struct.pack('i', mtime)
57 return magic + mtime
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000058
Jeremy Hylton8b6323d2000-02-04 00:28:21 +000059class CodeGenerator:
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000060
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000061 optimized = 0 # is namespace access optimized?
Jeremy Hylton3050d512000-02-12 00:12:38 +000062
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000063 def __init__(self, filename):
64## Subclasses must define a constructor that intializes self.graph
65## before calling this init function
Thomas Wouters46cc7c02000-08-12 20:32:46 +000066## self.graph = pyassem.PyFlowGraph()
67 self.filename = filename
68 self.locals = misc.Stack()
69 self.loops = misc.Stack()
70 self.curStack = 0
71 self.maxStack = 0
72 self._setupGraphDelegation()
Jeremy Hylton53187f32000-02-08 19:01:29 +000073
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000074 def _setupGraphDelegation(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000075 self.emit = self.graph.emit
76 self.newBlock = self.graph.newBlock
77 self.startBlock = self.graph.startBlock
78 self.nextBlock = self.graph.nextBlock
79 self.setDocstring = self.graph.setDocstring
Jeremy Hyltona5058122000-02-14 14:14:29 +000080
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000081 def getCode(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +000082 """Return a code object"""
83 return self.graph.getCode()
Jeremy Hylton76d01b82000-02-11 20:27:07 +000084
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000085 # Next five methods handle name access
Jeremy Hylton53187f32000-02-08 19:01:29 +000086
Jeremy Hylton40245602000-02-08 21:15:48 +000087 def isLocalName(self, name):
Jeremy Hylton873bdc12000-02-17 17:56:29 +000088 return self.locals.top().has_elt(name)
Jeremy Hylton40245602000-02-08 21:15:48 +000089
Jeremy Hylton3e0910c2000-02-10 17:20:39 +000090 def storeName(self, name):
91 self._nameOp('STORE', name)
92
93 def loadName(self, name):
94 self._nameOp('LOAD', name)
95
96 def delName(self, name):
97 self._nameOp('DELETE', name)
98
Jeremy Hylton36cc6a22000-03-16 20:06:59 +000099 def _nameOp(self, prefix, name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000100 if not self.optimized:
101 self.emit(prefix + '_NAME', name)
102 return
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000103 if self.isLocalName(name):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000104 self.emit(prefix + '_FAST', name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000105 else:
106 self.emit(prefix + '_GLOBAL', name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000107
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000108 def set_lineno(self, node):
109 """Emit SET_LINENO if node has lineno attribute
110
111 Returns true if SET_LINENO was emitted.
112
113 There are no rules for when an AST node should have a lineno
114 attribute. The transformer and AST code need to be reviewed
115 and a consistent policy implemented and documented. Until
116 then, this method works around missing line numbers.
117 """
118 lineno = getattr(node, 'lineno', None)
119 if lineno is not None:
120 self.emit('SET_LINENO', lineno)
121 return 1
122 return 0
123
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000124 # The first few visitor methods handle nodes that generator new
125 # code objects
126
127 def visitModule(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000128 lnf = walk(node.node, LocalNameFinder(), 0)
129 self.locals.push(lnf.getLocals())
130 self.setDocstring(node.doc)
131 self.visit(node.node)
132 self.emit('LOAD_CONST', None)
133 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000134
135 def visitFunction(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000136 self._visitFuncOrLambda(node, isLambda=0)
137 self.storeName(node.name)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000138
139 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000140 self._visitFuncOrLambda(node, isLambda=1)
141## self.storeName("<lambda>")
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000142
143 def _visitFuncOrLambda(self, node, isLambda):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000144 gen = FunctionCodeGenerator(node, self.filename, isLambda)
145 walk(node.code, gen)
146 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000147 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000148 for default in node.defaults:
149 self.visit(default)
150 self.emit('LOAD_CONST', gen.getCode())
151 self.emit('MAKE_FUNCTION', len(node.defaults))
152
153 def visitClass(self, node):
154 gen = ClassCodeGenerator(node, self.filename)
155 walk(node.code, gen)
156 gen.finish()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000157 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000158 self.emit('LOAD_CONST', node.name)
159 for base in node.bases:
160 self.visit(base)
161 self.emit('BUILD_TUPLE', len(node.bases))
162 self.emit('LOAD_CONST', gen.getCode())
163 self.emit('MAKE_FUNCTION', 0)
164 self.emit('CALL_FUNCTION', 0)
165 self.emit('BUILD_CLASS')
166 self.storeName(node.name)
167
168 # The rest are standard visitor methods
169
170 # The next few implement control-flow statements
171
172 def visitIf(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000173 end = self.newBlock()
174 numtests = len(node.tests)
175 for i in range(numtests):
176 test, suite = node.tests[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000177 self.set_lineno(test)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000178 self.visit(test)
179## if i == numtests - 1 and not node.else_:
180## nextTest = end
181## else:
182## nextTest = self.newBlock()
183 nextTest = self.newBlock()
184 self.emit('JUMP_IF_FALSE', nextTest)
185 self.nextBlock()
186 self.emit('POP_TOP')
187 self.visit(suite)
188 self.emit('JUMP_FORWARD', end)
189 self.nextBlock(nextTest)
190 self.emit('POP_TOP')
191 if node.else_:
192 self.visit(node.else_)
193 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000194
195 def visitWhile(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000196 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000197
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000198 loop = self.newBlock()
199 else_ = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000200
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000201 after = self.newBlock()
202 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000203
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000204 self.nextBlock(loop)
205 self.loops.push(loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000206
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000207 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000208 self.visit(node.test)
209 self.emit('JUMP_IF_FALSE', else_ or after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000210
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000211 self.nextBlock()
212 self.emit('POP_TOP')
213 self.visit(node.body)
214 self.emit('JUMP_ABSOLUTE', loop)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000215
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000216 self.startBlock(else_) # or just the POPs if not else clause
217 self.emit('POP_TOP')
218 self.emit('POP_BLOCK')
219 if node.else_:
220 self.visit(node.else_)
221 self.loops.pop()
222 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000223
224 def visitFor(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000225 start = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000226 anchor = self.newBlock()
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000227 after = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000228 self.loops.push(start)
229
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000230 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000231 self.emit('SETUP_LOOP', after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000232 self.visit(node.list)
233 self.visit(ast.Const(0))
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000234 self.nextBlock(start)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000235 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000236 self.emit('FOR_LOOP', anchor)
237 self.visit(node.assign)
238 self.visit(node.body)
239 self.emit('JUMP_ABSOLUTE', start)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000240 self.nextBlock(anchor)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000241 self.emit('POP_BLOCK')
242 if node.else_:
243 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000244 self.loops.pop()
245 self.nextBlock(after)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000246
247 def visitBreak(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000248 if not self.loops:
249 raise SyntaxError, "'break' outside loop (%s, %d)" % \
250 (self.filename, node.lineno)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000251 self.set_lineno(node)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000252 self.emit('BREAK_LOOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000253
254 def visitContinue(self, node):
255 if not self.loops:
256 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000257 (self.filename, node.lineno)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000258 l = self.loops.top()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000259 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000260 self.emit('JUMP_ABSOLUTE', l)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000261 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000262
263 def visitTest(self, node, jump):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000264 end = self.newBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000265 for child in node.nodes[:-1]:
266 self.visit(child)
267 self.emit(jump, end)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000268 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000269 self.emit('POP_TOP')
270 self.visit(node.nodes[-1])
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000271 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000272
273 def visitAnd(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000274 self.visitTest(node, 'JUMP_IF_FALSE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000275
276 def visitOr(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000277 self.visitTest(node, 'JUMP_IF_TRUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000278
279 def visitCompare(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000280 self.visit(node.expr)
281 cleanup = self.newBlock()
282 for op, code in node.ops[:-1]:
283 self.visit(code)
284 self.emit('DUP_TOP')
285 self.emit('ROT_THREE')
286 self.emit('COMPARE_OP', op)
287 self.emit('JUMP_IF_FALSE', cleanup)
288 self.nextBlock()
289 self.emit('POP_TOP')
290 # now do the last comparison
291 if node.ops:
292 op, code = node.ops[-1]
293 self.visit(code)
294 self.emit('COMPARE_OP', op)
295 if len(node.ops) > 1:
296 end = self.newBlock()
297 self.emit('JUMP_FORWARD', end)
298 self.nextBlock(cleanup)
299 self.emit('ROT_TWO')
300 self.emit('POP_TOP')
301 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000302
303 # exception related
304
305 def visitAssert(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000306 # XXX would be interesting to implement this via a
307 # transformation of the AST before this stage
308 end = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000309 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000310 # XXX __debug__ and AssertionError appear to be special cases
311 # -- they are always loaded as globals even if there are local
312 # names. I guess this is a sort of renaming op.
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000313 self.emit('LOAD_GLOBAL', '__debug__')
314 self.emit('JUMP_IF_FALSE', end)
315 self.nextBlock()
316 self.emit('POP_TOP')
317 self.visit(node.test)
318 self.emit('JUMP_IF_TRUE', end)
319 self.nextBlock()
320 self.emit('LOAD_GLOBAL', 'AssertionError')
321 self.visit(node.fail)
322 self.emit('RAISE_VARARGS', 2)
323 self.nextBlock(end)
324 self.emit('POP_TOP')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000325
326 def visitRaise(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000327 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000328 n = 0
329 if node.expr1:
330 self.visit(node.expr1)
331 n = n + 1
332 if node.expr2:
333 self.visit(node.expr2)
334 n = n + 1
335 if node.expr3:
336 self.visit(node.expr3)
337 n = n + 1
338 self.emit('RAISE_VARARGS', n)
339
340 def visitTryExcept(self, node):
341 handlers = self.newBlock()
342 end = self.newBlock()
343 if node.else_:
344 lElse = self.newBlock()
345 else:
346 lElse = end
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000347 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000348 self.emit('SETUP_EXCEPT', handlers)
349 self.visit(node.body)
350 self.emit('POP_BLOCK')
351 self.emit('JUMP_FORWARD', lElse)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000352 self.nextBlock(handlers)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000353
354 last = len(node.handlers) - 1
355 for i in range(len(node.handlers)):
356 expr, target, body = node.handlers[i]
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000357 self.set_lineno(expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000358 if expr:
359 self.emit('DUP_TOP')
360 self.visit(expr)
361 self.emit('COMPARE_OP', 'exception match')
362 next = self.newBlock()
363 self.emit('JUMP_IF_FALSE', next)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000364 self.nextBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000365 self.emit('POP_TOP')
366 self.emit('POP_TOP')
367 if target:
368 self.visit(target)
369 else:
370 self.emit('POP_TOP')
371 self.emit('POP_TOP')
372 self.visit(body)
373 self.emit('JUMP_FORWARD', end)
374 if expr:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000375 self.nextBlock(next)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000376 self.emit('POP_TOP')
377 self.emit('END_FINALLY')
378 if node.else_:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000379 self.nextBlock(lElse)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000380 self.visit(node.else_)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000381 self.nextBlock(end)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000382
383 def visitTryFinally(self, node):
384 final = self.newBlock()
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000385 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000386 self.emit('SETUP_FINALLY', final)
387 self.visit(node.body)
388 self.emit('POP_BLOCK')
389 self.emit('LOAD_CONST', None)
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000390 self.nextBlock(final)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000391 self.visit(node.final)
392 self.emit('END_FINALLY')
393
394 # misc
395
396## def visitStmt(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000397## # nothing to do except walk the children
398## pass
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000399
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000400 def visitDiscard(self, node):
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000401 self.visit(node.expr)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000402 self.emit('POP_TOP')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000403
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000404 def visitConst(self, node):
405 self.emit('LOAD_CONST', node.value)
406
407 def visitKeyword(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000408 self.emit('LOAD_CONST', node.name)
409 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000410
411 def visitGlobal(self, node):
412 # no code to generate
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000413 pass
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000414
415 def visitName(self, node):
416 self.loadName(node.name)
417
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000418 def visitPass(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000419 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000420
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000421 def visitImport(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000422 self.set_lineno(node)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000423 for name in node.names:
Jeremy Hyltona5058122000-02-14 14:14:29 +0000424 self.emit('IMPORT_NAME', name)
Jeremy Hylton3e0910c2000-02-10 17:20:39 +0000425 self.storeName(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000426
427 def visitFrom(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000428 self.set_lineno(node)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000429 self.emit('IMPORT_NAME', node.modname)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000430 for name in node.names:
Jeremy Hylton126960b2000-02-14 21:33:10 +0000431 if name == '*':
432 self.namespace = 0
Jeremy Hyltona5058122000-02-14 14:14:29 +0000433 self.emit('IMPORT_FROM', name)
434 self.emit('POP_TOP')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000435
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000436 def visitGetattr(self, node):
437 self.visit(node.expr)
438 self.emit('LOAD_ATTR', node.attrname)
439
440 # next five implement assignments
441
442 def visitAssign(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000443 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000444 self.visit(node.expr)
445 dups = len(node.nodes) - 1
446 for i in range(len(node.nodes)):
447 elt = node.nodes[i]
448 if i < dups:
449 self.emit('DUP_TOP')
450 if isinstance(elt, ast.Node):
451 self.visit(elt)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000452
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000453 def visitAssName(self, node):
454 if node.flags == 'OP_ASSIGN':
455 self.storeName(node.name)
456 elif node.flags == 'OP_DELETE':
457 self.delName(node.name)
458 else:
459 print "oops", node.flags
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000460
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000461 def visitAssAttr(self, node):
462 self.visit(node.expr)
463 if node.flags == 'OP_ASSIGN':
464 self.emit('STORE_ATTR', node.attrname)
465 elif node.flags == 'OP_DELETE':
466 self.emit('DELETE_ATTR', node.attrname)
467 else:
468 print "warning: unexpected flags:", node.flags
469 print node
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000470
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000471 def visitAssTuple(self, node):
472 if findOp(node) != 'OP_DELETE':
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000473 self.emit('UNPACK_SEQUENCE', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000474 for child in node.nodes:
475 self.visit(child)
476
477 visitAssList = visitAssTuple
478
479 def visitExec(self, node):
480 self.visit(node.expr)
481 if node.locals is None:
482 self.emit('LOAD_CONST', None)
483 else:
484 self.visit(node.locals)
485 if node.globals is None:
486 self.emit('DUP_TOP')
487 else:
488 self.visit(node.globals)
489 self.emit('EXEC_STMT')
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000490
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000491 def visitCallFunc(self, node):
Jeremy Hylton3050d512000-02-12 00:12:38 +0000492 pos = 0
493 kw = 0
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000494 self.set_lineno(node)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000495 self.visit(node.node)
496 for arg in node.args:
497 self.visit(arg)
Jeremy Hylton3050d512000-02-12 00:12:38 +0000498 if isinstance(arg, ast.Keyword):
499 kw = kw + 1
500 else:
501 pos = pos + 1
Jeremy Hyltonbe317e62000-05-02 22:32:59 +0000502 if node.star_args is not None:
503 self.visit(node.star_args)
504 if node.dstar_args is not None:
505 self.visit(node.dstar_args)
506 have_star = node.star_args is not None
507 have_dstar = node.dstar_args is not None
508 opcode = callfunc_opcode_info[have_star, have_dstar]
509 self.emit(opcode, kw << 8 | pos)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000510
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000511 def visitPrint(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000512 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000513 for child in node.nodes:
514 self.visit(child)
515 self.emit('PRINT_ITEM')
516
517 def visitPrintnl(self, node):
518 self.visitPrint(node)
519 self.emit('PRINT_NEWLINE')
520
521 def visitReturn(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000522 self.set_lineno(node)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000523 self.visit(node.value)
524 self.emit('RETURN_VALUE')
Jeremy Hylton40245602000-02-08 21:15:48 +0000525
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000526 # slice and subscript stuff
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000527
528 def visitSlice(self, node):
529 self.visit(node.expr)
530 slice = 0
531 if node.lower:
532 self.visit(node.lower)
533 slice = slice | 1
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000534 if node.upper:
535 self.visit(node.upper)
536 slice = slice | 2
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000537 if node.flags == 'OP_APPLY':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000538 self.emit('SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000539 elif node.flags == 'OP_ASSIGN':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000540 self.emit('STORE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000541 elif node.flags == 'OP_DELETE':
Jeremy Hyltona5058122000-02-14 14:14:29 +0000542 self.emit('DELETE_SLICE+%d' % slice)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000543 else:
Jeremy Hylton4f6bcd82000-02-15 23:45:26 +0000544 print "weird slice", node.flags
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000545 raise
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000546
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000547 def visitSubscript(self, node):
Jeremy Hylton40245602000-02-08 21:15:48 +0000548 self.visit(node.expr)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000549 for sub in node.subs:
550 self.visit(sub)
551 if len(node.subs) > 1:
552 self.emit('BUILD_TUPLE', len(node.subs))
553 if node.flags == 'OP_APPLY':
554 self.emit('BINARY_SUBSCR')
555 elif node.flags == 'OP_ASSIGN':
556 self.emit('STORE_SUBSCR')
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000557 elif node.flags == 'OP_DELETE':
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000558 self.emit('DELETE_SUBSCR')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000559
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000560 # binary ops
561
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000562 def binaryOp(self, node, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000563 self.visit(node.left)
564 self.visit(node.right)
565 self.emit(op)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000566
567 def visitAdd(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000568 return self.binaryOp(node, 'BINARY_ADD')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000569
570 def visitSub(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000571 return self.binaryOp(node, 'BINARY_SUBTRACT')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000572
573 def visitMul(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000574 return self.binaryOp(node, 'BINARY_MULTIPLY')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000575
576 def visitDiv(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000577 return self.binaryOp(node, 'BINARY_DIVIDE')
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000578
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000579 def visitMod(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000580 return self.binaryOp(node, 'BINARY_MODULO')
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000581
Jeremy Hylton126960b2000-02-14 21:33:10 +0000582 def visitPower(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000583 return self.binaryOp(node, 'BINARY_POWER')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000584
585 def visitLeftShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000586 return self.binaryOp(node, 'BINARY_LSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000587
588 def visitRightShift(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000589 return self.binaryOp(node, 'BINARY_RSHIFT')
Jeremy Hylton126960b2000-02-14 21:33:10 +0000590
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000591 # unary ops
592
593 def unaryOp(self, node, op):
594 self.visit(node.expr)
595 self.emit(op)
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000596
Jeremy Hylton126960b2000-02-14 21:33:10 +0000597 def visitInvert(self, node):
598 return self.unaryOp(node, 'UNARY_INVERT')
599
Jeremy Hylton40245602000-02-08 21:15:48 +0000600 def visitUnarySub(self, node):
601 return self.unaryOp(node, 'UNARY_NEGATIVE')
602
603 def visitUnaryAdd(self, node):
604 return self.unaryOp(node, 'UNARY_POSITIVE')
605
606 def visitUnaryInvert(self, node):
607 return self.unaryOp(node, 'UNARY_INVERT')
608
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000609 def visitNot(self, node):
610 return self.unaryOp(node, 'UNARY_NOT')
611
Jeremy Hylton40245602000-02-08 21:15:48 +0000612 def visitBackquote(self, node):
613 return self.unaryOp(node, 'UNARY_CONVERT')
614
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000615 # bit ops
616
Jeremy Hyltona5058122000-02-14 14:14:29 +0000617 def bitOp(self, nodes, op):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000618 self.visit(nodes[0])
619 for node in nodes[1:]:
620 self.visit(node)
621 self.emit(op)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000622
623 def visitBitand(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000624 return self.bitOp(node.nodes, 'BINARY_AND')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000625
626 def visitBitor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000627 return self.bitOp(node.nodes, 'BINARY_OR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000628
629 def visitBitxor(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000630 return self.bitOp(node.nodes, 'BINARY_XOR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000631
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000632 # object constructors
Jeremy Hylton40245602000-02-08 21:15:48 +0000633
Jeremy Hyltona5058122000-02-14 14:14:29 +0000634 def visitEllipsis(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000635 self.emit('LOAD_CONST', Ellipsis)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000636
Jeremy Hylton40245602000-02-08 21:15:48 +0000637 def visitTuple(self, node):
638 for elt in node.nodes:
639 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000640 self.emit('BUILD_TUPLE', len(node.nodes))
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000641
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000642 def visitList(self, node):
643 for elt in node.nodes:
644 self.visit(elt)
Jeremy Hyltona5058122000-02-14 14:14:29 +0000645 self.emit('BUILD_LIST', len(node.nodes))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000646
647 def visitSliceobj(self, node):
648 for child in node.nodes:
649 self.visit(child)
650 self.emit('BUILD_SLICE', len(node.nodes))
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000651
Jeremy Hyltona5058122000-02-14 14:14:29 +0000652 def visitDict(self, node):
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000653 lineno = getattr(node, 'lineno', None)
654 if lineno:
655 set.emit('SET_LINENO', lineno)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000656 self.emit('BUILD_MAP', 0)
657 for k, v in node.items:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000658 lineno2 = getattr(node, 'lineno', None)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000659 if lineno2 is not None and lineno != lineno2:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000660 self.emit('SET_LINENO', lineno2)
661 lineno = lineno2
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000662 self.emit('DUP_TOP')
663 self.visit(v)
664 self.emit('ROT_TWO')
665 self.visit(k)
666 self.emit('STORE_SUBSCR')
Jeremy Hyltona5058122000-02-14 14:14:29 +0000667
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000668class ModuleCodeGenerator(CodeGenerator):
669 super_init = CodeGenerator.__init__
670
671 def __init__(self, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000672 # XXX <module> is ? in compile.c
673 self.graph = pyassem.PyFlowGraph("<module>", filename)
674 self.super_init(filename)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000675
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000676class FunctionCodeGenerator(CodeGenerator):
677 super_init = CodeGenerator.__init__
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000678
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000679 optimized = 1
680 lambdaCount = 0
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000681
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000682 def __init__(self, func, filename, isLambda=0):
683 if isLambda:
684 klass = FunctionCodeGenerator
685 name = "<lambda.%d>" % klass.lambdaCount
686 klass.lambdaCount = klass.lambdaCount + 1
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000687 else:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000688 name = func.name
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000689 args, hasTupleArg = generateArgList(func.argnames)
690 self.graph = pyassem.PyFlowGraph(name, filename, args,
691 optimized=1)
692 self.isLambda = isLambda
693 self.super_init(filename)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000694
695 lnf = walk(func.code, LocalNameFinder(args), 0)
696 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000697 if func.varargs:
698 self.graph.setFlag(CO_VARARGS)
699 if func.kwargs:
700 self.graph.setFlag(CO_VARKEYWORDS)
Jeremy Hylton7daf04d2000-08-04 16:56:51 +0000701 self.set_lineno(func)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000702 if hasTupleArg:
703 self.generateArgUnpack(func.argnames)
704
705 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000706 self.graph.startExitBlock()
707 if not self.isLambda:
708 self.emit('LOAD_CONST', None)
709 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000710
711 def generateArgUnpack(self, args):
712 count = 0
713 for arg in args:
714 if type(arg) == types.TupleType:
715 self.emit('LOAD_FAST', '.nested%d' % count)
716 count = count + 1
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000717 self.unpackSequence(arg)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000718
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000719 def unpackSequence(self, tup):
720 self.emit('UNPACK_SEQUENCE', len(tup))
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000721 for elt in tup:
722 if type(elt) == types.TupleType:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000723 self.unpackSequence(elt)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000724 else:
725 self.emit('STORE_FAST', elt)
726
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000727 unpackTuple = unpackSequence
728
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000729class ClassCodeGenerator(CodeGenerator):
730 super_init = CodeGenerator.__init__
731
732 def __init__(self, klass, filename):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000733 self.graph = pyassem.PyFlowGraph(klass.name, filename,
734 optimized=0)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000735 self.super_init(filename)
736 lnf = walk(klass.code, LocalNameFinder(), 0)
737 self.locals.push(lnf.getLocals())
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000738 self.graph.setFlag(CO_NEWLOCALS)
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000739
740 def finish(self):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000741 self.graph.startExitBlock()
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000742 self.emit('LOAD_LOCALS')
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000743 self.emit('RETURN_VALUE')
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000744
745
746def generateArgList(arglist):
747 """Generate an arg list marking TupleArgs"""
748 args = []
749 extra = []
750 count = 0
751 for elt in arglist:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000752 if type(elt) == types.StringType:
753 args.append(elt)
754 elif type(elt) == types.TupleType:
755 args.append(TupleArg(count, elt))
756 count = count + 1
757 extra.extend(misc.flatten(elt))
758 else:
759 raise ValueError, "unexpect argument type:", elt
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000760 return args + extra, count
Jeremy Hyltona5058122000-02-14 14:14:29 +0000761
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000762class LocalNameFinder:
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000763 """Find local names in scope"""
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000764 def __init__(self, names=()):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000765 self.names = misc.Set()
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000766 self.globals = misc.Set()
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000767 for name in names:
768 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000769
770 def getLocals(self):
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000771 for elt in self.globals.elements():
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000772 if self.names.has_elt(elt):
773 self.names.remove(elt)
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000774 return self.names
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000775
Jeremy Hyltona5058122000-02-14 14:14:29 +0000776 def visitDict(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000777 pass
Jeremy Hyltona5058122000-02-14 14:14:29 +0000778
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000779 def visitGlobal(self, node):
780 for name in node.names:
781 self.globals.add(name)
Jeremy Hylton5e0ce532000-02-10 00:47:08 +0000782
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000783 def visitFunction(self, node):
784 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000785
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000786 def visitLambda(self, node):
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000787 pass
Jeremy Hylton76d01b82000-02-11 20:27:07 +0000788
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000789 def visitImport(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000790 for name in node.names:
791 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000792
793 def visitFrom(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000794 for name in node.names:
795 self.names.add(name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000796
Jeremy Hylton7fab23e2000-03-06 19:10:54 +0000797 def visitClass(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000798 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000799
800 def visitAssName(self, node):
Jeremy Hylton873bdc12000-02-17 17:56:29 +0000801 self.names.add(node.name)
Jeremy Hylton8b6323d2000-02-04 00:28:21 +0000802
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000803def findOp(node):
804 """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
805 v = OpFinder()
806 walk(node, v, 0)
807 return v.op
808
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000809class OpFinder:
810 def __init__(self):
811 self.op = None
812 def visitAssName(self, node):
813 if self.op is None:
814 self.op = node.flags
815 elif self.op != node.flags:
816 raise ValueError, "mixed ops in stmt"
817
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000818if __name__ == "__main__":
819 import sys
Jeremy Hylton3ec7e2c2000-02-17 22:09:35 +0000820
Jeremy Hylton36cc6a22000-03-16 20:06:59 +0000821 for file in sys.argv[1:]:
Thomas Wouters46cc7c02000-08-12 20:32:46 +0000822 compile(file)