2 (* McCarthy's ``91'' function. *)
8 function spec (x: int) : int = if x <= 100 then 91 else x-10
10 (* traditional recursive implementation *)
12 let rec f91 (n:int) : int variant { 101-n }
13 ensures { result = spec n }
20 (* non-recursive implementation using a while loop *)
25 let f91_nonrec (n0: int) ensures { result = spec n0 }
30 invariant { !e >= 0 /\ iter spec !e !n = spec n0 }
31 variant { 101 - !n + 10 * !e, !e }
32 if !n > 100 then begin
42 (* Use a 'morally' irrelevant control flow from a recursive function
43 to ease proof (the recursive structure does not contribute to the
44 program execution). This is a technique for proving derecursified
45 programs. See verifythis_2016_tree_traversal for a more
50 let f91_pseudorec (n0:int) : int
51 ensures { result = spec n0 }
57 ensures { !(old e) > 0 }
58 ensures { if !(old n) > 100 then !n = !(old n) - 10 /\ !e = !(old e) - 1
59 else !n = !(old n) + 11 /\ !e = !(old e) + 1 }
60 raises { Stop -> !e = !(old e) = 0 /\ !n = !(old n) }
61 = if not (!e > 0) then raise Stop;
62 if !n > 100 then begin
73 ensures { !e = !(old e) - 1 /\ !n = spec !(old n) }
74 raises { Stop -> false }
75 = let u = !n in bloc (); if u <= 100 then (aux (); aux ()) in
76 try aux (); bloc (); absurd
86 function spec (x: int) : int = if x <= 100 then 91 else x-10
88 let rec f91 (n: int63) : int63
90 ensures { result = spec n }
101 let f91_nonrec (n0: int63) : int63
102 ensures { result = spec n0 }
107 invariant { !e >= 0 /\ iter spec !e !n = spec n0 }
108 variant { 101 - !n + 10 * !e, !e:int }
109 if !n > 100 then begin
121 let f91_pseudorec (n0: int63) : int63
122 ensures { result = spec n0 }
128 ensures { !(old e) > 0 }
129 ensures { if !(old n) > 100 then !n = !(old n) - 10 /\ !e = !(old e) - 1
130 else !n = !(old n) + 11 /\ !e = !(old e) + 1 }
131 raises { Stop -> !e = !(old e) = 0 /\ !n = !(old n) }
132 = if not (gt !e zero) then raise Stop;
133 if !n > 100 then begin
141 let rec aux () : unit
144 ensures { !e = !(old e) - 1 /\ !n = spec !(old n) }
145 raises { Stop -> false }
146 = let u = !n in bloc (); if u <= 100 then (aux (); aux ()) in
147 try aux (); bloc (); absurd