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

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

(*
abstype T // ...

// @ : (t@ype, addr) -> view

fun read {l:addr}
  (pf: T @ l | p: ptr l): (T @ l | T)

abstype T1 // ...
abstype T2 // ...

fun write {l:addr}
  (pf: T1 @ l | p: ptr l, x: T2): (T2 @ l | void)
*)

(*
// implemented in [prelude/DATS/pointer.dats]
fun{a:t@ype} ptr_get_t {l:addr} (pf: !a @ l | p: ptr l):<> a

// implemented in [prelude/DATS/pointer.dats]
fun{a:t@ype} ptr_set_t {l:addr}
  (pf: !(a?) @ l >> a @ l | p: ptr l, x: a):<> void
// end of ...
*)

fn swap {a1,a2:type} {l1,l2:addr}
  (pf1: !a1 @ l1 >> a2 @ l1, pf2: !a2 @ l2 >> a1 @ l2 | p1: ptr l1, p2: ptr l2)
  : void = let
  extern prfun
    __cast12 (pf: !a1? @ l1 >> a2? @ l1): void
  extern prfun
    __cast21 (pf: !a2? @ l2 >> a1? @ l2): void
  val x1 = ptr_get_t<a1> (pf1 | p1)
  val x2 = ptr_get_t<a2> (pf2 | p2)
  val () = __cast12 (pf1) // pf1: a2? @ l1
  val () = ptr_set_t<a2> (pf1 | p1, x2)
  val () = __cast21 (pf2) // pf2: a1? @ l2
  val () = ptr_set_t<a1> (pf2 | p2, x1)
in
  // nothing
end // end of [swap]
  
(* ****** ****** *)