#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
  }