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

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

dataview
slseg_v (
  a:t@ype+, int, addr, addr
) =
  | {l:addr} slseg_v_nil (a, 0, l, l) of ()
  | {l1,l2:addr | l1 > null} {l_nxt:addr} {n:nat}
    slseg_v_cons (a, n+1, l1, l2) of 
      ((a, ptr (l_nxt)) @ l1, slseg_v (a, n, l_nxt, l2))
// end of [slseg_v]

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

viewdef sllst_v (a:t@ype, n:int, l:addr) = slseg_v (a, n, l, null)

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

extern
fun{a:t@ype}
sllst_length {n:nat} {l:addr}
  (pf: !sllst_v (a, n, l) | p: ptr l): int (n)
// end of [sllst_length]

(*
implement{a}
sllst_length (pf | p) =
  if p > null then let
    prval slseg_v_cons (pfat, pf2) = pf
    val n1 = sllst_length (pf2 | p->1)
    prval () = pf := slseg_v_cons (pfat, pf2)
  in
    n1 + 1
  end else let
    prval slseg_v_nil () = pf
    prval () = pf := slseg_v_nil ()
  in
    0
  end // end of [if]
// end of [sllst_length]  
*)

implement{a}
sllst_length (pf | p) = let
//
fun loop {i,j:nat} {l:addr} (
  pf: !sllst_v (a, i, l) | p: ptr l, j: int j
) : int(i+j) =
  if p > null then let
    prval slseg_v_cons (pfat, pf2) = pf
    val n = loop (pf2 | p->1, j+1)
    prval () = pf := slseg_v_cons (pfat, pf2)
  in
    n
  end else let
    prval slseg_v_nil () = pf
    prval () = pf := slseg_v_nil ()
  in
    j
  end // end of [if]
// end of [loop]
in
  loop (pf | p, 0)
end // end of [sllst_length]  

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

extern
fun{a:t@ype}
sllst_get {n,i:nat | i < n} {l:addr}
  (pf: !sllst_v (a, n, l) | p: ptr l, i: int i): a
// end of [sllst_length]

implement{a}
sllst_get (pf | p, i) = let
  prval slseg_v_cons (pfat, pf2) = pf
in
  if i = 0 then let
    val x = p->0
    prval () = pf := slseg_v_cons (pfat, pf2)
  in
    x
  end else let
    val x = sllst_get (pf2 | p->1, i-1)
    prval () = pf := slseg_v_cons (pfat, pf2)
  in
    x
  end // end of [if]
end // end of [sllst_get]

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

(* end of [slseg.dats] *)