cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1533 lines · 46.1 KB · Python
RawDownload
            # find the block that starts the loop            top = len(self.setups)            while top > 0:                top = top - 1                kind, loop_block = self.setups[top]                if kind == LOOP:                    break            if kind != LOOP:                raise SyntaxError, "'continue' outside loop (%s, %d)" % \                      (node.filename, node.lineno)            self.emit('CONTINUE_LOOP', loop_block)            self.nextBlock()        elif kind == END_FINALLY:            msg = "'continue' not allowed inside 'finally' clause (%s, %d)"            raise SyntaxError, msg % (node.filename, node.lineno)     def visitTest(self, node, jump):        end = self.newBlock()        for child in node.nodes[:-1]:            self.visit(child)            self.emit(jump, end)            self.nextBlock()            self.emit('POP_TOP')        self.visit(node.nodes[-1])        self.nextBlock(end)     def visitAnd(self, node):        self.visitTest(node, 'JUMP_IF_FALSE')     def visitOr(self, node):        self.visitTest(node, 'JUMP_IF_TRUE')     def visitIfExp(self, node):        endblock = self.newBlock()        elseblock = self.newBlock()        self.visit(node.test)        self.emit('JUMP_IF_FALSE', elseblock)        self.emit('POP_TOP')        self.visit(node.then)        self.emit('JUMP_FORWARD', endblock)        self.nextBlock(elseblock)        self.emit('POP_TOP')        self.visit(node.else_)        self.nextBlock(endblock)     def visitCompare(self, node):        self.visit(node.expr)        cleanup = self.newBlock()        for op, code in node.ops[:-1]:            self.visit(code)            self.emit('DUP_TOP')            self.emit('ROT_THREE')            self.emit('COMPARE_OP', op)            self.emit('JUMP_IF_FALSE', cleanup)            self.nextBlock()            self.emit('POP_TOP')        # now do the last comparison        if node.ops:            op, code = node.ops[-1]            self.visit(code)            self.emit('COMPARE_OP', op)        if len(node.ops) > 1:            end = self.newBlock()            self.emit('JUMP_FORWARD', end)            self.startBlock(cleanup)            self.emit('ROT_TWO')            self.emit('POP_TOP')            self.nextBlock(end)     # list comprehensions    __list_count = 0     def visitListComp(self, node):        self.set_lineno(node)        # setup list        append = "$append%d" % self.__list_count        self.__list_count = self.__list_count + 1        self.emit('BUILD_LIST', 0)        self.emit('DUP_TOP')        self.emit('LOAD_ATTR', 'append')        self._implicitNameOp('STORE', append)         stack = []        for i, for_ in zip(range(len(node.quals)), node.quals):            start, anchor = self.visit(for_)            cont = None            for if_ in for_.ifs:                if cont is None:                    cont = self.newBlock()                self.visit(if_, cont)            stack.insert(0, (start, cont, anchor))         self._implicitNameOp('LOAD', append)        self.visit(node.expr)        self.emit('CALL_FUNCTION', 1)        self.emit('POP_TOP')         for start, cont, anchor in stack:            if cont:                skip_one = self.newBlock()                self.emit('JUMP_FORWARD', skip_one)                self.startBlock(cont)                self.emit('POP_TOP')                self.nextBlock(skip_one)            self.emit('JUMP_ABSOLUTE', start)            self.startBlock(anchor)        self._implicitNameOp('DELETE', append)         self.__list_count = self.__list_count - 1     def visitListCompFor(self, node):        start = self.newBlock()        anchor = self.newBlock()         self.visit(node.list)        self.emit('GET_ITER')        self.nextBlock(start)        self.set_lineno(node, force=True)        self.emit('FOR_ITER', anchor)        self.nextBlock()        self.visit(node.assign)        return start, anchor     def visitListCompIf(self, node, branch):        self.set_lineno(node, force=True)        self.visit(node.test)        self.emit('JUMP_IF_FALSE', branch)        self.newBlock()        self.emit('POP_TOP')     def _makeClosure(self, gen, args):        frees = gen.scope.get_free_vars()        if frees:            for name in frees:                self.emit('LOAD_CLOSURE', name)            self.emit('BUILD_TUPLE', len(frees))            self.emit('LOAD_CONST', gen)            self.emit('MAKE_CLOSURE', args)        else:            self.emit('LOAD_CONST', gen)            self.emit('MAKE_FUNCTION', args)     def visitGenExpr(self, node):        gen = GenExprCodeGenerator(node, self.scopes, self.class_name,                                   self.get_module())        walk(node.code, gen)        gen.finish()        self.set_lineno(node)        self._makeClosure(gen, 0)        # precomputation of outmost iterable        self.visit(node.code.quals[0].iter)        self.emit('GET_ITER')        self.emit('CALL_FUNCTION', 1)     def visitGenExprInner(self, node):        self.set_lineno(node)        # setup list         stack = []        for i, for_ in zip(range(len(node.quals)), node.quals):            start, anchor, end = self.visit(for_)            cont = None            for if_ in for_.ifs:                if cont is None:                    cont = self.newBlock()                self.visit(if_, cont)            stack.insert(0, (start, cont, anchor, end))         self.visit(node.expr)        self.emit('YIELD_VALUE')        self.emit('POP_TOP')         for start, cont, anchor, end in stack:            if cont:                skip_one = self.newBlock()                self.emit('JUMP_FORWARD', skip_one)                self.startBlock(cont)                self.emit('POP_TOP')                self.nextBlock(skip_one)            self.emit('JUMP_ABSOLUTE', start)            self.startBlock(anchor)            self.emit('POP_BLOCK')            self.setups.pop()            self.startBlock(end)         self.emit('LOAD_CONST', None)     def visitGenExprFor(self, node):        start = self.newBlock()        anchor = self.newBlock()        end = self.newBlock()         self.setups.push((LOOP, start))        self.emit('SETUP_LOOP', end)         if node.is_outmost:            self.loadName('.0')        else:            self.visit(node.iter)            self.emit('GET_ITER')         self.nextBlock(start)        self.set_lineno(node, force=True)        self.emit('FOR_ITER', anchor)        self.nextBlock()        self.visit(node.assign)        return start, anchor, end     def visitGenExprIf(self, node, branch):        self.set_lineno(node, force=True)        self.visit(node.test)        self.emit('JUMP_IF_FALSE', branch)        self.newBlock()        self.emit('POP_TOP')     # exception related     def visitAssert(self, node):        # XXX would be interesting to implement this via a        # transformation of the AST before this stage        if __debug__:            end = self.newBlock()            self.set_lineno(node)            # XXX AssertionError appears to be special case -- it is always            # loaded as a global even if there is a local name.  I guess this            # is a sort of renaming op.            self.nextBlock()            self.visit(node.test)            self.emit('JUMP_IF_TRUE', end)            self.nextBlock()            self.emit('POP_TOP')            self.emit('LOAD_GLOBAL', 'AssertionError')            if node.fail:                self.visit(node.fail)                self.emit('RAISE_VARARGS', 2)            else:                self.emit('RAISE_VARARGS', 1)            self.nextBlock(end)            self.emit('POP_TOP')     def visitRaise(self, node):        self.set_lineno(node)        n = 0        if node.expr1:            self.visit(node.expr1)            n = n + 1        if node.expr2:            self.visit(node.expr2)            n = n + 1        if node.expr3:            self.visit(node.expr3)            n = n + 1        self.emit('RAISE_VARARGS', n)     def visitTryExcept(self, node):        body = self.newBlock()        handlers = self.newBlock()        end = self.newBlock()        if node.else_:            lElse = self.newBlock()        else:            lElse = end        self.set_lineno(node)        self.emit('SETUP_EXCEPT', handlers)        self.nextBlock(body)        self.setups.push((EXCEPT, body))        self.visit(node.body)        self.emit('POP_BLOCK')        self.setups.pop()        self.emit('JUMP_FORWARD', lElse)        self.startBlock(handlers)         last = len(node.handlers) - 1        for i in range(len(node.handlers)):            expr, target, body = node.handlers[i]            self.set_lineno(expr)            if expr:                self.emit('DUP_TOP')                self.visit(expr)                self.emit('COMPARE_OP', 'exception match')                next = self.newBlock()                self.emit('JUMP_IF_FALSE', next)                self.nextBlock()                self.emit('POP_TOP')            self.emit('POP_TOP')            if target:                self.visit(target)            else:                self.emit('POP_TOP')            self.emit('POP_TOP')            self.visit(body)            self.emit('JUMP_FORWARD', end)            if expr:                self.nextBlock(next)            else:                self.nextBlock()            if expr: # XXX                self.emit('POP_TOP')        self.emit('END_FINALLY')        if node.else_:            self.nextBlock(lElse)            self.visit(node.else_)        self.nextBlock(end)     def visitTryFinally(self, node):        body = self.newBlock()        final = self.newBlock()        self.set_lineno(node)        self.emit('SETUP_FINALLY', final)        self.nextBlock(body)        self.setups.push((TRY_FINALLY, body))        self.visit(node.body)        self.emit('POP_BLOCK')        self.setups.pop()        self.emit('LOAD_CONST', None)        self.nextBlock(final)        self.setups.push((END_FINALLY, final))        self.visit(node.final)        self.emit('END_FINALLY')        self.setups.pop()     __with_count = 0     def visitWith(self, node):        body = self.newBlock()        final = self.newBlock()        exitvar = "$exit%d" % self.__with_count        valuevar = "$value%d" % self.__with_count        self.__with_count += 1        self.set_lineno(node)        self.visit(node.expr)        self.emit('DUP_TOP')        self.emit('LOAD_ATTR', '__exit__')        self._implicitNameOp('STORE', exitvar)        self.emit('LOAD_ATTR', '__enter__')        self.emit('CALL_FUNCTION', 0)        if node.vars is None:            self.emit('POP_TOP')        else:            self._implicitNameOp('STORE', valuevar)        self.emit('SETUP_FINALLY', final)        self.nextBlock(body)        self.setups.push((TRY_FINALLY, body))        if node.vars is not None:            self._implicitNameOp('LOAD', valuevar)            self._implicitNameOp('DELETE', valuevar)            self.visit(node.vars)        self.visit(node.body)        self.emit('POP_BLOCK')        self.setups.pop()        self.emit('LOAD_CONST', None)        self.nextBlock(final)        self.setups.push((END_FINALLY, final))        self._implicitNameOp('LOAD', exitvar)        self._implicitNameOp('DELETE', exitvar)        self.emit('WITH_CLEANUP')        self.emit('END_FINALLY')        self.setups.pop()        self.__with_count -= 1     # misc     def visitDiscard(self, node):        self.set_lineno(node)        self.visit(node.expr)        self.emit('POP_TOP')     def visitConst(self, node):        self.emit('LOAD_CONST', node.value)     def visitKeyword(self, node):        self.emit('LOAD_CONST', node.name)        self.visit(node.expr)     def visitGlobal(self, node):        # no code to generate        pass     def visitName(self, node):        self.set_lineno(node)        self.loadName(node.name)     def visitPass(self, node):        self.set_lineno(node)     def visitImport(self, node):        self.set_lineno(node)        level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1        for name, alias in node.names:            if VERSION > 1:                self.emit('LOAD_CONST', level)                self.emit('LOAD_CONST', None)            self.emit('IMPORT_NAME', name)            mod = name.split(".")[0]            if alias:                self._resolveDots(name)                self.storeName(alias)            else:                self.storeName(mod)     def visitFrom(self, node):        self.set_lineno(node)        level = node.level        if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):            level = -1        fromlist = map(lambda (name, alias): name, node.names)        if VERSION > 1:            self.emit('LOAD_CONST', level)            self.emit('LOAD_CONST', tuple(fromlist))        self.emit('IMPORT_NAME', node.modname)        for name, alias in node.names:            if VERSION > 1:                if name == '*':                    self.namespace = 0                    self.emit('IMPORT_STAR')                    # There can only be one name w/ from ... import *                    assert len(node.names) == 1                    return                else:                    self.emit('IMPORT_FROM', name)                    self._resolveDots(name)                    self.storeName(alias or name)            else:                self.emit('IMPORT_FROM', name)        self.emit('POP_TOP')     def _resolveDots(self, name):        elts = name.split(".")        if len(elts) == 1:            return        for elt in elts[1:]:            self.emit('LOAD_ATTR', elt)     def visitGetattr(self, node):        self.visit(node.expr)        self.emit('LOAD_ATTR', self.mangle(node.attrname))     # next five implement assignments     def visitAssign(self, node):        self.set_lineno(node)        self.visit(node.expr)        dups = len(node.nodes) - 1        for i in range(len(node.nodes)):            elt = node.nodes[i]            if i < dups:                self.emit('DUP_TOP')            if isinstance(elt, ast.Node):                self.visit(elt)     def visitAssName(self, node):        if node.flags == 'OP_ASSIGN':            self.storeName(node.name)        elif node.flags == 'OP_DELETE':            self.set_lineno(node)            self.delName(node.name)        else:            print "oops", node.flags     def visitAssAttr(self, node):        self.visit(node.expr)        if node.flags == 'OP_ASSIGN':            self.emit('STORE_ATTR', self.mangle(node.attrname))        elif node.flags == 'OP_DELETE':            self.emit('DELETE_ATTR', self.mangle(node.attrname))        else:            print "warning: unexpected flags:", node.flags            print node     def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):        if findOp(node) != 'OP_DELETE':            self.emit(op, len(node.nodes))        for child in node.nodes:            self.visit(child)     if VERSION > 1:        visitAssTuple = _visitAssSequence        visitAssList = _visitAssSequence    else:        def visitAssTuple(self, node):            self._visitAssSequence(node, 'UNPACK_TUPLE')         def visitAssList(self, node):            self._visitAssSequence(node, 'UNPACK_LIST')     # augmented assignment     def visitAugAssign(self, node):        self.set_lineno(node)        aug_node = wrap_aug(node.node)        self.visit(aug_node, "load")        self.visit(node.expr)        self.emit(self._augmented_opcode[node.op])        self.visit(aug_node, "store")     _augmented_opcode = {        '+=' : 'INPLACE_ADD',        '-=' : 'INPLACE_SUBTRACT',        '*=' : 'INPLACE_MULTIPLY',        '/=' : 'INPLACE_DIVIDE',

Lines 501–1000 of 1533. Previous lines