syntax for assignment

parent 26c19ce1
...@@ -8,30 +8,30 @@ module M ...@@ -8,30 +8,30 @@ module M
parameter a : array int parameter a : array int
logic inv (a : array int) = logic inv (a : array int) =
a[0] = 0 and length a = 11 and forall k:int. 1 <= k <= 10 -> 0 < a[k] a[0] = 0 and length a = 11 and forall k:int. 1 <= k <= 10 -> 0 < a[k]
parameter loop1 : ref int parameter loop1 : ref int
parameter loop2 : ref int parameter loop2 : ref int
let insertion_sort () = let insertion_sort () =
{ inv a and { inv a and
(* ghost *) loop1 = 0 and loop2 = 0 } (* ghost *) loop1 = 0 and loop2 = 0 }
let i = ref 2 in let i = ref 2 in
while !i <= 10 do while !i <= 10 do
invariant { 2 <= i <= 11 and inv a and invariant { 2 <= i <= 11 and inv a and
(* ghost *) loop1 = i - 2 and 2 * loop2 <= (i-2) * (i-1) } (* ghost *) loop1 = i - 2 and 2 * loop2 <= (i-2) * (i-1) }
variant { 10 - i } variant { 10 - i }
(* ghost *) incr loop1; (* ghost *) incr loop1;
let j = ref !i in let j = ref !i in
while a[!j] < a[!j - 1] do while a[!j] < a[!j - 1] do
invariant { 1 <= j <= i and inv a and invariant { 1 <= j <= i and inv a and
(* ghost *) 2 * loop2 <= (i-2) * (i-1) + 2*(i-j) } (* ghost *) 2 * loop2 <= (i-2) * (i-1) + 2*(i-j) }
variant { j } variant { j }
(* ghost *) incr loop2; (* ghost *) incr loop2;
let temp = a[!j] in let temp = a[!j] in
set a !j a[!j - 1]; a[!j] <- a[!j - 1];
set a (!j - 1) temp; a[!j - 1] <- temp;
decr j decr j
done; done;
incr i incr i
...@@ -39,7 +39,7 @@ module M ...@@ -39,7 +39,7 @@ module M
{ loop1 = 9 and loop2 <= 45 } { loop1 = 9 and loop2 <= 45 }
end end
module ARM module ARM
use export int.Int use export int.Int
...@@ -49,14 +49,14 @@ module ARM ...@@ -49,14 +49,14 @@ module ARM
(* memory *) (* memory *)
parameter mem : ref (map int int) parameter mem : ref (map int int)
parameter mem_ldr : a:int -> {} int reads mem.contents { result = mem[a] } parameter mem_ldr : a:int -> {} int reads mem.contents { result = mem[a] }
parameter mem_str : a:int -> v:int -> parameter mem_str : a:int -> v:int ->
{} int writes mem.contents { mem = (old mem)[a <- v] } {} int writes mem.contents { mem = (old mem)[a <- v] }
(* data segment *) (* data segment *)
(* (*
parameter data : ref (t int int) parameter data : ref (t int int)
parameter data_ldr : a:int -> {} int reads data { result = data[a] } parameter data_ldr : a:int -> {} int reads data { result = data[a] }
parameter data_str : parameter data_str :
a:int -> v:int -> {} int writes data { data = (old data)[a <- v] } a:int -> v:int -> {} int writes data { data = (old data)[a <- v] }
*) *)
...@@ -69,17 +69,17 @@ module ARM ...@@ -69,17 +69,17 @@ module ARM
parameter fp : ref int parameter fp : ref int
parameter pc : ref int (* pc *) parameter pc : ref int (* pc *)
parameter ldr : parameter ldr :
r:ref int -> a:int -> {} unit reads mem.contents writes r.contents { r = mem[a] } r:ref int -> a:int -> {} unit reads mem.contents writes r.contents { r = mem[a] }
parameter str : parameter str :
r:ref int -> a:int -> {} unit reads r.contents writes mem.contents { mem = (old mem)[a <- r] } r:ref int -> a:int -> {} unit reads r.contents writes mem.contents { mem = (old mem)[a <- r] }
(* condition flags *) (* condition flags *)
parameter le : ref bool parameter le : ref bool
parameter cmp : r:ref int -> v:int -> parameter cmp : r:ref int -> v:int ->
{} {}
unit reads r.contents writes le.contents unit reads r.contents writes le.contents
{ le=True <-> r <= v } { le=True <-> r <= v }
end end
...@@ -114,13 +114,13 @@ module InsertionSortExample ...@@ -114,13 +114,13 @@ module InsertionSortExample
(* stack and data segment do not overlap *) (* stack and data segment do not overlap *)
logic separation (fp : int) = a+10 < fp-24 logic separation (fp : int) = a+10 < fp-24
logic inv (mem: map int int) = logic inv (mem: map int int) =
mem[a] = 0 and forall k:int. 1 <= k <= 10 -> 0 < mem[a + k] mem[a] = 0 and forall k:int. 1 <= k <= 10 -> 0 < mem[a + k]
logic inv_l2 (mem: map int int) (fp : int) (l4 : int) = logic inv_l2 (mem: map int int) (fp : int) (l4 : int) =
2 <= mem[fp - 16] <= 11 and l4 = mem[fp-16] - 2 and inv mem 2 <= mem[fp - 16] <= 11 and l4 = mem[fp-16] - 2 and inv mem
let path_init_l2 () = let path_init_l2 () =
{ separation fp and inv mem } { separation fp and inv mem }
(* ghost *) l4 := 0; l7 := 0; (* ghost *) l4 := 0; l7 := 0;
r3 := 2; r3 := 2;
...@@ -137,7 +137,7 @@ module InsertionSortExample ...@@ -137,7 +137,7 @@ module InsertionSortExample
end end
(* (*
Local Variables: Local Variables:
compile-command: "unset LANG; make -C ../.. examples/programs/arm.gui" compile-command: "unset LANG; make -C ../.. examples/programs/arm.gui"
End: End:
*) *)
...@@ -7,16 +7,16 @@ module M ...@@ -7,16 +7,16 @@ module M
(* iteration on a set *) (* iteration on a set *)
parameter set_has_next : parameter set_has_next :
s:ref (S.set 'a) -> s:ref (S.set 'a) ->
{} {}
bool reads s bool reads s
{ if result=True then S.is_empty s else not S.is_empty s } { if result=True then S.is_empty s else not S.is_empty s }
parameter set_next : parameter set_next :
s:ref (S.set 'a) -> s:ref (S.set 'a) ->
{ not S.is_empty s } { not S.is_empty s }
'a writes s 'a writes s
{ S.mem result (old s) and s = S.remove result (old s) } { S.mem result (old s) and s = S.remove result (old s) }
(* the graph *) (* the graph *)
...@@ -27,7 +27,7 @@ logic v : S.set vertex ...@@ -27,7 +27,7 @@ logic v : S.set vertex
logic g_succ(vertex) : S.set vertex logic g_succ(vertex) : S.set vertex
axiom G_succ_sound : axiom G_succ_sound :
forall x:vertex. S.subset (g_succ x) v forall x:vertex. S.subset (g_succ x) v
logic weight vertex vertex : int (* edge weight, if there is an edge *) logic weight vertex vertex : int (* edge weight, if there is an edge *)
...@@ -35,14 +35,14 @@ logic weight vertex vertex : int (* edge weight, if there is an edge *) ...@@ -35,14 +35,14 @@ logic weight vertex vertex : int (* edge weight, if there is an edge *)
axiom Weight_nonneg : forall x y:vertex. weight x y >= 0 axiom Weight_nonneg : forall x y:vertex. weight x y >= 0
parameter eq_vertex : parameter eq_vertex :
x:vertex -> y:vertex -> {} bool { if result=True then x=y else x<>y } x:vertex -> y:vertex -> {} bool { if result=True then x=y else x<>y }
(* visited vertices *) (* visited vertices *)
parameter visited : ref (S.set vertex) parameter visited : ref (S.set vertex)
parameter visited_add : parameter visited_add :
x:vertex -> {} unit writes visited { visited = S.add x (old visited) } x:vertex -> {} unit writes visited { visited = S.add x (old visited) }
(* current distances *) (* current distances *)
...@@ -53,18 +53,18 @@ parameter d : ref (M.map vertex int) ...@@ -53,18 +53,18 @@ parameter d : ref (M.map vertex int)
parameter q : ref (S.set vertex) parameter q : ref (S.set vertex)
parameter q_is_empty : parameter q_is_empty :
unit -> unit ->
{} {}
bool reads q bool reads q
{ if result=True then S.is_empty q else not S.is_empty q } { if result=True then S.is_empty q else not S.is_empty q }
parameter init : parameter init :
src:vertex -> src:vertex ->
{} {}
unit writes visited q d unit writes visited q d
{ S.is_empty visited and { S.is_empty visited and
q = S.add src S.empty and q = S.add src S.empty and
d = M.set (old d) src 0 } d = M.set (old d) src 0 }
let relax u v = let relax u v =
...@@ -77,38 +77,38 @@ let relax u v = ...@@ -77,38 +77,38 @@ let relax u v =
q := S.add v !q; q := S.add v !q;
d := M.set !d v x d := M.set !d v x
end end
{ (S.mem v visited and q = old q and d = old d) { (S.mem v visited and q = old q and d = old d)
or
(S.mem v q and M.get d u + weight u v >= M.get d v and
q = old q and d = old d)
or or
(S.mem v q and M.get d u + weight u v >= M.get d v and (S.mem v q and M.get (old d) u + weight u v < M.get (old d) v and
q = old q and d = old d)
or
(S.mem v q and M.get (old d) u + weight u v < M.get (old d) v and
q = old q and d = M.set (old d) v (M.get (old d) u + weight u v)) q = old q and d = M.set (old d) v (M.get (old d) u + weight u v))
or or
(not S.mem v visited and not S.mem v (old q) and q = S.add v (old q) and (not S.mem v visited and not S.mem v (old q) and q = S.add v (old q) and
d = M.set (old d) v (M.get (old d) u + weight u v)) } d = M.set (old d) v (M.get (old d) u + weight u v)) }
logic min (m:vertex) (q:S.set vertex) (d:M.map vertex int) = logic min (m:vertex) (q:S.set vertex) (d:M.map vertex int) =
S.mem m q and S.mem m q and
forall x:vertex. S.mem x q -> M.get d m <= M.get d x forall x:vertex. S.mem x q -> M.get d m <= M.get d x
parameter q_extract_min : parameter q_extract_min :
unit -> unit ->
{ not S.is_empty q } { not S.is_empty q }
vertex reads d writes q vertex reads d writes q
{ min result (old q) d and q = S.remove result (old q) } { min result (old q) d and q = S.remove result (old q) }
(* paths and shortest paths (* paths and shortest paths
path x y d = path x y d =
there is a path from x to y of length d there is a path from x to y of length d
shortest_path x y d = shortest_path x y d =
there is a path from x to y of length d, and no shorter path *) there is a path from x to y of length d, and no shorter path *)
inductive path vertex vertex int = inductive path vertex vertex int =
| Path_nil : | Path_nil :
forall x:vertex. path x x 0 forall x:vertex. path x x 0
| Path_cons : | Path_cons :
forall x y z:vertex. forall d:int. forall x y z:vertex. forall d:int.
path x y d -> S.mem z (g_succ y) -> path x z (d+weight y z) path x y d -> S.mem z (g_succ y) -> path x z (d+weight y z)
lemma Length_nonneg : forall x y:vertex. forall d:int. path x y d -> d >= 0 lemma Length_nonneg : forall x y:vertex. forall d:int. path x y d -> d >= 0
...@@ -128,18 +128,18 @@ lemma Path_shortest_path : ...@@ -128,18 +128,18 @@ lemma Path_shortest_path :
(* lemmas (those requiring induction) *) (* lemmas (those requiring induction) *)
lemma Main_lemma : lemma Main_lemma :
forall src v:vertex. forall d:int. forall src v:vertex. forall d:int.
path src v d -> not shortest_path src v d -> path src v d -> not shortest_path src v d ->
exists v':vertex. exists d':int. exists v':vertex. exists d':int.
shortest_path src v' d' and S.mem v (g_succ v') and d' + weight v' v < d shortest_path src v' d' and S.mem v (g_succ v') and d' + weight v' v < d
lemma Completeness_lemma : lemma Completeness_lemma :
forall s:S.set vertex. forall src:vertex. forall dst:vertex. forall d:int. forall s:S.set vertex. forall src:vertex. forall dst:vertex. forall d:int.
(* if s is closed under g_succ *) (* if s is closed under g_succ *)
(forall v:vertex. (forall v:vertex.
S.mem v s -> forall w:vertex. S.mem w (g_succ v) -> S.mem w s) -> S.mem v s -> forall w:vertex. S.mem w (g_succ v) -> S.mem w s) ->
(* and if s contains src *) (* and if s contains src *)
S.mem src s -> S.mem src s ->
(* then any vertex reachable from s is also in s *) (* then any vertex reachable from s is also in s *)
path src dst d -> S.mem dst s path src dst d -> S.mem dst s
...@@ -153,7 +153,7 @@ logic inv (src:vertex) (s q:S.set vertex) (d:M.map vertex int) = ...@@ -153,7 +153,7 @@ logic inv (src:vertex) (s q:S.set vertex) (d:M.map vertex int) =
(* S,Q are contained in V *) (* S,Q are contained in V *)
and S.subset s v and S.subset q v and S.subset s v and S.subset q v
(* S and Q are disjoint *) (* S and Q are disjoint *)
and and
(forall v:vertex. S.mem v q -> S.mem v s -> false) (forall v:vertex. S.mem v q -> S.mem v s -> false)
(* we already found the shortest paths for vertices in S *) (* we already found the shortest paths for vertices in S *)
and and
...@@ -163,21 +163,21 @@ logic inv (src:vertex) (s q:S.set vertex) (d:M.map vertex int) = ...@@ -163,21 +163,21 @@ logic inv (src:vertex) (s q:S.set vertex) (d:M.map vertex int) =
(forall v:vertex. S.mem v q -> path src v (M.get d v)) (forall v:vertex. S.mem v q -> path src v (M.get d v))
(* vertices at distance < min(Q) are already in S *) (* vertices at distance < min(Q) are already in S *)
and and
(forall m:vertex. min m q d -> (forall m:vertex. min m q d ->
forall x:vertex. forall dx:int. shortest_path src x dx -> forall x:vertex. forall dx:int. shortest_path src x dx ->
dx < M.get d m -> S.mem x s) dx < M.get d m -> S.mem x s)
logic inv_succ (src:vertex) (s q : S.set vertex) = logic inv_succ (src:vertex) (s q : S.set vertex) =
(* successors of vertices in S are either in S or in Q *) (* successors of vertices in S are either in S or in Q *)
(forall x:vertex. S.mem x s -> (forall x:vertex. S.mem x s ->
forall y:vertex. S.mem y (g_succ x) -> S.mem y s or S.mem y q) forall y:vertex. S.mem y (g_succ x) -> S.mem y s or S.mem y q)
logic inv_succ2 (src:vertex) (s q : S.set vertex) logic inv_succ2 (src:vertex) (s q : S.set vertex)
(u:vertex) (su:S.set vertex) = (u:vertex) (su:S.set vertex) =
(* successors of vertices in S are either in S or in Q, (* successors of vertices in S are either in S or in Q,
unless they are successors of u still in su *) unless they are successors of u still in su *)
(forall x:vertex. S.mem x s -> (forall x:vertex. S.mem x s ->
forall y:vertex. S.mem y (g_succ x) -> forall y:vertex. S.mem y (g_succ x) ->
(x<>u or (x=u and not S.mem y su)) -> S.mem y s or S.mem y q) (x<>u or (x=u and not S.mem y su)) -> S.mem y s or S.mem y q)
(* code *) (* code *)
...@@ -192,8 +192,8 @@ let shortest_path_code (src:vertex) (dst:vertex) = ...@@ -192,8 +192,8 @@ let shortest_path_code (src:vertex) (dst:vertex) =
assert { shortest_path src u (M.get d u) }; assert { shortest_path src u (M.get d u) };
visited_add u; visited_add u;
let su = ref (g_succ u) in let su = ref (g_succ u) in
while not (set_has_next su) do while not (set_has_next su) do
invariant invariant
{ S.subset su (g_succ u) and { S.subset su (g_succ u) and
inv src visited q d and inv_succ2 src visited q u su } inv src visited q d and inv_succ2 src visited q u su }
variant { S.cardinal su } variant { S.cardinal su }
...@@ -201,16 +201,16 @@ let shortest_path_code (src:vertex) (dst:vertex) = ...@@ -201,16 +201,16 @@ let shortest_path_code (src:vertex) (dst:vertex) =
relax u v relax u v
done done
done done
{ (forall v:vertex. { (forall v:vertex.
S.mem v visited -> shortest_path src v (M.get d v)) S.mem v visited -> shortest_path src v (M.get d v))
and and
(forall v:vertex. (forall v:vertex.
not S.mem v visited -> forall dv:int. not path src v dv) } not S.mem v visited -> forall dv:int. not path src v dv) }
end end
(* (*
Local Variables: Local Variables:
compile-command: "unset LANG; make -C ../.. examples/programs/dijkstra" compile-command: "unset LANG; make -C ../.. examples/programs/dijkstra"
End: End:
*) *)
...@@ -83,14 +83,14 @@ module Distance ...@@ -83,14 +83,14 @@ module Distance
for i = 0 to n2 do for i = 0 to n2 do
invariant { length t = n2+1 and invariant { length t = n2+1 and
forall j:int. 0 <= j < i -> t[j] = n2-j } forall j:int. 0 <= j < i -> t[j] = n2-j }
set t i (n2 - i) t[i] <- n2 - i
done; done;
(* loop over w1 *) (* loop over w1 *)
for i = n1-1 downto 0 do for i = n1-1 downto 0 do
invariant { length t = n2+1 invariant { length t = n2+1
and forall j:int. 0 <= j <= n2 -> min_suffix w1 w2 (i+1) j t[j] } and forall j:int. 0 <= j <= n2 -> min_suffix w1 w2 (i+1) j t[j] }
o := t[n2]; o := t[n2];
set t n2 (t[n2] + 1); t[n2] <- t[n2] + 1;
(* loop over w2 *) (* loop over w2 *)
for j = n2-1 downto 0 do for j = n2-1 downto 0 do
invariant { length t = n2+1 invariant { length t = n2+1
...@@ -101,9 +101,9 @@ module Distance ...@@ -101,9 +101,9 @@ module Distance
let temp = !o in let temp = !o in
o := t[j]; o := t[j];
if w1[i] = w2[j] then if w1[i] = w2[j] then
set t j temp t[j] <- temp
else else
set t j ((min t[j] t[j+1]) + 1) t[j] <- (min t[j] t[j+1]) + 1
end end
done done
done; done;
......
...@@ -16,12 +16,12 @@ module Flag ...@@ -16,12 +16,12 @@ module Flag
{ 0 <= i < length a and 0 <= j < length a } { 0 <= i < length a and 0 <= j < length a }
let v = a[i] in let v = a[i] in
begin begin
set a i a[j]; a[i] <- a[j];
set a j v a[j] <- v
end end
{ exchange a (old a) i j } { exchange a (old a) i j }
let dutch_flag (a:array color) (n:int) = let dutch_flag (a:array color) (n:int) =
{ 0 <= n and length a = n } { 0 <= n and length a = n }
let b = ref 0 in let b = ref 0 in
let i = ref 0 in let i = ref 0 in
...@@ -29,8 +29,8 @@ module Flag ...@@ -29,8 +29,8 @@ module Flag
label Init: label Init:
while !i < !r do while !i < !r do
invariant { 0 <= b <= i and i <= r <= n and invariant { 0 <= b <= i and i <= r <= n and
monochrome a 0 b Blue and monochrome a 0 b Blue and
monochrome a b i White and monochrome a b i White and
monochrome a r n Red and monochrome a r n Red and
length a = n and length a = n and
permut_sub a (at a Init) 0 (n-1) } permut_sub a (at a Init) 0 (n-1) }
...@@ -47,16 +47,16 @@ module Flag ...@@ -47,16 +47,16 @@ module Flag
swap a !r !i swap a !r !i
end end
done done
{ (exists b:int. exists r:int. { (exists b:int. exists r:int.
monochrome a 0 b Blue and monochrome a 0 b Blue and
monochrome a b r White and monochrome a b r White and
monochrome a r n Red) monochrome a r n Red)
and permut_sub a (old a) 0 (n-1) } and permut_sub a (old a) 0 (n-1) }
end end
(* (*
Local Variables: Local Variables:
compile-command: "unset LANG; make -C ../.. examples/programs/flag.gui" compile-command: "unset LANG; make -C ../.. examples/programs/flag.gui"
End: End:
*) *)
...@@ -11,22 +11,22 @@ module Muller ...@@ -11,22 +11,22 @@ module Muller
let compact (a : array int) = let compact (a : array int) =
let count = ref 0 in let count = ref 0 in
for i = 0 to length a - 1 do for i = 0 to length a - 1 do
invariant { 0 <= count = num_of a.elts 0 i <= i} invariant { 0 <= count = num_of a.elts 0 i <= i}
if a[i] <> 0 then incr count if a[i] <> 0 then incr count
done; done;
let u = make !count 0 in let u = make !count 0 in
count := 0; count := 0;
for i = 0 to length a - 1 do for i = 0 to length a - 1 do
invariant { 0 <= count = num_of a.elts 0 i <= i and invariant { 0 <= count = num_of a.elts 0 i <= i and
length u = num_of a.elts 0 (length a) } length u = num_of a.elts 0 (length a) }
if a[i] <> 0 then begin set u !count a[i]; incr count end if a[i] <> 0 then begin u[!count] <- a[i]; incr count end
done done
end end
(* (*
Local Variables: Local Variables:
compile-command: "unset LANG; make -C ../.. examples/programs/muller.gui" compile-command: "unset LANG; make -C ../.. examples/programs/muller.gui"
End: End:
*) *)
...@@ -92,13 +92,13 @@ let search_safety () = ...@@ -92,13 +92,13 @@ let search_safety () =
invariant { length x = m } invariant { length x = m }
let delta = y - !s - c + x[d] in let delta = y - !s - c + x[d] in
if 0 <= delta && delta <= 9 * d then begin if 0 <= delta && delta <= 9 * d then begin
set x d c; x[d] <- c;
let k = div delta 9 in let k = div delta 9 in
for i = 0 to d - 1 do for i = 0 to d - 1 do
invariant { length x = m } invariant { length x = m }
if i < k then set x i 9 if i < k then x[i] <- 9
else if i = k then set x i (mod delta 9) else if i = k then x[i] <- mod delta 9
else set x i 0 else x[i] <- 0
done; done;
raise Success raise Success
end end
...@@ -132,7 +132,7 @@ let search () = ...@@ -132,7 +132,7 @@ let search () =
invariant { x = at x Init } invariant { x = at x Init }
let delta = y - !s - c + x[d] in let delta = y - !s - c + x[d] in
if 0 <= delta && delta <= 9 * d then begin if 0 <= delta && delta <= 9 * d then begin
set x d c; x[d] <- c;
assert { sum x.elts d m = y - delta }; assert { sum x.elts d m = y - delta };