Changeset 391 for python/trunk/Lib/compiler
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/compiler/__init__.py
r2 r391 21 21 Generates a .pyc file by compiling filename. 22 22 """ 23 from warnings import warnpy3k 24 warnpy3k("the compiler package has been removed in Python 3.0", stacklevel=2) 25 del warnpy3k 23 24 import warnings 25 26 warnings.warn("The compiler package is deprecated and removed in Python 3.x.", 27 DeprecationWarning, stacklevel=2) 26 28 27 29 from compiler.transformer import parse, parseFile -
python/trunk/Lib/compiler/ast.py
r2 r391 52 52 53 53 class Add(Node): 54 def __init__(self, (left, right), lineno=None):55 self.left = left 56 self.right = right54 def __init__(self, leftright, lineno=None): 55 self.left = leftright[0] 56 self.right = leftright[1] 57 57 self.lineno = lineno 58 58 … … 432 432 433 433 class Div(Node): 434 def __init__(self, (left, right), lineno=None):435 self.left = left 436 self.right = right434 def __init__(self, leftright, lineno=None): 435 self.left = leftright[0] 436 self.right = leftright[1] 437 437 self.lineno = lineno 438 438 … … 486 486 487 487 class FloorDiv(Node): 488 def __init__(self, (left, right), lineno=None):489 self.left = left 490 self.right = right488 def __init__(self, leftright, lineno=None): 489 self.left = leftright[0] 490 self.right = leftright[1] 491 491 self.lineno = lineno 492 492 … … 561 561 562 562 563 564 563 def getChildren(self): 565 564 children = [] … … 591 590 self.varargs = self.kwargs = None 592 591 592 593 593 def getChildren(self): 594 594 return self.code, … … 607 607 self.lineno = lineno 608 608 self.is_outmost = False 609 610 609 611 610 def getChildren(self): … … 785 784 786 785 787 788 786 def getChildren(self): 789 787 children = [] … … 804 802 805 803 class LeftShift(Node): 806 def __init__(self, (left, right), lineno=None):807 self.left = left 808 self.right = right804 def __init__(self, leftright, lineno=None): 805 self.left = leftright[0] 806 self.right = leftright[1] 809 807 self.lineno = lineno 810 808 … … 893 891 return "ListCompIf(%s)" % (repr(self.test),) 894 892 893 class 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 914 class 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 895 938 class Mod(Node): 896 def __init__(self, (left, right), lineno=None):897 self.left = left 898 self.right = right939 def __init__(self, leftright, lineno=None): 940 self.left = leftright[0] 941 self.right = leftright[1] 899 942 self.lineno = lineno 900 943 … … 924 967 925 968 class Mul(Node): 926 def __init__(self, (left, right), lineno=None):927 self.left = left 928 self.right = right969 def __init__(self, leftright, lineno=None): 970 self.left = leftright[0] 971 self.right = leftright[1] 929 972 self.lineno = lineno 930 973 … … 996 1039 997 1040 class Power(Node): 998 def __init__(self, (left, right), lineno=None):999 self.left = left 1000 self.right = right1041 def __init__(self, leftright, lineno=None): 1042 self.left = leftright[0] 1043 self.right = leftright[1] 1001 1044 self.lineno = lineno 1002 1045 … … 1096 1139 1097 1140 class RightShift(Node): 1098 def __init__(self, (left, right), lineno=None):1099 self.left = left 1100 self.right = right1141 def __init__(self, leftright, lineno=None): 1142 self.left = leftright[0] 1143 self.right = leftright[1] 1101 1144 self.lineno = lineno 1102 1145 … … 1109 1152 def __repr__(self): 1110 1153 return "RightShift((%s, %s))" % (repr(self.left), repr(self.right)) 1154 1155 class 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),) 1111 1170 1112 1171 class Slice(Node): … … 1171 1230 1172 1231 class Sub(Node): 1173 def __init__(self, (left, right), lineno=None):1174 self.left = left 1175 self.right = right1232 def __init__(self, leftright, lineno=None): 1233 self.left = leftright[0] 1234 self.right = leftright[1] 1176 1235 self.lineno = lineno 1177 1236 -
python/trunk/Lib/compiler/consts.py
r2 r391 5 5 6 6 SC_LOCAL = 1 7 SC_GLOBAL = 2 8 SC_FREE = 3 9 SC_CELL = 4 10 SC_UNKNOWN = 5 7 SC_GLOBAL_IMPLICIT = 2 8 SC_GLOBAL_EXPLICIT = 3 9 SC_FREE = 4 10 SC_CELL = 5 11 SC_UNKNOWN = 6 11 12 12 13 CO_OPTIMIZED = 0x0001 -
python/trunk/Lib/compiler/pyassem.py
r2 r391 22 22 print "end", repr(self.current) 23 23 print " next", self.current.next 24 print " prev", self.current.prev 24 25 print " ", self.current.get_children() 25 26 print repr(block) … … 41 42 block = self.newBlock() 42 43 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. 50 50 self.current.addNext(block) 51 51 self.startBlock(block) … … 70 70 if self._debug: 71 71 print "\t", inst 72 if inst[0] in ['RETURN_VALUE', 'YIELD_VALUE']:73 self.current.addOutEdge(self.exit)74 72 if len(inst) == 2 and isinstance(inst[1], Block): 75 73 self.current.addOutEdge(inst[1]) … … 81 79 i.e. each node appears before all of its successors 82 80 """ 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) 97 82 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 get103 # 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 special112 "next" block. As a result, the DFS can order blocks so that a113 block isn't next to the right block for implicit control114 transfers.115 """116 index = {}117 for i in range(len(blocks)):118 index[blocks[i]] = i119 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 continue125 # The blocks are in the wrong order. Find the chain of126 # blocks to insert where they belong.127 cur = b128 chain = []129 elt = cur130 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 current134 # block list, so that they can be re-inserted.135 l = []136 for b in chain:137 assert index[b] > i138 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 location144 blocks[i:i + 1] = [cur] + chain145 # Finally, re-compute the block indexes146 for i in range(len(blocks)):147 index[blocks[i]] = i148 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 = 0171 for inst in b.insts:172 if inst[0] == 'JUMP_FORWARD':173 if inst[1] == c:174 forward_p = 1175 if not forward_p:176 continue177 constraints.append((index[c], i))178 179 if not constraints:180 break181 182 # XXX just do one for now183 # do swaps to get things in the right order184 goes_before, a_chain = constraints[0]185 assert a_chain > goes_before186 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)194 83 195 84 def getBlocks(self): … … 206 95 return l 207 96 208 def dfs_postorder(b, seen): 209 """Depth-first search of tree rooted at b, return in postorder""" 97 98 def 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 210 105 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: 214 113 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() 217 162 return order 163 218 164 219 165 class Block: … … 222 168 def __init__(self, label=''): 223 169 self.insts = [] 224 self.inEdges = misc.Set() 225 self.outEdges = misc.Set() 170 self.outEdges = set() 226 171 self.label = label 227 172 self.bid = Block._count 228 173 self.next = [] 174 self.prev = [] 229 175 Block._count = Block._count + 1 230 176 … … 242 188 def emit(self, inst): 243 189 op = inst[0] 244 if op[:4] == 'JUMP':245 self.outEdges.add(inst[1])246 190 self.insts.append(inst) 247 191 248 192 def getInstructions(self): 249 193 return self.insts 250 251 def addInEdge(self, block):252 self.inEdges.add(block)253 194 254 195 def addOutEdge(self, block): … … 258 199 self.next.append(block) 259 200 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.""" 278 212 try: 279 213 op, arg = self.insts[-1] 280 214 except (IndexError, ValueError): 281 215 return 282 if op in self._uncond_transfer: 283 self.next = [] 216 return op in self._uncond_transfer 284 217 285 218 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 289 230 290 231 def getContainedGraphs(self): … … 447 388 pc = pc + 3 448 389 opname = inst[0] 449 if self.hasjrel.has_elt(opname):390 if opname in self.hasjrel: 450 391 oparg = inst[1] 451 392 offset = begin[oparg] - pc 452 393 insts[i] = opname, offset 453 elif self.hasjabs.has_elt(opname):394 elif opname in self.hasjabs: 454 395 insts[i] = opname, begin[inst[1]] 455 396 self.stage = FLAT 456 397 457 hasjrel = misc.Set()398 hasjrel = set() 458 399 for i in dis.hasjrel: 459 400 hasjrel.add(dis.opname[i]) 460 hasjabs = misc.Set()401 hasjabs = set() 461 402 for i in dis.hasjabs: 462 403 hasjabs.add(dis.opname[i]) … … 745 686 'POP_TOP': -1, 746 687 'DUP_TOP': 1, 747 'LIST_APPEND': -2, 688 'LIST_APPEND': -1, 689 'SET_ADD': -1, 690 'MAP_ADD': -2, 748 691 'SLICE+1': -1, 749 692 'SLICE+2': -1, … … 794 737 def BUILD_LIST(self, count): 795 738 return -count+1 739 def BUILD_SET(self, count): 740 return -count+1 796 741 def CALL_FUNCTION(self, argc): 797 742 hi, lo = divmod(argc, 256) -
python/trunk/Lib/compiler/pycodegen.py
r2 r391 8 8 from compiler import ast, parse, walk, syntax 9 9 from compiler import pyassem, misc, future, symbols 10 from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL 10 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \ 11 SC_FREE, SC_CELL 11 12 from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, 12 13 CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION, … … 283 284 else: 284 285 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: 286 289 if not self.optimized: 287 290 self.emit(prefix + '_NAME', name) … … 419 422 self.visit(test) 420 423 nextTest = self.newBlock() 421 self.emit(' JUMP_IF_FALSE', nextTest)424 self.emit('POP_JUMP_IF_FALSE', nextTest) 422 425 self.nextBlock() 423 self.emit('POP_TOP')424 426 self.visit(suite) 425 427 self.emit('JUMP_FORWARD', end) 426 428 self.startBlock(nextTest) 427 self.emit('POP_TOP')428 429 if node.else_: 429 430 self.visit(node.else_) … … 444 445 self.set_lineno(node, force=True) 445 446 self.visit(node.test) 446 self.emit(' JUMP_IF_FALSE', else_ or after)447 self.emit('POP_JUMP_IF_FALSE', else_ or after) 447 448 448 449 self.nextBlock() 449 self.emit('POP_TOP')450 450 self.visit(node.body) 451 451 self.emit('JUMP_ABSOLUTE', loop) 452 452 453 453 self.startBlock(else_) # or just the POPs if not else clause 454 self.emit('POP_TOP')455 454 self.emit('POP_BLOCK') 456 455 self.setups.pop() … … 523 522 self.emit(jump, end) 524 523 self.nextBlock() 525 self.emit('POP_TOP')526 524 self.visit(node.nodes[-1]) 527 525 self.nextBlock(end) 528 526 529 527 def visitAnd(self, node): 530 self.visitTest(node, 'JUMP_IF_FALSE ')528 self.visitTest(node, 'JUMP_IF_FALSE_OR_POP') 531 529 532 530 def visitOr(self, node): 533 self.visitTest(node, 'JUMP_IF_TRUE ')531 self.visitTest(node, 'JUMP_IF_TRUE_OR_POP') 534 532 535 533 def visitIfExp(self, node): … … 537 535 elseblock = self.newBlock() 538 536 self.visit(node.test) 539 self.emit('JUMP_IF_FALSE', elseblock) 540 self.emit('POP_TOP') 537 self.emit('POP_JUMP_IF_FALSE', elseblock) 541 538 self.visit(node.then) 542 539 self.emit('JUMP_FORWARD', endblock) 543 540 self.nextBlock(elseblock) 544 self.emit('POP_TOP')545 541 self.visit(node.else_) 546 542 self.nextBlock(endblock) … … 554 550 self.emit('ROT_THREE') 555 551 self.emit('COMPARE_OP', op) 556 self.emit('JUMP_IF_FALSE ', cleanup)552 self.emit('JUMP_IF_FALSE_OR_POP', cleanup) 557 553 self.nextBlock() 558 self.emit('POP_TOP')559 554 # now do the last comparison 560 555 if node.ops: … … 571 566 572 567 # list comprehensions 573 __list_count = 0574 575 568 def visitListComp(self, node): 576 569 self.set_lineno(node) 577 570 # setup list 578 tmpname = "$list%d" % self.__list_count579 self.__list_count = self.__list_count + 1580 571 self.emit('BUILD_LIST', 0) 581 self.emit('DUP_TOP')582 self._implicitNameOp('STORE', tmpname)583 572 584 573 stack = [] … … 592 581 stack.insert(0, (start, cont, anchor)) 593 582 594 self._implicitNameOp('LOAD', tmpname)595 583 self.visit(node.expr) 596 self.emit('LIST_APPEND' )584 self.emit('LIST_APPEND', len(node.quals) + 1) 597 585 598 586 for start, cont, anchor in stack: 599 587 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) 605 589 self.emit('JUMP_ABSOLUTE', start) 606 590 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) 610 640 611 641 def visitListCompFor(self, node): … … 625 655 self.set_lineno(node, force=True) 626 656 self.visit(node.test) 627 self.emit(' JUMP_IF_FALSE', branch)657 self.emit('POP_JUMP_IF_FALSE', branch) 628 658 self.newBlock() 629 self.emit('POP_TOP')630 659 631 660 def _makeClosure(self, gen, args): … … 673 702 for start, cont, anchor, end in stack: 674 703 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) 680 705 self.emit('JUMP_ABSOLUTE', start) 681 706 self.startBlock(anchor) 682 707 self.emit('POP_BLOCK') 683 708 self.setups.pop() 684 self. startBlock(end)709 self.nextBlock(end) 685 710 686 711 self.emit('LOAD_CONST', None) … … 710 735 self.set_lineno(node, force=True) 711 736 self.visit(node.test) 712 self.emit(' JUMP_IF_FALSE', branch)737 self.emit('POP_JUMP_IF_FALSE', branch) 713 738 self.newBlock() 714 self.emit('POP_TOP')715 739 716 740 # exception related … … 727 751 self.nextBlock() 728 752 self.visit(node.test) 729 self.emit(' JUMP_IF_TRUE', end)753 self.emit('POP_JUMP_IF_TRUE', end) 730 754 self.nextBlock() 731 self.emit('POP_TOP')732 755 self.emit('LOAD_GLOBAL', 'AssertionError') 733 756 if node.fail: … … 737 760 self.emit('RAISE_VARARGS', 1) 738 761 self.nextBlock(end) 739 self.emit('POP_TOP')740 762 741 763 def visitRaise(self, node): … … 780 802 self.emit('COMPARE_OP', 'exception match') 781 803 next = self.newBlock() 782 self.emit(' JUMP_IF_FALSE', next)804 self.emit('POP_JUMP_IF_FALSE', next) 783 805 self.nextBlock() 784 self.emit('POP_TOP')785 806 self.emit('POP_TOP') 786 807 if target: … … 795 816 else: 796 817 self.nextBlock() 797 if expr: # XXX798 self.emit('POP_TOP')799 818 self.emit('END_FINALLY') 800 819 if node.else_: … … 825 844 body = self.newBlock() 826 845 final = self.newBlock() 827 valuevar = "$value%d" % self.__with_count828 846 self.__with_count += 1 847 valuevar = "_[%d]" % self.__with_count 829 848 self.set_lineno(node) 830 849 self.visit(node.expr) … … 901 920 if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT): 902 921 level = -1 903 fromlist = map(lambda (name, alias): name,node.names)922 fromlist = tuple(name for (name, alias) in node.names) 904 923 if VERSION > 1: 905 924 self.emit('LOAD_CONST', level) 906 self.emit('LOAD_CONST', tuple(fromlist))925 self.emit('LOAD_CONST', fromlist) 907 926 self.emit('IMPORT_NAME', node.modname) 908 927 for name, alias in node.names: … … 1246 1265 self.emit('BUILD_LIST', len(node.nodes)) 1247 1266 1267 def visitSet(self, node): 1268 self.set_lineno(node) 1269 for elt in node.nodes: 1270 self.visit(elt) 1271 self.emit('BUILD_SET', len(node.nodes)) 1272 1248 1273 def visitSliceobj(self, node): 1249 1274 for child in node.nodes: -
python/trunk/Lib/compiler/symbols.py
r2 r391 2 2 3 3 from compiler import ast 4 from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN 4 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \ 5 SC_FREE, SC_CELL, SC_UNKNOWN 5 6 from compiler.misc import mangle 6 7 import types … … 90 91 """ 91 92 if name in self.globals: 92 return SC_GLOBAL 93 return SC_GLOBAL_EXPLICIT 93 94 if name in self.cells: 94 95 return SC_CELL … … 100 101 return SC_UNKNOWN 101 102 else: 102 return SC_GLOBAL 103 return SC_GLOBAL_IMPLICIT 103 104 104 105 def get_free_vars(self): … … 153 154 or isinstance(self, ClassScope): 154 155 self.frees[name] = 1 155 elif sc == SC_GLOBAL :156 elif sc == SC_GLOBAL_IMPLICIT: 156 157 child_globals.append(name) 157 158 elif isinstance(self, FunctionScope) and sc == SC_LOCAL: -
python/trunk/Lib/compiler/transformer.py
r2 r391 582 582 exprlist = testlist 583 583 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: 586 588 test = self.com_node(nodelist[0]) 587 589 return self.com_generator_expression(test, nodelist[1]) … … 750 752 if nodelist[1][0] == token.RBRACE: 751 753 return Dict((), lineno=nodelist[0][2]) 752 return self.com_dict maker(nodelist[1])754 return self.com_dictorsetmaker(nodelist[1]) 753 755 754 756 def atom_backquote(self, nodelist): … … 966 968 967 969 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 969 984 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) 980 986 981 987 def com_augassign_op(self, node): … … 998 1004 while 1: 999 1005 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): 1001 1007 if len(node) > 2: 1002 1008 return self.com_assign_tuple(node, assigning) … … 1096 1102 stmts.append(result) 1097 1103 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]) 1141 1144 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]) 1185 1154 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) 1203 1239 1204 1240 def com_apply_trailer(self, primaryNode, nodelist): … … 1246 1282 1247 1283 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: 1249 1285 # allow f(x for x in y), but reject f(x for x in y, 1) 1250 1286 # should use f((x for x in y), 1) instead of f(x for x in y, 1) … … 1258 1294 1259 1295 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: 1261 1297 test = self.com_node(nodelist[1]) 1262 1298 return 0, self.com_generator_expression(test, nodelist[2])
Note:
See TracChangeset
for help on using the changeset viewer.