//
// An introductory example to linear types in ATS
//

(*

int: (int) -> t@ype
ptr: (addr) -> type

a @ l: view (linear prop)
@: (t@ype, addr) -> view

*)

(*

extern fun{a:t@ype}
  ptr_get {l:addr} (pf: a @ l | p: ptr l): (a @ l | a)

extern fun{a:t@ype}
  ptr_set {l:addr} (pf: a? @ l | p: ptr l, x: a): (a @ l | void)
  
fun iswap {i1,i2:int} {l1,l2:addr}
  (pf1: int i1 @ l1, pf2: int i2 @ l2 | p1: ptr l1, p2: ptr l2)
  : (int i2 @ l1, int i1 @ l2 | void) = let
  typedef T1 = int i1 and T2 = int i2
  val (pf1 | tmp1) = ptr_get<T1> (pf1 | p1)
  val (pf2 | tmp2) = ptr_get<T2> (pf2 | p2)
  val (pf1 | ()) = ptr_set<T2> (pf1 | p1, tmp2)
  val (pf2 | ()) = ptr_set<T1> (pf2 | p2, tmp1)
in
  (pf1, pf2 | ())
end // end of [iswap]

*)

(*

extern fun{a:t@ype}
  ptr_get {l:addr} (pf: !a @ l >> a @ l | p: ptr l): a

extern fun{a:t@ype}
  ptr_set {l:addr} (pf: !a? @ l >> a @ l | p: ptr l, x: a): void
  
fun iswap {i1,i2:int} {l1,l2:addr}
  (pf1: int i1 @ l1, pf2: int i2 @ l2 | p1: ptr l1, p2: ptr l2)
  : (int i2 @ l1, int i1 @ l2 | void) = let
  typedef T1 = int i1 and T2 = int i2
  val tmp1 = ptr_get<T1> (pf1 | p1)
  val () = ptr_set<T2> (pf1 | p1, ptr_get<T2> (pf2 | p2))
  val () = ptr_set<T1> (pf2 | p2, tmp1)
in
  (pf1, pf2 | ())
end // end of [iswap]

*)

extern fun{a:t@ype}
  ptr_get {l:addr} (pf: !a @ l >> a @ l | p: ptr l): a

extern fun{a:t@ype}
  ptr_set {l:addr} (pf: !a? @ l >> a @ l | p: ptr l, x: a): void
  
fun iswap {i1,i2:int} {l1,l2:addr}
  (pf1: !int i1 @ l1 >> int i2 @ l1, pf2: !int i2 @ l2 >> int i1 @ l2 | p1: ptr l1, p2: ptr l2)
  : void = let
  typedef T1 = int i1 and T2 = int i2
  val tmp1 = ptr_get<T1> (pf1 | p1)
  val () = ptr_set<T2> (pf1 | p1, ptr_get<T2> (pf2 | p2))
  val () = ptr_set<T1> (pf2 | p2, tmp1)
in
  ()
end // end of [iswap]

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

(* end of [linear101-2008-11-04.dats] *)