```  #line 192 "/home/travis/build/felix-lang/felix/src/packages/core_type_constructors.fdoc"

publish "slice type"
union slice[T] =
| Slice_all
| Slice_from of T
| Slice_to of T
| Slice_range of T * T
| Slice_range_excl of T * T
| Slice_one of T
;

// Note: guarrantees no overflow
// handles all cases for all integers correctly
// produces nothing if first > last
gen slice_range[T with Integer[T]] (first:T) (last:T) () = {
var i = first;
while i < last do
yield Some i;
i = i + #one[T];
done
if i == last do yield Some i; done
return None[T];
}

gen slice_range_excl[T with Integer[T]] (first:T) (limit:T) () = {
var i = first;
while i < limit do
yield Some i;
i = i + #one[T];
done
return None[T];
}

// Note: guarrantees no overflow if first + count - 1
// is in range of the type
// Terminates after count values emitted
// provided overflow doesn't throw.
// Well defined on unsigned types (just wraps around)
gen slice_count[T with Integer[T]] (first:T) (count:T) () = {
var k = count;
while k > #zero[T] do
yield Some (first + (count - k));
k = k - #one[T];
done
return None[T];
}

// hack so for in f do .. done will work too
gen iterator[t] (f:1->opt[t]) => f;

// slice index calculator

// Given length n, begin b and end e indicies
// normalise so either 0 <= b <= e <= n or m = 0
//
// if m = 0 ignore b,e and use empty slice
// otherwise return a slice starting at b inclusive
// and ending at e exclusive, length m > 0

// Normalised form allows negative indices.
// However out of range indices are trimmed back:
// the calculation is NOT modular.

fun cal_slice (n:int, var b:int, var e:int) = {
if b<0 do b = b + n; done
if b<0 do b = 0; done
if b>=n do b = n; done
// assert 0 <= b <= n (valid index or one past end)
if e<0 do  e = e + n; done
if e<0 do  e = 0; done
if e>=n do e = n; done
// assert 0 <= e <= n (valid index or one pas end)
var m = e - b;
if m<0 do m = 0; done
// assert 0 <= m <= n (if m > 0 then b < e else m = 0)
return b,e,m;
// assert m = 0 or  0 <= b <= e <= n and 0 < m < n
}

```