(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.(*****************************************************************************)
(*                   We define now the Mini-ML semantics                     *)
(*In this semantics we want to distinguish the places where application is   *)
(*used in a recursive scheme from the other places.                          *)
(*That's why we have a special rule for application in the case where the    *)
(*function applied has as value a recursive closure (this correspond in fact *)
(*to a test during application                                               *)
(*****************************************************************************)

Inductive ML_DS : MLenv -> MLexp -> MLval -> Prop :=
  | BOOL : forall (b : bool) (e : MLenv), ML_DS e (Bool b) (boolean b)
  | NUM : forall (n : nat) (e : MLenv), ML_DS e (Num n) (num n)
  | Sem_OP : forall (c : OP) (e : MLenv), ML_DS e (op c) (OP_clos c)
  | LAMBDA :
      forall (e : MLenv) (P : Pat) (E : MLexp),
      ML_DS e (lambda P E) (Clos P E e)
  | IDENT :
      forall (e : MLenv) (v : MLval) (I : Pat),
      VAL_OF e I v -> ML_DS e (id I) v
  | ITE1 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean true) -> ML_DS e E2 v -> ML_DS e (ite E1 E2 E3) v
  | ITE2 :
      forall (e : MLenv) (E1 E2 E3 : MLexp) (v : MLval),
      ML_DS e E1 (boolean false) -> ML_DS e E3 v -> ML_DS e (ite E1 E2 E3) v
  | MLPAIR :
      forall (e : MLenv) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 u -> ML_DS e E2 v -> ML_DS e (mlpair E1 E2) (valpair u v)
  | APPml1 :
      forall (e e1 : MLenv) (P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos P E e1) ->
      ML_DS e E2 u -> ML_DS (Econs P u e1) E v -> ML_DS e (appl E1 E2) v
  | APPml2 :
      forall (e e1 : MLenv) (x P : Pat) (E E1 E2 : MLexp) (u v : MLval),
      ML_DS e E1 (Clos_rec x E P e1) ->
      ML_DS e E2 u ->
      ML_DS (Econs x u (Econs P (Clos_rec x E P e1) e1)) E v ->
      ML_DS e (appl E1 E2) v
  | APPml_op :
      forall (e : MLenv) (E1 E2 : MLexp) (n m : nat) (c : OP),
      ML_DS e E1 (OP_clos c) ->
      ML_DS e E2 (valpair (num n) (num m)) ->
      ML_DS e (appl E1 E2) (num (eval_op c n m))
  | Sem_let :
      forall (e : MLenv) (P : Pat) (E1 E2 : MLexp) (u v : MLval),
      ML_DS e E2 u -> ML_DS (Econs P u e) E1 v -> ML_DS e (let' P E2 E1) v
  | Sem_letrec :
      forall (e : MLenv) (P x : Pat) (E E2 : MLexp) (u : MLval),
      ML_DS (Econs P (Clos_rec x E P e) e) E2 u ->
      ML_DS e (letrec P x E E2) u.

(* Specifications: *)
Lemma ML_DS_determ : forall (e : MLenv) (E : MLexp) (V : MLval), ML_DS e E V -> forall V' : MLval, ML_DS e E V' -> V = V' :>MLval.