module Control
  Break = Class.new
  Next  = Class.new
  Redo  = Class.new
  @stack = []
  def self.unique_name
    :"_#{@stack.size}"
  end
  def self.push_scope
    @stack.push self.unique_name
    @stack.last 
  end
  def self.pop_scope
    @stack.pop
  end
  def self.last
    @stack.last
  end
  def self.break(label = @stack.last)
    throw label, Control::Break
  end
  def self.next(label = @stack.last)
    throw label, Control::Next
  end
  def self.redo(label = @stack.last)
    throw label, Control::Redo
  end
  def self.label
   self.last
 end
end

module Enumerable
 def with_control
   return to_enum(__method__) unless block_given?
   name = Control.push_scope 
   each{|*a|
     ret = catch(name){ yield(*a) }
     break if ret == Control::Break
     next  if ret == Control::Next
     redo  if ret == Control::Redo    
     ret    
   }
  ensure
    Control.pop_scope
  end
end


1.upto(10).with_control{|i|
  a = Control.label
  1.upto(10).with_control{|j|
     Control.break a if i > 3 && j > 3
     p [i, j]
  }
} 

