require 'continuation'
class GoToProc
def initialize(&b)
@proc, @labels, @first_run = b, {}, true
self.run
@first_run = false
end
def run
callcc do |k|
@exit = k
self.instance_eval &@proc
end
end
def label(x)
callcc { |cont| @labels[x] = cont }
yield unless @first_run
end
def goto(x)
@labels[x].call()
end
def exit
@exit.call()
end
end
factorial = GoToProc.new do
label(1) { @x, @f = 10, 1 }
label(2) { goto 5 if @x == 1 }
label(3) { @f *= @x; @x -= 1 }
label(4) { goto 2 }
label(5) { puts "factorial = #{@f}" }
label(6) { exit }
end
factorial.run
cmVxdWlyZSAnY29udGludWF0aW9uJwoKY2xhc3MgR29Ub1Byb2MKICBkZWYgaW5pdGlhbGl6ZSgmYikKICAgIEBwcm9jLCBAbGFiZWxzLCBAZmlyc3RfcnVuID0gYiwge30sIHRydWUKICAgIHNlbGYucnVuCiAgICBAZmlyc3RfcnVuID0gZmFsc2UKICBlbmQKCiAgZGVmIHJ1bgogICAgY2FsbGNjIGRvIHxrfAogICAgICBAZXhpdCA9IGsKICAgICAgc2VsZi5pbnN0YW5jZV9ldmFsICZAcHJvYwogICAgZW5kCiAgZW5kCgogIGRlZiBsYWJlbCh4KQogICAgY2FsbGNjIHsgfGNvbnR8IEBsYWJlbHNbeF0gPSBjb250IH0KICAgIHlpZWxkIHVubGVzcyBAZmlyc3RfcnVuCiAgZW5kCgogIGRlZiBnb3RvKHgpCiAgICBAbGFiZWxzW3hdLmNhbGwoKQogIGVuZAoKICBkZWYgZXhpdAogICAgQGV4aXQuY2FsbCgpCiAgZW5kCmVuZAoKZmFjdG9yaWFsID0gR29Ub1Byb2MubmV3IGRvCiAgbGFiZWwoMSkgeyBAeCwgQGYgPSAxMCwgMSB9CiAgbGFiZWwoMikgeyBnb3RvIDUgaWYgQHggPT0gMSB9CiAgbGFiZWwoMykgeyBAZiAqPSBAeDsgQHggLT0gMSB9CiAgbGFiZWwoNCkgeyBnb3RvIDIgfQogIGxhYmVsKDUpIHsgcHV0cyAiZmFjdG9yaWFsID0gI3tAZn0iIH0KICBsYWJlbCg2KSB7IGV4aXQgfQplbmQKCmZhY3RvcmlhbC5ydW4=