Require Import ToString Coqlib Utf8 Maps ShareTree Sets Util.
Require Import AdomLib.
Require Import IdealExpr AbIdealEnv.
Require Import Integers ZIntervals.
Require Import Hash FastArith.
Require Import FactMsgHelpers.
Module MVar :=
T.
Module SVar <:
SET with Definition elt :=
var :=
Tree2Set(
MVar).
Module SVarO :=
SetOp(
SVar).
Module HExp_Cells <:
Hashable.
Definition t :=
iexpr.
Definition eq :
Util.EqDec t :=
_.
Definition hash :
hashable t :=
_.
Definition bits :=
F8.
End HExp_Cells.
Module MExp :=
Hashtable HExp_Cells.
Module SExp <:
SET with Definition elt :=
iexpr :=
Tree2Set(
MExp).
Module SExpO :=
SetOp(
SExp).
Module MExp_Properties :=
Tree_Properties(
MExp).
Fixpoint iexpr_free_vars_acc (
e:
iexpr) (
acc:
SVar.t) :
SVar.t :=
match e with
|
IEvar _ x =>
SVar.add x acc
|
IEconst _ |
IEZitv _ =>
acc
|
IEunop _ e =>
iexpr_free_vars_acc e acc
|
IEbinop _ e1 e2 =>
iexpr_free_vars_acc e1 (
iexpr_free_vars_acc e2 acc)
end.
Lemma iexpr_free_vars_acc_iff:
∀
e acc x,
SVar.mem x (
iexpr_free_vars_acc e acc) <->
SVar.mem x acc \/
SVar.mem x (
iexpr_free_vars_acc e SVar.empty).
Proof.
Lemma eval_iexpr_upd_free_acc:
∀
x ρ
n v e,
eval_iexpr ρ
e v ->
∀
acc,
~
SVar.mem x (
iexpr_free_vars_acc e acc) ->
eval_iexpr (
upd ρ
x n)
e v.
Proof.
induction 1;
intros;
simpl in *.
-
rewrite SVar.mem_add in H1.
constructor;
auto.
unfold upd.
destruct @
eq_dec;
auto.
destruct H1.
auto.
-
constructor.
-
constructor.
auto.
-
econstructor;
eauto.
-
econstructor;
eauto.
eapply IHeval_iexpr2.
contradict H2.
rewrite iexpr_free_vars_acc_iff.
eauto.
Qed.
Definition iexpr_free_vars (
e:
iexpr) :
SVar.t :=
iexpr_free_vars_acc e SVar.empty.
Lemma eval_iexpr_upd_free:
∀
x ρ
n v e,
~
SVar.mem x (
iexpr_free_vars e) ->
eval_iexpr ρ
e v ->
eval_iexpr (
upd ρ
x n)
e v.
Proof.
Fixpoint iexpr_is_free (
e:
iexpr) (
y:
var) :
bool :=
match e with
|
IEvar _ x =>
if eq_dec y x then true else false
|
IEconst _ |
IEZitv _ =>
false
|
IEunop _ e =>
iexpr_is_free e y
|
IEbinop _ e1 e2 =>
iexpr_is_free e1 y ||
iexpr_is_free e2 y
end.
Lemma iexpr_is_free_iexpr_free_vars:
∀
e y,
SVar.mem y (
iexpr_free_vars e) ->
iexpr_is_free e y.
Proof.
Fixpoint ite_iexpr_free_vars_acc (
e:
ite_iexpr) (
acc:
SVar.t) :
SVar.t :=
match e with
|
Leaf e =>
iexpr_free_vars_acc e acc
|
Ite c et ef =>
iexpr_free_vars_acc c
(
ite_iexpr_free_vars_acc et
(
ite_iexpr_free_vars_acc ef acc))
end.
Lemma ite_iexpr_free_vars_acc_iff:
∀
e acc x,
SVar.mem x (
ite_iexpr_free_vars_acc e acc) <->
SVar.mem x acc \/
SVar.mem x (
ite_iexpr_free_vars_acc e SVar.empty).
Proof.
Lemma eval_ite_iexpr_upd_free_acc:
∀
x ρ
n v e,
eval_ite_iexpr ρ
e v ->
∀
acc,
~
SVar.mem x (
ite_iexpr_free_vars_acc e acc) ->
eval_ite_iexpr (
upd ρ
x n)
e v.
Proof.
Definition ite_iexpr_free_vars (
e:
ite_iexpr) :
SVar.t :=
ite_iexpr_free_vars_acc e SVar.empty.
Lemma eval_ite_iexpr_upd_free:
∀
x ρ
n v e,
~
SVar.mem x (
ite_iexpr_free_vars e) ->
eval_ite_iexpr ρ
e v ->
eval_ite_iexpr (
upd ρ
x n)
e v.
Proof.
Definition max_eq_sz :
Z := 30.
Definition max_fact_sz :
Z := 10.
Opaque max_eq_sz.
Opaque max_fact_sz.
Fixpoint iexpr_subst (
e:
iexpr) (
x:
var) (
e':
iexpr) :
iexpr.
refine (
match e as ee return ee =
e ->
_ with
|
IEvar _ x' =>
fun _ =>
if eq_dec x x'
then e'
else e
|
IEconst _ |
IEZitv _ =>
fun _ =>
e
|
IEunop op e1 =>
fun _ =>
let e1' :=
iexpr_subst e1 x e'
in
ifeq e1' ==
e1 then e else IEunop op e1'
|
IEbinop op e1 e2 =>
fun _ =>
let e1' :=
iexpr_subst e1 x e'
in
let e2' :=
iexpr_subst e2 x e'
in
ifeq e1' ==
e1 then
ifeq e2' ==
e2 then e else IEbinop op e1'
e2'
else IEbinop op e1'
e2'
end eq_refl).
Proof.
- abstract congruence.
- intros; reflexivity.
Grab Existential Variables.
abstract (intros; destruct H0; subst; subst; subst op0; congruence).
Defined.
Lemma iexpr_subst_eval:
∀ ρ
v e,
eval_iexpr ρ
e v ->
∀
x e',
eval_iexpr ρ
e' (ρ
x) ->
eval_iexpr ρ (
iexpr_subst e x e')
v.
Proof.
induction 1;
simpl;
intros.
-
destruct @
eq_dec.
congruence.
constructor;
auto.
-
constructor;
auto.
-
constructor;
auto.
-
unfold physEq.
econstructor;
eauto.
-
unfold physEq.
econstructor;
eauto.
Qed.
Lemma iexpr_subst_free:
∀
e x e', ~
SVar.mem x (
iexpr_free_vars e') ->
∀
y,
SVar.mem y (
iexpr_free_vars (
iexpr_subst e x e')) ->
x ≠
y /\
(
SVar.mem y (
iexpr_free_vars e) \/
SVar.mem y (
iexpr_free_vars e')).
Proof.
Fixpoint ite_iexpr_subst (
e:
ite_iexpr) (
x:
var) (
e':
iexpr) :
ite_iexpr.
refine (
match e as ee return ee =
e ->
_ with
|
Leaf e1 =>
fun _ =>
let e1' :=
iexpr_subst e1 x e'
in
ifeq e1' ==
e1 then e else Leaf e1'
|
Ite c e1 e2 =>
fun _ =>
let c' :=
iexpr_subst c x e'
in
let e1' :=
ite_iexpr_subst e1 x e'
in
let e2' :=
ite_iexpr_subst e2 x e'
in
ifeq c' ==
c then
ifeq e1' ==
e1 then
ifeq e2' ==
e2 then e else Ite c'
e1'
e2'
else Ite c'
e1'
e2'
else Ite c'
e1'
e2'
end eq_refl).
Proof.
- abstract congruence.
- intros; reflexivity.
Grab Existential Variables.
+ intros; reflexivity.
+ abstract (intros; destruct H0, H1; subst; subst; congruence).
Defined.
Lemma ite_iexpr_subst_eval:
∀ ρ
v e,
eval_ite_iexpr ρ
e v ->
∀
x e',
eval_iexpr ρ
e' (ρ
x) ->
eval_ite_iexpr ρ (
ite_iexpr_subst e x e')
v.
Proof.
Lemma ite_iexpr_subst_free:
∀
e x e', ~
SVar.mem x (
iexpr_free_vars e') ->
∀
y,
SVar.mem y (
ite_iexpr_free_vars (
ite_iexpr_subst e x e')) ->
x ≠
y /\
(
SVar.mem y (
ite_iexpr_free_vars e) \/
SVar.mem y (
iexpr_free_vars e')).
Proof.
Record t0 :=
{
eqs :
MVar.t ite_iexpr;
eqs_free :
MVar.t SVar.t;
facts :
MExp.t bool;
facts_free :
MVar.t SExp.t
}.
Record t0_inv (
ab:
t0) :
Prop :=
{
eqs_free_correct :
∀
x e,
MVar.get x ab.(
eqs) =
Some e ->
∀
y,
SVar.mem y (
ite_iexpr_free_vars e) ->
∃
s,
MVar.get y ab.(
eqs_free) =
Some s /\
SVar.mem x s;
facts_free_correct :
∀
e b,
MExp.get e ab.(
facts) =
Some b ->
∀
y,
SVar.mem y (
iexpr_free_vars e) ->
∃
s,
MVar.get y ab.(
facts_free) =
Some s /\
SExp.mem e s }.
Definition t := {
ab:
t0 |
t0_inv ab}.
Record gamm0 (
ab:
t0) (ρ:
var ->
ideal_num) :
Prop :=
{
eqs_gamm :
∀
x e,
MVar.get x ab.(
eqs) =
Some e ->
eval_ite_iexpr ρ
e (ρ
x);
facts_gamm :
∀
e b,
MExp.get e ab.(
facts) =
Some b ->
eval_iexpr ρ
e (
INz (
if b then F1 else F0)) }.
Instance gamm0' :
gamma_op t0 (
var ->
ideal_num) :=
gamm0.
Instance gamm :
gamma_op t (
var ->
ideal_num) :=
fun ab =>
gamm0 (
proj1_sig ab).
Definition enrich_qchan (
ab:
t) (
c:
query_chan) :
query_chan :=
{|
get_var_ty :=
c.(
get_var_ty);
get_itv :=
c.(
get_itv);
get_congr :=
c.(
get_congr);
get_eq_expr x :=
MVar.get x (
proj1_sig ab).(
eqs);
linearize_expr :=
c.(
linearize_expr) |}.
Lemma enrich_qchan_correct:
∀ ρ
ab c, ρ ∈ γ
ab -> ρ ∈ γ
c -> ρ ∈ γ (
enrich_qchan ab c).
Proof.
intros ρ ab c H H0; constructor; simpl.
- intros v. apply H0.
- intros e a H1. apply H0; auto.
- intros e a H1. apply H0; auto.
- intros x e H1. apply H; auto.
- intros. eapply H0; eauto.
Qed.
Definition remove_eq (
x:
var) (
e:
ite_iexpr) (
ab:
t0) :
t0 :=
{|
eqs :=
MVar.remove x ab.(
eqs);
eqs_free :=
SVar.fold (
fun x'
free =>
match MVar.get_set x'
free with
| (
None,
_) =>
free
| (
Some s,
setter) =>
setter (
SVar.rem x s)
end)
(
ite_iexpr_free_vars e)
ab.(
eqs_free);
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free)
|}.
Lemma remove_eq_inv:
∀
x e ab,
t0_inv ab ->
MVar.get x ab.(
eqs) =
Some e ->
t0_inv (
remove_eq x e ab).
Proof.
Lemma remove_eq_get:
∀
x e ab y,
MVar.get y (
remove_eq x e ab).(
eqs) =
if eq_dec y x then None else MVar.get y ab.(
eqs).
Proof.
Lemma remove_eq_gamm0:
∀
x e ab ρ, ρ ∈ γ
ab -> ρ ∈ γ (
remove_eq x e ab).
Proof.
constructor. 2:
apply H.
simpl.
intros.
rewrite MVar.grspec in H0.
destruct (
MVar.elt_eq x0 x).
discriminate.
apply H;
auto.
Qed.
Definition unfree_eq (
x:
var) (
ab:
t0) (
x':
var) (
e':
iexpr) :
t0 :=
match MVar.get_set x ab.(
eqs)
with
| (
Some e,
setter) =>
let newe :=
ite_iexpr_subst e x'
e'
in
if Z.leb (
ite_iexpr_sz newe)
max_eq_sz then
let free :=
match MVar.get_set x'
ab.(
eqs_free)
with
| (
None,
_) =>
ab.(
eqs_free)
| (
Some s,
setter) =>
setter (
SVar.rem x s)
end
in
let free :=
SVar.fold
(
fun y free =>
let '(
o,
setter) :=
MVar.get_set y free in
setter
(
SVar.add x match o with None =>
SVar.empty |
Some s =>
s end))
(
iexpr_free_vars e')
free
in
{|
eqs :=
setter newe;
eqs_free :=
free;
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free)
|}
else remove_eq x e ab
| (
None,
_) =>
ab
end.
Lemma unfree_eq_inv:
∀
ab x x'
e',
~
SVar.mem x' (
iexpr_free_vars e') ->
t0_inv ab ->
t0_inv (
unfree_eq x ab x'
e').
Proof.
Lemma unfree_eq_gamm0:
∀
x ab x'
e' ρ,
ρ ∈ γ
ab ->
eval_iexpr ρ
e' (ρ
x') ->
ρ ∈ γ (
unfree_eq x ab x'
e').
Proof.
Lemma unfree_eq_get:
∀
ab x x'
e'
y,
match MVar.get y (
unfree_eq x ab x'
e').(
eqs)
with
|
None =>
MVar.get y ab.(
eqs) =
None \/
x =
y
|
Some e =>
if eq_dec x y then
∃
ee,
MVar.get x ab.(
eqs) =
Some ee /\
e =
ite_iexpr_subst ee x'
e'
else MVar.get y ab.(
eqs) =
Some e
end.
Proof.
Definition forget0_eqs (
x:
var) (
e:
option iexpr) (
ab:
t0) :
t0 :=
match MVar.get x ab.(
eqs_free)
with
|
None =>
ab
|
Some s =>
let ab :=
SVar.fold
(
fun x'
ab =>
match e with
|
Some e =>
unfree_eq x'
ab x e
|
_ =>
match MVar.get x'
ab.(
eqs)
with
|
Some e' =>
remove_eq x'
e'
ab
|
None =>
ab
end
end)
s ab
in
{|
eqs :=
ab.(
eqs);
eqs_free :=
MVar.remove x ab.(
eqs_free);
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free) |}
end.
Lemma forget0_eqs_inv:
∀
ab x e,
t0_inv ab ->
match e with
|
Some e => ~
SVar.mem x (
iexpr_free_vars e)
|
_ =>
True
end ->
t0_inv (
forget0_eqs x e ab).
Proof.
Lemma forget0_eqs_gamm0:
∀
x e ab ρ,
ρ ∈ γ
ab ->
match e with
|
Some e =>
eval_iexpr ρ
e (ρ
x)
|
None =>
True
end ->
ρ ∈ γ (
forget0_eqs x e ab).
Proof.
Definition remove_fact (
e:
iexpr) (
ab:
t0) :
t0 :=
{|
facts :=
MExp.remove e ab.(
facts);
facts_free :=
SVar.fold (
fun x'
free =>
match MVar.get_set x'
free with
| (
None,
_) =>
free
| (
Some s,
setter) =>
setter (
MExp.remove e s)
end)
(
iexpr_free_vars e)
ab.(
facts_free);
eqs :=
ab.(
eqs);
eqs_free :=
ab.(
eqs_free)
|}.
Lemma remove_fact_inv:
∀
ab p,
t0_inv ab ->
t0_inv (
remove_fact p ab).
Proof.
Lemma remove_fact_gamm0:
∀
ab ρ
e, ρ ∈ γ
ab -> ρ ∈ γ (
remove_fact e ab).
Proof.
unfold remove_fact.
constructor;
intros.
-
eapply H;
auto.
-
eapply H.
simpl in H0.
rewrite MExp.grspec in H0.
destruct (
eq_dec e0 e);
now intuition.
Qed.
Lemma remove_fact_get:
∀
e ab ee,
MExp.get ee (
remove_fact e ab).(
facts) =
if eq_dec ee e then None else MExp.get ee ab.(
facts).
Proof.
Definition try_add_fact_aux (
e:
iexpr) (
b:
bool) (
ab:
t0) :
t0+⊥ :=
if iexpr_det e &&
Z.leb (
iexpr_sz e)
max_fact_sz then
match MExp.get_set e ab.(
facts)
with
| (
None,
setter) =>
NotBot
{|
eqs :=
ab.(
eqs);
eqs_free :=
ab.(
eqs_free);
facts :=
setter b;
facts_free :=
SVar.fold
(
fun x'
free =>
let '(
o,
setter) :=
MVar.get_set x'
free in
setter
(
SExp.add e
(
match o with
|
None =>
SExp.empty
|
Some s =>
s
end)))
(
iexpr_free_vars e)
ab.(
facts_free)
|}
| (
Some b',
_) =>
if Bool.eqb b b'
then NotBot ab else Bot
end
else NotBot ab.
Lemma try_add_fact_aux_inv:
∀
e f ab ab',
t0_inv ab ->
try_add_fact_aux e f ab =
NotBot ab' ->
t0_inv ab'.
Proof.
Lemma try_add_fact_aux_gamm0:
∀
e (
b:
bool) ρ
ab,
ρ ∈ γ
ab ->
eval_iexpr ρ
e (
INz (
if b then F1 else F0)) ->
ρ ∈ γ (
try_add_fact_aux e b ab).
Proof.
Definition unfree_fact (
e:
iexpr) (
ab:
t0) (
x':
var) (
e':
iexpr) :
t0+⊥ :=
match MExp.get e ab.(
facts)
with
|
Some b =>
let newe :=
iexpr_subst e x'
e'
in
try_add_fact_aux newe b (
remove_fact e ab)
|
None =>
NotBot (
remove_fact e ab)
end.
Lemma unfree_fact_inv:
∀
ab e x'
e'
ab',
t0_inv ab ->
unfree_fact e ab x'
e' =
NotBot ab' ->
t0_inv ab'.
Proof.
Lemma unfree_fact_gamm0:
∀
e ab x'
e' ρ,
ρ ∈ γ
ab ->
eval_iexpr ρ
e' (ρ
x') ->
ρ ∈ γ (
unfree_fact e ab x'
e').
Proof.
Lemma unfree_fact_get:
∀
ab e x'
e'
ab'
ee,
unfree_fact e ab x'
e' =
NotBot ab' ->
match MExp.get ee ab'.(
facts)
with
|
None =>
MExp.get ee ab.(
facts) =
None \/
e =
ee
|
Some b =>
ee =
iexpr_subst e x'
e' /\
MExp.get e ab.(
facts) =
Some b \/
MExp.get ee ab.(
facts) =
Some b /\ (
ee ≠
e \/ ~
SVar.mem x' (
iexpr_free_vars e))
end.
Proof.
Definition forget0_facts (
x:
var) (
e:
option iexpr) (
ab:
t0) :
t0+⊥ :=
match MVar.get x ab.(
facts_free)
with
|
None =>
NotBot ab
|
Some s =>
do ab <-
SExp.fold (
fun f ab =>
do ab <-
ab;
match e with
|
Some e =>
unfree_fact f ab x e
|
None =>
ret (
remove_fact f ab)
end)
s (
NotBot ab);
ret {|
eqs :=
ab.(
eqs);
eqs_free :=
ab.(
eqs_free);
facts :=
ab.(
facts);
facts_free :=
MVar.remove x ab.(
facts_free) |}
end.
Lemma forget0_facts_inv:
∀
ab x e ab',
t0_inv ab ->
match e with
|
Some e => ~
SVar.mem x (
iexpr_free_vars e)
|
_ =>
True
end ->
forget0_facts x e ab =
NotBot ab' ->
t0_inv ab'.
Proof.
Lemma forget0_facts_gamm0:
∀
x e ab ρ,
ρ ∈ γ
ab ->
match e with
|
Some e =>
eval_iexpr ρ
e (ρ
x)
|
None =>
True
end ->
ρ ∈ γ (
forget0_facts x e ab).
Proof.
Definition forget0 (
x:
var) (
ab:
t0) :
t0+⊥ :=
let e :=
MVar.get x ab.(
eqs)
in
let e' :=
match e with
|
Some (
Leaf e) =>
if iexpr_is_free e x then None else Some e
|
_ =>
None
end
in
let ab :=
match e with None =>
ab |
Some e =>
remove_eq x e ab end in
forget0_facts x e' (
forget0_eqs x e'
ab).
Lemma forget0_inv:
∀
ab x ab',
t0_inv ab ->
forget0 x ab =
NotBot ab' ->
t0_inv ab'.
Proof.
Lemma forget0_gamm0:
∀
x ab ρ,
ρ ∈ γ
ab ->
ρ ∈ γ (
forget0 x ab).
Proof.
Lemma eqs_free_forget0_facts:
∀
x e ab ab',
forget0_facts x e ab =
NotBot ab' ->
ab'.(
eqs_free) =
ab.(
eqs_free).
Proof.
Lemma eqs_forget0_facts:
∀
x e ab ab',
forget0_facts x e ab =
NotBot ab' ->
ab'.(
eqs) =
ab.(
eqs).
Proof.
Lemma eqs_forget0_eqs:
∀
x e ab x'
e',
MVar.get x' (
forget0_eqs x e ab).(
eqs) =
Some e' ->
∃
e',
MVar.get x'
ab.(
eqs) =
Some e'.
Proof.
Lemma forget0_gamm0_upd:
∀
x ρ
n ab,
t0_inv ab ->
ρ ∈ γ
ab ->
(
upd ρ
x n) ∈ γ (
forget0 x ab).
Proof.
Definition forget (
x:
var) (
ab:
t *
query_chan) (
chan:
query_chan): (
t *
messages_chan)+⊥.
refine
(
match forget0 x (
proj1_sig (
fst ab))
as ab return _ =
ab ->
_ with
|
NotBot ab =>
fun EQ =>
NotBot (
exist _ ab _,
nil)
|
Bot =>
fun _ =>
Bot
end eq_refl).
Proof.
Lemma forget_correct :
∀
x ρ
n ab chan, ρ ∈ γ
ab -> (
upd ρ
x n) ∈ γ
chan ->
(
upd ρ
x n) ∈ γ (
forget x ab chan).
Proof.
Definition try_add_eq (
x:
var) (
e:
iexpr) (
ab:
t0) :
t0 :=
if Z.leb (
iexpr_sz e)
max_eq_sz then
match MVar.get_set x ab.(
eqs)
with
| (
None,
setter) =>
{|
eqs :=
setter (
Leaf e);
eqs_free :=
SVar.fold
(
fun x'
free =>
let '(
o,
setter') :=
MVar.get_set x'
free in
setter' (
SVar.add x (
match o with
|
None =>
SVar.empty
|
Some s =>
s
end)))
(
iexpr_free_vars e)
ab.(
eqs_free);
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free) |}
| (
Some _,
_) =>
ab
end
else ab.
Lemma try_add_eq_inv:
∀
ab x e,
t0_inv ab ->
t0_inv (
try_add_eq x e ab).
Proof.
Lemma try_add_eq_gamm0:
∀
x e ρ
ab,
ρ ∈ γ
ab ->
eval_iexpr ρ
e (ρ
x) ->
t0_inv ab ->
ρ ∈ γ (
try_add_eq x e ab).
Proof.
Opaque try_add_eq.
Definition assign (
x:
var) (
e:
iexpr) (
ab:
t *
query_chan) (
chan:
query_chan):
(
t *
messages_chan)+⊥.
refine
(
if
match e with
|
IEvar _ x' =>
if eq_dec x x'
then true else false
|
_ =>
false
end
then NotBot (
fst ab,
nil)
else
let e :=
if iexpr_is_free e x then
match MVar.get x (
proj1_sig (
fst ab)).(
eqs)
with
|
Some (
Leaf e') =>
if iexpr_is_free e'
x then None else Some (
iexpr_subst e x e')
|
_ =>
None
end
else
Some e
in
let e :=
do e <-
e;
if iexpr_det e then Some e else None in
match e with
|
None =>
forget x ab chan
|
Some e =>
match forget0 x (
proj1_sig (
fst ab))
as ab return ab =
_ -> (
t *
messages_chan)+⊥
with
|
Bot =>
fun _ =>
Bot
|
NotBot ab =>
fun EQ =>
let ab :=
try_add_eq x e ab in
NotBot (
exist _ ab _,
nil)
end eq_refl
end).
Proof.
Lemma assign_correct:
∀
x e ρ
n ab chan,
ρ ∈ γ
ab -> (
upd ρ
x n) ∈ γ
chan ->
n ∈
eval_iexpr ρ
e ->
(
upd ρ
x n) ∈ γ (
assign x e ab chan).
Proof.
intros.
unfold assign.
match goal with
| |- γ (
if ?
B then _ else _)
_ =>
destruct B eqn:
EQb
end.
-
assert (∀
y, ρ
y = ρ +[
x =>
n]
y).
{
intros.
unfold upd.
destruct @
eq_dec. 2:
auto.
subst.
destruct e;
try discriminate.
destruct (
eq_dec x v);
try discriminate.
inv H1.
auto. }
assert (∀
e n ρ,
eval_iexpr ρ
e n ->
∀ ρ', (∀
y:
var, ρ
y = ρ'
y) ->
eval_iexpr ρ'
e n).
{
induction 1;
econstructor;
eauto.
congruence. }
assert (∀
e n ρ,
eval_ite_iexpr ρ
e n ->
∀ ρ', (∀
y:
var, ρ
y = ρ'
y) ->
eval_ite_iexpr ρ'
e n).
{
induction 1;
intros.
-
constructor.
eauto.
-
constructor 2;
eauto.
-
constructor 3;
eauto. }
split. 2:
constructor.
constructor;
intros.
+
eapply H4,
H2.
rewrite <-
H2.
apply (
proj1 H).
auto.
+
eapply H3,
H2.
eapply (
proj1 H).
eauto.
-
match goal with
| |- γ
match ?
E with _ =>
_ end _ =>
destruct E eqn:?
end.
2:
apply forget_correct;
now auto.
pose proof forget0_gamm0_upd x ρ
n (
proj1_sig (
fst ab)) (
proj2_sig (
fst ab)) (
proj1 H).
pose proof fun ab' =>
forget0_inv (
proj1_sig (
fst ab))
x ab' (
proj2_sig (
fst ab)).
generalize (
assign_subproof x ab i).
destruct (
forget0 x (
proj1_sig (
fst ab))).
now auto.
split. 2:
now constructor.
apply try_add_eq_gamm0,
H3,
eq_refl.
apply H2.
eapply eval_iexpr_upd_free_acc.
+
unfold upd.
destruct @
eq_dec. 2:
congruence.
destruct (
iexpr_is_free e x). 2:
simpl in Heqo;
destruct iexpr_det;
congruence.
destruct (
MVar.get x (
proj1_sig (
fst ab)).(
eqs))
as [[]|]
eqn:
EQget;
try (
simpl in Heqo;
congruence).
destruct (
iexpr_is_free i0 x);
inv Heqo.
destruct (
iexpr_det (
iexpr_subst e x i0));
inv H5.
apply iexpr_subst_eval.
auto.
eapply H in EQget.
inv EQget.
now auto.
+
intro.
pose proof H4.
apply iexpr_is_free_iexpr_free_vars in H4.
destruct (
iexpr_is_free e x)
eqn:
FREEe. 2:
simpl in Heqo;
destruct iexpr_det;
congruence.
destruct (
MVar.get x (
proj1_sig (
fst ab)).(
eqs))
as [[]|];
try (
simpl in Heqo;
congruence).
destruct (
iexpr_is_free i0 x)
eqn:
FREEi;
inv Heqo.
destruct (
iexpr_det (
iexpr_subst e x i0));
inv H7.
apply iexpr_subst_free in H5.
now intuition.
intro.
apply iexpr_is_free_iexpr_free_vars in H6.
congruence.
Qed.
Definition try_add_fact (
e:
iexpr) (
b:
bool) (
ab:
t) :
t+⊥.
refine
(
let H :=
_ in
match e with
|
IEconst _ =>
NotBot ab
|
_ =>
match try_add_fact_aux e b (
proj1_sig ab)
as ab'
return _ =
ab' ->
_ with
|
NotBot ab =>
fun EQ =>
NotBot (
exist _ ab (
H ab EQ))
|
Bot =>
fun _ =>
Bot
end eq_refl
end).
Proof.
Lemma try_add_fact_gamm:
∀
e (
b:
bool) ρ
ab,
ρ ∈ γ
ab ->
eval_iexpr ρ
e (
INz (
if b then F1 else F0)) ->
ρ ∈ γ (
try_add_fact e b ab).
Proof.
Definition assume0 (
e:
iexpr) (
b:
bool) (
ab:
t0) :
t0 :=
match e with
|
IEbinop (
IOcmp Ceq) (
IEvar _ x)
e'
|
IEbinop (
IOcmp Ceq)
e' (
IEvar _ x) =>
if b then try_add_eq x e'
ab
else ab
|
IEbinop (
IOcmp Cne) (
IEvar _ x)
e'
|
IEbinop (
IOcmp Cne)
e' (
IEvar _ x) =>
if b then ab
else try_add_eq x e'
ab
|
_ =>
ab
end.
Lemma assume0_inv:
∀
e b ab,
t0_inv ab ->
t0_inv (
assume0 e b ab).
Proof.
destruct e;
simpl;
intros;
auto.
assert (∀
x e,
t0_inv (
if b then try_add_eq x e ab else ab)).
{
destruct b;
auto.
intros.
apply try_add_eq_inv.
auto. }
assert (∀
x e,
t0_inv (
if b then ab else try_add_eq x e ab)).
{
destruct b;
auto.
intros.
apply try_add_eq_inv.
auto. }
assert (
t0_inv (
if b then ab else ab)). {
destruct b;
auto. }
destruct i;
auto;
destruct c;
auto;
destruct e1,
e2;
auto;
try (
destruct i as [|[] []];
auto);
try (
destruct i0 as [|[] []];
auto).
Qed.
Lemma assume0_gamm0:
∀
c ρ
ab (
b:
bool)
v,
t0_inv ab -> ρ ∈ γ
ab ->
v <> 0 ->
(
INz (
if b return Zfast then v else F0)) ∈
eval_iexpr ρ
c ->
ρ ∈ γ (
assume0 c b ab).
Proof.
destruct c;
simpl;
eauto;
intros.
inv H2.
inv H9;
auto;
auto.
assert (∀
x e ρ
ab,
gamm0 ab ρ →
eval_iexpr ρ
e (ρ
x) →
t0_inv ab →
gamm0 (
try_add_eq x e ab) ρ).
{
intros.
eapply try_add_eq_gamm0 in H3;
eauto. }
assert (0 ∈ γ (
ZITV 0 0))
by (
compute;
split;
discriminate).
destruct c;
simpl in H7;
destruct b, (
Z.compare_spec i1 i2);
fastunwrap;
try congruence;
simpl in H7;
inv H7;
inv H6;
inv H8;
auto;
(
try (
destruct itv as [|[] []]));
(
try (
destruct itv0 as [|[] []]));
auto;
try eapply H2;
try match goal with H : ρ ?
id =
_ |-
context [ρ ?
id] =>
rewrite H end;
try match goal with H : ?
x ∈ γ (
ZITV 0 0) |-
_ =>
change (0 <=
x <= 0)
in H;
assert (
x = 0)
by omega;
subst;
clear H end;
(
simpl;
eauto;
try (
econstructor;
eauto);
omega).
Qed.
Definition assume (
e:
iexpr) (
b:
bool) (
ab:
t *
query_chan):
t+⊥.
refine (
let '(
e,
b') :=
simplify_bool_expr e (
snd ab)
return t+⊥
in
do ab <-
try_add_fact e (
xorb b b') (
fst ab);
NotBot (
exist _ (
assume0 e (
xorb b b') (
proj1_sig ab))
_)).
Proof.
Lemma assume_correct :
∀
e ρ
ab (
b:
bool), ρ ∈ γ
ab ->
(
INz (
if b then F1 else F0)) ∈
eval_iexpr ρ
e ->
ρ ∈ γ (
assume e b ab).
Proof.
Lemma ite_iexpr_eqdec : ∀ (
e1 e2:
ite_iexpr), {
e1 =
e2} + {
e1 <>
e2}.
Proof.
Definition leb (
ab1:
t *
query_chan) (
ab2:
t) :
bool.
refine (
let ab1 :=
proj1_sig (
fst ab1)
in
let ab2 :=
proj1_sig ab2 in
MVar.shforall2 (
fun _ e1'
e2' =>
match e1',
e2'
with
|
_,
None =>
true
|
None,
_ =>
false
|
Some e1,
Some e2 =>
if ite_iexpr_eqdec e1 e2 then true else false
end)
_ ab1.(
eqs)
ab2.(
eqs) &&
MExp.shforall2 (
fun _ f1 f2 =>
match f1,
f2 with
|
_,
None =>
true
|
None,
_ =>
false
|
Some b1,
Some b2 =>
Bool.eqb b1 b2
end)
_ ab1.(
facts)
ab2.(
facts)).
Proof.
-
abstract (
destruct v;
auto;
destruct ite_iexpr_eqdec;
congruence).
-
abstract (
destruct v as [[]|];
auto).
Defined.
Lemma leb_correct:
∀
ab1 ab2 ρ,
leb ab1 ab2 =
true -> ρ ∈ γ
ab1 -> ρ ∈ γ
ab2.
Proof.
Definition top (
chan:
query_chan) : (
t *
messages_chan)+⊥.
refine (
NotBot (
exist _
{|
eqs :=
MVar.empty _;
eqs_free :=
MVar.empty _;
facts :=
MExp.empty _;
facts_free :=
MVar.empty _
|}
_,
nil)).
Proof.
constructor.
-
abstract (
intros;
rewrite MVar.gempty in H;
discriminate).
-
abstract (
intros;
rewrite MExp.gempty in H;
discriminate).
Defined.
Lemma top_correct:
∀
chan ρ, ρ ∈ γ
chan -> ρ ∈ γ (
top chan).
Proof.
intros.
split. 2:
constructor.
constructor;
simpl;
intros.
-
rewrite MVar.gempty in H0.
discriminate.
-
rewrite MExp.gempty in H0.
discriminate.
Qed.
Definition join0_cond (
widen:
bool) (
ab1:
t0) (
ab2:
t0) :
option (
iexpr *
bool).
refine (
if widen then None
else
let candidates :=
MExp.shcombine_diff (
fun e ob1 ob2 =>
match ob1,
ob2 with
|
None,
_ |
_,
None =>
None
|
Some b1,
Some b2 =>
if xorb b1 b2 then ob1 else None
end)
_ ab1.(
facts)
ab2.(
facts)
in
MExp.fold (
fun acc e b =>
match acc with
|
Some eb =>
Some eb
|
None =>
Some (
e,
b)
end)
candidates None).
Proof.
abstract (destruct v as [[]|]; auto). Defined.
Lemma join0_cond_correct :
∀
w ab1 ab2 ρ
e b,
join0_cond w ab1 ab2 =
Some (
e,
b) ->
(ρ ∈ γ
ab1 ->
eval_iexpr ρ
e (
INz (
if b then F1 else F0))) /\
(ρ ∈ γ
ab2 ->
eval_iexpr ρ
e (
INz (
if negb b then F1 else F0))).
Proof.
Definition join0_eqs (
w:
bool) (
ab1:
t0) (
ab2:
t0) (
ab:
t0) :
t0.
refine(
match join0_cond w ab1 ab2 with
|
Some (
cond,
swap) =>
let diffs :=
MVar.shcombine_diff (
fun _ e1 e2 =>
match e1,
e2 with
|
Some e1,
None =>
Some (
e1,
false)
|
Some e1,
Some e2 =>
if ite_iexpr_eqdec e1 e2 then None
else
if Z.leb (
ite_iexpr_sz (
Ite cond e1 e2))
max_eq_sz then Some (
e2,
true)
else None
|
_,
_ =>
None
end)
_ ab1.(
eqs)
ab2.(
eqs)
in
let cond_free :=
iexpr_free_vars cond in
let free :=
MVar.fold (
fun free x eb =>
match eb with
| (
e,
false) =>
SVar.fold (
fun x'
free =>
match MVar.get_set x'
free with
| (
None,
_) =>
free
| (
Some s,
setter) =>
setter (
SVar.rem x s)
end)
(
ite_iexpr_free_vars e)
free
| (
e,
true) =>
SVar.fold (
fun x'
free =>
let '(
o,
setter) :=
MVar.get_set x'
free in
setter
(
SVar.add x
(
match o with
|
None =>
SVar.empty
|
Some s =>
s
end)))
(
ite_iexpr_free_vars_acc e cond_free)
free
end)
diffs ab1.(
eqs_free)
in
{|
eqs :=
MVar.shcombine (
fun _ e1 e2 =>
match e1,
e2 with
|
None,
_ |
_,
None =>
None
|
Some e1,
Some e2 =>
if ite_iexpr_eqdec e1 e2 then Some e1
else
let e' :=
if swap then Ite cond e1 e2
else Ite cond e2 e1
in
if Z.leb (
ite_iexpr_sz e')
max_eq_sz then Some e'
else None
end)
_ ab1.(
eqs)
ab2.(
eqs);
eqs_free :=
free;
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free)
|}
|
None =>
let diffs :=
MVar.shcombine_diff (
fun _ e1 e2 =>
match e1,
e2 with
|
Some e1,
None =>
Some e1
|
Some e1,
Some e2 =>
if ite_iexpr_eqdec e1 e2 then None
else Some e1
|
_,
_ =>
None
end)
_ ab1.(
eqs)
ab2.(
eqs)
in
let free :=
MVar.fold (
fun free x e1 =>
SVar.fold (
fun x'
free =>
match MVar.get_set x'
free with
| (
None,
_) =>
free
| (
Some s,
setter) =>
setter (
SVar.rem x s)
end)
(
ite_iexpr_free_vars e1)
free)
diffs ab1.(
eqs_free)
in
{|
eqs :=
MVar.shcombine (
fun _ e1'
e2' =>
match e1',
e2'
with
|
None,
_ |
_,
None =>
None
|
Some e1,
Some e2 =>
if ite_iexpr_eqdec e1 e2 then e1'
else None
end)
_ ab1.(
eqs)
ab2.(
eqs);
eqs_free :=
free;
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free)
|}
end);
abstract (
destruct v;
auto;
destruct ite_iexpr_eqdec;
congruence).
Proof.
Defined.
Lemma join0_eqs_correct :
∀
w ab1 ab2 ab,
t0_inv ab1 ->
t0_inv ab2 ->
t0_inv ab ->
t0_inv (
join0_eqs w ab1 ab2 ab) /\
∀ ρ, ρ ∈ (γ
ab1 ∪ γ
ab2) ->
ρ ∈ γ
ab ->
ρ ∈ γ (
join0_eqs w ab1 ab2 ab).
Proof.
intros.
pose proof (
join0_cond_correct w ab1 ab2).
unfold join0_eqs.
destruct join0_cond as [[
cond swap]|].
-
split.
+
split;
try apply H1.
simpl.
intros.
rewrite MVar.gshcombine in H3.
destruct (
MVar.get x (
eqs ab1))
eqn:
EQ1. 2:
discriminate.
destruct (
MVar.get x (
eqs ab2))
eqn:
EQ2. 2:
discriminate.
rewrite MVar.fold_spec, <-
fold_left_rev_right.
match goal with
| |-
context [
MVar.elements ?
t] =>
pose proof MVar.elements_correct (
m:=
t) (
i:=
x);
pose proof (
MVar.elements_complete t x)
end.
rewrite MVar.gshcombine_diff,
EQ1,
EQ2 in H5,
H6.
setoid_rewrite in_rev in H5.
setoid_rewrite in_rev in H6.
apply or_introl with (
B :=
SVar.mem y (
ite_iexpr_free_vars i))
in H5.
revert H5 H6.
replace (
ite_iexpr_sz (
if swap then Ite cond i i0 else Ite cond i0 i))
with (
iexpr_sz cond +
ite_iexpr_sz i +
ite_iexpr_sz i0 + 1)
in H3 by (
destruct swap;
simpl;
ring).
induction rev.
{
simpl.
intros.
eapply H.
eauto.
destruct ite_iexpr_eqdec.
congruence.
destruct H5.
edestruct H5. 2:
auto.
destruct Z.leb;
inv H3.
eauto. }
{
destruct a as (
x' &
e2 & []);
simpl;
intros.
-
rewrite SVar.fold_spec.
pose proof proj1 (
SVar.elements_spec
(
ite_iexpr_free_vars_acc e2 (
iexpr_free_vars cond))
y).
match type of IHl with
| ?
P ->
_ =>
eapply or_introl with (
B:=
P)
in H7
end.
revert H7.
induction SVar.elements;
intros.
+
apply IHl;
auto.
destruct H5,
H7;
auto.
destruct ite_iexpr_eqdec.
right.
congruence.
destruct Z.leb;
inv H3.
edestruct H5.
eauto. 2:
left;
intros;
inv H8;
now auto.
inv H3.
right.
rewrite ite_iexpr_free_vars_acc_iff in H7.
simpl in H7.
destruct swap;
inv H4;
unfold ite_iexpr_free_vars in H8;
simpl in H8.
apply iexpr_free_vars_acc_iff in H8.
rewrite (
ite_iexpr_free_vars_acc_iff i)
in H8.
now intuition.
apply iexpr_free_vars_acc_iff in H8.
rewrite (
ite_iexpr_free_vars_acc_iff i0)
in H8.
now intuition.
+
fold SVar.t in *.
simpl.
match goal with
| |-
context [
MVar.get_set a ?
m] =>
destruct (
MVar.get_set_spec a m), (
MVar.get_set a m)
end.
rewrite H9.
rewrite MVar.gsspec.
destruct (
MVar.elt_eq y a).
2:
destruct IHl0 as (
s & -> &
Hsx); [
simpl in H7;
now intuition|
eauto].
subst.
eexists.
split.
eauto.
rewrite SVar.mem_add.
simpl in H8.
subst o.
destruct H5. 2:
destruct IHl0 as (
s & -> &
Hsx);
now auto.
destruct ite_iexpr_eqdec.
destruct IHl0 as (
s & -> &
Hsx);
auto.
right.
left.
discriminate.
destruct Z.leb;
inv H3.
edestruct H5.
eauto.
inv H3.
now auto.
destruct IHl0 as (
s & -> &
Hsx);
auto;
right;
left.
intros.
congruence.
-
rewrite SVar.fold_spec.
induction SVar.elements.
+
apply IHl. 2:
now auto.
destruct H5;
auto.
left.
destruct ite_iexpr_eqdec.
discriminate.
intros.
edestruct H5.
eauto.
destruct Z.leb;
congruence.
auto.
+
simpl.
destruct IHl0 as (
s &
Hs &
Hsx).
match goal with
| |-
context [
MVar.get_set a ?
m] =>
destruct (
MVar.get_set_spec a m), (
MVar.get_set a m)
as [[] ?]
end. 2:
now eauto.
rewrite H8,
MVar.gsspec.
destruct MVar.elt_eq. 2:
now eauto.
subst.
eexists.
split.
eauto.
apply SVar.mem_rem.
fold SVar.t in *.
simpl in H7.
assert (
s =
t1)
by congruence.
subst.
split.
auto.
intro.
subst.
specialize (
H6 _ (
or_introl eq_refl)).
destruct ite_iexpr_eqdec,
Z.leb;
congruence. }
+
constructor;
simpl. 2:
apply H4.
intros.
rewrite MVar.gshcombine in H5.
destruct (
MVar.get x ab1.(
eqs))
eqn:
EQ1. 2:
discriminate.
destruct (
MVar.get x ab2.(
eqs))
eqn:
EQ2. 2:
discriminate.
destruct ite_iexpr_eqdec.
inv H5.
subst.
destruct H3;
apply H3;
auto.
specialize (
H2 ρ
_ _ eq_refl).
destruct H2.
destruct swap,
H3,
Z.leb;
inv H5.
constructor 3.
eauto.
apply H3;
auto.
constructor 2.
eauto.
apply H3;
auto.
constructor 2.
eauto.
apply H3;
auto.
constructor 3.
eauto.
apply H3;
auto.
-
split.
+
split;
try apply H1.
simpl.
intros.
rewrite MVar.gshcombine in H3.
destruct (
MVar.get x (
eqs ab1))
eqn:
EQ1. 2:
discriminate.
destruct (
MVar.get x (
eqs ab2))
eqn:
EQ2. 2:
discriminate.
rewrite MVar.fold_spec, <-
fold_left_rev_right.
match goal with
| |-
context [
MVar.elements ?
t] =>
pose proof (
MVar.elements_complete t x)
end.
rewrite MVar.gshcombine_diff,
EQ1,
EQ2 in H5.
setoid_rewrite in_rev in H5.
revert H5.
induction rev.
{
simpl.
intros.
eapply H.
eauto.
destruct ite_iexpr_eqdec;
congruence. }
{
destruct a as [
x'
e1];
simpl;
intros.
rewrite SVar.fold_spec.
induction SVar.elements.
auto.
simpl.
destruct IHl0 as (
s &
Hs &
Hsx).
match goal with
| |-
context [
MVar.get_set a ?
m] =>
destruct (
MVar.get_set_spec a m), (
MVar.get_set a m)
as [[] ?]
end. 2:
now eauto.
rewrite H7,
MVar.gsspec.
destruct MVar.elt_eq. 2:
now eauto.
subst.
eexists.
split.
eauto.
apply SVar.mem_rem.
fold SVar.t in *.
simpl in H6.
assert (
s =
t1)
by congruence.
subst.
split.
auto.
intro.
subst.
specialize (
H5 _ (
or_introl eq_refl)).
destruct ite_iexpr_eqdec;
congruence. }
+
constructor;
simpl. 2:
apply H4.
intros.
rewrite MVar.gshcombine in H5.
destruct (
MVar.get x ab1.(
eqs))
eqn:
EQ1. 2:
discriminate.
destruct (
MVar.get x ab2.(
eqs))
eqn:
EQ2. 2:
discriminate.
destruct ite_iexpr_eqdec;
inv H5.
subst.
destruct H3;
apply H3;
auto.
Qed.
Definition join0_facts (
ab1:
t0) (
ab2:
t0) (
ab:
t0) :
t0.
refine (
let diffs :=
MExp.shcombine_diff (
fun _ ob1 ob2 =>
match ob1,
ob2 with
|
Some _,
None =>
Some tt
|
Some b1,
Some b2 =>
if xorb b1 b2 then Some tt else None
|
_,
_ =>
None
end)
_ ab1.(
facts)
ab2.(
facts)
in
let free :=
SExp.fold (
fun e free =>
SVar.fold (
fun x'
free =>
match MVar.get_set x'
free with
| (
None,
_) =>
free
| (
Some s,
setter) =>
setter (
SExp.rem e s)
end)
(
iexpr_free_vars e)
free)
diffs ab1.(
facts_free)
in
{|
facts :=
MExp.shcombine (
fun _ ob1 ob2 =>
match ob1,
ob2 with
|
None,
_ |
_,
None =>
None
|
Some b1,
Some b2 =>
if xorb b1 b2 then None else ob1
end)
_ ab1.(
facts)
ab2.(
facts);
facts_free :=
free;
eqs :=
ab.(
eqs);
eqs_free :=
ab.(
eqs_free)
|});
abstract (
destruct v as [[]|];
auto;
simpl;
congruence).
Proof.
Defined.
Lemma join0_facts_correct :
∀
ab1 ab2 ab,
t0_inv ab1 ->
t0_inv ab2 ->
t0_inv ab ->
t0_inv (
join0_facts ab1 ab2 ab) /\
∀ ρ, ρ ∈ (γ
ab1 ∪ γ
ab2) ->
ρ ∈ γ
ab ->
ρ ∈ γ (
join0_facts ab1 ab2 ab).
Proof.
Definition join0_aux (
w:
bool) (
ab1:
t0) (
ab2:
t0) :
t0 :=
let ab :=
{|
eqs :=
MVar.empty _;
eqs_free :=
MVar.empty _;
facts :=
MExp.empty _;
facts_free :=
MVar.empty _ |}
in
let ab :=
join0_eqs w ab1 ab2 ab in
let ab :=
join0_facts ab1 ab2 ab in
{|
eqs :=
ab.(
eqs);
eqs_free :=
ab.(
eqs_free);
facts :=
ab.(
facts);
facts_free :=
ab.(
facts_free) |}.
Lemma join0_aux_correct :
∀
ab1 ab2 w,
t0_inv ab1 ->
t0_inv ab2 ->
t0_inv (
join0_aux w ab1 ab2) /\
∀ ρ, ρ ∈ (γ
ab1 ∪ γ
ab2) ->
ρ ∈ γ (
join0_aux w ab1 ab2).
Proof.
Program Instance join0 :
join_op t t :=
join0_aux false.
Next Obligation.
Program Definition widen0 :
t ->
t ->
t :=
join0_aux true.
Next Obligation.
Definition join (
ab1:
t *
query_chan) (
ab2:
t *
query_chan) (
chan:
query_chan) :
(
t *
messages_chan)+⊥ :=
NotBot ((
fst ab1) ⊔ (
fst ab2),
nil).
Lemma join_correct :
∀
ab1 ab2 chan ρ,
ρ ∈ γ
ab1 \/ ρ ∈ γ
ab2 -> ρ ∈ γ
chan ->
ρ ∈ γ (
join ab1 ab2 chan).
Proof.
Definition widen (
ab1:
t+⊥) (
ab2:(
t *
query_chan)+⊥) (
chan:
query_chan+⊥) :
t+⊥ * (
t *
messages_chan)+⊥ :=
let w :=
match ab1 with
|
Bot =>
do (
ab2,
_) <-
ab2;
ret ab2
|
NotBot ab1 =>
match ab2 with
|
Bot =>
NotBot ab1
|
NotBot (
ab2,
_) =>
NotBot (
widen0 ab1 ab2)
end
end
in
(
w,
do w <-
w;
ret (
w,
nil)).
Lemma widen_incr :
∀
ab1 ab2 chan ρ,
ρ ∈ γ
ab1 -> ρ ∈ γ
chan ->
ρ ∈ γ (
widen ab1 ab2 chan).
Proof.
intros.
unfold widen.
destruct ab1.
contradiction.
destruct ab2 as [|[]].
split.
auto.
split.
auto.
constructor.
assert (ρ ∈ γ (
widen0 x t1)).
{
eapply join0_aux_correct.
apply proj2_sig.
apply proj2_sig.
auto. }
split.
auto.
split.
auto.
constructor.
Qed.
Program Instance abVarExpEq_env :
ab_ideal_env t (
t+⊥) :=
{|
id_leb :=
leb;
id_top :=
top;
id_join :=
join;
id_init_iter :=
id;
id_widen :=
widen;
assign :=
assign;
forget :=
forget;
enrich_query_chan :=
enrich_qchan;
process_msg m ab :=
match m return _ with
|
Fact_msg e b =>
do res <-
assume_unfold assume e b ab;
ret (
res,
m::
nil)
|
_ =>
ret (
fst ab,
m::
nil)
end |}.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
Next Obligation.
Instance abVarExpEq_env_tostring
{
_:
ToString var} {
_:
ToString (
MVar.t ite_iexpr)} :
ToString t :=
fun x =>
(
MExp.fold (
fun acc e b =>
acc ++ "[" ++
to_string e ++ "↦" ++
(
if b:
bool then "
true"
else "
false") ++ "]")
(
proj1_sig x).(
facts)
"{" ++ "}"
++
to_string (
proj1_sig x).(
eqs))%
string.