Skip to content

Commit

Permalink
Restructure to better match CRuby code
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Feb 13, 2025
1 parent 0490236 commit 5de9016
Showing 1 changed file with 35 additions and 38 deletions.
73 changes: 35 additions & 38 deletions core/src/main/java/org/jruby/RubyRange.java
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,9 @@ private IRubyObject stepCommon(ThreadContext context, IRubyObject stepArg, Block
throw argumentError(context, "#step iteration for beginless ranges is meaningless");
}

IRubyObject v = begin;
int c, dir;

if (begin instanceof RubyFixnum && end.isNil() && step instanceof RubyFixnum) {
fixnumEndlessStep(context, step, block);
} else if (begin instanceof RubyFixnum && end instanceof RubyFixnum && step instanceof RubyFixnum stepf) {
Expand All @@ -830,47 +833,41 @@ private IRubyObject stepCommon(ThreadContext context, IRubyObject stepArg, Block
} else if (!symBegin.isNil() && step instanceof RubyFixnum) {
// same as above: backward compatibility for symbols
symbolStep(context, step, block, (RubyString) symBegin);
} else {
int c, dir;
IRubyObject v = begin;
if (!end.isNil()) {
if (beginIsNumeric && stepIsNumeric && rangeLess(context, step, asFixnum(context, 0)) < 0) {
// iterate backwards, for consistency with ArithmeticSequence
if (isExclusive) {
for (; rangeLess(context, end, v) < 0; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
}
} else {
for (; (c = rangeLess(context, end, v)) <= 0; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
if (c == 0) break;
}
}

} else {
// Direction of the comparison. We use it as a comparison operator in cycle:
// if begin < end, the cycle performs while value < end (iterating forward)
// if begin > end, the cycle performs while value > end (iterating backward with
// a negative step)
dir = rangeLess(context, begin, end);
// One preliminary addition to check the step moves iteration in the same direction as
// from begin to end; otherwise, the iteration should be empty.
if (rangeLess(context, begin, begin.callMethod(context, "+", step)) == dir) {
if (isExclusive) {
for (; rangeLess(context, v, end) == dir; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
}
} else {
for (; (c = rangeLess(context, v, end)) == dir || c == 0; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
if (c == 0) break;
}
}
}
} else if (end.isNil()) {
for (; ; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
}
} else if (beginIsNumeric && stepIsNumeric && rangeLess(context, step, asFixnum(context, 0)) < 0) {
// iterate backwards, for consistency with ArithmeticSequence
if (isExclusive) {
for (; rangeLess(context, end, v) < 0; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
}
} else {
for (; (c = rangeLess(context, end, v)) <= 0; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
if (c == 0) break;
}
}
} else if ((dir = rangeLess(context, begin, end)) == 0) {
if (!isExclusive) {
block.yield(context, v);
}
} else if (rangeLess(context, begin, begin.callMethod(context, "+", step)) == dir) {
// Direction of the comparison. We use it as a comparison operator in cycle:
// if begin < end, the cycle performs while value < end (iterating forward)
// if begin > end, the cycle performs while value > end (iterating backward with
// a negative step)
// One preliminary addition to check the step moves iteration in the same direction as
// from begin to end; otherwise, the iteration should be empty.
if (isExclusive) {
for (; rangeLess(context, v, end) == dir; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
}
} else {
for (; ; v = v.callMethod(context, "+", step)) {
for (; (c = rangeLess(context, v, end)) == dir || c == 0; v = v.callMethod(context, "+", step)) {
block.yield(context, v);
if (c == 0) break;
}
}
}
Expand Down

0 comments on commit 5de9016

Please sign in to comment.