(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*We can now define an equivalence between ML values and CAM values with the *)
(*the help of the predicate Traduction                                       *)
(*****************************************************************************)


Inductive Equiv_val : MLval -> CSem_val -> Prop :=
  | Eqbool : forall b : bool, Equiv_val (boolean b) (val (elem b))
  | Eqnum : forall n : nat, Equiv_val (num n) (val (int n))
  | Eq_op : forall c : OP, Equiv_val (OP_clos c) (val (def_op c))
  | Eqpair :
      forall (V1 V2 : MLval) (Cval1 Cval2 : CSem_val),
      Equiv_val V1 Cval1 ->
      Equiv_val V2 Cval2 -> Equiv_val (valpair V1 V2) (Cam_pair Cval1 Cval2)
  | Eqclos :
      forall (p : Pat) (E : MLexp) (C : Commande) (e : MLenv) 
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette p s) E C ->
      Equiv_val (Clos p E e) (Cam_clos C CV)
  | Eqclos_rec :
      forall (p x : Pat) (E : MLexp) (e : MLenv) (C : Commande)
        (CV : CSem_val) (s : Squelette),
      Equiv_env e CV ->
      Habite e s ->
      Traduction (cons_squelette x (cons_squelette p s)) E C ->
      Equiv_val (Clos_rec x E p e) (Cam_clos_rec C CV)
with Equiv_env : MLenv -> CSem_val -> Prop :=
  | Eqenv1 : Equiv_env Enil Cam_nil
  | Eqenv2 :
      forall (p : Pat) (E : MLenv) (CV0 : CSem_val),
      Equiv_env E CV0 ->
      forall (V : MLval) (CV : CSem_val),
      Equiv_val V CV -> Equiv_env (Econs p V E) (Cam_pair CV0 CV).(*****************************************************************************)
(*                 We can now give a formulation of the proof                *)
(*****************************************************************************)

Inductive compilation (E : MLexp) : Prop :=
    preuve_compilation :
      (forall (e : MLenv) (V : MLval),
       ML_DS e E V ->
       forall (s : Squelette) (C : Commande),
       Traduction s E C ->
       Habite e s ->
       forall CV : CSem_val,
       Equiv_env e CV ->
       exists CV1 : CSem_val,
         Equiv_val V CV1 /\
         (forall s : Etat, CAM_DS (ETcons CV s) C (ETcons CV1 s))) ->
      compilation E.(*****************************************************************************)
(*                 We can now give a formulation of the proof                *)
(*****************************************************************************)

Inductive compilation (E : MLexp) : Prop :=
    preuve_compilation :
      (forall (e : MLenv) (V : MLval),
       ML_DS e E V ->
       forall (s : Squelette) (C : Commande),
       Traduction s E C ->
       Habite e s ->
       forall CV : CSem_val,
       Equiv_env e CV ->
       exists CV1 : CSem_val,
         Equiv_val V CV1 /\
         (forall s : Etat, CAM_DS (ETcons CV s) C (ETcons CV1 s))) ->
      compilation E.

(* Specifications: *)
Lemma Proof_bool : forall b : bool, compilation (Bool b).
Lemma Proof_int : forall n : nat, compilation (Num n).
Lemma Proof_op : forall c : OP, compilation (op c).