Built with Alectryon, running Coq+SerAPI v8.12.0+0.12.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
Require Import Helpers.Helpers. Require Import Proc. Require Import Abstraction. Require Import List. Import ListNotations.
Looping combinators.
loop body iteration 0 loop body iteration 1 .. loop body iteration N-1
* starting state: loop invariant holds for 0 iterations loop body iteration 0 * intermediate state: loop invariant holds for 1 iterations loop body iteration 1 * intermediate state: loop invariant holds for 2 iterations .. * intermediate state: loop invariant holds for N-1 iterations loop body iteration N-1 * final state: loop invariant holds for N iterations
Starting state | V Loop invariant(0) ... Loop invariant(K) | [loop body] | V Loop invariant(K+1) ... Loop invariant(N) | V Final state
Combinator for list iteration.
Fixpoint foreach `(l: list V) `(body: V -> T -> proc T) (acc: T) : proc T :=
match l with
| nil =>
Ret acc
| v :: l' =>
acc <- body v acc;
foreach l' body acc
end.
In the case of list iteration, our loop invariant, loop_inv, is a
function of the list we have processed so far, the accumulated value
of type T, the ghost state A, and the current state of the system,
State. A common pattern will be to store the starting state for the
entire loop in the ghost state, if the loop invariant wants to relate
the starting state to the current state.
Given a loop invariant, we can synthesize a spec for the entire invocation
of foreach, defined by foreach_spec below. It captures the intuition
that was laid out at the top of this file: the precondition for foreach
is that the loop invariant holds with an initial prefix (which will be
nil in the common case), and the postcondition is that the loop invariant
now holds with the entire list l being processed. The recovered
condition says that, when we crash, we executed some number of
iterations of the loop body.
Definition foreach_spec {R} `(loop_inv: list V -> T -> A -> State -> Prop)
(wipe: State -> State -> Prop)
(prefix: list V) (l: list V) (acc: T) : Specification A T R State :=
fun (a : A) state => {|
pre := loop_inv prefix acc a state;
post := fun r state' => loop_inv (prefix ++ l) r a state';
recovered := fun _ state' =>
exists r n pre_wipe,
loop_inv (prefix ++ (firstn n l)) r a pre_wipe /\
wipe pre_wipe state'
|}.
The following theorem, foreach_ok_helper, proves that foreach_spec
is correct. It uses induction over the iterations of foreach, but the
benefit is that other code that needs to reason about loops no longer
needs to do low-level Coq induction. It assumes that the loop body is
correct in a particularly induction-friendly way, which we will clean up
below.
forall (V T A State : Type) (loopinv : list V -> T -> A -> State -> Prop) (wipe : State -> State -> Prop) (body : V -> T -> proc T) (R : Type) (recover : proc R) (abstr : Abstraction State) (l prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrforall (V T A State : Type) (loopinv : list V -> T -> A -> State -> Prop) (wipe : State -> State -> Prop) (body : V -> T -> proc T) (R : Type) (recover : proc R) (abstr : Abstraction State) (l prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateforall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix [] acc) (foreach [] body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrforall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix (a :: l) acc) (foreach (a :: l) body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateforall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix [] acc) (foreach [] body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstrproc_spec (foreach_spec loopinv wipe prefix [] acc) (foreach [] body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstrproc_spec (foreach_spec loopinv wipe prefix [] acc) (Ret acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)loopinv (prefix ++ []) acc a stateV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rexists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n []) r a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)loopinv (prefix ++ []) acc a stateauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)loopinv prefix acc a stateV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rexists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n []) r a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rloopinv (prefix ++ firstn 0 []) acc a state /\ wipe state state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rloopinv (prefix ++ []) acc a state /\ wipe state state'auto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra:Astate:StateH1:loopinv prefix acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rloopinv prefix acc a state /\ wipe state state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrforall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix (a :: l) acc) (foreach (a :: l) body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstrproc_spec (foreach_spec loopinv wipe prefix (a :: l) acc) (foreach (a :: l) body acc) recover abstrstep_proc. exists a'. intuition idtac. +V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstrproc_spec (foreach_spec loopinv wipe prefix (a :: l) acc) (acc <- body a acc; foreach l body acc) recover abstrauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stateL:Marker "precondition" (body a acc)loopinv prefix acc a' stateV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn n [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn 0 [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn (S n) [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn 0 [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn 0 [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv (prefix ++ firstn 0 (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tpre_wipe:StateH2:loopinv ((prefix ++ []) ++ []) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv (prefix ++ []) r0 a' pre_wipe /\ wipe pre_wipe state'eauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tpre_wipe:StateH2:loopinv prefix r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv prefix r0 a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn (S n) [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv ((prefix ++ []) ++ firstn (S n) [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv (prefix ++ firstn 1 (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv ((prefix ++ []) ++ a :: firstn n []) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv (prefix ++ [a]) r0 a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv (prefix ++ a :: firstn n []) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv (prefix ++ [a]) r0 a' pre_wipe /\ wipe pre_wipe state'auto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv (prefix ++ [a]) r0 a' pre_wipeH3:wipe pre_wipe state'L:Marker "recovered condition" (body a acc)loopinv (prefix ++ [a]) r0 a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl:list VIHl:forall (prefix : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe prefix l acc) (foreach l body acc) recover abstrprefix:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)proc_spec (fun (_ : unit) (state' : State) => {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state'; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |}) (foreach l body r) recover abstreapply proc_spec_implication; intros. {V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)proc_spec (fun (_ : unit) (state' : State) => {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state'; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |}) (foreach l body r) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)L:Marker "using spec for" (foreach l body r)forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc) (body v acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)L:Marker "using spec for" (foreach l body r)v:Vacc0:Tprefix':list Vproc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstreauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)L:Marker "using spec for" (foreach l body r)v:Vacc0:Tprefix':list Vproc_spec (foreach_spec loopinv wipe (prefix ++ [a] ++ prefix') [v] acc0) (body v acc0) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:pre {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |}exists a'0 : A, pre (foreach_spec loopinv wipe (prefix ++ [a]) l r a'0 state0) /\ (forall (v : T) (state' : State), post (foreach_spec loopinv wipe (prefix ++ [a]) l r a'0 state0) v state' -> post {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |} v state') /\ (forall (rv : R) (state' : State), recovered (foreach_spec loopinv wipe (prefix ++ [a]) l r a'0 state0) rv state' -> recovered {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |} rv state')V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:pre {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |}pre (foreach_spec loopinv wipe (prefix ++ [a]) l r a' state0) /\ (forall (v : T) (state' : State), post (foreach_spec loopinv wipe (prefix ++ [a]) l r a' state0) v state' -> post {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |} v state') /\ (forall (rv : R) (state' : State), recovered (foreach_spec loopinv wipe (prefix ++ [a]) l r a' state0) rv state' -> recovered {| pre := loopinv ((prefix ++ []) ++ [a]) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (prefix ++ a :: l) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'' |} rv state')V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv ((prefix ++ []) ++ [a]) r a' state0loopinv (prefix ++ [a]) r a' state0 /\ (forall (v : T) (state' : State), loopinv ((prefix ++ [a]) ++ l) v a' state' -> loopinv (prefix ++ a :: l) v a' state') /\ (R -> forall state' : State, (exists (r : T) (n : nat) (pre_wipe : State), loopinv ((prefix ++ [a]) ++ firstn n l) r a' pre_wipe /\ wipe pre_wipe state') -> exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state')V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0loopinv (prefix ++ [a]) r a' state0 /\ (forall (v : T) (state' : State), loopinv ((prefix ++ [a]) ++ l) v a' state' -> loopinv (prefix ++ a :: l) v a' state') /\ (R -> forall state' : State, (exists (r : T) (n : nat) (pre_wipe : State), loopinv ((prefix ++ [a]) ++ firstn n l) r a' pre_wipe /\ wipe pre_wipe state') -> exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state')V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0v:Tstate':StateH3:loopinv ((prefix ++ [a]) ++ l) v a' state'loopinv (prefix ++ a :: l) v a' state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv ((prefix ++ [a]) ++ firstn n l) r0 a' pre_wipeH4:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0v:Tstate':StateH3:loopinv ((prefix ++ [a]) ++ l) v a' state'loopinv (prefix ++ a :: l) v a' state'eauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0v:Tstate':StateH3:loopinv (prefix ++ [a] ++ l) v a' state'loopinv (prefix ++ a :: l) v a' state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv ((prefix ++ [a]) ++ firstn n l) r0 a' pre_wipeH4:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix ++ firstn n (a :: l)) r a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv ((prefix ++ [a]) ++ firstn n l) r0 a' pre_wipeH4:wipe pre_wipe state'loopinv (prefix ++ firstn (S n) (a :: l)) r0 a' pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv ((prefix ++ [a]) ++ firstn n l) r0 a' pre_wipeH4:wipe pre_wipe state'loopinv (prefix ++ a :: firstn n l) r0 a' pre_wipe /\ wipe pre_wipe state'intuition eauto. Qed.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statea:Vl, prefix:list VIHl:forall acc : T, rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ((prefix ++ [a]) ++ prefix') [v] acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe (prefix ++ [a]) l acc) (foreach l body acc) recover abstracc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe (prefix ++ prefix') [v] acc) (body v acc) recover abstra':Astate:StateH1:loopinv prefix acc a' stater:TLexec:Marker "after" (body a acc)a0:unitstate0:StateH2:loopinv (prefix ++ [a]) r a' state0rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (prefix ++ [a] ++ firstn n l) r0 a' pre_wipeH4:wipe pre_wipe state'loopinv (prefix ++ a :: firstn n l) r0 a' pre_wipe /\ wipe pre_wipe state'
In order to reason about foreach, we need to prove that each
iteration of the body preserves the loop invariant. The following
definition, foreach_body_spec, captures what we expect to be true
about a single execution of the loop body: starting with a precondition
that the loop invariant holds for some prefix of the list, the
postcondition must be that the loop invariant holds with one more element
added to the list, and the recovery condition is that either we processed
one more element, or we did nothing.
Definition foreach_body_spec {R} `(loop_inv: list V -> T -> A -> State -> Prop)
(wipe: State -> State -> Prop)
(prefix: list V) (v: V) (acc: T) : Specification A T R State :=
fun (a : A) state => {|
pre := loop_inv prefix acc a state;
post := fun r state' => loop_inv (prefix ++ [v]) r a state';
recovered := fun _ state' =>
exists pre_wipe,
( loop_inv prefix acc a pre_wipe \/
exists r', loop_inv (prefix ++ [v]) r' a pre_wipe ) /\
wipe pre_wipe state'
|}.
The final theorem, foreach_ok, simply re-states foreach_ok_helper
using a more friendly definition for what must be true about the loop
body, with the help of the foreach_body_spec.
forall (V T A State : Type) (loopinv : list V -> T -> A -> State -> Prop) (wipe : State -> State -> Prop) (body : V -> T -> proc T) (R : Type) (recover : proc R) (abstr : Abstraction State) (l : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe [] l acc) (foreach l body acc) recover abstrforall (V T A State : Type) (loopinv : list V -> T -> A -> State -> Prop) (wipe : State -> State -> Prop) (body : V -> T -> proc T) (R : Type) (recover : proc R) (abstr : Abstraction State) (l : list V) (acc : T), rec_wipe recover abstr wipe -> (forall (v : V) (acc0 : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc0) (body v acc0) recover abstr) -> proc_spec (foreach_spec loopinv wipe [] l acc) (foreach l body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrproc_spec (foreach_spec loopinv wipe [] l acc) (foreach l body acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrrec_wipe recover abstr wipeV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrforall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ([] ++ prefix') [v] acc) (body v acc) recover abstreauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrrec_wipe recover abstr wipeV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrforall (v : V) (acc : T) (prefix' : list V), proc_spec (foreach_spec loopinv wipe ([] ++ prefix') [v] acc) (body v acc) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Vproc_spec (foreach_spec loopinv wipe ([] ++ prefix') [v] acc0) (body v acc0) recover abstreapply proc_spec_implication. { intros. eauto. } intros. simpl in *. exists a.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Vproc_spec (foreach_spec loopinv wipe prefix' [v] acc0) (body v acc0) recover abstrV, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:StateH2:loopinv prefix' acc0 a pre_wipeH3:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix' ++ firstn n [v]) r a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:Stater':TH2:loopinv (prefix' ++ [v]) r' a pre_wipeH3:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix' ++ firstn n [v]) r a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:StateH2:loopinv prefix' acc0 a pre_wipeH3:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix' ++ firstn n [v]) r a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:StateH2:loopinv prefix' acc0 a pre_wipeH3:wipe pre_wipe state'loopinv (prefix' ++ firstn 0 [v]) acc0 a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:StateH2:loopinv prefix' acc0 a pre_wipeH3:wipe pre_wipe state'loopinv (prefix' ++ []) acc0 a pre_wipe /\ wipe pre_wipe state'intuition eauto.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:StateH2:loopinv prefix' acc0 a pre_wipeH3:wipe pre_wipe state'loopinv prefix' acc0 a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:Stater':TH2:loopinv (prefix' ++ [v]) r' a pre_wipeH3:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (prefix' ++ firstn n [v]) r a pre_wipe /\ wipe pre_wipe state'V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:Stater':TH2:loopinv (prefix' ++ [v]) r' a pre_wipeH3:wipe pre_wipe state'loopinv (prefix' ++ firstn 1 [v]) r' a pre_wipe /\ wipe pre_wipe state'intuition eauto. Qed.V, T, A, State:Typeloopinv:list V -> T -> A -> State -> Propwipe:State -> State -> Propbody:V -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statel:list Vacc:TH:rec_wipe recover abstr wipeH0:forall (v : V) (acc : T) (prefix : list V), proc_spec (foreach_body_spec loopinv wipe prefix v acc) (body v acc) recover abstrv:Vacc0:Tprefix':list Va:Astate:StateH1:loopinv prefix' acc0 a staterv:Rstate', pre_wipe:Stater':TH2:loopinv (prefix' ++ [v]) r' a pre_wipeH3:wipe pre_wipe state'loopinv (prefix' ++ [v]) r' a pre_wipe /\ wipe pre_wipe state'
Combinator for nat iteration.
Fixpoint for_range (start: nat) (count: nat) `(body: nat -> T -> proc T) (acc: T) : proc T :=
match count with
| O =>
Ret acc
| S count' =>
acc <- body start acc;
for_range (start + 1) count' body acc
end.
The definitions of for_range_spec and for_range_ok mirror the
definitions of foreach_spec and foreach_ok above. There is no
analogue of foreach_ok_helper and foreach_body_spec, because the
for_range_spec is usable enough as-is for the body correctness
condition, without re-phrasing it like we did in foreach_body_spec.
Definition for_range_spec {R} `(loop_inv: nat -> T -> A -> State -> Prop) (wipe: State -> State -> Prop) (count: nat) (base: nat) (acc: T) : Specification A T R State := fun (a : A) state => {| pre := loop_inv base acc a state; post := fun r state' => loop_inv (base+count) r a state'; recovered := fun _ state' => exists r n pre_wipe, loop_inv (base+n) r a pre_wipe /\ n <= count /\ wipe pre_wipe state' |}.forall (T A State : Type) (loopinv : nat -> T -> A -> State -> Prop) (wipe : State -> State -> Prop) (body : nat -> T -> proc T) (R : Type) (recover : proc R) (abstr : Abstraction State) (count start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrforall (T A State : Type) (loopinv : nat -> T -> A -> State -> Prop) (wipe : State -> State -> Prop) (body : nat -> T -> proc T) (R : Type) (recover : proc R) (abstr : Abstraction State) (count start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateforall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe 0 start acc) (for_range start 0 body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrforall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe (S count) start acc) (for_range start (S count) body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Stateforall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe 0 start acc) (for_range start 0 body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), n < start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrproc_spec (for_range_spec loopinv wipe 0 start acc) (for_range start 0 body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), n < start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrproc_spec (for_range_spec loopinv wipe 0 start acc) (Ret acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)loopinv (start + 0) acc a stateT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rexists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a pre_wipe /\ n <= 0 /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)loopinv (start + 0) acc a stateeauto.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)loopinv start acc a stateT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rexists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a pre_wipe /\ n <= 0 /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rloopinv (start + 0) acc a state /\ 0 <= 0 /\ wipe state state'intuition eauto.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statestart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + 0 -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstra:Astate:StateH1:loopinv start acc a stateLexec:Marker "post" (Ret acc)state':StateH2:wipe state state'r:Rloopinv start acc a state /\ 0 <= 0 /\ wipe state state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrforall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe (S count) start acc) (for_range start (S count) body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), n < start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrproc_spec (for_range_spec loopinv wipe (S count) start acc) (for_range start (S count) body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), n < start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrproc_spec (for_range_spec loopinv wipe (S count) start acc) (acc <- body start acc; for_range (start + 1) count body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), n < start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), n < start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstrproc_spec (for_range_spec loopinv wipe (S count) start acc) (acc <- body start acc; for_range (start + 1) count body acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stateexists a : A, (Marker "precondition" (body start acc) -> loopinv start acc a state) /\ (R -> forall state' : State, (exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a pre_wipe /\ n <= 1 /\ wipe pre_wipe state') -> Marker "recovered condition" (body start acc) -> exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state') /\ (forall r : T, Marker "after" (body start acc) -> proc_spec (fun (_ : unit) (state' : State) => {| pre := loopinv (start + 1) r a state'; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r1 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r1 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}) (for_range (start + 1) count body r) recover abstr)T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' state(Marker "precondition" (body start acc) -> loopinv start acc a' state) /\ (R -> forall state' : State, (exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= 1 /\ wipe pre_wipe state') -> Marker "recovered condition" (body start acc) -> exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state') /\ (forall r : T, Marker "after" (body start acc) -> proc_spec (fun (_ : unit) (state' : State) => {| pre := loopinv (start + 1) r a' state'; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r1 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r1 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}) (for_range (start + 1) count body r) recover abstr)T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv (start + n) r0 a' pre_wipeH3:n <= 1H4:wipe pre_wipe state'L:Marker "recovered condition" (body start acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)proc_spec (fun (_ : unit) (state' : State) => {| pre := loopinv (start + 1) r a' state'; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}) (for_range (start + 1) count body r) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv (start + n) r0 a' pre_wipeH3:n <= 1H4:wipe pre_wipe state'L:Marker "recovered condition" (body start acc)exists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv (start + n) r0 a' pre_wipeH3:n <= 1H4:wipe pre_wipe state'L:Marker "recovered condition" (body start acc)loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'lia.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:Rstate':Stater0:Tn:natpre_wipe:StateH2:loopinv (start + n) r0 a' pre_wipeH3:n <= 1H4:wipe pre_wipe state'L:Marker "recovered condition" (body start acc)n <= S counteapply proc_spec_implication. { intros.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)proc_spec (fun (_ : unit) (state' : State) => {| pre := loopinv (start + 1) r a' state'; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}) (for_range (start + 1) count body r) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)L:Marker "using spec for" (for_range (start + 1) count body r)forall (n : nat) (acc : T), S n <= start + 1 + count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)L:Marker "using spec for" (for_range (start + 1) count body r)n:natacc0:TH2:S n <= start + 1 + countproc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstrlia.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)L:Marker "using spec for" (for_range (start + 1) count body r)n:natacc0:TH2:S n <= start + 1 + countS n <= start + S countT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)unit -> forall state : State, pre {| pre := loopinv (start + 1) r a' state; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} -> exists a'0 : A, pre (for_range_spec loopinv wipe count (start + 1) r a'0 state) /\ (forall (v : T) (state' : State), post (for_range_spec loopinv wipe count (start + 1) r a'0 state) v state' -> post {| pre := loopinv (start + 1) r a' state; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} v state') /\ (forall (rv : R) (state' : State), recovered (for_range_spec loopinv wipe count (start + 1) r a'0 state) rv state' -> recovered {| pre := loopinv (start + 1) r a' state; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} rv state')T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}exists a'0 : A, pre (for_range_spec loopinv wipe count (start + 1) r a'0 state0) /\ (forall (v : T) (state' : State), post (for_range_spec loopinv wipe count (start + 1) r a'0 state0) v state' -> post {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} v state') /\ (forall (rv : R) (state' : State), recovered (for_range_spec loopinv wipe count (start + 1) r a'0 state0) rv state' -> recovered {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} rv state')T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}pre (for_range_spec loopinv wipe count (start + 1) r a' state0) /\ (forall (v : T) (state' : State), post (for_range_spec loopinv wipe count (start + 1) r a' state0) v state' -> post {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} v state') /\ (forall (rv : R) (state' : State), recovered (for_range_spec loopinv wipe count (start + 1) r a' state0) rv state' -> recovered {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |} rv state')T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}loopinv (start + 1) r a' state0 /\ (forall (v : T) (state' : State), loopinv (start + 1 + count) v a' state' -> loopinv (start + S count) v a' state') /\ (R -> forall state' : State, (exists (r : T) (n : nat) (pre_wipe : State), loopinv (start + 1 + n) r a' pre_wipe /\ n <= count /\ wipe pre_wipe state') -> exists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a' pre_wipe /\ n <= S count /\ wipe pre_wipe state')T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}v:Tstate':StateH3:loopinv (start + 1 + count) v a' state'loopinv (start + S count) v a' state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}v:Tstate':StateH3:loopinv (start + 1 + count) v a' state'loopinv (start + S count) v a' state'eauto.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}v:Tstate':StateH3:loopinv (start + 1 + count) v a' state'loopinv (start + 1 + count) v a' state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'exists (r : T) (n : nat) (pre_wipe : State), loopinv (start + n) r a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'loopinv (start + (n + 1)) r0 a' pre_wipe /\ n + 1 <= S count /\ wipe pre_wipe state'T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'loopinv (start + (n + 1)) r0 a' pre_wipeT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'n + 1 <= S countT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'loopinv (start + (n + 1)) r0 a' pre_wipeeauto.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'loopinv (start + 1 + n) r0 a' pre_wipeT, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'n + 1 <= S countlia. } Qed.T, A, State:Typeloopinv:nat -> T -> A -> State -> Propwipe:State -> State -> Propbody:nat -> T -> proc TR:Typerecover:proc Rabstr:Abstraction Statecount:natIHcount:forall (start : nat) (acc : T), rec_wipe recover abstr wipe -> (forall (n : nat) (acc0 : T), S n <= start + count -> proc_spec (for_range_spec loopinv wipe 1 n acc0) (body n acc0) recover abstr) -> proc_spec (for_range_spec loopinv wipe count start acc) (for_range start count body acc) recover abstrstart:natacc:TH:rec_wipe recover abstr wipeH0:forall (n : nat) (acc : T), S n <= start + S count -> proc_spec (for_range_spec loopinv wipe 1 n acc) (body n acc) recover abstrH0':proc_spec (for_range_spec loopinv wipe 1 start acc) (body start acc) recover abstra':Astate:StateH1:loopinv start acc a' stater:TLexec:Marker "after" (body start acc)a:unitstate0:StateH2:pre {| pre := loopinv (start + 1) r a' state0; post := fun (r' : T) (state'' : State) => loopinv (start + S count) r' a' state''; recovered := fun (_ : R) (state'' : State) => exists (r0 : T) (n : nat) (pre_wipe : State), loopinv (start + n) r0 a' pre_wipe /\ n <= S count /\ wipe pre_wipe state'' |}rv:Rstate':Stater0:Tn:natpre_wipe:StateH3:loopinv (start + 1 + n) r0 a' pre_wipeH4:n <= countH5:wipe pre_wipe state'n + 1 <= S count