1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

test_optimization.rb: tailcall

* test/ruby/test_optimization.rb (TestRubyOptimization.tailcall):
  helper method to compile methods with tailcall optimization
  enabled.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2016-03-17 04:31:10 +00:00
parent fdbb82967f
commit 7b2b831959

View file

@ -230,47 +230,54 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal true, MyObj.new == nil
end
def self.tailcall(klass, src, file = nil, path = nil, line = nil)
unless file
loc, = caller_locations(1, 1)
file = loc.path
line ||= loc.lineno
end
RubyVM::InstructionSequence.new("proc {|_|_.class_eval {#{src}}}",
file, (path || file), line,
tailcall_optimization: true,
trace_instruction: false)
.eval[klass]
end
def tailcall(*args)
self.class.tailcall(singleton_class, *args)
end
def test_tailcall
bug4082 = '[ruby-core:33289]'
option = {
tailcall_optimization: true,
trace_instruction: false,
}
RubyVM::InstructionSequence.new(<<-EOF, "Bug#4082", bug4082, nil, option).eval
class #{self.class}::Tailcall
def fact_helper(n, res)
if n == 1
res
else
fact_helper(n - 1, n * res)
end
end
def fact(n)
fact_helper(n, 1)
tailcall(<<-EOF)
def fact_helper(n, res)
if n == 1
res
else
fact_helper(n - 1, n * res)
end
end
def fact(n)
fact_helper(n, 1)
end
EOF
assert_equal(9131, Tailcall.new.fact(3000).to_s.size, bug4082)
assert_equal(9131, fact(3000).to_s.size, bug4082)
end
def test_tailcall_with_block
bug6901 = '[ruby-dev:46065]'
option = {
tailcall_optimization: true,
trace_instruction: false,
}
RubyVM::InstructionSequence.new(<<-EOF, "Bug#6901", bug6901, nil, option).eval
def identity(val)
val
end
tailcall(<<-EOF)
def identity(val)
val
end
def delay
-> {
identity(yield)
}
end
def delay
-> {
identity(yield)
}
end
EOF
assert_equal(123, delay { 123 }.call, bug6901)
end
@ -280,15 +287,12 @@ class TestRubyOptimization < Test::Unit::TestCase
end
def test_tailcall_inhibited_by_block
assert_separately([], <<~'end;')
def just_yield
yield
tailcall(<<-EOF)
def yield_result
just_yield {:ok}
end
iseq = RubyVM::InstructionSequence
result = iseq.compile("just_yield {:ok}", __FILE__, __FILE__, __LINE__,
tailcall_optimization: true).eval
assert_equal(:ok, result)
end;
EOF
assert_equal(:ok, yield_result)
end
class Bug10557