//
// Course: BU CAS CS 520, Fall 2010
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Lecture on Tuesday, Nov 4, 2010
//

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

staload "prelude/DATS/pointer.dats"

dataview
charr_v (int(*n*), addr(*l*)) =
  | {l:addr} charr_v_nil (0, l)
  | {n:nat} {l:addr}
     charr_v_cons (n+1, l) of (char @ l, charr_v (n, l+1))
// end of [charr_v]

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

prfun
charr_v_split
  {n,i:nat | i <= n} {l:addr} .<n>.
  (pf: charr_v (n, l)): (charr_v (i, l), charr_v (n-i,l+i)) =
  sif i == 0 then
    (charr_v_nil (), pf)
  else let
    prval charr_v_cons (pf1, pf2) = pf
    prval (pf21, pf22) = charr_v_split {n-1,i-1} (pf2)
  in
    (charr_v_cons (pf1, pf21), pf22)
  end // end of [sif]
// end of [charr_v_split]

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

prfun
charr_v_unsplit
  {n1,n2:nat} {l:addr} .<n1>. (
  pf1: charr_v (n1, l), pf2: charr_v (n2, l+n1)
) : charr_v (n1+n2, l) =
  sif n1 == 0 then let
    prval charr_v_nil () = pf1 in pf2
  end else let
    prval charr_v_cons (pf11, pf12) = pf1
  in
    charr_v_cons (pf11, charr_v_unsplit (pf12, pf2))
  end // end of [sif]

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

extern
prfun
charr_v_takeout1
  {n,i:nat | i < n} {l:addr}
  (pf: charr_v (n, l))
  : (char @ (l+i), char @ (l+i) -<lin> charr_v (n, l))

prfun
charr_v_takeout
  {n,i:nat | i < n} {l:addr} .<i>.
  (pf: charr_v (n, l))
  : (char @ (l+i), char @ (l+i) -<lin> charr_v (n, l)) =
  sif i == 0 then let
    prval charr_v_cons (pf1, pf2) = pf
  in
    (pf1, llam pf1 => charr_v_cons (pf1, pf2))
  end else let
    prval charr_v_cons (pf1, pf2) = pf
    prval (pfat, fpf) = charr_v_takeout {n-1,i-1} (pf2)    
  in
    (pfat, llam pfat => charr_v_cons (pf1, fpf (pfat)))
  end // end of [sif]

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

(*
fun charr_get
  {n,i:nat | i < n} {l:addr} .<n>. (
  pf: !charr_v (n, l) | p: ptr l, i: int i
) : char = let
  prval (pf1, pf2) = charr_v_split {n,i} (pf)
  prval charr_v_cons (pf21, pf22) = pf2
  val c = !(p+i)
  prval () = pf := charr_v_unsplit (pf1, charr_v_cons (pf21, pf22))
in
  c
end // end of [charr_get]
*)

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

fun charr_get
  {n,i:nat | i < n} {l:addr} .<n>. (
  pf: !charr_v (n, l) | p: ptr l, i: int i
) : char = let
  prval (pfat, fpf) = charr_v_takeout {n,i} (pf)
  val c = !(p+i)
  prval () = pf := fpf (pfat)
in
  c
end // end of [charr_get]

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

(* end of [charr.dats] *)