//
// Course: BU CAS CS 520
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
//

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

dataview sllst_v
  (a:t@ype, int(*n*), addr(*l*)) =
  | {l:addr} sllst_v_nil (a, 0, null)
  | {n:nat} {l:addr | l <> null} {l_nxt:addr}
      sllst_v_cons (a, n+1, l) of ((a, ptr l_nxt) @ l, sllst_v (a, n, l_nxt))

fun{a:t@ype}
  sllst_length {n:nat} {l:addr}
    (pf: !sllst_v (a, n, l) | p: ptr l): int n =
  if p <> null then let
    prval sllst_v_cons (pf_at, pf1) = pf
    val n = sllst_length (pf1 | p->1)
    prval () = pf := sllst_v_cons (pf_at, pf1)
  in
    n + 1
  end else let
    prval sllst_v_nil () = pf
    prval () = pf := sllst_v_nil ()
  in
    0
  end // end of [if]
// end of [sllst_length]

fun{a:t@ype} sllst_append_main
  {n1,n2:nat} {l1,l2:addr | l1 <> null} (
    pf1: sllst_v (a, n1, l1)
  , pf2: sllst_v (a, n2, l2)
  | p1: ptr l1, p2: ptr l2
  ) : (sllst_v (a, n1+n2, l1) | void) = let
  prval sllst_v_cons (pf_at, pf1) = pf1
  val p1_nxt = p1->1
in
  if p1_nxt <> null then let
    val (pf | ()) = sllst_append_main (pf1, pf2 | p1_nxt, p2)
  in
    (sllst_v_cons (pf_at, pf) | ())
  end else let
    val () = p1->1 := p2
    prval sllst_v_nil () = pf1
  in
    (sllst_v_cons (pf_at, pf2) | ())
  end // end of [if]
end // end of [sllst_append_main]

fun{a:t@ype} sllst_append
  {n1,n2:nat} {l1,l2:addr} (
    pf1: sllst_v (a, n1, l1)
  , pf2: sllst_v (a, n2, l2)
  | p1: ptr l1, p2: ptr l2
  ) : [l:addr] (sllst_v (a, n1+n2, l) | ptr l) =
  if p1 <> null then let
    val (pf | ()) = sllst_append_main (pf1, pf2 | p1, p2)
  in
    (pf | p1)
  end else let
    prval sllst_v_nil () = pf1
  in
    (pf2 | p2)
  end // end of [if]
// end of [sllst_append]

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

(* end of [sllst.dats] *)