[Python-checkins] CVS: python/dist/src/Tools/compiler/compiler pycodegen.py,1.35,1.36 pyassem.py,1.18,1.19

Jeremy Hylton jhylton@users.sourceforge.net
2001年4月12日 13:21:41 -0700


Update of /cvsroot/python/python/dist/src/Tools/compiler/compiler
In directory usw-pr-cvs1:/tmp/cvs-serv7276/compiler
Modified Files:
	pycodegen.py pyassem.py 
Log Message:
pyassem.py:
 Fix annoying bugs in flow graph layout code. In some cases the
 implicit control transfers weren't honored. In other cases,
 JUMP_FORWARD instructions jumped backwards.
 Remove unused arg from nextBlock().
pycodegen.py
 Add optional force kwarg to set_lineno() that will emit a
 SET_LINENO even if it is the same as the previous lineno.
 Use explicit LOAD_FAST and STORE_FAST to access list comp implicit
 variables. (The symbol table doesn't know about them.)
Index: pycodegen.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pycodegen.py,v
retrieving revision 1.35
retrieving revision 1.36
diff -C2 -r1.35 -r1.36
*** pycodegen.py	2001年04月12日 17:33:34	1.35
--- pycodegen.py	2001年04月12日 20:21:39	1.36
***************
*** 194,198 ****
 self.emit(prefix + '_GLOBAL', name)
 
! def set_lineno(self, node):
 """Emit SET_LINENO if node has lineno attribute and it is 
 different than the last lineno emitted.
--- 194,198 ----
 self.emit(prefix + '_GLOBAL', name)
 
! def set_lineno(self, node, force=0):
 """Emit SET_LINENO if node has lineno attribute and it is 
 different than the last lineno emitted.
***************
*** 206,210 ****
 """
 lineno = getattr(node, 'lineno', None)
! if lineno is not None and lineno != self.last_lineno:
 self.emit('SET_LINENO', lineno)
 self.last_lineno = lineno
--- 206,211 ----
 """
 lineno = getattr(node, 'lineno', None)
! if lineno is not None and (lineno != self.last_lineno
! or force):
 self.emit('SET_LINENO', lineno)
 self.last_lineno = lineno
***************
*** 414,420 ****
 
 def visitListComp(self, node):
- # XXX would it be easier to transform the AST into the form it
- # would have if the list comp were expressed as a series of
- # for and if stmts and an explicit append?
 self.set_lineno(node)
 # setup list
--- 415,418 ----
***************
*** 424,431 ****
 self.emit('DUP_TOP')
 self.emit('LOAD_ATTR', 'append')
! self.storeName(append)
! l = len(node.quals)
 stack = []
! for i, for_ in zip(range(l), node.quals):
 start, anchor = self.visit(for_)
 cont = None
--- 422,429 ----
 self.emit('DUP_TOP')
 self.emit('LOAD_ATTR', 'append')
! self.emit('STORE_FAST', append)
! 
 stack = []
! for i, for_ in zip(range(len(node.quals)), node.quals):
 start, anchor = self.visit(for_)
 cont = None
***************
*** 435,440 ****
 self.visit(if_, cont)
 stack.insert(0, (start, cont, anchor))
! 
! self.loadName(append)
 self.visit(node.expr)
 self.emit('CALL_FUNCTION', 1)
--- 433,438 ----
 self.visit(if_, cont)
 stack.insert(0, (start, cont, anchor))
! 
! self.emit('LOAD_FAST', append)
 self.visit(node.expr)
 self.emit('CALL_FUNCTION', 1)
***************
*** 450,459 ****
 self.emit('JUMP_ABSOLUTE', start)
 self.startBlock(anchor)
! self.delName(append)
 
 self.__list_count = self.__list_count - 1
 
 def visitListCompFor(self, node):
- self.set_lineno(node)
 start = self.newBlock()
 anchor = self.newBlock()
--- 448,456 ----
 self.emit('JUMP_ABSOLUTE', start)
 self.startBlock(anchor)
! self.emit('DELETE_FAST', append)
 
 self.__list_count = self.__list_count - 1
 
 def visitListCompFor(self, node):
 start = self.newBlock()
 anchor = self.newBlock()
***************
*** 469,473 ****
 
 def visitListCompIf(self, node, branch):
! self.set_lineno(node)
 self.visit(node.test)
 self.emit('JUMP_IF_FALSE', branch)
--- 466,470 ----
 
 def visitListCompIf(self, node, branch):
! self.set_lineno(node, force=1)
 self.visit(node.test)
 self.emit('JUMP_IF_FALSE', branch)
***************
*** 673,676 ****
--- 670,674 ----
 
 def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
+ ## print >> sys.stderr, "AssSequence", op, findOp(node), node
 if findOp(node) != 'OP_DELETE':
 self.emit(op, len(node.nodes))
Index: pyassem.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pyassem.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -r1.18 -r1.19
*** pyassem.py	2001年04月12日 17:33:34	1.18
--- pyassem.py	2001年04月12日 20:21:39	1.19
***************
*** 28,36 ****
 if self.current:
 print "end", repr(self.current)
 print " ", self.current.get_children()
 print repr(block)
 self.current = block
 
! def nextBlock(self, block=None, force=0):
 # XXX think we need to specify when there is implicit transfer
 # from one block to the next. might be better to represent this
--- 28,37 ----
 if self.current:
 print "end", repr(self.current)
+ print " next", self.current.next
 print " ", self.current.get_children()
 print repr(block)
 self.current = block
 
! def nextBlock(self, block=None):
 # XXX think we need to specify when there is implicit transfer
 # from one block to the next. might be better to represent this
***************
*** 96,99 ****
--- 97,101 ----
 order = dfs_postorder(self.entry, {})
 order.reverse()
+ self.fixupOrder(order, self.exit)
 # hack alert
 if not self.exit in order:
***************
*** 102,105 ****
--- 104,204 ----
 return order
 
+ def fixupOrder(self, blocks, default_next):
+ """Fixup bad order introduced by DFS."""
+ 
+ # XXX This is a total mess. There must be a better way to get
+ # the code blocks in the right order.
+ 
+ self.fixupOrderHonorNext(blocks, default_next)
+ self.fixupOrderForward(blocks, default_next)
+ 
+ def fixupOrderHonorNext(self, blocks, default_next):
+ """Fix one problem with DFS.
+ 
+ The DFS uses child block, but doesn't know about the special
+ "next" block. As a result, the DFS can order blocks so that a
+ block isn't next to the right block for implicit control
+ transfers.
+ """
+ index = {}
+ for i in range(len(blocks)):
+ index[blocks[i]] = i
+ 
+ for i in range(0, len(blocks) - 1):
+ b = blocks[i]
+ n = blocks[i + 1]
+ if not b.next or b.next[0] == default_next or b.next[0] == n:
+ continue
+ # The blocks are in the wrong order. Find the chain of
+ # blocks to insert where they belong.
+ cur = b
+ chain = []
+ elt = cur
+ while elt.next and elt.next[0] != default_next:
+ chain.append(elt.next[0])
+ elt = elt.next[0]
+ # Now remove the blocks in the chain from the current
+ # block list, so that they can be re-inserted.
+ l = []
+ for b in chain:
+ assert index[b] > i
+ l.append((index[b], b))
+ l.sort()
+ l.reverse()
+ for j, b in l:
+ del blocks[index[b]]
+ # Insert the chain in the proper location
+ blocks[i:i + 1] = [cur] + chain
+ # Finally, re-compute the block indexes
+ for i in range(len(blocks)):
+ index[blocks[i]] = i
+ 
+ def fixupOrderForward(self, blocks, default_next):
+ """Make sure all JUMP_FORWARDs jump forward"""
+ index = {}
+ chains = []
+ cur = []
+ for b in blocks:
+ index[b] = len(chains)
+ cur.append(b)
+ if b.next and b.next[0] == default_next:
+ chains.append(cur)
+ cur = []
+ chains.append(cur)
+ 
+ while 1:
+ constraints = []
+ 
+ for i in range(len(chains)):
+ l = chains[i]
+ for b in l:
+ for c in b.get_children():
+ if index[c] < i:
+ forward_p = 0
+ for inst in b.insts:
+ if inst[0] == 'JUMP_FORWARD':
+ if inst[1] == c:
+ forward_p = 1
+ if not forward_p:
+ continue
+ constraints.append((index[c], i))
+ 
+ if not constraints:
+ break
+ 
+ # XXX just do one for now
+ # do swaps to get things in the right order
+ goes_before, a_chain = constraints[0]
+ assert a_chain > goes_before
+ c = chains[a_chain]
+ chains.remove(c)
+ chains.insert(goes_before, c)
+ 
+ 
+ del blocks[:]
+ for c in chains:
+ for b in c:
+ blocks.append(b)
+ 
 def getBlocks(self):
 return self.blocks.elements()

AltStyle によって変換されたページ (->オリジナル) /