parameters: (start_block, exit_block)
return_statement: return order
docstring: Order blocks so that they are emitted in the right order
docstring_summary: Order blocks so that they are emitted in the right order
docstring_tokens: Order blocks so that they are emitted in the right order
function: def order_blocks(start_block, exit_block):
      """Order blocks so that they are emitted in the right order"""
      # Rules:
      # - when a block has a next block, the next block must be emitted just after
      # - when a block has followers (relative jumps), it must be emitted before
      #   them
      # - all reachable blocks must be emitted
      order = []
  
      # Find all the blocks to be emitted.
      remaining = set()
      todo = [start_block]
      while todo:
          b = todo.pop()
          if b in remaining:
              continue
          remaining.add(b)
          for c in b.get_children():
              if c not in remaining:
                  todo.append(c)
  
      # A block is dominated by another block if that block must be emitted
      # before it.
      dominators = {}
      for b in remaining:
          if __debug__ and b.next:
              assert b is b.next[0].prev[0], (b, b.next)
          # Make sure every block appears in dominators, even if no
          # other block must precede it.
          dominators.setdefault(b, set())
          # preceeding blocks dominate following blocks
          for c in b.get_followers():
              while 1:
                  dominators.setdefault(c, set()).add(b)
                  # Any block that has a next pointer leading to c is also
                  # dominated because the whole chain will be emitted at once.
                  # Walk backwards and add them all.
                  if c.prev and c.prev[0] is not b:
                      c = c.prev[0]
                  else:
                      break
  
      def find_next():
          # Find a block that can be emitted next.
          for b in remaining:
              for c in dominators[b]:
                  if c in remaining:
                      break # can't emit yet, dominated by a remaining block
              else:
                  return b
          assert 0, 'circular dependency, cannot find next block'
  
      b = start_block
      while 1:
          order.append(b)
          remaining.discard(b)
          if b.next:
              b = b.next[0]
              continue
          elif b is not exit_block and not b.has_unconditional_transfer():
              order.append(exit_block)
          if not remaining:
              break
          b = find_next()
      return order
function_tokens: def order_blocks ( start_block , exit_block ) : # Rules: # - when a block has a next block, the next block must be emitted just after # - when a block has followers (relative jumps), it must be emitted before #   them # - all reachable blocks must be emitted order = [ ] # Find all the blocks to be emitted. remaining = set ( ) todo = [ start_block ] while todo : b = todo . pop ( ) if b in remaining : continue remaining . add ( b ) for c in b . get_children ( ) : if c not in remaining : todo . append ( c ) # A block is dominated by another block if that block must be emitted # before it. dominators = { } for b in remaining : if __debug__ and b . next : assert b is b . next [ 0 ] . prev [ 0 ] , ( b , b . next ) # Make sure every block appears in dominators, even if no # other block must precede it. dominators . setdefault ( b , set ( ) ) # preceeding blocks dominate following blocks for c in b . get_followers ( ) : while 1 : dominators . setdefault ( c , set ( ) ) . add ( b ) # Any block that has a next pointer leading to c is also # dominated because the whole chain will be emitted at once. # Walk backwards and add them all. if c . prev and c . prev [ 0 ] is not b : c = c . prev [ 0 ] else : break def find_next ( ) : # Find a block that can be emitted next. for b in remaining : for c in dominators [ b ] : if c in remaining : break # can't emit yet, dominated by a remaining block else : return b assert 0 , 'circular dependency, cannot find next block' b = start_block while 1 : order . append ( b ) remaining . discard ( b ) if b . next : b = b . next [ 0 ] continue elif b is not exit_block and not b . has_unconditional_transfer ( ) : order . append ( exit_block ) if not remaining : break b = find_next ( ) return order