module M

  use int.Int

  type intref = { mutable contents : int }

  let function (!) x = x.contents

  let (:=) x v ensures { !x = v } = x.contents <- v

  val a : intref

  let p1 (b : intref)
    requires { 0 <= !a <= 10 /\ 3 <= !b <= 17 }
    ensures  { 17 <= !a <= 42 }
  = a := !a + !b;
    assert { 5 <= !a <= 15 };
    if !a >= 10 then a := !a - 1

  val c : intref

  let p2 ()
    requires { 0 <= !a <= 10 }
    ensures  { 7 <= !a <= 42 }
  = c := 1;
    while !c <= 10 do
      invariant { 2 <= !c <= 11 }
      invariant { 3 <= !a <= 10 }
      variant { !c }
      a := !a + !c;
      c := !c + 2
    done

  let p3 ()
    requires { 0 <= !a <= 10 }
    requires { 3 <= !c <= 5 }
    ensures  { 7 <= !a <= 42 }
  =
    while !c <= 10 do
      invariant { 2 <= !c <= 11 }
      invariant { 3 <= !a <= 10 }
      variant { !c }
      a := !a + !c;
      c := !c + 2
    done

end
