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 : Valexpr
  | expr_var : varexpr
  | expr_add : exprexprexpr
  .

Inductive ext_expr :=
  | expr_add_1 : exprext_expr
  | expr_add_2 : ext_expr
  .

Inductive stat :=
  | stat_skip : stat
  | stat_asgn : varexprstat
  | stat_seq : statstatstat
  | stat_if : exprstatstatstat
  | stat_while : exprstatstat
  | stat_throw : stat
  | stat_proc_call : procexprstat
  .

Inductive ext_stat :=
  | stat_asgn_1 : varext_stat
  | stat_seq_1 : statext_stat
  | stat_if_1 : statstatext_stat
  | stat_while_1 : exprstatext_stat
  | stat_while_2 : exprstatext_stat
  | stat_proc_call_1 : procext_stat
  .

Inductive prog :=
  | prog_proc_decl : procvarstatprogprog
  | prog_stat : statprog
  .

Inductive terms :=
  | terms_expr : exprterms
  | terms_ext_expr : ext_exprterms
  | terms_stat : statterms
  | terms_ext_stat : ext_statterms
  | terms_prog : progterms
  .

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 c2decide (c1 = c2)
  | expr_var x1, expr_var x2decide (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_skiptrue
  | stat_asgn x1 e1, stat_asgn x2 e2decide (x1 = x2e1 = 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_throwtrue
  | stat_proc_call f1 e1, stat_proc_call f2 e2decide (f1 = f2e1 = 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 e2decide (e1 = e2)
  | expr_add_2, expr_add_2true
  | _, _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 x2decide (x1 = x2)
  | stat_seq_1 s1, stat_seq_1 s2decide (s1 = s2)
  | stat_if_1 s11 s21, stat_if_1 s12 s22decide (s11 = s12s21 = s22)
  | stat_while_1 e1 s1, stat_while_1 e2 s2decide (e1 = e2s1 = s2)
  | stat_while_2 e1 s1, stat_while_2 e2 s2decide (e1 = e2s1 = s2)
  | stat_proc_call_1 f1, stat_proc_call_1 f2decide (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 = f2x1 = x2s1 = s2compare_prog p1 p2)
  | prog_stat s1, prog_stat s2decide (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 e2decide (e1 = e2)
  | terms_ext_expr e1, terms_ext_expr e2decide (e1 = e2)
  | terms_stat s1, terms_stat s2decide (s1 = s2)
  | terms_ext_stat s1, terms_ext_stat s2decide (s1 = s2)
  | terms_prog p1, terms_prog p2decide (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 : exprexprProp :=
  | 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_1e1 = 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 : exprext_exprProp :=
  | 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 : exprstatProp :=
  | 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 : statstatProp :=
  | 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_1s1 = 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_1s1 = 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 : exprext_statProp :=
  | 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 : statext_statProp :=
  | 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 = ss1 = 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 : termstermsProp :=
  | 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_exprwhile_name
  | name_abort_ext_stat : ext_statwhile_name
  | name_cst : Valwhile_name
  | name_var : varwhile_name
  | name_varCxt : varwhile_name
  | name_varUndef : varwhile_name
  | name_add : exprexprwhile_name
  | name_add_1 : exprwhile_name
  | name_add_2 : while_name
  | name_skip : while_name
  | name_throw : while_name
  | name_asgn : varexprwhile_name
  | name_asgn_1 : varwhile_name
  | name_asgn_1_immutable : varwhile_name
  | name_seq : statstatwhile_name
  | name_seq_1 : statwhile_name
  | name_if : exprstatstatwhile_name
  | name_if_1_true : statstatwhile_name
  | name_if_1_false : statstatwhile_name
  | name_while : exprstatwhile_name
  | name_while_1 : exprstatwhile_name
  | name_while_2_true : exprstatwhile_name
  | name_while_2_false : exprstatwhile_name
  | name_proc_call : procexprwhile_name
  | name_proc_call_1 : procvarstatwhile_name
  | name_proc_call_1_undef : procwhile_name
  | name_proc_decl : procvarstatprogwhile_name
  | name_prog_stat : statwhile_name
  .

Definition while_struct n : Rule_struct terms :=
  match n with
  | name_abort_ext_expr eRule_struct_Ax _
  | name_abort_ext_stat sRule_struct_Ax _
  | name_cst cRule_struct_Ax _
  | name_var xRule_struct_Ax _
  | name_varCxt xRule_struct_Ax _
  | name_varUndef xRule_struct_Ax _
  | name_add e1 e2Rule_struct_R2 (term := terms) e1 (expr_add_1 e2)
  | name_add_1 e2Rule_struct_R2 (term := terms) e2 expr_add_2
  | name_add_2Rule_struct_Ax _
  | name_skipRule_struct_Ax _
  | name_throwRule_struct_Ax _
  | name_asgn x eRule_struct_R2 (term := terms) e (stat_asgn_1 x)
  | name_asgn_1 xRule_struct_Ax _
  | name_asgn_1_immutable xRule_struct_Ax _
  | name_seq s1 s2Rule_struct_R2 (term := terms) s1 (stat_seq_1 s2)
  | name_seq_1 s2Rule_struct_R1 (term := terms) s2
  | name_if e s1 s2Rule_struct_R2 (term := terms) e (stat_if_1 s1 s2)
  | name_if_1_true s1 s2Rule_struct_R1 (term := terms) s1
  | name_if_1_false s1 s2Rule_struct_R1 (term := terms) s2
  | name_while e sRule_struct_R1 (term := terms) (stat_while_1 e s)
  | name_while_1 e sRule_struct_R2 (term := terms) e (stat_while_2 e s)
  | name_while_2_true e sRule_struct_R2 (term := terms) s (stat_while_1 e s)
  | name_while_2_false e sRule_struct_Ax _
  | name_proc_call f eRule_struct_R2 (term := terms) e (stat_proc_call_1 f)
  | name_proc_call_1 f x sRule_struct_R1 (term := terms) s
  | name_proc_call_1_undef fRule_struct_Ax _
  | name_proc_decl f x s pRule_struct_R1 (term := terms) p
  | name_prog_stat sRule_struct_R1 (term := terms) s
  end.

Definition while_left n : terms :=
  match n with
  | name_abort_ext_expr ee
  | name_abort_ext_stat ss
  | name_cst cexpr_cst c
  | name_var xexpr_var x
  | name_varCxt xexpr_var x
  | name_varUndef xexpr_var x
  | name_add e1 e2expr_add e1 e2
  | name_add_1 e2expr_add_1 e2
  | name_add_2expr_add_2
  | name_skipstat_skip
  | name_throwstat_throw
  | name_asgn x estat_asgn x e
  | name_asgn_1 xstat_asgn_1 x
  | name_asgn_1_immutable xstat_asgn_1 x
  | name_seq s1 s2stat_seq s1 s2
  | name_seq_1 s2stat_seq_1 s2
  | name_if e s1 s2stat_if e s1 s2
  | name_if_1_true s1 s2stat_if_1 s1 s2
  | name_if_1_false s1 s2stat_if_1 s1 s2
  | name_while e sstat_while e s
  | name_while_1 e sstat_while_1 e s
  | name_while_2_true e sstat_while_2 e s
  | name_while_2_false e sstat_while_2 e s
  | name_proc_call f estat_proc_call f e
  | name_proc_call_1 f x sstat_proc_call_1 f
  | name_proc_call_1_undef fstat_proc_call_1 f
  | name_proc_decl f x s pprog_proc_decl f x s p
  | name_prog_stat sprog_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 : Valoute
  | oute_error : erroroute
  .

Coercion oute_error : error >-> oute.

Definition is_val o :=
  match o with
  | oute_val vTrue
  | oute_error errFalse
  end.

Inductive aborte : outeProp :=
  | aborte_error : err,
    aborte (oute_error err)
  .

Inductive outs :=
  | outs_normal : Envouts
  | outs_error : errorouts
  .

Coercion outs_error : error >-> outs.

Definition is_env o :=
  match o with
  | outs_normal ETrue
  | outs_error errFalse
  end.

Inductive ctx_ref : CtxEnvvarProp :=
  | ctx_ref_cons : x v,
      ctx_ref (Some (x, v)) x
  .

Inductive aborts : outsProp :=
  | aborts_error : err,
    aborts (outs_error err)
  .

Inductive while_res : Type :=
  | while_res_expr : outewhile_res
  | while_res_stat : outswhile_res
  .

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

Inductive abort_res : while_resProp :=
  | 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 : EnvVwhile_st
  | while_st_stat : EnvVEnvFwhile_st
  | while_st_prog : EnvVEnvFwhile_st
  | while_st_add_1 : EnvVwhile_reswhile_st
  | while_st_add_2 : Valwhile_reswhile_st
  | while_st_asgn_1 : EnvVwhile_reswhile_st
  | while_st_seq_1 : CtxEnvEnvFwhile_reswhile_st
  | while_st_if_1 : EnvVEnvFwhile_reswhile_st
  | while_st_while_1 : CtxEnvEnvFwhile_reswhile_st
  | while_st_while_2 : EnvVEnvFwhile_reswhile_st
  | while_st_proc_call_1 : EnvVEnvFwhile_reswhile_st
  .

Inductive abort_st : while_stProp :=
  | 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, CSome (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 ois_val o
  | name_add_2, while_st_add_2 v r
       o, r = while_res_expr ois_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 ois_val o
  | name_asgn_1_immutable x, while_st_asgn_1 (E, C) r
      ctx_ref C x
       o, r = while_res_expr ois_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 ois_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 ois_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 ois_val o
  | name_proc_call_1_undef f, while_st_proc_call_1 Ev Ef r
      ¬ indomF Ef f
       o, r = while_res_expr ois_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 Eff Ev Ef
  | _None
  end.

Definition if_st_prog A (f : __option A) sigma :=
  match sigma with
  | while_st_prog Ev Eff Ev Ef
  | _None
  end.

Definition if_res_expr A (f : _option A) r :=
  match r with
  | while_res_expr of o
  | _None
  end.

Definition if_res_stat A (f : _option A) r :=
  match r with
  | while_res_stat of 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 Cdoute_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 oSome (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 oSome (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 oSome (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 rSome (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 oSome (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.