Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/compiler/__init__.py

    r2 r391  
    2121    Generates a .pyc file by compiling filename.
    2222"""
    23 from warnings import warnpy3k
    24 warnpy3k("the compiler package has been removed in Python 3.0", stacklevel=2)
    25 del warnpy3k
     23
     24import warnings
     25
     26warnings.warn("The compiler package is deprecated and removed in Python 3.x.",
     27              DeprecationWarning, stacklevel=2)
    2628
    2729from compiler.transformer import parse, parseFile
  • python/trunk/Lib/compiler/ast.py

    r2 r391  
    5252
    5353class Add(Node):
    54     def __init__(self, (left, right), lineno=None):
    55         self.left = left
    56         self.right = right
     54    def __init__(self, leftright, lineno=None):
     55        self.left = leftright[0]
     56        self.right = leftright[1]
    5757        self.lineno = lineno
    5858
     
    432432
    433433class Div(Node):
    434     def __init__(self, (left, right), lineno=None):
    435         self.left = left
    436         self.right = right
     434    def __init__(self, leftright, lineno=None):
     435        self.left = leftright[0]
     436        self.right = leftright[1]
    437437        self.lineno = lineno
    438438
     
    486486
    487487class FloorDiv(Node):
    488     def __init__(self, (left, right), lineno=None):
    489         self.left = left
    490         self.right = right
     488    def __init__(self, leftright, lineno=None):
     489        self.left = leftright[0]
     490        self.right = leftright[1]
    491491        self.lineno = lineno
    492492
     
    561561
    562562
    563 
    564563    def getChildren(self):
    565564        children = []
     
    591590        self.varargs = self.kwargs = None
    592591
     592
    593593    def getChildren(self):
    594594        return self.code,
     
    607607        self.lineno = lineno
    608608        self.is_outmost = False
    609 
    610609
    611610    def getChildren(self):
     
    785784
    786785
    787 
    788786    def getChildren(self):
    789787        children = []
     
    804802
    805803class LeftShift(Node):
    806     def __init__(self, (left, right), lineno=None):
    807         self.left = left
    808         self.right = right
     804    def __init__(self, leftright, lineno=None):
     805        self.left = leftright[0]
     806        self.right = leftright[1]
    809807        self.lineno = lineno
    810808
     
    893891        return "ListCompIf(%s)" % (repr(self.test),)
    894892
     893class SetComp(Node):
     894    def __init__(self, expr, quals, lineno=None):
     895        self.expr = expr
     896        self.quals = quals
     897        self.lineno = lineno
     898
     899    def getChildren(self):
     900        children = []
     901        children.append(self.expr)
     902        children.extend(flatten(self.quals))
     903        return tuple(children)
     904
     905    def getChildNodes(self):
     906        nodelist = []
     907        nodelist.append(self.expr)
     908        nodelist.extend(flatten_nodes(self.quals))
     909        return tuple(nodelist)
     910
     911    def __repr__(self):
     912        return "SetComp(%s, %s)" % (repr(self.expr), repr(self.quals))
     913
     914class DictComp(Node):
     915    def __init__(self, key, value, quals, lineno=None):
     916        self.key = key
     917        self.value = value
     918        self.quals = quals
     919        self.lineno = lineno
     920
     921    def getChildren(self):
     922        children = []
     923        children.append(self.key)
     924        children.append(self.value)
     925        children.extend(flatten(self.quals))
     926        return tuple(children)
     927
     928    def getChildNodes(self):
     929        nodelist = []
     930        nodelist.append(self.key)
     931        nodelist.append(self.value)
     932        nodelist.extend(flatten_nodes(self.quals))
     933        return tuple(nodelist)
     934
     935    def __repr__(self):
     936        return "DictComp(%s, %s, %s)" % (repr(self.key), repr(self.value), repr(self.quals))
     937
    895938class Mod(Node):
    896     def __init__(self, (left, right), lineno=None):
    897         self.left = left
    898         self.right = right
     939    def __init__(self, leftright, lineno=None):
     940        self.left = leftright[0]
     941        self.right = leftright[1]
    899942        self.lineno = lineno
    900943
     
    924967
    925968class Mul(Node):
    926     def __init__(self, (left, right), lineno=None):
    927         self.left = left
    928         self.right = right
     969    def __init__(self, leftright, lineno=None):
     970        self.left = leftright[0]
     971        self.right = leftright[1]
    929972        self.lineno = lineno
    930973
     
    9961039
    9971040class Power(Node):
    998     def __init__(self, (left, right), lineno=None):
    999         self.left = left
    1000         self.right = right
     1041    def __init__(self, leftright, lineno=None):
     1042        self.left = leftright[0]
     1043        self.right = leftright[1]
    10011044        self.lineno = lineno
    10021045
     
    10961139
    10971140class RightShift(Node):
    1098     def __init__(self, (left, right), lineno=None):
    1099         self.left = left
    1100         self.right = right
     1141    def __init__(self, leftright, lineno=None):
     1142        self.left = leftright[0]
     1143        self.right = leftright[1]
    11011144        self.lineno = lineno
    11021145
     
    11091152    def __repr__(self):
    11101153        return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
     1154
     1155class Set(Node):
     1156    def __init__(self, nodes, lineno=None):
     1157        self.nodes = nodes
     1158        self.lineno = lineno
     1159
     1160    def getChildren(self):
     1161        return tuple(flatten(self.nodes))
     1162
     1163    def getChildNodes(self):
     1164        nodelist = []
     1165        nodelist.extend(flatten_nodes(self.nodes))
     1166        return tuple(nodelist)
     1167
     1168    def __repr__(self):
     1169        return "Set(%s)" % (repr(self.nodes),)
    11111170
    11121171class Slice(Node):
     
    11711230
    11721231class Sub(Node):
    1173     def __init__(self, (left, right), lineno=None):
    1174         self.left = left
    1175         self.right = right
     1232    def __init__(self, leftright, lineno=None):
     1233        self.left = leftright[0]
     1234        self.right = leftright[1]
    11761235        self.lineno = lineno
    11771236
  • python/trunk/Lib/compiler/consts.py

    r2 r391  
    55
    66SC_LOCAL = 1
    7 SC_GLOBAL = 2
    8 SC_FREE = 3
    9 SC_CELL = 4
    10 SC_UNKNOWN = 5
     7SC_GLOBAL_IMPLICIT = 2
     8SC_GLOBAL_EXPLICIT = 3
     9SC_FREE = 4
     10SC_CELL = 5
     11SC_UNKNOWN = 6
    1112
    1213CO_OPTIMIZED = 0x0001
  • python/trunk/Lib/compiler/pyassem.py

    r2 r391  
    2222                print "end", repr(self.current)
    2323                print "    next", self.current.next
     24                print "    prev", self.current.prev
    2425                print "   ", self.current.get_children()
    2526            print repr(block)
     
    4142            block = self.newBlock()
    4243
    43         # Note: If the current block ends with an unconditional
    44         # control transfer, then it is incorrect to add an implicit
    45         # transfer to the block graph.  The current code requires
    46         # these edges to get the blocks emitted in the right order,
    47         # however. :-(  If a client needs to remove these edges, call
    48         # pruneEdges().
    49 
     44        # Note: If the current block ends with an unconditional control
     45        # transfer, then it is techically incorrect to add an implicit
     46        # transfer to the block graph. Doing so results in code generation
     47        # for unreachable blocks.  That doesn't appear to be very common
     48        # with Python code and since the built-in compiler doesn't optimize
     49        # it out we don't either.
    5050        self.current.addNext(block)
    5151        self.startBlock(block)
     
    7070        if self._debug:
    7171            print "\t", inst
    72         if inst[0] in ['RETURN_VALUE', 'YIELD_VALUE']:
    73             self.current.addOutEdge(self.exit)
    7472        if len(inst) == 2 and isinstance(inst[1], Block):
    7573            self.current.addOutEdge(inst[1])
     
    8179        i.e. each node appears before all of its successors
    8280        """
    83         # XXX make sure every node that doesn't have an explicit next
    84         # is set so that next points to exit
    85         for b in self.blocks.elements():
    86             if b is self.exit:
    87                 continue
    88             if not b.next:
    89                 b.addNext(self.exit)
    90         order = dfs_postorder(self.entry, {})
    91         order.reverse()
    92         self.fixupOrder(order, self.exit)
    93         # hack alert
    94         if not self.exit in order:
    95             order.append(self.exit)
    96 
     81        order = order_blocks(self.entry, self.exit)
    9782        return order
    98 
    99     def fixupOrder(self, blocks, default_next):
    100         """Fixup bad order introduced by DFS."""
    101 
    102         # XXX This is a total mess.  There must be a better way to get
    103         # the code blocks in the right order.
    104 
    105         self.fixupOrderHonorNext(blocks, default_next)
    106         self.fixupOrderForward(blocks, default_next)
    107 
    108     def fixupOrderHonorNext(self, blocks, default_next):
    109         """Fix one problem with DFS.
    110 
    111         The DFS uses child block, but doesn't know about the special
    112         "next" block.  As a result, the DFS can order blocks so that a
    113         block isn't next to the right block for implicit control
    114         transfers.
    115         """
    116         index = {}
    117         for i in range(len(blocks)):
    118             index[blocks[i]] = i
    119 
    120         for i in range(0, len(blocks) - 1):
    121             b = blocks[i]
    122             n = blocks[i + 1]
    123             if not b.next or b.next[0] == default_next or b.next[0] == n:
    124                 continue
    125             # The blocks are in the wrong order.  Find the chain of
    126             # blocks to insert where they belong.
    127             cur = b
    128             chain = []
    129             elt = cur
    130             while elt.next and elt.next[0] != default_next:
    131                 chain.append(elt.next[0])
    132                 elt = elt.next[0]
    133             # Now remove the blocks in the chain from the current
    134             # block list, so that they can be re-inserted.
    135             l = []
    136             for b in chain:
    137                 assert index[b] > i
    138                 l.append((index[b], b))
    139             l.sort()
    140             l.reverse()
    141             for j, b in l:
    142                 del blocks[index[b]]
    143             # Insert the chain in the proper location
    144             blocks[i:i + 1] = [cur] + chain
    145             # Finally, re-compute the block indexes
    146             for i in range(len(blocks)):
    147                 index[blocks[i]] = i
    148 
    149     def fixupOrderForward(self, blocks, default_next):
    150         """Make sure all JUMP_FORWARDs jump forward"""
    151         index = {}
    152         chains = []
    153         cur = []
    154         for b in blocks:
    155             index[b] = len(chains)
    156             cur.append(b)
    157             if b.next and b.next[0] == default_next:
    158                 chains.append(cur)
    159                 cur = []
    160         chains.append(cur)
    161 
    162         while 1:
    163             constraints = []
    164 
    165             for i in range(len(chains)):
    166                 l = chains[i]
    167                 for b in l:
    168                     for c in b.get_children():
    169                         if index[c] < i:
    170                             forward_p = 0
    171                             for inst in b.insts:
    172                                 if inst[0] == 'JUMP_FORWARD':
    173                                     if inst[1] == c:
    174                                         forward_p = 1
    175                             if not forward_p:
    176                                 continue
    177                             constraints.append((index[c], i))
    178 
    179             if not constraints:
    180                 break
    181 
    182             # XXX just do one for now
    183             # do swaps to get things in the right order
    184             goes_before, a_chain = constraints[0]
    185             assert a_chain > goes_before
    186             c = chains[a_chain]
    187             chains.remove(c)
    188             chains.insert(goes_before, c)
    189 
    190         del blocks[:]
    191         for c in chains:
    192             for b in c:
    193                 blocks.append(b)
    19483
    19584    def getBlocks(self):
     
    20695        return l
    20796
    208 def dfs_postorder(b, seen):
    209     """Depth-first search of tree rooted at b, return in postorder"""
     97
     98def order_blocks(start_block, exit_block):
     99    """Order blocks so that they are emitted in the right order"""
     100    # Rules:
     101    # - when a block has a next block, the next block must be emitted just after
     102    # - when a block has followers (relative jumps), it must be emitted before
     103    #   them
     104    # - all reachable blocks must be emitted
    210105    order = []
    211     seen[b] = b
    212     for c in b.get_children():
    213         if c in seen:
     106
     107    # Find all the blocks to be emitted.
     108    remaining = set()
     109    todo = [start_block]
     110    while todo:
     111        b = todo.pop()
     112        if b in remaining:
    214113            continue
    215         order = order + dfs_postorder(c, seen)
    216     order.append(b)
     114        remaining.add(b)
     115        for c in b.get_children():
     116            if c not in remaining:
     117                todo.append(c)
     118
     119    # A block is dominated by another block if that block must be emitted
     120    # before it.
     121    dominators = {}
     122    for b in remaining:
     123        if __debug__ and b.next:
     124            assert b is b.next[0].prev[0], (b, b.next)
     125        # Make sure every block appears in dominators, even if no
     126        # other block must precede it.
     127        dominators.setdefault(b, set())
     128        # preceding blocks dominate following blocks
     129        for c in b.get_followers():
     130            while 1:
     131                dominators.setdefault(c, set()).add(b)
     132                # Any block that has a next pointer leading to c is also
     133                # dominated because the whole chain will be emitted at once.
     134                # Walk backwards and add them all.
     135                if c.prev and c.prev[0] is not b:
     136                    c = c.prev[0]
     137                else:
     138                    break
     139
     140    def find_next():
     141        # Find a block that can be emitted next.
     142        for b in remaining:
     143            for c in dominators[b]:
     144                if c in remaining:
     145                    break # can't emit yet, dominated by a remaining block
     146            else:
     147                return b
     148        assert 0, 'circular dependency, cannot find next block'
     149
     150    b = start_block
     151    while 1:
     152        order.append(b)
     153        remaining.discard(b)
     154        if b.next:
     155            b = b.next[0]
     156            continue
     157        elif b is not exit_block and not b.has_unconditional_transfer():
     158            order.append(exit_block)
     159        if not remaining:
     160            break
     161        b = find_next()
    217162    return order
     163
    218164
    219165class Block:
     
    222168    def __init__(self, label=''):
    223169        self.insts = []
    224         self.inEdges = misc.Set()
    225         self.outEdges = misc.Set()
     170        self.outEdges = set()
    226171        self.label = label
    227172        self.bid = Block._count
    228173        self.next = []
     174        self.prev = []
    229175        Block._count = Block._count + 1
    230176
     
    242188    def emit(self, inst):
    243189        op = inst[0]
    244         if op[:4] == 'JUMP':
    245             self.outEdges.add(inst[1])
    246190        self.insts.append(inst)
    247191
    248192    def getInstructions(self):
    249193        return self.insts
    250 
    251     def addInEdge(self, block):
    252         self.inEdges.add(block)
    253194
    254195    def addOutEdge(self, block):
     
    258199        self.next.append(block)
    259200        assert len(self.next) == 1, map(str, self.next)
    260 
    261     _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE',
    262                         'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
    263 
    264     def pruneNext(self):
    265         """Remove bogus edge for unconditional transfers
    266 
    267         Each block has a next edge that accounts for implicit control
    268         transfers, e.g. from a JUMP_IF_FALSE to the block that will be
    269         executed if the test is true.
    270 
    271         These edges must remain for the current assembler code to
    272         work. If they are removed, the dfs_postorder gets things in
    273         weird orders.  However, they shouldn't be there for other
    274         purposes, e.g. conversion to SSA form.  This method will
    275         remove the next edge when it follows an unconditional control
    276         transfer.
    277         """
     201        block.prev.append(self)
     202        assert len(block.prev) == 1, map(str, block.prev)
     203
     204    _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS',
     205                        'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP',
     206                        )
     207
     208    def has_unconditional_transfer(self):
     209        """Returns True if there is an unconditional transfer to an other block
     210        at the end of this block. This means there is no risk for the bytecode
     211        executer to go past this block's bytecode."""
    278212        try:
    279213            op, arg = self.insts[-1]
    280214        except (IndexError, ValueError):
    281215            return
    282         if op in self._uncond_transfer:
    283             self.next = []
     216        return op in self._uncond_transfer
    284217
    285218    def get_children(self):
    286         if self.next and self.next[0] in self.outEdges:
    287             self.outEdges.remove(self.next[0])
    288         return self.outEdges.elements() + self.next
     219        return list(self.outEdges) + self.next
     220
     221    def get_followers(self):
     222        """Get the whole list of followers, including the next block."""
     223        followers = set(self.next)
     224        # Blocks that must be emitted *after* this one, because of
     225        # bytecode offsets (e.g. relative jumps) pointing to them.
     226        for inst in self.insts:
     227            if inst[0] in PyFlowGraph.hasjrel:
     228                followers.add(inst[1])
     229        return followers
    289230
    290231    def getContainedGraphs(self):
     
    447388                pc = pc + 3
    448389            opname = inst[0]
    449             if self.hasjrel.has_elt(opname):
     390            if opname in self.hasjrel:
    450391                oparg = inst[1]
    451392                offset = begin[oparg] - pc
    452393                insts[i] = opname, offset
    453             elif self.hasjabs.has_elt(opname):
     394            elif opname in self.hasjabs:
    454395                insts[i] = opname, begin[inst[1]]
    455396        self.stage = FLAT
    456397
    457     hasjrel = misc.Set()
     398    hasjrel = set()
    458399    for i in dis.hasjrel:
    459400        hasjrel.add(dis.opname[i])
    460     hasjabs = misc.Set()
     401    hasjabs = set()
    461402    for i in dis.hasjabs:
    462403        hasjabs.add(dis.opname[i])
     
    745686        'POP_TOP': -1,
    746687        'DUP_TOP': 1,
    747         'LIST_APPEND': -2,
     688        'LIST_APPEND': -1,
     689        'SET_ADD': -1,
     690        'MAP_ADD': -2,
    748691        'SLICE+1': -1,
    749692        'SLICE+2': -1,
     
    794737    def BUILD_LIST(self, count):
    795738        return -count+1
     739    def BUILD_SET(self, count):
     740        return -count+1
    796741    def CALL_FUNCTION(self, argc):
    797742        hi, lo = divmod(argc, 256)
  • python/trunk/Lib/compiler/pycodegen.py

    r2 r391  
    88from compiler import ast, parse, walk, syntax
    99from compiler import pyassem, misc, future, symbols
    10 from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
     10from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \
     11     SC_FREE, SC_CELL
    1112from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
    1213     CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
     
    283284            else:
    284285                self.emit(prefix + '_FAST', name)
    285         elif scope == SC_GLOBAL:
     286        elif scope == SC_GLOBAL_EXPLICIT:
     287            self.emit(prefix + '_GLOBAL', name)
     288        elif scope == SC_GLOBAL_IMPLICIT:
    286289            if not self.optimized:
    287290                self.emit(prefix + '_NAME', name)
     
    419422            self.visit(test)
    420423            nextTest = self.newBlock()
    421             self.emit('JUMP_IF_FALSE', nextTest)
     424            self.emit('POP_JUMP_IF_FALSE', nextTest)
    422425            self.nextBlock()
    423             self.emit('POP_TOP')
    424426            self.visit(suite)
    425427            self.emit('JUMP_FORWARD', end)
    426428            self.startBlock(nextTest)
    427             self.emit('POP_TOP')
    428429        if node.else_:
    429430            self.visit(node.else_)
     
    444445        self.set_lineno(node, force=True)
    445446        self.visit(node.test)
    446         self.emit('JUMP_IF_FALSE', else_ or after)
     447        self.emit('POP_JUMP_IF_FALSE', else_ or after)
    447448
    448449        self.nextBlock()
    449         self.emit('POP_TOP')
    450450        self.visit(node.body)
    451451        self.emit('JUMP_ABSOLUTE', loop)
    452452
    453453        self.startBlock(else_) # or just the POPs if not else clause
    454         self.emit('POP_TOP')
    455454        self.emit('POP_BLOCK')
    456455        self.setups.pop()
     
    523522            self.emit(jump, end)
    524523            self.nextBlock()
    525             self.emit('POP_TOP')
    526524        self.visit(node.nodes[-1])
    527525        self.nextBlock(end)
    528526
    529527    def visitAnd(self, node):
    530         self.visitTest(node, 'JUMP_IF_FALSE')
     528        self.visitTest(node, 'JUMP_IF_FALSE_OR_POP')
    531529
    532530    def visitOr(self, node):
    533         self.visitTest(node, 'JUMP_IF_TRUE')
     531        self.visitTest(node, 'JUMP_IF_TRUE_OR_POP')
    534532
    535533    def visitIfExp(self, node):
     
    537535        elseblock = self.newBlock()
    538536        self.visit(node.test)
    539         self.emit('JUMP_IF_FALSE', elseblock)
    540         self.emit('POP_TOP')
     537        self.emit('POP_JUMP_IF_FALSE', elseblock)
    541538        self.visit(node.then)
    542539        self.emit('JUMP_FORWARD', endblock)
    543540        self.nextBlock(elseblock)
    544         self.emit('POP_TOP')
    545541        self.visit(node.else_)
    546542        self.nextBlock(endblock)
     
    554550            self.emit('ROT_THREE')
    555551            self.emit('COMPARE_OP', op)
    556             self.emit('JUMP_IF_FALSE', cleanup)
     552            self.emit('JUMP_IF_FALSE_OR_POP', cleanup)
    557553            self.nextBlock()
    558             self.emit('POP_TOP')
    559554        # now do the last comparison
    560555        if node.ops:
     
    571566
    572567    # list comprehensions
    573     __list_count = 0
    574 
    575568    def visitListComp(self, node):
    576569        self.set_lineno(node)
    577570        # setup list
    578         tmpname = "$list%d" % self.__list_count
    579         self.__list_count = self.__list_count + 1
    580571        self.emit('BUILD_LIST', 0)
    581         self.emit('DUP_TOP')
    582         self._implicitNameOp('STORE', tmpname)
    583572
    584573        stack = []
     
    592581            stack.insert(0, (start, cont, anchor))
    593582
    594         self._implicitNameOp('LOAD', tmpname)
    595583        self.visit(node.expr)
    596         self.emit('LIST_APPEND')
     584        self.emit('LIST_APPEND', len(node.quals) + 1)
    597585
    598586        for start, cont, anchor in stack:
    599587            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)
     588                self.nextBlock(cont)
    605589            self.emit('JUMP_ABSOLUTE', start)
    606590            self.startBlock(anchor)
    607         self._implicitNameOp('DELETE', tmpname)
    608 
    609         self.__list_count = self.__list_count - 1
     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)
    610640
    611641    def visitListCompFor(self, node):
     
    625655        self.set_lineno(node, force=True)
    626656        self.visit(node.test)
    627         self.emit('JUMP_IF_FALSE', branch)
     657        self.emit('POP_JUMP_IF_FALSE', branch)
    628658        self.newBlock()
    629         self.emit('POP_TOP')
    630659
    631660    def _makeClosure(self, gen, args):
     
    673702        for start, cont, anchor, end in stack:
    674703            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)
     704                self.nextBlock(cont)
    680705            self.emit('JUMP_ABSOLUTE', start)
    681706            self.startBlock(anchor)
    682707            self.emit('POP_BLOCK')
    683708            self.setups.pop()
    684             self.startBlock(end)
     709            self.nextBlock(end)
    685710
    686711        self.emit('LOAD_CONST', None)
     
    710735        self.set_lineno(node, force=True)
    711736        self.visit(node.test)
    712         self.emit('JUMP_IF_FALSE', branch)
     737        self.emit('POP_JUMP_IF_FALSE', branch)
    713738        self.newBlock()
    714         self.emit('POP_TOP')
    715739
    716740    # exception related
     
    727751            self.nextBlock()
    728752            self.visit(node.test)
    729             self.emit('JUMP_IF_TRUE', end)
     753            self.emit('POP_JUMP_IF_TRUE', end)
    730754            self.nextBlock()
    731             self.emit('POP_TOP')
    732755            self.emit('LOAD_GLOBAL', 'AssertionError')
    733756            if node.fail:
     
    737760                self.emit('RAISE_VARARGS', 1)
    738761            self.nextBlock(end)
    739             self.emit('POP_TOP')
    740762
    741763    def visitRaise(self, node):
     
    780802                self.emit('COMPARE_OP', 'exception match')
    781803                next = self.newBlock()
    782                 self.emit('JUMP_IF_FALSE', next)
     804                self.emit('POP_JUMP_IF_FALSE', next)
    783805                self.nextBlock()
    784                 self.emit('POP_TOP')
    785806            self.emit('POP_TOP')
    786807            if target:
     
    795816            else:
    796817                self.nextBlock()
    797             if expr: # XXX
    798                 self.emit('POP_TOP')
    799818        self.emit('END_FINALLY')
    800819        if node.else_:
     
    825844        body = self.newBlock()
    826845        final = self.newBlock()
    827         valuevar = "$value%d" % self.__with_count
    828846        self.__with_count += 1
     847        valuevar = "_[%d]" % self.__with_count
    829848        self.set_lineno(node)
    830849        self.visit(node.expr)
     
    901920        if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
    902921            level = -1
    903         fromlist = map(lambda (name, alias): name, node.names)
     922        fromlist = tuple(name for (name, alias) in node.names)
    904923        if VERSION > 1:
    905924            self.emit('LOAD_CONST', level)
    906             self.emit('LOAD_CONST', tuple(fromlist))
     925            self.emit('LOAD_CONST', fromlist)
    907926        self.emit('IMPORT_NAME', node.modname)
    908927        for name, alias in node.names:
     
    12461265        self.emit('BUILD_LIST', len(node.nodes))
    12471266
     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
    12481273    def visitSliceobj(self, node):
    12491274        for child in node.nodes:
  • python/trunk/Lib/compiler/symbols.py

    r2 r391  
    22
    33from compiler import ast
    4 from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
     4from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \
     5    SC_FREE, SC_CELL, SC_UNKNOWN
    56from compiler.misc import mangle
    67import types
     
    9091        """
    9192        if name in self.globals:
    92             return SC_GLOBAL
     93            return SC_GLOBAL_EXPLICIT
    9394        if name in self.cells:
    9495            return SC_CELL
     
    100101            return SC_UNKNOWN
    101102        else:
    102             return SC_GLOBAL
     103            return SC_GLOBAL_IMPLICIT
    103104
    104105    def get_free_vars(self):
     
    153154                   or isinstance(self, ClassScope):
    154155                    self.frees[name] = 1
    155                 elif sc == SC_GLOBAL:
     156                elif sc == SC_GLOBAL_IMPLICIT:
    156157                    child_globals.append(name)
    157158                elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
  • python/trunk/Lib/compiler/transformer.py

    r2 r391  
    582582    exprlist = testlist
    583583
    584     def testlist_gexp(self, nodelist):
    585         if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for:
     584    def testlist_comp(self, nodelist):
     585        # test ( comp_for | (',' test)* [','] )
     586        assert nodelist[0][0] == symbol.test
     587        if len(nodelist) == 2 and nodelist[1][0] == symbol.comp_for:
    586588            test = self.com_node(nodelist[0])
    587589            return self.com_generator_expression(test, nodelist[1])
     
    750752        if nodelist[1][0] == token.RBRACE:
    751753            return Dict((), lineno=nodelist[0][2])
    752         return self.com_dictmaker(nodelist[1])
     754        return self.com_dictorsetmaker(nodelist[1])
    753755
    754756    def atom_backquote(self, nodelist):
     
    966968
    967969    def com_with(self, nodelist):
    968         # with_stmt: 'with' expr [with_var] ':' suite
     970        # with_stmt: 'with' with_item (',' with_item)* ':' suite
     971        body = self.com_node(nodelist[-1])
     972        for i in range(len(nodelist) - 3, 0, -2):
     973            ret = self.com_with_item(nodelist[i], body, nodelist[0][2])
     974            if i == 1:
     975                return ret
     976            body = ret
     977
     978    def com_with_item(self, nodelist, body, lineno):
     979        # with_item: test ['as' expr]
     980        if len(nodelist) == 4:
     981            var = self.com_assign(nodelist[3], OP_ASSIGN)
     982        else:
     983            var = None
    969984        expr = self.com_node(nodelist[1])
    970         body = self.com_node(nodelist[-1])
    971         if nodelist[2][0] == token.COLON:
    972             var = None
    973         else:
    974             var = self.com_assign(nodelist[2][2], OP_ASSIGN)
    975         return With(expr, var, body, lineno=nodelist[0][2])
    976 
    977     def com_with_var(self, nodelist):
    978         # with_var: 'as' expr
    979         return self.com_node(nodelist[1])
     985        return With(expr, var, body, lineno=lineno)
    980986
    981987    def com_augassign_op(self, node):
     
    9981004        while 1:
    9991005            t = node[0]
    1000             if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_gexp):
     1006            if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_comp):
    10011007                if len(node) > 2:
    10021008                    return self.com_assign_tuple(node, assigning)
     
    10961102            stmts.append(result)
    10971103
    1098     if hasattr(symbol, 'list_for'):
    1099         def com_list_constructor(self, nodelist):
    1100             # listmaker: test ( list_for | (',' test)* [','] )
    1101             values = []
    1102             for i in range(1, len(nodelist)):
    1103                 if nodelist[i][0] == symbol.list_for:
    1104                     assert len(nodelist[i:]) == 1
    1105                     return self.com_list_comprehension(values[0],
    1106                                                        nodelist[i])
    1107                 elif nodelist[i][0] == token.COMMA:
    1108                     continue
    1109                 values.append(self.com_node(nodelist[i]))
    1110             return List(values, lineno=values[0].lineno)
    1111 
    1112         def com_list_comprehension(self, expr, node):
    1113             # list_iter: list_for | list_if
    1114             # list_for: 'for' exprlist 'in' testlist [list_iter]
    1115             # list_if: 'if' test [list_iter]
    1116 
    1117             # XXX should raise SyntaxError for assignment
    1118 
    1119             lineno = node[1][2]
    1120             fors = []
    1121             while node:
    1122                 t = node[1][1]
    1123                 if t == 'for':
    1124                     assignNode = self.com_assign(node[2], OP_ASSIGN)
    1125                     listNode = self.com_node(node[4])
    1126                     newfor = ListCompFor(assignNode, listNode, [])
    1127                     newfor.lineno = node[1][2]
    1128                     fors.append(newfor)
    1129                     if len(node) == 5:
    1130                         node = None
    1131                     else:
    1132                         node = self.com_list_iter(node[5])
    1133                 elif t == 'if':
    1134                     test = self.com_node(node[2])
    1135                     newif = ListCompIf(test, lineno=node[1][2])
    1136                     newfor.ifs.append(newif)
    1137                     if len(node) == 3:
    1138                         node = None
    1139                     else:
    1140                         node = self.com_list_iter(node[3])
     1104    def com_list_constructor(self, nodelist):
     1105        # listmaker: test ( list_for | (',' test)* [','] )
     1106        values = []
     1107        for i in range(1, len(nodelist)):
     1108            if nodelist[i][0] == symbol.list_for:
     1109                assert len(nodelist[i:]) == 1
     1110                return self.com_list_comprehension(values[0],
     1111                                                   nodelist[i])
     1112            elif nodelist[i][0] == token.COMMA:
     1113                continue
     1114            values.append(self.com_node(nodelist[i]))
     1115        return List(values, lineno=values[0].lineno)
     1116
     1117    def com_list_comprehension(self, expr, node):
     1118        return self.com_comprehension(expr, None, node, 'list')
     1119
     1120    def com_comprehension(self, expr1, expr2, node, type):
     1121        # list_iter: list_for | list_if
     1122        # list_for: 'for' exprlist 'in' testlist [list_iter]
     1123        # list_if: 'if' test [list_iter]
     1124
     1125        # XXX should raise SyntaxError for assignment
     1126        # XXX(avassalotti) Set and dict comprehensions should have generator
     1127        #                  semantics. In other words, they shouldn't leak
     1128        #                  variables outside of the comprehension's scope.
     1129
     1130        lineno = node[1][2]
     1131        fors = []
     1132        while node:
     1133            t = node[1][1]
     1134            if t == 'for':
     1135                assignNode = self.com_assign(node[2], OP_ASSIGN)
     1136                compNode = self.com_node(node[4])
     1137                newfor = ListCompFor(assignNode, compNode, [])
     1138                newfor.lineno = node[1][2]
     1139                fors.append(newfor)
     1140                if len(node) == 5:
     1141                    node = None
     1142                elif type == 'list':
     1143                    node = self.com_list_iter(node[5])
    11411144                else:
    1142                     raise SyntaxError, \
    1143                           ("unexpected list comprehension element: %s %d"
    1144                            % (node, lineno))
    1145             return ListComp(expr, fors, lineno=lineno)
    1146 
    1147         def com_list_iter(self, node):
    1148             assert node[0] == symbol.list_iter
    1149             return node[1]
    1150     else:
    1151         def com_list_constructor(self, nodelist):
    1152             values = []
    1153             for i in range(1, len(nodelist), 2):
    1154                 values.append(self.com_node(nodelist[i]))
    1155             return List(values, lineno=values[0].lineno)
    1156 
    1157     if hasattr(symbol, 'gen_for'):
    1158         def com_generator_expression(self, expr, node):
    1159             # gen_iter: gen_for | gen_if
    1160             # gen_for: 'for' exprlist 'in' test [gen_iter]
    1161             # gen_if: 'if' test [gen_iter]
    1162 
    1163             lineno = node[1][2]
    1164             fors = []
    1165             while node:
    1166                 t = node[1][1]
    1167                 if t == 'for':
    1168                     assignNode = self.com_assign(node[2], OP_ASSIGN)
    1169                     genNode = self.com_node(node[4])
    1170                     newfor = GenExprFor(assignNode, genNode, [],
    1171                                         lineno=node[1][2])
    1172                     fors.append(newfor)
    1173                     if (len(node)) == 5:
    1174                         node = None
    1175                     else:
    1176                         node = self.com_gen_iter(node[5])
    1177                 elif t == 'if':
    1178                     test = self.com_node(node[2])
    1179                     newif = GenExprIf(test, lineno=node[1][2])
    1180                     newfor.ifs.append(newif)
    1181                     if len(node) == 3:
    1182                         node = None
    1183                     else:
    1184                         node = self.com_gen_iter(node[3])
     1145                    node = self.com_comp_iter(node[5])
     1146            elif t == 'if':
     1147                test = self.com_node(node[2])
     1148                newif = ListCompIf(test, lineno=node[1][2])
     1149                newfor.ifs.append(newif)
     1150                if len(node) == 3:
     1151                    node = None
     1152                elif type == 'list':
     1153                    node = self.com_list_iter(node[3])
    11851154                else:
    1186                     raise SyntaxError, \
    1187                             ("unexpected generator expression element: %s %d"
    1188                              % (node, lineno))
    1189             fors[0].is_outmost = True
    1190             return GenExpr(GenExprInner(expr, fors), lineno=lineno)
    1191 
    1192         def com_gen_iter(self, node):
    1193             assert node[0] == symbol.gen_iter
    1194             return node[1]
    1195 
    1196     def com_dictmaker(self, nodelist):
    1197         # dictmaker: test ':' test (',' test ':' value)* [',']
    1198         items = []
    1199         for i in range(1, len(nodelist), 4):
    1200             items.append((self.com_node(nodelist[i]),
    1201                           self.com_node(nodelist[i+2])))
    1202         return Dict(items, lineno=items[0][0].lineno)
     1155                    node = self.com_comp_iter(node[3])
     1156            else:
     1157                raise SyntaxError, \
     1158                      ("unexpected comprehension element: %s %d"
     1159                       % (node, lineno))
     1160        if type == 'list':
     1161            return ListComp(expr1, fors, lineno=lineno)
     1162        elif type == 'set':
     1163            return SetComp(expr1, fors, lineno=lineno)
     1164        elif type == 'dict':
     1165            return DictComp(expr1, expr2, fors, lineno=lineno)
     1166        else:
     1167            raise ValueError("unexpected comprehension type: " + repr(type))
     1168
     1169    def com_list_iter(self, node):
     1170        assert node[0] == symbol.list_iter
     1171        return node[1]
     1172
     1173    def com_comp_iter(self, node):
     1174        assert node[0] == symbol.comp_iter
     1175        return node[1]
     1176
     1177    def com_generator_expression(self, expr, node):
     1178        # comp_iter: comp_for | comp_if
     1179        # comp_for: 'for' exprlist 'in' test [comp_iter]
     1180        # comp_if: 'if' test [comp_iter]
     1181
     1182        lineno = node[1][2]
     1183        fors = []
     1184        while node:
     1185            t = node[1][1]
     1186            if t == 'for':
     1187                assignNode = self.com_assign(node[2], OP_ASSIGN)
     1188                genNode = self.com_node(node[4])
     1189                newfor = GenExprFor(assignNode, genNode, [],
     1190                                    lineno=node[1][2])
     1191                fors.append(newfor)
     1192                if (len(node)) == 5:
     1193                    node = None
     1194                else:
     1195                    node = self.com_comp_iter(node[5])
     1196            elif t == 'if':
     1197                test = self.com_node(node[2])
     1198                newif = GenExprIf(test, lineno=node[1][2])
     1199                newfor.ifs.append(newif)
     1200                if len(node) == 3:
     1201                    node = None
     1202                else:
     1203                    node = self.com_comp_iter(node[3])
     1204            else:
     1205                raise SyntaxError, \
     1206                        ("unexpected generator expression element: %s %d"
     1207                         % (node, lineno))
     1208        fors[0].is_outmost = True
     1209        return GenExpr(GenExprInner(expr, fors), lineno=lineno)
     1210
     1211    def com_dictorsetmaker(self, nodelist):
     1212        # dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
     1213        #                   (test (comp_for | (',' test)* [','])) )
     1214        assert nodelist[0] == symbol.dictorsetmaker
     1215        nodelist = nodelist[1:]
     1216        if len(nodelist) == 1 or nodelist[1][0] == token.COMMA:
     1217            # set literal
     1218            items = []
     1219            for i in range(0, len(nodelist), 2):
     1220                items.append(self.com_node(nodelist[i]))
     1221            return Set(items, lineno=items[0].lineno)
     1222        elif nodelist[1][0] == symbol.comp_for:
     1223            # set comprehension
     1224            expr = self.com_node(nodelist[0])
     1225            return self.com_comprehension(expr, None, nodelist[1], 'set')
     1226        elif len(nodelist) > 3 and nodelist[3][0] == symbol.comp_for:
     1227            # dict comprehension
     1228            assert nodelist[1][0] == token.COLON
     1229            key = self.com_node(nodelist[0])
     1230            value = self.com_node(nodelist[2])
     1231            return self.com_comprehension(key, value, nodelist[3], 'dict')
     1232        else:
     1233            # dict literal
     1234            items = []
     1235            for i in range(0, len(nodelist), 4):
     1236                items.append((self.com_node(nodelist[i]),
     1237                              self.com_node(nodelist[i+2])))
     1238            return Dict(items, lineno=items[0][0].lineno)
    12031239
    12041240    def com_apply_trailer(self, primaryNode, nodelist):
     
    12461282
    12471283            if len_nodelist != 2 and isinstance(result, GenExpr) \
    1248                and len(node) == 3 and node[2][0] == symbol.gen_for:
     1284               and len(node) == 3 and node[2][0] == symbol.comp_for:
    12491285                # allow f(x for x in y), but reject f(x for x in y, 1)
    12501286                # should use f((x for x in y), 1) instead of f(x for x in y, 1)
     
    12581294
    12591295    def com_argument(self, nodelist, kw, star_node):
    1260         if len(nodelist) == 3 and nodelist[2][0] == symbol.gen_for:
     1296        if len(nodelist) == 3 and nodelist[2][0] == symbol.comp_for:
    12611297            test = self.com_node(nodelist[1])
    12621298            return 0, self.com_generator_expression(test, nodelist[2])
Note: See TracChangeset for help on using the changeset viewer.