ยปCore Development>Code coverage>Lib/compiler/pycodegen.py

Python code coverage for Lib/compiler/pycodegen.py

#countcontent
12import imp
22import os
32import marshal
42import struct
52import sys
62from cStringIO import StringIO
7n/a
82from compiler import ast, parse, walk, syntax
92from compiler import pyassem, misc, future, symbols
102from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \
11n/a SC_FREE, SC_CELL
122from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
13n/a CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
14n/a CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION)
152from compiler.pyassem import TupleArg
16n/a
17n/a# XXX The version-specific code can go, since this code only works with 2.x.
18n/a# Do we have Python 1.x or Python 2.x?
192try:
202 VERSION = sys.version_info[0]
210except AttributeError:
220 VERSION = 1
23n/a
242callfunc_opcode_info = {
25n/a # (Have *args, Have **args) : opcode
262 (0,0) : "CALL_FUNCTION",
272 (1,0) : "CALL_FUNCTION_VAR",
282 (0,1) : "CALL_FUNCTION_KW",
292 (1,1) : "CALL_FUNCTION_VAR_KW",
30n/a}
31n/a
322LOOP = 1
332EXCEPT = 2
342TRY_FINALLY = 3
352END_FINALLY = 4
36n/a
372def compileFile(filename, display=0):
380 f = open(filename, 'U')
390 buf = f.read()
400 f.close()
410 mod = Module(buf, filename)
420 try:
430 mod.compile(display)
440 except SyntaxError:
450 raise
46n/a else:
470 f = open(filename + "c", "wb")
480 mod.dump(f)
490 f.close()
50n/a
512def compile(source, filename, mode, flags=None, dont_inherit=None):
52n/a """Replacement for builtin compile() function"""
5331 if flags is not None or dont_inherit is not None:
540 raise RuntimeError, "not implemented yet"
55n/a
5631 if mode == "single":
573 gen = Interactive(source, filename)
5828 elif mode == "exec":
5919 gen = Module(source, filename)
609 elif mode == "eval":
619 gen = Expression(source, filename)
62n/a else:
630 raise ValueError("compile() 3rd arg must be 'exec' or "
64n/a "'eval' or 'single'")
6531 gen.compile()
6631 return gen.code
67n/a
684class AbstractCompileMode:
69n/a
702 mode = None # defined by subclass
71n/a
722 def __init__(self, source, filename):
7331 self.source = source
7431 self.filename = filename
7531 self.code = None
76n/a
772 def _get_tree(self):
7831 tree = parse(self.source, self.mode)
7931 misc.set_filename(self.filename, tree)
8031 syntax.check(tree)
8131 return tree
82n/a
832 def compile(self):
840 pass # implemented by subclass
85n/a
862 def getCode(self):
870 return self.code
88n/a
894class Expression(AbstractCompileMode):
90n/a
912 mode = "eval"
92n/a
932 def compile(self):
949 tree = self._get_tree()
959 gen = ExpressionCodeGenerator(tree)
969 self.code = gen.getCode()
97n/a
984class Interactive(AbstractCompileMode):
99n/a
1002 mode = "single"
101n/a
1022 def compile(self):
1033 tree = self._get_tree()
1043 gen = InteractiveCodeGenerator(tree)
1053 self.code = gen.getCode()
106n/a
1074class Module(AbstractCompileMode):
108n/a
1092 mode = "exec"
110n/a
1112 def compile(self, display=0):
11219 tree = self._get_tree()
11319 gen = ModuleCodeGenerator(tree)
11419 if display:
1150 import pprint
1160 print pprint.pprint(tree)
11719 self.code = gen.getCode()
118n/a
1192 def dump(self, f):
1200 f.write(self.getPycHeader())
1210 marshal.dump(self.code, f)
122n/a
1232 MAGIC = imp.get_magic()
124n/a
1252 def getPycHeader(self):
126n/a # compile.c uses marshal to write a long directly, with
127n/a # calling the interface that would also generate a 1-byte code
128n/a # to indicate the type of the value. simplest way to get the
129n/a # same effect is to call marshal and then skip the code.
1300 mtime = os.path.getmtime(self.filename)
1310 mtime = struct.pack('<i', mtime)
1320 return self.MAGIC + mtime
133n/a
1344class LocalNameFinder:
1352 """Find local names in scope"""
1362 def __init__(self, names=()):
1371050 self.names = misc.Set()
1381050 self.globals = misc.Set()
1391995 for name in names:
140945 self.names.add(name)
141n/a
142n/a # XXX list comprehensions and for loops
143n/a
1442 def getLocals(self):
1451061 for elt in self.globals.elements():
14611 if self.names.has_elt(elt):
14711 self.names.remove(elt)
1481050 return self.names
149n/a
1502 def visitDict(self, node):
15196 pass
152n/a
1532 def visitGlobal(self, node):
15418 for name in node.names:
15511 self.globals.add(name)
156n/a
1572 def visitFunction(self, node):
158617 self.names.add(node.name)
159n/a
1602 def visitLambda(self, node):
16118 pass
162n/a
1632 def visitImport(self, node):
164101 for name, alias in node.names:
16553 self.names.add(alias or name)
166n/a
1672 def visitFrom(self, node):
16832 for name, alias in node.names:
16917 self.names.add(alias or name)
170n/a
1712 def visitClass(self, node):
172391 self.names.add(node.name)
173n/a
1742 def visitAssName(self, node):
175824 self.names.add(node.name)
176n/a
1772def is_constant_false(node):
178118 if isinstance(node, ast.Const):
1790 if not node.value:
1800 return 1
181118 return 0
182n/a
1834class CodeGenerator:
184n/a """Defines basic code generator for Python bytecode
185n/a
186n/a This class is an abstract base class. Concrete subclasses must
187n/a define an __init__() that defines self.graph and then calls the
188n/a __init__() defined in this class.
189n/a
190n/a The concrete class must also define the class attributes
191n/a NameFinder, FunctionGen, and ClassGen. These attributes can be
192n/a defined in the initClass() method, which is a hook for
193n/a initializing these methods after all the classes have been
194n/a defined.
1952 """
196n/a
1972 optimized = 0 # is namespace access optimized?
1982 __initialized = None
1992 class_name = None # provide default for instance variable
200n/a
2012 def __init__(self):
2021059 if self.__initialized is None:
2036 self.initClass()
2046 self.__class__.__initialized = 1
2051059 self.checkClass()
2061059 self.locals = misc.Stack()
2071059 self.setups = misc.Stack()
2081059 self.last_lineno = None
2091059 self._setupGraphDelegation()
2101059 self._div_op = "BINARY_DIVIDE"
211n/a
212n/a # XXX set flags based on future features
2131059 futures = self.get_module().futures
2141066 for feature in futures:
2157 if feature == "division":
2160 self.graph.setFlag(CO_FUTURE_DIVISION)
2170 self._div_op = "BINARY_TRUE_DIVIDE"
2187 elif feature == "absolute_import":
2190 self.graph.setFlag(CO_FUTURE_ABSIMPORT)
2207 elif feature == "with_statement":
2216 self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
2221 elif feature == "print_function":
2231 self.graph.setFlag(CO_FUTURE_PRINT_FUNCTION)
224n/a
2252 def initClass(self):
226n/a """This method is called once for each class"""
227n/a
2282 def checkClass(self):
229n/a """Verify that class is constructed correctly"""
2301059 try:
2311059 assert hasattr(self, 'graph')
2321059 assert getattr(self, 'NameFinder')
2331059 assert getattr(self, 'FunctionGen')
2341059 assert getattr(self, 'ClassGen')
2350 except AssertionError, msg:
2360 intro = "Bad class construction for %s" % self.__class__.__name__
2370 raise AssertionError, intro
238n/a
2392 def _setupGraphDelegation(self):
2401059 self.emit = self.graph.emit
2411059 self.newBlock = self.graph.newBlock
2421059 self.startBlock = self.graph.startBlock
2431059 self.nextBlock = self.graph.nextBlock
2441059 self.setDocstring = self.graph.setDocstring
245n/a
2462 def getCode(self):
247n/a """Return a code object"""
2481059 return self.graph.getCode()
249n/a
2502 def mangle(self, name):
25112013 if self.class_name is not None:
25211233 return misc.mangle(name, self.class_name)
253n/a else:
254780 return name
255n/a
2562 def parseSymbols(self, tree):
25731 s = symbols.SymbolVisitor()
25831 walk(tree, s)
25931 return s.scopes
260n/a
2612 def get_module(self):
2620 raise RuntimeError, "should be implemented by subclasses"
263n/a
264n/a # Next five methods handle name access
265n/a
2662 def isLocalName(self, name):
2670 return self.locals.top().has_elt(name)
268n/a
2692 def storeName(self, name):
2702302 self._nameOp('STORE', name)
271n/a
2722 def loadName(self, name):
2736817 self._nameOp('LOAD', name)
274n/a
2752 def delName(self, name):
27619 self._nameOp('DELETE', name)
277n/a
2782 def _nameOp(self, prefix, name):
2799138 name = self.mangle(name)
2809138 scope = self.scope.check_name(name)
2819138 if scope == SC_LOCAL:
2826958 if not self.optimized:
2831342 self.emit(prefix + '_NAME', name)
284n/a else:
2855616 self.emit(prefix + '_FAST', name)
2862180 elif scope == SC_GLOBAL_EXPLICT:
287298 self.emit(prefix + '_GLOBAL', name)
2881882 elif scope == SC_GLOBAL_IMPLICIT:
2891385 if not self.optimized:
29056 self.emit(prefix + '_NAME', name)
291n/a else:
2921329 self.emit(prefix + '_GLOBAL', name)
293497 elif scope == SC_FREE or scope == SC_CELL:
294497 self.emit(prefix + '_DEREF', name)
295n/a else:
2960 raise RuntimeError, "unsupported scope for var %s: %d" % \
2970 (name, scope)
298n/a
2992 def _implicitNameOp(self, prefix, name):
300n/a """Emit name ops for names generated implicitly by for loops
301n/a
302n/a The interpreter generates names that start with a period or
303n/a dollar sign. The symbol table ignores these names because
304n/a they aren't present in the program text.
305n/a """
30612 if self.optimized:
30712 self.emit(prefix + '_FAST', name)
308n/a else:
3090 self.emit(prefix + '_NAME', name)
310n/a
311n/a # The set_lineno() function and the explicit emit() calls for
312n/a # SET_LINENO below are only used to generate the line number table.
313n/a # As of Python 2.3, the interpreter does not have a SET_LINENO
314n/a # instruction. pyassem treats SET_LINENO opcodes as a special case.
315n/a
3162 def set_lineno(self, node, force=False):
317n/a """Emit SET_LINENO if necessary.
318n/a
319n/a The instruction is considered necessary if the node has a
320n/a lineno attribute and it is different than the last lineno
321n/a emitted.
322n/a
323n/a Returns true if SET_LINENO was emitted.
324n/a
325n/a There are no rules for when an AST node should have a lineno
326n/a attribute. The transformer and AST code need to be reviewed
327n/a and a consistent policy implemented and documented. Until
328n/a then, this method works around missing line numbers.
329n/a """
33016581 lineno = getattr(node, 'lineno', None)
33116581 if lineno is not None and (lineno != self.last_lineno
33210619 or force):
3336071 self.emit('SET_LINENO', lineno)
3346071 self.last_lineno = lineno
3356071 return True
33610510 return False
337n/a
338n/a # The first few visitor methods handle nodes that generator new
339n/a # code objects. They use class attributes to determine what
340n/a # specialized code generators to use.
341n/a
3422 NameFinder = LocalNameFinder
3432 FunctionGen = None
3442 ClassGen = None
345n/a
3462 def visitModule(self, node):
34722 self.scopes = self.parseSymbols(node)
34822 self.scope = self.scopes[node]
34922 self.emit('SET_LINENO', 0)
35022 if node.doc:
3515 self.emit('LOAD_CONST', node.doc)
3525 self.storeName('__doc__')
35322 lnf = walk(node.node, self.NameFinder(), verbose=0)
35422 self.locals.push(lnf.getLocals())
35522 self.visit(node.node)
35622 self.emit('LOAD_CONST', None)
35722 self.emit('RETURN_VALUE')
358n/a
3592 def visitExpression(self, node):
3609 self.set_lineno(node)
3619 self.scopes = self.parseSymbols(node)
3629 self.scope = self.scopes[node]
3639 self.visit(node.node)
3649 self.emit('RETURN_VALUE')
365n/a
3662 def visitFunction(self, node):
367617 self._visitFuncOrLambda(node, isLambda=0)
368617 if node.doc:
36921 self.setDocstring(node.doc)
370617 self.storeName(node.name)
371n/a
3722 def visitLambda(self, node):
37318 self._visitFuncOrLambda(node, isLambda=1)
374n/a
3752 def _visitFuncOrLambda(self, node, isLambda=0):
376635 if not isLambda and node.decorators:
37738 for decorator in node.decorators.nodes:
37819 self.visit(decorator)
37919 ndecorators = len(node.decorators.nodes)
380n/a else:
381616 ndecorators = 0
382n/a
383635 gen = self.FunctionGen(node, self.scopes, isLambda,
384635 self.class_name, self.get_module())
385635 walk(node.code, gen)
386635 gen.finish()
387635 self.set_lineno(node)
388678 for default in node.defaults:
38943 self.visit(default)
390635 self._makeClosure(gen, len(node.defaults))
391654 for i in range(ndecorators):
39219 self.emit('CALL_FUNCTION', 1)
393n/a
3942 def visitClass(self, node):
395391 gen = self.ClassGen(node, self.scopes,
396391 self.get_module())
397391 walk(node.code, gen)
398391 gen.finish()
399391 self.set_lineno(node)
400391 self.emit('LOAD_CONST', node.name)
401805 for base in node.bases:
402414 self.visit(base)
403391 self.emit('BUILD_TUPLE', len(node.bases))
404391 self._makeClosure(gen, 0)
405391 self.emit('CALL_FUNCTION', 0)
406391 self.emit('BUILD_CLASS')
407391 self.storeName(node.name)
408n/a
409n/a # The rest are standard visitor methods
410n/a
411n/a # The next few implement control-flow statements
412n/a
4132 def visitIf(self, node):
414116 end = self.newBlock()
415116 numtests = len(node.tests)
416234 for i in range(numtests):
417118 test, suite = node.tests[i]
418118 if is_constant_false(test):
419n/a # XXX will need to check generator stuff here
4200 continue
421118 self.set_lineno(test)
422118 self.visit(test)
423118 nextTest = self.newBlock()
424118 self.emit('POP_JUMP_IF_FALSE', nextTest)
425118 self.nextBlock()
426118 self.visit(suite)
427118 self.emit('JUMP_FORWARD', end)
428118 self.startBlock(nextTest)
429116 if node.else_:
43026 self.visit(node.else_)
431116 self.nextBlock(end)
432n/a
4332 def visitWhile(self, node):
43412 self.set_lineno(node)
435n/a
43612 loop = self.newBlock()
43712 else_ = self.newBlock()
438n/a
43912 after = self.newBlock()
44012 self.emit('SETUP_LOOP', after)
441n/a
44212 self.nextBlock(loop)
44312 self.setups.push((LOOP, loop))
444n/a
44512 self.set_lineno(node, force=True)
44612 self.visit(node.test)
44712 self.emit('POP_JUMP_IF_FALSE', else_ or after)
448n/a
44912 self.nextBlock()
45012 self.visit(node.body)
45112 self.emit('JUMP_ABSOLUTE', loop)
452n/a
45312 self.startBlock(else_) # or just the POPs if not else clause
45412 self.emit('POP_BLOCK')
45512 self.setups.pop()
45612 if node.else_:
4570 self.visit(node.else_)
45812 self.nextBlock(after)
459n/a
4602 def visitFor(self, node):
46190 start = self.newBlock()
46290 anchor = self.newBlock()
46390 after = self.newBlock()
46490 self.setups.push((LOOP, start))
465n/a
46690 self.set_lineno(node)
46790 self.emit('SETUP_LOOP', after)
46890 self.visit(node.list)
46990 self.emit('GET_ITER')
470n/a
47190 self.nextBlock(start)
47290 self.set_lineno(node, force=1)
47390 self.emit('FOR_ITER', anchor)
47490 self.visit(node.assign)
47590 self.visit(node.body)
47690 self.emit('JUMP_ABSOLUTE', start)
47790 self.nextBlock(anchor)
47890 self.emit('POP_BLOCK')
47990 self.setups.pop()
48090 if node.else_:
4810 self.visit(node.else_)
48290 self.nextBlock(after)
483n/a
4842 def visitBreak(self, node):
4850 if not self.setups:
4860 raise SyntaxError, "'break' outside loop (%s, %d)" % \
4870 (node.filename, node.lineno)
4880 self.set_lineno(node)
4890 self.emit('BREAK_LOOP')
490n/a
4912 def visitContinue(self, node):
4923 if not self.setups:
4930 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
4940 (node.filename, node.lineno)
4953 kind, block = self.setups.top()
4963 if kind == LOOP:
4973 self.set_lineno(node)
4983 self.emit('JUMP_ABSOLUTE', block)
4993 self.nextBlock()
5000 elif kind == EXCEPT or kind == TRY_FINALLY:
5010 self.set_lineno(node)
502n/a # find the block that starts the loop
5030 top = len(self.setups)
5040 while top > 0:
5050 top = top - 1
5060 kind, loop_block = self.setups[top]
5070 if kind == LOOP:
5080 break
5090 if kind != LOOP:
5100 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
5110 (node.filename, node.lineno)
5120 self.emit('CONTINUE_LOOP', loop_block)
5130 self.nextBlock()
5140 elif kind == END_FINALLY:
5150 msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
5160 raise SyntaxError, msg % (node.filename, node.lineno)
517n/a
5182 def visitTest(self, node, jump):
51917 end = self.newBlock()
52034 for child in node.nodes[:-1]:
52117 self.visit(child)
52217 self.emit(jump, end)
52317 self.nextBlock()
52417 self.visit(node.nodes[-1])
52517 self.nextBlock(end)
526n/a
5272 def visitAnd(self, node):
5289 self.visitTest(node, 'JUMP_IF_FALSE_OR_POP')
529n/a
5302 def visitOr(self, node):
5318 self.visitTest(node, 'JUMP_IF_TRUE_OR_POP')
532n/a
5332 def visitIfExp(self, node):
5340 endblock = self.newBlock()
5350 elseblock = self.newBlock()
5360 self.visit(node.test)
5370 self.emit('POP_JUMP_IF_FALSE', elseblock)
5380 self.visit(node.then)
5390 self.emit('JUMP_FORWARD', endblock)
5400 self.nextBlock(elseblock)
5410 self.visit(node.else_)
5420 self.nextBlock(endblock)
543n/a
5442 def visitCompare(self, node):
545232 self.visit(node.expr)
546232 cleanup = self.newBlock()
547235 for op, code in node.ops[:-1]:
5483 self.visit(code)
5493 self.emit('DUP_TOP')
5503 self.emit('ROT_THREE')
5513 self.emit('COMPARE_OP', op)
5523 self.emit('JUMP_IF_FALSE_OR_POP', cleanup)
5533 self.nextBlock()
554n/a # now do the last comparison
555232 if node.ops:
556232 op, code = node.ops[-1]
557232 self.visit(code)
558232 self.emit('COMPARE_OP', op)
559232 if len(node.ops) > 1:
5603 end = self.newBlock()
5613 self.emit('JUMP_FORWARD', end)
5623 self.startBlock(cleanup)
5633 self.emit('ROT_TWO')
5643 self.emit('POP_TOP')
5653 self.nextBlock(end)
566n/a
567n/a # list comprehensions
5682 def visitListComp(self, node):
56913 self.set_lineno(node)
570n/a # setup list
57113 self.emit('BUILD_LIST', 0)
572n/a
57313 stack = []
57426 for i, for_ in zip(range(len(node.quals)), node.quals):
57513 start, anchor = self.visit(for_)
57613 cont = None
57717 for if_ in for_.ifs:
5784 if cont is None:
5794 cont = self.newBlock()
5804 self.visit(if_, cont)
58113 stack.insert(0, (start, cont, anchor))
582n/a
58313 self.visit(node.expr)
58413 self.emit('LIST_APPEND', len(node.quals) + 1)
585n/a
58626 for start, cont, anchor in stack:
58713 if cont:
5884 self.nextBlock(cont)
58913 self.emit('JUMP_ABSOLUTE', start)
59013 self.startBlock(anchor)
591n/a
5922 def visitSetComp(self, node):
5932 self.set_lineno(node)
594n/a # setup list
5952 self.emit('BUILD_SET', 0)
596n/a
5972 stack = []
5985 for i, for_ in zip(range(len(node.quals)), node.quals):
5993 start, anchor = self.visit(for_)
6003 cont = None
6015 for if_ in for_.ifs:
6022 if cont is None:
6032 cont = self.newBlock()
6042 self.visit(if_, cont)
6053 stack.insert(0, (start, cont, anchor))
606n/a
6072 self.visit(node.expr)
6082 self.emit('SET_ADD', len(node.quals) + 1)
609n/a
6105 for start, cont, anchor in stack:
6113 if cont:
6122 self.nextBlock(cont)
6133 self.emit('JUMP_ABSOLUTE', start)
6143 self.startBlock(anchor)
615n/a
6162 def visitDictComp(self, node):
6172 self.set_lineno(node)
618n/a # setup list
6192 self.emit('BUILD_MAP', 0)
620n/a
6212 stack = []
6225 for i, for_ in zip(range(len(node.quals)), node.quals):
6233 start, anchor = self.visit(for_)
6243 cont = None
6255 for if_ in for_.ifs:
6262 if cont is None:
6272 cont = self.newBlock()
6282 self.visit(if_, cont)
6293 stack.insert(0, (start, cont, anchor))
630n/a
6312 self.visit(node.value)
6322 self.visit(node.key)
6332 self.emit('MAP_ADD', len(node.quals) + 1)
634n/a
6355 for start, cont, anchor in stack:
6363 if cont:
6372 self.nextBlock(cont)
6383 self.emit('JUMP_ABSOLUTE', start)
6393 self.startBlock(anchor)
640n/a
6412 def visitListCompFor(self, node):
64219 start = self.newBlock()
64319 anchor = self.newBlock()
644n/a
64519 self.visit(node.list)
64619 self.emit('GET_ITER')
64719 self.nextBlock(start)
64819 self.set_lineno(node, force=True)
64919 self.emit('FOR_ITER', anchor)
65019 self.nextBlock()
65119 self.visit(node.assign)
65219 return start, anchor
653n/a
6542 def visitListCompIf(self, node, branch):
6558 self.set_lineno(node, force=True)
6568 self.visit(node.test)
6578 self.emit('POP_JUMP_IF_FALSE', branch)
6588 self.newBlock()
659n/a
6602 def _makeClosure(self, gen, args):
6611028 frees = gen.scope.get_free_vars()
6621028 if frees:
663297 for name in frees:
664157 self.emit('LOAD_CLOSURE', name)
665140 self.emit('BUILD_TUPLE', len(frees))
666140 self.emit('LOAD_CONST', gen)
667140 self.emit('MAKE_CLOSURE', args)
668n/a else:
669888 self.emit('LOAD_CONST', gen)
670888 self.emit('MAKE_FUNCTION', args)
671n/a
6722 def visitGenExpr(self, node):
6732 gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
6742 self.get_module())
6752 walk(node.code, gen)
6762 gen.finish()
6772 self.set_lineno(node)
6782 self._makeClosure(gen, 0)
679n/a # precomputation of outmost iterable
6802 self.visit(node.code.quals[0].iter)
6812 self.emit('GET_ITER')
6822 self.emit('CALL_FUNCTION', 1)
683n/a
6842 def visitGenExprInner(self, node):
6852 self.set_lineno(node)
686n/a # setup list
687n/a
6882 stack = []
6895 for i, for_ in zip(range(len(node.quals)), node.quals):
6903 start, anchor, end = self.visit(for_)
6913 cont = None
6925 for if_ in for_.ifs:
6932 if cont is None:
6942 cont = self.newBlock()
6952 self.visit(if_, cont)
6963 stack.insert(0, (start, cont, anchor, end))
697n/a
6982 self.visit(node.expr)
6992 self.emit('YIELD_VALUE')
7002 self.emit('POP_TOP')
701n/a
7025 for start, cont, anchor, end in stack:
7033 if cont:
7042 self.nextBlock(cont)
7053 self.emit('JUMP_ABSOLUTE', start)
7063 self.startBlock(anchor)
7073 self.emit('POP_BLOCK')
7083 self.setups.pop()
7093 self.nextBlock(end)
710n/a
7112 self.emit('LOAD_CONST', None)
712n/a
7132 def visitGenExprFor(self, node):
7143 start = self.newBlock()
7153 anchor = self.newBlock()
7163 end = self.newBlock()
717n/a
7183 self.setups.push((LOOP, start))
7193 self.emit('SETUP_LOOP', end)
720n/a
7213 if node.is_outmost:
7222 self.loadName('.0')
723n/a else:
7241 self.visit(node.iter)
7251 self.emit('GET_ITER')
726n/a
7273 self.nextBlock(start)
7283 self.set_lineno(node, force=True)
7293 self.emit('FOR_ITER', anchor)
7303 self.nextBlock()
7313 self.visit(node.assign)
7323 return start, anchor, end
733n/a
7342 def visitGenExprIf(self, node, branch):
7352 self.set_lineno(node, force=True)
7362 self.visit(node.test)
7372 self.emit('POP_JUMP_IF_FALSE', branch)
7382 self.newBlock()
739n/a
740n/a # exception related
741n/a
7422 def visitAssert(self, node):
743n/a # XXX would be interesting to implement this via a
744n/a # transformation of the AST before this stage
745n/a if __debug__:
7463 end = self.newBlock()
7473 self.set_lineno(node)
748n/a # XXX AssertionError appears to be special case -- it is always
749n/a # loaded as a global even if there is a local name. I guess this
750n/a # is a sort of renaming op.
7513 self.nextBlock()
7523 self.visit(node.test)
7533 self.emit('POP_JUMP_IF_TRUE', end)
7543 self.nextBlock()
7553 self.emit('LOAD_GLOBAL', 'AssertionError')
7563 if node.fail:
7571 self.visit(node.fail)
7581 self.emit('RAISE_VARARGS', 2)
759n/a else:
7602 self.emit('RAISE_VARARGS', 1)
7613 self.nextBlock(end)
762n/a
7632 def visitRaise(self, node):
76428 self.set_lineno(node)
76528 n = 0
76628 if node.expr1:
76727 self.visit(node.expr1)
76827 n = n + 1
76928 if node.expr2:
77012 self.visit(node.expr2)
77112 n = n + 1
77228 if node.expr3:
7730 self.visit(node.expr3)
7740 n = n + 1
77528 self.emit('RAISE_VARARGS', n)
776n/a
7772 def visitTryExcept(self, node):
778132 body = self.newBlock()
779132 handlers = self.newBlock()
780132 end = self.newBlock()
781132 if node.else_:
78298 lElse = self.newBlock()
783n/a else:
78434 lElse = end
785132 self.set_lineno(node)
786132 self.emit('SETUP_EXCEPT', handlers)
787132 self.nextBlock(body)
788132 self.setups.push((EXCEPT, body))
789132 self.visit(node.body)
790132 self.emit('POP_BLOCK')
791132 self.setups.pop()
792132 self.emit('JUMP_FORWARD', lElse)
793132 self.startBlock(handlers)
794n/a
795132 last = len(node.handlers) - 1
796266 for i in range(len(node.handlers)):
797134 expr, target, body = node.handlers[i]
798134 self.set_lineno(expr)
799134 if expr:
800127 self.emit('DUP_TOP')
801127 self.visit(expr)
802127 self.emit('COMPARE_OP', 'exception match')
803127 next = self.newBlock()
804127 self.emit('POP_JUMP_IF_FALSE', next)
805127 self.nextBlock()
806134 self.emit('POP_TOP')
807134 if target:
80819 self.visit(target)
809n/a else:
810115 self.emit('POP_TOP')
811134 self.emit('POP_TOP')
812134 self.visit(body)
813134 self.emit('JUMP_FORWARD', end)
814134 if expr:
815127 self.nextBlock(next)
816n/a else:
8177 self.nextBlock()
818132 self.emit('END_FINALLY')
819132 if node.else_:
82098 self.nextBlock(lElse)
82198 self.visit(node.else_)
822132 self.nextBlock(end)
823n/a
8242 def visitTryFinally(self, node):
82512 body = self.newBlock()
82612 final = self.newBlock()
82712 self.set_lineno(node)
82812 self.emit('SETUP_FINALLY', final)
82912 self.nextBlock(body)
83012 self.setups.push((TRY_FINALLY, body))
83112 self.visit(node.body)
83212 self.emit('POP_BLOCK')
83312 self.setups.pop()
83412 self.emit('LOAD_CONST', None)
83512 self.nextBlock(final)
83612 self.setups.push((END_FINALLY, final))
83712 self.visit(node.final)
83812 self.emit('END_FINALLY')
83912 self.setups.pop()
840n/a
8412 __with_count = 0
842n/a
8432 def visitWith(self, node):
8448 body = self.newBlock()
8458 final = self.newBlock()
8468 self.__with_count += 1
8478 valuevar = "_[%d]" % self.__with_count
8488 self.set_lineno(node)
8498 self.visit(node.expr)
8508 self.emit('DUP_TOP')
8518 self.emit('LOAD_ATTR', '__exit__')
8528 self.emit('ROT_TWO')
8538 self.emit('LOAD_ATTR', '__enter__')
8548 self.emit('CALL_FUNCTION', 0)
8558 if node.vars is None:
8564 self.emit('POP_TOP')
857n/a else:
8584 self._implicitNameOp('STORE', valuevar)
8598 self.emit('SETUP_FINALLY', final)
8608 self.nextBlock(body)
8618 self.setups.push((TRY_FINALLY, body))
8628 if node.vars is not None:
8634 self._implicitNameOp('LOAD', valuevar)
8644 self._implicitNameOp('DELETE', valuevar)
8654 self.visit(node.vars)
8668 self.visit(node.body)
8678 self.emit('POP_BLOCK')
8688 self.setups.pop()
8698 self.emit('LOAD_CONST', None)
8708 self.nextBlock(final)
8718 self.setups.push((END_FINALLY, final))
8728 self.emit('WITH_CLEANUP')
8738 self.emit('END_FINALLY')
8748 self.setups.pop()
8758 self.__with_count -= 1
876n/a
877n/a # misc
878n/a
8792 def visitDiscard(self, node):
8801515 self.set_lineno(node)
8811515 self.visit(node.expr)
8821515 self.emit('POP_TOP')
883n/a
8842 def visitConst(self, node):
8853259 self.emit('LOAD_CONST', node.value)
886n/a
8872 def visitKeyword(self, node):
88839 self.emit('LOAD_CONST', node.name)
88939 self.visit(node.expr)
890n/a
8912 def visitGlobal(self, node):
892n/a # no code to generate
8937 pass
894n/a
8952 def visitName(self, node):
8966804 self.set_lineno(node)
8976804 self.loadName(node.name)
898n/a
8992 def visitPass(self, node):
900262 self.set_lineno(node)
901n/a
9022 def visitImport(self, node):
90348 self.set_lineno(node)
90448 level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1
905101 for name, alias in node.names:
90653 if VERSION > 1:
90753 self.emit('LOAD_CONST', level)
90853 self.emit('LOAD_CONST', None)
90953 self.emit('IMPORT_NAME', name)
91053 mod = name.split(".")[0]
91153 if alias:
9126 self._resolveDots(name)
9136 self.storeName(alias)
914n/a else:
91547 self.storeName(mod)
916n/a
9172 def visitFrom(self, node):
91815 self.set_lineno(node)
91915 level = node.level
92015 if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
92115 level = -1
92247 fromlist = tuple(name for (name, alias) in node.names)
92315 if VERSION > 1:
92415 self.emit('LOAD_CONST', level)
92515 self.emit('LOAD_CONST', fromlist)
92615 self.emit('IMPORT_NAME', node.modname)
92732 for name, alias in node.names:
92817 if VERSION > 1:
92917 if name == '*':
9300 self.namespace = 0
9310 self.emit('IMPORT_STAR')
932n/a # There can only be one name w/ from ... import *
9330 assert len(node.names) == 1
9340 return
935n/a else:
93617 self.emit('IMPORT_FROM', name)
93717 self._resolveDots(name)
93817 self.storeName(alias or name)
939n/a else:
9400 self.emit('IMPORT_FROM', name)
94115 self.emit('POP_TOP')
942n/a
9432 def _resolveDots(self, name):
94423 elts = name.split(".")
94523 if len(elts) == 1:
94623 return
9470 for elt in elts[1:]:
9480 self.emit('LOAD_ATTR', elt)
949n/a
9502 def visitGetattr(self, node):
9512526 self.visit(node.expr)
9522526 self.emit('LOAD_ATTR', self.mangle(node.attrname))
953n/a
954n/a # next five implement assignments
955n/a
9562 def visitAssign(self, node):
957971 self.set_lineno(node)
958971 self.visit(node.expr)
959971 dups = len(node.nodes) - 1
9601946 for i in range(len(node.nodes)):
961975 elt = node.nodes[i]
962975 if i < dups:
9634 self.emit('DUP_TOP')
964975 if isinstance(elt, ast.Node):
965975 self.visit(elt)
966n/a
9672 def visitAssName(self, node):
968829 if node.flags == 'OP_ASSIGN':
969810 self.storeName(node.name)
97019 elif node.flags == 'OP_DELETE':
97119 self.set_lineno(node)
97219 self.delName(node.name)
973n/a else:
9740 print "oops", node.flags
975n/a
9762 def visitAssAttr(self, node):
977337 self.visit(node.expr)
978337 if node.flags == 'OP_ASSIGN':
979306 self.emit('STORE_ATTR', self.mangle(node.attrname))
98031 elif node.flags == 'OP_DELETE':
98131 self.emit('DELETE_ATTR', self.mangle(node.attrname))
982n/a else:
9830 print "warning: unexpected flags:", node.flags
9840 print node
985n/a
9862 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
98735 if findOp(node) != 'OP_DELETE':
98835 self.emit(op, len(node.nodes))
989114 for child in node.nodes:
99079 self.visit(child)
991n/a
9922 if VERSION > 1:
9932 visitAssTuple = _visitAssSequence
9942 visitAssList = _visitAssSequence
995n/a else:
9960 def visitAssTuple(self, node):
9970 self._visitAssSequence(node, 'UNPACK_TUPLE')
998n/a
9990 def visitAssList(self, node):
10000 self._visitAssSequence(node, 'UNPACK_LIST')
1001n/a
1002n/a # augmented assignment
1003n/a
10042 def visitAugAssign(self, node):
100517 self.set_lineno(node)
100617 aug_node = wrap_aug(node.node)
100717 self.visit(aug_node, "load")
100817 self.visit(node.expr)
100917 self.emit(self._augmented_opcode[node.op])
101017 self.visit(aug_node, "store")
1011n/a
10122 _augmented_opcode = {
10132 '+=' : 'INPLACE_ADD',
10142 '-=' : 'INPLACE_SUBTRACT',
10152 '*=' : 'INPLACE_MULTIPLY',
10162 '/=' : 'INPLACE_DIVIDE',
10172 '//=': 'INPLACE_FLOOR_DIVIDE',
10182 '%=' : 'INPLACE_MODULO',
10192 '**=': 'INPLACE_POWER',
10202 '>>=': 'INPLACE_RSHIFT',
10212 '<<=': 'INPLACE_LSHIFT',
10222 '&=' : 'INPLACE_AND',
10232 '^=' : 'INPLACE_XOR',
10242 '|=' : 'INPLACE_OR',
1025n/a }
1026n/a
10272 def visitAugName(self, node, mode):
102822 if mode == "load":
102911 self.loadName(node.name)
103011 elif mode == "store":
103111 self.storeName(node.name)
1032n/a
10332 def visitAugGetattr(self, node, mode):
103412 if mode == "load":
10356 self.visit(node.expr)
10366 self.emit('DUP_TOP')
10376 self.emit('LOAD_ATTR', self.mangle(node.attrname))
10386 elif mode == "store":
10396 self.emit('ROT_TWO')
10406 self.emit('STORE_ATTR', self.mangle(node.attrname))
1041n/a
10422 def visitAugSlice(self, node, mode):
10430 if mode == "load":
10440 self.visitSlice(node, 1)
10450 elif mode == "store":
10460 slice = 0
10470 if node.lower:
10480 slice = slice | 1
10490 if node.upper:
10500 slice = slice | 2
10510 if slice == 0:
10520 self.emit('ROT_TWO')
10530 elif slice == 3:
10540 self.emit('ROT_FOUR')
1055n/a else:
10560 self.emit('ROT_THREE')
10570 self.emit('STORE_SLICE+%d' % slice)
1058n/a
10592 def visitAugSubscript(self, node, mode):
10600 if mode == "load":
10610 self.visitSubscript(node, 1)
10620 elif mode == "store":
10630 self.emit('ROT_THREE')
10640 self.emit('STORE_SUBSCR')
1065n/a
10662 def visitExec(self, node):
10679 self.visit(node.expr)
10689 if node.locals is None:
10693 self.emit('LOAD_CONST', None)
1070n/a else:
10716 self.visit(node.locals)
10729 if node.globals is None:
10739 self.emit('DUP_TOP')
1074n/a else:
10750 self.visit(node.globals)
10769 self.emit('EXEC_STMT')
1077n/a
10782 def visitCallFunc(self, node):
10792955 pos = 0
10802955 kw = 0
10812955 self.set_lineno(node)
10822955 self.visit(node.node)
10836897 for arg in node.args:
10843942 self.visit(arg)
10853942 if isinstance(arg, ast.Keyword):
108639 kw = kw + 1
1087n/a else:
10883903 pos = pos + 1
10892955 if node.star_args is not None:
109012 self.visit(node.star_args)
10912955 if node.dstar_args is not None:
109210 self.visit(node.dstar_args)
10932955 have_star = node.star_args is not None
10942955 have_dstar = node.dstar_args is not None
10952955 opcode = callfunc_opcode_info[have_star, have_dstar]
10962955 self.emit(opcode, kw << 8 | pos)
1097n/a
10982 def visitPrint(self, node, newline=0):
10998 self.set_lineno(node)
11008 if node.dest:
11014 self.visit(node.dest)
110217 for child in node.nodes:
11039 if node.dest:
11045 self.emit('DUP_TOP')
11059 self.visit(child)
11069 if node.dest:
11075 self.emit('ROT_TWO')
11085 self.emit('PRINT_ITEM_TO')
1109n/a else:
11104 self.emit('PRINT_ITEM')
11118 if node.dest and not newline:
11120 self.emit('POP_TOP')
1113n/a
11142 def visitPrintnl(self, node):
11158 self.visitPrint(node, newline=1)
11168 if node.dest:
11174 self.emit('PRINT_NEWLINE_TO')
1118n/a else:
11194 self.emit('PRINT_NEWLINE')
1120n/a
11212 def visitReturn(self, node):
1122280 self.set_lineno(node)
1123280 self.visit(node.value)
1124280 self.emit('RETURN_VALUE')
1125n/a
11262 def visitYield(self, node):
11272 self.set_lineno(node)
11282 self.visit(node.value)
11292 self.emit('YIELD_VALUE')
1130n/a
1131n/a # slice and subscript stuff
1132n/a
11332 def visitSlice(self, node, aug_flag=None):
1134n/a # aug_flag is used by visitAugSlice
113534 self.visit(node.expr)
113634 slice = 0
113734 if node.lower:
113818 self.visit(node.lower)
113918 slice = slice | 1
114034 if node.upper:
114120 self.visit(node.upper)
114220 slice = slice | 2
114334 if aug_flag:
11440 if slice == 0:
11450 self.emit('DUP_TOP')
11460 elif slice == 3:
11470 self.emit('DUP_TOPX', 3)
1148n/a else:
11490 self.emit('DUP_TOPX', 2)
115034 if node.flags == 'OP_APPLY':
115129 self.emit('SLICE+%d' % slice)
11525 elif node.flags == 'OP_ASSIGN':
11533 self.emit('STORE_SLICE+%d' % slice)
11542 elif node.flags == 'OP_DELETE':
11552 self.emit('DELETE_SLICE+%d' % slice)
1156n/a else:
11570 print "weird slice", node.flags
11580 raise
1159n/a
11602 def visitSubscript(self, node, aug_flag=None):
1161148 self.visit(node.expr)
1162296 for sub in node.subs:
1163148 self.visit(sub)
1164148 if len(node.subs) > 1:
11650 self.emit('BUILD_TUPLE', len(node.subs))
1166148 if aug_flag:
11670 self.emit('DUP_TOPX', 2)
1168148 if node.flags == 'OP_APPLY':
1169110 self.emit('BINARY_SUBSCR')
117038 elif node.flags == 'OP_ASSIGN':
117135 self.emit('STORE_SUBSCR')
11723 elif node.flags == 'OP_DELETE':
11733 self.emit('DELETE_SUBSCR')
1174n/a
1175n/a # binary ops
1176n/a
11772 def binaryOp(self, node, op):
1178253 self.visit(node.left)
1179253 self.visit(node.right)
1180253 self.emit(op)
1181n/a
11822 def visitAdd(self, node):
118393 return self.binaryOp(node, 'BINARY_ADD')
1184n/a
11852 def visitSub(self, node):
11865 return self.binaryOp(node, 'BINARY_SUBTRACT')
1187n/a
11882 def visitMul(self, node):
118946 return self.binaryOp(node, 'BINARY_MULTIPLY')
1190n/a
11912 def visitDiv(self, node):
11924 return self.binaryOp(node, self._div_op)
1193n/a
11942 def visitFloorDiv(self, node):
119513 return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
1196n/a
11972 def visitMod(self, node):
119878 return self.binaryOp(node, 'BINARY_MODULO')
1199n/a
12002 def visitPower(self, node):
12014 return self.binaryOp(node, 'BINARY_POWER')
1202n/a
12032 def visitLeftShift(self, node):
12046 return self.binaryOp(node, 'BINARY_LSHIFT')
1205n/a
12062 def visitRightShift(self, node):
12074 return self.binaryOp(node, 'BINARY_RSHIFT')
1208n/a
1209n/a # unary ops
1210n/a
12112 def unaryOp(self, node, op):
121291 self.visit(node.expr)
121391 self.emit(op)
1214n/a
12152 def visitInvert(self, node):
12160 return self.unaryOp(node, 'UNARY_INVERT')
1217n/a
12182 def visitUnarySub(self, node):
121956 return self.unaryOp(node, 'UNARY_NEGATIVE')
1220n/a
12212 def visitUnaryAdd(self, node):
12224 return self.unaryOp(node, 'UNARY_POSITIVE')
1223n/a
12242 def visitUnaryInvert(self, node):
12250 return self.unaryOp(node, 'UNARY_INVERT')
1226n/a
12272 def visitNot(self, node):
122831 return self.unaryOp(node, 'UNARY_NOT')
1229n/a
12302 def visitBackquote(self, node):
12310 return self.unaryOp(node, 'UNARY_CONVERT')
1232n/a
1233n/a # bit ops
1234n/a
12352 def bitOp(self, nodes, op):
12363 self.visit(nodes[0])
12376 for node in nodes[1:]:
12383 self.visit(node)
12393 self.emit(op)
1240n/a
12412 def visitBitand(self, node):
12421 return self.bitOp(node.nodes, 'BINARY_AND')
1243n/a
12442 def visitBitor(self, node):
12451 return self.bitOp(node.nodes, 'BINARY_OR')
1246n/a
12472 def visitBitxor(self, node):
12481 return self.bitOp(node.nodes, 'BINARY_XOR')
1249n/a
1250n/a # object constructors
1251n/a
12522 def visitEllipsis(self, node):
12530 self.emit('LOAD_CONST', Ellipsis)
1254n/a
12552 def visitTuple(self, node):
1256508 self.set_lineno(node)
12571781 for elt in node.nodes:
12581273 self.visit(elt)
1259508 self.emit('BUILD_TUPLE', len(node.nodes))
1260n/a
12612 def visitList(self, node):
1262313 self.set_lineno(node)
1263979 for elt in node.nodes:
1264666 self.visit(elt)
1265313 self.emit('BUILD_LIST', len(node.nodes))
1266n/a
12672 def visitSet(self, node):
12682 self.set_lineno(node)
12698 for elt in node.nodes:
12706 self.visit(elt)
12712 self.emit('BUILD_SET', len(node.nodes))
1272n/a
12732 def visitSliceobj(self, node):
12740 for child in node.nodes:
12750 self.visit(child)
12760 self.emit('BUILD_SLICE', len(node.nodes))
1277n/a
12782 def visitDict(self, node):
1279101 self.set_lineno(node)
1280101 self.emit('BUILD_MAP', 0)
1281236 for k, v in node.items:
1282135 self.emit('DUP_TOP')
1283135 self.visit(k)
1284135 self.visit(v)
1285135 self.emit('ROT_THREE')
1286135 self.emit('STORE_SUBSCR')
1287n/a
12884class NestedScopeMixin:
12892 """Defines initClass() for nested scoping (Python 2.2-compatible)"""
12902 def initClass(self):
12916 self.__class__.NameFinder = LocalNameFinder
12926 self.__class__.FunctionGen = FunctionCodeGenerator
12936 self.__class__.ClassGen = ClassCodeGenerator
1294n/a
12954class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
12962 __super_init = CodeGenerator.__init__
1297n/a
12982 scopes = None
1299n/a
13002 def __init__(self, tree):
130119 self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
130219 self.futures = future.find_futures(tree)
130319 self.__super_init()
130419 walk(tree, self)
1305n/a
13062 def get_module(self):
130792 return self
1308n/a
13094class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
13102 __super_init = CodeGenerator.__init__
1311n/a
13122 scopes = None
13132 futures = ()
1314n/a
13152 def __init__(self, tree):
13169 self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
13179 self.__super_init()
13189 walk(tree, self)
1319n/a
13202 def get_module(self):
132110 return self
1322n/a
13234class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
1324n/a
13252 __super_init = CodeGenerator.__init__
1326n/a
13272 scopes = None
13282 futures = ()
1329n/a
13302 def __init__(self, tree):
13313 self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
13323 self.__super_init()
13333 self.set_lineno(tree)
13343 walk(tree, self)
13353 self.emit('RETURN_VALUE')
1336n/a
13372 def get_module(self):
13383 return self
1339n/a
13402 def visitDiscard(self, node):
1341n/a # XXX Discard means it's an expression. Perhaps this is a bad
1342n/a # name.
13430 self.visit(node.expr)
13440 self.emit('PRINT_EXPR')
1345n/a
13464class AbstractFunctionCode:
13472 optimized = 1
13482 lambdaCount = 0
1349n/a
13502 def __init__(self, func, scopes, isLambda, class_name, mod):
1351637 self.class_name = class_name
1352637 self.module = mod
1353637 if isLambda:
135420 klass = FunctionCodeGenerator
135520 name = "<lambda.%d>" % klass.lambdaCount
135620 klass.lambdaCount = klass.lambdaCount + 1
1357n/a else:
1358617 name = func.name
1359n/a
1360637 args, hasTupleArg = generateArgList(func.argnames)
1361637 self.graph = pyassem.PyFlowGraph(name, func.filename, args,
1362637 optimized=1)
1363637 self.isLambda = isLambda
1364637 self.super_init()
1365n/a
1366637 if not isLambda and func.doc:
136721 self.setDocstring(func.doc)
1368n/a
1369637 lnf = walk(func.code, self.NameFinder(args), verbose=0)
1370637 self.locals.push(lnf.getLocals())
1371637 if func.varargs:
137224 self.graph.setFlag(CO_VARARGS)
1373637 if func.kwargs:
13744 self.graph.setFlag(CO_VARKEYWORDS)
1375637 self.set_lineno(func)
1376637 if hasTupleArg:
13770 self.generateArgUnpack(func.argnames)
1378n/a
13792 def get_module(self):
13801059 return self.module
1381n/a
13822 def finish(self):
1383637 self.graph.startExitBlock()
1384637 if not self.isLambda:
1385617 self.emit('LOAD_CONST', None)
1386637 self.emit('RETURN_VALUE')
1387n/a
13882 def generateArgUnpack(self, args):
13890 for i in range(len(args)):
13900 arg = args[i]
13910 if isinstance(arg, tuple):
13920 self.emit('LOAD_FAST', '.%d' % (i * 2))
13930 self.unpackSequence(arg)
1394n/a
13952 def unpackSequence(self, tup):
13960 if VERSION > 1:
13970 self.emit('UNPACK_SEQUENCE', len(tup))
1398n/a else:
13990 self.emit('UNPACK_TUPLE', len(tup))
14000 for elt in tup:
14010 if isinstance(elt, tuple):
14020 self.unpackSequence(elt)
1403n/a else:
14040 self._nameOp('STORE', elt)
1405n/a
14062 unpackTuple = unpackSequence
1407n/a
14084class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
14092 CodeGenerator):
14102 super_init = CodeGenerator.__init__ # call be other init
14112 scopes = None
1412n/a
14132 __super_init = AbstractFunctionCode.__init__
1414n/a
14152 def __init__(self, func, scopes, isLambda, class_name, mod):
1416635 self.scopes = scopes
1417635 self.scope = scopes[func]
1418635 self.__super_init(func, scopes, isLambda, class_name, mod)
1419635 self.graph.setFreeVars(self.scope.get_free_vars())
1420635 self.graph.setCellVars(self.scope.get_cell_vars())
1421635 if self.scope.generator is not None:
14222 self.graph.setFlag(CO_GENERATOR)
1423n/a
14244class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
14252 CodeGenerator):
14262 super_init = CodeGenerator.__init__ # call be other init
14272 scopes = None
1428n/a
14292 __super_init = AbstractFunctionCode.__init__
1430n/a
14312 def __init__(self, gexp, scopes, class_name, mod):
14322 self.scopes = scopes
14332 self.scope = scopes[gexp]
14342 self.__super_init(gexp, scopes, 1, class_name, mod)
14352 self.graph.setFreeVars(self.scope.get_free_vars())
14362 self.graph.setCellVars(self.scope.get_cell_vars())
14372 self.graph.setFlag(CO_GENERATOR)
1438n/a
14394class AbstractClassCode:
1440n/a
14412 def __init__(self, klass, scopes, module):
1442391 self.class_name = klass.name
1443391 self.module = module
1444391 self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
1445391 optimized=0, klass=1)
1446391 self.super_init()
1447391 lnf = walk(klass.code, self.NameFinder(), verbose=0)
1448391 self.locals.push(lnf.getLocals())
1449391 self.graph.setFlag(CO_NEWLOCALS)
1450391 if klass.doc:
14517 self.setDocstring(klass.doc)
1452n/a
14532 def get_module(self):
1454923 return self.module
1455n/a
14562 def finish(self):
1457391 self.graph.startExitBlock()
1458391 self.emit('LOAD_LOCALS')
1459391 self.emit('RETURN_VALUE')
1460n/a
14614class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
14622 super_init = CodeGenerator.__init__
14632 scopes = None
1464n/a
14652 __super_init = AbstractClassCode.__init__
1466n/a
14672 def __init__(self, klass, scopes, module):
1468391 self.scopes = scopes
1469391 self.scope = scopes[klass]
1470391 self.__super_init(klass, scopes, module)
1471391 self.graph.setFreeVars(self.scope.get_free_vars())
1472391 self.graph.setCellVars(self.scope.get_cell_vars())
1473391 self.set_lineno(klass)
1474391 self.emit("LOAD_GLOBAL", "__name__")
1475391 self.storeName("__module__")
1476391 if klass.doc:
14777 self.emit("LOAD_CONST", klass.doc)
14787 self.storeName('__doc__')
1479n/a
14802def generateArgList(arglist):
1481n/a """Generate an arg list marking TupleArgs"""
1482637 args = []
1483637 extra = []
1484637 count = 0
14851582 for i in range(len(arglist)):
1486945 elt = arglist[i]
1487945 if isinstance(elt, str):
1488945 args.append(elt)
14890 elif isinstance(elt, tuple):
14900 args.append(TupleArg(i * 2, elt))
14910 extra.extend(misc.flatten(elt))
14920 count = count + 1
1493n/a else:
14940 raise ValueError, "unexpect argument type:", elt
1495637 return args + extra, count
1496n/a
14972def findOp(node):
1498n/a """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
149935 v = OpFinder()
150035 walk(node, v, verbose=0)
150135 return v.op
1502n/a
15034class OpFinder:
15042 def __init__(self):
150535 self.op = None
15062 def visitAssName(self, node):
150781 if self.op is None:
150835 self.op = node.flags
150946 elif self.op != node.flags:
15100 raise ValueError, "mixed ops in stmt"
15112 visitAssAttr = visitAssName
15122 visitSubscript = visitAssName
1513n/a
15144class Delegator:
1515n/a """Base class to support delegation for augmented assignment nodes
1516n/a
1517n/a To generator code for augmented assignments, we use the following
1518n/a wrapper classes. In visitAugAssign, the left-hand expression node
1519n/a is visited twice. The first time the visit uses the normal method
1520n/a for that node . The second time the visit uses a different method
1521n/a that generates the appropriate code to perform the assignment.
1522n/a These delegator classes wrap the original AST nodes in order to
1523n/a support the variant visit methods.
15242 """
15252 def __init__(self, obj):
152617 self.obj = obj
1527n/a
15282 def __getattr__(self, attr):
152940 return getattr(self.obj, attr)
1530n/a
15314class AugGetattr(Delegator):
15322 pass
1533n/a
15344class AugName(Delegator):
15352 pass
1536n/a
15374class AugSlice(Delegator):
15382 pass
1539n/a
15404class AugSubscript(Delegator):
15412 pass
1542n/a
15432wrapper = {
15442 ast.Getattr: AugGetattr,
15452 ast.Name: AugName,
15462 ast.Slice: AugSlice,
15472 ast.Subscript: AugSubscript,
1548n/a }
1549n/a
15502def wrap_aug(node):
155117 return wrapper[node.__class__](node)
1552n/a
15532if __name__ == "__main__":
15540 for file in sys.argv[1:]:
15550 compileFile(file)