//
// An introduction to dataviews
//

(* ****** ****** *)

dataview array_v (a:t@ype, int, addr) =
  | {l:addr} array_v_nil (a, 0, l)
  | {n:nat} {l:addr} array_v_cons (a, n+1, l) of (a @ l, array_v (a, n, l+sizeof a))

(* ****** ****** *)

prfun array_v_split {a:t@ype} {n,i:nat | i <= n} {l:addr} {ofs:int} .<i>.
  (pf_mul: MUL (i, sizeof a, ofs), pf_arr: array_v (a, n, l))
  : @(array_v (a, i, l), array_v (a, n-i, l+ofs)) =
  sif i > 0 then let
    prval array_v_cons (pf1_elt, pf2_arr) = pf_arr
    // pf1_mul : MUL (i-1, sizeof a, ofs - sizeof a)
    prval pf1_mul = mul_add_const {~1} {i, sizeof a} (pf_mul)
    prval @(pf1_arr_res, pf2_arr_res) = array_v_split {a} {n-1,i-1} (pf1_mul, pf2_arr)
  in
    @(array_v_cons (pf1_elt, pf1_arr_res), pf2_arr_res)
  end else let
    prval MULbas () = pf_mul
  in
    (array_v_nil {a} {l} (), pf_arr)
  end // end of [sif]
// end of [array_v_split]

(* ****** ****** *)

prfun array_v_unsplit {a:t@ype} {n1,n2:nat} {l:addr} {ofs:int} .<n1>.
  (pf_mul: MUL (n1, sizeof a, ofs), pf1_arr: array_v (a, n1, l), pf2_arr: array_v (a, n2, l+ofs))
  : array_v (a, n1+n2, l) =
  sif n1 > 0 then let
    prval array_v_cons (pf11_elt, pf12_arr) = pf1_arr
    // pf1_mul : MUL (n1-1, sizeof a, ofs - sizeof a)
    prval pf1_mul = mul_add_const {~1} {n1, sizeof a} (pf_mul)
    prval pf_arr_res = array_v_unsplit {a} (pf1_mul, pf12_arr, pf2_arr)
  in
    array_v_cons (pf11_elt, pf_arr_res)
  end else let
    prval array_v_nil () = pf1_arr; prval MULbas () = pf_mul
  in
    pf2_arr
  end // end of [sif]
// end of [array_v_unsplit]

(* ****** ****** *)

dataview slseg1_v (a:t@ype, int, addr(*beg*), addr(*end*)) =
  | {l:addr} slseg1_v_nil (a, 0, l, l)
  | {n:nat} {l_beg,l_end:addr} {l_nxt:addr}
    slseg1_v_cons (a, n+1, l_beg, l_end) of ((a, ptr l_nxt) @ l_beg, slseg1_v (a, n, l_nxt, l_end))

(* ****** ****** *)

prfun slseg1_v_append
  {a:t@ype} {n12,n23:nat} {l1,l2,l3:addr} .<n12>.
  (pf12: slseg1_v (a, n12, l1, l2), pf23: slseg1_v (a, n23, l2, l3))
  : slseg1_v (a, n12+n23, l1, l3) =
  case+ pf12 of
  | slseg1_v_cons (pf121, pf122) => slseg1_v_cons (pf121, slseg1_v_append (pf122, pf23))
  | slseg1_v_nil () => pf23
// end of [slseg1_v_append]

fun{a:t@ype} slseg1_split
  {n,i:nat | i <= n} {l_beg,l_end:addr} .<n>.
  (pf: slseg1_v (a, n, l_beg, l_end) | p: ptr l_beg, i: int i)
  :<> [l_mid:addr] (
    slseg1_v (a, i, l_beg, l_mid), slseg1_v (a, n-i, l_mid, l_end) | ptr l_mid
  ) = begin
  if i > 0 then let
    prval slseg1_v_cons (pf1_at, pf2) = pf; val p_nxt = p->1
    val (pf1_res, pf2_res | p_mid) = slseg1_split (pf2 | p_nxt, i-1)
  in
    (slseg1_v_cons (pf1_at, pf1_res), pf2_res | p_mid)
  end else begin
    (slseg1_v_nil (), pf | p)
  end // end of [if]
end // end of [slseg1_split]
  
(* ****** ****** *)

(* end of [linear102-2008-11-13.dats] *)