#

RubyVM::InstructionSequence.compile_option = {
  :tailcall_optimization => true  ,
  :trace_instruction     => false ,
}
eval <<SRC
def fact( n , a = 1  )
 if n == 0
   a
 else
   fact(n-1 , n * a)
 end
end
p fact(9999)

SRC




class Module
  def tco(name)
    continue = []
    first = true
    arguments = nil

    private_name = "private_" + name.to_s
    alias_method private_name, name
    private private_name

    proc = lambda do |*args|
      if first
        first = false
        while true
          result = send(private_name, *args)
          if result.equal? continue
            args = arguments
          else
            first = true
            return result
          end
        end
      else
        arguments = args
        continue
      end
    end
    define_method name, proc
  end
end



class Sum
  def sum1(n, acc=0)
    if n == 0
      acc
    else
      sum1(n-1, acc+n)
    end
  end

  def sum2(n, acc=0)
    if n == 0
      acc
    else
      sum2(n-1, acc+n)
    end
  end
  tco :sum2 
end

p Sum.new.sum2(100000)


# stakki ovver flow
#p Sum.new.sum1(100000)



