Commit cab3db52 authored by Dan Frumin's avatar Dan Frumin
Browse files

Merge branch 'bind'

parents 6678f0c8 772ff880
...@@ -9,7 +9,7 @@ Inductive dloc := ...@@ -9,7 +9,7 @@ Inductive dloc :=
| dLoc : nat nat dloc (* index * offset *) | dLoc : nat nat dloc (* index * offset *)
| dLocUnknown : cloc dloc. | dLocUnknown : cloc dloc.
Global Instance dloc_decision : EqDecision dloc. Global Instance dloc_eq_dec : EqDecision dloc.
Proof. solve_decision. Defined. Proof. solve_decision. Defined.
(* Symbolic integers *) (* Symbolic integers *)
...@@ -29,7 +29,7 @@ Inductive dbase_lit : Type := ...@@ -29,7 +29,7 @@ Inductive dbase_lit : Type :=
| dLitUnit : dbase_lit | dLitUnit : dbase_lit
| dLitUnknown : base_lit dbase_lit. | dLitUnknown : base_lit dbase_lit.
Global Instance dlit_decision : EqDecision dbase_lit. Global Instance dbase_lit_eq_dec : EqDecision dbase_lit.
Proof. solve_decision. Defined. Proof. solve_decision. Defined.
Inductive dval : Type := Inductive dval : Type :=
...@@ -38,7 +38,7 @@ Inductive dval : Type := ...@@ -38,7 +38,7 @@ Inductive dval : Type :=
| dLocV : dloc dval | dLocV : dloc dval
| dValUnknown : val dval. | dValUnknown : val dval.
Global Instance dval_EqDecision : EqDecision dval. Global Instance dval_eq_dec : EqDecision dval.
Proof. solve_decision. Defined. Proof. solve_decision. Defined.
Definition dloc_interp (E : known_locs) (dl : dloc) : cloc := Definition dloc_interp (E : known_locs) (dl : dloc) : cloc :=
...@@ -248,23 +248,26 @@ Qed. ...@@ -248,23 +248,26 @@ Qed.
(** Dexpr *) (** Dexpr *)
Inductive dexpr : Type := Inductive dexpr : Type :=
| dEVal : dval dexpr | dEVal : dval dexpr
| dEVar : string dexpr
| dEPair : dexpr dexpr dexpr | dEPair : dexpr dexpr dexpr
| dEFst : dexpr dexpr | dEFst : dexpr dexpr
| dESnd : dexpr dexpr | dESnd : dexpr dexpr
| dEUnknown (e : expr) `{!Closed [] e} : dexpr. | dEUnknown (e : W.expr) : dexpr.
Fixpoint dexpr_interp (E: known_locs) (de: dexpr) : expr := Fixpoint dexpr_interp (E: known_locs) (de: dexpr) : expr :=
match de with match de with
| dEVal dv => dval_interp E dv | dEVal dv => dval_interp E dv
| dEVar x => Var x
| dEPair de1 de2 => (dexpr_interp E de1, dexpr_interp E de2) | dEPair de1 de2 => (dexpr_interp E de1, dexpr_interp E de2)
| dEFst de => Fst (dexpr_interp E de) | dEFst de => Fst (dexpr_interp E de)
| dESnd de => Snd (dexpr_interp E de) | dESnd de => Snd (dexpr_interp E de)
| dEUnknown e => e | dEUnknown e => W.to_expr e
end. end.
(** DCexpr *) (** DCexpr *)
Inductive dcexpr : Type := Inductive dcexpr : Type :=
| dCRet : dexpr dcexpr | dCRet : dexpr dcexpr
| dCBind : string dcexpr dcexpr dcexpr
| dCAlloc : dcexpr dcexpr dcexpr | dCAlloc : dcexpr dcexpr dcexpr
| dCLoad : dcexpr dcexpr | dCLoad : dcexpr dcexpr
| dCStore : dcexpr dcexpr dcexpr | dCStore : dcexpr dcexpr dcexpr
...@@ -274,11 +277,12 @@ Inductive dcexpr : Type := ...@@ -274,11 +277,12 @@ Inductive dcexpr : Type :=
| dCSeq : dcexpr dcexpr dcexpr | dCSeq : dcexpr dcexpr dcexpr
| dCPar : dcexpr dcexpr dcexpr | dCPar : dcexpr dcexpr dcexpr
| dCInvoke (f: val) (de: dcexpr) | dCInvoke (f: val) (de: dcexpr)
| dCUnknown (e : expr) `{!Closed [] e}. | dCUnknown (e : W.expr).
Fixpoint dcexpr_interp (E: known_locs) (de: dcexpr) : expr := Fixpoint dcexpr_interp (E: known_locs) (de: dcexpr) : expr :=
match de with match de with
| dCRet de => a_ret (dexpr_interp E de) | dCRet de => a_ret (dexpr_interp E de)
| dCBind x de1 de2 => x ←ᶜ (dcexpr_interp E de1) ;; (dcexpr_interp E de2)
| dCAlloc de1 de2 => a_alloc (dcexpr_interp E de1) (dcexpr_interp E de2) | dCAlloc de1 de2 => a_alloc (dcexpr_interp E de1) (dcexpr_interp E de2)
| dCLoad de1 => a_load (dcexpr_interp E de1) | dCLoad de1 => a_load (dcexpr_interp E de1)
| dCStore de1 de2 => a_store (dcexpr_interp E de1) (dcexpr_interp E de2) | dCStore de1 de2 => a_store (dcexpr_interp E de1) (dcexpr_interp E de2)
...@@ -289,11 +293,10 @@ Fixpoint dcexpr_interp (E: known_locs) (de: dcexpr) : expr := ...@@ -289,11 +293,10 @@ Fixpoint dcexpr_interp (E: known_locs) (de: dcexpr) : expr :=
| dCSeq de1 de2 => dcexpr_interp E de1 ; dcexpr_interp E de2 | dCSeq de1 de2 => dcexpr_interp E de1 ; dcexpr_interp E de2
| dCPar de1 de2 => dcexpr_interp E de1 ||| dcexpr_interp E de2 | dCPar de1 de2 => dcexpr_interp E de1 ||| dcexpr_interp E de2
| dCInvoke fv de => call (fv, dcexpr_interp E de) | dCInvoke fv de => call (fv, dcexpr_interp E de)
| dCUnknown e1 => e1 | dCUnknown e1 => W.to_expr e1
end. end.
(** Well-foundness of dcexpr w.r.t. known_locs *) (** Well-formedness of dcexpr w.r.t. known_locs *)
Definition dloc_wf (E: known_locs) (dl : dloc) : bool := Definition dloc_wf (E: known_locs) (dl : dloc) : bool :=
match dl with match dl with
| dLoc i _ => bool_decide (is_Some (E !! i)) | dLoc i _ => bool_decide (is_Some (E !! i))
...@@ -307,24 +310,27 @@ Fixpoint dval_wf (E: known_locs) (dv : dval) : bool := ...@@ -307,24 +310,27 @@ Fixpoint dval_wf (E: known_locs) (dv : dval) : bool :=
| _ => true | _ => true
end. end.
Fixpoint dexpr_wf (E: known_locs) (de: dexpr) : bool := Fixpoint dexpr_wf (X: list string) (E: known_locs) (de: dexpr) : bool :=
match de with match de with
| dEVal dv => dval_wf E dv | dEVal dv => dval_wf E dv
| dEFst de | dESnd de => dexpr_wf E de | dEVar x => bool_decide (x X)
| dEPair de1 de2 => dexpr_wf E de1 && dexpr_wf E de2 | dEFst de | dESnd de => dexpr_wf X E de
| dEUnknown _ => true | dEPair de1 de2 => dexpr_wf X E de1 && dexpr_wf X E de2
| dEUnknown e => W.is_closed X e
end. end.
Fixpoint dcexpr_wf (E: known_locs) (de: dcexpr) : bool := Fixpoint dcexpr_wf (X: list string) (E: known_locs) (de: dcexpr) : bool :=
match de with match de with
| dCRet de => dexpr_wf E de | dCRet de => dexpr_wf X E de
| dCLoad de1 | dCUnOp _ de1 | dCInvoke _ de1 => dcexpr_wf E de1 | dCBind x de1 de2 => dcexpr_wf X E de1 && dcexpr_wf (x :: X) E de2
| dCLoad de1 | dCUnOp _ de1 | dCInvoke _ de1 => dcexpr_wf X E de1
| dCAlloc de1 de2 | dCStore de1 de2 | dCBinOp _ de1 de2 | dCAlloc de1 de2 | dCStore de1 de2 | dCBinOp _ de1 de2
| dCPreBinOp _ de1 de2 | dCSeq de1 de2 | dCPar de1 de2 => | dCPreBinOp _ de1 de2 | dCSeq de1 de2 | dCPar de1 de2 =>
dcexpr_wf E de1 && dcexpr_wf E de2 dcexpr_wf X E de1 && dcexpr_wf X E de2
| dCUnknown _ => true | dCUnknown e => W.is_closed X e
end. end.
(*TODO: Fuse wf_mono and interp_mono into one lemma for dval and dcexpr *) (*TODO: Fuse wf_mono and interp_mono into one lemma for dval and dcexpr *)
Lemma dval_wf_mono (E E': known_locs) (dv: dval) : Lemma dval_wf_mono (E E': known_locs) (dv: dval) :
dval_wf E dv E `prefix_of` E' dval_wf E' dv. dval_wf E dv E `prefix_of` E' dval_wf E' dv.
...@@ -341,13 +347,19 @@ Proof. ...@@ -341,13 +347,19 @@ Proof.
* specialize (prefix_cons_inv_2 _ _ _ _ Hpre). naive_solver. * specialize (prefix_cons_inv_2 _ _ _ _ Hpre). naive_solver.
Qed. Qed.
Lemma dexpr_wf_mono (E E': known_locs) (de: dexpr) :
dexpr_wf E de E `prefix_of` E' dexpr_wf E' de. Lemma dexpr_wf_mono (X: list string) (E E': known_locs) (de: dexpr) :
dexpr_wf X E de E `prefix_of` E' dexpr_wf X E' de.
Proof. induction de; simplify_eq /=; [apply dval_wf_mono|..]; naive_solver. Qed. Proof. induction de; simplify_eq /=; [apply dval_wf_mono|..]; naive_solver. Qed.
Lemma dcexpr_wf_mono (E E': known_locs) (de: dcexpr) : Lemma dcexpr_wf_mono (X: list string) (E E': known_locs) (de: dcexpr) :
dcexpr_wf E de E `prefix_of` E' dcexpr_wf E' de. dcexpr_wf X E de E `prefix_of` E' dcexpr_wf X E' de.
Proof. induction de; simplify_eq /=; [apply dexpr_wf_mono|..]; naive_solver. Qed. Proof.
revert X.
induction de; intros X; simplify_eq /=; [try apply dexpr_wf_mono|..];
naive_solver.
Qed.
Lemma dun_op_eval_Some_wf E dv u dw: Lemma dun_op_eval_Some_wf E dv u dw:
dval_wf E dv dun_op_eval E u dv = Some dw dval_wf E dw. dval_wf E dv dun_op_eval E u dv = Some dw dval_wf E dw.
...@@ -366,7 +378,7 @@ Proof. ...@@ -366,7 +378,7 @@ Proof.
simpl. unfold dptr_plus_eval. repeat case_match; naive_solver. simpl. unfold dptr_plus_eval. repeat case_match; naive_solver.
Qed. Qed.
(** / Well-foundness of dcexpr w.r.t. known_locs *) (** / Well-formedness of dcexpr w.r.t. known_locs *)
Lemma dloc_interp_mono (E E': known_locs) (i j: nat) : Lemma dloc_interp_mono (E E': known_locs) (i j: nat) :
dloc_wf E (dLoc i j) E `prefix_of` E' dloc_wf E (dLoc i j) E `prefix_of` E'
...@@ -404,8 +416,9 @@ Proof. ...@@ -404,8 +416,9 @@ Proof.
* specialize (prefix_cons_inv_2 _ _ _ _ Hpre). naive_solver. * specialize (prefix_cons_inv_2 _ _ _ _ Hpre). naive_solver.
Qed. Qed.
Lemma dexpr_interp_mono (E E': known_locs) (de: dexpr) :
dexpr_wf E de E `prefix_of` E' dexpr_interp E de = dexpr_interp E' de. Lemma dexpr_interp_mono (X: list string) (E E': known_locs) (de: dexpr) :
dexpr_wf X E de E `prefix_of` E' dexpr_interp E de = dexpr_interp E' de.
Proof. Proof.
induction de; simplify_eq /=; intros H Hpre; induction de; simplify_eq /=; intros H Hpre;
try (by rewrite IHde ) || try (by rewrite IHde ) ||
...@@ -415,24 +428,42 @@ Proof. ...@@ -415,24 +428,42 @@ Proof.
by rewrite (dval_interp_mono E E'). by rewrite (dval_interp_mono E E').
Qed. Qed.
Lemma dcexpr_interp_mono (E E': known_locs) (de: dcexpr) : Lemma dcexpr_interp_mono (X: list string) (E E': known_locs) (de: dcexpr) :
dcexpr_wf E de E `prefix_of` E' dcexpr_interp E de = dcexpr_interp E' de. dcexpr_wf X E de E `prefix_of` E'
dcexpr_interp E de = dcexpr_interp E' de.
Proof. Proof.
induction de; simplify_eq /=; intros H Hpre; revert X.
try (by rewrite IHde ) || induction de; simplify_eq /=; intros X H Hpre; eauto;
(apply andb_prop_elim in H as [H1 H2]; destruct_and?;
rewrite IHde2; [rewrite IHde1; done | done | done ]; try by rewrite (IHde X)
by rewrite (IHde1 H1 Hpre (dcexpr_interp E de1))) || eauto. || (rewrite (IHde2 X) // (IHde1 X) //).
by rewrite (dexpr_interp_mono E E'). - by rewrite (dexpr_interp_mono X E E').
- rewrite (IHde1 X) //.
by erewrite (IHde2 (_::X)).
Qed. Qed.
Global Instance dexpr_closed E de : Closed [] (dexpr_interp E de). Global Instance dexpr_closed X E de :
Proof. induction de; simpl; try solve_closed. Qed. dexpr_wf X E de
Closed X (dexpr_interp E de).
Proof.
revert X. induction de; simpl; intros; unfold Closed; simpl; eauto using is_closed_of_val;
try by apply IHde.
destruct_and!. by split_and; [apply IHde1 | apply IHde2].
by apply W.is_closed_correct.
Qed.
Global Instance dcexpr_closed E de : Closed [] (dcexpr_interp E de). Global Instance dcexpr_closed X E de :
dcexpr_wf X E de
Closed X (dcexpr_interp E de).
Proof. Proof.
induction de; simpl; try solve_closed. rewrite /Closed /=. revert X. induction de; intros; unfold Closed in *; simplify_eq /=;
split_and. change (Closed [] a_ret). solve_closed. apply (dexpr_closed E d). try (destruct_and!; split_and; first split_and; [ apply is_closed_of_val | by apply IHde2 | by apply IHde1]);
try (destruct_and!; split_and; first split_and; [ apply is_closed_of_val | by apply IHde1 | by apply IHde2]).
- split_and; eauto using is_closed_of_val. by apply dexpr_closed.
- split_and; [ apply is_closed_of_val | by apply IHde].
- split_and; [ apply is_closed_of_val | by apply IHde].
- split_and; first split_and; [ apply is_closed_of_val | apply is_closed_of_val | by apply IHde].
- by apply W.is_closed_correct.
Qed. Qed.
(** * Reification of C syntax *) (** * Reification of C syntax *)
...@@ -537,96 +568,112 @@ Proof. done. Qed. ...@@ -537,96 +568,112 @@ Proof. done. Qed.
(** ** IntoDExpr *) (** ** IntoDExpr *)
Class IntoDExpr (E: known_locs) (e: expr) (de: dexpr) := Class IntoDExpr (E: known_locs) (e: expr) (de: dexpr) :=
{ into_dexpr : e = dexpr_interp E de; into_dexpr : e = dexpr_interp E de.
into_dexpr_wf : dexpr_wf E de }.
Global Instance into_dexpr_val E e dv : Global Instance into_dexpr_val E e dv :
ExprIntoDVal E e dv ExprIntoDVal E e dv
IntoDExpr E e (dEVal dv) | 5. IntoDExpr E e (dEVal dv) | 5.
Proof. intros [-> ?]; split; auto. Qed. Proof. by intros [-> ?]. Qed.
Global Instance into_dexpr_var E x :
IntoDExpr E (Var x) (dEVar x) | 5.
Proof. done. Qed.
Global Instance into_dexpr_pair E e1 e2 de1 de2 : Global Instance into_dexpr_pair E e1 e2 de1 de2 :
IntoDExpr E e1 de1 IntoDExpr E e2 de2 IntoDExpr E e1 de1 IntoDExpr E e2 de2
IntoDExpr E (Pair e1 e2) (dEPair de1 de2). IntoDExpr E (Pair e1 e2) (dEPair de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDExpr=> -> ->. Qed.
Global Instance into_dexpr_fst E e de: Global Instance into_dexpr_fst E e de:
IntoDExpr E e de IntoDExpr E e de
IntoDExpr E (Fst e) (dEFst de). IntoDExpr E (Fst e) (dEFst de).
Proof. intros [-> ?]; split; auto. Qed. Proof. by rewrite /IntoDExpr=> ->. Qed.
Global Instance into_dexpr_snd E e de: Global Instance into_dexpr_snd E e de:
IntoDExpr E e de IntoDExpr E e de
IntoDExpr E (Snd e) (dESnd de). IntoDExpr E (Snd e) (dESnd de).
Proof. intros [-> ?]; split; auto. Qed. Proof. by rewrite /IntoDExpr=> ->. Qed.
Global Instance into_dexpr_unknown E e `{Closed [] e}: Lemma into_dexpr_unknown {E e} de :
IntoDExpr E e (dEUnknown e) | 100. e = W.to_expr de
Proof. done. Qed. IntoDExpr E e (dEUnknown de).
Proof. by intros ->. Qed.
Hint Extern 100 (IntoDExpr _ ?e _) =>
let e' := W.of_expr e in
apply (into_dexpr_unknown e'); reflexivity : typeclass_instances.
(** ** IntoDCExpr *) (** ** IntoDCExpr *)
Class IntoDCExpr (E: known_locs) (e: expr) (de: dcexpr) := Class IntoDCExpr (E: known_locs) (e: expr) (de: dcexpr) :=
{ into_dcexpr : e = dcexpr_interp E de; into_dcexpr : e = dcexpr_interp E de.
into_dcexpr_wf : dcexpr_wf E de }.
Global Instance into_dcexpr_ret E e de: Global Instance into_dcexpr_ret E e de:
IntoDExpr E e de IntoDExpr E e de
IntoDCExpr E (a_ret e) (dCRet de). IntoDCExpr E (a_ret e) (dCRet de).
Proof. intros [-> ?]; split; auto. Qed. Proof. by rewrite /IntoDExpr=> ->. Qed.
Global Instance into_dcexpr_bind E x e1 e2 de1 de2:
IntoDCExpr E e1 de1
IntoDCExpr E e2 de2
IntoDCExpr E (BNamed x ←ᶜ e1 ;; e2) (dCBind x de1 de2).
Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_alloc E e1 e2 de1 de2 : Global Instance into_dcexpr_alloc E e1 e2 de1 de2 :
IntoDCExpr E e1 de1 IntoDCExpr E e2 de2 IntoDCExpr E e1 de1 IntoDCExpr E e2 de2
IntoDCExpr E (a_alloc e1 e2) (dCAlloc de1 de2). IntoDCExpr E (a_alloc e1 e2) (dCAlloc de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_load E e de: Global Instance into_dcexpr_load E e de:
IntoDCExpr E e de IntoDCExpr E e de
IntoDCExpr E (a_load e) (dCLoad de). IntoDCExpr E (a_load e) (dCLoad de).
Proof. intros [-> ?]; split; auto. Qed. Proof. by rewrite /IntoDCExpr=> ->. Qed.
Global Instance into_dcexpr_store E e1 e2 de1 de2: Global Instance into_dcexpr_store E e1 e2 de1 de2:
IntoDCExpr E e1 de1 IntoDCExpr E e1 de1
IntoDCExpr E e2 de2 IntoDCExpr E e2 de2
IntoDCExpr E (a_store e1 e2) (dCStore de1 de2). IntoDCExpr E (a_store e1 e2) (dCStore de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_binop E e1 e2 op de1 de2: Global Instance into_dcexpr_binop E e1 e2 op de1 de2:
IntoDCExpr E e1 de1 IntoDCExpr E e1 de1
IntoDCExpr E e2 de2 IntoDCExpr E e2 de2
IntoDCExpr E (a_bin_op op e1 e2) (dCBinOp op de1 de2). IntoDCExpr E (a_bin_op op e1 e2) (dCBinOp op de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_prebinop E e1 e2 op de1 de2: Global Instance into_dcexpr_prebinop E e1 e2 op de1 de2:
IntoDCExpr E e1 de1 IntoDCExpr E e1 de1
IntoDCExpr E e2 de2 IntoDCExpr E e2 de2
IntoDCExpr E (a_pre_bin_op op e1 e2) (dCPreBinOp op de1 de2). IntoDCExpr E (a_pre_bin_op op e1 e2) (dCPreBinOp op de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_unop E e op de: Global Instance into_dcexpr_unop E e op de:
IntoDCExpr E e de IntoDCExpr E e de
IntoDCExpr E (a_un_op op e) (dCUnOp op de). IntoDCExpr E (a_un_op op e) (dCUnOp op de).
Proof. intros [-> ?]; split; auto. Qed. Proof. by rewrite /IntoDCExpr=> ->. Qed.
Global Instance into_dcexpr_sequence E e1 e2 de1 de2: Global Instance into_dcexpr_sequence E e1 e2 de1 de2:
IntoDCExpr E e1 de1 IntoDCExpr E e1 de1
IntoDCExpr E e2 de2 IntoDCExpr E e2 de2
IntoDCExpr E (e1 ; e2) (dCSeq de1 de2). IntoDCExpr E (e1 ; e2) (dCSeq de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_par E e1 e2 de1 de2: Global Instance into_dcexpr_par E e1 e2 de1 de2:
IntoDCExpr E e1 de1 IntoDCExpr E e1 de1
IntoDCExpr E e2 de2 IntoDCExpr E e2 de2
IntoDCExpr E (e1 ||| e2) (dCPar de1 de2). IntoDCExpr E (e1 ||| e2) (dCPar de1 de2).
Proof. intros [-> ?] [-> ?]; split; simpl; auto. Qed. Proof. by rewrite /IntoDCExpr=> -> ->. Qed.
Global Instance into_dcexpr_invoke E `{Closed [] e1} ef f `{!IntoVal ef f} de1 : Global Instance into_dcexpr_invoke e1 E ef f de1 :
IntoVal ef f ->
IntoDCExpr E e1 de1 IntoDCExpr E e1 de1
IntoDCExpr E (call (ef, e1)) (dCInvoke f de1). IntoDCExpr E (call (ef, e1)) (dCInvoke f de1).
Proof. Proof. by rewrite /IntoVal /IntoDCExpr=> <- ->. Qed.
intros. unfold IntoVal in *. simplify_eq /=.
split; simpl; auto; f_equal; by inversion H0.
Qed.
Global Instance into_dcexpr_unknown E e `{Closed [] e}: Lemma into_dcexpr_unknown {E e} de :
IntoDCExpr E e (dCUnknown e) | 100. e = W.to_expr de
Proof. done. Qed. IntoDCExpr E e (dCUnknown de).
Proof. by intros ->. Qed.
Hint Extern 100 (IntoDCExpr _ ?e _) =>
let e' := W.of_expr e in
apply (into_dcexpr_unknown e'); reflexivity : typeclass_instances.
...@@ -56,22 +56,22 @@ Section factorial_spec. ...@@ -56,22 +56,22 @@ Section factorial_spec.
AWP factorial #n @ R {{ v, v = #(fact n) }}%I. AWP factorial #n @ R {{ v, v = #(fact n) }}%I.
Proof. Proof.
awp_lam. awp_lam.
iApply awp_bind. awp_alloc_ret r "[Hr _]". vcg_solver.
iApply awp_bind. awp_alloc_ret c "[Hc _]". iIntros (r) "[Hr _]". vcg_continue. iIntros "Hr".
iApply a_sequence_spec'. iNext. iIntros (c) "[Hc _]". vcg_continue. iIntros "Hr Hc".
iApply (awp_wand _ (λ _, c C #n r C #(fact n))%I with "[Hr Hc]"). iApply (awp_wand _ (λ _, c C #n r C #(fact n))%I with "[Hr Hc]").
- iApply ((factorial_body_spec n 0 c r) with "[$Hr $Hc]"); eauto with lia. - iApply ((factorial_body_spec n 0 c r) with "[$Hr $Hc]"); eauto with lia.
- iIntros (?) "[Hc Hr]". iModIntro. - iIntros (?) "[Hc Hr]". vcg_continue. iModIntro. eauto.
awp_load_ret r.
Qed. Qed.
Lemma factorial_spec_with_inv (n: nat) R : Lemma factorial_spec_with_inv (n: nat) R :
awp (factorial #n) R (λ v, v = #(fact n))%I. awp (factorial #n) R (λ v, v = #(fact n))%I.
Proof. Proof.
awp_lam. awp_lam.
iApply awp_bind. awp_alloc_ret r "[Hr _]". vcg_solver.
iApply awp_bind. awp_alloc_ret c "[Hc _]". iIntros (r) "[Hr _]". vcg_continue. iIntros "Hr".
iApply a_sequence_spec'. iNext. do 3 awp_lam. iIntros (c) "[Hc _]". vcg_continue. iIntros "Hr Hc".
do 3 awp_lam.
iApply (a_while_inv_spec iApply (a_while_inv_spec
(k:nat, k n c C #k r C #(fact k))%I with "[Hr Hc]"). (k:nat, k n c C #k r C #(fact k))%I with "[Hr Hc]").
- iExists O. eauto with iFrame lia. - iExists O. eauto with iFrame lia.
...@@ -87,8 +87,9 @@ Section factorial_spec. ...@@ -87,8 +87,9 @@ Section factorial_spec.
{ rewrite Nat.add_1_r /fact. lia. } { rewrite Nat.add_1_r /fact. lia. }
assert (Z_of_nat' (k + 1)%nat = (k + 1)) as <- by lia. assert (Z_of_nat' (k + 1)%nat = (k + 1)) as <- by lia.
iExists (k+1)%nat. eauto with iFrame lia. iExists (k+1)%nat. eauto with iFrame lia.
+ iLeft. iSplit; eauto. do 2 iModIntro. + iLeft. iSplit; eauto. iModIntro.
iRevert "H". iIntros "%". assert (k = n) as -> by lia. iRevert "H". iIntros "%". assert (k = n) as -> by lia.