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 contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

(** 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.