Module E:=Ex.Module E:=E.Inductive ImpProg: Type := 
  | Iskip: ImpProg
  | Iset (A:Type) (v:E.Var A) (expr:E.Expr A): ImpProg
  | Iif (cond:E.Expr bool) (p1 p2:ImpProg): ImpProg
  | Iseq (p1 p2:ImpProg): ImpProg
  | Iwhile (cond:E.Expr bool) (p:ImpProg): ImpProg.Inductive ImpProg: Type := 
  | Iskip: ImpProg
  | Iset (A:Type) (v:E.Var A) (expr:E.Expr A): ImpProg
  | Iif (cond:E.Expr bool) (p1 p2:ImpProg): ImpProg
  | Iseq (p1 p2:ImpProg): ImpProg
  | Iwhile (cond:E.Expr bool) (p:ImpProg): ImpProg.Inductive ImpProg: Type := 
  | Iskip: ImpProg
  | Iset (A:Type) (v:E.Var A) (expr:E.Expr A): ImpProg
  | Iif (cond:E.Expr bool) (p1 p2:ImpProg): ImpProg
  | Iseq (p1 p2:ImpProg): ImpProg
  | Iwhile (cond:E.Expr bool) (p:ImpProg): ImpProg.Inductive ImpProg: Type := 
  | Iskip: ImpProg
  | Iset (A:Type) (v:E.Var A) (expr:E.Expr A): ImpProg
  | Iif (cond:E.Expr bool) (p1 p2:ImpProg): ImpProg
  | Iseq (p1 p2:ImpProg): ImpProg
  | Iwhile (cond:E.Expr bool) (p:ImpProg): ImpProg.Inductive ImpProg: Type := 
  | Iskip: ImpProg
  | Iset (A:Type) (v:E.Var A) (expr:E.Expr A): ImpProg
  | Iif (cond:E.Expr bool) (p1 p2:ImpProg): ImpProg
  | Iseq (p1 p2:ImpProg): ImpProg
  | Iwhile (cond:E.Expr bool) (p:ImpProg): ImpProg.Inductive ImpProg: Type := 
  | Iskip: ImpProg
  | Iset (A:Type) (v:E.Var A) (expr:E.Expr A): ImpProg
  | Iif (cond:E.Expr bool) (p1 p2:ImpProg): ImpProg
  | Iseq (p1 p2:ImpProg): ImpProg
  | Iwhile (cond:E.Expr bool) (p:ImpProg): ImpProg.Inductive exec: E.Env -> ImpProg -> E.Env -> Prop :=
 | exec_Iskip: 
    forall e, (exec e Iskip e)
 | exec_Iset:
    forall (A:Type) e x (expr: E.Expr A), 
     (exec e (Iset x expr) (E.upd x (E.eval expr e) e))
 | exec_Iif:
    forall e (cond: E.Expr bool) p1 p2 e', 
      (exec e (if (E.eval cond e) then p1 else p2) e') 
         -> (exec e (Iif cond p1 p2) e')
 | exec_Iseq:
    forall e p1 p2 e' e'',
      (exec e p1 e') 
       -> (exec e' p2 e'')    
         -> (exec e (Iseq p1 p2) e'')
 | exec_Iwhile:
    forall e cond p e', 
     (exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e')
        -> (exec e (Iwhile cond p) e').Inductive exec: E.Env -> ImpProg -> E.Env -> Prop :=
 | exec_Iskip: 
    forall e, (exec e Iskip e)
 | exec_Iset:
    forall (A:Type) e x (expr: E.Expr A), 
     (exec e (Iset x expr) (E.upd x (E.eval expr e) e))
 | exec_Iif:
    forall e (cond: E.Expr bool) p1 p2 e', 
      (exec e (if (E.eval cond e) then p1 else p2) e') 
         -> (exec e (Iif cond p1 p2) e')
 | exec_Iseq:
    forall e p1 p2 e' e'',
      (exec e p1 e') 
       -> (exec e' p2 e'')    
         -> (exec e (Iseq p1 p2) e'')
 | exec_Iwhile:
    forall e cond p e', 
     (exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e')
        -> (exec e (Iwhile cond p) e').Inductive exec: E.Env -> ImpProg -> E.Env -> Prop :=
 | exec_Iskip: 
    forall e, (exec e Iskip e)
 | exec_Iset:
    forall (A:Type) e x (expr: E.Expr A), 
     (exec e (Iset x expr) (E.upd x (E.eval expr e) e))
 | exec_Iif:
    forall e (cond: E.Expr bool) p1 p2 e', 
      (exec e (if (E.eval cond e) then p1 else p2) e') 
         -> (exec e (Iif cond p1 p2) e')
 | exec_Iseq:
    forall e p1 p2 e' e'',
      (exec e p1 e') 
       -> (exec e' p2 e'')    
         -> (exec e (Iseq p1 p2) e'')
 | exec_Iwhile:
    forall e cond p e', 
     (exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e')
        -> (exec e (Iwhile cond p) e').Inductive exec: E.Env -> ImpProg -> E.Env -> Prop :=
 | exec_Iskip: 
    forall e, (exec e Iskip e)
 | exec_Iset:
    forall (A:Type) e x (expr: E.Expr A), 
     (exec e (Iset x expr) (E.upd x (E.eval expr e) e))
 | exec_Iif:
    forall e (cond: E.Expr bool) p1 p2 e', 
      (exec e (if (E.eval cond e) then p1 else p2) e') 
         -> (exec e (Iif cond p1 p2) e')
 | exec_Iseq:
    forall e p1 p2 e' e'',
      (exec e p1 e') 
       -> (exec e' p2 e'')    
         -> (exec e (Iseq p1 p2) e'')
 | exec_Iwhile:
    forall e cond p e', 
     (exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e')
        -> (exec e (Iwhile cond p) e').Inductive exec: E.Env -> ImpProg -> E.Env -> Prop :=
 | exec_Iskip: 
    forall e, (exec e Iskip e)
 | exec_Iset:
    forall (A:Type) e x (expr: E.Expr A), 
     (exec e (Iset x expr) (E.upd x (E.eval expr e) e))
 | exec_Iif:
    forall e (cond: E.Expr bool) p1 p2 e', 
      (exec e (if (E.eval cond e) then p1 else p2) e') 
         -> (exec e (Iif cond p1 p2) e')
 | exec_Iseq:
    forall e p1 p2 e' e'',
      (exec e p1 e') 
       -> (exec e' p2 e'')    
         -> (exec e (Iseq p1 p2) e'')
 | exec_Iwhile:
    forall e cond p e', 
     (exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e')
        -> (exec e (Iwhile cond p) e').Inductive exec: E.Env -> ImpProg -> E.Env -> Prop :=
 | exec_Iskip: 
    forall e, (exec e Iskip e)
 | exec_Iset:
    forall (A:Type) e x (expr: E.Expr A), 
     (exec e (Iset x expr) (E.upd x (E.eval expr e) e))
 | exec_Iif:
    forall e (cond: E.Expr bool) p1 p2 e', 
      (exec e (if (E.eval cond e) then p1 else p2) e') 
         -> (exec e (Iif cond p1 p2) e')
 | exec_Iseq:
    forall e p1 p2 e' e'',
      (exec e p1 e') 
       -> (exec e' p2 e'')    
         -> (exec e (Iseq p1 p2) e'')
 | exec_Iwhile:
    forall e cond p e', 
     (exec e (Iif cond (Iseq p (Iwhile cond p)) Iskip) e')
        -> (exec e (Iwhile cond p) e').

(* Specifications: *)
Lemma exec_Iif_true: forall e cond p1 p2 e', (E.eval cond e)=true -> (exec e p1 e') -> (exec e (Iif cond p1 p2) e').
Lemma exec_Iif_false: forall e cond p1 p2 e', (E.eval cond e)=false -> (exec e p2 e') -> (exec e (Iif cond p1 p2) e').