Rewrite Integer#times in Ruby (#8388)
This commit is contained in:
parent
4efcaf956e
commit
5b5ae3d9e0
Notes:
git
2023-09-07 17:58:12 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
@ -19,5 +19,5 @@ matrix 0.4.2 https://github.com/ruby/matrix
|
|||||||
prime 0.1.2 https://github.com/ruby/prime
|
prime 0.1.2 https://github.com/ruby/prime
|
||||||
rbs 3.2.1 https://github.com/ruby/rbs
|
rbs 3.2.1 https://github.com/ruby/rbs
|
||||||
typeprof 0.21.8 https://github.com/ruby/typeprof
|
typeprof 0.21.8 https://github.com/ruby/typeprof
|
||||||
debug 1.8.0 https://github.com/ruby/debug
|
debug 1.8.0 https://github.com/ruby/debug 927587afb6aac69b358b86a01f602d207053e8d2
|
||||||
racc 1.7.1 https://github.com/ruby/racc
|
racc 1.7.1 https://github.com/ruby/racc
|
||||||
|
53
numeric.c
53
numeric.c
@ -5652,58 +5652,6 @@ int_downto(VALUE from, VALUE to)
|
|||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
|
||||||
int_dotimes_size(VALUE num, VALUE args, VALUE eobj)
|
|
||||||
{
|
|
||||||
if (FIXNUM_P(num)) {
|
|
||||||
if (NUM2LONG(num) <= 0) return INT2FIX(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) return INT2FIX(0);
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* times {|i| ... } -> self
|
|
||||||
* times -> enumerator
|
|
||||||
*
|
|
||||||
* Calls the given block +self+ times with each integer in <tt>(0..self-1)</tt>:
|
|
||||||
*
|
|
||||||
* a = []
|
|
||||||
* 5.times {|i| a.push(i) } # => 5
|
|
||||||
* a # => [0, 1, 2, 3, 4]
|
|
||||||
*
|
|
||||||
* With no block given, returns an Enumerator.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
int_dotimes(VALUE num)
|
|
||||||
{
|
|
||||||
RETURN_SIZED_ENUMERATOR(num, 0, 0, int_dotimes_size);
|
|
||||||
|
|
||||||
if (FIXNUM_P(num)) {
|
|
||||||
long i, end;
|
|
||||||
|
|
||||||
end = FIX2LONG(num);
|
|
||||||
for (i=0; i<end; i++) {
|
|
||||||
rb_yield_1(LONG2FIX(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VALUE i = INT2FIX(0);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (!RTEST(int_le(i, num))) break;
|
|
||||||
rb_yield(i);
|
|
||||||
i = rb_int_plus(i, INT2FIX(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* round(ndigits= 0, half: :up) -> integer
|
* round(ndigits= 0, half: :up) -> integer
|
||||||
@ -6243,7 +6191,6 @@ Init_Numeric(void)
|
|||||||
rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1);
|
rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1);
|
||||||
rb_define_method(rb_cInteger, "upto", int_upto, 1);
|
rb_define_method(rb_cInteger, "upto", int_upto, 1);
|
||||||
rb_define_method(rb_cInteger, "downto", int_downto, 1);
|
rb_define_method(rb_cInteger, "downto", int_downto, 1);
|
||||||
rb_define_method(rb_cInteger, "times", int_dotimes, 0);
|
|
||||||
rb_define_method(rb_cInteger, "succ", int_succ, 0);
|
rb_define_method(rb_cInteger, "succ", int_succ, 0);
|
||||||
rb_define_method(rb_cInteger, "next", int_succ, 0);
|
rb_define_method(rb_cInteger, "next", int_succ, 0);
|
||||||
rb_define_method(rb_cInteger, "pred", int_pred, 0);
|
rb_define_method(rb_cInteger, "pred", int_pred, 0);
|
||||||
|
23
numeric.rb
23
numeric.rb
@ -217,6 +217,29 @@ class Integer
|
|||||||
Primitive.cexpr! 'rb_int_size(self)'
|
Primitive.cexpr! 'rb_int_size(self)'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# call-seq:
|
||||||
|
# times {|i| ... } -> self
|
||||||
|
# times -> enumerator
|
||||||
|
#
|
||||||
|
# Calls the given block +self+ times with each integer in <tt>(0..self-1)</tt>:
|
||||||
|
#
|
||||||
|
# a = []
|
||||||
|
# 5.times {|i| a.push(i) } # => 5
|
||||||
|
# a # => [0, 1, 2, 3, 4]
|
||||||
|
#
|
||||||
|
# With no block given, returns an Enumerator.
|
||||||
|
def times
|
||||||
|
unless block_given?
|
||||||
|
return to_enum(:times) { self < 0 ? 0 : self }
|
||||||
|
end
|
||||||
|
i = 0
|
||||||
|
while i < self
|
||||||
|
yield i
|
||||||
|
i = i.succ
|
||||||
|
end
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# to_i -> self
|
# to_i -> self
|
||||||
#
|
#
|
||||||
|
@ -215,15 +215,15 @@ class TestBacktrace < Test::Unit::TestCase
|
|||||||
@res = caller_locations(2, 1).inspect
|
@res = caller_locations(2, 1).inspect
|
||||||
end
|
end
|
||||||
@line = __LINE__ + 1
|
@line = __LINE__ + 1
|
||||||
1.times.map { 1.times.map { foo } }
|
[1].map.map { [1].map.map { foo } }
|
||||||
assert_equal("[\"#{__FILE__}:#{@line}:in `times'\"]", @res)
|
assert_equal("[\"#{__FILE__}:#{@line}:in `map'\"]", @res)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_caller_location_path_cfunc_iseq_no_pc
|
def test_caller_location_path_cfunc_iseq_no_pc
|
||||||
def self.foo
|
def self.foo
|
||||||
@res = caller_locations(2, 1)[0].path
|
@res = caller_locations(2, 1)[0].path
|
||||||
end
|
end
|
||||||
1.times.map { 1.times.map { foo } }
|
[1].map.map { [1].map.map { foo } }
|
||||||
assert_equal(__FILE__, @res)
|
assert_equal(__FILE__, @res)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -321,23 +321,34 @@ class TestInteger < Test::Unit::TestCase
|
|||||||
begin;
|
begin;
|
||||||
called = false
|
called = false
|
||||||
Integer.class_eval do
|
Integer.class_eval do
|
||||||
alias old_plus +
|
alias old_succ succ
|
||||||
undef +
|
undef succ
|
||||||
define_method(:+){|x| called = true; 1}
|
define_method(:succ){|x| called = true; x+1}
|
||||||
alias old_lt <
|
alias old_lt <
|
||||||
undef <
|
undef <
|
||||||
define_method(:<){|x| called = true}
|
define_method(:<){|x| called = true}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
fix = 1
|
||||||
|
fix.times{break 0}
|
||||||
|
fix_called = called
|
||||||
|
|
||||||
|
called = false
|
||||||
|
|
||||||
big = 2**65
|
big = 2**65
|
||||||
big.times{break 0}
|
big.times{break 0}
|
||||||
|
big_called = called
|
||||||
|
|
||||||
Integer.class_eval do
|
Integer.class_eval do
|
||||||
undef +
|
undef succ
|
||||||
alias + old_plus
|
alias succ old_succ
|
||||||
undef <
|
undef <
|
||||||
alias < old_lt
|
alias < old_lt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Asssert that Fixnum and Bignum behave consistently
|
||||||
bug18377 = "[ruby-core:106361]"
|
bug18377 = "[ruby-core:106361]"
|
||||||
assert_equal(false, called, bug18377)
|
assert_equal(fix_called, big_called, bug18377)
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -504,7 +504,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
|
|||||||
1: trace = TracePoint.trace(*trace_events){|tp| next if !target_thread?
|
1: trace = TracePoint.trace(*trace_events){|tp| next if !target_thread?
|
||||||
2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding&.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy'
|
2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding&.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy'
|
||||||
3: }
|
3: }
|
||||||
4: 1.times{|;_local_var| _local_var = :inner
|
4: [1].each{|;_local_var| _local_var = :inner
|
||||||
5: tap{}
|
5: tap{}
|
||||||
6: }
|
6: }
|
||||||
7: class XYZZY
|
7: class XYZZY
|
||||||
@ -531,10 +531,10 @@ class TestSetTraceFunc < Test::Unit::TestCase
|
|||||||
answer_events = [
|
answer_events = [
|
||||||
#
|
#
|
||||||
[:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
|
[:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
|
||||||
[:c_call, 4, 'xyzzy', Integer, :times, 1, nil, :nothing],
|
[:c_call, 4, 'xyzzy', Array, :each, [1], nil, :nothing],
|
||||||
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
|
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
|
||||||
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
|
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
|
||||||
[:c_return, 4, "xyzzy", Integer, :times, 1, nil, 1],
|
[:c_return, 4, "xyzzy", Array, :each, [1], nil, [1]],
|
||||||
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
|
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
|
||||||
[:c_call, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, :nothing],
|
[:c_call, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, :nothing],
|
||||||
[:c_return, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, nil],
|
[:c_return, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, nil],
|
||||||
@ -639,7 +639,7 @@ CODE
|
|||||||
1: set_trace_func(lambda{|event, file, line, id, binding, klass|
|
1: set_trace_func(lambda{|event, file, line, id, binding, klass|
|
||||||
2: events << [event, line, file, klass, id, binding&.eval('self'), binding&.eval("_local_var")] if file == 'xyzzy'
|
2: events << [event, line, file, klass, id, binding&.eval('self'), binding&.eval("_local_var")] if file == 'xyzzy'
|
||||||
3: })
|
3: })
|
||||||
4: 1.times{|;_local_var| _local_var = :inner
|
4: [1].map{|;_local_var| _local_var = :inner
|
||||||
5: tap{}
|
5: tap{}
|
||||||
6: }
|
6: }
|
||||||
7: class XYZZY
|
7: class XYZZY
|
||||||
@ -994,7 +994,7 @@ CODE
|
|||||||
/return/ =~ tp.event ? tp.return_value : nil
|
/return/ =~ tp.event ? tp.return_value : nil
|
||||||
]
|
]
|
||||||
}.enable{
|
}.enable{
|
||||||
1.times{
|
[1].map{
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
method_for_test_tracepoint_block{
|
method_for_test_tracepoint_block{
|
||||||
@ -1004,10 +1004,10 @@ CODE
|
|||||||
# pp events
|
# pp events
|
||||||
# expected_events =
|
# expected_events =
|
||||||
[[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
[[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
||||||
[:c_call, :times, Integer, Integer, nil],
|
[:c_call, :map, Array, Array, nil],
|
||||||
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
||||||
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 3],
|
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 3],
|
||||||
[:c_return, :times, Integer, Integer, 1],
|
[:c_return, :map, Array, Array, [3]],
|
||||||
[:call, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
[:call, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
||||||
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
|
||||||
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4],
|
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4],
|
||||||
@ -1310,7 +1310,7 @@ CODE
|
|||||||
next if !target_thread?
|
next if !target_thread?
|
||||||
events << tp.event
|
events << tp.event
|
||||||
}.enable{
|
}.enable{
|
||||||
1.times{
|
[1].map{
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
method_for_test_tracepoint_block{
|
method_for_test_tracepoint_block{
|
||||||
@ -1332,7 +1332,7 @@ CODE
|
|||||||
next if !target_thread?
|
next if !target_thread?
|
||||||
events << tp.event
|
events << tp.event
|
||||||
}.enable{
|
}.enable{
|
||||||
1.times{
|
[1].map{
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
method_for_test_tracepoint_block{
|
method_for_test_tracepoint_block{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user