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:
parent
fdbb82967f
commit
7b2b831959
@ -230,47 +230,54 @@ class TestRubyOptimization < Test::Unit::TestCase
|
|||||||
assert_equal true, MyObj.new == nil
|
assert_equal true, MyObj.new == nil
|
||||||
end
|
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
|
def test_tailcall
|
||||||
bug4082 = '[ruby-core:33289]'
|
bug4082 = '[ruby-core:33289]'
|
||||||
|
|
||||||
option = {
|
tailcall(<<-EOF)
|
||||||
tailcall_optimization: true,
|
def fact_helper(n, res)
|
||||||
trace_instruction: false,
|
if n == 1
|
||||||
}
|
res
|
||||||
RubyVM::InstructionSequence.new(<<-EOF, "Bug#4082", bug4082, nil, option).eval
|
else
|
||||||
class #{self.class}::Tailcall
|
fact_helper(n - 1, n * res)
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
def fact(n)
|
||||||
|
fact_helper(n, 1)
|
||||||
|
end
|
||||||
EOF
|
EOF
|
||||||
assert_equal(9131, Tailcall.new.fact(3000).to_s.size, bug4082)
|
assert_equal(9131, fact(3000).to_s.size, bug4082)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_tailcall_with_block
|
def test_tailcall_with_block
|
||||||
bug6901 = '[ruby-dev:46065]'
|
bug6901 = '[ruby-dev:46065]'
|
||||||
|
|
||||||
option = {
|
tailcall(<<-EOF)
|
||||||
tailcall_optimization: true,
|
def identity(val)
|
||||||
trace_instruction: false,
|
val
|
||||||
}
|
end
|
||||||
RubyVM::InstructionSequence.new(<<-EOF, "Bug#6901", bug6901, nil, option).eval
|
|
||||||
def identity(val)
|
|
||||||
val
|
|
||||||
end
|
|
||||||
|
|
||||||
def delay
|
def delay
|
||||||
-> {
|
-> {
|
||||||
identity(yield)
|
identity(yield)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
EOF
|
EOF
|
||||||
assert_equal(123, delay { 123 }.call, bug6901)
|
assert_equal(123, delay { 123 }.call, bug6901)
|
||||||
end
|
end
|
||||||
@ -280,15 +287,12 @@ class TestRubyOptimization < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_tailcall_inhibited_by_block
|
def test_tailcall_inhibited_by_block
|
||||||
assert_separately([], <<~'end;')
|
tailcall(<<-EOF)
|
||||||
def just_yield
|
def yield_result
|
||||||
yield
|
just_yield {:ok}
|
||||||
end
|
end
|
||||||
iseq = RubyVM::InstructionSequence
|
EOF
|
||||||
result = iseq.compile("just_yield {:ok}", __FILE__, __FILE__, __LINE__,
|
assert_equal(:ok, yield_result)
|
||||||
tailcall_optimization: true).eval
|
|
||||||
assert_equal(:ok, result)
|
|
||||||
end;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Bug10557
|
class Bug10557
|
||||||
|
Loading…
x
Reference in New Issue
Block a user