def extract_control_blocks(head, blocks, cfg)

      # Find the last control block, i.e. the block that has a successor that is not in the loop.
      last_control_block = nil
      blocks.each do |b|
        cfg.successors[b].each do |succ|
          next if blocks.include?(succ)
          # The last control block has to be unique.
          raise StandardError if last_control_block
          last_control_block = b
        end
      end

      # The control block's succesor that is not in the loop is the unique exit block.
      exit_block = cfg.successors[last_control_block].select{|b| !blocks.include?(b)}
      raise StandardError unless exit_block.size == 1

      # In the case of a simple control statement, the last control block is the head block
      # and there are no other control blocks.
      return [last_control_block], exit_block if last_control_block == head

      # If the loop has a complicated control statement, there will be multiple control
      # blocks. Identify them all the way up to the head block.
      work_list = [last_control_block]
      control_blocks = [last_control_block]
      until work_list.empty?
        cfg.predecessors[work_list.shift].each do |pred|
          next if control_blocks.include?(pred)
          next if pred == head && (control_blocks.push(pred) || true)
          control_blocks.push(pred)
          work_list |= [pred]
        end
      end

      return control_blocks, exit_block
    end
def extract_control_blocks(head, blocks, cfg)

      # Find the last control block, i.e. the block that has a successor that is not in the loop.
      last_control_block = nil
      blocks.each do |b|
        cfg.successors[b].each do |succ|
          next if blocks.include?(succ)
          # The last control block has to be unique.
          raise StandardError if last_control_block
          last_control_block = b
        end
      end

      # The control block's succesor that is not in the loop is the unique exit block.
      exit_block = cfg.successors[last_control_block].select{|b| !blocks.include?(b)}
      raise StandardError unless exit_block.size == 1

      # In the case of a simple control statement, the last control block is the head block
      # and there are no other control blocks.
      return [last_control_block], exit_block if last_control_block == head

      # If the loop has a complicated control statement, there will be multiple control
      # blocks. Identify them all the way up to the head block.
      work_list = [last_control_block]
      control_blocks = [last_control_block]
      until work_list.empty?
        cfg.predecessors[work_list.shift].each do |pred|
          next if control_blocks.include?(pred)
          next if pred == head && (control_blocks.push(pred) || true)
          control_blocks.push(pred)
          work_list |= [pred]
        end
      end

      return control_blocks, exit_block
    end
Given a loop, this function returns a tuple containing the loop's control blocks
 and its (unique) exit block.