Skip to content
Snippets Groups Projects
heap.v 10.5 KiB
Newer Older
From heap_lang Require Export derived.
From program_logic Require Import ownership auth.
Ralf Jung's avatar
Ralf Jung committed
From heap_lang Require Import notation.
Import uPred.
(* TODO: The entire construction could be generalized to arbitrary languages that have
   a finmap as their state. Or maybe even beyond "as their state", i.e. arbitrary
   predicates over finmaps instead of just ownP. *)

Definition heapRA := mapRA loc (exclRA (leibnizC val)).
Class HeapInG Σ (i : gid) := heap_inG :> InG heap_lang Σ i (authRA heapRA).
Instance heap_inG_auth `{HeapInG Σ i} : AuthInG heap_lang Σ i heapRA.
Proof. split; apply _. Qed.
Definition to_heap : state  heapRA := fmap Excl.
Definition from_heap : heapRA  state := omap (maybe Excl).
(* TODO: Do we want to expose heap ownership based on the state, or the heapRA?
   The former does not expose the annoying "Excl", so for now I am going for
   that. We should be able to derive the lemmas we want for this, too. *)
Definition heap_own {Σ} (i : gid) `{HeapInG Σ i}
  (γ : gname) (σ : state) : iPropG heap_lang Σ := auth_own i γ (to_heap σ).
Definition heap_mapsto {Σ} (i : gid) `{HeapInG Σ i}
  (γ : gname) (l : loc) (v : val) : iPropG heap_lang Σ := heap_own i γ {[ l  v ]}.
Definition heap_inv {Σ} (i : gid) `{HeapInG Σ i}
  (h : heapRA) : iPropG heap_lang Σ := ownP (from_heap h).
Definition heap_ctx {Σ} (i : gid) `{HeapInG Σ i}
  (γ : gname) (N : namespace) : iPropG heap_lang Σ := auth_ctx i γ N (heap_inv i).
Section heap.
  Context {Σ : iFunctorG} (HeapI : gid) `{!HeapInG Σ HeapI}.
  Implicit Types N : namespace.
  Implicit Types P : iPropG heap_lang Σ.
  Implicit Types σ : state.
  Implicit Types h g : heapRA.
  Implicit Types γ : gname.
Robbert Krebbers's avatar
Robbert Krebbers committed
  Lemma from_to_heap σ : from_heap (to_heap σ) = σ.
Robbert Krebbers's avatar
Robbert Krebbers committed
    apply map_eq=>l. rewrite lookup_omap lookup_fmap. by case (σ !! l).
  Qed.
  Lemma to_heap_valid σ :  to_heap σ.
  Proof. intros n l. rewrite lookup_fmap. by case (σ !! l). Qed.
  Hint Resolve to_heap_valid.

  Global Instance heap_inv_proper : Proper (() ==> ()) (heap_inv HeapI).
  Proof. intros h1 h2. by fold_leibniz=> ->. Qed.
    (heap_own HeapI γ σ1  heap_own HeapI γ σ2)%I
     ( (σ1 ⊥ₘ σ2)  heap_own HeapI γ (σ1  σ2))%I.
Robbert Krebbers's avatar
Robbert Krebbers committed
  Proof.
 (* TODO. *)
  Abort.

  Lemma heap_own_mapsto γ σ l v :
    (* TODO: Is this the best way to express "l ∉ dom σ"? *)
    (heap_own HeapI γ σ  heap_mapsto HeapI γ l v)%I
     ( (σ !! l = None)  heap_own HeapI γ (<[l:=v]>σ))%I.
  (* TODO: Do we want equivalence to a big sum? *)
  Lemma heap_alloc N σ :
    ownP σ  pvs N N ( γ, heap_ctx HeapI γ N  heap_own HeapI γ σ).
Robbert Krebbers's avatar
Robbert Krebbers committed
  Proof. by rewrite -{1}[σ]from_to_heap -(auth_alloc _ N). Qed.
Ralf Jung's avatar
Ralf Jung committed
  Lemma wp_alloc_heap N E γ σ e v P Q :
    nclose N  E   to_val e = Some v 
    P  heap_ctx HeapI γ N 
    P  (heap_own HeapI γ σ 
          ( l, σ !! l = None  heap_own HeapI γ (<[l:=v]>σ) - Q (LocV l))) 
    P  wp E (Alloc e) Q.
  Proof.
Ralf Jung's avatar
Ralf Jung committed
    rewrite /heap_ctx /heap_own. intros HN Hval Hctx HP.
    set (LU (l : loc) := local_update_op (A:=heapRA) ({[ l  Excl v ]})).
    eapply (auth_fsa (heap_inv HeapI) (wp_fsa _) _ (LU := LU)); simpl.
    { by eauto. } { by eauto. } { by eauto. }
    rewrite HP=>{HP Hctx HN}. apply sep_mono; first done.
    apply forall_intro=>hf. apply wand_intro_l. rewrite /heap_inv.
    rewrite -assoc. apply const_elim_sep_l=>Hv /=.
    rewrite {1}[(ownP _)%I]pvs_timeless !pvs_frame_r. apply wp_strip_pvs.
    rewrite -wp_alloc_pst; first (apply sep_mono; first done); try eassumption.
    apply later_mono, forall_intro=>l. rewrite (forall_elim l). apply wand_intro_l.
    rewrite -(exist_intro l) !left_id. rewrite always_and_sep_l -assoc.
    apply const_elim_sep_l=>Hfresh.
    assert (σ !! l = None) as Hfresh_σ.
    { move: Hfresh (Hv 0%nat l). rewrite /from_heap /to_heap lookup_omap.
      rewrite lookup_op !lookup_fmap.
      case _:(σ !! l)=>[v'|]/=; case _:(hf !! l)=>[[?||]|]/=; done. }
    rewrite const_equiv // const_equiv; last first.
    { move=>n l'. move:(Hv n l') Hfresh.
      rewrite /from_heap /to_heap !lookup_omap !lookup_op !lookup_fmap !Hfresh_σ /=.
      destruct (decide (l=l')).
      - subst l'. rewrite lookup_singleton !Hfresh_σ.
        case _:(hf !! l)=>[[?||]|]/=; done.
      - rewrite lookup_singleton_ne //.
        case _:(σ !! l')=>[?|]/=; case _:(hf !! l')=>[[?||]|]/=; done. }
    rewrite !left_id -later_intro.
    assert ({[l  Excl v]}  to_heap σ = to_heap (<[l:=v]> σ)) as EQ.
    { apply: map_eq=>l'. rewrite lookup_op !lookup_fmap.
      destruct (decide (l=l')); simplify_map_equality.
      - rewrite lookup_insert. done.
      - rewrite !lookup_insert_ne // lookup_empty left_id. done. }
    rewrite EQ. apply sep_mono; last done. f_equiv. apply: map_eq=>l'. 
    move:(Hv 0%nat l') Hfresh. destruct (decide (l=l')); simplify_map_equality.
    - rewrite lookup_insert !lookup_omap !lookup_op !lookup_fmap lookup_insert.
      case _:(σ !! l')=>[?|]/=; case _:(hf !! l')=>[[?||]|]/=; done.
    - rewrite lookup_insert_ne // !lookup_omap !lookup_op !lookup_fmap lookup_insert_ne //.
  Qed.
  Lemma wp_load_heap N E γ σ l v P Q :
Ralf Jung's avatar
Ralf Jung committed
    nclose N  E 
    P  heap_ctx HeapI γ N 
    P  (heap_own HeapI γ σ   (heap_own HeapI γ σ - Q v)) 
Ralf Jung's avatar
Ralf Jung committed
    rewrite /heap_ctx /heap_own. intros Hl HN Hctx HP.
    eapply (auth_fsa (heap_inv HeapI) (wp_fsa _) (λ _:(), id)); simpl; eauto.
    rewrite HP=>{HP Hctx HN}. apply sep_mono; first done.
    apply forall_intro=>hf. apply wand_intro_l. rewrite /heap_inv.
    rewrite -assoc. apply const_elim_sep_l=>Hv /=.
    rewrite {1}[(ownP _)%I]pvs_timeless !pvs_frame_r. apply wp_strip_pvs.
    rewrite -wp_load_pst; first (apply sep_mono; first done); last first.
    { move: (Hv 0%nat l). rewrite lookup_omap lookup_op lookup_fmap Hl /=.
Ralf Jung's avatar
Ralf Jung committed
      case _:(hf !! l)=>[[?||]|]; by auto. }
    apply later_mono, wand_intro_l.
    rewrite -(exist_intro ()) left_id const_equiv // left_id.
  Lemma wp_load N E γ l v P Q :
Ralf Jung's avatar
Ralf Jung committed
    nclose N  E 
    P  heap_ctx HeapI γ N 
    P  (heap_mapsto HeapI γ l v   (heap_mapsto HeapI γ l v - Q v)) 
Ralf Jung's avatar
Ralf Jung committed
    P  wp E (Load (Loc l)) Q.
  Proof.
Ralf Jung's avatar
Ralf Jung committed
    intros HN. rewrite /heap_mapsto. apply wp_load_heap; last done.
Ralf Jung's avatar
Ralf Jung committed
    by simplify_map_equality.
  Qed.
Ralf Jung's avatar
Ralf Jung committed

Ralf Jung's avatar
Ralf Jung committed
  Lemma wp_store_heap N E γ σ l v' e v P Q :
    σ !! l = Some v'  to_val e = Some v  
    nclose N  E 
Ralf Jung's avatar
Ralf Jung committed
    P  heap_ctx HeapI γ N 
    P  (heap_own HeapI γ σ   (heap_own HeapI γ (<[l:=v]>σ) - Q (LitV LitUnit))) 
    P  wp E (Store (Loc l) e) Q.
  Proof.
Ralf Jung's avatar
Ralf Jung committed
    rewrite /heap_ctx /heap_own. intros Hl Hval HN Hctx HP.
    eapply (auth_fsa (heap_inv HeapI) (wp_fsa _) (λ _:(), alter (λ _, Excl v) l)); simpl; eauto.
Ralf Jung's avatar
Ralf Jung committed
    rewrite HP=>{HP Hctx HN}. apply sep_mono; first done.
    apply forall_intro=>hf. apply wand_intro_l. rewrite /heap_inv.
    rewrite -assoc. apply const_elim_sep_l=>Hv /=.
    rewrite {1}[(ownP _)%I]pvs_timeless !pvs_frame_r. apply wp_strip_pvs.
    rewrite -wp_store_pst; first (apply sep_mono; first done); try eassumption; last first.
    { move: (Hv 0%nat l). rewrite lookup_omap lookup_op lookup_fmap Hl /=.
      case _:(hf !! l)=>[[?||]|]; by auto. }
    apply later_mono, wand_intro_l.
    rewrite -(exist_intro ()) const_equiv //; last first.
Ralf Jung's avatar
Ralf Jung committed
    (* TODO I think there are some general fin_map lemmas hiding in here. *)
    { split.
      - exists (Excl v'). by rewrite lookup_fmap Hl.
      - move=>n l'. move: (Hv n l'). rewrite !lookup_op.
        destruct (decide (l=l')); simplify_map_equality.
        + rewrite lookup_alter lookup_fmap Hl /=. case (hf !! l')=>[[?||]|]; by auto.
        + rewrite lookup_alter_ne //. }
    rewrite left_id -later_intro.
    assert (alter (λ _ : excl val, Excl v) l (to_heap σ) = to_heap (<[l:=v]> σ)) as EQ.
    { apply: map_eq=>l'. destruct (decide (l=l')); simplify_map_equality.
      + by rewrite lookup_alter /to_heap !lookup_fmap lookup_insert Hl /=.
      + rewrite lookup_alter_ne // !lookup_fmap lookup_insert_ne //. }
    rewrite !EQ. apply sep_mono; last done.
    f_equiv. apply: map_eq=>l'. move: (Hv 0%nat l'). destruct (decide (l=l')); simplify_map_equality.
    - rewrite /from_heap /to_heap lookup_insert lookup_omap !lookup_op.
      rewrite !lookup_fmap lookup_insert Hl.
      case (hf !! l')=>[[?||]|]; auto; contradiction.
    - rewrite /from_heap /to_heap lookup_insert_ne // !lookup_omap !lookup_op !lookup_fmap.
      rewrite lookup_insert_ne //.
  Qed.

Ralf Jung's avatar
Ralf Jung committed
  Lemma wp_store N E γ l v' e v P Q :
    to_val e = Some v  
    nclose N  E  
Ralf Jung's avatar
Ralf Jung committed
    P  heap_ctx HeapI γ N 
    P  (heap_mapsto HeapI γ l v'   (heap_mapsto HeapI γ l v - Q (LitV LitUnit))) 
    P  wp E (Store (Loc l) e) Q.
  Proof.
Ralf Jung's avatar
Ralf Jung committed
    rewrite /heap_mapsto=>Hval HN Hctx HP. eapply wp_store_heap; try eassumption; last first.
Ralf Jung's avatar
Ralf Jung committed
    - rewrite HP. apply sep_mono; first done. by rewrite insert_singleton.
    - by rewrite lookup_insert.
  Qed.
Ralf Jung's avatar
Ralf Jung committed

  Lemma wp_cas_fail_heap N E γ σ l v' e1 v1 e2 v2 P Q :
    to_val e1 = Some v1  to_val e2 = Some v2  σ !! l = Some v'  v'  v1 
    nclose N  E 
    P  heap_ctx HeapI γ N 
    P  (heap_own HeapI γ σ   (heap_own HeapI γ σ - Q 'false)) 
    P  wp E (Cas (Loc l) e1 e2) Q.
  Proof.
    rewrite /heap_ctx /heap_own. intros He1 He2 Hl Hne HN Hctx HP.
    eapply (auth_fsa (heap_inv HeapI) (wp_fsa _) (λ _:(), id)); simpl; eauto.
Ralf Jung's avatar
Ralf Jung committed
    { split_ands; eexists; eauto. }
    rewrite HP=>{HP Hctx HN}. apply sep_mono; first done.
    apply forall_intro=>hf. apply wand_intro_l. rewrite /heap_inv.
    rewrite -assoc. apply const_elim_sep_l=>Hv /=.
    rewrite {1}[(ownP _)%I]pvs_timeless !pvs_frame_r. apply wp_strip_pvs.
    rewrite -wp_cas_fail_pst; first (apply sep_mono; first done); try eassumption; last first.
    { move: (Hv 0%nat l). rewrite lookup_omap lookup_op lookup_fmap Hl /=.
      case _:(hf !! l)=>[[?||]|]; by auto. }
    apply later_mono, wand_intro_l.
    rewrite -(exist_intro ()) left_id const_equiv // left_id.
Ralf Jung's avatar
Ralf Jung committed
    by rewrite -later_intro.
  Qed.

  Lemma wp_cas_fail N E γ l v' e1 v1 e2 v2 P Q :
    to_val e1 = Some v1  to_val e2 = Some v2  v'  v1 
    nclose N  E 
    P  heap_ctx HeapI γ N 
    P  (heap_mapsto HeapI γ l v'   (heap_mapsto HeapI γ l v' - Q 'false)) 
    P  wp E (Cas (Loc l) e1 e2) Q.
  Proof.
    rewrite /heap_mapsto=>???. eapply wp_cas_fail_heap; try eassumption.
    by simplify_map_equality.
  Qed.