range_each: do not goto into a branch

I'm not necessarily against every goto in general, but jumping into a
branch is definitely a bad idea.  Better refactor.
This commit is contained in:
卜部昌平 2020-06-16 14:31:11 +09:00
parent cc27cd26d7
commit 9c5804ac1c
Notes: git 2020-06-29 11:06:52 +09:00

56
range.c
View File

@ -829,6 +829,36 @@ range_enum_size(VALUE range, VALUE args, VALUE eobj)
return range_size(range); return range_size(range);
} }
RBIMPL_ATTR_NORETURN()
static void
range_each_bignum_endless(VALUE beg)
{
for (;; beg = rb_big_plus(beg, INT2FIX(1))) {
rb_yield(beg);
}
}
RBIMPL_ATTR_NORETURN()
static void
range_each_fixnum_endless(VALUE beg)
{
for (long i = FIX2LONG(beg); FIXABLE(i); i++) {
rb_yield(LONG2FIX(i));
}
range_each_bignum_endless(LONG2NUM(RUBY_FIXNUM_MAX + 1));
}
static VALUE
range_each_fixnum_loop(VALUE beg, VALUE end, VALUE range)
{
long lim = FIX2LONG(end) + !EXCL(range);
for (long i = FIX2LONG(beg); i < lim; i++) {
rb_yield(LONG2FIX(i));
}
return range;
}
/* /*
* call-seq: * call-seq:
* rng.each {| i | block } -> rng * rng.each {| i | block } -> rng
@ -854,7 +884,7 @@ static VALUE
range_each(VALUE range) range_each(VALUE range)
{ {
VALUE beg, end; VALUE beg, end;
long i, lim; long i;
RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size); RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
@ -862,24 +892,10 @@ range_each(VALUE range)
end = RANGE_END(range); end = RANGE_END(range);
if (FIXNUM_P(beg) && NIL_P(end)) { if (FIXNUM_P(beg) && NIL_P(end)) {
fixnum_endless: range_each_fixnum_endless(beg);
i = FIX2LONG(beg);
while (FIXABLE(i)) {
rb_yield(LONG2FIX(i++));
}
beg = LONG2NUM(i);
bignum_endless:
for (;; beg = rb_big_plus(beg, INT2FIX(1)))
rb_yield(beg);
} }
else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */ else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
fixnum_loop: return range_each_fixnum_loop(beg, end, range);
lim = FIX2LONG(end);
if (!EXCL(range))
lim += 1;
for (i = FIX2LONG(beg); i < lim; i++) {
rb_yield(LONG2FIX(i));
}
} }
else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) { else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) {
if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */ if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
@ -888,11 +904,11 @@ range_each(VALUE range)
do { do {
rb_yield(beg); rb_yield(beg);
} while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1)))); } while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
if (NIL_P(end)) goto fixnum_endless; if (NIL_P(end)) range_each_fixnum_endless(beg);
if (FIXNUM_P(end)) goto fixnum_loop; if (FIXNUM_P(end)) return range_each_fixnum_loop(beg, end, range);
} }
else { else {
if (NIL_P(end)) goto bignum_endless; if (NIL_P(end)) range_each_bignum_endless(beg);
if (FIXNUM_P(end)) return range; if (FIXNUM_P(end)) return range;
} }
} }