Home | History | Annotate | Download | only in compiler
      1 import imp
      2 import os
      3 import marshal
      4 import struct
      5 import sys
      6 from cStringIO import StringIO
      7 
      8 from compiler import ast, parse, walk, syntax
      9 from compiler import pyassem, misc, future, symbols
     10 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \
     11      SC_FREE, SC_CELL
     12 from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
     13      CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
     14      CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION)
     15 from compiler.pyassem import TupleArg
     16 
     17 # XXX The version-specific code can go, since this code only works with 2.x.
     18 # Do we have Python 1.x or Python 2.x?
     19 try:
     20     VERSION = sys.version_info[0]
     21 except AttributeError:
     22     VERSION = 1
     23 
     24 callfunc_opcode_info = {
     25     # (Have *args, Have **args) : opcode
     26     (0,0) : "CALL_FUNCTION",
     27     (1,0) : "CALL_FUNCTION_VAR",
     28     (0,1) : "CALL_FUNCTION_KW",
     29     (1,1) : "CALL_FUNCTION_VAR_KW",
     30 }
     31 
     32 LOOP = 1
     33 EXCEPT = 2
     34 TRY_FINALLY = 3
     35 END_FINALLY = 4
     36 
     37 def compileFile(filename, display=0):
     38     f = open(filename, 'U')
     39     buf = f.read()
     40     f.close()
     41     mod = Module(buf, filename)
     42     try:
     43         mod.compile(display)
     44     except SyntaxError:
     45         raise
     46     else:
     47         f = open(filename + "c", "wb")
     48         mod.dump(f)
     49         f.close()
     50 
     51 def compile(source, filename, mode, flags=None, dont_inherit=None):
     52     """Replacement for builtin compile() function"""
     53     if flags is not None or dont_inherit is not None:
     54         raise RuntimeError, "not implemented yet"
     55 
     56     if mode == "single":
     57         gen = Interactive(source, filename)
     58     elif mode == "exec":
     59         gen = Module(source, filename)
     60     elif mode == "eval":
     61         gen = Expression(source, filename)
     62     else:
     63         raise ValueError("compile() 3rd arg must be 'exec' or "
     64                          "'eval' or 'single'")
     65     gen.compile()
     66     return gen.code
     67 
     68 class AbstractCompileMode:
     69 
     70     mode = None # defined by subclass
     71 
     72     def __init__(self, source, filename):
     73         self.source = source
     74         self.filename = filename
     75         self.code = None
     76 
     77     def _get_tree(self):
     78         tree = parse(self.source, self.mode)
     79         misc.set_filename(self.filename, tree)
     80         syntax.check(tree)
     81         return tree
     82 
     83     def compile(self):
     84         pass # implemented by subclass
     85 
     86     def getCode(self):
     87         return self.code
     88 
     89 class Expression(AbstractCompileMode):
     90 
     91     mode = "eval"
     92 
     93     def compile(self):
     94         tree = self._get_tree()
     95         gen = ExpressionCodeGenerator(tree)
     96         self.code = gen.getCode()
     97 
     98 class Interactive(AbstractCompileMode):
     99 
    100     mode = "single"
    101 
    102     def compile(self):
    103         tree = self._get_tree()
    104         gen = InteractiveCodeGenerator(tree)
    105         self.code = gen.getCode()
    106 
    107 class Module(AbstractCompileMode):
    108 
    109     mode = "exec"
    110 
    111     def compile(self, display=0):
    112         tree = self._get_tree()
    113         gen = ModuleCodeGenerator(tree)
    114         if display:
    115             import pprint
    116             print pprint.pprint(tree)
    117         self.code = gen.getCode()
    118 
    119     def dump(self, f):
    120         f.write(self.getPycHeader())
    121         marshal.dump(self.code, f)
    122 
    123     MAGIC = imp.get_magic()
    124 
    125     def getPycHeader(self):
    126         # compile.c uses marshal to write a long directly, with
    127         # calling the interface that would also generate a 1-byte code
    128         # to indicate the type of the value.  simplest way to get the
    129         # same effect is to call marshal and then skip the code.
    130         mtime = os.path.getmtime(self.filename)
    131         mtime = struct.pack('<i', mtime)
    132         return self.MAGIC + mtime
    133 
    134 class LocalNameFinder:
    135     """Find local names in scope"""
    136     def __init__(self, names=()):
    137         self.names = misc.Set()
    138         self.globals = misc.Set()
    139         for name in names:
    140             self.names.add(name)
    141 
    142     # XXX list comprehensions and for loops
    143 
    144     def getLocals(self):
    145         for elt in self.globals.elements():
    146             if self.names.has_elt(elt):
    147                 self.names.remove(elt)
    148         return self.names
    149 
    150     def visitDict(self, node):
    151         pass
    152 
    153     def visitGlobal(self, node):
    154         for name in node.names:
    155             self.globals.add(name)
    156 
    157     def visitFunction(self, node):
    158         self.names.add(node.name)
    159 
    160     def visitLambda(self, node):
    161         pass
    162 
    163     def visitImport(self, node):
    164         for name, alias in node.names:
    165             self.names.add(alias or name)
    166 
    167     def visitFrom(self, node):
    168         for name, alias in node.names:
    169             self.names.add(alias or name)
    170 
    171     def visitClass(self, node):
    172         self.names.add(node.name)
    173 
    174     def visitAssName(self, node):
    175         self.names.add(node.name)
    176 
    177 def is_constant_false(node):
    178     if isinstance(node, ast.Const):
    179         if not node.value:
    180             return 1
    181     return 0
    182 
    183 class CodeGenerator:
    184     """Defines basic code generator for Python bytecode
    185 
    186     This class is an abstract base class.  Concrete subclasses must
    187     define an __init__() that defines self.graph and then calls the
    188     __init__() defined in this class.
    189 
    190     The concrete class must also define the class attributes
    191     NameFinder, FunctionGen, and ClassGen.  These attributes can be
    192     defined in the initClass() method, which is a hook for
    193     initializing these methods after all the classes have been
    194     defined.
    195     """
    196 
    197     optimized = 0 # is namespace access optimized?
    198     __initialized = None
    199     class_name = None # provide default for instance variable
    200 
    201     def __init__(self):
    202         if self.__initialized is None:
    203             self.initClass()
    204             self.__class__.__initialized = 1
    205         self.checkClass()
    206         self.locals = misc.Stack()
    207         self.setups = misc.Stack()
    208         self.last_lineno = None
    209         self._setupGraphDelegation()
    210         self._div_op = "BINARY_DIVIDE"
    211 
    212         # XXX set flags based on future features
    213         futures = self.get_module().futures
    214         for feature in futures:
    215             if feature == "division":
    216                 self.graph.setFlag(CO_FUTURE_DIVISION)
    217                 self._div_op = "BINARY_TRUE_DIVIDE"
    218             elif feature == "absolute_import":
    219                 self.graph.setFlag(CO_FUTURE_ABSIMPORT)
    220             elif feature == "with_statement":
    221                 self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
    222             elif feature == "print_function":
    223                 self.graph.setFlag(CO_FUTURE_PRINT_FUNCTION)
    224 
    225     def initClass(self):
    226         """This method is called once for each class"""
    227 
    228     def checkClass(self):
    229         """Verify that class is constructed correctly"""
    230         try:
    231             assert hasattr(self, 'graph')
    232             assert getattr(self, 'NameFinder')
    233             assert getattr(self, 'FunctionGen')
    234             assert getattr(self, 'ClassGen')
    235         except AssertionError, msg:
    236             intro = "Bad class construction for %s" % self.__class__.__name__
    237             raise AssertionError, intro
    238 
    239     def _setupGraphDelegation(self):
    240         self.emit = self.graph.emit
    241         self.newBlock = self.graph.newBlock
    242         self.startBlock = self.graph.startBlock
    243         self.nextBlock = self.graph.nextBlock
    244         self.setDocstring = self.graph.setDocstring
    245 
    246     def getCode(self):
    247         """Return a code object"""
    248         return self.graph.getCode()
    249 
    250     def mangle(self, name):
    251         if self.class_name is not None:
    252             return misc.mangle(name, self.class_name)
    253         else:
    254             return name
    255 
    256     def parseSymbols(self, tree):
    257         s = symbols.SymbolVisitor()
    258         walk(tree, s)
    259         return s.scopes
    260 
    261     def get_module(self):
    262         raise RuntimeError, "should be implemented by subclasses"
    263 
    264     # Next five methods handle name access
    265 
    266     def isLocalName(self, name):
    267         return self.locals.top().has_elt(name)
    268 
    269     def storeName(self, name):
    270         self._nameOp('STORE', name)
    271 
    272     def loadName(self, name):
    273         self._nameOp('LOAD', name)
    274 
    275     def delName(self, name):
    276         self._nameOp('DELETE', name)
    277 
    278     def _nameOp(self, prefix, name):
    279         name = self.mangle(name)
    280         scope = self.scope.check_name(name)
    281         if scope == SC_LOCAL:
    282             if not self.optimized:
    283                 self.emit(prefix + '_NAME', name)
    284             else:
    285                 self.emit(prefix + '_FAST', name)
    286         elif scope == SC_GLOBAL_EXPLICIT:
    287             self.emit(prefix + '_GLOBAL', name)
    288         elif scope == SC_GLOBAL_IMPLICIT:
    289             if not self.optimized:
    290                 self.emit(prefix + '_NAME', name)
    291             else:
    292                 self.emit(prefix + '_GLOBAL', name)
    293         elif scope == SC_FREE or scope == SC_CELL:
    294             self.emit(prefix + '_DEREF', name)
    295         else:
    296             raise RuntimeError, "unsupported scope for var %s: %d" % \
    297                   (name, scope)
    298 
    299     def _implicitNameOp(self, prefix, name):
    300         """Emit name ops for names generated implicitly by for loops
    301 
    302         The interpreter generates names that start with a period or
    303         dollar sign.  The symbol table ignores these names because
    304         they aren't present in the program text.
    305         """
    306         if self.optimized:
    307             self.emit(prefix + '_FAST', name)
    308         else:
    309             self.emit(prefix + '_NAME', name)
    310 
    311     # The set_lineno() function and the explicit emit() calls for
    312     # SET_LINENO below are only used to generate the line number table.
    313     # As of Python 2.3, the interpreter does not have a SET_LINENO
    314     # instruction.  pyassem treats SET_LINENO opcodes as a special case.
    315 
    316     def set_lineno(self, node, force=False):
    317         """Emit SET_LINENO if necessary.
    318 
    319         The instruction is considered necessary if the node has a
    320         lineno attribute and it is different than the last lineno
    321         emitted.
    322 
    323         Returns true if SET_LINENO was emitted.
    324 
    325         There are no rules for when an AST node should have a lineno
    326         attribute.  The transformer and AST code need to be reviewed
    327         and a consistent policy implemented and documented.  Until
    328         then, this method works around missing line numbers.
    329         """
    330         lineno = getattr(node, 'lineno', None)
    331         if lineno is not None and (lineno != self.last_lineno
    332                                    or force):
    333             self.emit('SET_LINENO', lineno)
    334             self.last_lineno = lineno
    335             return True
    336         return False
    337 
    338     # The first few visitor methods handle nodes that generator new
    339     # code objects.  They use class attributes to determine what
    340     # specialized code generators to use.
    341 
    342     NameFinder = LocalNameFinder
    343     FunctionGen = None
    344     ClassGen = None
    345 
    346     def visitModule(self, node):
    347         self.scopes = self.parseSymbols(node)
    348         self.scope = self.scopes[node]
    349         self.emit('SET_LINENO', 0)
    350         if node.doc:
    351             self.emit('LOAD_CONST', node.doc)
    352             self.storeName('__doc__')
    353         lnf = walk(node.node, self.NameFinder(), verbose=0)
    354         self.locals.push(lnf.getLocals())
    355         self.visit(node.node)
    356         self.emit('LOAD_CONST', None)
    357         self.emit('RETURN_VALUE')
    358 
    359     def visitExpression(self, node):
    360         self.set_lineno(node)
    361         self.scopes = self.parseSymbols(node)
    362         self.scope = self.scopes[node]
    363         self.visit(node.node)
    364         self.emit('RETURN_VALUE')
    365 
    366     def visitFunction(self, node):
    367         self._visitFuncOrLambda(node, isLambda=0)
    368         if node.doc:
    369             self.setDocstring(node.doc)
    370         self.storeName(node.name)
    371 
    372     def visitLambda(self, node):
    373         self._visitFuncOrLambda(node, isLambda=1)
    374 
    375     def _visitFuncOrLambda(self, node, isLambda=0):
    376         if not isLambda and node.decorators:
    377             for decorator in node.decorators.nodes:
    378                 self.visit(decorator)
    379             ndecorators = len(node.decorators.nodes)
    380         else:
    381             ndecorators = 0
    382 
    383         gen = self.FunctionGen(node, self.scopes, isLambda,
    384                                self.class_name, self.get_module())
    385         walk(node.code, gen)
    386         gen.finish()
    387         self.set_lineno(node)
    388         for default in node.defaults:
    389             self.visit(default)
    390         self._makeClosure(gen, len(node.defaults))
    391         for i in range(ndecorators):
    392             self.emit('CALL_FUNCTION', 1)
    393 
    394     def visitClass(self, node):
    395         gen = self.ClassGen(node, self.scopes,
    396                             self.get_module())
    397         walk(node.code, gen)
    398         gen.finish()
    399         self.set_lineno(node)
    400         self.emit('LOAD_CONST', node.name)
    401         for base in node.bases:
    402             self.visit(base)
    403         self.emit('BUILD_TUPLE', len(node.bases))
    404         self._makeClosure(gen, 0)
    405         self.emit('CALL_FUNCTION', 0)
    406         self.emit('BUILD_CLASS')
    407         self.storeName(node.name)
    408 
    409     # The rest are standard visitor methods
    410 
    411     # The next few implement control-flow statements
    412 
    413     def visitIf(self, node):
    414         end = self.newBlock()
    415         numtests = len(node.tests)
    416         for i in range(numtests):
    417             test, suite = node.tests[i]
    418             if is_constant_false(test):
    419                 # XXX will need to check generator stuff here
    420                 continue
    421             self.set_lineno(test)
    422             self.visit(test)
    423             nextTest = self.newBlock()
    424             self.emit('POP_JUMP_IF_FALSE', nextTest)
    425             self.nextBlock()
    426             self.visit(suite)
    427             self.emit('JUMP_FORWARD', end)
    428             self.startBlock(nextTest)
    429         if node.else_:
    430             self.visit(node.else_)
    431         self.nextBlock(end)
    432 
    433     def visitWhile(self, node):
    434         self.set_lineno(node)
    435 
    436         loop = self.newBlock()
    437         else_ = self.newBlock()
    438 
    439         after = self.newBlock()
    440         self.emit('SETUP_LOOP', after)
    441 
    442         self.nextBlock(loop)
    443         self.setups.push((LOOP, loop))
    444 
    445         self.set_lineno(node, force=True)
    446         self.visit(node.test)
    447         self.emit('POP_JUMP_IF_FALSE', else_ or after)
    448 
    449         self.nextBlock()
    450         self.visit(node.body)
    451         self.emit('JUMP_ABSOLUTE', loop)
    452 
    453         self.startBlock(else_) # or just the POPs if not else clause
    454         self.emit('POP_BLOCK')
    455         self.setups.pop()
    456         if node.else_:
    457             self.visit(node.else_)
    458         self.nextBlock(after)
    459 
    460     def visitFor(self, node):
    461         start = self.newBlock()
    462         anchor = self.newBlock()
    463         after = self.newBlock()
    464         self.setups.push((LOOP, start))
    465 
    466         self.set_lineno(node)
    467         self.emit('SETUP_LOOP', after)
    468         self.visit(node.list)
    469         self.emit('GET_ITER')
    470 
    471         self.nextBlock(start)
    472         self.set_lineno(node, force=1)
    473         self.emit('FOR_ITER', anchor)
    474         self.visit(node.assign)
    475         self.visit(node.body)
    476         self.emit('JUMP_ABSOLUTE', start)
    477         self.nextBlock(anchor)
    478         self.emit('POP_BLOCK')
    479         self.setups.pop()
    480         if node.else_:
    481             self.visit(node.else_)
    482         self.nextBlock(after)
    483 
    484     def visitBreak(self, node):
    485         if not self.setups:
    486             raise SyntaxError, "'break' outside loop (%s, %d)" % \
    487                   (node.filename, node.lineno)
    488         self.set_lineno(node)
    489         self.emit('BREAK_LOOP')
    490 
    491     def visitContinue(self, node):
    492         if not self.setups:
    493             raise SyntaxError, "'continue' outside loop (%s, %d)" % \
    494                   (node.filename, node.lineno)
    495         kind, block = self.setups.top()
    496         if kind == LOOP:
    497             self.set_lineno(node)
    498             self.emit('JUMP_ABSOLUTE', block)
    499             self.nextBlock()
    500         elif kind == EXCEPT or kind == TRY_FINALLY:
    501             self.set_lineno(node)
    502             # find the block that starts the loop
    503             top = len(self.setups)
    504             while top > 0:
    505                 top = top - 1
    506                 kind, loop_block = self.setups[top]
    507                 if kind == LOOP:
    508                     break
    509             if kind != LOOP:
    510                 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
    511                       (node.filename, node.lineno)
    512             self.emit('CONTINUE_LOOP', loop_block)
    513             self.nextBlock()
    514         elif kind == END_FINALLY:
    515             msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
    516             raise SyntaxError, msg % (node.filename, node.lineno)
    517 
    518     def visitTest(self, node, jump):
    519         end = self.newBlock()
    520         for child in node.nodes[:-1]:
    521             self.visit(child)
    522             self.emit(jump, end)
    523             self.nextBlock()
    524         self.visit(node.nodes[-1])
    525         self.nextBlock(end)
    526 
    527     def visitAnd(self, node):
    528         self.visitTest(node, 'JUMP_IF_FALSE_OR_POP')
    529 
    530     def visitOr(self, node):
    531         self.visitTest(node, 'JUMP_IF_TRUE_OR_POP')
    532 
    533     def visitIfExp(self, node):
    534         endblock = self.newBlock()
    535         elseblock = self.newBlock()
    536         self.visit(node.test)
    537         self.emit('POP_JUMP_IF_FALSE', elseblock)
    538         self.visit(node.then)
    539         self.emit('JUMP_FORWARD', endblock)
    540         self.nextBlock(elseblock)
    541         self.visit(node.else_)
    542         self.nextBlock(endblock)
    543 
    544     def visitCompare(self, node):
    545         self.visit(node.expr)
    546         cleanup = self.newBlock()
    547         for op, code in node.ops[:-1]:
    548             self.visit(code)
    549             self.emit('DUP_TOP')
    550             self.emit('ROT_THREE')
    551             self.emit('COMPARE_OP', op)
    552             self.emit('JUMP_IF_FALSE_OR_POP', cleanup)
    553             self.nextBlock()
    554         # now do the last comparison
    555         if node.ops:
    556             op, code = node.ops[-1]
    557             self.visit(code)
    558             self.emit('COMPARE_OP', op)
    559         if len(node.ops) > 1:
    560             end = self.newBlock()
    561             self.emit('JUMP_FORWARD', end)
    562             self.startBlock(cleanup)
    563             self.emit('ROT_TWO')
    564             self.emit('POP_TOP')
    565             self.nextBlock(end)
    566 
    567     # list comprehensions
    568     def visitListComp(self, node):
    569         self.set_lineno(node)
    570         # setup list
    571         self.emit('BUILD_LIST', 0)
    572 
    573         stack = []
    574         for i, for_ in zip(range(len(node.quals)), node.quals):
    575             start, anchor = self.visit(for_)
    576             cont = None
    577             for if_ in for_.ifs:
    578                 if cont is None:
    579                     cont = self.newBlock()
    580                 self.visit(if_, cont)
    581             stack.insert(0, (start, cont, anchor))
    582 
    583         self.visit(node.expr)
    584         self.emit('LIST_APPEND', len(node.quals) + 1)
    585 
    586         for start, cont, anchor in stack:
    587             if cont:
    588                 self.nextBlock(cont)
    589             self.emit('JUMP_ABSOLUTE', start)
    590             self.startBlock(anchor)
    591 
    592     def visitSetComp(self, node):
    593         self.set_lineno(node)
    594         # setup list
    595         self.emit('BUILD_SET', 0)
    596 
    597         stack = []
    598         for i, for_ in zip(range(len(node.quals)), node.quals):
    599             start, anchor = self.visit(for_)
    600             cont = None
    601             for if_ in for_.ifs:
    602                 if cont is None:
    603                     cont = self.newBlock()
    604                 self.visit(if_, cont)
    605             stack.insert(0, (start, cont, anchor))
    606 
    607         self.visit(node.expr)
    608         self.emit('SET_ADD', len(node.quals) + 1)
    609 
    610         for start, cont, anchor in stack:
    611             if cont:
    612                 self.nextBlock(cont)
    613             self.emit('JUMP_ABSOLUTE', start)
    614             self.startBlock(anchor)
    615 
    616     def visitDictComp(self, node):
    617         self.set_lineno(node)
    618         # setup list
    619         self.emit('BUILD_MAP', 0)
    620 
    621         stack = []
    622         for i, for_ in zip(range(len(node.quals)), node.quals):
    623             start, anchor = self.visit(for_)
    624             cont = None
    625             for if_ in for_.ifs:
    626                 if cont is None:
    627                     cont = self.newBlock()
    628                 self.visit(if_, cont)
    629             stack.insert(0, (start, cont, anchor))
    630 
    631         self.visit(node.value)
    632         self.visit(node.key)
    633         self.emit('MAP_ADD', len(node.quals) + 1)
    634 
    635         for start, cont, anchor in stack:
    636             if cont:
    637                 self.nextBlock(cont)
    638             self.emit('JUMP_ABSOLUTE', start)
    639             self.startBlock(anchor)
    640 
    641     def visitListCompFor(self, node):
    642         start = self.newBlock()
    643         anchor = self.newBlock()
    644 
    645         self.visit(node.list)
    646         self.emit('GET_ITER')
    647         self.nextBlock(start)
    648         self.set_lineno(node, force=True)
    649         self.emit('FOR_ITER', anchor)
    650         self.nextBlock()
    651         self.visit(node.assign)
    652         return start, anchor
    653 
    654     def visitListCompIf(self, node, branch):
    655         self.set_lineno(node, force=True)
    656         self.visit(node.test)
    657         self.emit('POP_JUMP_IF_FALSE', branch)
    658         self.newBlock()
    659 
    660     def _makeClosure(self, gen, args):
    661         frees = gen.scope.get_free_vars()
    662         if frees:
    663             for name in frees:
    664                 self.emit('LOAD_CLOSURE', name)
    665             self.emit('BUILD_TUPLE', len(frees))
    666             self.emit('LOAD_CONST', gen)
    667             self.emit('MAKE_CLOSURE', args)
    668         else:
    669             self.emit('LOAD_CONST', gen)
    670             self.emit('MAKE_FUNCTION', args)
    671 
    672     def visitGenExpr(self, node):
    673         gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
    674                                    self.get_module())
    675         walk(node.code, gen)
    676         gen.finish()
    677         self.set_lineno(node)
    678         self._makeClosure(gen, 0)
    679         # precomputation of outmost iterable
    680         self.visit(node.code.quals[0].iter)
    681         self.emit('GET_ITER')
    682         self.emit('CALL_FUNCTION', 1)
    683 
    684     def visitGenExprInner(self, node):
    685         self.set_lineno(node)
    686         # setup list
    687 
    688         stack = []
    689         for i, for_ in zip(range(len(node.quals)), node.quals):
    690             start, anchor, end = self.visit(for_)
    691             cont = None
    692             for if_ in for_.ifs:
    693                 if cont is None:
    694                     cont = self.newBlock()
    695                 self.visit(if_, cont)
    696             stack.insert(0, (start, cont, anchor, end))
    697 
    698         self.visit(node.expr)
    699         self.emit('YIELD_VALUE')
    700         self.emit('POP_TOP')
    701 
    702         for start, cont, anchor, end in stack:
    703             if cont:
    704                 self.nextBlock(cont)
    705             self.emit('JUMP_ABSOLUTE', start)
    706             self.startBlock(anchor)
    707             self.emit('POP_BLOCK')
    708             self.setups.pop()
    709             self.nextBlock(end)
    710 
    711         self.emit('LOAD_CONST', None)
    712 
    713     def visitGenExprFor(self, node):
    714         start = self.newBlock()
    715         anchor = self.newBlock()
    716         end = self.newBlock()
    717 
    718         self.setups.push((LOOP, start))
    719         self.emit('SETUP_LOOP', end)
    720 
    721         if node.is_outmost:
    722             self.loadName('.0')
    723         else:
    724             self.visit(node.iter)
    725             self.emit('GET_ITER')
    726 
    727         self.nextBlock(start)
    728         self.set_lineno(node, force=True)
    729         self.emit('FOR_ITER', anchor)
    730         self.nextBlock()
    731         self.visit(node.assign)
    732         return start, anchor, end
    733 
    734     def visitGenExprIf(self, node, branch):
    735         self.set_lineno(node, force=True)
    736         self.visit(node.test)
    737         self.emit('POP_JUMP_IF_FALSE', branch)
    738         self.newBlock()
    739 
    740     # exception related
    741 
    742     def visitAssert(self, node):
    743         # XXX would be interesting to implement this via a
    744         # transformation of the AST before this stage
    745         if __debug__:
    746             end = self.newBlock()
    747             self.set_lineno(node)
    748             # XXX AssertionError appears to be special case -- it is always
    749             # loaded as a global even if there is a local name.  I guess this
    750             # is a sort of renaming op.
    751             self.nextBlock()
    752             self.visit(node.test)
    753             self.emit('POP_JUMP_IF_TRUE', end)
    754             self.nextBlock()
    755             self.emit('LOAD_GLOBAL', 'AssertionError')
    756             if node.fail:
    757                 self.visit(node.fail)
    758                 self.emit('RAISE_VARARGS', 2)
    759             else:
    760                 self.emit('RAISE_VARARGS', 1)
    761             self.nextBlock(end)
    762 
    763     def visitRaise(self, node):
    764         self.set_lineno(node)
    765         n = 0
    766         if node.expr1:
    767             self.visit(node.expr1)
    768             n = n + 1
    769         if node.expr2:
    770             self.visit(node.expr2)
    771             n = n + 1
    772         if node.expr3:
    773             self.visit(node.expr3)
    774             n = n + 1
    775         self.emit('RAISE_VARARGS', n)
    776 
    777     def visitTryExcept(self, node):
    778         body = self.newBlock()
    779         handlers = self.newBlock()
    780         end = self.newBlock()
    781         if node.else_:
    782             lElse = self.newBlock()
    783         else:
    784             lElse = end
    785         self.set_lineno(node)
    786         self.emit('SETUP_EXCEPT', handlers)
    787         self.nextBlock(body)
    788         self.setups.push((EXCEPT, body))
    789         self.visit(node.body)
    790         self.emit('POP_BLOCK')
    791         self.setups.pop()
    792         self.emit('JUMP_FORWARD', lElse)
    793         self.startBlock(handlers)
    794 
    795         last = len(node.handlers) - 1
    796         for i in range(len(node.handlers)):
    797             expr, target, body = node.handlers[i]
    798             self.set_lineno(expr)
    799             if expr:
    800                 self.emit('DUP_TOP')
    801                 self.visit(expr)
    802                 self.emit('COMPARE_OP', 'exception match')
    803                 next = self.newBlock()
    804                 self.emit('POP_JUMP_IF_FALSE', next)
    805                 self.nextBlock()
    806             self.emit('POP_TOP')
    807             if target:
    808                 self.visit(target)
    809             else:
    810                 self.emit('POP_TOP')
    811             self.emit('POP_TOP')
    812             self.visit(body)
    813             self.emit('JUMP_FORWARD', end)
    814             if expr:
    815                 self.nextBlock(next)
    816             else:
    817                 self.nextBlock()
    818         self.emit('END_FINALLY')
    819         if node.else_:
    820             self.nextBlock(lElse)
    821             self.visit(node.else_)
    822         self.nextBlock(end)
    823 
    824     def visitTryFinally(self, node):
    825         body = self.newBlock()
    826         final = self.newBlock()
    827         self.set_lineno(node)
    828         self.emit('SETUP_FINALLY', final)
    829         self.nextBlock(body)
    830         self.setups.push((TRY_FINALLY, body))
    831         self.visit(node.body)
    832         self.emit('POP_BLOCK')
    833         self.setups.pop()
    834         self.emit('LOAD_CONST', None)
    835         self.nextBlock(final)
    836         self.setups.push((END_FINALLY, final))
    837         self.visit(node.final)
    838         self.emit('END_FINALLY')
    839         self.setups.pop()
    840 
    841     __with_count = 0
    842 
    843     def visitWith(self, node):
    844         body = self.newBlock()
    845         final = self.newBlock()
    846         self.__with_count += 1
    847         valuevar = "_[%d]" % self.__with_count
    848         self.set_lineno(node)
    849         self.visit(node.expr)
    850         self.emit('DUP_TOP')
    851         self.emit('LOAD_ATTR', '__exit__')
    852         self.emit('ROT_TWO')
    853         self.emit('LOAD_ATTR', '__enter__')
    854         self.emit('CALL_FUNCTION', 0)
    855         if node.vars is None:
    856             self.emit('POP_TOP')
    857         else:
    858             self._implicitNameOp('STORE', valuevar)
    859         self.emit('SETUP_FINALLY', final)
    860         self.nextBlock(body)
    861         self.setups.push((TRY_FINALLY, body))
    862         if node.vars is not None:
    863             self._implicitNameOp('LOAD', valuevar)
    864             self._implicitNameOp('DELETE', valuevar)
    865             self.visit(node.vars)
    866         self.visit(node.body)
    867         self.emit('POP_BLOCK')
    868         self.setups.pop()
    869         self.emit('LOAD_CONST', None)
    870         self.nextBlock(final)
    871         self.setups.push((END_FINALLY, final))
    872         self.emit('WITH_CLEANUP')
    873         self.emit('END_FINALLY')
    874         self.setups.pop()
    875         self.__with_count -= 1
    876 
    877     # misc
    878 
    879     def visitDiscard(self, node):
    880         self.set_lineno(node)
    881         self.visit(node.expr)
    882         self.emit('POP_TOP')
    883 
    884     def visitConst(self, node):
    885         self.emit('LOAD_CONST', node.value)
    886 
    887     def visitKeyword(self, node):
    888         self.emit('LOAD_CONST', node.name)
    889         self.visit(node.expr)
    890 
    891     def visitGlobal(self, node):
    892         # no code to generate
    893         pass
    894 
    895     def visitName(self, node):
    896         self.set_lineno(node)
    897         self.loadName(node.name)
    898 
    899     def visitPass(self, node):
    900         self.set_lineno(node)
    901 
    902     def visitImport(self, node):
    903         self.set_lineno(node)
    904         level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1
    905         for name, alias in node.names:
    906             if VERSION > 1:
    907                 self.emit('LOAD_CONST', level)
    908                 self.emit('LOAD_CONST', None)
    909             self.emit('IMPORT_NAME', name)
    910             mod = name.split(".")[0]
    911             if alias:
    912                 self._resolveDots(name)
    913                 self.storeName(alias)
    914             else:
    915                 self.storeName(mod)
    916 
    917     def visitFrom(self, node):
    918         self.set_lineno(node)
    919         level = node.level
    920         if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
    921             level = -1
    922         fromlist = tuple(name for (name, alias) in node.names)
    923         if VERSION > 1:
    924             self.emit('LOAD_CONST', level)
    925             self.emit('LOAD_CONST', fromlist)
    926         self.emit('IMPORT_NAME', node.modname)
    927         for name, alias in node.names:
    928             if VERSION > 1:
    929                 if name == '*':
    930                     self.namespace = 0
    931                     self.emit('IMPORT_STAR')
    932                     # There can only be one name w/ from ... import *
    933                     assert len(node.names) == 1
    934                     return
    935                 else:
    936                     self.emit('IMPORT_FROM', name)
    937                     self._resolveDots(name)
    938                     self.storeName(alias or name)
    939             else:
    940                 self.emit('IMPORT_FROM', name)
    941         self.emit('POP_TOP')
    942 
    943     def _resolveDots(self, name):
    944         elts = name.split(".")
    945         if len(elts) == 1:
    946             return
    947         for elt in elts[1:]:
    948             self.emit('LOAD_ATTR', elt)
    949 
    950     def visitGetattr(self, node):
    951         self.visit(node.expr)
    952         self.emit('LOAD_ATTR', self.mangle(node.attrname))
    953 
    954     # next five implement assignments
    955 
    956     def visitAssign(self, node):
    957         self.set_lineno(node)
    958         self.visit(node.expr)
    959         dups = len(node.nodes) - 1
    960         for i in range(len(node.nodes)):
    961             elt = node.nodes[i]
    962             if i < dups:
    963                 self.emit('DUP_TOP')
    964             if isinstance(elt, ast.Node):
    965                 self.visit(elt)
    966 
    967     def visitAssName(self, node):
    968         if node.flags == 'OP_ASSIGN':
    969             self.storeName(node.name)
    970         elif node.flags == 'OP_DELETE':
    971             self.set_lineno(node)
    972             self.delName(node.name)
    973         else:
    974             print "oops", node.flags
    975 
    976     def visitAssAttr(self, node):
    977         self.visit(node.expr)
    978         if node.flags == 'OP_ASSIGN':
    979             self.emit('STORE_ATTR', self.mangle(node.attrname))
    980         elif node.flags == 'OP_DELETE':
    981             self.emit('DELETE_ATTR', self.mangle(node.attrname))
    982         else:
    983             print "warning: unexpected flags:", node.flags
    984             print node
    985 
    986     def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
    987         if findOp(node) != 'OP_DELETE':
    988             self.emit(op, len(node.nodes))
    989         for child in node.nodes:
    990             self.visit(child)
    991 
    992     if VERSION > 1:
    993         visitAssTuple = _visitAssSequence
    994         visitAssList = _visitAssSequence
    995     else:
    996         def visitAssTuple(self, node):
    997             self._visitAssSequence(node, 'UNPACK_TUPLE')
    998 
    999         def visitAssList(self, node):
   1000             self._visitAssSequence(node, 'UNPACK_LIST')
   1001 
   1002     # augmented assignment
   1003 
   1004     def visitAugAssign(self, node):
   1005         self.set_lineno(node)
   1006         aug_node = wrap_aug(node.node)
   1007         self.visit(aug_node, "load")
   1008         self.visit(node.expr)
   1009         self.emit(self._augmented_opcode[node.op])
   1010         self.visit(aug_node, "store")
   1011 
   1012     _augmented_opcode = {
   1013         '+=' : 'INPLACE_ADD',
   1014         '-=' : 'INPLACE_SUBTRACT',
   1015         '*=' : 'INPLACE_MULTIPLY',
   1016         '/=' : 'INPLACE_DIVIDE',
   1017         '//=': 'INPLACE_FLOOR_DIVIDE',
   1018         '%=' : 'INPLACE_MODULO',
   1019         '**=': 'INPLACE_POWER',
   1020         '>>=': 'INPLACE_RSHIFT',
   1021         '<<=': 'INPLACE_LSHIFT',
   1022         '&=' : 'INPLACE_AND',
   1023         '^=' : 'INPLACE_XOR',
   1024         '|=' : 'INPLACE_OR',
   1025         }
   1026 
   1027     def visitAugName(self, node, mode):
   1028         if mode == "load":
   1029             self.loadName(node.name)
   1030         elif mode == "store":
   1031             self.storeName(node.name)
   1032 
   1033     def visitAugGetattr(self, node, mode):
   1034         if mode == "load":
   1035             self.visit(node.expr)
   1036             self.emit('DUP_TOP')
   1037             self.emit('LOAD_ATTR', self.mangle(node.attrname))
   1038         elif mode == "store":
   1039             self.emit('ROT_TWO')
   1040             self.emit('STORE_ATTR', self.mangle(node.attrname))
   1041 
   1042     def visitAugSlice(self, node, mode):
   1043         if mode == "load":
   1044             self.visitSlice(node, 1)
   1045         elif mode == "store":
   1046             slice = 0
   1047             if node.lower:
   1048                 slice = slice | 1
   1049             if node.upper:
   1050                 slice = slice | 2
   1051             if slice == 0:
   1052                 self.emit('ROT_TWO')
   1053             elif slice == 3:
   1054                 self.emit('ROT_FOUR')
   1055             else:
   1056                 self.emit('ROT_THREE')
   1057             self.emit('STORE_SLICE+%d' % slice)
   1058 
   1059     def visitAugSubscript(self, node, mode):
   1060         if mode == "load":
   1061             self.visitSubscript(node, 1)
   1062         elif mode == "store":
   1063             self.emit('ROT_THREE')
   1064             self.emit('STORE_SUBSCR')
   1065 
   1066     def visitExec(self, node):
   1067         self.visit(node.expr)
   1068         if node.locals is None:
   1069             self.emit('LOAD_CONST', None)
   1070         else:
   1071             self.visit(node.locals)
   1072         if node.globals is None:
   1073             self.emit('DUP_TOP')
   1074         else:
   1075             self.visit(node.globals)
   1076         self.emit('EXEC_STMT')
   1077 
   1078     def visitCallFunc(self, node):
   1079         pos = 0
   1080         kw = 0
   1081         self.set_lineno(node)
   1082         self.visit(node.node)
   1083         for arg in node.args:
   1084             self.visit(arg)
   1085             if isinstance(arg, ast.Keyword):
   1086                 kw = kw + 1
   1087             else:
   1088                 pos = pos + 1
   1089         if node.star_args is not None:
   1090             self.visit(node.star_args)
   1091         if node.dstar_args is not None:
   1092             self.visit(node.dstar_args)
   1093         have_star = node.star_args is not None
   1094         have_dstar = node.dstar_args is not None
   1095         opcode = callfunc_opcode_info[have_star, have_dstar]
   1096         self.emit(opcode, kw << 8 | pos)
   1097 
   1098     def visitPrint(self, node, newline=0):
   1099         self.set_lineno(node)
   1100         if node.dest:
   1101             self.visit(node.dest)
   1102         for child in node.nodes:
   1103             if node.dest:
   1104                 self.emit('DUP_TOP')
   1105             self.visit(child)
   1106             if node.dest:
   1107                 self.emit('ROT_TWO')
   1108                 self.emit('PRINT_ITEM_TO')
   1109             else:
   1110                 self.emit('PRINT_ITEM')
   1111         if node.dest and not newline:
   1112             self.emit('POP_TOP')
   1113 
   1114     def visitPrintnl(self, node):
   1115         self.visitPrint(node, newline=1)
   1116         if node.dest:
   1117             self.emit('PRINT_NEWLINE_TO')
   1118         else:
   1119             self.emit('PRINT_NEWLINE')
   1120 
   1121     def visitReturn(self, node):
   1122         self.set_lineno(node)
   1123         self.visit(node.value)
   1124         self.emit('RETURN_VALUE')
   1125 
   1126     def visitYield(self, node):
   1127         self.set_lineno(node)
   1128         self.visit(node.value)
   1129         self.emit('YIELD_VALUE')
   1130 
   1131     # slice and subscript stuff
   1132 
   1133     def visitSlice(self, node, aug_flag=None):
   1134         # aug_flag is used by visitAugSlice
   1135         self.visit(node.expr)
   1136         slice = 0
   1137         if node.lower:
   1138             self.visit(node.lower)
   1139             slice = slice | 1
   1140         if node.upper:
   1141             self.visit(node.upper)
   1142             slice = slice | 2
   1143         if aug_flag:
   1144             if slice == 0:
   1145                 self.emit('DUP_TOP')
   1146             elif slice == 3:
   1147                 self.emit('DUP_TOPX', 3)
   1148             else:
   1149                 self.emit('DUP_TOPX', 2)
   1150         if node.flags == 'OP_APPLY':
   1151             self.emit('SLICE+%d' % slice)
   1152         elif node.flags == 'OP_ASSIGN':
   1153             self.emit('STORE_SLICE+%d' % slice)
   1154         elif node.flags == 'OP_DELETE':
   1155             self.emit('DELETE_SLICE+%d' % slice)
   1156         else:
   1157             print "weird slice", node.flags
   1158             raise
   1159 
   1160     def visitSubscript(self, node, aug_flag=None):
   1161         self.visit(node.expr)
   1162         for sub in node.subs:
   1163             self.visit(sub)
   1164         if len(node.subs) > 1:
   1165             self.emit('BUILD_TUPLE', len(node.subs))
   1166         if aug_flag:
   1167             self.emit('DUP_TOPX', 2)
   1168         if node.flags == 'OP_APPLY':
   1169             self.emit('BINARY_SUBSCR')
   1170         elif node.flags == 'OP_ASSIGN':
   1171             self.emit('STORE_SUBSCR')
   1172         elif node.flags == 'OP_DELETE':
   1173             self.emit('DELETE_SUBSCR')
   1174 
   1175     # binary ops
   1176 
   1177     def binaryOp(self, node, op):
   1178         self.visit(node.left)
   1179         self.visit(node.right)
   1180         self.emit(op)
   1181 
   1182     def visitAdd(self, node):
   1183         return self.binaryOp(node, 'BINARY_ADD')
   1184 
   1185     def visitSub(self, node):
   1186         return self.binaryOp(node, 'BINARY_SUBTRACT')
   1187 
   1188     def visitMul(self, node):
   1189         return self.binaryOp(node, 'BINARY_MULTIPLY')
   1190 
   1191     def visitDiv(self, node):
   1192         return self.binaryOp(node, self._div_op)
   1193 
   1194     def visitFloorDiv(self, node):
   1195         return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
   1196 
   1197     def visitMod(self, node):
   1198         return self.binaryOp(node, 'BINARY_MODULO')
   1199 
   1200     def visitPower(self, node):
   1201         return self.binaryOp(node, 'BINARY_POWER')
   1202 
   1203     def visitLeftShift(self, node):
   1204         return self.binaryOp(node, 'BINARY_LSHIFT')
   1205 
   1206     def visitRightShift(self, node):
   1207         return self.binaryOp(node, 'BINARY_RSHIFT')
   1208 
   1209     # unary ops
   1210 
   1211     def unaryOp(self, node, op):
   1212         self.visit(node.expr)
   1213         self.emit(op)
   1214 
   1215     def visitInvert(self, node):
   1216         return self.unaryOp(node, 'UNARY_INVERT')
   1217 
   1218     def visitUnarySub(self, node):
   1219         return self.unaryOp(node, 'UNARY_NEGATIVE')
   1220 
   1221     def visitUnaryAdd(self, node):
   1222         return self.unaryOp(node, 'UNARY_POSITIVE')
   1223 
   1224     def visitUnaryInvert(self, node):
   1225         return self.unaryOp(node, 'UNARY_INVERT')
   1226 
   1227     def visitNot(self, node):
   1228         return self.unaryOp(node, 'UNARY_NOT')
   1229 
   1230     def visitBackquote(self, node):
   1231         return self.unaryOp(node, 'UNARY_CONVERT')
   1232 
   1233     # bit ops
   1234 
   1235     def bitOp(self, nodes, op):
   1236         self.visit(nodes[0])
   1237         for node in nodes[1:]:
   1238             self.visit(node)
   1239             self.emit(op)
   1240 
   1241     def visitBitand(self, node):
   1242         return self.bitOp(node.nodes, 'BINARY_AND')
   1243 
   1244     def visitBitor(self, node):
   1245         return self.bitOp(node.nodes, 'BINARY_OR')
   1246 
   1247     def visitBitxor(self, node):
   1248         return self.bitOp(node.nodes, 'BINARY_XOR')
   1249 
   1250     # object constructors
   1251 
   1252     def visitEllipsis(self, node):
   1253         self.emit('LOAD_CONST', Ellipsis)
   1254 
   1255     def visitTuple(self, node):
   1256         self.set_lineno(node)
   1257         for elt in node.nodes:
   1258             self.visit(elt)
   1259         self.emit('BUILD_TUPLE', len(node.nodes))
   1260 
   1261     def visitList(self, node):
   1262         self.set_lineno(node)
   1263         for elt in node.nodes:
   1264             self.visit(elt)
   1265         self.emit('BUILD_LIST', len(node.nodes))
   1266 
   1267     def visitSet(self, node):
   1268         self.set_lineno(node)
   1269         for elt in node.nodes:
   1270             self.visit(elt)
   1271         self.emit('BUILD_SET', len(node.nodes))
   1272 
   1273     def visitSliceobj(self, node):
   1274         for child in node.nodes:
   1275             self.visit(child)
   1276         self.emit('BUILD_SLICE', len(node.nodes))
   1277 
   1278     def visitDict(self, node):
   1279         self.set_lineno(node)
   1280         self.emit('BUILD_MAP', 0)
   1281         for k, v in node.items:
   1282             self.emit('DUP_TOP')
   1283             self.visit(k)
   1284             self.visit(v)
   1285             self.emit('ROT_THREE')
   1286             self.emit('STORE_SUBSCR')
   1287 
   1288 class NestedScopeMixin:
   1289     """Defines initClass() for nested scoping (Python 2.2-compatible)"""
   1290     def initClass(self):
   1291         self.__class__.NameFinder = LocalNameFinder
   1292         self.__class__.FunctionGen = FunctionCodeGenerator
   1293         self.__class__.ClassGen = ClassCodeGenerator
   1294 
   1295 class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
   1296     __super_init = CodeGenerator.__init__
   1297 
   1298     scopes = None
   1299 
   1300     def __init__(self, tree):
   1301         self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
   1302         self.futures = future.find_futures(tree)
   1303         self.__super_init()
   1304         walk(tree, self)
   1305 
   1306     def get_module(self):
   1307         return self
   1308 
   1309 class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
   1310     __super_init = CodeGenerator.__init__
   1311 
   1312     scopes = None
   1313     futures = ()
   1314 
   1315     def __init__(self, tree):
   1316         self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
   1317         self.__super_init()
   1318         walk(tree, self)
   1319 
   1320     def get_module(self):
   1321         return self
   1322 
   1323 class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
   1324 
   1325     __super_init = CodeGenerator.__init__
   1326 
   1327     scopes = None
   1328     futures = ()
   1329 
   1330     def __init__(self, tree):
   1331         self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
   1332         self.__super_init()
   1333         self.set_lineno(tree)
   1334         walk(tree, self)
   1335         self.emit('RETURN_VALUE')
   1336 
   1337     def get_module(self):
   1338         return self
   1339 
   1340     def visitDiscard(self, node):
   1341         # XXX Discard means it's an expression.  Perhaps this is a bad
   1342         # name.
   1343         self.visit(node.expr)
   1344         self.emit('PRINT_EXPR')
   1345 
   1346 class AbstractFunctionCode:
   1347     optimized = 1
   1348     lambdaCount = 0
   1349 
   1350     def __init__(self, func, scopes, isLambda, class_name, mod):
   1351         self.class_name = class_name
   1352         self.module = mod
   1353         if isLambda:
   1354             klass = FunctionCodeGenerator
   1355             name = "<lambda.%d>" % klass.lambdaCount
   1356             klass.lambdaCount = klass.lambdaCount + 1
   1357         else:
   1358             name = func.name
   1359 
   1360         args, hasTupleArg = generateArgList(func.argnames)
   1361         self.graph = pyassem.PyFlowGraph(name, func.filename, args,
   1362                                          optimized=1)
   1363         self.isLambda = isLambda
   1364         self.super_init()
   1365 
   1366         if not isLambda and func.doc:
   1367             self.setDocstring(func.doc)
   1368 
   1369         lnf = walk(func.code, self.NameFinder(args), verbose=0)
   1370         self.locals.push(lnf.getLocals())
   1371         if func.varargs:
   1372             self.graph.setFlag(CO_VARARGS)
   1373         if func.kwargs:
   1374             self.graph.setFlag(CO_VARKEYWORDS)
   1375         self.set_lineno(func)
   1376         if hasTupleArg:
   1377             self.generateArgUnpack(func.argnames)
   1378 
   1379     def get_module(self):
   1380         return self.module
   1381 
   1382     def finish(self):
   1383         self.graph.startExitBlock()
   1384         if not self.isLambda:
   1385             self.emit('LOAD_CONST', None)
   1386         self.emit('RETURN_VALUE')
   1387 
   1388     def generateArgUnpack(self, args):
   1389         for i in range(len(args)):
   1390             arg = args[i]
   1391             if isinstance(arg, tuple):
   1392                 self.emit('LOAD_FAST', '.%d' % (i * 2))
   1393                 self.unpackSequence(arg)
   1394 
   1395     def unpackSequence(self, tup):
   1396         if VERSION > 1:
   1397             self.emit('UNPACK_SEQUENCE', len(tup))
   1398         else:
   1399             self.emit('UNPACK_TUPLE', len(tup))
   1400         for elt in tup:
   1401             if isinstance(elt, tuple):
   1402                 self.unpackSequence(elt)
   1403             else:
   1404                 self._nameOp('STORE', elt)
   1405 
   1406     unpackTuple = unpackSequence
   1407 
   1408 class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
   1409                             CodeGenerator):
   1410     super_init = CodeGenerator.__init__ # call be other init
   1411     scopes = None
   1412 
   1413     __super_init = AbstractFunctionCode.__init__
   1414 
   1415     def __init__(self, func, scopes, isLambda, class_name, mod):
   1416         self.scopes = scopes
   1417         self.scope = scopes[func]
   1418         self.__super_init(func, scopes, isLambda, class_name, mod)
   1419         self.graph.setFreeVars(self.scope.get_free_vars())
   1420         self.graph.setCellVars(self.scope.get_cell_vars())
   1421         if self.scope.generator is not None:
   1422             self.graph.setFlag(CO_GENERATOR)
   1423 
   1424 class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
   1425                            CodeGenerator):
   1426     super_init = CodeGenerator.__init__ # call be other init
   1427     scopes = None
   1428 
   1429     __super_init = AbstractFunctionCode.__init__
   1430 
   1431     def __init__(self, gexp, scopes, class_name, mod):
   1432         self.scopes = scopes
   1433         self.scope = scopes[gexp]
   1434         self.__super_init(gexp, scopes, 1, class_name, mod)
   1435         self.graph.setFreeVars(self.scope.get_free_vars())
   1436         self.graph.setCellVars(self.scope.get_cell_vars())
   1437         self.graph.setFlag(CO_GENERATOR)
   1438 
   1439 class AbstractClassCode:
   1440 
   1441     def __init__(self, klass, scopes, module):
   1442         self.class_name = klass.name
   1443         self.module = module
   1444         self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
   1445                                            optimized=0, klass=1)
   1446         self.super_init()
   1447         lnf = walk(klass.code, self.NameFinder(), verbose=0)
   1448         self.locals.push(lnf.getLocals())
   1449         self.graph.setFlag(CO_NEWLOCALS)
   1450         if klass.doc:
   1451             self.setDocstring(klass.doc)
   1452 
   1453     def get_module(self):
   1454         return self.module
   1455 
   1456     def finish(self):
   1457         self.graph.startExitBlock()
   1458         self.emit('LOAD_LOCALS')
   1459         self.emit('RETURN_VALUE')
   1460 
   1461 class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
   1462     super_init = CodeGenerator.__init__
   1463     scopes = None
   1464 
   1465     __super_init = AbstractClassCode.__init__
   1466 
   1467     def __init__(self, klass, scopes, module):
   1468         self.scopes = scopes
   1469         self.scope = scopes[klass]
   1470         self.__super_init(klass, scopes, module)
   1471         self.graph.setFreeVars(self.scope.get_free_vars())
   1472         self.graph.setCellVars(self.scope.get_cell_vars())
   1473         self.set_lineno(klass)
   1474         self.emit("LOAD_GLOBAL", "__name__")
   1475         self.storeName("__module__")
   1476         if klass.doc:
   1477             self.emit("LOAD_CONST", klass.doc)
   1478             self.storeName('__doc__')
   1479 
   1480 def generateArgList(arglist):
   1481     """Generate an arg list marking TupleArgs"""
   1482     args = []
   1483     extra = []
   1484     count = 0
   1485     for i in range(len(arglist)):
   1486         elt = arglist[i]
   1487         if isinstance(elt, str):
   1488             args.append(elt)
   1489         elif isinstance(elt, tuple):
   1490             args.append(TupleArg(i * 2, elt))
   1491             extra.extend(misc.flatten(elt))
   1492             count = count + 1
   1493         else:
   1494             raise ValueError, "unexpect argument type:", elt
   1495     return args + extra, count
   1496 
   1497 def findOp(node):
   1498     """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
   1499     v = OpFinder()
   1500     walk(node, v, verbose=0)
   1501     return v.op
   1502 
   1503 class OpFinder:
   1504     def __init__(self):
   1505         self.op = None
   1506     def visitAssName(self, node):
   1507         if self.op is None:
   1508             self.op = node.flags
   1509         elif self.op != node.flags:
   1510             raise ValueError, "mixed ops in stmt"
   1511     visitAssAttr = visitAssName
   1512     visitSubscript = visitAssName
   1513 
   1514 class Delegator:
   1515     """Base class to support delegation for augmented assignment nodes
   1516 
   1517     To generator code for augmented assignments, we use the following
   1518     wrapper classes.  In visitAugAssign, the left-hand expression node
   1519     is visited twice.  The first time the visit uses the normal method
   1520     for that node .  The second time the visit uses a different method
   1521     that generates the appropriate code to perform the assignment.
   1522     These delegator classes wrap the original AST nodes in order to
   1523     support the variant visit methods.
   1524     """
   1525     def __init__(self, obj):
   1526         self.obj = obj
   1527 
   1528     def __getattr__(self, attr):
   1529         return getattr(self.obj, attr)
   1530 
   1531 class AugGetattr(Delegator):
   1532     pass
   1533 
   1534 class AugName(Delegator):
   1535     pass
   1536 
   1537 class AugSlice(Delegator):
   1538     pass
   1539 
   1540 class AugSubscript(Delegator):
   1541     pass
   1542 
   1543 wrapper = {
   1544     ast.Getattr: AugGetattr,
   1545     ast.Name: AugName,
   1546     ast.Slice: AugSlice,
   1547     ast.Subscript: AugSubscript,
   1548     }
   1549 
   1550 def wrap_aug(node):
   1551     return wrapper[node.__class__](node)
   1552 
   1553 if __name__ == "__main__":
   1554     for file in sys.argv[1:]:
   1555         compileFile(file)
   1556