porting programs to mutable types

parent 0532d853
...@@ -58,10 +58,10 @@ drivers () { ...@@ -58,10 +58,10 @@ drivers () {
programs () { programs () {
for f in $1/*.mlw; do for f in $1/*.mlw; do
echo -n " "$f"... " echo -n " "$f"... "
if ! $pgml $pgml_options $f > /dev/null 2>&1; then if ! $pgml -L modules $pgml_options $f > /dev/null 2>&1; then
echo echo
echo "$pgml $pgml_options $f" echo "$pgml $pgml_options $f"
$pgml $pgml_options $f $pgml -L modules $pgml_options $f
echo "FAILED!" echo "FAILED!"
exit 1 exit 1
else else
...@@ -73,7 +73,7 @@ programs () { ...@@ -73,7 +73,7 @@ programs () {
bad_programs () { bad_programs () {
for f in $1/*.mlw; do for f in $1/*.mlw; do
echo -n " "$f"... " echo -n " "$f"... "
if $pgml $pgml_options $f > /dev/null 2>&1; then if $pgml -L modules $pgml_options $f > /dev/null 2>&1; then
echo echo
echo "$pgml $pgml_options $f" echo "$pgml $pgml_options $f"
echo "SHOULD FAIL!" echo "SHOULD FAIL!"
...@@ -87,10 +87,10 @@ bad_programs () { ...@@ -87,10 +87,10 @@ bad_programs () {
valid_goals () { valid_goals () {
for f in $1/*.mlw; do for f in $1/*.mlw; do
echo -n " "$f"... " echo -n " "$f"... "
if $pgml -P alt-ergo $f | grep -q -v Valid; then if $pgml -L modules -P alt-ergo $f | grep -q -v Valid; then
echo "valid test $f failed!" echo "valid test $f failed!"
echo "$pgml -P alt-ergo $f" echo "$pgml -P alt-ergo $f"
$pgml -P alt-ergo $f $pgml -L modules -P alt-ergo $f
exit 1 exit 1
else else
echo "ok" echo "ok"
...@@ -102,7 +102,7 @@ valid_goals () { ...@@ -102,7 +102,7 @@ valid_goals () {
test_provers () { test_provers () {
for f in $1/*.mlw; do for f in $1/*.mlw; do
echo -n " "$f"... " echo -n " "$f"... "
if $pgml -P alt-ergo $f | grep -q -v Valid; then if $pgml -L modules -P alt-ergo $f | grep -q -v Valid; then
echo "valid test $f failed!" echo "valid test $f failed!"
exit 1 exit 1
else else
...@@ -123,10 +123,6 @@ echo "=== Checking drivers ===" ...@@ -123,10 +123,6 @@ echo "=== Checking drivers ==="
drivers drivers drivers drivers
echo "" echo ""
echo "=== Checking valid goals ==="
valid_goals bench/valid
echo ""
echo "=== Parsing good files ===" echo "=== Parsing good files ==="
goods bench/typing/bad --parse-only goods bench/typing/bad --parse-only
echo "" echo ""
...@@ -169,6 +165,10 @@ programs bench/programs/good ...@@ -169,6 +165,10 @@ programs bench/programs/good
programs examples/programs programs examples/programs
echo "" echo ""
echo "=== Checking valid goals ==="
valid_goals bench/valid
echo ""
echo "=== Checking provers ===" echo "=== Checking provers ==="
echo -n "Test provers on true..." echo -n "Test provers on true..."
provers=$($pgm --list-provers | cut -d " " -f 3 |grep -v "^$") provers=$($pgm --list-provers | cut -d " " -f 3 |grep -v "^$")
......
...@@ -8,7 +8,7 @@ let p1 () = {} (raise E : unit) { false } | E -> { true } ...@@ -8,7 +8,7 @@ let p1 () = {} (raise E : unit) { false } | E -> { true }
(* exception with an argument *) (* exception with an argument *)
exception F of int exception F int
let p2 () = {} raise (F 1) : unit { false } | F -> { result = 1 } let p2 () = {} raise (F 1) : unit { false } | F -> { result = 1 }
...@@ -43,20 +43,22 @@ let p6 () = ...@@ -43,20 +43,22 @@ let p6 () =
(* composition of exceptions with side-effect on a reference *) (* composition of exceptions with side-effect on a reference *)
use import module stdlib.Ref
parameter x : ref int parameter x : ref int
let p7 () = let p7 () =
{} begin x := 1; raise E; x := 2 end { false } | E -> { !x = 1 } {} begin x := 1; raise E; x := 2 end { false } | E -> { x = 1 }
let p8 () = let p8 () =
{} {}
begin x := 1; raise (F !x); x := 2 end begin x := 1; raise (F !x); x := 2 end
{ false } | F -> { !x = 1 and result = 1 } { false } | F -> { x = 1 and result = 1 }
let p9 () = let p9 () =
{} {}
(raise (F begin x := 1; !x end) : unit) (raise (F begin x := 1; !x end) : unit)
{ false } | F -> { !x = 1 and result = 1 } { false } | F -> { x = 1 and result = 1 }
(* try / with *) (* try / with *)
...@@ -80,7 +82,7 @@ let p13 () = ...@@ -80,7 +82,7 @@ let p13 () =
with E -> x := 2 with E -> x := 2
| F _ -> x := 3 | F _ -> x := 3
end end
{ !x = 2 } { x = 2 }
let p13a () = let p13a () =
{} {}
...@@ -90,7 +92,7 @@ let p13a () = ...@@ -90,7 +92,7 @@ let p13a () =
with E -> with E ->
x := 0 x := 0
end end
{ !x <> 1 } { x <> 1 }
exception E1 exception E1
exception E2 exception E2
...@@ -104,17 +106,17 @@ let p14 () = ...@@ -104,17 +106,17 @@ let p14 () =
if !x = 3 then raise E3; if !x = 3 then raise E3;
raise E : unit raise E : unit
end end
{ false } | E1 -> { !x = 1 } | E2 -> { !x = 2 } | E3 -> { !x = 3 } { false } | E1 -> { x = 1 } | E2 -> { x = 2 } | E3 -> { x = 3 }
| E -> { !x <> 1 and !x <> 2 and !x <> 3 } | E -> { x <> 1 and x <> 2 and x <> 3 }
let p15 () = let p15 () =
{} {}
if !x = 0 then raise E else (x := 0; raise (F !x)) : unit if !x = 0 then raise E else (x := 0; raise (F !x)) : unit
{ false } | E -> { !x=0 } | F -> { result=0 } { false } | E -> { x=0 } | F -> { result=0 }
let p16 () = {} if !x = 0 then (x:=1; raise E) { !x<>0 } | E -> { !x=1 } let p16 () = {} if !x = 0 then (x:=1; raise E) { x<>0 } | E -> { x=1 }
let p17 () = {} (x := 0; (raise E; x := 1)) { false } | E -> { !x=0 } let p17 () = {} (x := 0; (raise E; x := 1)) { false } | E -> { x=0 }
end end
......
module M module M
use import int.Int
use import module stdlib.Ref
(* for loop with invariant *) (* for loop with invariant *)
let test1 () = let test1 () =
let x = ref 0 in let x = ref 0 in
for i = 1 to 10 do for i = 1 to 10 do
invariant { !x = i-1 } invariant { x = i-1 }
x := !x + 1 x := !x + 1
done; done;
assert { !x = 10 } assert { x = 10 }
(* we don't even enter *) (* we don't even enter *)
let test2 () = let test2 () =
...@@ -15,7 +18,7 @@ let test2 () = ...@@ -15,7 +18,7 @@ let test2 () =
for i = 2 to 1 do for i = 2 to 1 do
x := 1 x := 1
done; done;
assert { !x = 0 } assert { x = 0 }
exception E exception E
...@@ -47,17 +50,17 @@ let test4 x = ...@@ -47,17 +50,17 @@ let test4 x =
let test1d () = let test1d () =
let x = ref 11 in let x = ref 11 in
for i = 10 downto 1 do for i = 10 downto 1 do
invariant { !x = i+1 } invariant { x = i+1 }
x := !x - 1 x := !x - 1
done; done;
assert { !x = 1 } assert { x = 1 }
let test2d () = let test2d () =
let x = ref 0 in let x = ref 0 in
for i = 1 downto 2 do for i = 1 downto 2 do
x := 1 x := 1
done; done;
assert { !x = 0 } assert { x = 0 }
let test3d () = let test3d () =
{ } { }
......
module M module M
use import int.Int
use import list.List use import list.List
use import list.Length use import list.Length
......
module M module M
use import int.Int
use import module stdlib.Ref
(** 1. A loop increasing [i] up to 10. *) (** 1. A loop increasing [i] up to 10. *)
parameter i : ref int parameter i : ref int
let loop1 (u:unit) = let loop1 (u:unit) =
{ !i <= 10 } { i <= 10 }
while !i < 10 do while !i < 10 do
invariant { !i <= 10 } variant { 10 - !i } invariant { i <= 10 } variant { 10 - i }
i := !i + 1 i := !i + 1
done done
{ !i = 10 } { i = 10 }
(** 2. The same loop, followed by a function call. *) (** 2. The same loop, followed by a function call. *)
parameter x: ref int parameter x: ref int
let negate (u:unit) = {} x := - !x { !x = -old(!x) } let negate (u:unit) = {} x := - !x { x = - (old x) }
let loop2 (u:unit) = let loop2 (u:unit) =
{ !x <= 10 } { x <= 10 }
begin begin
while !x < 10 do invariant { !x <= 10 } variant { 10 - !x } while !x < 10 do invariant { x <= 10 } variant { 10 - x }
x := !x + 1 x := !x + 1
done; done;
assert { !x = 10 }; assert { x = 10 };
if !x > 0 then (negate ()); if !x > 0 then (negate ());
assert { !x = -10 } assert { x = -10 }
end end
{} {}
......
module M module M
use import int.Int
use import int.EuclideanDivision use import int.EuclideanDivision
logic even (x : int) = x = 2 * (div x 2) logic even (x : int) = x = 2 * (div x 2)
......
module M module M
use import module stdlib.Ref
logic q1 int int int logic q1 int int int
parameter r : ref int parameter r : ref int
parameter f1 : y:int -> parameter f1 : y:int ->
{} unit writes r { q1 (!r) (old (!r)) y } {} unit writes r { q1 r (old r) y }
let g1 () = {} f1 !r { q1 (!r) (old (!r)) (old (!r)) } let g1 () = {} f1 !r { q1 r (old r) (old r) }
logic foo int : int logic foo int : int
logic q int int int logic q int int int
parameter f : t:ref int -> x:int -> parameter f : t:ref int -> x:int ->
{} unit reads t writes t { q (!t) (old (!t)) x } {} unit reads t writes t { q t (old t) x }
let g (t:ref int) = let g (t:ref int) =
{} {}
f t (foo !t) f t (foo !t)
{ q (!t) (old (!t)) (foo (old (!t))) } { q t (old t) (foo (old t)) }
end end
......
module M module M
use import int.Int
use import module stdlib.Ref
(* Tests for proof obligations. *) (* Tests for proof obligations. *)
parameter x : ref int parameter x : ref int
...@@ -8,13 +11,13 @@ parameter x : ref int ...@@ -8,13 +11,13 @@ parameter x : ref int
(* basic stuff: assignment, sequence and local variables *) (* basic stuff: assignment, sequence and local variables *)
let p1 () = { q(!x+1) } begin x := !x + 1 end { q(!x) } let p1 () = { q (x+1) } begin x := !x + 1 end { q x }
let p2 () = { q(7) } begin x := 3 + 4 end { q(!x) } let p2 () = { q 7 } begin x := 3 + 4 end { q x }
let p3 () = {} begin x := !x + 1; x := !x + 2 end { !x = old(!x) + 3 } let p3 () = {} begin x := !x + 1; x := !x + 2 end { x = (old x) + 3 }
let p4 () = {} begin x := 7; x := 2 * !x end { !x = 14 } let p4 () = {} begin x := 7; x := 2 * !x end { x = 14 }
let p5 () = {} 3 + 4 { result = 7 } let p5 () = {} 3 + 4 { result = 7 }
...@@ -25,14 +28,14 @@ let p7 () = {} 3 + (let a = 4 in a + a) { result = 11 } ...@@ -25,14 +28,14 @@ let p7 () = {} 3 + (let a = 4 in a + a) { result = 11 }
(* side effects in function arguments *) (* side effects in function arguments *)
let p8 () = let p8 () =
{ q(!x+1) } 3 + begin x := !x + 1; !x end { q(!x) and result = old(!x) + 4 } { q (x+1) } 3 + begin x := !x + 1; !x end { q x and result = (old x) + 4 }
(* evaluation order (argument first) *) (* evaluation order (argument first) *)
let p9 () = let p9 () =
{} begin x := 1; 1 end + begin x := 2; 1 end { result = 2 and !x = 2 } {} begin x := 1; 1 end + begin x := 2; 1 end { result = 2 and x = 2 }
let p9a () = {} begin x := 1; 1 end + 1 { result = 2 and !x = 1 } let p9a () = {} begin x := 1; 1 end + 1 { result = 2 and x = 1 }
(* function with a post-condition *) (* function with a post-condition *)
...@@ -46,19 +49,19 @@ let p11a () = {} let a = (fsucc 1) in a + a { result = 4 } ...@@ -46,19 +49,19 @@ let p11a () = {} let a = (fsucc 1) in a + a { result = 4 }
(* function with a post-condition and side-effects *) (* function with a post-condition and side-effects *)
parameter incrx : unit -> { } unit writes x { !x = old(!x) + 1 } parameter incrx : unit -> { } unit writes x { x = (old x) + 1 }
let p12 () = { !x = 0 } incrx () { !x = 1 } let p12 () = { x = 0 } incrx () { x = 1 }
let p13 () = {} begin incrx (); incrx () end { !x = old(!x) + 2 } let p13 () = {} begin incrx (); incrx () end { x = (old x) + 2 }
let p13a () = {} incrx (incrx ()) { !x = old(!x) + 2 } let p13a () = {} incrx (incrx ()) { x = (old x) + 2 }
(* function with side-effects, result and post-condition *) (* function with side-effects, result and post-condition *)
parameter incrx2 : unit -> { } int writes x { !x = old(!x) + 1 and result = !x } parameter incrx2 : unit -> { } int writes x { x = old x + 1 and result = x }
let p14 () = { !x = 0 } incrx2 () { result = 1 } let p14 () = { x = 0 } incrx2 () { result = 1 }
end end
......
module M module M
use import int.Int
use import module stdlib.Ref
(** Recursive functions *) (** Recursive functions *)
(** 1. Pure function *) (** 1. Pure function *)
...@@ -11,33 +14,35 @@ let rec f1 (x:int) : int variant { x } = ...@@ -11,33 +14,35 @@ let rec f1 (x:int) : int variant { x } =
parameter x : ref int parameter x : ref int
let rec f2 (u:unit) : unit variant { !x } = let rec f2 (u:unit) : unit variant { x } =
{ !x >= 0 } (if !x > 0 then begin x := !x - 1; f2 () end) { !x = 0 } { x >= 0 } (if !x > 0 then begin x := !x - 1; f2 () end) { x = 0 }
(** 3. With effects and a pure argument *) (** 3. With effects and a pure argument *)
let rec f3 (a:int) : unit variant { a } = let rec f3 (a:int) : unit variant { a } =
{ a >= 0 } { a >= 0 }
if a > 0 then begin x := !x + 1; (f3 (a-1)) end if a > 0 then begin x := !x + 1; (f3 (a-1)) end
{ !x = old !x + a } { x = old x + a }
(** 4. With effects and a reference as argument *) (** 4. With effects and a reference as argument *)
let rec f4 (a:ref int) : unit variant { !a } = let rec f4 (a:ref int) : unit variant { a } =
{ !a >= 0 } { a >= 0 }
if !a > 0 then begin x := !x + 1; a := !a - 1; f4 a end if !a > 0 then begin x := !x + 1; a := !a - 1; f4 a end
{ !x = old !x + old !a } { x = old x + old a }
(** 5. The acid test: (** 5. The acid test:
partial application of a recursive function with effects *) partial application of a recursive function with effects *)
let rec f5 (a b:ref int) variant { !a } = (* FIXME
{ !a >= 0 } let rec f5 (a b:ref int) variant { a } =
{ a >= 0 }
if !a = 0 then !b else begin a := !a - 1; b := !b + 1; f5 a b end if !a = 0 then !b else begin a := !a - 1; b := !b + 1; f5 a b end
{ result = old !a + old !b } { result = old a + old b }
let test_f5 () = let test_f5 () =
{ !x >= 0 } let f = f5 x in let b = ref 0 in f b { result = old !x } { x >= 0 } let f = f5 x in let b = ref 0 in f b { result = old !x }
*)
end end
......
...@@ -10,7 +10,7 @@ parameter b1 : ref int ...@@ -10,7 +10,7 @@ parameter b1 : ref int
parameter b2 : ref int parameter b2 : ref int
let f () = let f () =
{} b := 1 - !b; !b { result = !b and !b = 1 - old(!b) } {} b := 1 - !b; !b { result = b and b = 1 - old b }
let k () = let k () =
{} {}
...@@ -19,7 +19,7 @@ let k () = ...@@ -19,7 +19,7 @@ let k () =
b1 := (1 - (f ())) + (f ()); b1 := (1 - (f ())) + (f ());
b2 := (f ()) * (1 - (f ())) b2 := (f ()) * (1 - (f ()))
end end
{ !b1 = 0 and !b2 = 1 } { b1 = 0 and b2 = 1 }
end end
......
module M module M
use import int.Int
use import module stdlib.Ref
(* side effects in tests *) (* side effects in tests *)
parameter x : ref int parameter x : ref int
parameter set_and_test_zero : parameter set_and_test_zero :
v:int -> v:int ->
{} bool writes x { !x = v and if result=True then !x = 0 else !x <> 0 } {} bool writes x { x = v and if result=True then x = 0 else x <> 0 }
let p () = {} if set_and_test_zero 0 then 1 else 2 { result = 1 } let p () = {} if set_and_test_zero 0 then 1 else 2 { result = 1 }
parameter set_and_test_nzero : parameter set_and_test_nzero :
v:int -> v:int ->
{} bool writes x { !x = v and if result=True then !x <> 0 else !x = 0 } {} bool writes x { x = v and if result=True then x <> 0 else x = 0 }
let p2 (y:ref int) = let p2 (y:ref int) =
{ !y >= 0 } { y >= 0 }
while set_and_test_nzero !y do while set_and_test_nzero !y do
invariant { !y >= 0 } variant { !y } invariant { y >= 0 } variant { y }
y := !y - 1 y := !y - 1
done done
{ !y = 0 } { y = 0 }
let p3 (y:ref int) = let p3 (y:ref int) =
{ !y >= 0 } { y >= 0 }
while let b = set_and_test_nzero !y in b do while let b = set_and_test_nzero !y in b do
invariant { !y >= 0 } variant { !y } invariant { y >= 0 } variant { y }
y := !y - 1 y := !y - 1
done done
{ !y = 0 } { y = 0 }
let p4 (y:ref int) = let p4 (y:ref int) =
{ !y >= 1 } { y >= 1 }
while begin y := !y - 1; (set_and_test_nzero !y) end do while begin y := !y - 1; (set_and_test_nzero !y) end do
invariant { !y >= 1 } variant { !y } invariant { y >= 1 } variant { y }
() ()
done done
{ !y = 0 } { y = 0 }
end end
......
module M module M
use import int.Int
use import module stdlib.Ref
parameter x : ref int parameter x : ref int
parameter f : unit -> { } unit writes x { !x = 1 - old (!x) } parameter f : unit -> { } unit writes x { x = 1 - old x }
let p () = let p () =
begin begin
...@@ -10,7 +13,7 @@ let p () = ...@@ -10,7 +13,7 @@ let p () =
let t = () in (); let t = () in ();
(f ()); (f ());
(f ()); (f ());
assert { !x = at (!x) Init };