Skip to content

Commit 1a6e1e2

Browse files
huonwcatamorphism
authored andcommitted
libcore: Correct behaviour of range_step for uint, tests for range* functions.
Splits the range_step function into the two directions (up, low -> high, and down, high -> low) for the uint types, since there is no way to have `step < 0` for a backwards range.
1 parent 83e3c82 commit 1a6e1e2

File tree

2 files changed

+124
-15
lines changed

2 files changed

+124
-15
lines changed

src/libcore/int-template.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,45 @@ fn test_times_negative() {
373373
use iter::Times;
374374
for (-10).times { log(error, ~"nope!"); }
375375
}
376+
377+
#[test]
378+
pub fn test_ranges() {
379+
let mut l = ~[];
380+
381+
for range(0,3) |i| {
382+
l.push(i);
383+
}
384+
for range_rev(13,10) |i| {
385+
l.push(i);
386+
}
387+
for range_step(20,26,2) |i| {
388+
l.push(i);
389+
}
390+
for range_step(36,30,-2) |i| {
391+
l.push(i);
392+
}
393+
assert l == ~[0,1,2,
394+
13,12,11,
395+
20,22,24,
396+
36,34,32];
397+
398+
// None of the `fail`s should execute.
399+
for range(10,0) |_i| {
400+
fail ~"unreachable";
401+
}
402+
for range_rev(0,10) |_i| {
403+
fail ~"unreachable";
404+
}
405+
for range_step(10,0,1) |_i| {
406+
fail ~"unreachable";
407+
}
408+
for range_step(0,10,-1) |_i| {
409+
fail ~"unreachable";
410+
}
411+
}
412+
413+
#[test]
414+
#[should_fail]
415+
fn test_range_step_zero_step() {
416+
for range_step(0,10,0) |_i| {}
417+
}

src/libcore/uint-template.rs

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,34 +69,53 @@ pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
6969
pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
7070

7171
#[inline(always)]
72-
/// Iterate over the range [`start`,`start`+`step`..`stop`)
73-
pub pure fn range_step(start: T, stop: T, step: T, it: fn(T) -> bool) {
72+
/**
73+
* Iterate over the range [`start`,`start`+`step`..`stop`)
74+
*
75+
* Note that `uint` requires separate `range_step` functions for each
76+
* direction.
77+
*
78+
*/
79+
pub pure fn range_step_up(start: T, stop: T, step: T, it: fn(T) -> bool) {
7480
let mut i = start;
7581
if step == 0 {
76-
fail ~"range_step called with step == 0";
77-
} else if step > 0 { // ascending
78-
while i < stop {
79-
if !it(i) { break }
80-
i += step;
81-
}
82-
} else { // descending
83-
while i > stop {
84-
if !it(i) { break }
85-
i += step;
86-
}
82+
fail ~"range_step_up called with step == 0";
83+
}
84+
while i < stop {
85+
if !it(i) { break }
86+
i += step;
87+
}
88+
}
89+
90+
#[inline(always)]
91+
/**
92+
* Iterate over the range [`start`,`start`-`step`..`stop`)
93+
*
94+
* Note that `uint` requires separate `range_step` functions for each
95+
* direction.
96+
*
97+
*/
98+
pub pure fn range_step_down(start: T, stop: T, step: T, it: fn(T) -> bool) {
99+
let mut i = start;
100+
if step == 0 {
101+
fail ~"range_step_down called with step == 0";
102+
}
103+
while i > stop {
104+
if !it(i) { break }
105+
i -= step;
87106
}
88107
}
89108

90109
#[inline(always)]
91110
/// Iterate over the range [`lo`..`hi`)
92111
pub pure fn range(lo: T, hi: T, it: fn(T) -> bool) {
93-
range_step(lo, hi, 1 as T, it);
112+
range_step_up(lo, hi, 1 as T, it);
94113
}
95114

96115
#[inline(always)]
97116
/// Iterate over the range [`hi`..`lo`)
98117
pub pure fn range_rev(hi: T, lo: T, it: fn(T) -> bool) {
99-
range_step(hi, lo, -1 as T, it);
118+
range_step_down(hi, lo, 1 as T, it);
100119
}
101120

102121
/// Computes the bitwise complement
@@ -351,3 +370,51 @@ pub fn test_times() {
351370
for ten.times { accum += 1; }
352371
assert (accum == 10);
353372
}
373+
use io;
374+
#[test]
375+
pub fn test_ranges() {
376+
let mut l = ~[];
377+
378+
for range(0,3) |i| {
379+
l.push(i);
380+
}
381+
for range_rev(13,10) |i| {
382+
l.push(i);
383+
}
384+
for range_step_up(20,26,2) |i| {
385+
l.push(i);
386+
}
387+
for range_step_down(36,30,2) |i| {
388+
l.push(i);
389+
}
390+
391+
assert l == ~[0,1,2,
392+
13,12,11,
393+
20,22,24,
394+
36,34,32];
395+
396+
// None of the `fail`s should execute.
397+
for range(0,0) |_i| {
398+
fail ~"unreachable";
399+
}
400+
for range_rev(0,0) |_i| {
401+
fail ~"unreachable";
402+
}
403+
for range_step_up(10,0,1) |_i| {
404+
fail ~"unreachable";
405+
}
406+
for range_step_down(0,10,1) |_i| {
407+
fail ~"unreachable";
408+
}
409+
}
410+
411+
#[test]
412+
#[should_fail]
413+
fn test_range_step_up_zero_step() {
414+
for range_step_up(0,10,0) |_i| {}
415+
}
416+
#[test]
417+
#[should_fail]
418+
fn test_range_step_down_zero_step() {
419+
for range_step_down(0,10,0) |_i| {}
420+
}

0 commit comments

Comments
 (0)