From d7f2e1a05cf7cf8a7f7ec860ce1bf9d44f18e76e Mon Sep 17 00:00:00 2001 From: jihgfee <jihgfee@gmail.com> Date: Tue, 3 Nov 2020 16:38:53 +0100 Subject: [PATCH] Added example of rpc client/service --- _CoqProject | 1 + theories/examples/rpc.v | 139 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 theories/examples/rpc.v diff --git a/_CoqProject b/_CoqProject index dad39bb..c846664 100644 --- a/_CoqProject +++ b/_CoqProject @@ -25,6 +25,7 @@ theories/examples/map_reduce.v theories/examples/swap_mapper.v theories/examples/subprotocols.v theories/examples/list_rev.v +theories/examples/rpc.v theories/logrel/model.v theories/logrel/telescopes.v theories/logrel/subtyping.v diff --git a/theories/examples/rpc.v b/theories/examples/rpc.v new file mode 100644 index 0000000..12b5da1 --- /dev/null +++ b/theories/examples/rpc.v @@ -0,0 +1,139 @@ +From iris.heap_lang Require Import proofmode. +From actris.channel Require Import proofmode. + +Definition server : val := + rec: "go" "dict" "c" := + if: ~ (recv "c") then #() + else + let: "f" := "dict" (recv "c") in + let: "res" := "f" (recv "c") in + send "c" "res";; + "go" "dict" "c". + +Definition Left : val := #true. +Definition Right : val := #false. + +Notation plus_id := 1%Z. +Notation incr_ref_id := 2%Z. + +Definition client : val := + λ: "c", + send "c" Left;; + send "c" #plus_id;; send "c" (#40,#2);; let: "res1" := recv "c" in + send "c" Left;; + let: "l" := ref #41 in + send "c" #incr_ref_id;; send "c" "l";; let: "res2" := ! (recv "c") in + send "c" Right;; + ("res1","res2"). + +Definition program : val := + λ: "dict", + let: "c" := new_chan #() in + Fork (server "dict" (Snd "c"));; + client (Fst "c"). + +Section rpc_example. + Context `{!heapG Σ, !chanG Σ}. + + Definition f_spec {T U} (IT : T → val → iProp Σ) (IU : U → val → iProp Σ) + (f : T → U) (fv : val) : iProp Σ := + (∀ x v, {{{ IT x v }}} fv v {{{ w, RET w; IU (f x) w }}})%I. + + Definition rpc_prot_aux (f_specs : gmap Z (val → iProp Σ)) (rec : iProto Σ) + : iProto Σ := + ((<! (T U:Type) IT IU (f : T → U) (id:Z)> MSG #id + {{ ⌜f_specs !! id = Some (f_spec IT IU f)⌠}}; + <! (x:T) (v:val)> MSG v {{ IT x v }} ; + <? (w:val)> MSG w {{ IU (f x) w }} ; rec) + <+> END)%proto. + + Instance rpc_prot_aux_contractive (f_specs : gmap Z (val → iProp Σ)) : + Contractive (rpc_prot_aux f_specs). + Proof. solve_proto_contractive. Qed. + Definition rpc_prot (f_specs : gmap Z (val → iProp Σ)) : iProto Σ := + fixpoint (rpc_prot_aux f_specs). + Global Instance rpc_prot_unfold f_specs : + ProtoUnfold (rpc_prot f_specs) (rpc_prot_aux f_specs (rpc_prot f_specs)). + Proof. apply proto_unfold_eq, fixpoint_unfold. Qed. + + Definition dict_spec (dict : val) (f_specs : gmap Z _) : iProp Σ := + ∀ (T U : Type) (id : Z) (IT : T → val → iProp Σ) (IU : U → val → iProp Σ) + (f : T → U), + {{{ ⌜f_specs !! id = Some (f_spec IT IU f)⌠}}} + dict #id + {{{ fv, RET fv; f_spec IT IU f fv }}}. + + Lemma server_spec dict f_specs c prot : + {{{ dict_spec dict f_specs ∗ + c ↣ (iProto_dual (rpc_prot f_specs) <++> prot)%proto }}} + server dict c + {{{ RET #(); c ↣ prot }}}. + Proof. + iIntros (Φ) "[#Hdict Hc] HΦ". + iLöb as "IH". + wp_rec. + wp_branch; last first. + { wp_pures. by iApply "HΦ". } + wp_recv (T U IT IU f id) as "Hlookup". + wp_apply ("Hdict" with "Hlookup"); iIntros (fv) "Hfv". + wp_recv (x v) as "HIT". + wp_apply ("Hfv" with "HIT"); iIntros (w) "HIU". + wp_send (w) with "[$HIU]". + wp_pures. by iApply ("IH" with "Hc"). + Qed. + + Definition plus_spec := + f_spec (λ (x:Z*Z) (v:val), ⌜(#(fst x), #(snd x))%V = vâŒ)%I + (λ y w, ⌜#y = wâŒ)%I + (λ (x:Z*Z), (fst x) + (snd x))%Z. + + Definition incr_ref_spec := + f_spec (λ (x:Z) (v:val), ∃ (l : loc), ⌜v = #l⌠∗ l ↦ #x)%I + (λ (y:Z) (w:val), ∃ (l : loc), ⌜w = #l⌠∗ l ↦ #y)%I + (λ (x:Z), x+1)%Z. + + Definition client_f_specs : gmap Z (val → iProp Σ) := + {[ plus_id := plus_spec ]} ∪ + {[ incr_ref_id := incr_ref_spec ]}. + + Lemma client_spec c : + {{{ c ↣ rpc_prot client_f_specs }}} + client c + {{{ RET (#42, #42); True }}}. + Proof. + iIntros (Φ) "Hc HΦ". + wp_lam. + (** plus *) + wp_select. + wp_send with "[//]". wp_send with "[]". + { by instantiate (1:=(40,2)%Z). } + wp_recv (w) as "<-". + (** incr_ref *) + wp_select. + wp_alloc l as "Hl". + wp_send with "[//]". wp_send with "[Hl]". + { eauto. } + wp_recv (w) as (l') "[-> Hl]". + wp_load. + (** Termination *) + wp_select. + wp_pures. + by iApply "HΦ". + Qed. + + Lemma program_spec dict : + {{{ dict_spec dict client_f_specs }}} + program dict + {{{ v, RET v; True }}}. + Proof. + iIntros (Φ) "#Hdict HΦ". + wp_lam. + wp_apply (new_chan_spec (rpc_prot client_f_specs))=> //. + iIntros (c1 c2) "[Hc1 Hc2]". + wp_apply (wp_fork with "[Hc2]"). + - iIntros "!>". wp_apply (server_spec _ _ _ END%proto with "[Hc2]"). + rewrite right_id. iFrame "Hdict Hc2". by iIntros "_". + - by wp_apply (client_spec with "Hc1"). + Qed. + +End rpc_example. -- GitLab