Library ConcreteWhile


This file contains the definition of the example language, and equip it of a concrete semantics, giving some examples of terms and concrete derivations.

Set Implicit Arguments.
Require Export Utf8.
Require Export PrettyBigStep.

Require Export LibHeap.

Module Heap := LibHeap.HeapList.

Section ConcreteExample.

Concrete Example

Syntax


Definition var := string.
Definition proc := string.
Definition Val := int.

Inductive expr :=
  | expr_cst : Val → expr
  | expr_var : var → expr
  | expr_add : expr → expr → expr
  .

Inductive ext_expr :=
  | expr_add_1 : expr → ext_expr
  | expr_add_2 : ext_expr
  .

Inductive stat :=
  | stat_skip : stat
  | stat_asgn : var → expr → stat
  | stat_seq : stat → stat → stat
  | stat_if : expr → stat → stat → stat
  | stat_while : expr → stat → stat
  | stat_throw : stat
  | stat_proc_call : proc → expr → stat
  .

Inductive ext_stat :=
  | stat_asgn_1 : var → ext_stat
  | stat_seq_1 : stat → ext_stat
  | stat_if_1 : stat → stat → ext_stat
  | stat_while_1 : expr → stat → ext_stat
  | stat_while_2 : expr → stat → ext_stat
  | stat_proc_call_1 : proc → ext_stat
  .

Inductive prog :=
  | prog_proc_decl : proc → var → stat → prog → prog
  | prog_stat : stat → prog
  .

Inductive terms :=
  | terms_expr : expr → terms
  | terms_ext_expr : ext_expr → terms
  | terms_stat : stat → terms
  | terms_ext_stat : ext_stat → terms
  | terms_prog : prog → terms
  .

Coercion terms_expr : expr >-> terms.
Coercion terms_ext_expr : ext_expr >-> terms.
Coercion terms_stat : stat >-> terms.
Coercion terms_ext_stat : ext_stat >-> terms.
Coercion terms_prog : prog >-> terms.

Fixpoint compare_expr e1 e2 :=
  match e1, e2 with
  | expr_cst c1, expr_cst c2 ⇒ decide (c1 = c2)
  | expr_var x1, expr_var x2 ⇒ decide (x1 = x2)
  | expr_add e11 e21, expr_add e12 e22 ⇒
    compare_expr e11 e12 && compare_expr e21 e22
  | _, _ ⇒ false
  end.

Global Instance expr_Comparable : Comparable expr.
  applys comparable_beq compare_expr. intros x y. iff H.
   gen y; induction x; intros; destruct y; simpls; rew_refl in *; tryfalse; substs*; fequals×.
   substs~; induction y; simpls; rew_refl¬.
Defined.

Fixpoint compare_stat s1 s2 :=
  match s1, s2 with
  | stat_skip, stat_skip ⇒ true
  | stat_asgn x1 e1, stat_asgn x2 e2 ⇒ decide (x1 = x2 ∧ e1 = e2)
  | stat_seq s11 s12, stat_seq s21 s22 ⇒
    compare_stat s11 s21 && compare_stat s12 s22
  | stat_if e1 s11 s12, stat_if e2 s21 s22 ⇒
    decide (e1 = e2) && compare_stat s11 s21 && compare_stat s12 s22
  | stat_while e1 s1, stat_while e2 s2 ⇒
    decide (e1 = e2) && compare_stat s1 s2
  | stat_throw, stat_throw ⇒ true
  | stat_proc_call f1 e1, stat_proc_call f2 e2 ⇒ decide (f1 = f2 ∧ e1 = e2)
  | _, _ ⇒ false
  end.

Global Instance stat_Comparable : Comparable stat.
  applys comparable_beq compare_stat. intros x y. iff H.
   gen y; induction x; intros; destruct y; simpls~; tryfalse;
     try rewrite <- and_andb in *; rew_refl in *; substs*; fequals×.
   substs~; induction y; simpls; try rewrite <- and_andb; rew_refl¬.
Defined.

Global Instance stat_Inhab : Inhab stat.
  apply prove_Inhab. constructors¬.
Defined.

Definition compare_ext_expr e1 e2 :=
  match e1, e2 with
  | expr_add_1 e1, expr_add_1 e2 ⇒ decide (e1 = e2)
  | expr_add_2, expr_add_2 ⇒ true
  | _, _ ⇒ false
  end.

Global Instance ext_expr_Comparable : Comparable ext_expr.
  applys comparable_beq compare_ext_expr. intros x y.
  destruct x; destruct y; simpl; rew_refl; iff H; tryfalse; try congruence; auto.
Defined.

Definition compare_ext_stat s1 s2 :=
  match s1, s2 with
  | stat_asgn_1 x1, stat_asgn_1 x2 ⇒ decide (x1 = x2)
  | stat_seq_1 s1, stat_seq_1 s2 ⇒ decide (s1 = s2)
  | stat_if_1 s11 s21, stat_if_1 s12 s22 ⇒ decide (s11 = s12 ∧ s21 = s22)
  | stat_while_1 e1 s1, stat_while_1 e2 s2 ⇒ decide (e1 = e2 ∧ s1 = s2)
  | stat_while_2 e1 s1, stat_while_2 e2 s2 ⇒ decide (e1 = e2 ∧ s1 = s2)
  | stat_proc_call_1 f1, stat_proc_call_1 f2 ⇒ decide (f1 = f2)
  | _, _ ⇒ false
  end.

Global Instance ext_stat_Comparable : Comparable ext_stat.
  applys comparable_beq compare_ext_stat. intros x y.
  destruct x; destruct y; simpl; rew_refl; iff H; tryfalse; (fequals× || inverts× H).
Defined.

Fixpoint compare_prog p1 p2 : bool :=
  match p1, p2 with
  | prog_proc_decl f1 x1 s1 p1, prog_proc_decl f2 x2 s2 p2 ⇒
    decide (f1 = f2 ∧ x1 = x2 ∧ s1 = s2 ∧ compare_prog p1 p2)
  | prog_stat s1, prog_stat s2 ⇒ decide (s1 = s2)
  | _, _ ⇒ false
  end.

Global Instance prog_Comparable : Comparable prog.
  applys comparable_beq compare_prog.
  induction x; induction y; simpl; rew_refl; iff H; tryfalse; (fequals× || inverts× H).
   repeat inverts H as H. apply¬ IHx.
   splits¬. apply¬ IHx.
Defined.

Definition compare_terms p1 p2 :=
  match p1, p2 with
  | terms_expr e1, terms_expr e2 ⇒ decide (e1 = e2)
  | terms_ext_expr e1, terms_ext_expr e2 ⇒ decide (e1 = e2)
  | terms_stat s1, terms_stat s2 ⇒ decide (s1 = s2)
  | terms_ext_stat s1, terms_ext_stat s2 ⇒ decide (s1 = s2)
  | terms_prog p1, terms_prog p2 ⇒ decide (p1 = p2)
  | _, _ ⇒ false
  end.

Global Instance terms_Comparable : Comparable terms.
  applys comparable_beq compare_terms. intros x y.
  destruct x; destruct y; simpl; rew_refl; iff H; tryfalse; (fequals× || inverts× H).
Defined.


Inductive sub_expr_expr : expr → expr → Prop :=
  | sub_expr_expr_add_1 : ∀ e1 e2,
    sub_expr_expr e1 (expr_add e1 e2)
  | sub_expr_expr_add_2 : ∀ e1 e2,
    sub_expr_expr e2 (expr_add e1 e2)
  .

Global Instance sub_expr_expr_Decidable : ∀ e1 e2,
    Decidable (sub_expr_expr e1 e2).
  introv. destruct e2;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
  applys decidable_make (decide (e1 = e2_1 ∨ e1 = e2_2)).
  rewrite decide_def. cases_if as D; fold_bool; rew_refl.
   inverts D as [?|?]; substs; constructors.
   intro A; inverts¬ A.
Defined.

Inductive sub_expr_ext_expr : expr → ext_expr → Prop :=
  | sub_expr_ext_expr_add_1 : ∀ e,
    sub_expr_ext_expr e (expr_add_1 e)
  .

Global Instance sub_expr_ext_expr_Decidable : ∀ e1 e2,
    Decidable (sub_expr_ext_expr e1 e2).
  introv. destruct e2;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
  applys decidable_make (decide (e1 = e)).
  rewrite decide_def. cases_if as D; fold_bool; rew_refl.
   constructors.
   intro A; inverts¬ A.
Defined.

Inductive sub_expr_stat : expr → stat → Prop :=
  | sub_expr_stat_asgn : ∀ x e,
    sub_expr_stat e (stat_asgn x e)
  | sub_expr_stat_if : ∀ e s1 s2,
    sub_expr_stat e (stat_if e s1 s2)
  | sub_expr_stat_while : ∀ e s,
    sub_expr_stat e (stat_while e s)
  .

Global Instance sub_expr_stat_Decidable : ∀ e s,
    Decidable (sub_expr_stat e s).
  introv. destruct s;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
   applys decidable_make (decide (e = e0)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     constructors.
     intro A; inverts¬ A.
   applys decidable_make (decide (e = e0)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     constructors.
     intro A; inverts¬ A.
   applys decidable_make (decide (e = e0)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     constructors.
     intro A; inverts¬ A.
Defined.

Inductive sub_stat_stat : stat → stat → Prop :=
  | sub_stat_stat_seq_1 : ∀ s1 s2,
    sub_stat_stat s1 (stat_seq s1 s2)
  | sub_stat_stat_seq_2 : ∀ s1 s2,
    sub_stat_stat s2 (stat_seq s1 s2)
  | sub_stat_stat_if_1 : ∀ e s1 s2,
    sub_stat_stat s1 (stat_if e s1 s2)
  | sub_stat_stat_if_2 : ∀ e s1 s2,
    sub_stat_stat s2 (stat_if e s1 s2)
  | sub_stat_stat_while : ∀ e s,
    sub_stat_stat s (stat_while e s)
  .

Global Instance sub_stat_stat_Decidable : ∀ s1 s2,
    Decidable (sub_stat_stat s1 s2).
  introv. destruct s2;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
   applys decidable_make (decide (s1 = s2_1 ∨ s1 = s2_2)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     inverts D as [?|?]; substs; constructors.
     intro A; inverts¬ A.
   applys decidable_make (decide (s1 = s2_1 ∨ s1 = s2_2)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     inverts D as [?|?]; substs; constructors.
     intro A; inverts¬ A.
   applys decidable_make (decide (s1 = s2)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     constructors.
     intro A; inverts¬ A.
Defined.

Inductive sub_expr_ext_stat : expr → ext_stat → Prop :=
  | sub_expr_ext_stat_while_1 : ∀ e s,
    sub_expr_ext_stat e (stat_while_1 e s)
  | sub_expr_ext_stat_while_2 : ∀ e s,
    sub_expr_ext_stat e (stat_while_2 e s)
  .

Global Instance sub_expr_ext_stat_Decidable : ∀ e s,
    Decidable (sub_expr_ext_stat e s).
  introv. destruct s;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
   applys decidable_make (decide (e = e0)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     constructors.
     intro A; inverts¬ A.
   applys decidable_make (decide (e = e0)).
    rewrite decide_def. cases_if as D; fold_bool; rew_refl.
     constructors.
     intro A; inverts¬ A.
Defined.

Inductive sub_stat_ext_stat : stat → ext_stat → Prop :=
  | sub_stat_ext_stat_seq_1 : ∀ s,
    sub_stat_ext_stat s (stat_seq_1 s)
  | sub_stat_ext_stat_if_1_1 : ∀ s1 s2,
    sub_stat_ext_stat s1 (stat_if_1 s1 s2)
  | sub_stat_ext_stat_if_1_2 : ∀ s1 s2,
    sub_stat_ext_stat s2 (stat_if_1 s1 s2)
  | sub_stat_ext_stat_while_1 : ∀ e s,
    sub_stat_ext_stat s (stat_while_1 e s)
  | sub_stat_ext_stat_while_2 : ∀ e s,
    sub_stat_ext_stat s (stat_while_2 e s)
  .

Global Instance sub_stat_ext_stat_Decidable : ∀ s1 s2,
    Decidable (sub_stat_ext_stat s1 s2).
  introv. destruct s2;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
  applys decidable_make (decide (s1 = s)).
  rewrite decide_def. cases_if as D; fold_bool; rew_refl.
   constructors.
   intro A; inverts¬ A.
  applys decidable_make (decide (s1 = s ∨ s1 = s0)).
  rewrite decide_def. cases_if as D; fold_bool; rew_refl.
   inverts D as [?|?]; substs; constructors.
   intro A; inverts¬ A.
  applys decidable_make (decide (s1 = s)).
  rewrite decide_def. cases_if as D; fold_bool; rew_refl.
   constructors.
   intro A; inverts¬ A.
  applys decidable_make (decide (s1 = s)).
  rewrite decide_def. cases_if as D; fold_bool; rew_refl.
   constructors.
   intro A; inverts¬ A.
Defined.

Inductive sub_terms : terms → terms → Prop :=
  | sub_terms_expr_expr : ∀ e1 e2,
    sub_expr_expr e1 e2 →
    sub_terms e1 e2
  | sub_terms_expr_ext_expr : ∀ e1 e2,
    sub_expr_ext_expr e1 e2 →
    sub_terms e1 e2
  | sub_terms_expr_stat : ∀ e1 s2,
    sub_expr_stat e1 s2 →
    sub_terms e1 s2
  | sub_terms_expr_ext_stat : ∀ e1 s2,
    sub_expr_ext_stat e1 s2 →
    sub_terms e1 s2
  | sub_terms_stat_stat : ∀ s1 s2,
    sub_stat_stat s1 s2 →
    sub_terms s1 s2
  | sub_terms_stat_ext_stat : ∀ s1 s2,
    sub_stat_ext_stat s1 s2 →
    sub_terms s1 s2
  .

Global Instance sub_terms_Decidable : ∀ t1 t2,
    Decidable (sub_terms t1 t2).
  introv. destruct t1; destruct t2;
    try solve [ applys decidable_make false; fold_bool; rew_refl; intro A; inverts A ].
   applys decidable_make (decide (sub_expr_expr e e0)). rew_refl. apply eq_isTrue.
    iff S; [ constructors¬ | inverts¬ S ].
   applys decidable_make (decide (sub_expr_ext_expr e e0)). rew_refl. apply eq_isTrue.
    iff S; [ constructors¬ | inverts¬ S ].
   applys decidable_make (decide (sub_expr_stat e s)). rew_refl. apply eq_isTrue.
    iff S; [ constructors¬ | inverts¬ S ].
   applys decidable_make (decide (sub_expr_ext_stat e e0)). rew_refl. apply eq_isTrue.
    iff S; [ constructors¬ | inverts¬ S ].
   applys decidable_make (decide (sub_stat_stat s s0)). rew_refl. apply eq_isTrue.
    iff S; [ constructors¬ | inverts¬ S ].
   applys decidable_make (decide (sub_stat_ext_stat s e)). rew_refl. apply eq_isTrue.
    iff S; [ constructors¬ | inverts¬ S ].
Defined.

Structure


Inductive while_name :=
  | name_abort_ext_expr : ext_expr → while_name
  | name_abort_ext_stat : ext_stat → while_name
  | name_cst : Val → while_name
  | name_var : var → while_name
  | name_varCxt : var → while_name
  | name_varUndef : var → while_name
  | name_add : expr → expr → while_name
  | name_add_1 : expr → while_name
  | name_add_2 : while_name
  | name_skip : while_name
  | name_throw : while_name
  | name_asgn : var → expr → while_name
  | name_asgn_1 : var → while_name
  | name_asgn_1_immutable : var → while_name
  | name_seq : stat → stat → while_name
  | name_seq_1 : stat → while_name
  | name_if : expr → stat → stat → while_name
  | name_if_1_true : stat → stat → while_name
  | name_if_1_false : stat → stat → while_name
  | name_while : expr → stat → while_name
  | name_while_1 : expr → stat → while_name
  | name_while_2_true : expr → stat → while_name
  | name_while_2_false : expr → stat → while_name
  | name_proc_call : proc → expr → while_name
  | name_proc_call_1 : proc → var → stat → while_name
  | name_proc_call_1_undef : proc → while_name
  | name_proc_decl : proc → var → stat → prog → while_name
  | name_prog_stat : stat → while_name
  .

Definition while_struct n : Rule_struct terms :=
  match n with
  | name_abort_ext_expr e ⇒ Rule_struct_Ax _
  | name_abort_ext_stat s ⇒ Rule_struct_Ax _
  | name_cst c ⇒ Rule_struct_Ax _
  | name_var x ⇒ Rule_struct_Ax _
  | name_varCxt x ⇒ Rule_struct_Ax _
  | name_varUndef x ⇒ Rule_struct_Ax _
  | name_add e1 e2 ⇒ Rule_struct_R2 (term := terms) e1 (expr_add_1 e2)
  | name_add_1 e2 ⇒ Rule_struct_R2 (term := terms) e2 expr_add_2
  | name_add_2 ⇒ Rule_struct_Ax _
  | name_skip ⇒ Rule_struct_Ax _
  | name_throw ⇒ Rule_struct_Ax _
  | name_asgn x e ⇒ Rule_struct_R2 (term := terms) e (stat_asgn_1 x)
  | name_asgn_1 x ⇒ Rule_struct_Ax _
  | name_asgn_1_immutable x ⇒ Rule_struct_Ax _
  | name_seq s1 s2 ⇒ Rule_struct_R2 (term := terms) s1 (stat_seq_1 s2)
  | name_seq_1 s2 ⇒ Rule_struct_R1 (term := terms) s2
  | name_if e s1 s2 ⇒ Rule_struct_R2 (term := terms) e (stat_if_1 s1 s2)
  | name_if_1_true s1 s2 ⇒ Rule_struct_R1 (term := terms) s1
  | name_if_1_false s1 s2 ⇒ Rule_struct_R1 (term := terms) s2
  | name_while e s ⇒ Rule_struct_R1 (term := terms) (stat_while_1 e s)
  | name_while_1 e s ⇒ Rule_struct_R2 (term := terms) e (stat_while_2 e s)
  | name_while_2_true e s ⇒ Rule_struct_R2 (term := terms) s (stat_while_1 e s)
  | name_while_2_false e s ⇒ Rule_struct_Ax _
  | name_proc_call f e ⇒ Rule_struct_R2 (term := terms) e (stat_proc_call_1 f)
  | name_proc_call_1 f x s ⇒ Rule_struct_R1 (term := terms) s
  | name_proc_call_1_undef f ⇒ Rule_struct_Ax _
  | name_proc_decl f x s p ⇒ Rule_struct_R1 (term := terms) p
  | name_prog_stat s ⇒ Rule_struct_R1 (term := terms) s
  end.

Definition while_left n : terms :=
  match n with
  | name_abort_ext_expr e ⇒ e
  | name_abort_ext_stat s ⇒ s
  | name_cst c ⇒ expr_cst c
  | name_var x ⇒ expr_var x
  | name_varCxt x ⇒ expr_var x
  | name_varUndef x ⇒ expr_var x
  | name_add e1 e2 ⇒ expr_add e1 e2
  | name_add_1 e2 ⇒ expr_add_1 e2
  | name_add_2 ⇒ expr_add_2
  | name_skip ⇒ stat_skip
  | name_throw ⇒ stat_throw
  | name_asgn x e ⇒ stat_asgn x e
  | name_asgn_1 x ⇒ stat_asgn_1 x
  | name_asgn_1_immutable x ⇒ stat_asgn_1 x
  | name_seq s1 s2 ⇒ stat_seq s1 s2
  | name_seq_1 s2 ⇒ stat_seq_1 s2
  | name_if e s1 s2 ⇒ stat_if e s1 s2
  | name_if_1_true s1 s2 ⇒ stat_if_1 s1 s2
  | name_if_1_false s1 s2 ⇒ stat_if_1 s1 s2
  | name_while e s ⇒ stat_while e s
  | name_while_1 e s ⇒ stat_while_1 e s
  | name_while_2_true e s ⇒ stat_while_2 e s
  | name_while_2_false e s ⇒ stat_while_2 e s
  | name_proc_call f e ⇒ stat_proc_call f e
  | name_proc_call_1 f x s ⇒ stat_proc_call_1 f
  | name_proc_call_1_undef f ⇒ stat_proc_call_1 f
  | name_proc_decl f x s p ⇒ prog_proc_decl f x s p
  | name_prog_stat s ⇒ prog_stat s
  end.

Definition while_str := {|

    term := terms;
    name := while_name;

    rule_struct := while_struct;

    left := while_left

  |}.

Rules


Inductive error : Set :=
  | Err
  .

Definition CtxEnv := option (var × Val).

Definition Env := Heap.heap var Val.

Definition EnvV := (Env × CtxEnv)%type.

Definition EnvF := Heap.heap proc (var × stat).

Definition indomF (Ef : EnvF) f := Heap.indom Ef f.

Definition indom (E : Env) x := Heap.indom E x.

Definition writeF Ef f x s : EnvF := write Ef f (x, s).

Definition write E x v : Env := write E x v.

Definition EnvEmpty : Env := empty.

Definition EnvVEmpty : EnvV := (EnvEmpty, None).

Definition EnvFEmpty : EnvF := empty.

Inductive oute :=
  | oute_val : Val → oute
  | oute_error : error → oute
  .

Coercion oute_error : error >-> oute.

Definition is_val o :=
  match o with
  | oute_val v ⇒ True
  | oute_error err ⇒ False
  end.

Inductive aborte : oute → Prop :=
  | aborte_error : ∀ err,
    aborte (oute_error err)
  .

Inductive outs :=
  | outs_normal : Env → outs
  | outs_error : error → outs
  .

Coercion outs_error : error >-> outs.

Definition is_env o :=
  match o with
  | outs_normal E ⇒ True
  | outs_error err ⇒ False
  end.

Inductive ctx_ref : CtxEnv → var → Prop :=
  | ctx_ref_cons : ∀ x v,
      ctx_ref (Some (x, v)) x
  .

Inductive aborts : outs → Prop :=
  | aborts_error : ∀ err,
    aborts (outs_error err)
  .

Inductive while_res : Type :=
  | while_res_expr : oute → while_res
  | while_res_stat : outs → while_res
  .

Coercion while_res_expr : oute >-> while_res.
Coercion while_res_stat : outs >-> while_res.

Inductive abort_res : while_res → Prop :=
  | abort_res_expr : abort_res (while_res_expr Err)
  | abort_res_stat : abort_res (while_res_stat Err)
  .

Inductive while_st : Type :=
  | while_st_expr : EnvV → while_st
  | while_st_stat : EnvV → EnvF → while_st
  | while_st_prog : EnvV → EnvF → while_st
  | while_st_add_1 : EnvV → while_res → while_st
  | while_st_add_2 : Val → while_res → while_st
  | while_st_asgn_1 : EnvV → while_res → while_st
  | while_st_seq_1 : CtxEnv → EnvF → while_res → while_st
  | while_st_if_1 : EnvV → EnvF → while_res → while_st
  | while_st_while_1 : CtxEnv → EnvF → while_res → while_st
  | while_st_while_2 : EnvV → EnvF → while_res → while_st
  | while_st_proc_call_1 : EnvV → EnvF → while_res → while_st
  .

Inductive abort_st : while_st → Prop :=
  | abort_st_add_1 : ∀ Ev r,
    abort_res r →
    abort_st (while_st_add_1 Ev r)
  | abort_st_add_2 : ∀ v r,
    abort_res r →
    abort_st (while_st_add_2 v r)
  | abort_st_asgn_1 : ∀ Ev r,
    abort_res r →
    abort_st (while_st_asgn_1 Ev r)
  | abort_st_seq_1 : ∀ C Ef r,
    abort_res r →
    abort_st (while_st_seq_1 C Ef r)
  | abort_st_if_1 : ∀ Ev Ef r,
    abort_res r →
    abort_st (while_st_if_1 Ev Ef r)
  | abort_st_while_1 : ∀ C Ef r,
    abort_res r →
    abort_st (while_st_while_1 C Ef r)
  | abort_st_while_2 : ∀ Ev Ef r,
    abort_res r →
    abort_st (while_st_while_2 Ev Ef r)
  | abort_st_proc_call_1 : ∀ Ev Ef r,
    abort_res r →
    abort_st (while_st_proc_call_1 Ev Ef r)
  .

Definition while_cond n sigma : Prop :=
  match n, sigma with
  | name_abort_ext_expr e, sigma ⇒
      abort_st sigma
  | name_abort_ext_stat s, sigma ⇒
      abort_st sigma
  | name_cst c, while_st_expr Ev ⇒
      True
  | name_var x, while_st_expr (E, C) ⇒
      indom E x
  | name_varCxt x, while_st_expr (E, Some (y, v)) ⇒
      x = y
  | name_varUndef x, while_st_expr (E, C) ⇒
      (∀ v, C ≠ Some (x, v)) ∧
      ¬ indom E x
  | name_add e1 e2, while_st_expr Ev ⇒
      True
  | name_add_1 e2, while_st_add_1 Ev r ⇒
      ∃ o, r = while_res_expr o ∧ is_val o
  | name_add_2, while_st_add_2 v r ⇒
      ∃ o, r = while_res_expr o ∧ is_val o
  | name_skip, while_st_stat Ev Ef ⇒
      True
  | name_throw, while_st_stat Ev Ef ⇒
      True
  | name_asgn x e, while_st_stat Ev Ef ⇒
      True
  | name_asgn_1 x, while_st_asgn_1 (E, C) r ⇒
      ¬ ctx_ref C x ∧
      ∃ o, r = while_res_expr o ∧ is_val o
  | name_asgn_1_immutable x, while_st_asgn_1 (E, C) r ⇒
      ctx_ref C x ∧
      ∃ o, r = while_res_expr o ∧ is_val o
  | name_seq s1 s2, while_st_stat Ev Ef ⇒
      True
  | name_seq_1 s2, while_st_seq_1 C Ef r ⇒
      ∃ o, r = while_res_stat o ∧ is_env o
  | name_if e s1 s2, while_st_stat Ev Ef ⇒
      True
  | name_if_1_true s1 s2, while_st_if_1 Ev Ef o ⇒
      ∃ v, v ≠ 0 ∧ o = oute_val v
  | name_if_1_false s1 s2, while_st_if_1 Ev Ef o ⇒
      o = oute_val 0
  | name_while e s, while_st_stat Ev Ef ⇒
      True
  | name_while_1 e s, while_st_while_1 C Ef r ⇒
      ∃ o, r = while_res_stat o ∧ is_env o
  | name_while_2_true e s, while_st_while_2 Ev Ef o ⇒
      ∃ v, v ≠ 0 ∧ o = oute_val v
  | name_while_2_false e s, while_st_while_2 Ev Ef o ⇒
      o = oute_val 0
  | name_proc_call f e, while_st_stat Ev Ef ⇒
      True
  | name_proc_call_1 f x s, while_st_proc_call_1 Ev Ef r ⇒
      binds Ef f (x, s) ∧
      ∃ o, r = while_res_expr o ∧ is_val o
  | name_proc_call_1_undef f, while_st_proc_call_1 Ev Ef r ⇒
      ¬ indomF Ef f ∧
      ∃ o, r = while_res_expr o ∧ is_val o
  | name_proc_decl f x s p, while_st_prog Ev Ef ⇒
      True
  | name_prog_stat s, while_st_prog Ev Ef ⇒
      True
  | _, _ ⇒
      False
  end.

Monads

Definition if_st_expr A (f : _ → _ → option A) sigma :=
  match sigma with
  | while_st_expr (E, C) ⇒ f E C
  | _ ⇒ None
  end.

Definition if_st_stat A (f : _ → _ → option A) sigma :=
  match sigma with
  | while_st_stat Ev Ef ⇒ f Ev Ef
  | _ ⇒ None
  end.

Definition if_st_prog A (f : _ → _ → option A) sigma :=
  match sigma with
  | while_st_prog Ev Ef ⇒ f Ev Ef
  | _ ⇒ None
  end.

Definition if_res_expr A (f : _ → option A) r :=
  match r with
  | while_res_expr o ⇒ f o
  | _ ⇒ None
  end.

Definition if_res_stat A (f : _ → option A) r :=
  match r with
  | while_res_stat o ⇒ f o
  | _ ⇒ None
  end.

Definition while_rule n : Rule while_st while_res :=
  match n with
  | name_abort_ext_expr e ⇒
    let ax _ := Some (while_res_expr Err) in
    Rule_Ax ax
  | name_abort_ext_stat s ⇒
    let ax _ := Some (while_res_stat Err) in
    Rule_Ax ax
  | name_cst c ⇒
    let ax _ := Some (oute_val c : while_res) in
    Rule_Ax ax
  | name_var x ⇒
    let ax :=
      if_st_expr (fun E C ⇒
        option_map (oute_val : _ → while_res) (read_option E x)) in
    Rule_Ax ax
  | name_varCxt x ⇒
    let ax :=
      if_st_expr (fun E C ⇒
        option_map (fun Cd ⇒ oute_val (snd Cd) : while_res) C) in
    Rule_Ax ax
  | name_varUndef x ⇒
    let ax _ := Some (Err : while_res) in
    Rule_Ax ax
  | name_add e1 e2 ⇒
    let up :=
      if_st_expr (fun E C ⇒
        Some (while_st_expr (E, C))) in
    let next sigma o :=
      if_st_expr (fun E C ⇒
        Some (while_st_add_1 (E, C) o)) sigma in
    Rule_R2 up next
  | name_add_1 e2 ⇒
    let up sigma :=
      match sigma with
      | while_st_add_1 E o ⇒ Some (while_st_expr E)
      | _ ⇒ None
      end in
    let next sigma r :=
      match sigma with
      | while_st_add_1 E (oute_val v) ⇒ Some (while_st_add_2 v r)
      | _ ⇒ None
      end in
    Rule_R2 up next
  | name_add_2 ⇒
    let ax sigma :=
      match sigma with
      | while_st_add_2 v1 (oute_val v2) ⇒ Some (oute_val (v1 + v2) : while_res)
      | _ ⇒ None
      end in
    Rule_Ax ax
  | name_skip ⇒
    let ax :=
      if_st_stat (fun Ev Ef ⇒
        Some (outs_normal (fst Ev) : while_res)) in
    Rule_Ax ax
  | name_throw ⇒
    let ax _ := Some (while_res_stat Err) in
    Rule_Ax ax
  | name_asgn x e ⇒
    let up :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_expr Ev)) in
    let next sigma r :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_asgn_1 Ev r)) sigma in
    Rule_R2 up next
  | name_asgn_1 x ⇒
    let ax sigma :=
      match sigma with
      | while_st_asgn_1 (E, C) (oute_val v) ⇒
        Some (outs_normal (write E x v) : while_res)
      | _ ⇒ None
      end in
    Rule_Ax ax
  | name_asgn_1_immutable x ⇒
    let ax _ := Some (while_res_stat Err) in
    Rule_Ax ax
  | name_seq s1 s2 ⇒
    let up :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_stat Ev Ef)) in
    let next sigma r :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_seq_1 (snd Ev) Ef r)) sigma in
    Rule_R2 up next
  | name_seq_1 s2 ⇒
    let up sigma :=
      match sigma with
      | while_st_seq_1 C Ef (outs_normal E) ⇒ Some (while_st_stat (E, C) Ef)
      | _ ⇒ None
      end in
    Rule_R1 _ up
  | name_if e s1 s2 ⇒
    let up :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_expr Ev)) in
    let next sigma r :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_if_1 Ev Ef r)) sigma in
    Rule_R2 up next
  | name_if_1_true s1 s2 ⇒
    let up sigma :=
      match sigma with
      | while_st_if_1 Ev Ef o ⇒ Some (while_st_stat Ev Ef)
      | _ ⇒ None
      end in
    Rule_R1 _ up
  | name_if_1_false s1 s2 ⇒
    let up sigma :=
      match sigma with
      | while_st_if_1 Ev Ef o ⇒ Some (while_st_stat Ev Ef)
      | _ ⇒ None
      end in
    Rule_R1 _ up
  | name_while e s ⇒
    let up :=
      if_st_stat (fun Ev Ef ⇒
        let (E, C) := Ev in
        Some (while_st_while_1 C Ef (outs_normal E))) in
    Rule_R1 _ up
  | name_while_1 e s ⇒
    let up sigma :=
      match sigma with
      | while_st_while_1 C Ef (while_res_stat (outs_normal E)) ⇒
        Some (while_st_expr (E, C))
      | _ ⇒ None
      end in
    let next sigma r :=
      match sigma with
      | while_st_while_1 C Ef (while_res_stat (outs_normal E)) ⇒
        Some (while_st_while_2 (E, C) Ef r)
      | _ ⇒ None
      end in
    Rule_R2 up next
  | name_while_2_true e s ⇒
    let up sigma :=
      match sigma with
      | while_st_while_2 Ev Ef r ⇒ Some (while_st_stat Ev Ef)
      | _ ⇒ None
      end in
    let next sigma r :=
      match sigma with
      | while_st_while_2 Ev Ef _ ⇒ Some (while_st_while_1 (snd Ev) Ef r)
      | _ ⇒ None
      end in
    Rule_R2 up next
  | name_while_2_false e s ⇒
    let ax sigma :=
      match sigma with
      | while_st_while_2 (E, C) Ef o ⇒ Some (outs_normal E : while_res)
      | _ ⇒ None
      end in
    Rule_Ax ax
  | name_proc_call f e ⇒
    let up :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_expr Ev)) in
    let next sigma r :=
      if_st_stat (fun Ev Ef ⇒
        Some (while_st_proc_call_1 Ev Ef r)) sigma in
    Rule_R2 up next
  | name_proc_call_1 f x s ⇒
    let up sigma :=
      match sigma with
      | while_st_proc_call_1 (E, C) Ef (oute_val v) ⇒
        let C := Some (x, v) in
        Some (while_st_stat (E, C) Ef)
      | _ ⇒ None
      end in
    Rule_R1 _ up
  | name_proc_call_1_undef f ⇒
    let ax _ := Some (while_res_stat Err) in
    Rule_Ax ax
  | name_proc_decl f x s p ⇒
    let up :=
      if_st_prog (fun Ev Ef ⇒
        let Ef := writeF Ef f x s in
        Some (while_st_prog Ev Ef)) in
    Rule_R1 _ up
  | name_prog_stat s ⇒
    let up :=
      if_st_prog (fun Ev Ef ⇒
        Some (while_st_stat Ev Ef)) in
    Rule_R1 _ up
  end.

Definition while_sem :=
  make_semantics while_str while_cond while_rule.

Lemma while_rule_format_correct : rule_format_correct_all while_sem.
Proof. intro n. destruct n; constructors. Qed.

Lemma while_semantics_full : semantics_full while_sem.
Proof.
  introv C. simpls. destruct n; destruct sigma; simpls; tryfalse; try solve [ constructors¬ ].
  destruct e as [E Ct]. constructors¬. simpl. rewrite read_option_def.
  cases_if; simpls¬. false¬ C.
  destruct e as [E Ct]. destruct Ct as [[y va]|]; tryfalse. substs¬.
  constructors¬. simpls¬.
  destruct e1 as [E Ct]. constructors¬.
   simpls¬.
   introv. eexists. reflexivity.
  constructors¬. introv. lets (o&E&V): (rm C). substs.
  destruct o as [v|]; tryfalse. eexists. reflexivity.
  lets (o&E&V): (rm C). substs. destruct o as [v2|]; tryfalse. constructors¬.
  constructors¬. reflexivity.
  constructors¬.
   simpls¬.
   introv. eexists. reflexivity.
  destruct e as [E Ct]. lets (NC&o&Eq&V): (rm C). substs.
  destruct o as [v2|]; tryfalse. constructors¬.
  constructors¬.
   simpls¬.
   introv. eexists. reflexivity.
  lets (o&Eq&V): (rm C). substs. destruct o as [E|]; tryfalse. constructors¬.
  constructors¬.
   simpls¬.
   introv. eexists. reflexivity.
  destruct e0 as [E Ct]. constructors¬. simpls¬.
  lets (o&Eq&V): (rm C). substs. destruct o as [E|]; tryfalse. constructors¬.
  introv. eexists. reflexivity.
  lets (o&Nz&Eq): (rm C). substs. constructors¬.
  introv. eexists. reflexivity.
  destruct e0 as [E Ct]. substs. constructors¬.
  constructors¬.
   simpls¬.
   introv. eexists. reflexivity.
  destruct e as [E Ct]. lets (R&o&Eq&V): (rm C). destruct o as [va|]; tryfalse.
  substs. constructors¬.
  constructors¬. simpls¬.
  constructors¬. reflexivity.
Qed.

On A Concrete Term


Definition prog_test0 : terms :=
  
  (prog_stat
    (stat_seq
      (stat_seq
         (stat_asgn "a" (expr_cst 6))
         (stat_asgn "b" (expr_cst 7)))
      (stat_seq
         (stat_seq
            (stat_asgn "n" (expr_var "a"))
            (stat_asgn "res" (expr_cst 0)))
         (stat_while (expr_var "n")
            (stat_seq
               (stat_asgn "res" (expr_add (expr_var "res") (expr_var "b")))
               (stat_asgn "n" (expr_add (expr_var "n") (expr_cst (0-1)))))))))%string
  .

Definition prog_test1 : terms :=
  prog_stat (stat_asgn "x"%string (expr_cst 42)).

Definition prog_test2 : terms :=
  prog_stat
    (stat_if (expr_add (expr_var "x"%string) (expr_cst 1))
      (stat_asgn "y"%string (expr_cst (-1)%Z))
      (stat_asgn "y"%string (expr_var "x"%string))).

Definition prog_test3 : terms :=
  prog_stat
    (stat_if (expr_var "x"%string)
      (stat_asgn "y"%string (expr_cst 0))
      (stat_asgn "y"%string (expr_var "x"%string))).

Definition prog_test4 : terms :=
  prog_stat
    (stat_if (expr_var "x"%string)
      (stat_asgn "x"%string (expr_cst 0))
      stat_skip).

Definition prog_test5 : terms :=
  prog_stat
    (stat_while (expr_var "x"%string)
      (stat_asgn "x"%string (expr_add (expr_var "x"%string) (expr_cst 1)))).

Definition prog_test6 : terms :=
  prog_stat
    (stat_while (expr_cst 0)
      (stat_asgn "x"%string (expr_cst 42))).

Definition prog_test7 : terms :=
  prog_stat
    (stat_while (expr_cst 1)
       (stat_asgn "x"%string (expr_cst 42))).

Definition prog_test8 : terms :=
  prog_stat
    (stat_asgn "x"%string
       (expr_add (expr_cst 42) (expr_add (expr_cst 18) (expr_cst 17)))).

Definition prog_test9 : terms :=
  prog_stat
    (stat_seq
      (stat_asgn "x" (expr_cst 1))
      (stat_while (expr_var "x")
        (stat_asgn "x" (expr_cst 0))))%string.

Definition prog_test10 : terms :=
  prog_stat
    (stat_seq
      (stat_seq
          (stat_asgn "x" (expr_cst 1))
          (stat_seq
            (stat_asgn "y" (expr_cst 1))
            (stat_asgn "z" (expr_cst 1))))
     (stat_while (expr_var "x")
       (stat_seq
          (stat_asgn "x" (expr_var "y"))
          (stat_seq
            (stat_asgn "y" (expr_var "z"))
            (stat_asgn "z" (expr_cst 0))))))%string.

Definition prog_test11 : terms :=
  prog_stat (stat_if (expr_var "x"%string) stat_throw stat_skip).

Definition prog_test12 : terms :=
  prog_stat
    (stat_seq
      (stat_seq
          (stat_asgn "x" (expr_cst 1))
          (stat_seq
            (stat_asgn "y" (expr_cst 1))
            (stat_asgn "z" (expr_cst 1))))
     (stat_while (expr_var "z")
       (stat_seq
          (stat_if (expr_var "y")
            (stat_asgn "z" (expr_cst 0))
            stat_skip)
        (stat_seq
           (stat_if (expr_var "x")
             (stat_asgn "y" (expr_cst 0))
             stat_skip)
           (stat_asgn "x" (expr_cst 0))))))%string.

Definition prog_test13 : terms :=
  prog_stat
    (stat_seq
      (stat_asgn "a" (expr_cst 5))
      (stat_while (expr_var "a")
        (stat_seq
          (stat_seq
            (stat_asgn "b" (expr_cst 5))
            (stat_while (expr_var "b")
              (stat_seq
                (stat_seq
                  (stat_asgn "c" (expr_cst 5))
                  (stat_while (expr_var "c")
                    (stat_seq
                      (stat_asgn "x" (expr_add (expr_var "x") (expr_var "c")))
                      (stat_asgn "c" (expr_add (expr_var "c") (expr_cst (-1)%Z))))))
                (stat_asgn "b" (expr_add (expr_var "b") (expr_cst (-1)%Z))))))
          (stat_asgn "a" (expr_add (expr_var "a") (expr_cst (-1)%Z))))))%string.

Definition prog_test14 : terms :=
  prog_stat
    (stat_seq
       (stat_seq
          (stat_asgn "y" (expr_cst 0))
          (stat_asgn "x" (expr_cst 18)))
       (stat_while (expr_var "x")
         (stat_seq
           (stat_asgn "x" (expr_add (expr_var "x") (expr_cst (-1)%Z)))
           (stat_asgn "y" (expr_add (expr_var "y") (expr_cst 1))))))%string.

Definition prog_test15 : terms :=
  (prog_proc_decl "f" "x"
    (stat_proc_call "g" (expr_cst 1))
  (prog_proc_decl "g" "x"
    (stat_proc_call "h" (expr_var "x"))
  (prog_proc_decl "h" "y"
    (stat_proc_call "f" (expr_var "x"))
  (prog_stat
    (stat_seq
      (stat_asgn "x" (expr_cst 0))
      (stat_proc_call "g" (expr_cst (-1)%Z)))))))%string.

Definition prog_test16 : terms :=
  (prog_proc_decl "triangle" "x"
    (stat_if (expr_var "x")
      (stat_seq
        (stat_proc_call "triangle" (expr_add (expr_var "x") (expr_cst (-1)%Z)))
        (stat_asgn "res" (expr_add (expr_var "res") (expr_var "x"))))
      (stat_asgn "res" (expr_cst 0)))
  (prog_stat
    (stat_proc_call "triangle" (expr_cst 42))))%string.

Definition prog_test17 : terms :=
  (prog_proc_decl "f" "l"
    (stat_while (expr_var "y")
      (stat_seq
        (stat_asgn "y" (expr_add (expr_var "y") (expr_cst (-1)%Z)))
        (stat_if (expr_var "x")
          (stat_proc_call "f" (expr_cst 42))
          stat_skip)))
  (prog_stat
    (stat_seq
      (stat_asgn "y" (expr_cst 42))
      (stat_proc_call "f" (expr_cst 18)))))%string.

Definition prog_test18 : terms :=
  
  (prog_proc_decl "prod" "n"
    (stat_if (expr_var "n")
      (stat_seq
        (stat_proc_call "prod" (expr_add (expr_var "n") (expr_cst (-1)%Z)))
        (stat_asgn "res" (expr_add (expr_var "res") (expr_var "b"))))
      (stat_asgn "res" (expr_cst 0)))
  (prog_stat
    (stat_seq
      (stat_seq
        (stat_asgn "a" (expr_cst 6))
        (stat_asgn "b" (expr_cst 7)))
      (stat_proc_call "prod" (expr_var "a")))))%string.

Definition prog_test19 : terms :=
  (prog_proc_decl "id" "x"
    (stat_asgn "res" (expr_var "x"))
  (prog_stat
    (stat_seq
      (stat_seq
        (stat_proc_call "id" (expr_cst 42))
        (stat_asgn "r1" (expr_var "res")))
    (stat_seq
      (stat_seq
        (stat_proc_call "id" (expr_cst (-1)%Z))
        (stat_asgn "r2" (expr_var "res")))
    (stat_seq
      (stat_seq
        (stat_proc_call "id" (expr_cst 0))
        (stat_asgn "r3" (expr_var "res")))
    (stat_seq
      (stat_seq
        (stat_proc_call "id" (expr_cst 18))
        (stat_seq
          (stat_proc_call "id" (expr_var "res"))
          (stat_proc_call "id" (expr_var "res"))))
        (stat_asgn "r4" (expr_var "res"))))))))%string.

Definition prog_test20 : terms :=
  (prog_proc_decl "f" "x"
    (stat_if (expr_var "x")
      (stat_asgn "res" (expr_cst 0))
      (stat_asgn "res" (expr_var "x")))
  (prog_stat
    (stat_seq
      (stat_seq
        (stat_proc_call "f" (expr_cst 42))
        (stat_asgn "r1" (expr_var "res")))
    (stat_seq
      (stat_seq
        (stat_proc_call "f" (expr_cst (-1)%Z))
        (stat_asgn "r2" (expr_var "res")))
    (stat_seq
      (stat_seq
        (stat_proc_call "f" (expr_cst 0))
        (stat_asgn "r3" (expr_var "res")))
    (stat_seq
      (stat_seq
        (stat_proc_call "f" (expr_cst 18))
        (stat_seq
          (stat_proc_call "f" (expr_var "res"))
          (stat_proc_call "f" (expr_var "res"))))
        (stat_asgn "r4" (expr_var "res"))))))))%string.

Definition prog_test21 : terms :=
  (prog_stat
    (stat_proc_call "undefined_proc" (expr_cst 42)))%string.

Definition prog_test22 : terms :=
  (prog_stat
    (stat_seq
      (stat_if (expr_var "x")
        (stat_asgn "y" (expr_cst (-1)%Z))
        (stat_asgn "y" (expr_cst 1)))
    (stat_seq
      (stat_if (expr_var "y")
        (stat_if (expr_var "x")
          (stat_asgn "z" (expr_cst 1))
          (stat_asgn "z" (expr_cst (-1)%Z)))
        stat_throw)
      (stat_if (expr_add (expr_var "y") (expr_var "z"))
        (stat_asgn "a" (expr_cst 1))
        (stat_asgn "a" (expr_cst 0))))))%string.

Lemma prog_test1_effect :
  eval while_sem prog_test1
    (while_st_prog EnvVEmpty EnvFEmpty)
    (outs_normal (write EnvEmpty "x"%string 42)).
Proof.
  eapply eval_cons with (n := name_prog_stat _).
    reflexivity.
    exact I.
  apply× apply_R1.
  eapply eval_cons with (n := name_asgn _ _).
    reflexivity.
    exact I.
  apply× apply_R2.
   eapply eval_cons with (n := name_cst _).
    reflexivity.
    exact I.
    apply× apply_Ax.
   eapply eval_cons with (n := name_asgn_1 _).
      reflexivity.
      split.
       intro A. inverts A.
       eexists. splits¬. exact I.
    apply× apply_Ax.
Qed.

Lemma prog_test6_effect :
  eval while_sem prog_test6
    (while_st_prog EnvVEmpty EnvFEmpty)
    (while_res_stat (outs_normal EnvEmpty)).
Proof.
  eapply eval_cons with (n := name_prog_stat _).
    reflexivity.
    exact I.
  apply× apply_R1.
  eapply eval_cons with (n := name_while _ _).
    reflexivity.
    exact I.
  apply× apply_R1.
   eapply eval_cons with (n := name_while_1 _ _).
     reflexivity.
     eexists. splits¬. constructors.
   apply× apply_R2.
    eapply eval_cons with (n := name_cst _).
      reflexivity.
      exact I.
     apply× apply_Ax.
    eapply eval_cons with (n := name_while_2_false _ _).
      reflexivity.
      reflexivity.
     apply× apply_Ax.
Qed.

End ConcreteExample.

We can even have a derivation tree using the following lines:
Extraction Language Ocaml. Require Export ExtrOcamlBasic. Require Export ExtrOcamlNatInt. Require Export ExtrOcamlString. Extraction prog_test1_effect.