(*  Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
(* This file contains an earlier version of state-related definitions.  The theory from this file should be moved to Procedure.v *)
Set Implicit Arguments.
(* Require Import ProgramLogic_old.   Definition stateful_comp_spec (S D R: Set)(inv : S -> S -> Prop)(pre : (S * D) -> (S * D) -> Prop)(post : (S * R) -> (S * R) -> Prop)(c1 c2 : (S * D) -> Comp (S * R)):= comp_spec_old (fun a1 a2 => pre a1 a2 /\ inv (fst a1) (fst a2)) (fun b1 b2 => post b1 b2 /\ inv (fst b1) (fst b2)) c1 c2 .   Section CompLoop.  Variable D R State : Set. Hypothesis S_EqDec : EqDec State.  Fixpoint compLoop (c : (State * D) -> Comp (State * R))(count : nat)(s : State)(d : D) : Comp State := match count with | 0 => ret s | S count' => [s', _] <-$2 c (s, d); compLoop c count' s' d end.  Lemma compLoop_wf : forall (o : (State * D) -> Comp (State * R)) count (s : State) (d : D), (forall x y, well_formed_comp (o (x, y))) -> well_formed_comp (compLoop o count s d).  induction count; intuition; unfold compLoop; wftac.  Qed.   Lemma compLoop_inv : forall (c : (State * D) -> Comp (State * R)) (inv : State -> Prop) d, (forall s s' r,  In (s', r) (getSupport (c (s, d))) -> inv s -> inv s') -> forall count s s', inv s -> In s' (getSupport (compLoop c count s d)) -> inv s'.  induction count; intuition; simpl in *. intuition; subst. trivial.  eapply in_getUnique_if in H1. apply in_flatten in H1. destruct H1. intuition. apply in_map_iff in H2. destruct H2. intuition. subst. destruct x0. eapply IHcount. eapply H. eauto. trivial. trivial.  Qed.  End CompLoop.  Class AdversaryWithOracle_concrete (D_A R_A D_O R_O : Set) (S_A : Set) (A1 : D_A -> Comp (S_A * D_O)) (A2 : S_A -> R_O -> Comp (S_A * D_O)) (A3 : S_A -> Comp R_A) := {  S_A_EqDec : EqDec S_A;  A1_wf : forall x, well_formed_comp (A1 x); A2_wf : forall x y, well_formed_comp (A2 x y); A3_wf : forall x, well_formed_comp (A3 x)  }.  Definition StatefulProc (S D R : Set) := S * D -> Comp (S * R).  Section AdversaryWithOracle_concrete.  Context `{A : AdversaryWithOracle_concrete }. Variable S_O : Set. (*  Definition Oracle := StatefulProc S_O D_O R_O. *)
Instance eqd_S_A : EqDec S_A.
eapply S_A_EqDec.
Defined.
Hypothesis R_A_EqDec : EqDec R_A.
Hypothesis D_A_EqDec : EqDec D_A.
Hypothesis S_O_EqDec : EqDec S_O.
Hypothesis D_O_EqDec : EqDec D_O.
Hypothesis R_O_EqDec : EqDec R_O.
Fixpoint loopA (oracleF : StatefulProc S_O D_O R_O)(count : nat)(s_A : S_A)(s_O : S_O)(d_O : D_O) : Comp (S_A * S_O) :=
match count with
| 0 => ret (s_A, s_O)
| S count' =>
[s_O', r_O] <-$2 oracleF (s_O, d_O);
[s_A', d_O'] <-$2 (A2 s_A r_O);
loopA oracleF count' s_A' s_O' d_O'
end.

Lemma loopA_wf_inv : forall oracleF inv count s_A s_O d_O,
inv s_O ->
(forall s d s' r, In (s', r) (getSupport (oracleF (s, d))) -> inv s -> inv s') ->
(forall s d, inv s -> well_formed_comp (oracleF (s, d))) ->
well_formed_comp (loopA oracleF count s_A s_O d_O).