Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
Actris
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
tlsomers
Actris
Commits
aa527705
Commit
aa527705
authored
5 years ago
by
Jonas Kastberg Hinrichsen
Browse files
Options
Downloads
Patches
Plain Diff
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
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
theories/examples/list_sort.v
+235
-208
235 additions, 208 deletions
theories/examples/list_sort.v
with
235 additions
and
208 deletions
theories/examples/list_sort.v
+
235
−
208
View file @
aa527705
...
@@ -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
.
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment