
use int.Int
use ref.Ref

val incr (x:ref int) : unit writes {x} ensures { !x = old !x + 1 }

val x : ref int

val id_not_0 (x:int) : int requires { x <> 0 } ensures { result = x }

val id (x:int) : int ensures { result = x }

let test_and_1 ()
  ensures  { result = 1 }
  = if (incr x; !x > 0) && id !x = 1 then !x else 0+1

let test_and_2 ()
  requires { !x <> 0 }
  ensures  { result = 1 }
  = if id_not_0 !x >= 1 && !x <= 1 then !x else 0+1

let test_or_1 ()
  ensures  { result = 1 -> !x <> 0 }
  = if (incr x; !x > 0) || !x < 0 then 1 else 2

let test_or_2 ()
  ensures  { 0 <= result <= 1 }
  = if !x = 0 || !x = 1 then !x else 1

let test_not_1 ()
  ensures  { !x = 0 }
  = if not (!x = 0) then x := 0

let test_not_2 ()
  requires { !x <= 0 }
  ensures  { !x = 0 }
  diverges
  = while not (!x = 0) do invariant { !x <= 0 } incr x done

let test_all_1 ()
  ensures  { result=True <-> !x>=1 }
  = (!x >= 0 && not (!x = 0) || !x >= 1)

(* from Cesar Munoz's CD3D *)

val constant d : int

val vx : ref int
val vy : ref int

val sq (x:int) : int ensures { result = x*x }

let test_cd3d ()
  ensures { result=1 -> !vx=0 /\ !vy=0 }
  = if !vx=0 && !vy=0 && sq !vx + sq !vy < sq d then 1 else 2

