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

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

extern praxi ptr_view_conversion
  {a1,a2:viewt@ype | sizeof a1 == sizeof a2} {l:addr}
  (pf: !a1? @ l >> a2? @ l): void

fn{a1,a2:viewt@ype | sizeof a1 == sizeof a2} swap {l1,l2:addr}
  (pf1: !a1 @ l1 >> a2 @ l1, pf2: !a2 @ l2 >> a1 @ l2 | p1: ptr l1, p2: ptr l2)
  : void = let
  val tmp = !p1
  prval () = ptr_view_conversion {a1,a2} (pf1)
  val () = !p1 := !p2
  prval () = ptr_view_conversion {a2,a1} (pf2)
  val () = !p2 := tmp
in
  // empty
end // end of [swap]

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

implement main () = let
  typedef T = int
  var x1: T = 1 and x2: T = 2
  val () = printf ("x1 = %i and x2 = %i\n", @(x1, x2))
  val () = swap<T,T> (view@ x1, view@ x2 | &x1, &x2)
  val () = printf ("x1 = %i and x2 = %i\n", @(x1, x2))
  typedef T = double
  var x1: T = 1.0 and x2: T = 2.0
  val () = printf ("x1 = %f and x2 = %f\n", @(x1, x2))
  val () = swap<T,T> (view@ x1, view@ x2 | &x1, &x2)  
  val () = printf ("x1 = %f and x2 = %f\n", @(x1, x2))
in
  // empty
end // end of [main]

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

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