(** * Auxiliary lemmas for completeness

   The proof of completeness requires to exhibit a variant. 
   The purpose of the following lemmas is to build this variant.
*)

(** ** A technical issue: the inversion of [exec]

   If your are not interested in Coq details, you may skip this part
   which only explains how to avoid the assumption of a (consistent
   and standard) axiom to prove the completeness.

   Because the use of dependent types in constructor [exec_Iset], the
   standard inversion of Coq may fail on [exec] (see
   [exec_test_inversion] below).

   This comes from the fact the following property is not provable in
   the core theory of Coq (although it is consistent with it) :

   [forall A (x1 x2:E.Var A) e1 e2, (Iset x1 e1)=(Iset x2 e2) -> x1=x2 /\ e1=e2.]

   To deal with this problem, we may assume a (consistent) axiom given
   in #<a href=http://coq.inria.fr/V8.1/stdlib/Coq.Logic.EqdepFacts.html>#
      [EqdepFacts]#</a>#.
   But here, we can avoid this axiom.

   Indeed, I define an ad-hoc inversion lemma for [exec] called
   [exec_inversion] below. This lemma is directly derived from the
   notion of weakest liberal precondition: [aux_wlp] is an other
   alternative definition of [wlp].

*)
Definition aux_wlp (prog: ImpProg) : Pred -> Pred 
 := fun post e =>
  match prog with
  | Iskip => post e
  | (Iset A x expr) => post (E.upd x (E.eval expr e) e)
  | (Iif cond p1 p2) =>
       forall e', exec e (if E.eval cond e then p1 else p2) e' 
          -> post e'
  | (Iseq p1 p2) => forall e1 e2, exec e p1 e1 -> exec e1 p2 e2 -> post e2
  | (Iwhile cond p) => forall e', exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e' -> post e'
  end.(** Below, a little tactic to helps in applying [exec_inversion]. *)
Ltac exec_inversion H :=
  match type of H with
  | (exec ?e ?p ?e') => pattern e'; apply (exec_inversion H); simpl; clear H
  end.

(* Specifications: *)
Lemma exec_test_inversion: forall A (x:E.Var A) expr e e', (exec e (Iset x expr) e') -> e'=(E.upd x (E.eval expr e) e).
Lemma exec_deterministic: forall ei p ef, (exec ei p ef) -> forall ef', (exec ei p ef') -> ef=ef'.