shc "k" fb vr (fun r => rs fc r)]
- the continuation [(λ vr. < fc >)] is represented as
a tuple [(vr, fun r => rs fc r)]. *)
| rs : flow -> flow
rs f vr is a reset with body f and return value vr.
| defun : var -> (val -> flow) -> flow
| discard : var -> flow
defun x uf is equivalent to ens_ (x=(λ x r. uf x r)), where x can reside in the environment (which regular ens_ cannot access).
Should defun be scoped? We don't think so, because the resulting continuation is first-class and does not have a well-defined lifetime.
.
Definition seq (f1 f2:flow) := bind f1 (fun _ => f2).
Definition sh k fb := shc k fb (fun v => ens (fun r => \[r = v])).
Definition ens_ H := ens (fun r => \[r = vunit] \* H).
Definition empty := ens_ \[True].
Notation req_ H := (req H empty).
Definition ufun := val -> flow.
#[global]
Instance Inhab_ufun : Inhab ufun.
Proof.
constructor.
exists (fun (v:val) => ens_ \[]).
constructor.
Qed.
Definition senv := Fmap.fmap var ufun.
Definition empty_env : senv := Fmap.empty.
Inductive result : Type :=
| norm : val -> result
| shft : var -> flow -> (val -> flow) -> result.
See shc for what the arguments mean.
Declare Scope flow_scope.
Open Scope flow_scope.
Infix ";;" := seq (at level 38, right associativity) : flow_scope.
Notation "'let' x '=' f1 'in' f2" :=
(bind f1 (fun x => f2))
(at level 38, x binder, right associativity, only printing) : flow_scope.
Notation "'∃' x1 .. xn , H" :=
(fex (fun x1 => .. (fex (fun xn => H)) ..))
(at level 39, x1 binder, H at level 50, right associativity,
format "'[' '∃' '/ ' x1 .. xn , '/ ' H ']'") : flow_scope.
Notation "'∀' x1 .. xn , H" :=
(fall (fun x1 => .. (fall (fun xn => H)) ..))
(at level 39, x1 binder, H at level 50, right associativity,
format "'[' '∀' '/ ' x1 .. xn , '/ ' H ']'") : flow_scope.
Notation "f '$' '(' x ',' r ')'" := (unk f x r)
(at level 80, format "f '$' '(' x ',' r ')'", only printing) : flow_scope.
Notation "'sh' '(' k '.' fb '),' vr" := (sh k fb vr)
(at level 80, format "'sh' '(' k '.' fb '),' vr", only printing) : flow_scope.
Notation "'ens' r '.' Q" := (ens (fun r => Q))
(at level 80, format "'ens' r '.' Q" , only printing) : flow_scope.
Implicit Types s : senv.
Implicit Types h : heap.
Implicit Types H : hprop.
Implicit Types Q : postcond.
Implicit Types u : ufun.
Implicit Types f : flow.
Implicit Types fk : val -> flow.
Implicit Types x y z k : var.
Implicit Types a v r : val.
Implicit Types R : result.
Implicit Types e : expr.
Interpretation of a staged formula
Inductive satisfies : senv -> senv -> heap -> heap -> result -> flow -> Prop :=
| s_req : forall (s1 s2:senv) H (h1 h2:heap) R f,
(forall (hp hr:heap),
H hp ->
h1 = Fmap.union hr hp ->
Fmap.disjoint hr hp ->
satisfies s1 s2 hr h2 R f) ->
satisfies s1 s2 h1 h2 R (req H f)
| s_ens : forall s1 Q h1 h2 R,
(exists v h3,
R = norm v /\
Q v h3 /\
h2 = Fmap.union h1 h3 /\
Fmap.disjoint h1 h3) ->
satisfies s1 s1 h1 h2 R (ens Q)
| s_bind : forall s3 h3 v s1 s2 f1 (f2:val->flow) h1 h2 R,
satisfies s1 s3 h1 h3 (norm v) f1 ->
satisfies s3 s2 h3 h2 R (f2 v) ->
satisfies s1 s2 h1 h2 R (bind f1 f2)
| s_fex s1 s2 h1 h2 R (A:Type) (f:A->flow)
(H: exists b,
satisfies s1 s2 h1 h2 R (f b)) :
satisfies s1 s2 h1 h2 R (@fex A f)
| s_fall s1 s2 h1 h2 R (A:Type) (f:A->flow)
(H: forall b,
satisfies s1 s2 h1 h2 R (f b)) :
satisfies s1 s2 h1 h2 R (@fall A f)
| s_unk : forall s1 s2 h1 h2 R xf uf a,
Fmap.read s1 xf = uf ->
satisfies s1 s2 h1 h2 R (uf a) ->
satisfies s1 s2 h1 h2 R (unk xf a)
| s_intersect s1 s2 h1 h2 R f1 f2
(H1: satisfies s1 s2 h1 h2 R f1)
(H2: satisfies s1 s2 h1 h2 R f2) :
satisfies s1 s2 h1 h2 R (intersect f1 f2)
| s_disj_l s1 s2 h1 h2 R f1 f2
(H: satisfies s1 s2 h1 h2 R f1) :
satisfies s1 s2 h1 h2 R (disj f1 f2)
| s_disj_r s1 s2 h1 h2 R f1 f2
(H: satisfies s1 s2 h1 h2 R f2) :
satisfies s1 s2 h1 h2 R (disj f1 f2)
The new rules for shift/reset are as follows.
| s_shc : forall s1 h1 fb fk k,
~ Fmap.indom s1 k ->
satisfies s1 s1 h1 h1
(shft k fb fk)
(shc k fb fk)
A sh on its own reduces to a shft containing an identity continuation.
shc corresponds directly to shft.
| s_bind_sh : forall s1 s2 f1 (f2:val->flow) fk h1 h2 fb k,
satisfies s1 s2 h1 h2 (shft k fb fk) f1 ->
satisfies s1 s2 h1 h2 (shft k fb (fun r1 => bind (fk r1) f2))
(bind f1 f2)
This rule extends the continuation in a shft on the left side of a seq. Notably, it moves whatever comes next under the reset, preserving shift-freedom by constructon.
| s_rs_sh : forall k s1 s2 fr h1 h2 rf s3 h3 fb fk,
satisfies s1 s3 h1 h3 (shft k fb fk) fr ->
satisfies (Fmap.update s3 k (fun a => rs (fk a))) s2
h3 h2 rf (rs fb) ->
satisfies s1 s2 h1 h2 rf (rs fr)
This rule applies when the body of a rs evaluates to a shft (not when a sh is directly inside a rs; that happens in reduction). The continuation carried by the shft is known, so it is bound in (the environment of) the shift body before that is run.
The two resets in the semantics are accounted for: one is around the shift body, and one is already the topmost form in the continuation.
Note: because staged formulae are turned into values (via shft and being added to the senv), rewriting can no longer be done to weaken them. Environment entailment was an attempt at solving this problem; the Proper instances might have to be tweaked to allow rewriting too. Another possible solution is a syntactic entailment relation in the relevant rules to allow weakening.
| s_rs_val : forall s1 s2 h1 h2 v f,
satisfies s1 s2 h1 h2 (norm v) f ->
satisfies s1 s2 h1 h2 (norm v) (rs f)
| s_defun s1 s2 h1 x uf :
~ Fmap.indom s1 x ->
s2 = Fmap.update s1 x uf ->
satisfies s1 s2 h1 h1 (norm vunit) (defun x uf)
| s_discard s1 s2 h (f:var) :
s2 = Fmap.remove s1 f ->
satisfies s1 s2 h h (norm vunit) (discard f)
.
Notation "s1 ',' s2 ',' h1 ',' h2 ',' r '|=' f" :=
(satisfies s1 s2 h1 h2 r f) (at level 30, only printing).
Lemma s_sh : forall s1 h1 fb k,
~ Fmap.indom s1 k ->
satisfies s1 s1 h1 h1
(shft k fb (fun r1 => ens (fun r => \[r = r1])))
(sh k fb).
Proof.
unfold sh. intros.
applys* s_shc.
Qed.
Ltac zap :=
lazymatch goal with
| H: exists _, _ |- _ => destr H; zap
| H: _ /\ _ |- _ => destr H; zap
| |- _ /\ _ => splits; zap
| |- exists _, _ => eexists; zap
| _ => jauto
end.
Ltac heaps :=
lazymatch goal with
| H: exists _, _ |- _ => destr H; heaps
| H: _ /\ _ |- _ => destr H; heaps
| H: norm _ = norm _ |- _ => injects H; heaps
| H: (_ ~~> _) _ |- _ => hinv H; heaps
| H: \[_] _ |- _ => hinv H; heaps
| H: (_ \* _) _ |- _ => hinv H; heaps
| |- (_ ~~> _) _ => hintro; heaps
| |- (_ \* _) _ => hintro; heaps
| |- \[_] _ => hintro; heaps
| |- _ /\ _ => splits; heaps
| |- exists _, _ => eexists; heaps
| _ => subst; rew_fmap *
end.
Lemma s_seq : forall s3 h3 r1 s1 s2 f1 f2 h1 h2 R,
satisfies s1 s3 h1 h3 (norm r1) f1 ->
satisfies s3 s2 h3 h2 R f2 ->
satisfies s1 s2 h1 h2 R (seq f1 f2).
Proof.
unfold seq. intros.
applys* s_bind.
Qed.
Notation s_seq_sh := s_bind_sh.
Lemma s_ens_ : forall H h1 h2 s1,
(exists h3,
H h3 /\
h2 = Fmap.union h1 h3 /\
Fmap.disjoint h1 h3) ->
satisfies s1 s1 h1 h2 (norm vunit) (ens_ H).
Proof.
unfold ens_. intros.
applys* s_ens.
heaps.
Qed.
A specialization of equal_f for exposing the equalities in continuations after inversion.
Entailment
Definition entails (f1 f2:flow) : Prop :=
forall s1 s2 h1 h2 R,
satisfies s1 s2 h1 h2 R f1 -> satisfies s1 s2 h1 h2 R f2.
Infix "⊑" := entails (at level 90, right associativity) : flow_scope.
Inductive gentails_under : senv -> nat -> flow -> flow -> Prop :=
| geu_base : forall s1 f1 f2,
(forall s2 h1 h2 v,
satisfies s1 s2 h1 h2 (norm v) f1 ->
satisfies s1 s2 h1 h2 (norm v) f2) ->
gentails_under s1 O f1 f2
| geu_shift : forall s1 n f1 f2,
(forall s2 h1 h2 k fb fk,
satisfies s1 s2 h1 h2 (shft k fb fk) f1 ->
exists fb1 fk1,
satisfies s1 s2 h1 h2 (shft k fb1 fk1) f2 /\
gentails_under s1 n fb fb1 /\
forall v, gentails_under s1 n (fk v) (fk1 v)) ->
gentails_under s1 (S n) f1 f2.
Notation "env '⊢' f1 '⊆' f2" :=
(gentails_under env _ f1 f2) (at level 90, only printing) : flow_scope.
Inductive gentails : nat -> flow -> flow -> Prop :=
| ge_base : forall f1 f2,
(forall s1 s2 h1 h2 v,
satisfies s1 s2 h1 h2 (norm v) f1 ->
satisfies s1 s2 h1 h2 (norm v) f2) ->
gentails O f1 f2
| ge_shift : forall n f1 f2,
(forall s1 s2 h1 h2 k fb fk,
satisfies s1 s2 h1 h2 (shft k fb fk) f1 ->
exists fb1 fk1,
satisfies s1 s2 h1 h2 (shft k fb1 fk1) f2 /\
gentails n fb fb1 /\
forall v, gentails n (fk v) (fk1 v)) ->
gentails (S n) f1 f2.
Notation "f1 '⊆' n f2" :=
(gentails n f1 f2) (at level 90, only printing) : flow_scope.
Lemma entails_gentails: forall n f1 f2,
entails f1 f2 -> gentails n f1 f2.
Proof.
unfold entails.
intros n. induction n; intros.
{ applys* ge_base. }
{ applys ge_shift. jauto. }
Qed.
Definition entails_under s1 f1 f2 :=
forall h1 h2 s2 R,
satisfies s1 s2 h1 h2 R f1 -> satisfies s1 s2 h1 h2 R f2.
Notation "env '⊢' f1 '⊑' f2" :=
(entails_under env f1 f2) (at level 90, only printing) : flow_scope.
Lemma entails_under_gentails_under: forall n s1 f1 f2,
entails_under s1 f1 f2 -> gentails_under s1 n f1 f2.
Proof.
unfold entails_under.
intros n. induction n; intros.
{ applys* geu_base. }
{ applys geu_shift. jauto. }
Qed.
Definition bientails (f1 f2:flow) : Prop :=
forall h1 h2 R s1 s2,
satisfies s1 s2 h1 h2 R f1 <-> satisfies s1 s2 h1 h2 R f2.
Instance entails_refl : Reflexive entails.
Proof.
unfold Reflexive, entails.
intros.
exact H.
Qed.
Instance entails_trans : Transitive entails.
Proof.
unfold Transitive, entails.
intros.
auto.
Qed.
Instance entails_preorder : PreOrder entails.
Proof.
constructor.
apply entails_refl.
apply entails_trans.
Qed.
Instance gentails_refl : forall n, Reflexive (gentails n).
Proof.
unfold Reflexive.
intros n. induction n; intros.
- applys ge_base. intros.
assumption.
- intros.
applys ge_shift. intros.
exs. splits*.
Qed.
Instance gentails_trans : forall n, Transitive (gentails n).
Proof.
unfold Transitive.
intros n. induction n; intros.
- inverts H. inverts H0. applys ge_base. intros.
eauto.
- applys ge_shift. intros.
inverts H as H. specializes H H1. destr H.
inverts H0 as H0. specializes H0 H2. destr H0.
exs. splits*.
Qed.
Instance gentails_preorder : forall n, PreOrder (gentails n).
Proof.
constructor.
apply gentails_refl.
apply gentails_trans.
Qed.
Instance gentails_under_refl : forall n env, Reflexive (gentails_under env n).
Proof.
unfold Reflexive.
intros n. induction n; intros.
- applys geu_base. intros.
assumption.
- intros.
applys geu_shift. intros.
exs. splits*.
Qed.
Instance gentails_under_trans : forall n env, Transitive (gentails_under env n).
Proof.
unfold Transitive.
intros n. induction n; intros.
- inverts H. inverts H0. applys geu_base. intros.
eauto.
- applys geu_shift. intros.
inverts H as H. specializes H H1. destr H.
inverts H0 as H0. specializes H0 H2. destr H0.
exs. splits*.
Qed.
Instance gentails_under_preorder : forall n env, PreOrder (gentails_under env n).
Proof.
constructor.
apply gentails_under_refl.
apply gentails_under_trans.
Qed.
Instance entails_under_refl : forall env, Reflexive (entails_under env).
Proof.
unfold Reflexive, entails_under.
intros.
eauto.
Qed.
Instance entails_under_trans : forall env, Transitive (entails_under env).
Proof.
unfold Transitive, entails_under.
intros.
auto.
Qed.
Instance entails_under_preorder : forall env, PreOrder (entails_under env).
Proof.
constructor.
apply entails_under_refl.
apply entails_under_trans.
Qed.
Instance bientails_equiv : Equivalence bientails.
Proof.
constructor.
- unfold Reflexive.
unfold bientails.
reflexivity.
- unfold Symmetric.
unfold bientails.
symmetry.
auto.
- unfold Transitive.
unfold bientails.
intros.
split.
+ intros. apply H0. apply H. easy.
+ intros. apply H. apply H0. easy.
Qed.
Definition flow_res (f:flow) (v:val) : Prop :=
forall s1 s2 h1 h2, satisfies s1 s2 h1 h2 (norm v) f.
Definition flow_res1 (f:flow) (v1:val) : Prop :=
forall s1 s2 h1 h2 v, satisfies s1 s2 h1 h2 (norm v) f -> v1 = v.