From 4e90af7af0624620cff8a70678198e91597fb1ed Mon Sep 17 00:00:00 2001 From: Robbert Krebbers <mail@robbertkrebbers.nl> Date: Sun, 30 Jun 2019 11:14:47 +0200 Subject: [PATCH] Automatically unfold recursive protocols. --- theories/channel/proto_channel.v | 11 ++++++- theories/examples/list_sort_elem.v | 47 ++++++++++-------------------- theories/examples/loop_sort.v | 9 +++--- 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/theories/channel/proto_channel.v b/theories/channel/proto_channel.v index 8bf5901..18501ad 100644 --- a/theories/channel/proto_channel.v +++ b/theories/channel/proto_channel.v @@ -4,7 +4,6 @@ From iris.base_logic.lib Require Import invariants. From iris.heap_lang Require Import proofmode notation. From iris.algebra Require Import auth excl. From osiris.utils Require Import auth_excl. -Set Default Proof Using "Type*". Export action. Definition start_chan : val := λ: "f", @@ -180,6 +179,9 @@ Class ProtoContNormalize {Σ TT} (d : bool) (pc : TT → val * iProp Σ * iProto ProtoNormalize d ((pc x).2) pas ((qc x).2). Hint Mode ProtoContNormalize ! ! ! ! ! - : typeclass_instances. +Notation ProtoUnfold p1 p2 := (∀ d pas q, + ProtoNormalize d p2 pas q → ProtoNormalize d p1 pas q). + (** Auxiliary definitions and invariants *) Fixpoint proto_eval `{!proto_chanG Σ} (vs : list val) (p1 p2 : iProto Σ) : iProp Σ := match vs with @@ -295,6 +297,10 @@ Section proto. Proof. solve_proper. Qed. Global Instance iProto_dual_proper : Proper ((≡) ==> (≡)) (@iProto_dual Σ). Proof. apply (ne_proper _). Qed. + Global Instance iProto_dual_if_ne d : NonExpansive (@iProto_dual_if Σ d). + Proof. solve_proper. Qed. + Global Instance iProto_dual_if_proper d : Proper ((≡) ==> (≡)) (@iProto_dual_if Σ d). + Proof. apply (ne_proper _). Qed. Global Instance iProto_dual_involutive : Involutive (≡) (@iProto_dual Σ). Proof. @@ -357,6 +363,9 @@ Section proto. Proof. by rewrite /iProto_dual /iProto_app proto_map_app. Qed. (** Classes *) + Lemma proto_unfold_eq p1 p2 : p1 ≡ p2 → ProtoUnfold p1 p2. + Proof. rewrite /ProtoNormalize=> Hp d pas q ->. by rewrite Hp. Qed. + Global Instance proto_normalize_done p : ProtoNormalize false p [] p | 0. Proof. by rewrite /ProtoNormalize /= right_id. Qed. Global Instance proto_normalize_done_dual p : diff --git a/theories/examples/list_sort_elem.v b/theories/examples/list_sort_elem.v index f4897c7..ca6ddf8 100644 --- a/theories/examples/list_sort_elem.v +++ b/theories/examples/list_sort_elem.v @@ -63,9 +63,9 @@ Section list_sort_elem. Qed. Definition tail_protocol (xs : list (A * val)) : list (A * val) → iProto Σ := fixpoint (tail_protocol_aux xs). - Lemma tail_protocol_unfold xs ys: - tail_protocol xs ys ≡ tail_protocol_aux xs (tail_protocol xs) ys. - Proof. apply (fixpoint_unfold (tail_protocol_aux _)). Qed. + Global Instance tail_protocol_unfold xs ys : + ProtoUnfold (tail_protocol xs ys) (tail_protocol_aux xs (tail_protocol xs) ys). + Proof. apply proto_unfold_eq, (fixpoint_unfold (tail_protocol_aux _)). Qed. Definition head_protocol_aux (rec : list (A * val) -d> iProto Σ) : list (A * val) -d> iProto Σ := λ xs, @@ -79,9 +79,9 @@ Section list_sort_elem. Qed. Definition head_protocol : list (A * val) → iProto Σ := fixpoint head_protocol_aux. - Lemma head_protocol_unfold xs : - head_protocol xs ≡ head_protocol_aux head_protocol xs. - Proof. apply (fixpoint_unfold head_protocol_aux). Qed. + Global Instance head_protocol_unfold xs : + ProtoUnfold (head_protocol xs) (head_protocol_aux head_protocol xs). + Proof. apply proto_unfold_eq, (fixpoint_unfold head_protocol_aux). Qed. Definition list_sort_elem_protocol : iProto Σ := head_protocol []. @@ -98,11 +98,8 @@ Section list_sort_elem. }}}. Proof. iIntros (Ψ) "(Hc & Hc1 & Hc2) HΨ". iLöb as "IH" forall (c c1 c2 xs xs1 xs2 Ψ). - wp_rec. - rewrite head_protocol_unfold. - wp_apply (branch_spec with "Hc"); iIntros ([]) "[Hc _]"; wp_pures. + wp_rec. wp_apply (branch_spec with "Hc"); iIntros ([]) "[Hc _]"; wp_pures. - wp_apply (recv_proto_spec with "Hc"); iIntros (x v) "/= Hc HI". - rewrite (head_protocol_unfold xs1). wp_apply (select_spec with "[$Hc1]")=> //=; iIntros "Hc1". wp_apply (send_proto_spec with "Hc1"); simpl. iExists x, v. iSplit; [done|]. iIntros "{$HI} !> Hc1". @@ -110,8 +107,7 @@ Section list_sort_elem. iIntros (xs' xs1' xs2'); iDestruct 1 as (Hxs') "(Hc & Hc2 & Hc1)". rewrite -!(assoc_L (++)). iApply "HΨ". iFrame "Hc Hc1 Hc2". by rewrite Hxs' (comm (++) xs1') assoc_L. - - rewrite (head_protocol_unfold xs1) (head_protocol_unfold xs2). - wp_apply (select_spec with "[$Hc1]")=> //=; iIntros "Hc1". + - wp_apply (select_spec with "[$Hc1]")=> //=; iIntros "Hc1". wp_apply (select_spec with "[$Hc2]")=> //=; iIntros "Hc2". iApply ("HΨ" $! [] [] []). rewrite !right_id_L. by iFrame. Qed. @@ -130,13 +126,10 @@ Section list_sort_elem. Proof. iIntros (Hxs Hys Hsorted Hrel Ψ) "[Hc Hcin] HΨ". iLöb as "IH" forall (c cin xs ys xs' ys' Hxs Hys Hsorted Hrel). - wp_rec. - rewrite (tail_protocol_unfold xs'). - wp_apply (branch_spec with "Hcin"); iIntros ([]) "[Hcin Hys']". + wp_rec. wp_apply (branch_spec with "Hcin"); iIntros ([]) "[Hcin Hys']". - iClear "Hys'". wp_apply (recv_proto_spec with "Hcin"); iIntros (x v) "/= Hcin". iDestruct 1 as (Hx) "HI". - rewrite (tail_protocol_unfold xs). wp_apply (select_spec with "[$Hc]")=> //=; iIntros "Hc". wp_apply (send_proto_spec with "Hc"); simpl. iExists x, v. iFrame "HI". do 2 (iSplit; [by auto|]); iIntros "!> Hc". @@ -146,8 +139,7 @@ Section list_sort_elem. { rewrite fmap_app /=. apply Sorted_snoc; auto. } { intros x'. rewrite !fmap_app. inversion 1; discriminate_list || simplify_list_eq. by constructor. } - - iDestruct "Hys'" as %Hys'. rewrite (tail_protocol_unfold xs). - wp_apply (select_spec with "[$Hc]")=> //=. + - iDestruct "Hys'" as %Hys'. wp_apply (select_spec with "[$Hc]")=> //=. { by rewrite Hys Hxs Hys'. } iIntros "Hc". iApply "HΨ". iFrame. Qed. @@ -170,9 +162,7 @@ Section list_sort_elem. iIntros (Hxs Hys Hsort Htl Htl_le) "#Hcmp !>". iIntros (Ψ) "(Hc & Hc1 & Hc2 & HIy1) HΨ". iLöb as "IH" forall (c1 c2 xs1 xs2 ys y1 w1 ys1 ys2 Hxs Hys Hsort Htl Htl_le). - wp_rec. - rewrite (tail_protocol_unfold xs) (tail_protocol_unfold xs2). - wp_apply (branch_spec with "[$Hc2]"); iIntros ([]) "[Hc2 Hys2]". + wp_rec. wp_apply (branch_spec with "[$Hc2]"); iIntros ([]) "[Hc2 Hys2]". - iClear "Hys2". wp_apply (recv_proto_spec with "Hc2"); iIntros (x v) "/= Hc2". iDestruct 1 as (Htl2) "HIx". @@ -220,10 +210,9 @@ Section list_sort_elem. {{{ RET #(); c ↣ END @ N }}}. Proof. iIntros "#Hcmp !>" (Ψ) "Hc HΨ". iLöb as "IH" forall (c Ψ). - wp_rec; wp_pures. rewrite /list_sort_elem_protocol {2}head_protocol_unfold. + wp_rec; wp_pures. wp_apply (branch_spec with "Hc"); iIntros ([]) "[Hc _]"; wp_pures. - wp_apply (recv_proto_spec with "Hc"); iIntros (x1 v1) "/= Hc HIx1". - rewrite (head_protocol_unfold [_]). wp_apply (branch_spec with "Hc"); iIntros ([]) "[Hc _]"; wp_pures. + wp_apply (recv_proto_spec with "Hc"); iIntros (x2 v2) "/= Hc HIx2". wp_apply (start_chan_proto_spec N list_sort_elem_protocol). @@ -232,7 +221,6 @@ Section list_sort_elem. wp_apply (start_chan_proto_spec N list_sort_elem_protocol). { iIntros (cz) "Hcz". wp_apply ("IH" with "Hcz"); auto. } iIntros (cz) "Hcz". - rewrite /list_sort_elem_protocol {2 3}(head_protocol_unfold []). wp_apply (select_spec with "[$Hcy]")=> //; iIntros "Hcy". wp_apply (send_proto_spec with "Hcy")=> //=. iExists x1, v1. iFrame "HIx1". iSplit; [done|]; iIntros "!> Hcy". @@ -241,7 +229,6 @@ Section list_sort_elem. iExists x2, v2. iFrame "HIx2". iSplit; [done|]; iIntros "!> Hcz". wp_apply (list_sort_elem_service_split_spec with "[$Hc $Hcy $Hcz]"). iIntros (xs' xs1' xs2'); iDestruct 1 as (Hxs') "(Hc & Hcy & Hcz) /=". - rewrite (tail_protocol_unfold (_ :: xs1')). wp_apply (branch_spec with "Hcy"); iIntros (b) "[Hcy Hnil]". destruct b; last first. { by iDestruct "Hnil" as %?%Permutation_nil_cons. } @@ -251,14 +238,10 @@ Section list_sort_elem. with "Hcmp [$Hc $Hcy $Hcz $HIx]"); simpl; auto using TlRel_nil, Sorted_nil. { by rewrite Hxs' Permutation_middle. } iIntros "(Hc & Hcy & Hcz)". by iApply "HΨ". - + rewrite (tail_protocol_unfold [_]). - wp_apply (select_spec with "[$Hc]")=> //=; iIntros "Hc". + + wp_apply (select_spec with "[$Hc]")=> //=; iIntros "Hc". wp_apply (send_proto_spec with "Hc"); simpl. iExists x1, v1. iFrame "HIx1". do 2 (iSplit; [by auto using TlRel_nil|]). - iIntros "!> Hc". - rewrite (tail_protocol_unfold [_]). - by wp_apply (select_spec with "[$Hc]"). - - rewrite (tail_protocol_unfold []). - by wp_apply (select_spec with "[$Hc]"). + iIntros "!> Hc". by wp_apply (select_spec with "[$Hc]"). + - by wp_apply (select_spec with "[$Hc]"). Qed. End list_sort_elem. diff --git a/theories/examples/loop_sort.v b/theories/examples/loop_sort.v index 254a259..4c6dc44 100644 --- a/theories/examples/loop_sort.v +++ b/theories/examples/loop_sort.v @@ -25,9 +25,9 @@ Section loop_sort. f_contractive; f_equiv=> //. apply iProto_message_ne=> c /=; by repeat f_equiv. Qed. Definition loop_sort_protocol : iProto Σ := fixpoint loop_sort_protocol_aux. - Lemma loop_sort_protocol_unfold : - loop_sort_protocol ≡ loop_sort_protocol_aux loop_sort_protocol. - Proof. apply (fixpoint_unfold loop_sort_protocol_aux). Qed. + Global Instance loop_sort_protocol_unfold : + ProtoUnfold loop_sort_protocol (loop_sort_protocol_aux loop_sort_protocol). + Proof. apply proto_unfold_eq, (fixpoint_unfold loop_sort_protocol_aux). Qed. Lemma loop_sort_service_spec c : {{{ c ↣ iProto_dual loop_sort_protocol @ N }}} @@ -35,8 +35,7 @@ Section loop_sort. {{{ RET #(); c ↣ END @ N }}}. Proof. iIntros (Ψ) "Hc HΨ". iLöb as "IH" forall (c Ψ). - wp_rec. rewrite {2}loop_sort_protocol_unfold. - wp_apply (branch_spec with "Hc"); iIntros ([]) "/= [Hc _]"; wp_if. + wp_rec. wp_apply (branch_spec with "Hc"); iIntros ([]) "/= [Hc _]"; wp_if. { wp_apply (list_sort_service_spec with "Hc"); iIntros "Hc". by wp_apply ("IH" with "Hc"). } wp_apply (branch_spec with "Hc"); iIntros ([]) "/= [Hc _]"; wp_if. -- GitLab