Skip to content
Snippets Groups Projects
Commit aa527705 authored by Jonas Kastberg Hinrichsen's avatar Jonas Kastberg Hinrichsen
Browse files

Turned list_sort generic, so the service takes compare in protocol

parent c0aabb40
No related branches found
No related tags found
No related merge requests found
...@@ -11,221 +11,238 @@ Require Import Omega. ...@@ -11,221 +11,238 @@ Require Import Omega.
Section ListSortExample. Section ListSortExample.
Context `{!heapG Σ} `{logrelG val Σ} (N : namespace). Context `{!heapG Σ} `{logrelG val Σ} (N : namespace).
Definition lsplit_ref : val := Section SortService.
λ: "xs", let: "ys_zs" := lsplit !"xs" in Context `{EncDec T}.
(ref (Fst "ys_zs"), ref (Snd ("ys_zs"))). Context (R : relation T) `{!Total R} `{ x y, Decision (R x y)}.
Lemma lsplit_ref_spec lxs (x : Z) (xs : list Z) : Definition lsplit_ref : val :=
{{{ lxs encode (x::xs) }}} λ: "xs", let: "ys_zs" := lsplit !"xs" in
lsplit_ref #lxs (ref (Fst "ys_zs"), ref (Snd ("ys_zs"))).
{{{ lys lzs ys zs, RET (#lys,#lzs);
(x::xs) = ys++zs
lxs encode (x::xs)
lys encode ys
lzs encode zs }}}.
Proof.
iIntros (Φ) "Hhd HΦ".
wp_lam. wp_load. wp_apply (lsplit_spec (T:=Z))=> //. iIntros (ys zs <-).
wp_alloc lzs as "Hlzs".
wp_alloc lys as "Hlys".
wp_pures.
iApply "HΦ".
eauto 10 with iFrame.
Qed.
Definition compare_vals : val := Lemma lsplit_ref_spec lxs (x : T) (xs : list T) :
λ: "x" "y", "x" "y". {{{ lxs encode (x::xs) }}}
lsplit_ref #lxs
{{{ lys lzs ys zs, RET (#lys,#lzs);
(x::xs) = ys++zs
lxs encode (x::xs)
lys encode ys
lzs encode zs }}}.
Proof.
iIntros (Φ) "Hhd HΦ".
wp_lam. wp_load. wp_apply (lsplit_spec)=> //. iIntros (ys zs <-).
wp_alloc lzs as "Hlzs".
wp_alloc lys as "Hlys".
wp_pures.
iApply "HΦ".
eauto 10 with iFrame.
Qed.
Lemma compare_vals_spec (x y : Z) : Definition lmerge : val :=
{{{ True }}} rec: "go" "cmp" "hys" "hzs" :=
compare_vals (encode x) (encode y) match: "hys" with
{{{ RET (encode (bool_decide (x y))); True }}}. NONE => "hzs"
Proof. iIntros (Φ) "_ HΦ". wp_lam. wp_pures. by iApply "HΦ". Qed.
Definition lmerge : val :=
rec: "go" "hys" "hzs" :=
match: "hys" with
NONE => "hzs"
| SOME "_" =>
match: "hzs" with
NONE => "hys"
| SOME "_" => | SOME "_" =>
let: "y" := lhead "hys" in match: "hzs" with
let: "z" := lhead "hzs" in NONE => "hys"
if: (compare_vals "y" "z") | SOME "_" =>
then lcons "y" ("go" (ltail "hys") "hzs") let: "y" := lhead "hys" in
else lcons "z" ("go" "hys" (ltail "hzs")) let: "z" := lhead "hzs" in
end if: ("cmp" "y" "z")
end. then lcons "y" ("go" "cmp" (ltail "hys") "hzs")
else lcons "z" ("go" "cmp" "hys" (ltail "hzs"))
end
end.
Lemma list_merge_emp1 (ys : list Z) : list_merge () [] ys = ys. Lemma list_merge_emp1 (ys : list T) : list_merge (R) [] ys = ys.
Proof. induction ys; eauto. Qed. Proof. induction ys; eauto. Qed.
Lemma list_merge_emp2 (xs : list Z) : list_merge () xs [] = xs. Lemma list_merge_emp2 (xs : list T) : list_merge (R) xs [] = xs.
Proof. induction xs; eauto. Qed. Proof. induction xs; eauto. Qed.
Lemma lmerge_spec (ys zs : list Z) : Definition cmp_spec (cmp : val) : iProp Σ :=
{{{ True }}} ( x y, {{{ True }}}
lmerge (encode ys) (encode zs) cmp (encode x) (encode y)
{{{ RET (encode (list_merge () ys zs)); True }}}. {{{ RET encode (bool_decide (R x y)); True}}})%I.
Proof.
revert ys zs.
iLöb as "IH".
iIntros (ys zs Φ _) "HΦ".
wp_lam.
destruct ys as [|y ys].
{ wp_pures. rewrite list_merge_emp1. by iApply ("HΦ"). }
destruct zs as [|z zs].
{ wp_pures. rewrite list_merge_emp2. by iApply ("HΦ"). }
wp_apply (lhead_spec (T:=Z))=> //; iIntros "_".
wp_apply (lhead_spec (T:=Z))=> //; iIntros "_".
wp_apply (compare_vals_spec)=> //; iIntros "_".
rewrite list_merge_cons.
destruct (decide (y z)).
- rewrite bool_decide_true=> //.
wp_apply (ltail_spec (T:=Z))=> //; iIntros (_).
wp_apply ("IH")=> //; iIntros (_).
wp_apply (lcons_spec (T:=Z))=> //.
- rewrite bool_decide_false=> //.
wp_apply (ltail_spec (T:=Z))=> //; iIntros (_).
wp_apply ("IH")=> //; iIntros (_).
wp_apply (lcons_spec (T:=Z))=> //.
Qed.
Definition lmerge_ref : val := Lemma lmerge_spec (cmp : val) (ys zs : list T) :
λ: "lxs" "hys" "hzs", cmp_spec cmp
"lxs" <- lmerge "hys" "hzs". {{{ True }}}
lmerge cmp (encode ys) (encode zs)
{{{ RET (encode (list_merge (R) ys zs)); True }}}.
Proof.
revert ys zs.
iLöb as "IH".
iIntros (ys zs Hcmp_spec Φ _) "HΦ".
wp_lam.
destruct ys as [|y ys].
{ wp_pures. rewrite list_merge_emp1. by iApply ("HΦ"). }
destruct zs as [|z zs].
{ wp_pures. rewrite list_merge_emp2. by iApply ("HΦ"). }
wp_apply (lhead_spec)=> //; iIntros "_".
wp_apply (lhead_spec)=> //; iIntros "_".
wp_apply (Hcmp_spec)=> //; iIntros "_".
rewrite list_merge_cons.
destruct (decide (R y z)).
- rewrite bool_decide_true=> //.
wp_apply (ltail_spec)=> //; iIntros (_).
wp_apply ("IH")=> //; iIntros (_).
wp_apply (lcons_spec)=> //.
- rewrite bool_decide_false=> //.
wp_apply (ltail_spec)=> //; iIntros (_).
wp_apply ("IH")=> //; iIntros (_).
wp_apply (lcons_spec)=> //.
Qed.
Lemma lmerge_ref_spec ldx tmp ys zs : Definition lmerge_ref : val :=
{{{ ldx tmp }}} λ: "cmp" "lxs" "hys" "hzs",
lmerge_ref #ldx (encode ys) (encode zs) "lxs" <- lmerge "cmp" "hys" "hzs".
{{{ RET #(); ldx encode (list_merge () ys zs) }}}.
Proof.
iIntros (Φ) "Hldx HΦ".
wp_lam.
wp_apply (lmerge_spec ys zs)=> //.
iIntros (_).
wp_store.
by iApply ("HΦ").
Qed.
Definition list_sort_service : val := Lemma lmerge_ref_spec (cmp : val) ldx tmp ys zs :
rec: "go" "c" := cmp_spec cmp
let: "xs" := recv "c" #Right in {{{ ldx tmp }}}
if: llength (!"xs") #1 lmerge_ref cmp #ldx (encode ys) (encode zs)
then send "c" #Right "xs" {{{ RET #(); ldx encode (list_merge R ys zs) }}}.
else let: "ys_zs" := lsplit_ref "xs" in Proof.
let: "ys" := Fst "ys_zs" in iIntros (cmp_spec Φ) "Hldx HΦ".
let: "zs" := Snd "ys_zs" in wp_lam.
let: "cy" := new_chan #() in Fork("go" "cy");; wp_apply (lmerge_spec cmp ys zs)=> //.
let: "cz" := new_chan #() in Fork("go" "cz");; iIntros (_).
send "cy" #Left "ys";; wp_store.
send "cz" #Left "zs";; by iApply ("HΦ").
let: "ys" := recv "cy" #Left in Qed.
let: "zs" := recv "cz" #Left in
lmerge_ref "xs" !"ys" !"zs";;
send "c" #Right "xs".
Lemma list_sort_service_spec γ c xs : Definition list_sort_service : val :=
{{{ c @ Right : (<?> l @ l encode xs, rec: "go" "c" :=
<!> l' @ let: "cmp" := recv "c" #Right in
l = l' ( ys : list Z, let: "xs" := recv "c" #Right in
l' encode ys if: llength (!"xs") #1
Sorted () ys then send "c" #Right "xs"
Permutation ys xs), else let: "ys_zs" := lsplit_ref "xs" in
TEnd) {N,γ} }}} let: "ys" := Fst "ys_zs" in
list_sort_service c let: "zs" := Snd "ys_zs" in
{{{ RET #(); c @ Right : TEnd {N,γ} }}}. let: "cy" := new_chan #() in Fork("go" "cy");;
Proof. let: "cz" := new_chan #() in Fork("go" "cz");;
revert γ c xs. send "cy" #Left "cmp";;
iLöb as "IH". send "cy" #Left "ys";;
iIntros (γ c xs Φ) "Hstr HΦ". send "cz" #Left "cmp";;
wp_lam. send "cz" #Left "zs";;
wp_apply (recv_st_spec N loc with "Hstr"). let: "ys" := recv "cy" #Left in
iIntros (v) "Hstr". let: "zs" := recv "cz" #Left in
iDestruct "Hstr" as "[Hstr HP]". lmerge_ref "cmp" "xs" !"ys" !"zs";;
wp_load. send "c" #Right "xs".
destruct xs.
{ Definition sort_protocol xs :=
wp_apply (llength_spec (T:=Z))=> //; iIntros (_). (<?> cmp @ cmp_spec cmp,
wp_apply (send_st_spec N loc with "[HP Hstr]")=> //. iFrame. <?> l @ l encode xs,
eauto 10 with iFrame. <!> l' @ l = l'
} ( ys : list T,
destruct xs. l' encode ys
{ Sorted (R) ys
wp_apply (llength_spec (T:=Z))=> //; iIntros (_). Permutation ys xs),
wp_apply (send_st_spec N loc with "[HP Hstr]")=> //. iFrame. TEnd)%stype.
eauto 10 with iFrame.
} Lemma list_sort_service_spec γ c xs :
wp_apply (llength_spec (T:=Z))=> //; iIntros (_). {{{ c @ Right : sort_protocol xs {N,γ} }}}
wp_pures. list_sort_service c
assert (bool_decide (S (S (length xs)) 1) = false) as HSS. {{{ RET #(); c @ Right : TEnd {N,γ} }}}.
{ apply bool_decide_false. lia. } Proof.
rewrite HSS. revert γ c xs.
wp_apply (lsplit_ref_spec with "HP"); iLöb as "IH".
iIntros (hdy hdz ys zs) "(Heq & Hhdx & Hhdy & Hhdz)". iIntros (γ c xs Φ) "Hstr HΦ".
iDestruct "Heq" as %->. wp_lam.
wp_apply (new_chan_st_spec N wp_apply (recv_st_spec N val with "Hstr").
(<!> l @ l encode ys, iIntros (cmp) "[Hstr cmp_spec]".
<?> l' @ l = l' iDestruct ("cmp_spec") as %Hcmp_spec.
( ys' : list Z, wp_pures.
l' encode ys' wp_apply (recv_st_spec N loc with "Hstr").
Sorted () ys' iIntros (v) "Hstr".
Permutation ys' ys), iDestruct "Hstr" as "[Hstr HP]".
TEnd))=>//; wp_load.
iIntros (cy γy) "[Hstly Hstry]". destruct xs.
wp_apply (wp_fork with "[Hstry]"). {
{ iNext. iApply ("IH" with "Hstry"). iNext. by iIntros "Hstry". } wp_apply (llength_spec)=> //; iIntros (_).
wp_apply (new_chan_st_spec N wp_apply (send_st_spec N loc with "[HP Hstr]")=> //. iFrame.
(<!> l @ l encode zs, eauto 10 with iFrame.
<?> l' @ l = l' }
( zs' : list Z, destruct xs.
l' encode zs' {
Sorted () zs' wp_apply (llength_spec)=> //; iIntros (_).
Permutation zs' zs), wp_apply (send_st_spec N loc with "[HP Hstr]")=> //. iFrame.
TEnd))=>//; eauto 10 with iFrame.
iIntros (cz γz) "[Hstlz Hstrz]". }
wp_apply (wp_fork with "[Hstrz]"). wp_apply (llength_spec)=> //; iIntros (_).
{ iNext. iApply ("IH" with "Hstrz"). iNext. by iIntros "Hstrz". } wp_pures.
wp_apply (send_st_spec N loc with "[Hhdy Hstly]"). iFrame. assert (bool_decide (S (S (length xs)) 1) = false) as HSS.
iIntros "Hstly". { apply bool_decide_false. lia. }
wp_apply (send_st_spec N loc with "[Hhdz Hstlz]"). iFrame. rewrite HSS.
iIntros "Hstlz". wp_apply (lsplit_ref_spec with "HP");
wp_apply (recv_st_spec N loc with "Hstly"). iIntros (hdy hdz ys zs) "(Heq & Hhdx & Hhdy & Hhdz)".
iIntros (ly') "[Hstly Hys']". iDestruct "Heq" as %->.
iDestruct "Hys'" as (<- ys') "(Hys' & Hys'_sorted_of)". wp_apply (new_chan_st_spec N _ (sort_protocol ys))=> //.
iDestruct "Hys'_sorted_of" as %[Hys'_sorted Hys'_perm]. iIntros (cy γy) "[Hstly Hstry]".
wp_apply (recv_st_spec N loc with "Hstlz"). wp_apply (wp_fork with "[Hstry]").
iIntros (lz') "[Hstlz Hzs']". { iNext. iApply ("IH" with "Hstry"). iNext. by iIntros "Hstry". }
iDestruct "Hzs'" as (<- zs') "(Hzs' & Hzs'_sorted_of)". wp_apply (new_chan_st_spec N _ (sort_protocol zs))=> //.
iDestruct "Hzs'_sorted_of" as %[Hzs'_sorted Hzs'_perm]. iIntros (cz γz) "[Hstlz Hstrz]".
wp_load. wp_apply (wp_fork with "[Hstrz]").
wp_load. { iNext. iApply ("IH" with "Hstrz"). iNext. by iIntros "Hstrz". }
wp_apply (lmerge_ref_spec with "Hhdx")=> //. wp_apply (send_st_spec N val with "[Hstly]"). iFrame. done.
iIntros "Hhdx". iIntros "Hstly".
wp_apply (send_st_spec N loc with "[Hstr Hhdx]"). wp_apply (send_st_spec N loc with "[Hhdy Hstly]"). iFrame.
{ iIntros "Hstly".
iFrame. wp_apply (send_st_spec N val with "[Hstlz]"). iFrame. done.
iSplit=> //. iIntros "Hstlz".
iExists (list_merge () ys' zs'). wp_apply (send_st_spec N loc with "[Hhdz Hstlz]"). iFrame.
iSplit=> //. iIntros "Hstlz".
iPureIntro. wp_apply (recv_st_spec N loc with "Hstly").
split. iIntros (ly') "[Hstly Hys']".
- apply Sorted_list_merge=> //. iDestruct "Hys'" as (<- ys') "(Hys' & Hys'_sorted_of)".
{ intros x y. lia. } (* Why is this needed? *) iDestruct "Hys'_sorted_of" as %[Hys'_sorted Hys'_perm].
- rewrite merge_Permutation. wp_apply (recv_st_spec N loc with "Hstlz").
by apply Permutation_app. iIntros (lz') "[Hstlz Hzs']".
} iDestruct "Hzs'" as (<- zs') "(Hzs' & Hzs'_sorted_of)".
iIntros "Hstr". iDestruct "Hzs'_sorted_of" as %[Hzs'_sorted Hzs'_perm].
by iApply "HΦ". wp_load.
Qed. wp_load.
wp_pures.
wp_apply (lmerge_ref_spec with "[Hhdx]")=> //.
iIntros "Hhdx".
wp_apply (send_st_spec N loc with "[Hstr Hhdx]").
{
iFrame.
iSplit=> //.
iExists (list_merge R ys' zs').
iSplit=> //.
iPureIntro.
split.
- apply Sorted_list_merge=> //.
- rewrite merge_Permutation.
by apply Permutation_app.
}
iIntros "Hstr".
by iApply "HΦ".
Qed.
End SortService.
Definition compare_vals : val :=
λ: "x" "y", "x" "y".
Instance total_le : Total Z.le.
Proof. intros x y. lia. Qed.
Lemma compare_vals_spec (x y : Z) :
{{{ True }}}
compare_vals (encode x) (encode y)
{{{ RET (encode (bool_decide (x y))); True }}}.
Proof. iIntros (Φ) "_ HΦ". wp_lam. wp_pures. by iApply "HΦ". Qed.
Definition list_sort : val := Definition list_sort : val :=
λ: "xs", λ: "xs",
let: "c" := new_chan #() in let: "c" := new_chan #() in
Fork(list_sort_service "c");; Fork(list_sort_service "c");;
send "c" #Left "xs";; send "c" #Left compare_vals;;
recv "c" #Left. send "c" #Left "xs";;
recv "c" #Left.
Lemma list_sort_spec l xs : Lemma list_sort_spec l xs :
{{{ l encode xs }}} {{{ l encode xs }}}
...@@ -234,19 +251,30 @@ Section ListSortExample. ...@@ -234,19 +251,30 @@ Section ListSortExample.
Proof. Proof.
iIntros (Φ) "Hc HΦ". iIntros (Φ) "Hc HΦ".
wp_lam. wp_lam.
wp_apply (new_chan_st_spec N wp_apply (new_chan_st_spec N _ (sort_protocol () xs))=> //.
(<!> l @ l encode xs,
<?> l' @ l = l'
( ys : list Z,
l' encode ys
Sorted () ys
Permutation ys xs), TEnd))=>//.
iIntros (c γ) "[Hstl Hstr]". iIntros (c γ) "[Hstl Hstr]".
wp_apply (wp_fork with "[Hstr]"). wp_apply (wp_fork with "[Hstr]").
{ {
iApply (list_sort_service_spec γ c xs with "[Hstr]"). iFrame. iApply (list_sort_service_spec () γ c xs with "Hstr").
iNext. iNext. iIntros "Hstr". done. iNext. iNext. iIntros "Hstr". done.
} }
wp_apply (send_st_spec N val with "[$Hstl]").
{
iPureIntro.
iIntros (x y Φ').
iModIntro. iIntros (_) "HΦ".
iApply compare_vals_spec=> //.
iNext.
iIntros (_).
destruct (decide (x y)).
- rewrite bool_decide_true=>//.
rewrite bool_decide_true=>//.
by iApply "HΦ".
- rewrite bool_decide_false=>//.
rewrite bool_decide_false=>//.
by iApply "HΦ".
}
iIntros "Hstl".
wp_apply (send_st_spec N loc with "[Hc $Hstl]"). iFrame. wp_apply (send_st_spec N loc with "[Hc $Hstl]"). iFrame.
iIntros "Hstl". iIntros "Hstl".
wp_apply (recv_st_spec N loc with "Hstl"). wp_apply (recv_st_spec N loc with "Hstl").
...@@ -254,5 +282,4 @@ Section ListSortExample. ...@@ -254,5 +282,4 @@ Section ListSortExample.
iDestruct "HP" as (<- ys) "[Hys Hys_sorted_of]". iDestruct "HP" as (<- ys) "[Hys Hys_sorted_of]".
iApply "HΦ". iFrame. iApply "HΦ". iFrame.
Qed. Qed.
End ListSortExample. End ListSortExample.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment