+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2004-2008 Jean Privat <jean@pryen.org>
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Module for range of discrete objects.
-module range
-
-import abstract_collection
-
-# Range of discrete objects.
-class Range[E: Discrete]
- super Collection[E]
-
- redef var first: E
-
- # Get the last element.
- var last: E
-
- # Get the element after the last one.
- var after: E
-
- # assert [1..10].has(5)
- # assert [1..10].has(10)
- # assert not [1..10[.has(10)
- redef fun has(item) do return item >= first and item <= last
-
- # assert [1..1].has_only(1)
- # assert not [1..10].has_only(1)
- redef fun has_only(item) do return first == item and item == last or is_empty
-
- # assert [1..10].count(1) == 1
- # assert [1..10].count(0) == 0
- redef fun count(item)
- do
- if has(item) then
- return 1
- else
- return 0
- end
- end
-
- redef fun iterator do return new IteratorRange[E](self)
-
- # Gets an iterator starting at the end and going backwards
- #
- # var reviter = [1..4].reverse_iterator
- # assert reviter.to_a == [4,3,2,1]
- #
- # reviter = [1..4[.reverse_iterator
- # assert reviter.to_a == [3,2,1]
- fun reverse_iterator: Iterator[E] do return new ReverseIteratorRange[E](self)
-
- # assert [1..10].length == 10
- # assert [1..10[.length == 9
- # assert [1..1].length == 1
- # assert [1..-10].length == 0
- redef fun length
- do
- if is_empty then return 0
- var nb = first.distance(after)
- if nb > 0 then
- return nb
- else
- return 0
- end
- end
-
- # assert not [1..10[.is_empty
- # assert not [1..1].is_empty
- # assert [1..-10].is_empty
- redef fun is_empty do return first >= after
-
- # Create a range [`from`, `to`].
- # The syntax `[from..to]` is equivalent.
- #
- # var a = [10..15]
- # var b = new Range[Int] (10,15)
- # assert a == b
- # assert a.to_a == [10, 11, 12, 13, 14, 15]
- init(from: E, to: E) is old_style_init do
- first = from
- last = to
- after = to.successor(1)
- end
-
- # Create a range [`from`, `to`[.
- # The syntax `[from..to[` is equivalent.
- #
- # var a = [10..15[
- # var b = new Range[Int].without_last(10,15)
- # assert a == b
- # assert a.to_a == [10, 11, 12, 13, 14]
- init without_last(from: E, to: E)
- do
- first = from
- if from <= to then
- last = to.predecessor(1)
- after = to
- else
- last = to.successor(1)
- after = to
- end
- end
-
- # Two ranges are equals if they have the same first and last elements.
- #
- # var a = new Range[Int](10, 15)
- # var b = new Range[Int].without_last(10, 15)
- # assert a == [10..15]
- # assert a == [10..16[
- # assert not a == [10..15[
- # assert b == [10..15[
- # assert b == [10..14]
- # assert not b == [10..15]
- redef fun ==(o) do
- return o isa Range[E] and self.first == o.first and self.last == o.last
- end
-
- # var a = new Range[Int](10, 15)
- # assert a.hash == 455
- # var b = new Range[Int].without_last(10, 15)
- # assert b.hash == 432
- redef fun hash do
- # 11 and 23 are magic numbers empirically determined to be not so bad.
- return first.hash * 11 + last.hash * 23
- end
-
- # Gets an iterator that progress with a given step.
- #
- # The main usage is in `for` construction.
- #
- # ~~~
- # for i in [10..25].step(10) do assert i == 10 or i == 20
- # ~~~
- #
- # But `step` is usable as any kind of iterator.
- #
- # ~~~
- # assert [10..27].step(5).to_a == [10,15,20,25]
- # ~~~
- #
- # If `step == 1`, then it is equivalent to the default `iterator`.
- #
- # ~~~
- # assert [1..5].step(1).to_a == [1..5].to_a
- # ~~~
- #
- # If `step` is negative, then the iterator will iterate on ranges whose `first` > `last`.
- #
- # ~~~
- # assert [25..12].step(-5).to_a == [25,20,15]
- # ~~~
- #
- # On such ranges, the default `iterator` will be empty
- #
- # ~~~
- # assert [5..1].step(1).to_a.is_empty
- # assert [5..1].iterator.to_a.is_empty
- # assert [5..1].to_a.is_empty
- # assert [5..1].is_empty
- # ~~~
- #
- # Note that on non-empty range, iterating with a negative step will be empty
- #
- # ~~~
- # assert [1..5].step(-1).to_a.is_empty
- # ~~~
- fun step(step: Int): Iterator[E]
- do
- var i
- if step >= 0 then
- i = iterator
- else
- i = new DowntoIteratorRange[E](self)
- step = -step
- end
-
- if step == 1 then return i
- return i.to_step(step)
- end
-end
-
-# Iterator on ranges.
-private class IteratorRange[E: Discrete]
- super Iterator[E]
- var range: Range[E]
- redef var item is noinit
-
- redef fun is_ok do return _item < _range.after
-
- redef fun next do _item = _item.successor(1)
-
- init
- do
- _item = _range.first
- end
-end
-
-# Reverse iterator on ranges.
-private class ReverseIteratorRange[E: Discrete]
- super Iterator[E]
- var range: Range[E]
- redef var item is noinit
-
- redef fun is_ok do return _item >= _range.first
-
- redef fun next do _item = _item.predecessor(1)
-
- init
- do
- _item = _range.last
- end
-end
-
-# Iterator on ranges.
-private class DowntoIteratorRange[E: Discrete]
- super IndexedIterator[E]
- var range: Range[E]
- redef var item is noinit
- redef fun index do return _item.distance(_range.first)
-
- redef fun is_ok do return _item >= _range.last
-
- redef fun next do _item = _item.predecessor(1)
-
- init
- do
- _item = _range.first
- end
-end
-
-redef class Int
- # Returns the range from 0 to `self-1`, is used to do:
- #
- # var s = new Array[String]
- # for i in 3.times do s.add "cool"
- # assert s.join(" ") == "cool cool cool"
- #
- # s.clear
- # for i in 10.times do s.add(i.to_s)
- # assert s.to_s == "0123456789"
- fun times: Range[Int] do return [0 .. self[
-end