You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
semantics-2023/theories/program_logics/heap_lang/primitive_laws.v

178 lines
7.1 KiB

(** This file proves the basic laws of the HeapLang program logic by applying
the Iris lifting lemmas. *)
From iris.proofmode Require Import proofmode.
From iris.bi.lib Require Import fractional.
From iris.base_logic.lib Require Export gen_heap.
From semantics.pl.program_logic Require Export sequential_wp.
From semantics.pl.program_logic Require Import ectx_lifting.
From iris.heap_lang Require Export class_instances.
From iris.heap_lang Require Import tactics notation.
From semantics.pl.program_logic Require Export notation.
From iris.prelude Require Import options.
Class heapGS Σ := HeapGS {
heapGS_invGS : invGS_gen HasNoLc Σ;
heapGS_gen_heapGS : gen_heapGS loc (option val) Σ;
}.
#[export] Existing Instance heapGS_gen_heapGS.
Global Instance heapGS_irisGS `{!heapGS Σ} : irisGS heap_lang Σ := {
iris_invGS := heapGS_invGS;
state_interp σ := (gen_heap_interp σ.(heap))%I;
}.
(** Since we use an [option val] instance of [gen_heap], we need to overwrite
the notations. That also helps for scopes and coercions. *)
(** FIXME: Refactor these notations using custom entries once Coq bug #13654
has been fixed. *)
Notation "l ↦{ dq } v" := (mapsto (L:=loc) (V:=option val) l dq (Some v%V))
(at level 20, format "l ↦{ dq } v") : bi_scope.
Notation "l ↦□ v" := (mapsto (L:=loc) (V:=option val) l DfracDiscarded (Some v%V))
(at level 20, format "l ↦□ v") : bi_scope.
Notation "l ↦{# q } v" := (mapsto (L:=loc) (V:=option val) l (DfracOwn q) (Some v%V))
(at level 20, format "l ↦{# q } v") : bi_scope.
Notation "l ↦ v" := (mapsto (L:=loc) (V:=option val) l (DfracOwn 1) (Some v%V))
(at level 20, format "l ↦ v") : bi_scope.
Section lifting.
Context `{!heapGS Σ}.
Implicit Types P Q : iProp Σ.
Implicit Types Φ Ψ : val iProp Σ.
Implicit Types efs : list expr.
Implicit Types σ : state.
Implicit Types v : val.
Implicit Types l : loc.
(** Recursive functions: we do not use this lemmas as it is easier to use Löb
induction directly, but this demonstrates that we can state the expected
reasoning principle for recursive functions, without any visible . *)
Lemma wp_rec_löb s E1 E2 f x e Φ Ψ :
( ( v, Ψ v - WP (rec: f x := e)%V v @ s; E1; E2 {{ Φ }}) -
v, Ψ v - WP (subst' x v (subst' f (rec: f x := e) e)) @ s; E1; E2 {{ Φ }}) -
v, Ψ v - WP (rec: f x := e)%V v @ s; E1; E2 {{ Φ }}.
Proof.
iIntros "#Hrec". iLöb as "IH". iIntros (v) "".
iApply lifting.wp_pure_step_later; first done.
iNext. iApply ("Hrec" with "[] HΨ"). iIntros "!>" (w) "".
iApply ("IH" with "").
Qed.
(** Heap *)
(** We need to adjust the [gen_heap] and [gen_inv_heap] lemmas because of our
value type being [option val]. *)
Lemma mapsto_valid l dq v : l {dq} v - dq.
Proof. apply mapsto_valid. Qed.
Lemma mapsto_valid_2 l dq1 dq2 v1 v2 :
l {dq1} v1 - l {dq2} v2 - (dq1 dq2) v1 = v2.
Proof.
iIntros "H1 H2".
iDestruct (mapsto_valid_2 with "H1 H2") as %[? [=]]. done.
Qed.
Lemma mapsto_agree l dq1 dq2 v1 v2 : l {dq1} v1 - l {dq2} v2 - v1 = v2.
Proof. iIntros "H1 H2". iDestruct (mapsto_agree with "H1 H2") as %[=]. done. Qed.
Lemma mapsto_combine l dq1 dq2 v1 v2 :
l {dq1} v1 - l {dq2} v2 - l {dq1 dq2} v1 v1 = v2.
Proof.
iIntros "Hl1 Hl2". iDestruct (mapsto_combine with "Hl1 Hl2") as "[$ Heq]".
by iDestruct "Heq" as %[= ->].
Qed.
Lemma mapsto_frac_ne l1 l2 dq1 dq2 v1 v2 :
¬ (dq1 dq2) l1 {dq1} v1 - l2 {dq2} v2 - l1 l2.
Proof. apply mapsto_frac_ne. Qed.
Lemma mapsto_ne l1 l2 dq2 v1 v2 : l1 v1 - l2 {dq2} v2 - l1 l2.
Proof. apply mapsto_ne. Qed.
Lemma mapsto_persist l dq v : l {dq} v == l v.
Proof. apply mapsto_persist. Qed.
Lemma heap_array_to_seq_mapsto l v (n : nat) :
([ map] l' ov heap_array l (replicate n v), gen_heap.mapsto l' (DfracOwn 1) ov) -
[ list] i seq 0 n, (l + (i : nat)) v.
Proof.
iIntros "Hvs". iInduction n as [|n] "IH" forall (l); simpl.
{ done. }
rewrite big_opM_union; last first.
{ apply map_disjoint_spec=> l' v1 v2 /lookup_singleton_Some [-> _].
intros (j&w&?&Hjl&_)%heap_array_lookup.
rewrite Loc.add_assoc -{1}[l']Loc.add_0 in Hjl. simplify_eq; lia. }
rewrite Loc.add_0 -fmap_S_seq big_sepL_fmap.
setoid_rewrite Nat2Z.inj_succ. setoid_rewrite <-Z.add_1_l.
setoid_rewrite <-Loc.add_assoc.
rewrite big_opM_singleton; iDestruct "Hvs" as "[$ Hvs]". by iApply "IH".
Qed.
Lemma wp_allocN_seq s E v n Φ :
(0 < n)%Z
( l, ([ list] i seq 0 (Z.to_nat n), (l + (i : nat)) v) - Φ (LitV $ LitLoc l)) -
WP AllocN (Val $ LitV $ LitInt $ n) (Val v) @ s; E; E {{ Φ }}.
Proof.
iIntros (Hn) "".
iApply wp_lift_head_step_fupd_nomask; first done.
iIntros (σ1) "Hσ !>"; iSplit; first by destruct n; auto with lia head_step.
iIntros (e2 σ2 κ efs Hstep); inv_head_step.
iMod (gen_heap_alloc_big _ (heap_array _ (replicate (Z.to_nat n) v)) with "Hσ")
as "(Hσ & Hl & Hm)".
{ apply heap_array_map_disjoint.
rewrite replicate_length Z2Nat.id; auto with lia. }
iApply step_fupd_intro; first done.
iModIntro. iFrame "Hσ". do 2 (iSplit; first done).
iApply wp_value_fupd. iApply "".
by iApply heap_array_to_seq_mapsto.
Qed.
Lemma wp_alloc s E v Φ :
( l, l v - Φ (LitV $ LitLoc l)) -
WP Alloc (Val v) @ s; E; E {{ Φ }}.
Proof.
iIntros "". iApply wp_allocN_seq; [auto with lia..|].
iIntros "!>" (l) "/= (? & _)". rewrite Loc.add_0. iApply ""; iFrame.
Qed.
Lemma wp_free s E l v Φ :
l v -
( Φ (LitV LitUnit)) -
WP Free (Val $ LitV $ LitLoc l) @ s; E; E {{ Φ }}.
Proof.
iIntros ">Hl HΦ". iApply wp_lift_head_step_fupd_nomask; first done.
iIntros (σ1) "Hσ !>". iDestruct (gen_heap_valid with "Hσ Hl") as %?.
iSplit; first by eauto with head_step.
iIntros (e2 σ2 κ efs Hstep); inv_head_step.
iMod (gen_heap_update with "Hσ Hl") as "[$ Hl]".
iIntros "!>!>!>". iSplit; first done. iSplit; first done.
iApply wp_value. by iApply "".
Qed.
Lemma wp_load s E l dq v Φ :
l {dq} v -
(l {dq} v - Φ v) -
WP Load (Val $ LitV $ LitLoc l) @ s; E; E {{ Φ }}.
Proof.
iIntros ">Hl HΦ". iApply wp_lift_head_step_fupd_nomask; first done.
iIntros (σ1) "Hσ !>". iDestruct (gen_heap_valid with "Hσ Hl") as %?.
iSplit; first by eauto with head_step.
iIntros (e2 σ2 κ efs Hstep); inv_head_step.
iApply step_fupd_intro; first done. iNext. iFrame.
iSplitR; first done. iSplitR; first done. iApply wp_value. by iApply "".
Qed.
Lemma wp_store s E l v' v Φ :
l v' -
(l v - Φ (LitV LitUnit)) -
WP Store (Val $ LitV $ LitLoc l) (Val v) @ s; E; E {{ Φ }}.
Proof.
iIntros ">Hl HΦ". iApply wp_lift_head_step_fupd_nomask; first done.
iIntros (σ1) "Hσ !>". iDestruct (gen_heap_valid with "Hσ Hl") as %?.
iSplit; first by eauto with head_step.
iIntros (e2 σ2 κ efs Hstep); inv_head_step.
iMod (gen_heap_update with "Hσ Hl") as "[$ Hl]".
iApply step_fupd_intro; first done. iNext.
iSplit; first done. iSplit; first done.
iApply wp_value. by iApply "".
Qed.
End lifting.