@@ -191,6 +191,17 @@ iterator is empty."
191
191
" An iterator which begins at zero and counts up through and including LIMIT."
192
192
(up-to (+ 1 limit)))
193
193
194
+
195
+ ; ; All the haranguing below is so that we don't overflow a bounded
196
+ ; ; type in a range-decreasing call. We generally assume a lower
197
+ ; ; bound (e.g., 0 for unsigned types) is more common than an upper
198
+ ; ; bound.
199
+ (repr :enum )
200
+ (define-type RangeStatus
201
+ RangeContinue
202
+ RangeLast
203
+ RangeDone)
204
+
194
205
(declare range-decreasing ((Num :num ) (Ord :num ) =>
195
206
:num ->
196
207
:num ->
@@ -201,16 +212,36 @@ iterator is empty."
201
212
202
213
Equivalent to reversing `range-increasing`"
203
214
(assert (<= end start)
204
- " END ~a should be less than or equal to START ~a in RANGE-INCREASING "
215
+ " END ~a should be less than or equal to START ~a in RANGE-DECREASING "
205
216
end start)
206
217
(assert (> step 0 )
207
- " STEP ~a should be positive and non-zero in RANGE-INCREASING "
218
+ " STEP ~a should be positive and non-zero in RANGE-DECREASING "
208
219
step )
209
- ; ; FIXME: avoid underflow in the DONE? test
210
- (recursive-iter ((flip - ) step )
211
- (fn (n) (>= end (+ n step ))) ; like (>= (- end step)), but without potential underflow
212
- (- start step ) ; begin after START
213
- ))
220
+ (let ((end+step (+ end step )))
221
+ (if (< start end+step)
222
+ empty
223
+ (let ((start-step (- start step ))
224
+ (next (cell :new start-step))
225
+ (status (cell :new (if (< start-step end+step)
226
+ RangeLast
227
+ RangeContinue))))
228
+ (%Iterator
229
+ (fn ()
230
+ (match (cell :read status)
231
+ ((RangeDone)
232
+ None)
233
+ ((RangeLast)
234
+ (cell :write! status RangeDone)
235
+ (Some (cell :read next)))
236
+ ((RangeContinue)
237
+ (let ((this (cell :read next))
238
+ (next-next (- this step )))
239
+ (cell :write! status (if (< next-next end+step)
240
+ RangeLast
241
+ RangeContinue))
242
+ (cell :write! next next-next)
243
+ (Some this)))))
244
+ None)))))
214
245
215
246
(declare down-from ((Num :num ) (Ord :num ) => :num -> Iterator :num ))
216
247
(define (down-from limit)
0 commit comments