Library C_contrib
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
From mathcomp Require Import div.
Require Import Init_ext ssrZ ZArith_ext String_ext seq_ext.
Require Import machine_int.
Import MachineInt.
Require Import C_types C_types_fp C_value C_expr C_expr_equiv C_expr_ground.
Require Import C_seplog.
Local Open Scope C_types_scope.
Local Open Scope C_expr_scope.
Local Open Scope machine_int_scope.
Require Import while_bipl.
From mathcomp Require Import seq.
Module C_Contrib_f (C_Env : CENV).
Definition g := C_Env.g.
Definition sigma := C_Env.sigma.
Module Import C_seplog_m := C_Seplog_f C_Env.
Export C_seplog_m.
Local Open Scope C_types_scope.
Local Open Scope zarith_ext_scope.
From mathcomp Require Import div.
Require Import Init_ext ssrZ ZArith_ext String_ext seq_ext.
Require Import machine_int.
Import MachineInt.
Require Import C_types C_types_fp C_value C_expr C_expr_equiv C_expr_ground.
Require Import C_seplog.
Local Open Scope C_types_scope.
Local Open Scope C_expr_scope.
Local Open Scope machine_int_scope.
Require Import while_bipl.
From mathcomp Require Import seq.
Module C_Contrib_f (C_Env : CENV).
Definition g := C_Env.g.
Definition sigma := C_Env.sigma.
Module Import C_seplog_m := C_Seplog_f C_Env.
Export C_seplog_m.
Local Open Scope C_types_scope.
Local Open Scope zarith_ext_scope.
wp_assign
Set Implicit Arguments.
Unset Strict Implicit.
Section wp_assign_sect.
Variable (str : string) (t : g.-typ).
Hypothesis str_t : assoc_get str sigma = |_ t _|.
Lemma wp_assign_con e P0 P1 : wp_assign str_t e (P0 ** P1) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1.
Proof.
move => s h; split.
- inversion 1; subst; clear H.
inversion H0; subst; clear H0.
by constructor.
- inversion 1; subst; clear H.
inversion H1; subst; clear H1.
inversion H2; subst; clear H2.
by constructor.
Qed.
Lemma wp_assign_assert (e' : exp sigma t) {t' : g.-typ} (e : exp sigma t') P :
wp_assign str_t e' (fun s h => P ([ e ]_ s) h) <==>
(fun s h => P ([subst_exp str str_t e' e]_ s) h).
Proof.
move=> s h; split.
- inversion_clear 1.
by rewrite -subst_exp_store_upd in H0.
- move=> H; apply wp_assign_c.
by rewrite -subst_exp_store_upd.
Qed.
Lemma wp_assign_bbang (e' : exp sigma t) (b : bexp sigma) :
wp_assign str_t e' (`! b) <==> `! @subst_bexp g _ str t str_t e' b.
Proof.
rewrite /bbang /bang => s h; split.
- inversion_clear 1.
case: H0 => H1 H2; split => //.
rewrite subst_bexp_store_upd; tauto.
- case => H1 H2.
apply wp_assign_c; split=> //.
by rewrite -subst_bexp_store_upd.
Qed.
Lemma wp_assign_sbang e P : wp_assign str_t e (!!( P )) <==> !!( P ).
Proof. move => s h; split=> //; by inversion 1. Qed.
Lemma wp_assign_emp e : wp_assign str_t e emp <==> emp.
Proof. move => s h; split => //; by inversion 1. Qed.
Lemma wp_assign_T e : wp_assign str_t e TT <==> TT.
Proof. done. Qed.
Lemma wp_assign_F e : wp_assign str_t e FF <==> FF.
Proof. move=> s h; split; by [case=> {}s {}h [] | case]. Qed.
Lemma wp_assign_ex (e : exp sigma t) {A} (P : A -> assert) :
(wp_assign str_t e (sepex x, P x)) <==> sepex y, wp_assign str_t e (P y).
Proof.
move=> s h; split.
- inversion_clear 1.
inversion_clear H0.
exists x; constructor; tauto.
- inversion_clear 1.
inversion_clear H0.
constructor.
by exists x.
Qed.
Lemma wp_assign_mapsto_le (e : exp sigma t) {t' : Ctyp.t g} (e' : exp sigma (:* t')) (val : log t'):
wp_assign str_t e (e' |le~> val) <==> subst_exp str str_t e e' |le~> val.
Proof.
move => s h; split.
- inversion_clear 1.
by rewrite -subst_exp_store_upd in H0.
- econstructor.
by rewrite -subst_exp_store_upd.
Qed.
Lemma wp_assign_mapsto_lV (e : exp sigma t) {t' : g.-typ} (e' : (:* t').-phy) (val : log t') :
wp_assign str_t e (e' |lV~> val) <==> e' |lV~> val.
Proof.
move => s h; split.
- by inversion_clear 1.
- by constructor.
Qed.
Lemma wp_assign_mapstos (e : exp sigma t) {t': g.-typ} : forall (l : seq (t'.-phy)) (e' : exp _ (:* t')),
(wp_assign str_t e (e' |--> l)) <==> (subst_exp str str_t e e') |--> l.
Proof.
elim => //=.
- by move => e'; rewrite wp_assign_emp.
- move => hd tl Hind e' s h; split.
+ inversion_clear 1.
inversion H0; subst; clear H0.
rewrite -subst_exp_store_upd in H1.
constructor => //=.
rewrite (_ : subst_exp str str_t e e' \+ [ 1 ]sc = subst_exp str str_t e (e' \+ [ 1 ]sc)) //.
apply (proj1 (Hind _ s h2)).
by constructor.
+ econstructor.
inversion H; subst; clear H.
constructor => //=.
by rewrite -subst_exp_store_upd.
rewrite (_ : _ \+ _ = subst_exp str str_t e (e' \+ [ 1 ]sc)) // in H2.
move: (proj2 (Hind _ s h2) H2).
by inversion_clear 1.
Qed.
Lemma wp_assign_fit (e : exp sigma t) (ty' : g.-typ) (l : seq (ty'.-phy)) (e' : exp sigma (:* ty')) :
wp_assign str_t e !(fun s =>
(u2Z (ptr<=phy [ e' ]_s) + Z_of_nat (sizeof ty' * size l) <
2 ^^ ptr_len)%Z) <==>
!(fun s => (u2Z (ptr<=phy [ subst_exp str str_t e e' ]_s) +
Z_of_nat (sizeof ty' * size l) < 2 ^^ ptr_len)%Z).
Proof.
move=> s h; split.
case=> s' h' [] H; rewrite /emp => ?; subst h'.
split => //.
by rewrite subst_exp_store_upd.
case=> H; rewrite /emp => ?; subst h.
apply wp_assign_c; split => //.
by rewrite -subst_exp_store_upd.
Qed.
Lemma wp_assign_mapstos_fit (e : exp sigma t) {t' : g.-typ} :
forall (l : seq (t'.-phy)) (e': exp _ (:* t')),
wp_assign str_t e (e' |---> l) <==> (subst_exp str str_t e e') |---> l.
Proof.
move=> l e'.
rewrite /mapstos_fit wp_assign_con wp_assign_mapstos.
apply con_congr => //.
apply wp_assign_fit.
Qed.
Lemma wp_assign_store_upd (e : exp sigma t) (Q : assert) :
wp_assign str_t e Q <==> (fun s h => Q (store_upd str_t ([ e ]_s) s) h).
Proof.
move => s h; split.
by inversion_clear 1.
by constructor.
Qed.
Lemma wp_assign_or e P Q :
wp_assign str_t e (P \\// Q) <==> wp_assign str_t e P \\// wp_assign str_t e Q.
Proof.
move => s h; split.
- inversion 1; subst; clear H.
inversion_clear H0; by [left | right].
- inversion 1; inversion H0; subst; clear H; constructor; [by left | by right].
Qed.
Lemma wp_assign_inde e P : inde_cmd (assign str_t e) P -> wp_assign str_t e P <==> P.
Proof.
move => Hinde s h.
have Hin : (str, t) \in modified_vars (assign str_t e) by rewrite in_cons eq_refl.
split.
- inversion_clear 1.
apply (Hinde s h str t ([ e ]_ s) Hin).
set X := assoc_get_subset_in _ _ _.
by have -> : X = str_t by apply eq_irrelevance.
- constructor.
move: (proj1 (Hinde s h str t ([ e ]_ s) Hin) H).
set X := assoc_get_subset_in _ _ _.
by have -> : X = str_t by apply eq_irrelevance.
Qed.
End wp_assign_sect.
Unset Implicit Arguments.
Set Strict Implicit.
lookup for fields
Section wp_lookup_sect.
Variables (t : g.-typ) (str : string).
Hypothesis str_t : env_get str sigma = |_ :* t _|.
Variable e'' : exp sigma (:* t).
Variable (t' : g.-typ) (str' : string).
Hypothesis str't : env_get str' sigma = |_ t' _|.
Variable tg : tag.
Hypothesis t'tg : styp tg = t.
Variable fld : string.
Hypothesis fld_t' : assoc_get fld (get_fields g tg) = |_ t' _|.
Variable e : exp sigma (:* t).
Lemma hoare_lookup_fldp_subst P Q :
P ===> (`! \b var_e _ _ (:* t) str_t \= e'' ) ** TT ->
{{ P }} lookup str't (fldp _ fld (subst_exp _ str_t e'' e) t'tg fld_t') {{ Q }} ->
{{ P }} lookup str't (fldp _ fld e t'tg fld_t') {{ Q }}.
Proof.
Transparent eval.
move=> HP Hoare.
apply hoare_complete => s h HPsh.
case: (soundness _ _ _ Hoare s h HPsh) => Hsem1 Hsem2.
have He': forall e', [subst_exp str str_t e'' e']_ s = [e']_ s.
move => c e'.
rewrite subst_exp_store_upd.
have : (`! \b var_e _ _ _ str_t \= e'') s hp.emp.
move: (HP _ _ HPsh) => H'.
inversion H'; subst; clear H'.
split; last by done.
by apply (proj1 H0).
move/bbang_eqp_store_get => <-.
by rewrite store_upd_get_eq.
split.
- move => H'.
apply Hsem1.
inversion_clear H'.
inversion H; subst; clear H.
apply exec_cmd0, exec_lookup_err => //=.
rewrite /a in H1.
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e1.
rewrite He'; exact H1.
- move => s' h' Hsem.
apply Hsem2.
inversion_clear Hsem.
inversion H; subst; clear H.
rewrite /a in H1.
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e1.
(have: Hstr0 = str't by apply eq_irrelevance) => ?; subst Hstr0.
(have: Hstr1 = str't by apply eq_irrelevance) => ?; subst Hstr1.
apply exec_cmd0, exec_lookup => //=.
rewrite He'; exact H1.
Opaque eval.
Qed.
End wp_lookup_sect.
CoInductive wp_lookup_fldp
str {t' : g.-typ} (str_t' : assoc_get str sigma = Some t')
{t : g.-typ} (e : exp sigma (:* t)) tg (tgt : styp tg = t)
f (f_t : assoc_get f (get_fields g tg) = Some t')
(P : assert) : assert :=
| mkWpLookupFldpConv : forall s h (lvs : logs _) (pv : _.-phy) (lv : _.-log),
values_get f _ _ lvs (assoc_get_in f_t) = lv ->
pv |x| lv ->
([e]_ s |lV~> log_of_styp _ _ tgt lvs ** TT) s h /\
(wp_assign str_t' [ pv ]c P) s h ->
wp_lookup_fldp _ str_t' e _ tgt _ f_t P s h.
Notation "P '`{' x '<-' e '.->' f '}''" := (wp_lookup_fldp x _ e _ _ f _ P) (at level 5, x, e at next level, format "'[hv ' P '/ ' `{ x <- e .-> f }' ']'") : C_assert_scope.
Notation "P '`{' x '<-' e '.->' f '}''" := (wp_lookup_fldp x erefl e _ erefl f erefl P) (at level 5, x, e at next level, only parsing) : C_assert_scope.
Section ent_R_lookup_trans_sect.
Variable str : string.
Variable t : g.-typ.
Hypothesis str_t : assoc_get str sigma = Some t.
Variable e : exp sigma (:* t).
Lemma ent_R_lookup_trans (pv : t.-phy) (lv : t.-log) (P R : assert) :
pv |x| lv ->
R ===> (e |le~> lv) ** TT ->
R ===> wp_assign str_t [ pv ]c P ->
R ===> wp_lookup str_t e P.
Proof.
move=> pv_lv H' H s h Hh.
move: (H' _ _ Hh) => {}H'.
case: H' Hh => h1 h2 h1dh2 H1 H2 Hh.
rewrite /phylog_conv in pv_lv.
move/log_mapsto_heap_get_conv : (H1).
move/(_ _ pv_lv) => H1'.
apply wp_lookup_c with pv.
by apply heap_get_value_union_L.
by case: (H _ _ Hh).
Qed.
End ent_R_lookup_trans_sect.
Section wp_lookup_fldp_sect.
Variable str : string.
Variable t' : g.-typ.
Hypothesis str_t' : assoc_get str sigma = Some t'.
Variable t : g.-typ.
Variable e : exp sigma (:* t).
Variable tg : tag.
Hypothesis tgt : styp tg = t.
Variable f : string.
Hypothesis f_t' : assoc_get f (get_fields g tg) = |_ t' _|.
Lemma wp_lookup_fldp_ex (A : Type) (P : A -> assert) :
wp_lookup_fldp _ str_t' e _ tgt _ f_t' (sepex x, P x) <==>
sepex y, wp_lookup_fldp _ str_t' e _ tgt _ f_t' (P y).
Proof.
move => s h; split.
- inversion_clear 1.
case: H2 => H2 H3.
inversion_clear H3.
case: H => a H.
exists a.
rewrite -H0 in H1.
econstructor.
+ reflexivity.
+ exact H1.
+ done.
- case => a.
inversion_clear 1.
rewrite -H in H0.
econstructor.
+ reflexivity.
+ exact H0.
+ case: H1 => H11 H12.
split => //.
apply wp_assign_ex; by exists a.
Qed.
Lemma ent_R_lookup_fldp_trans (pv : t'.-phy) lvs (P : assert) R :
R ===> (fun s h => ([e]_ s |lV~> log_of_styp _ _ tgt lvs) s h) ** TT ->
pv |x| values_get f _ _ lvs (assoc_get_in f_t') ->
R ===> wp_assign str_t' [ pv ]c P ->
R ===> wp_lookup_fldp _ str_t' e _ tgt _ f_t' P.
Proof.
move=> H1 H2 H3.
econstructor.
- reflexivity.
- by apply H2.
- split.
+ move: (H1 _ _ H).
inversion 1; subst.
by constructor.
+ by apply H3.
Qed.
Lemma ent_R_lookup_fldp (pv : t'.-phy) lvs (P : assert) :
pv |x| values_get f _ _ lvs (assoc_get_in f_t') ->
(fun s h => ([e]_ s |lV~> log_of_styp _ _ tgt lvs) s h) ===>
wp_assign str_t' [ pv ]c P ->
(fun s h => ([e]_ s |lV~> log_of_styp _ _ tgt lvs) s h) ===>
wp_lookup_fldp _ str_t' e _ tgt _ f_t' P.
Proof.
move=> H1 H2.
eapply ent_R_lookup_fldp_trans; eauto.
by apply ent_R_con_T.
Qed.
Lemma hoare_lookup_fldp (P : assert) :
{{ wp_lookup_fldp _ str_t' e _ tgt _ f_t' P }} lookup str_t' (fldp sigma f e tgt f_t') {{ P }}.
Proof.
Transparent eval.
apply hoare_stren with (wp_lookup str_t' (fldp _ f e tgt f_t') P); last by apply hoare_hoare0, hoare0_lookup.
rewrite /entails => s h HP; inversion HP; subst; clear HP.
case: H1 => H H1.
inversion H1; subst; clear H1.
econstructor; last by apply H2.
inversion_clear H.
apply heap_get_value_union_L; first by map_tac_m.Disj.
rewrite /=.
inversion H3; subst; clear H3 => //=.
apply Eqdep.EqdepTheory.inj_pair2 in H7.
subst vs0.
move: (@log_mapstos_mapsto g _ _ _ _ _ (assoc_get_in f_t') _ H11) => [] h1' [] h2' [] Hdisj [] Heq /= Hmapsto'.
set new_addr := (_ + _)%nat in Hmapsto'.
rewrite Heq.
rewrite -hp.unionA.
apply heap_get_value_union_L.
apply hp.disjhU => //.
suff : h0 # pad.
rewrite Heq => ?; by map_tac_m.Disj.
move/log_mapstos_inv_heap_dom : (H11) => H11'.
by rewrite hp.disjE H15 H11' size_iota dis_iota.
apply phy_mapsto_heap_get => //=.
move: (proj2 (phylog_mapsto_conv _ _ _ H0 h1' (field_address new_addr _ _ (get_fields _ _) (assoc_get_in f_t'))) Hmapsto') => Hequiv.
apply (phy_mapsto_eq Hequiv) => //=.
rewrite -value_phy_shift_pointer.
have padd_is_zero : padd '|u2Z (ptr<=phy ([e ]_ s))|
(align (seq.head (f, t') (get_fields g tg)).2) = O.
apply padd_0; first by apply align_gt0.
eapply dvdn_trans; last by apply H8.
rewrite -nth0.
apply align_get_fields => //.
by apply assoc_get_in.
rewrite -has_predT.
apply/hasP.
exists (f, t') => //; by apply assoc_get_in.
rewrite /new_addr padd_is_zero addn0.
move: (log_mapstos_inv2 _ _ _ _ _ _ (assoc_get_in f_t') H11) => H11_inv.
rewrite padd_is_zero addn0 in H11_inv.
rewrite field_address_slide0 // => i Hi str_dummy ty_dummy Hdummy.
eapply dvdn_trans; last by apply H8.
by apply align_get_fields.
move: (phy_mapsto_overflow Hequiv) => Hoverflow.
apply: (leZ_ltZ_trans _ Hoverflow).
rewrite (field_address_slide0 _ new_addr); last first.
move=> i Hi str_dummy ty_dummy Hdummy.
rewrite /new_addr padd_0; last 2 first.
exact/align_gt0.
eapply dvdn_trans; last by apply H8.
rewrite -nth0.
apply align_get_fields => //.
by apply assoc_get_in.
by apply leq_ltn_trans with i.
rewrite addn0.
eapply dvdn_trans; last by apply H8.
by apply align_get_fields.
rewrite inj_plus /new_addr inj_plus Z_of_nat_Zabs_nat; last exact/min_u2Z.
rewrite -2!addZA; apply leZ_add2l.
apply leZ_addl; first exact: Zle_0_nat.
rewrite addZC.
apply leZ_addl; by [apply Zle_0_nat | apply leZZ].
Opaque eval.
Qed.
Lemma hoare_lookup_fldp_stren (P Q : assert) :
P ===> wp_lookup_fldp _ str_t' e _ tgt _ f_t' Q ->
{{ P }} lookup str_t' (fldp _ f e tgt f_t') {{ Q }}.
Proof. move/hoare_stren; apply. apply hoare_lookup_fldp. Qed.
End wp_lookup_fldp_sect.
lookup mapstos
CoInductive wp_lookup_mapstos str {t : g.-typ} (str_t : assoc_get str sigma = Some t)
(l : seq (t.-phy)) (ei : exp sigma (:* t)) (e : exp sigma (:* t)) (i : nat) (P : assert) : assert :=
| mkWpLookupMapstos : forall s h,
(size l > i)%nat ->
(`! \b ei \= e \+ [Z_of_nat i]sc ** (e |--> l) ** TT) s h ->
(wp_assign str_t [ nth pv0 l i ]c P) s h ->
wp_lookup_mapstos _ str_t l ei e i P s h.
Notation "P '`{' x '<-' l '{' ei ',' e ',' i '}' '}''" := (wp_lookup_mapstos x _ l ei e i P) (at level 5, x, e at next level, format "'[hv ' P '/ ' `{ x <- l { ei , e , i } }' ']'") : C_assert_scope.
Section wp_lookup_mapstos_sect.
Variable str : string.
Variable t : g.-typ.
Hypothesis str_t : assoc_get str sigma = Some t.
Variable l : seq (t.-phy).
Variables ei e : exp sigma (:* t).
Variable i : nat.
Lemma hoare_lookup_mapstos (Q : assert) :
Z_of_nat (size l * sizeof t) < 2 ^^ 31 ->
{{ wp_lookup_mapstos _ str_t l ei e i Q }} lookup str_t ei {{ Q }}.
Proof.
move=> l_ub.
apply hoare_stren with (@wp_lookup_back_TT _ _ str_t ei Q); last by apply hoare_lookup_back_TT.
move=> s_ h_ [] s h i_sz_l H1 Hh {s_ h_}.
move eqnh1 : h => h'.
case: H1 (eqnh1) => h1 h2 _ Hei Hh2; subst h'.
case: Hei => Hei; rewrite /emp => ?; subst h1.
rewrite hp.unioneh => ?; subst h2.
move eqnh : h => h'.
case: Hh2 (eqnh) => h1 h0 h1h0 Hh1 _ eqnh'; subst h' h.
rewrite (@nth_decomp _ pv0 l i i_sz_l) in Hh1.
have {}Hh1 : (e |--> take i l **
(e \+ [Z_of_nat i]sc) |pe~> nth pv0 l i **
(e \+ [Z_of_nat i.+1]sc) |--> drop i.+1 l) s h1.
clear h1h0 Hei Hh.
apply (mapstos_cat i) in Hh1; last 2 first.
by rewrite size_take i_sz_l.
rewrite size_cat size_take i_sz_l [size _]/= size_drop (_ : _ + _ = size l)%nat //.
rewrite subnS prednK; last by rewrite subn_gt0.
by rewrite subnKC // ltnW.
move: Hh1; apply monotony_L.
rewrite mapstos_cons.
apply monotony_L, add_pe_n_1.
by rewrite size_drop subnKC.
move eqnh1 : h1 => h1'.
case: Hh1 (eqnh1) => h11 h12 h11h12 Hh11 Hh12 eqnh1'; subst h1' h1.
move eqnh12 : h12 => h12'.
case : Hh12 (eqnh12) => h121 h122 h121h122 Hh121 Hh122 eqnh12'; subst h12' h12.
econstructor; last by apply Hh.
rewrite (_ : _ \U _ = h121 \U (h11 \U h122 \U h0)); last by Equal.
constructor => //.
- by Disj.
- move: Hei.
rewrite beval_eq_p_eq.
by move/eqP => ->.
Qed.
Lemma hoare_lookup_mapstos_stren (P Q : assert) :
Z_of_nat (size l * sizeof t) < 2 ^^ 31 ->
P ===> wp_lookup_mapstos _ str_t l ei e i Q ->
{{ P }} lookup str_t ei {{ Q }}.
Proof.
move=> Hfit H.
eapply hoare_stren; first by apply H.
by apply hoare_lookup_mapstos.
Qed.
Lemma ent_R_lookup_mapstos_trans (P R : assert) : (size l > i)%nat ->
R ===> `! \b ei \= e \+ [ Z<=nat i ]sc ** ( e |--> l) ** TT ->
R ===> wp_assign str_t [nth pv0 l i]c P ->
R ===> wp_lookup_mapstos _ str_t l ei e i P.
Proof.
move=> Hl H1 H2 s h HR.
move: {H1}(H1 _ _ HR) => H1.
move: {H2 HR}(H2 _ _ HR) => H2.
by constructor.
Qed.
End wp_lookup_mapstos_sect.
lookup mapstos_fit
CoInductive wp_lookup_mapstos_fit str {t : g.-typ} (str_t : assoc_get str sigma = Some t)
(l : seq (t.-phy)) (ei : exp sigma (:* t)) (e : exp sigma (:* t)) (i : nat)
(P : assert) : assert :=
| mkWpLookupMapstosFit: forall s h,
(size l > i)%nat ->
(`! \b ei \= e \+ [Z_of_nat i]sc ** ( e |---> l) ** TT) s h ->
(wp_assign str_t [nth pv0 l i]c P) s h ->
wp_lookup_mapstos_fit _ str_t l ei e i P s h.
Notation "P '`{' x '<fit-' l '{' ei ',' e ',' i '}' '}''" := (wp_lookup_mapstos_fit x _ l ei e i P) (at level 5, x, e at next level, format "'[hv ' P '/ ' `{ x <fit- l { ei , e , i } }' ']'") : C_assert_scope.
Section wp_lookup_mapstos_fit_sect.
Variable str : string.
Variable t : g.-typ.
Hypothesis str_t : assoc_get str sigma = Some t.
Variable l : seq (t.-phy).
Variables ei e : exp sigma (:* t).
Variable i : nat.
Lemma hoare_lookup_mapstos_fit (Q : assert) :
Z_of_nat (size l * sizeof t) < 2 ^^ 31 ->
{{ wp_lookup_mapstos_fit _ str_t l ei e i Q }} lookup str_t ei {{ Q }}.
Proof.
move=> l_ub.
apply hoare_stren with (wp_lookup_mapstos _ str_t l ei e i Q); last first.
by apply hoare_lookup_mapstos.
move=> s h [] s' h' il H H'.
apply mkWpLookupMapstos => //.
apply conA, conC in H.
apply conA, conC.
move: H; apply monotony_L, monotony_L.
rewrite /mapstos_fit.
eapply ent_trans; first by apply equiv_imp, con_and_bang_R.
by move=> s_ h_ [].
Qed.
Lemma hoare_lookup_mapstos_fit_stren (P Q : assert) :
Z_of_nat (size l * sizeof t) < 2 ^^ 31 ->
P ===> wp_lookup_mapstos_fit _ str_t l ei e i Q ->
{{ P }} lookup str_t ei {{ Q }}.
Proof.
move => Hfit H.
eapply hoare_stren; first by apply H.
by apply hoare_lookup_mapstos_fit.
Qed.
Lemma ent_R_lookup_mapstos_fit_trans (P : assert) R :
(size l > i)%nat ->
R ===> `! \b ei \= e \+ [Z_of_nat i]sc ** e |---> l ** TT ->
R ===> wp_assign str_t [nth pv0 l i]c P ->
R ===> wp_lookup_mapstos_fit _ str_t l ei e i P.
Proof.
move => Hl H1 H2 s h HR.
move: {H1}(H1 _ _ HR) => H1.
move: {H2 HR}(H2 _ _ HR) => H2.
by constructor.
Qed.
End wp_lookup_mapstos_fit_sect.
Local Open Scope C_cmd_scope.
Section hoare_mutation_subst_sect.
Variable t : g.-typ.
Variable e1 : exp sigma (:* t).
Variable e2 : exp sigma t.
Lemma hoare_mutation_local_forward_ground_le (lv lv' : t.-log) He2 :
ground_exp e2 He2 |x| lv' ->
{{ e1 |le~> lv }} e1 *<- e2 {{ e1 |le~> lv' }}.
Proof.
move=> e2_x_lv'.
eapply hoare_stren; last by apply hoare_hoare0, hoare0_mutation.
move=> s h P.
case: (log_mapsto_heap_get_ex lv ('| (Z<=u (ptr<=phy ([ e1 ]_s))) |) h P) => pv Hpv.
apply wp_mutation_c with pv => //.
apply log_mapsto_heap_upd with lv => //.
suff -> : [ e2 ]_s = ground_exp _ He2 by assumption.
by apply ground_exp_sem.
Qed.
Lemma hoare_mutation_subst_btyp t' str Hstr (e' : exp sigma (g.-ityp: t')) P Q :
P ===> `! \b @var_e g _ str _ Hstr \= e' ** TT ->
{{ P }} subst_exp str Hstr e' e1 *<- subst_exp str Hstr e' e2 {{ Q }} ->
{{ P }} e1 *<- e2 {{ Q }}.
Proof.
move=> H1 H2.
apply hoare_complete => s h Psh.
case: (soundness _ _ _ H2 s h Psh) => Hsem1 Hsem2.
have He' : forall e_, [ subst_exp str Hstr e' e_ ]_s = [ e_ ]_s.
move=> r_ e_.
case: (H1 _ _ Psh) => h1 h2 h1dh2 H4 _.
apply bbang_eqi_store_get in H4.
by rewrite subst_exp_store_upd -H4 store_upd_get_eq.
split.
- move=> abs.
apply Hsem1.
inversion_clear abs.
inversion H; subst; clear H.
rewrite /a in H3.
apply Eqdep.EqdepTheory.inj_pair2 in H6; subst e4.
apply Eqdep.EqdepTheory.inj_pair2 in H7; subst e5.
apply exec_cmd0, exec_mutation_err.
set pv1 := [ _ ]_ s.
set pv2 := [ _ ]_ s in H3.
suff -> : pv1 = pv2 by assumption.
rewrite /pv1 /pv2.
by rewrite He'.
- move=> s' h' H.
inversion_clear H.
inversion H0; subst; clear H0.
rewrite /a0 in H3 *.
apply Eqdep.EqdepTheory.inj_pair2 in H6; subst e4.
apply Eqdep.EqdepTheory.inj_pair2 in H7; subst e5.
apply Hsem2.
apply exec_cmd0.
rewrite -(He' _ e1) -(He' _ e2).
apply exec_mutation with v.
by rewrite -(He' _ e1) in H3.
Qed.
End hoare_mutation_subst_sect.
mutation backward-reasoning form (MUBR)
CoInductive wp_mutation_backward {t : g.-typ} (e : exp sigma (:* t)) (e' : exp sigma t)
(Q : assert) : assert :=
| mkWpMutationBackward : forall s h (old new : log t),
([ e' ]_ s) |x| new ->
([ e ]_ s |lV~> old ** ([ e ]_ s |lV~> new -* Q)) s h ->
wp_mutation_backward e e' Q s h.
Lemma hoare_mutation_backward {t : g.-typ} (e1 : exp sigma (:* t)) (e2 : exp sigma t) Q :
{{ wp_mutation_backward e1 e2 Q }} e1 *<- e2 {{ Q }}.
Proof.
apply hoare_stren with (wp_mutation e1 e2 Q); last by apply hoare_hoare0, hoare0_mutation.
move => s h HP.
inversion HP; subst; clear HP.
case: H0 => h1 h2 h1dh2 H1 H2.
case: (log_mapsto_heap_get_ex _ _ _ H1) => old' Hold'.
econstructor.
apply heap_get_value_union_L; first by map_tac_m.Disj.
apply Hold'.
rewrite heap_upd_union_L => //=.
- have Hdisj: (heap_upd t '|u2Z (ptr<=phy [e1 ]_ s)| [e2 ]_ s h1) # h2 by apply disj_heap_upd.
apply (H2 (heap_upd t '|u2Z (ptr<=phy [e1 ]_ s)| [e2 ]_ s h1) Hdisj).
by apply log_mapsto_heap_upd with old.
- by rewrite (log_mapsto_inv_heap_dom _ _ _ H1) seq_ext.inc_refl.
Qed.
Section hoare_mutation_fldp_local_foward_sect.
Variable f : string.
Variable tg : tag.
Variables t t' : g.-typ.
Hypothesis tgt' : styp tg = t'.
Hypothesis f_t : assoc_get f (get_fields g tg) = Some t.
Variable e2 : exp sigma t.
Lemma hoare_mutation_fldp_local_forward (e1 : exp sigma (:* t')) (lvs : logs _) :
{{ fun s h => ([ e1 ]_ s |lV~> log_of_styp _ _ tgt' lvs) s h }}
fldp _ _ e1 tgt' f_t *<- e2
{{ fun s h => forall lv, ([ e2 ]_ s) |x| lv ->
([ e1 ]_ s |lV~>
log_of_styp _ _ tgt' (values_set _ _ lv _ lvs (assoc_get_in f_t))) s h }}.
Proof.
apply hoare_stren with
(wp_mutation (fldp _ _ e1 tgt' f_t) e2 (fun s h =>
forall val, ([ e2 ]_ s) |x| val ->
([ e1 ]_ s |lV~> log_of_styp _ _ tgt'
(values_set _ _ val _ lvs (assoc_get_in f_t))) s h)); last by apply hoare_hoare0, hoare0_mutation.
move => s h //= HP.
inversion HP; subst => //=.
simpl in tgt'.
apply Eqdep.EqdepTheory.inj_pair2 in H2.
subst vs0.
move: (log_mapstos_mapsto _ _ _ _ _ (assoc_get_in f_t) _ H6) => [] h1' [] h2' [] Hdisj [] Heq Hmapsto'.
move: (log_mapsto_heap_get_ex _ _ _ Hmapsto') => [] x Hx.
rewrite padd_0 in Hmapsto'; last 2 first.
by apply align_gt0.
eapply dvdn_trans; last by apply H3.
rewrite -nth0.
apply align_get_fields => //.
by apply assoc_get_in.
rewrite -has_predT.
apply/hasP.
exists (f, t) => //.
by apply: assoc_get_in.
rewrite addn0 in Hmapsto'.
have Htmp' : h0 # pad.
clear Hx.
apply log_mapstos_inv_heap_dom in H6.
by rewrite hp.disjE H6 H10 dis_iota // H6 size_iota.
have Htmp : Z_of_nat (field_address 0 _ _ (get_fields g tg) (assoc_get_in f_t)) <=
Z_of_nat (size (hp.dom h0)) +
Z_of_nat
(padd ('|u2Z (ptr<=phy ([ e1 ]_ s))| + size (hp.dom h0))
(align t')).
have H1': (field_address 0 _ _ (get_fields g tg) (assoc_get_in f_t) < sizeof t')%nat.
by eapply lt_field_address0_sizeof; eauto.
have H2': size (hp.dom (h0 \U pad)) = sizeof t'.
apply log_mapsto_inv_heap_dom in HP.
by rewrite HP size_iota.
have H3' : (size (hp.dom (h0 \U pad)) = size (hp.dom h0) + size (hp.dom pad))%nat.
by rewrite hp_prop_m.size_dom_union.
have H5_: size (hp.dom pad) = padd ('|u2Z (ptr<=phy ([ e1 ]_ s))| + size (hp.dom h0)) (align t').
by rewrite H10 size_iota.
rewrite -H5_ -inj_plus plusE -H3' H2'.
apply inj_le.
apply/leP.
apply ltnW.
exact H1'.
apply wp_mutation_c with (v := x).
- apply heap_get_value_union_L => //.
rewrite Heq.
apply heap_get_value_union_L; first by map_tac_m.Disj.
rewrite -value_phy_shift_pointer.
+ rewrite padd_0 in Hx; last 2 first.
by apply align_gt0.
eapply dvdn_trans; last by apply H3.
rewrite -nth0.
apply align_get_fields => //.
by apply assoc_get_in.
rewrite -has_predT.
apply/hasP.
exists (f, t) => //.
by apply: assoc_get_in.
rewrite addn0 in Hx.
rewrite -field_address_slide0 // => i Hi str_dummy ty_dummy Hdummy.
eapply dvdn_trans; last by apply H3.
by apply align_get_fields.
+ apply: (leZ_ltZ_trans _ H4).
rewrite inj_plus Z_of_nat_Zabs_nat; last exact/min_u2Z.
rewrite -addZA; apply leZ_add2l.
exact Htmp.
- move => val Hval /=.
rewrite -value_phy_shift_pointer.
+ by apply values_set_heap_upd.
+ apply: (leZ_ltZ_trans _ H4).
rewrite inj_plus Z_of_nat_Zabs_nat; last exact/min_u2Z.
rewrite -addZA; apply leZ_add2l.
exact Htmp.
Qed.
Lemma hoare_mutation_fldp_local_forward_ground_le
(e1 : exp sigma (:* t')) (He2 : vars e2 = nil) val lvs :
ground_exp e2 He2 |x| val ->
{{ e1 |le~> log_of_styp _ _ tgt' lvs }}
fldp _ _ e1 tgt' f_t *<- e2
{{ e1 |le~> log_of_styp _ _ tgt' (values_set _ _ val _ lvs (assoc_get_in f_t)) }}.
Proof.
move=> Hequiv.
eapply hoare_weak; last by apply hoare_mutation_fldp_local_forward.
move=> s h //=.
apply.
by rewrite ground_exp_sem.
Qed.
Lemma hoare_mutation_fldp_local_forward_ground_lV (v1 : (:* t').-phy) He2 val lvs :
(ground_exp e2 He2) |x| val ->
{{ v1 |lV~> log_of_styp _ _ tgt' lvs }}
fldp _ _ [ v1 ]c tgt' f_t *<- e2
{{ v1 |lV~> log_of_styp _ _ tgt' (values_set _ _ val _ lvs (assoc_get_in f_t)) }}.
Proof.
move=> Hequiv.
eapply hoare_weak; last by apply hoare_mutation_fldp_local_forward with (e1 := [ v1 ]c).
move => s h //=.
apply.
by rewrite ground_exp_sem.
Qed.
End hoare_mutation_fldp_local_foward_sect.
Section hoare_mutation_fldp_subst_sect.
Variable f : string.
Variable tg : tag.
Variable t t' : g.-typ.
Hypothesis tgt' : styp tg = t'.
Hypothesis f_t : assoc_get f (get_fields g tg) = Some t.
Variable e1 : exp sigma (:* t').
Variable e2 : exp sigma t.
Lemma hoare_mutation_fldp_subst_ityp str (t'' : integral) Hstr (e : exp sigma (ityp: t'')) P Q :
P ===> `! \b @var_e g _ str (ityp: t'') Hstr \= e ** TT ->
{{ P }}
fldp _ _ (subst_exp str Hstr e e1) tgt' f_t *<- subst_exp str Hstr e e2
{{ Q }} ->
{{ P }} fldp _ _ e1 tgt' f_t *<- e2 {{ Q }}.
Proof.
move => HP Hoare.
apply hoare_complete => s h HPsh.
move: (soundness _ _ _ Hoare s h HPsh) => [] Hsem1 Hsem2.
have He': forall e', [subst_exp _ Hstr e e']_ s = [e']_ s.
move => c e'.
have Hb : (`! \b var_e _ str (ityp: t'') Hstr \= e) s hp.emp.
move: (HP _ _ HPsh) => H'.
inversion H'; subst; clear H'.
split; last by done.
by apply (proj1 H0).
rewrite subst_exp_store_upd.
by rewrite -(bbang_eqi_store_get _ _ _ _ _ _ Hb) store_upd_get_eq.
split.
- move => H'.
apply Hsem1.
Transparent eval.
inversion_clear H'; inversion H; subst; clear H.
constructor; eapply exec_mutation_err => //=.
unfold a in *.
apply Eqdep.EqdepTheory.inj_pair2 in H4; subst e4.
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e5.
rewrite He'; exact H1.
- move => s' h' Hsem.
apply Hsem2.
inversion_clear Hsem.
inversion H; subst; clear H.
rewrite -(He' _ e5).
unfold a0 in *.
apply Eqdep.EqdepTheory.inj_pair2 in H4; subst e4.
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e5.
rewrite /= -(He' _ e1).
constructor; eapply exec_mutation => //=.
rewrite /= in H1.
rewrite (He' _ e1); exact H1.
Opaque eval.
Qed.
P => str = e'' -> { P } e1{e''/str}.f *<- e2{e''/str} { Q } -> { P } e1.f *<- e2 { Q }
Lemma hoare_mutation_fldp_subst_ptr str (t'' : g.-typ) Hstr (e'' : exp sigma (:* t'')) P Q :
P ===> `! \b @var_e g _ str (:* t'') Hstr \= e'' ** TT ->
{{ P }}
fldp _ _ (subst_exp str Hstr e'' e1) tgt' f_t *<- subst_exp str Hstr e'' e2
{{ Q }} ->
{{ P }} fldp _ _ e1 tgt' f_t *<- e2 {{ Q }}.
Proof.
Transparent eval.
move => HP Hoare.
apply hoare_complete => s h HPsh.
move: (soundness _ _ _ Hoare s h HPsh) => [] Hsem1 Hsem2.
have He' : forall e', [subst_exp str Hstr e'' e']_ s = [ e' ]_ s.
move => c e'.
have Hb : (`! \b var_e _ str (:* t'') Hstr \= e'') s hp.emp.
move: (HP _ _ HPsh) => H'.
inversion H'; subst; clear H'.
split; last by done.
by apply (proj1 H0).
by rewrite subst_exp_store_upd -(bbang_eqp_store_get _ _ _ _ _ _ Hb) store_upd_get_eq.
split.
- move => H'.
apply Hsem1.
inversion_clear H'; inversion H; subst; clear H.
constructor; eapply exec_mutation_err => //=.
unfold a in *.
apply Eqdep.EqdepTheory.inj_pair2 in H4; subst e4.
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e5.
rewrite He'; exact H1.
- move => s' h' Hsem.
apply Hsem2.
inversion_clear Hsem.
inversion H; subst; clear H.
rewrite -(He' _ e5).
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e5.
rewrite He'.
unfold a0 in *.
apply Eqdep.EqdepTheory.inj_pair2 in H4; subst e4.
rewrite -(He' _ e2) /= -(He' _ e1).
constructor; eapply exec_mutation => //=.
rewrite (He' _ e1); exact H1.
Opaque eval.
Qed.
End hoare_mutation_fldp_subst_sect.
P ===> `! \b @var_e g _ str (:* t'') Hstr \= e'' ** TT ->
{{ P }}
fldp _ _ (subst_exp str Hstr e'' e1) tgt' f_t *<- subst_exp str Hstr e'' e2
{{ Q }} ->
{{ P }} fldp _ _ e1 tgt' f_t *<- e2 {{ Q }}.
Proof.
Transparent eval.
move => HP Hoare.
apply hoare_complete => s h HPsh.
move: (soundness _ _ _ Hoare s h HPsh) => [] Hsem1 Hsem2.
have He' : forall e', [subst_exp str Hstr e'' e']_ s = [ e' ]_ s.
move => c e'.
have Hb : (`! \b var_e _ str (:* t'') Hstr \= e'') s hp.emp.
move: (HP _ _ HPsh) => H'.
inversion H'; subst; clear H'.
split; last by done.
by apply (proj1 H0).
by rewrite subst_exp_store_upd -(bbang_eqp_store_get _ _ _ _ _ _ Hb) store_upd_get_eq.
split.
- move => H'.
apply Hsem1.
inversion_clear H'; inversion H; subst; clear H.
constructor; eapply exec_mutation_err => //=.
unfold a in *.
apply Eqdep.EqdepTheory.inj_pair2 in H4; subst e4.
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e5.
rewrite He'; exact H1.
- move => s' h' Hsem.
apply Hsem2.
inversion_clear Hsem.
inversion H; subst; clear H.
rewrite -(He' _ e5).
apply Eqdep.EqdepTheory.inj_pair2 in H5; subst e5.
rewrite He'.
unfold a0 in *.
apply Eqdep.EqdepTheory.inj_pair2 in H4; subst e4.
rewrite -(He' _ e2) /= -(He' _ e1).
constructor; eapply exec_mutation => //=.
rewrite (He' _ e1); exact H1.
Opaque eval.
Qed.
End hoare_mutation_fldp_subst_sect.
Conditional branching
Lemma hoare_ifte_bang P Q b c d :
{{ P ** `! b }} c {{ Q }} -> {{ P ** `! \~b b }} d {{ Q }} ->
{{ P }} ifte b c d {{ Q }}.
Proof.
move => H1 H2.
apply hoare_ifte.
- eapply hoare_stren; last by apply H1.
rewrite /bbang /bang /eval_b /C_Semop0.eval_b /emp /= => s h HPre; inversion HPre; subst; clear HPre.
rewrite -(hp.unionhe h).
constructor => //=; by Disj.
- eapply hoare_stren; last by apply H2.
rewrite /bbang /bang /eval_b /C_Semop0.eval_b /emp /= => s h HPre; inversion HPre; subst; clear HPre.
rewrite -(hp.unionhe h).
constructor => //=; by Disj.
Qed.
Lemma hoare_ifte_left_bang P Q b c d : P ===> `! b ->
{{ P }} c {{ Q }} -> {{ P }} ifte b c d {{ Q }}.
Proof.
move => HP Hhoare.
apply hoare_ifte_bang.
apply hoare_stren with P => //=.
move => s h H; inversion H; subst; clear H.
rewrite /bbang /bang in H2; inversion_clear H2.
by rewrite H3 hp.unionhe.
eapply hoare_stren; last by apply hoare_L_F.
move => s h H; inversion H; subst; clear H.
case: H2 => H2 H3.
case: (HP _ _ H1) => H' _.
rewrite beval_neg_not in H2.
rewrite /bbang /bang /= in H'.
move/negP in H2; contradiction.
Qed.
Lemma hoare_ifte_right_bang P Q b c d : P ===> `! \~b b ->
{{ P }} d {{ Q }} -> {{ P }} ifte b c d {{ Q }}.
Proof.
move => HP Hhoare.
apply hoare_ifte_bang.
- eapply hoare_stren; last by apply hoare_L_F.
move => s h H; inversion H; subst; clear H.
inversion_clear H2.
move: (HP _ _ H1).
inversion_clear 1.
move: H2.
rewrite beval_neg_not.
move/negP.
contradiction.
- apply hoare_stren with P => //=.
move => s h; inversion 1; subst; clear H.
rewrite /bbang /bang in H2; inversion_clear H2.
by rewrite H3 hp.unionhe.
Qed.
Hoare triples about while-loops
Lemma hoare_while_invariant_bang (P : assert) (t : bexp sigma) (c : cmd) (Q Inv : assert) :
P ===> Inv ->
Inv ** `! \~b t ===> Q ->
{{ Inv ** `! t }} c {{ Inv }} ->
{{ P }} while t c {{ Q }}.
Proof.
move=> H1 H2 H3.
move: (hoare_while_invariant P t c Q Inv H1).
rewrite /eval_b //=.
apply.
eapply ent_trans; last by apply H2.
move => s h [] H4 H5.
rewrite -(hp.unionhe h).
constructor => //=; by map_tac_m.Disj.
eapply hoare_stren; last by apply H3.
move => s h //= [] H4 H5.
rewrite -(hp.unionhe h).
constructor => //=; by map_tac_m.Disj.
Qed.
Definition forloop c1 pre_test test c2 body :=
c1 ;
pre_test ;
While \b test {{
body ;
c2 ;
pre_test
}}.
Notation "'For(' c1 '\;' pretest '\,' test '\;' c2 '){{' c '}}' " :=
(forloop c1 pretest test c2 c)
(at level 200, format
"'[v' 'For(' c1 '\;' '//' pretest '\,' '//' test '\;' '//' c2 '){{' '//' '[' c ']' '//' '}}' ']'") : whilesemop_scope.
Notation "'For(' c1 '\;' test '\;' c2 '){{' c '}}' " :=
(forloop c1 skip test c2 c)
(at level 200, format
"'[v' 'For(' c1 '\;' '//' test '\;' '//' c2 '){{' '//' '[' c ']' '//' '}}' ']'") : whilesemop_scope.
Lemma hoare_forloop c1 pre_test test c2 body (P Q : assert) :
{{ Q }} c1 {{ P }} ->
{{ P }} pre_test {{ P }} ->
{{ `! \b test ** P }} body ; c2 ; pre_test {{ P }} ->
{{ Q }} forloop c1 pre_test test c2 body {{ `! \~b \b test ** P}}.
Proof.
move=> Hc1 Hpre_test H.
rewrite /forloop.
apply hoare_seq with P => //.
apply hoare_seq with P => //.
apply hoare_while_invariant_bang with P => //.
rewrite conC; by apply ent_id.
by rewrite conC.
Qed.
Lemma hoare_forloop2 c1 pre_test test c2 body (P Q inv : assert) :
{{ P }} c1; pre_test {{ inv }} ->
`! \~b \b test ** inv ===> Q ->
{{ `! \b test ** inv }} body ; c2; pre_test {{ inv }} ->
{{ P }} forloop c1 pre_test test c2 body {{ Q }}.
Proof.
move=> H1 H2 H3.
apply hoare_seq_assoc', hoare_seq with inv => //.
apply hoare_while_invariant with inv => //.
- eapply ent_trans; last by apply H2.
rewrite conC /C_definition.eval_b /C_StateBipl.eval_b /=.
by apply equiv_imp2, con_and_bang_R.
- eapply hoare_stren; last by apply H3.
rewrite conC /C_definition.eval_b /C_StateBipl.eval_b /=.
by apply equiv_imp2, con_and_bang_R.
Qed.
Set Implicit Arguments.
Unset Strict Implicit.
Section wp_assign_con_variants.
Variable (str : string) (t : g.-typ).
Hypothesis str_t : assoc_get str sigma = Some t.
Variable e : exp sigma t.
Variables P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15 P16 P17 P18 P19 : assert.
Lemma wp_assign_con2 : wp_assign str_t e (P0 ** P1 ** P2) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con3 : wp_assign str_t e (P0 ** P1 ** P2 ** P3) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con4 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con5 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con6 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con7 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7.
Proof.
by do 7 rewrite wp_assign_con.
Qed.
Lemma wp_assign_con8 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con9 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con10 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con11 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con12 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con13 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con14 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13 ** P14) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13 ** wp_assign str_t e P14.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con15 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13 ** P14 ** P15) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13 ** wp_assign str_t e P14 **
wp_assign str_t e P15.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con16 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13 ** P14 ** P15 ** P16) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13 ** wp_assign str_t e P14 **
wp_assign str_t e P15 ** wp_assign str_t e P16.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con17 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13 ** P14 ** P15 ** P16 ** P17) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13 ** wp_assign str_t e P14 **
wp_assign str_t e P15 ** wp_assign str_t e P16 ** wp_assign str_t e P17.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con18 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13 ** P14 ** P15 ** P16 ** P17 ** P18) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13 ** wp_assign str_t e P14 **
wp_assign str_t e P15 ** wp_assign str_t e P16 ** wp_assign str_t e P17 **
wp_assign str_t e P18.
Proof.
by do ! rewrite wp_assign_con.
Qed.
Lemma wp_assign_con19 : wp_assign str_t e (P0 ** P1 ** P2 ** P3 ** P4 ** P5 ** P6 ** P7 ** P8 ** P9 ** P10 ** P11 ** P12 ** P13 ** P14 ** P15 ** P16 ** P17 ** P18 ** P19) <==>
wp_assign str_t e P0 ** wp_assign str_t e P1 ** wp_assign str_t e P2 **
wp_assign str_t e P3 ** wp_assign str_t e P4 ** wp_assign str_t e P5 **
wp_assign str_t e P6 ** wp_assign str_t e P7 ** wp_assign str_t e P8 **
wp_assign str_t e P9 ** wp_assign str_t e P10 ** wp_assign str_t e P11 **
wp_assign str_t e P12 ** wp_assign str_t e P13 ** wp_assign str_t e P14 **
wp_assign str_t e P15 ** wp_assign str_t e P16 ** wp_assign str_t e P17 **
wp_assign str_t e P18 ** wp_assign str_t e P19.
Proof.
by do ! rewrite wp_assign_con.
Qed.
End wp_assign_con_variants.
Ltac count_sepcons P :=
match P with
| (?P1 ** ?P2) => let n1 := count_sepcons P1 in
let n2 := count_sepcons P2 in
constr: ((1 + n1 + n2)%nat)
| _ => O
end.
Ltac easy_Ent_monotony_R new_goal H :=
apply ent_trans with new_goal;
[ clear H | repeat (apply monotony_R || apply monotony_L); exact H].
Ltac easy_Ent_monotony_L new_goal H :=
apply ent_trans with new_goal;
[ repeat (apply monotony_R || apply monotony_L); exact H | clear H ].
Ltac Ent_R_subst_con_distr_generic_helper ctxt wp_assign_con_lemma :=
let H := fresh in
generalize (equiv_imp2 _ _ wp_assign_con_lemma); intro H ;
match goal with
| H : ?Hsubst ===> _ |- _ =>
let new_goal := context ctxt [ Hsubst ] in
easy_Ent_monotony_R new_goal H
end.
Ltac Ent_R_subst_con_distr_generic :=
match goal with
| |- _ ===> ?rhs =>
match rhs with
| context ctxt' [wp_assign ?H ?expr (?P ** ?Q)] =>
let n := count_sepcons (P ** Q) in
let n' := eval compute in (n <= 19)%nat in
match n' with
| true =>
match rhs with
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14 ** ?P15 ** ?P16 ** ?P17 ** ?P18 ** ?P19 ** ?P20)] =>
let tmp := constr: (@wp_assign_con19 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P15 P16 P17 P18 P19 P10) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14 ** ?P15 ** ?P16 ** ?P17 ** ?P18 ** ?P19)] =>
let tmp := constr: (@wp_assign_con18 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P15 P16 P17 P18 P19) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14 ** ?P15 ** ?P16 ** ?P17 ** ?P18)] =>
let tmp := constr: (@wp_assign_con17 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P15 P16 P17 P18) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14 ** ?P15 ** ?P16 ** ?P17)] =>
let tmp := constr: (@wp_assign_con16 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P15 P16 P17) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14 ** ?P15 ** ?P16)] =>
let tmp := constr: (@wp_assign_con15 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P15 P16) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14 ** ?P15)] =>
let tmp := constr: (@wp_assign_con14 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P15) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13 ** ?P14)] =>
let tmp := constr: (@wp_assign_con13 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12 ** ?P13)] =>
let tmp := constr: (@wp_assign_con12 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11 ** ?P12)] =>
let tmp := constr: (@wp_assign_con11 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10 ** ?P11)] =>
let tmp := constr: (@wp_assign_con10 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9 ** ?P10)] =>
let tmp := constr: (@wp_assign_con9 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9 P10) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8 ** ?P9)] =>
let tmp := constr: (@wp_assign_con8 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8 P9) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7 ** ?P8)] =>
let tmp := constr: (@wp_assign_con7 _ _ H expr P1 P2 P3 P4 P5 P6 P7 P8) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6 ** ?P7)] =>
let tmp := constr: (@wp_assign_con6 _ _ H expr P1 P2 P3 P4 P5 P6 P7) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5 ** ?P6)] =>
let tmp := constr: (@wp_assign_con5 _ _ H expr P1 P2 P3 P4 P5 P6) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4 ** ?P5)] =>
let tmp := constr: (@wp_assign_con4 _ _ H expr P1 P2 P3 P4 P5) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3 ** ?P4)] =>
let tmp := constr: (@wp_assign_con3 _ _ H expr P1 P2 P3 P4) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P1 ** ?P2 ** ?P3)] =>
let tmp := constr: (@wp_assign_con2 _ _ H expr P1 P2 P3) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| context ctxt [wp_assign ?H ?expr (?P ** ?Q)] =>
let tmp := constr: (@wp_assign_con _ _ H expr P Q) in
Ent_R_subst_con_distr_generic_helper ctxt tmp
| _ => fail "Ent_R_subst_con_distr: shouldn't happen"
end
| false => idtac "Ent_R_subst_con_distr: rewrite !wp_assign_con" ; fail
end
end
end.
Ltac Ent_R_subst_con_distr :=
match goal with
| |- _ ===> ?rhs =>
match rhs with
| wp_assign ?H ?expr (?P ** ?Q) =>
let n := count_sepcons (P ** Q) in
let n' := eval compute in n in
match n' with
| 1%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con _ _ _ _))
| 2%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con2 _ _ _ _ _))
| 3%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con3 _ _ _ _ _ _))
| 4%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con4 _ _ _ _ _ _ _))
| 5%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con5 _ _ _ _ _ _ _ _))
| 6%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con6 _ _ _ _ _ _ _ _ _))
| 7%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con7 _ _ _ _ _ _ _ _ _ _))
| 8%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con8 _ _ _ _ _ _ _ _ _ _ _))
| 9%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con9 _ _ _ _ _ _ _ _ _ _ _ _))
| 10%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con10 _ _ _ _ _ _ _ _ _ _ _ _ _))
| 11%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con11 _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 12%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con12 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 13%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con13 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 14%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con14 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 15%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con15 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 16%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con16 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 17%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con17 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 18%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con18 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| 19%nat => eapply ent_trans; last by apply (equiv_imp2 _ _ (wp_assign_con19 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _))
| _ => fail "Ent_R_subst_con_distr: not yet supported"
end
| context ctxt [wp_assign ?H ?expr (?P ** ?Q)] => Ent_R_subst_con_distr_generic
| _ => fail "Ent_R_subst_con_distr: use rewrite !wp_assign_con"
end
end.
Lemma hoare_pullout_sbang_postcond (P : assert) (c : cmd) (Q : assert) (R : Prop) :
R -> {{P}}c {{Q}} -> {{ P }} c {{ !!(R) ** Q}}.
Proof.
move => r Hoare.
apply hoare_weak with Q; last by [].
move => s h HQ.
rewrite -(hp.unioneh h).
constructor; by [map_tac_m.Disj | |].
Qed.
Lemma ground_bbang_sbang (b : bexp sigma) (H : bvars b = nil) :
`! b <==> sbang (ground_bexp b H).
Proof.
move => s h; rewrite /bbang /bang /sbang; split; split.
- case: H0 => H1 H2.
by rewrite -(ground_bexp_sem s _ H).
- by case: H0.
- rewrite (ground_bexp_sem s _ H); tauto.
- tauto.
Qed.
Lemma entail_exists_left_intro {A : Type} (P : A -> assert) Q:
(forall x, P x ===> Q) -> (sepex x, P x) ===> Q.
Proof. move => H s h [] x Hx; by apply (H x). Qed.
Lemma entail_exists_right_intro {A : Type} (P : A -> assert) Q:
(exists x, Q ===> P x) -> Q ===> (sepex x, P x).
Proof. move => [] x Hx s h H; by exists x; apply Hx. Qed.
Lemma exists_left_prenex {A : Type} (P : A -> assert) Q :
(sepex x, P x) ** Q <==> sepex x, P x ** Q.
Proof.
split.
- case=> h1 h2 h1dh2 [x Hh1] Hh2; by exists x.
- case=> x [h1 h2 h1dh2 Hh1 Hh2]; apply con_c => //; by exists x.
Qed.
independence of assertion w.r.t. variables
Section only_dep_sect.
Definition only_dep (l : g.-env) (Hl : {subset l <= sigma}) (P : assert) :=
forall s h,
(forall x ty v (H : (x, ty) \notin l) (H0 : (x, ty) \in sigma),
(P s h <->
P (store_upd (assoc_get_subset_in uniq_sigma (fun _ => id) H0) v s) h)).
Lemma only_dep_equiv (l : g.-env) (Hl : {subset l <= sigma}) (P Q : assert) :
(P <==> Q) -> (only_dep Hl P <-> only_dep Hl Q).
Proof.
move=> Hequiv; split => H; move => s h x ty v H0 H1;
split => H2; by apply/Hequiv/(H s h x ty v H0 H1)/Hequiv.
Qed.
Lemma only_dep_contraction P (l' : g.-env) (H' : {subset l' <= sigma})
(l : g.-env) (H : {subset l <= sigma}) : l =i l' ->
only_dep H' P -> only_dep H P.
Proof.
move => ll' Hsub s h str ty v H1 H2.
by apply Hsub; rewrite -ll'.
Qed.
Lemma only_dep_inde_cmd c P l Hl : @only_dep l Hl P ->
forall l', l' = unzip1 l ->
(all (fun s => s \notin l') (unzip1 (modified_vars c))) ->
inde_cmd c P.
Proof.
move => Hdep l' Hl' Hbool s h x ty v H.
move: {Hdep}(Hdep s h x ty v) => Hdep.
have Hnotin: (x, ty) \notin l.
move/allP in Hbool.
subst l'.
apply notin_unzip1_notin, Hbool.
by apply/mapP; exists (x, ty).
have Hin : (x, ty) \in sigma by apply (modified_vars_subset_type_store c).
move : (assoc_get_subset_in _ _ _) (assoc_get_subset_in _ _ _)
(Hdep Hnotin Hin) => ob ob1.
by have ->: ob = ob1 by apply/eq_irrelevance.
Qed.
Lemma sepex_only_dep {A} lP HlP (P : A -> assert):
(forall x, @only_dep lP HlP (P x)) -> @only_dep lP HlP (sepexists P).
Proof.
move => H s h x ty v H0 H1; split.
- inversion_clear 1.
exists x0.
exact/(H x0 s h x ty v H0 H1).
- inversion_clear 1.
exists x0.
exact/(H x0 s h x ty v H0 H1).
Qed.
Lemma bbang_only_dep b : only_dep (bvars_subset_sigma b) (`! b).
Proof.
move => s h x ty v H0 H1; split; case=> H2 H3.
- split => //.
rewrite beval_store_upd_notin //.
by apply (uniq_subset_notin uniq_sigma (bvars_subset_sigma b) H0 H1).
- split => //.
rewrite beval_store_upd_notin // in H2.
by apply (uniq_subset_notin uniq_sigma (bvars_subset_sigma b) H0 H1).
Qed.
Lemma mapstos_store_upd_notin {ty : g.-typ} s
(ty' : g.-typ) y (H : env_get y sigma = Some ty') pval:
forall (l : seq (ty.-phy)) (e : exp sigma (:* ty)) (Hnotin: y \notin (unzip1 (vars e))),
(forall h, (e |--> l) s h <-> (e |--> l) (store_upd H pval s) h).
Proof.
elim => //= hd tl Hind; split.
- move => Hcon; inversion Hcon; subst; clear Hcon.
constructor => //=.
by rewrite eval_store_upd_notin.
apply/Hind => //=; by rewrite cats0.
- move => Hcon; inversion Hcon; subst; clear Hcon.
constructor => //=.
by rewrite eval_store_upd_notin in H1.
apply/Hind => //=; by rewrite cats0.
Qed.
Lemma mapstos_only_dep (t : g.-typ) (e : exp sigma (:* t)) l :
only_dep (vars_in_ts e) (e |--> l).
Proof.
move => s h x ty' v H0 H1.
apply mapstos_store_upd_notin, (uniq_subset_notin uniq_sigma (vars_in_ts e) H0 H1).
Qed.
Lemma log_mapsto_only_dep (ty : g.-typ) (p : (:* ty).-phy) (l : log ty) :
only_dep (@subset_nil _ sigma) (p |lV~> l).
Proof. by []. Qed.
Lemma log_mapsto_e_only_dep (ty : g.-typ) (e : exp sigma (:* ty)) (l : log ty):
only_dep (vars_in_ts e) (e |le~> l).
Proof.
move => s h x ty' v H0 H1.
rewrite /= eval_store_upd_notin //.
apply (uniq_subset_notin uniq_sigma (vars_in_ts e) H0 H1).
Qed.
Lemma sbang_only_dep (b : Prop) : only_dep (@subset_nil _ sigma) (!!( b )).
Proof. by []. Qed.
Lemma con_only_dep P Q lP HlP lQ HlQ :
@only_dep lP HlP P -> @only_dep lQ HlQ Q ->
@only_dep (lP ++ lQ) (subset_cat HlQ HlP) (P ** Q).
Proof.
move => HP HQ s h x ty v H0 H1.
move: H0 (H0) => H0' H0; move: H0'.
rewrite mem_cat negb_or; case/andP => HnotinP HnotinQ.
split; case => h1 h2 H2 H3 H4; by constructor => //;
[ apply (HP s h1 x ty v HnotinP H1) |
apply (HQ s h2 x ty v HnotinQ H1) ].
Qed.
Lemma sepor_only_dep P Q lP HlP lQ HlQ:
@only_dep lP HlP P -> @only_dep lQ HlQ Q ->
@only_dep (lP ++ lQ) (subset_cat HlQ HlP) (P \\// Q).
Proof.
move => HP HQ s h x ty v H0 H1.
move: H0 (H0) => H0' H0; move: H0'.
rewrite mem_cat negb_or; case/andP => HnotinP HnotinQ.
split; by case => H;[ left; apply (HP s h x ty v HnotinP H1) |
right; apply (HQ s h x ty v HnotinQ H1) ].
Qed.
Lemma bang_only_dep k b {ty} (e : exp sigma (:* ty)) :
@only_dep (vars e) (vars_in_ts e) (!(fun s =>
(u2Z (ptr<=phy [ e ]_s) + k < b)%Z)).
Proof.
rewrite /only_dep => s h str tu' v H1 H2.
rewrite /bang eval_store_upd_notin; first by tauto.
apply (uniq_subset_notin uniq_sigma (vars_in_ts e) H1 H2).
Qed.
Lemma mapstos_fit_only_dep {ty : g.-typ} (e : exp sigma (:* ty)) l :
only_dep (vars_in_ts e) (e |---> l).
Proof.
rewrite /mapstos_fit.
suff : @only_dep (vars e ++ vars e) (vars_in_ts (e \= e))
(e |--> l ** !(fun s => (Z<=u (ptr<=phy [e ]_ s) +
Z<=nat (sizeof ty * size l) < 2 ^^ ptr_len)%Z)).
apply only_dep_contraction => i; by rewrite mem_cat orb_idl.
eapply con_only_dep; by [apply mapstos_only_dep | apply bang_only_dep].
Qed.
End only_dep_sect.
Local Close Scope Z_scope.
Local Open Scope machine_int_scope.
Lemma mod_1_even e : `! \b e \% 1 \= ([ 0 ]sc : exp _ (ityp: sint)) ===>
(sepex k, `! \b e \= [ zext 1 (k : int 31) `<< 1 ]pc).
Proof.
move=> s h [] H H'; rewrite /emp in H'; subst h.
Transparent eval beval.
move: H => /=.
move He : ( [ e ]_s) => [he Hhe].
set H' := eq_ind_r _ _ _.
have -> : H' = Hhe by apply eq_irrelevance.
rewrite /= !i8_of_i32K.
case: ifP; last by rewrite is_zero_0.
rewrite not_is_zero_1.
move/eqP/s2Z_inj => H _.
rewrite Z2s_Z2u_k // in H.
set lhs := _ `% 32 in H.
have {}H : u2Z lhs = u2Z zero32 by rewrite H.
rewrite /lhs {lhs} u2Z_rem' in H; last first.
apply (@ltZ_trans (2 ^^ 1)%Z) => //; exact/max_u2Z.
exists ((i32<=i8 he Hhe `>> 1) `% 31); split => //=.
rewrite He -/H'.
set H'' := eq_ind_r _ _ _.
rewrite i8_of_i32K.
case: ifP; first by rewrite not_is_zero_1.
have -> : H' = Hhe by apply eq_irrelevance.
rewrite is_zero_0 /= => <-.
apply/eqP.
congr (Z<=s).
have -> : zext 1 ((i32<=i8 he Hhe `>> 1) `% 31) = (i32<=i8 he Hhe `>> 1).
rewrite shrl_rem.
apply u2Z_inj.
by rewrite u2Z_eq_rect.
symmetry.
apply shrl_shl.
rewrite Z2uK // (_ : 0%Z = u2Z (Z2u 1 0)) in H; last by rewrite Z2uK.
by move/u2Z_inj: H.
Opaque eval beval.
Qed.
Local Close Scope machine_int_scope.
Lemma b_le_trans_L a b (c : exp sigma (ityp: sint)) :
(- 2 ^^ 31 <= b <= a)%Z -> (a < 2 ^^ 31)%Z ->
`! \b [ a ]sc \<= c ===> `! \b [ b ]sc \<= c.
Proof.
move=> Hba Ha s h [] H1.
rewrite /emp => ?; subst h.
split => //.
Transparent eval beval.
move: H1 => /=.
move Hc : ( [ c ]_s ) => [hc Hhc].
rewrite 2!i8_of_i32K Z2sK; last lia.
rewrite Z2sK; last lia.
case: ifP => [H1 _ | ]; last by rewrite is_zero_0.
case: ifP; first by rewrite not_is_zero_1.
move/leZP/Znot_le_gt => H2.
exfalso.
move/leZP in H1; lia.
Opaque eval beval.
Qed.
Lemma b_le_trans_R a b (c : exp sigma (ityp: sint)) :
(- 2 ^^ 31 <= a <= b)%Z -> (b < 2 ^^ 31)%Z ->
`! \b c \<= [ a ]sc ===> `! \b c \<= [ b ]sc.
Proof.
move=> Hab Ha s h [] H1.
rewrite /emp => ?; subst h.
split => //.
Transparent eval beval.
move: H1 => /=.
move Hc : ( [ c ]_s ) => [hc Hhc].
rewrite 2!i8_of_i32K Z2sK; last lia.
rewrite Z2sK; last lia.
case: ifP => [H1 _ | ]; last by rewrite is_zero_0.
case: ifP; first by rewrite not_is_zero_1.
move/leZP/Znot_le_gt => H2.
exfalso.
move/leZP in H1; lia.
Opaque eval beval.
Qed.
End C_Contrib_f.