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