Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Jonas Kastberg
iris
Commits
6b37b21d
Commit
6b37b21d
authored
Oct 31, 2018
by
Robbert Krebbers
Browse files
Merge branch 'robbert/fork_postcondition' into 'master'
Fine-grained post-conditions for forked-off threads See merge request FP/iris-coq!182
parents
b0e4b6fa
678b75da
Changes
14
Hide whitespace changes
Inline
Side-by-side
CHANGELOG.md
View file @
6b37b21d
...
...
@@ -34,10 +34,14 @@ Changes in and extensions of the theory:
*
[#] heap_lang values are now injected in heap_lang expressions via a specific
constructor of the expr inductive type. This simplifies much the tactical
infrastructure around the language. In particular, this allow us to get rid
the refle
x
ion mechanism that was needed for proving closedness, atomicity and
the refle
ct
ion mechanism that was needed for proving closedness, atomicity and
"valueness" of a term. The price to pay is the addition of new
"administrative" reductions in the operational semantics of the language.
*
[#] Extend the state interpretation with a natural number that keeps track of
the number of forked-off threads, and have a global fixed proposition that
describes the postcondition of each forked-off thread (instead of it being
`True`
). Additionally, there is a stronger variant of the adequacy theorem
that allows to make use of the postconditions of the forked-off threads.
Changes in Coq:
...
...
theories/heap_lang/lifting.v
View file @
6b37b21d
...
...
@@ -16,8 +16,9 @@ Class heapG Σ := HeapG {
Instance
heapG_irisG
`
{
heapG
Σ
}
:
irisG
heap_lang
Σ
:
=
{
iris_invG
:
=
heapG_invG
;
state_interp
σ
κ
s
:
=
(
gen_heap_ctx
σ
.(
heap
)
∗
proph_map_ctx
κ
s
σ
.(
used_proph_id
))%
I
state_interp
σ
κ
s
_
:
=
(
gen_heap_ctx
σ
.(
heap
)
∗
proph_map_ctx
κ
s
σ
.(
used_proph_id
))%
I
;
fork_post
_
:
=
True
%
I
;
}.
(** Override the notations so that scopes and coercions work out *)
...
...
@@ -161,17 +162,17 @@ Implicit Types σ : state.
Lemma
wp_fork
s
E
e
Φ
:
▷
WP
e
@
s
;
⊤
{{
_
,
True
}}
-
∗
▷
Φ
(
LitV
LitUnit
)
-
∗
WP
Fork
e
@
s
;
E
{{
Φ
}}.
Proof
.
iIntros
"He HΦ"
.
i
Apply
wp_lift_pure_det_head_step
;
[
by
eauto
|
intros
;
inv_head_step
;
by
eauto
|]
.
iModIntro
;
iNext
;
iIntros
"!> /= {$He}"
.
by
iApply
wp_valu
e
.
iIntros
"He HΦ"
.
iApply
wp_lift_atomic_head_step
;
[
done
|].
i
Intros
(
σ
1
κ
κ
s
n
)
"Hσ !>"
;
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
by
iFram
e
.
Qed
.
Lemma
twp_fork
s
E
e
Φ
:
WP
e
@
s
;
⊤
[{
_
,
True
}]
-
∗
Φ
(
LitV
LitUnit
)
-
∗
WP
Fork
e
@
s
;
E
[{
Φ
}].
Proof
.
iIntros
"He HΦ"
.
i
Apply
twp_lift_pure_det_head_step
;
[
eauto
|
intros
;
inv_head_step
;
eauto
|]
.
iIntros
"!> /= {$He}"
.
by
iApply
twp_valu
e
.
iIntros
"He HΦ"
.
iApply
twp_lift_atomic_head_step
;
[
done
|].
i
Intros
(
σ
1
κ
s
n
)
"Hσ !>"
;
iSplit
;
first
by
eauto
.
iIntros
(
κ
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
by
iFram
e
.
Qed
.
(** Heap *)
...
...
@@ -179,7 +180,7 @@ Lemma wp_alloc s E v :
{{{
True
}}}
Alloc
(
Val
v
)
@
s
;
E
{{{
l
,
RET
LitV
(
LitLoc
l
)
;
l
↦
v
}}}.
Proof
.
iIntros
(
Φ
)
"_ HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ Hκs] !>"
;
iSplit
;
first
by
auto
.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ Hκs] !>"
;
iSplit
;
first
by
auto
.
iNext
;
iIntros
(
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_alloc
with
"Hσ"
)
as
"[Hσ Hl]"
;
first
done
.
iModIntro
;
iSplit
=>
//.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -188,7 +189,7 @@ Lemma twp_alloc s E v :
[[{
True
}]]
Alloc
(
Val
v
)
@
s
;
E
[[{
l
,
RET
LitV
(
LitLoc
l
)
;
l
↦
v
}]].
Proof
.
iIntros
(
Φ
)
"_ HΦ"
.
iApply
twp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
s
)
"[Hσ Hκs] !>"
;
iSplit
;
first
by
e
auto
.
iIntros
(
σ
1
κ
s
n
)
"[Hσ Hκs] !>"
;
iSplit
;
first
by
auto
.
iIntros
(
κ
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_alloc
with
"Hσ"
)
as
"[Hσ Hl]"
;
first
done
.
iModIntro
;
iSplit
=>
//.
iSplit
;
first
done
.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -198,7 +199,7 @@ Lemma wp_load s E l q v :
{{{
▷
l
↦
{
q
}
v
}}}
Load
(
Val
$
LitV
$
LitLoc
l
)
@
s
;
E
{{{
RET
v
;
l
↦
{
q
}
v
}}}.
Proof
.
iIntros
(
Φ
)
">Hl HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iModIntro
;
iSplit
=>
//.
iFrame
.
by
iApply
"HΦ"
.
Qed
.
...
...
@@ -206,7 +207,7 @@ Lemma twp_load s E l q v :
[[{
l
↦
{
q
}
v
}]]
Load
(
Val
$
LitV
$
LitLoc
l
)
@
s
;
E
[[{
RET
v
;
l
↦
{
q
}
v
}]].
Proof
.
iIntros
(
Φ
)
"Hl HΦ"
.
iApply
twp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iIntros
(
κ
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iModIntro
;
iSplit
=>
//.
iSplit
;
first
done
.
iFrame
.
by
iApply
"HΦ"
.
Qed
.
...
...
@@ -217,7 +218,7 @@ Lemma wp_store s E l v' v :
Proof
.
iIntros
(
Φ
)
">Hl HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_update
with
"Hσ Hl"
)
as
"[$ Hl]"
.
iModIntro
.
iSplit
=>//.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -228,7 +229,7 @@ Lemma twp_store s E l v' v :
Proof
.
iIntros
(
Φ
)
"Hl HΦ"
.
iApply
twp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iIntros
(
κ
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_update
with
"Hσ Hl"
)
as
"[$ Hl]"
.
iModIntro
.
iSplit
=>//.
iSplit
;
first
done
.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -240,7 +241,7 @@ Lemma wp_cas_fail s E l q v' v1 v2 :
{{{
RET
LitV
(
LitBool
false
)
;
l
↦
{
q
}
v'
}}}.
Proof
.
iIntros
(??
Φ
)
">Hl HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2'
σ
2
efs
Hstep
)
;
inv_head_step
.
iModIntro
;
iSplit
=>
//.
iFrame
.
by
iApply
"HΦ"
.
Qed
.
...
...
@@ -250,7 +251,7 @@ Lemma twp_cas_fail s E l q v' v1 v2 :
[[{
RET
LitV
(
LitBool
false
)
;
l
↦
{
q
}
v'
}]].
Proof
.
iIntros
(??
Φ
)
"Hl HΦ"
.
iApply
twp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iIntros
(
κ
v2'
σ
2
efs
Hstep
)
;
inv_head_step
.
iModIntro
;
iSplit
=>
//.
iSplit
;
first
done
.
iFrame
.
by
iApply
"HΦ"
.
Qed
.
...
...
@@ -261,7 +262,7 @@ Lemma wp_cas_suc s E l v1 v2 :
{{{
RET
LitV
(
LitBool
true
)
;
l
↦
v2
}}}.
Proof
.
iIntros
(?
Φ
)
">Hl HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2'
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_update
with
"Hσ Hl"
)
as
"[$ Hl]"
.
iModIntro
.
iSplit
=>//.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -272,7 +273,7 @@ Lemma twp_cas_suc s E l v1 v2 :
[[{
RET
LitV
(
LitBool
true
)
;
l
↦
v2
}]].
Proof
.
iIntros
(?
Φ
)
"Hl HΦ"
.
iApply
twp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iIntros
(
κ
v2'
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_update
with
"Hσ Hl"
)
as
"[$ Hl]"
.
iModIntro
.
iSplit
=>//.
iSplit
;
first
done
.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -283,7 +284,7 @@ Lemma wp_faa s E l i1 i2 :
{{{
RET
LitV
(
LitInt
i1
)
;
l
↦
LitV
(
LitInt
(
i1
+
i2
))
}}}.
Proof
.
iIntros
(
Φ
)
">Hl HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2'
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_update
with
"Hσ Hl"
)
as
"[$ Hl]"
.
iModIntro
.
iSplit
=>//.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -293,7 +294,7 @@ Lemma twp_faa s E l i1 i2 :
[[{
RET
LitV
(
LitInt
i1
)
;
l
↦
LitV
(
LitInt
(
i1
+
i2
))
}]].
Proof
.
iIntros
(
Φ
)
"Hl HΦ"
.
iApply
twp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
s
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iIntros
(
σ
1
κ
s
n
)
"[Hσ Hκs] !>"
.
iDestruct
(@
gen_heap_valid
with
"Hσ Hl"
)
as
%?.
iSplit
;
first
by
eauto
.
iIntros
(
κ
e2
σ
2
efs
Hstep
)
;
inv_head_step
.
iMod
(@
gen_heap_update
with
"Hσ Hl"
)
as
"[$ Hl]"
.
iModIntro
.
iSplit
=>//.
iSplit
;
first
done
.
iFrame
.
by
iApply
"HΦ"
.
...
...
@@ -304,7 +305,7 @@ Lemma wp_new_proph :
{{{
True
}}}
NewProph
{{{
v
(
p
:
proph_id
),
RET
(
LitV
(
LitProphecy
p
))
;
proph
p
v
}}}.
Proof
.
iIntros
(
Φ
)
"_ HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ HR] !>"
.
iDestruct
"HR"
as
(
R
[
Hfr
Hdom
])
"HR"
.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ HR] !>"
.
iDestruct
"HR"
as
(
R
[
Hfr
Hdom
])
"HR"
.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2
σ
2
efs
Hstep
).
inv_head_step
.
iMod
(@
proph_map_alloc
with
"HR"
)
as
"[HR Hp]"
.
...
...
@@ -323,7 +324,7 @@ Lemma wp_resolve_proph p v w:
{{{
RET
(
LitV
LitUnit
)
;
⌜
v
=
Some
w
⌝
}}}.
Proof
.
iIntros
(
Φ
)
"Hp HΦ"
.
iApply
wp_lift_atomic_head_step_no_fork
;
auto
.
iIntros
(
σ
1
κ
κ
s
)
"[Hσ HR] !>"
.
iDestruct
"HR"
as
(
R
[
Hfr
Hdom
])
"HR"
.
iIntros
(
σ
1
κ
κ
s
n
)
"[Hσ HR] !>"
.
iDestruct
"HR"
as
(
R
[
Hfr
Hdom
])
"HR"
.
iDestruct
(@
proph_map_valid
with
"HR Hp"
)
as
%
Hlookup
.
iSplit
;
first
by
eauto
.
iNext
;
iIntros
(
v2
σ
2
efs
Hstep
)
;
inv_head_step
.
iApply
fupd_frame_l
.
...
...
@@ -331,8 +332,7 @@ Proof.
iMod
(@
proph_map_remove
with
"HR Hp"
)
as
"Hp"
.
iModIntro
.
iSplitR
"HΦ"
.
-
iExists
_
.
iFrame
.
iPureIntro
.
split
;
first
by
eapply
first_resolve_delete
.
rewrite
dom_delete
.
rewrite
<-
difference_empty_L
.
by
eapply
difference_mono
.
rewrite
dom_delete
.
set_solver
.
-
iApply
"HΦ"
.
iPureIntro
.
by
eapply
first_resolve_eq
.
Qed
.
End
lifting
.
theories/heap_lang/total_adequacy.v
View file @
6b37b21d
...
...
@@ -12,6 +12,8 @@ Proof.
iMod
(
gen_heap_init
σ
.(
heap
))
as
(?)
"Hh"
.
iMod
(
proph_map_init
[]
σ
.(
used_proph_id
))
as
(?)
"Hp"
.
iModIntro
.
iExists
(
λ
σ
κ
s
,
(
gen_heap_ctx
σ
.(
heap
)
∗
proph_map_ctx
κ
s
σ
.(
used_proph_id
))%
I
).
iFrame
.
iExists
(
λ
σ
κ
s
_
,
(
gen_heap_ctx
σ
.(
heap
)
∗
proph_map_ctx
κ
s
σ
.(
used_proph_id
))%
I
),
(
λ
_
,
True
%
I
)
;
iFrame
.
iApply
(
Hwp
(
HeapG
_
_
_
_
)).
Qed
.
theories/program_logic/adequacy.v
View file @
6b37b21d
...
...
@@ -39,14 +39,14 @@ Implicit Types P Q : iProp Σ.
Implicit
Types
Φ
:
val
Λ
→
iProp
Σ
.
Implicit
Types
Φ
s
:
list
(
val
Λ
→
iProp
Σ
).
Notation
wptp
s
t
:
=
([
∗
list
]
ef
∈
t
,
WP
ef
@
s
;
⊤
{{
_
,
True
}})%
I
.
Notation
wptp
s
t
:
=
([
∗
list
]
ef
∈
t
,
WP
ef
@
s
;
⊤
{{
fork_post
}})%
I
.
Lemma
wp_step
s
E
e1
σ
1
κ
κ
s
e2
σ
2
efs
Φ
:
Lemma
wp_step
s
e1
σ
1
κ
κ
s
e2
σ
2
efs
m
Φ
:
prim_step
e1
σ
1
κ
e2
σ
2
efs
→
state_interp
σ
1
(
κ
++
κ
s
)
∗
WP
e1
@
s
;
E
{{
Φ
}}
={
E
,
∅
}
▷
=
∗
(
state_interp
σ
2
κ
s
∗
WP
e2
@
s
;
E
{{
Φ
}}
∗
wptp
s
efs
)
.
state_interp
σ
1
(
κ
++
κ
s
)
m
-
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
={
⊤
,
∅
}
▷
=
∗
state_interp
σ
2
κ
s
(
length
efs
+
m
)
∗
WP
e2
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
efs
.
Proof
.
rewrite
{
1
}
wp_unfold
/
wp_pre
.
iIntros
(?)
"
[
Hσ H
]
"
.
rewrite
{
1
}
wp_unfold
/
wp_pre
.
iIntros
(?)
"Hσ H"
.
rewrite
(
val_stuck
e1
σ
1
κ
e2
σ
2
efs
)
//.
iMod
(
"H"
$!
σ
1
with
"Hσ"
)
as
"(_ & H)"
.
iMod
(
"H"
$!
e2
σ
2
efs
with
"[//]"
)
as
"H"
.
...
...
@@ -55,43 +55,52 @@ Qed.
Lemma
wptp_step
s
e1
t1
t2
κ
κ
s
σ
1
σ
2
Φ
:
step
(
e1
::
t1
,
σ
1
)
κ
(
t2
,
σ
2
)
→
state_interp
σ
1
(
κ
++
κ
s
)
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t1
==
∗
∃
e2
t2'
,
⌜
t2
=
e2
::
t2'
⌝
∗
|={
⊤
,
∅
}
▷
=>
(
state_interp
σ
2
κ
s
∗
WP
e2
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t2'
)
.
state_interp
σ
1
(
κ
++
κ
s
)
(
length
t1
)
-
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
-
∗
wptp
s
t1
==
∗
∃
e2
t2'
,
⌜
t2
=
e2
::
t2'
⌝
∗
|={
⊤
,
∅
}
▷
=>
state_interp
σ
2
κ
s
(
pred
(
length
t2
))
∗
WP
e2
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t2'
.
Proof
.
iIntros
(
Hstep
)
"
(HW &
He
&
Ht
)
"
.
iIntros
(
Hstep
)
"
Hσ
He Ht"
.
destruct
Hstep
as
[
e1'
σ
1
'
e2'
σ
2
'
efs
[|?
t1'
]
t2'
??
Hstep
]
;
simplify_eq
/=.
-
iExists
e2'
,
(
t2'
++
efs
).
iSplitR
;
first
by
eauto
.
iFrame
"Ht"
.
iApply
wp_step
;
eauto
with
iFrame
.
-
iExists
e2'
,
(
t2'
++
efs
).
iModIntro
.
iSplitR
;
first
by
eauto
.
iMod
(
wp_step
with
"Hσ He"
)
as
"H"
;
first
done
.
iIntros
"!> !>"
.
iMod
"H"
as
"(Hσ & He2 & Hefs)"
.
iIntros
"!>"
.
rewrite
Nat
.
add_comm
app_length
.
iFrame
.
-
iExists
e
,
(
t1'
++
e2'
::
t2'
++
efs
)
;
iSplitR
;
first
eauto
.
iDestruct
"Ht"
as
"($ & He' & $)"
.
iFrame
"He"
.
iApply
wp_step
;
eauto
with
iFrame
.
iFrame
"He"
.
iDestruct
"Ht"
as
"(Ht1 & He1 & Ht2)"
.
iModIntro
.
iMod
(
wp_step
with
"Hσ He1"
)
as
"H"
;
first
done
.
iIntros
"!> !>"
.
iMod
"H"
as
"(Hσ & He2 & Hefs)"
.
iIntros
"!>"
.
rewrite
!
app_length
/=
!
app_length
.
replace
(
length
t1'
+
S
(
length
t2'
+
length
efs
))
with
(
length
efs
+
(
length
t1'
+
S
(
length
t2'
)))
by
omega
.
iFrame
.
Qed
.
Lemma
wptp_steps
s
n
e1
t1
κ
s
κ
s'
t2
σ
1
σ
2
Φ
:
nsteps
n
(
e1
::
t1
,
σ
1
)
κ
s
(
t2
,
σ
2
)
→
state_interp
σ
1
(
κ
s
++
κ
s'
)
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t1
⊢
|={
⊤
,
∅
}
▷
=>^
n
(
∃
e2
t2'
,
⌜
t2
=
e2
::
t2'
⌝
∗
state_interp
σ
2
κ
s'
∗
WP
e2
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t2'
).
state_interp
σ
1
(
κ
s
++
κ
s'
)
(
length
t1
)
-
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
-
∗
wptp
s
t1
={
⊤
,
∅
}
▷
=
∗
^
n
∃
e2
t2'
,
⌜
t2
=
e2
::
t2'
⌝
∗
state_interp
σ
2
κ
s'
(
pred
(
length
t2
))
∗
WP
e2
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t2'
.
Proof
.
revert
e1
t1
κ
s
κ
s'
t2
σ
1
σ
2
;
simpl
;
induction
n
as
[|
n
IH
]=>
e1
t1
κ
s
κ
s'
t2
σ
1
σ
2
/=.
{
inversion_clear
1
;
iIntros
"(?&?&?)"
;
iExists
e1
,
t1
;
iFrame
;
eauto
10
.
}
iIntros
(
Hsteps
)
"H"
.
inversion_clear
Hsteps
as
[|??
[
t1'
σ
1
'
]].
rewrite
<-
app_assoc
.
iMod
(
wptp_step
with
"H"
)
as
(
e1'
t1''
)
"[% H]"
;
first
eauto
;
simplify_eq
.
iMod
"H"
.
iModIntro
;
iNext
.
iMod
"H"
.
iModIntro
.
by
iApply
IH
.
revert
e1
t1
κ
s
κ
s'
t2
σ
1
σ
2
;
simpl
.
induction
n
as
[|
n
IH
]=>
e1
t1
κ
s
κ
s'
t2
σ
1
σ
2
/=.
{
inversion_clear
1
;
iIntros
"???"
;
iExists
e1
,
t1
;
iFrame
;
eauto
10
.
}
iIntros
(
Hsteps
)
"Hσ He Ht"
.
inversion_clear
Hsteps
as
[|??
[
t1'
σ
1
'
]].
rewrite
-(
assoc_L
(++)).
iMod
(
wptp_step
with
"Hσ He Ht"
)
as
(
e1'
t1''
?)
">H"
;
first
eauto
;
simplify_eq
.
iIntros
"!> !>"
.
iMod
"H"
as
"(Hσ & He & Ht)"
.
iModIntro
.
by
iApply
(
IH
with
"Hσ He Ht"
).
Qed
.
Lemma
wptp_result
s
n
e1
t1
κ
s
κ
s'
v2
t2
σ
1
σ
2
φ
:
Lemma
wptp_result
φ
κ
s'
s
n
e1
t1
κ
s
v2
t2
σ
1
σ
2
:
nsteps
n
(
e1
::
t1
,
σ
1
)
κ
s
(
of_val
v2
::
t2
,
σ
2
)
→
state_interp
σ
1
(
κ
s
++
κ
s'
)
∗
WP
e1
@
s
;
⊤
{{
v
,
∀
σ
,
state_interp
σ
κ
s'
={
⊤
,
∅
}=
∗
⌜φ
v
σ⌝
}}
∗
wptp
s
t1
⊢
|={
⊤
,
∅
}
▷
=>^(
S
n
)
⌜φ
v2
σ
2
⌝
.
state_interp
σ
1
(
κ
s
++
κ
s'
)
(
length
t1
)
-
∗
WP
e1
@
s
;
⊤
{{
v
,
∀
σ
,
state_interp
σ
κ
s'
(
length
t2
)
={
⊤
,
∅
}=
∗
⌜φ
v
σ⌝
}}
-
∗
wptp
s
t1
={
⊤
,
∅
}
▷
=
∗
^(
S
n
)
⌜φ
v2
σ
2
⌝
.
Proof
.
intros
.
rewrite
Nat_iter_S_r
wptp_steps
//.
apply
step_fupdN_mono
.
iIntros
(?)
"Hσ He Ht"
.
rewrite
Nat_iter_S_r
.
iDestruct
(
wptp_steps
with
"Hσ He Ht"
)
as
"H"
;
first
done
.
iApply
(
step_fupdN_wand
with
"H"
).
iDestruct
1
as
(
e2
t2'
?)
"(Hσ & H & _)"
;
simplify_eq
.
iMod
(
wp_value_inv'
with
"H"
)
as
"H"
.
iMod
(
fupd_plain_mask_empty
_
⌜φ
v2
σ
2
⌝
%
I
with
"[H Hσ]"
)
as
%?.
...
...
@@ -99,109 +108,166 @@ Proof.
by
iApply
step_fupd_intro
.
Qed
.
Lemma
wp_safe
E
e
σ
κ
s
Φ
:
state_interp
σ
κ
s
-
∗
WP
e
@
E
{{
Φ
}}
={
E
,
∅
}
▷
=
∗
⌜
is_Some
(
to_val
e
)
∨
reducible
e
σ⌝
.
Lemma
wptp_all_result
φ
κ
s'
s
n
e1
t1
κ
s
v2
vs2
σ
1
σ
2
:
nsteps
n
(
e1
::
t1
,
σ
1
)
κ
s
(
of_val
<$>
v2
::
vs2
,
σ
2
)
→
state_interp
σ
1
(
κ
s
++
κ
s'
)
(
length
t1
)
-
∗
WP
e1
@
s
;
⊤
{{
v
,
state_interp
σ
2
κ
s'
(
length
vs2
)
-
∗
([
∗
list
]
v
∈
vs2
,
fork_post
v
)
={
⊤
,
∅
}=
∗
⌜φ
v
⌝
}}
-
∗
wptp
s
t1
={
⊤
,
∅
}
▷
=
∗
^(
S
n
)
⌜φ
v2
⌝
.
Proof
.
iIntros
(
Hstep
)
"Hσ He Ht"
.
rewrite
Nat_iter_S_r
.
iDestruct
(
wptp_steps
with
"Hσ He Ht"
)
as
"H"
;
first
done
.
iApply
(
step_fupdN_wand
with
"H"
).
iDestruct
1
as
(
e2
t2'
?)
"(Hσ & H & Hvs)"
;
simplify_eq
/=.
rewrite
fmap_length
.
iMod
(
wp_value_inv'
with
"H"
)
as
"H"
.
iAssert
([
∗
list
]
v
∈
vs2
,
fork_post
v
)%
I
with
"[> Hvs]"
as
"Hm"
.
{
clear
Hstep
.
iInduction
vs2
as
[|
v
vs
]
"IH"
;
csimpl
;
first
by
iFrame
.
iDestruct
"Hvs"
as
"[Hv Hvs]"
.
iMod
(
wp_value_inv'
with
"Hv"
)
as
"$"
.
by
iApply
"IH"
.
}
iMod
(
fupd_plain_mask_empty
_
⌜φ
v2
⌝
%
I
with
"[H Hm Hσ]"
)
as
%?.
{
iApply
(
"H"
with
"Hσ Hm"
).
}
by
iApply
step_fupd_intro
.
Qed
.
Lemma
wp_safe
κ
s
m
e
σ
Φ
:
state_interp
σ
κ
s
m
-
∗
WP
e
{{
Φ
}}
={
⊤
,
∅
}
▷
=
∗
⌜
is_Some
(
to_val
e
)
∨
reducible
e
σ⌝
.
Proof
.
rewrite
wp_unfold
/
wp_pre
.
iIntros
"Hσ H"
.
destruct
(
to_val
e
)
as
[
v
|]
eqn
:
?.
{
iApply
(
step_fupd_
mask_mono
∅
_
_
∅
)
;
eaut
o
.
set_solver
.
}
{
iApply
step_fupd_
intr
o
.
set_solver
.
eauto
.
}
iMod
(
fupd_plain_mask_empty
_
⌜
reducible
e
σ⌝
%
I
with
"[H Hσ]"
)
as
%?.
{
by
iMod
(
"H"
$!
σ
[]
κ
s
with
"Hσ"
)
as
"
($&H)
"
.
}
{
by
iMod
(
"H"
$!
σ
[]
κ
s
with
"Hσ"
)
as
"
[$ H]
"
.
}
iApply
step_fupd_intro
;
first
by
set_solver
+.
iIntros
"!> !%"
.
by
right
.
Qed
.
Lemma
wptp_safe
n
e1
κ
s
κ
s'
e2
t1
t2
σ
1
σ
2
Φ
:
Lemma
wptp_safe
κ
s'
n
e1
κ
s
e2
t1
t2
σ
1
σ
2
Φ
:
nsteps
n
(
e1
::
t1
,
σ
1
)
κ
s
(
t2
,
σ
2
)
→
e2
∈
t2
→
state_interp
σ
1
(
κ
s
++
κ
s'
)
∗
WP
e1
{{
Φ
}}
∗
wptp
NotStuck
t1
⊢
|
={
⊤
,
∅
}
▷
=
>
^(
S
n
)
⌜
is_Some
(
to_val
e2
)
∨
reducible
e2
σ
2
⌝
.
state_interp
σ
1
(
κ
s
++
κ
s'
)
(
length
t1
)
-
∗
WP
e1
{{
Φ
}}
-
∗
wptp
NotStuck
t1
={
⊤
,
∅
}
▷
=
∗
^(
S
n
)
⌜
is_Some
(
to_val
e2
)
∨
reducible
e2
σ
2
⌝
.
Proof
.
intros
?
He2
.
rewrite
Nat_iter_S_r
wptp_steps
//.
apply
step_fupdN_mono
.
iDestruct
1
as
(
e2'
t2'
?)
"(Hw & H & Htp)"
;
simplify_eq
.
apply
elem_of_cons
in
He2
as
[<-|?].
-
iMod
(
wp_safe
with
"Hw H"
)
as
"$"
;
auto
.
-
iMod
(
wp_safe
with
"Hw [Htp]"
)
as
"$"
;
auto
.
by
iApply
(
big_sepL_elem_of
with
"Htp"
).
iIntros
(?
He2
)
"Hσ He Ht"
.
rewrite
Nat_iter_S_r
.
iDestruct
(
wptp_steps
with
"Hσ He Ht"
)
as
"H"
;
first
done
.
iApply
(
step_fupdN_wand
with
"H"
).
iDestruct
1
as
(
e2'
t2'
?)
"(Hσ & H & Ht)"
;
simplify_eq
.
apply
elem_of_cons
in
He2
as
[<-|(
t1''
&
t2''
&->)%
elem_of_list_split
].
-
iMod
(
wp_safe
with
"Hσ H"
)
as
"$"
;
auto
.
-
iDestruct
"Ht"
as
"(_ & He2 & _)"
.
by
iMod
(
wp_safe
with
"Hσ He2"
).
Qed
.
Lemma
wptp_invariance
s
n
e1
κ
s
κ
s'
e2
t1
t2
σ
1
σ
2
φ
Φ
:
Lemma
wptp_invariance
φ
s
n
e1
κ
s
κ
s'
e2
t1
t2
σ
1
σ
2
Φ
:
nsteps
n
(
e1
::
t1
,
σ
1
)
κ
s
(
t2
,
σ
2
)
→
(
state_interp
σ
2
κ
s'
={
⊤
,
∅
}=
∗
⌜φ⌝
)
∗
state_interp
σ
1
(
κ
s
++
κ
s'
)
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
∗
wptp
s
t1
⊢
|={
⊤
,
∅
}
▷
=>^(
S
n
)
|={
⊤
,
∅
}=>
⌜φ⌝
.
(
state_interp
σ
2
κ
s'
(
pred
(
length
t2
))
={
⊤
,
∅
}=
∗
⌜φ⌝
)
-
∗
state_interp
σ
1
(
κ
s
++
κ
s'
)
(
length
t1
)
-
∗
WP
e1
@
s
;
⊤
{{
Φ
}}
-
∗
wptp
s
t1
={
⊤
,
∅
}
▷
=
∗
^(
S
n
)
⌜φ⌝
.
Proof
.
intros
?.
rewrite
Nat_iter_S_r
wptp_steps
//
step_fupdN_frame_l
.
apply
step_fupdN_mono
.
iIntros
"[Hback H]"
;
iDestruct
"H"
as
(
e2'
t2'
->)
"[Hσ _]"
.
iSpecialize
(
"Hback"
with
"Hσ"
).
by
iApply
step_fupd_intro
.
iIntros
(?)
"Hφ Hσ He Ht"
.
rewrite
Nat_iter_S_r
.
iDestruct
(
wptp_steps
_
n
with
"Hσ He Ht"
)
as
"H"
;
first
done
.
iApply
(
step_fupdN_wand
with
"H"
).
iDestruct
1
as
(
e2'
t2'
->)
"[Hσ _]"
.
iSpecialize
(
"Hφ"
with
"Hσ"
).
iMod
(
fupd_plain_mask_empty
_
⌜φ⌝
%
I
with
"Hφ"
)
as
%?.
by
iApply
step_fupd_intro
.
Qed
.
End
adequacy
.
Theorem
wp_strong_adequacy
Σ
Λ
`
{
invPreG
Σ
}
s
e
σ
φ
:
(
∀
`
{
Hinv
:
invG
Σ
}
κ
s
,
(|={
⊤
}=>
∃
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
iProp
Σ
,
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
_
Hinv
stateI
in
stateI
σ
κ
s
∗
WP
e
@
s
;
⊤
{{
v
,
∀
σ
,
stateI
σ
[]
={
⊤
,
∅
}=
∗
⌜φ
v
σ⌝
}})%
I
)
→
(|={
⊤
}=>
∃
(
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
nat
→
iProp
Σ
)
(
fork_post
:
val
Λ
→
iProp
Σ
),
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
Hinv
stateI
fork_post
in
(* This could be strengthened so that φ also talks about the number
of forked-off threads *)
stateI
σ
κ
s
0
∗
WP
e
@
s
;
⊤
{{
v
,
∀
σ
m
,
stateI
σ
[]
m
={
⊤
,
∅
}=
∗
⌜φ
v
σ⌝
}})%
I
)
→
adequate
s
e
σ
φ
.
Proof
.
intros
Hwp
;
split
.
-
intros
t2
σ
2
v2
[
n
[
κ
s
?]]%
erased_steps_nsteps
.
eapply
(
step_fupdN_soundness'
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
i
Mod
Hwp
as
(
Istate
)
"[HI Hwp]"
.
iApply
(
step_fupd_mask_mono
∅
_
_
∅
)
;
auto
.
iModIntro
.
iNext
;
iModIntr
o
.
iApply
(
@
wp
tp_result
_
_
(
IrisG
_
_
_
Hinv
Istate
)
_
_
_
_
_
[])
;
eauto
with
iFrame
.
eapply
(
step_fupdN_soundness'
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
iMod
(
Hwp
_
(
κ
s
++
[]))
as
(
stateI
fork_post
)
"[Hσ Hwp]"
.
i
Apply
step_fupd_intro
;
first
done
.
iModIntro
.
iApply
(
@
wptp_result
_
_
(
IrisG
_
_
Hinv
stateI
fork_post
)
with
"[Hσ] [Hwp]"
)
;
eaut
o
.
iApply
(
wp
_wand
with
"Hwp"
).
iIntros
(
v
)
"H"
;
iIntros
(
σ
'
).
iApply
"H"
.
-
destruct
s
;
last
done
.
intros
t2
σ
2 e2
_
[
n
[
κ
s
?]]%
erased_steps_nsteps
?.
eapply
(
step_fupdN_soundness'
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
iMod
Hwp
as
(
Istate
)
"[HI Hwp]"
.
iApply
(
step_fupd_mask_mono
∅
_
_
∅
)
;
auto
.
iApply
(@
wptp_safe
_
_
(
IrisG
_
_
_
Hinv
Istate
)
_
_
_
[])
;
[
by
eauto
..|].
rewrite
app_nil_r
.
eauto
with
iFrame
.
eapply
(
step_fupdN_soundness'
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
iMod
(
Hwp
_
(
κ
s
++
[]))
as
(
stateI
fork_post
)
"[Hσ Hwp]"
.
iApply
step_fupd_intro
;
first
done
.
iModIntro
.
iApply
(@
wptp_safe
_
_
(
IrisG
_
_
Hinv
stateI
fork_post
)
with
"[Hσ] Hwp"
)
;
eauto
.
Qed
.
Theorem
wp_adequacy
Σ
Λ
`
{
invPreG
Σ
}
s
e
σ
φ
:
(
∀
`
{
Hinv
:
invG
Σ
}
κ
s
,
(|={
⊤
}=>
∃
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
iProp
Σ
,
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
_
Hinv
stateI
in
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
Hinv
(
λ
σ
κ
s
_
,
stateI
σ
κ
s
)
(
λ
_
,
True
%
I
)
in
stateI
σ
κ
s
∗
WP
e
@
s
;
⊤
{{
v
,
⌜φ
v
⌝
}})%
I
)
→
adequate
s
e
σ
(
λ
v
_
,
φ
v
).
Proof
.
intros
Hwp
.
apply
(
wp_strong_adequacy
Σ
_
)=>
Hinv
κ
s
.
iMod
Hwp
as
(
stateI
)
"[Hσ H]"
.
iExists
stateI
.
iIntros
"{$Hσ} !>"
.
iMod
Hwp
as
(
stateI
)
"[Hσ H]"
.
iExists
(
λ
σ
κ
s
_
,
stateI
σ
κ
s
),
(
λ
_
,
True
%
I
).
iIntros
"{$Hσ} !>"
.
iApply
(
wp_wand
with
"H"
).
iIntros
(
v
?
σ
'
)
"_"
.
iMod
(
fupd_intro_mask'
⊤
∅
)
as
"_"
;
auto
.
iIntros
"_"
.
by
iApply
fupd_mask_weaken
.
Qed
.
Theorem
wp_strong_all_adequacy
Σ
Λ
`
{
invPreG
Σ
}
s
e
σ
1
v
vs
σ
2
φ
:
(
∀
`
{
Hinv
:
invG
Σ
}
κ
s
,
(|={
⊤
}=>
∃
(
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
nat
→
iProp
Σ
)
(
fork_post
:
val
Λ
→
iProp
Σ
),
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
Hinv
stateI
fork_post
in
stateI
σ
1
κ
s
0
∗
WP
e
@
s
;
⊤
{{
v
,
stateI
σ
2
[]
(
length
vs
)
-
∗
([
∗
list
]
v
∈
vs
,
fork_post
v
)
={
⊤
,
∅
}=
∗
⌜
φ
v
⌝
}})%
I
)
→
rtc
erased_step
([
e
],
σ
1
)
(
of_val
<$>
v
::
vs
,
σ
2
)
→
φ
v
.
Proof
.
intros
Hwp
[
n
[
κ
s
?]]%
erased_steps_nsteps
.
eapply
(
step_fupdN_soundness'
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
iMod
Hwp
as
(
stateI
fork_post
)
"[Hσ Hwp]"
.
iApply
step_fupd_intro
;
first
done
.
iModIntro
.
iApply
(@
wptp_all_result
_
_
(
IrisG
_
_
Hinv
stateI
fork_post
)
with
"[Hσ] [Hwp]"
)
;
eauto
.
by
rewrite
right_id_L
.
Qed
.
Theorem
wp_invariance
Σ
Λ
`
{
invPreG
Σ
}
s
e
σ
1
t2
σ
2
φ
:
(
∀
`
{
Hinv
:
invG
Σ
}
κ
s
κ
s'
,
(|={
⊤
}=>
∃
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
iProp
Σ
,
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
_
Hinv
stateI
in
stateI
σ
1
(
κ
s
++
κ
s'
)
∗
WP
e
@
s
;
⊤
{{
_
,
True
}}
∗
(
stateI
σ
2
κ
s'
={
⊤
,
∅
}=
∗
⌜φ⌝
))%
I
)
→
(|={
⊤
}=>
∃
(
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
nat
→
iProp
Σ
)
(
fork_post
:
val
Λ
→
iProp
Σ
),
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
Hinv
stateI
fork_post
in
stateI
σ
1
(
κ
s
++
κ
s'
)
0
∗
WP
e
@
s
;
⊤
{{
_
,
True
}}
∗
(
stateI
σ
2
κ
s'
(
pred
(
length
t2
))
={
⊤
,
∅
}=
∗
⌜φ⌝
))%
I
)
→
rtc
erased_step
([
e
],
σ
1
)
(
t2
,
σ
2
)
→
φ
.
Proof
.
intros
Hwp
[
n
[
κ
s
?]]%
erased_steps_nsteps
.
eapply
(
step_fupdN_soundness
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
iMod
(
Hwp
Hinv
κ
s
[])
as
(
Istate
)
"(HIstate & Hwp & Hclose)"
.
apply
(
step_fupdN_soundness'
_
(
S
(
S
n
)))=>
Hinv
.
rewrite
Nat_iter_S
.
iMod
(
Hwp
Hinv
κ
s
[])
as
(
Istate
fork_post
)
"(Hσ & Hwp & Hclose)"
.
iApply
step_fupd_intro
;
first
done
.
iApply
(@
wptp_invariance
_
_
(
IrisG
_
_
_
Hinv
Istate
))
;
eauto
with
iFrame
.
iApply
(@
wptp_invariance
_
_
(
IrisG
_
_
Hinv
Istate
fork_post
)
with
"Hclose [Hσ] [Hwp]"
)
;
eauto
.
Qed
.
(* An equivalent version that does not require finding [fupd_intro_mask'], but
can be confusing to use. *)
Corollary
wp_invariance'
Σ
Λ
`
{
invPreG
Σ
}
s
e
σ
1
t2
σ
2
φ
:
(
∀
`
{
Hinv
:
invG
Σ
}
κ
s
κ
s'
,
(|={
⊤
}=>
∃
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
iProp
Σ
,
let
_
:
irisG
Λ
Σ
:
=
IrisG
_
_
_
Hinv
stateI
in
stateI
σ
1
κ
s
∗
WP
e
@
s
;
⊤
{{
_
,
True
}}
∗
(
stateI
σ
2
κ
s'
-
∗
∃
E
,
|={
⊤
,
E
}=>
⌜φ⌝
))%
I
)
→
(|={
⊤
}=>
∃
(
stateI
:
state
Λ
→
list
(
observation
Λ
)
→
nat
→
iProp
Σ
)