Module Qcert.NNRSimp.Optim.TNNRSimpUnflatten
Require Import String.
Require Import List.
Require Import ListSet.
Require Import Arith.
Require Import Bool.
Require Import Morphisms.
Require Import Setoid.
Require Import Decidable.
Require Import EquivDec.
Require Import Equivalence.
Require Import Program.
Require Import Utils.
Require Import DataSystem.
Require Import NNRSimpSystem.
Require Import NNRSimpUnflatten.
Section TNNRSimpUnflatten.
Local Open Scope nnrs_imp.
Context {
m:
basic_model}.
Local Hint Immediate type_NNRSimpSkip :
qcert.
Section eval.
Lemma nnrs_imp_expr_unflatten_write_eval e e'
v σ
c σ :
nnrs_imp_expr_unflatten_write e v =
Some e' ->
forall Γ
c,
bindings_type σ
c Γ
c ->
forall Γ,
pd_bindings_type σ Γ ->
forall τ,
[ Γ
c ; Γ ⊢
e ▷
Coll (
Coll τ) ] ->
forall d d',
lookup equiv_dec σ
v =
Some d ->
lift2P flattens_to d d' ->
lift2P
flattens_to
(
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e)
(
nnrs_imp_expr_eval brand_relation_brands σ
c (
update_first equiv_dec σ
v d')
e').
Proof.
intros eqq Γ
c Γ
c_bt Γ Γ
_bt τ
typ d d'
inn ft.
revert e'
eqq typ.
nnrs_imp_expr_cases (
induction e)
Case
;
simpl ;
intros e'
eqq typ
;
try discriminate.
-
Case "
NNRSimpVar"%
string.
match_destr_in eqq.
invcs eqq;
simpl.
rewrite e.
unfold var in *.
rewrite inn.
rewrite lookup_update_eq_in;
eauto.
apply lookup_in_domain in inn;
trivial.
-
Case "
NNRSimpConst"%
string.
destruct d0;
try discriminate.
destruct l;
try discriminate.
+
invcs eqq;
simpl;
reflexivity.
+
destruct d0;
try discriminate.
destruct l;
try discriminate.
invcs eqq;
simpl.
unfold oflatten;
simpl.
rewrite app_nil_r;
trivial.
-
Case "
NNRSimpBinop"%
string.
destruct b;
try discriminate.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
simpl.
invcs typ.
invcs H3.
apply Coll_right_inv in H;
subst.
specialize (
IHe1 _ eqq1 H5).
specialize (
IHe2 _ eqq2 H6).
unfold lift2P in *;
simpl.
repeat match_option_in IHe1
;
simpl in *
;
try contradiction.
repeat match_option_in IHe2
;
simpl in *
;
try contradiction.
destruct d0;
simpl in *;
try contradiction
;
destruct d1;
simpl in *;
try contradiction
;
trivial.
destruct d2;
simpl in *;
try contradiction
;
destruct d3;
simpl in *;
try contradiction
;
trivial.
unfold bunion.
erewrite oflatten_app;
eauto.
-
Case "
NNRSimpUnop"%
string.
destruct u;
simpl;
try discriminate.
match_destr_in eqq.
invcs eqq.
invcs typ.
invcs H2.
apply Coll_right_inv in H.
rtype_equalizer;
subst.
replace (
nnrs_imp_expr_eval brand_relation_brands σ
c (
update_first equiv_dec σ
v d')
e')
with (
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e').
+
case_eq (
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e');
simpl;
trivial.
intros ?
eqq.
eapply nnrs_imp_expr_eval_preserves_types in eqq;
eauto.
dtype_inverter.
rewrite oflatten_cons with (
r':=
nil);
simpl;
trivial.
rewrite app_nil_r;
trivial.
+
eapply nnrs_imp_expr_eval_same.
red;
intros.
destruct (
x ==
v).
*
rewrite e in *;
tauto.
*
rewrite lookup_update_neq;
eauto.
Qed.
Ltac disect_tac H stac
:=
unfold var in *
;
cut_to H;
unfold domain in *; [ |
solve[
stac]..]
;
unfold lift2P in H
; (
repeat match_option_in H;
try contradiction).
Ltac pcong
:=
solve[
repeat (
match goal with
| [
H:
_ =
_ |-
_ ] =>
rewrite H in *;
clear H
end;
try tauto)].
Ltac fuse_t stac
:=
repeat progress (
repeat rewrite in_app_iff in *
;
repeat
match goal with
| [
H : ~ (
_ \/
_ ) |-
_ ] =>
apply not_or in H
| [
H : (
_ \/
_ ) ->
False |-
_ ] =>
apply not_or in H
| [
H:
_ /\
_ |-
_ ] =>
destruct H
| [
H :
_ *
_ |-
_ ] =>
destruct H
| [
H:
_::
_ =
_::
_ |-
_ ] =>
invcs H
| [
H:
domain (
_ ++
_) =
domain _ |-
_ ] =>
rewrite domain_app in H
;
unfold domain in H
;
symmetry in H;
apply map_app_break in H
;
destruct H as [? [?[?[??]]]];
subst;
simpl in *
| [
H:
map (
_ ++
_) =
map _ |-
_ ] =>
rewrite map_app in H
;
symmetry in H;
apply map_app_break in H
;
destruct H as [? [?[?[??]]]];
subst;
simpl in *
| [
H:
_ ::
_ =
map _ ?
x |-
_ ] =>
destruct x;
try discriminate;
simpl in H;
invcs H
| [
H:
_ ::
_ =
domain ?
x |-
_ ] =>
destruct x;
try discriminate;
simpl in H;
invcs H
| [
H : ~
In _ (
remove _ _ _) |-
_ ] =>
apply not_in_remove_impl_not_in in H; [|
congruence]
| [
H : ?
x ++
_ = ?
y ++
_ |-
_ ] =>
let HH :=
fresh in
assert (
HH:
domain y =
domain x)
by
(
unfold domain in *;
try (
intuition congruence)
;
pcong)
;
apply app_inv_head_domain in H;[
clear HH|
apply HH]
| [
H:
forall a b c,
_ -> ?
x1 :: ?
dd :: ?
x2 =
_ ++
_ ::
_ ->
_ |-
_] =>
specialize (
H (
x1::
nil) (
snd dd)
x2);
simpl in H
;
match dd with
| (
_,
_) =>
idtac
|
_ =>
destruct dd
end
;
simpl in *
;
cut_to H; [ |
eauto 3 |
reflexivity]
end
;
simpl in *;
trivial;
intros;
try subst;
try contradiction;
try solve [
congruence |
f_equal;
congruence]).
Ltac fuse_tt :=
fuse_t ltac:(
try tauto;
try congruence).
Lemma nnrs_imp_stmt_unflatten_eval s s'
v σ
c σ
d :
nnrs_imp_stmt_unflatten s v =
Some s' ->
forall Γ
c,
bindings_type σ
c Γ
c ->
forall Γ,
pd_bindings_type σ Γ ->
forall τ,
lookup equiv_dec σ
v =
Some d ->
lookup equiv_dec Γ
v =
Some (
Coll (
Coll τ)) ->
[ Γ
c ; Γ ⊢
s ] ->
forall d',
lift2P flattens_to d d' ->
lift2P
(
fun σ₁' σ₂' =>
match lookup equiv_dec σ₁'
v with
|
Some dd =>
exists dd',
σ₂' =
update_first equiv_dec σ₁'
v dd'
/\
lift2P flattens_to dd dd'
|
None =>
False
end
)
(
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ)
(
nnrs_imp_stmt_eval brand_relation_brands σ
c s' (
update_first equiv_dec σ
v d')).
Proof.
intros eqq Γ
c σ
c_bt.
revert s' σ
d eqq.
nnrs_imp_stmt_cases (
induction s)
Case
;
simpl ;
intros s' σ
d eqq Γ σ
_bt τ σ
inn Γ
inn typ d'
ft.
-
Case "
NNRSimpSkip"%
string.
invcs eqq;
simpl;
intros.
unfold var in *.
rewrite σ
inn.
eauto.
-
Case "
NNRSimpSeq"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1 [
eqq2 ?]] ];
subst;
simpl.
invcs typ.
specialize (
IHs1 _ _ _ eqq1 _ σ
_bt _ σ
inn Γ
inn H2 _ ft).
unfold lift2P in *.
do 3 (
match_option_in IHs1;
simpl in *
;
try contradiction).
destruct IHs1 as [
dd' [?
ft']].
subst.
generalize (
nnrs_imp_stmt_eval_preserves_types _ σ
c_bt σ
_bt H2 _ eqq)
;
intros p_bt.
eapply IHs2;
eauto.
-
Case "
NNRSimpAssign"%
string.
destruct (
equiv_dec v0 v);
unfold equiv,
complement in *.
+
subst;
simpl in *.
apply some_lift in eqq.
destruct eqq as [?
eqq ?];
subst.
invcs typ.
unfold equiv_dec,
string_eqdec in *.
rewrite Γ
inn in H3.
invcs H3.
generalize (
nnrs_imp_expr_unflatten_write_eval _ _ _ _ _
eqq _ σ
c_bt _ σ
_bt _ H2 _ _ σ
inn ft)
;
intros ft'.
simpl.
unfold lift2P in ft'.
unfold equiv_dec,
string_eqdec in *.
repeat match_option_in ft'
;
simpl in *
;
try contradiction.
rewrite σ
inn.
simpl.
repeat rewrite lookup_update_eq_in.
*
exists (
Some d1).
repeat rewrite update_first_update_first_eq;
simpl.
tauto.
*
apply lookup_in_domain in σ
inn;
trivial.
*
apply lookup_in_domain in σ
inn;
trivial.
+
apply some_lift in eqq.
destruct eqq as [?
eqq ?];
subst.
invcs typ.
rewrite (
nnrs_imp_expr_unflatten_read_eval _ _ _ brand_relation_brands σ
c _ _ _
eqq σ
inn ft).
simpl.
unfold equiv_dec,
string_eqdec,
var in *.
match_option;
simpl;
trivial.
rewrite lookup_update_neq by eauto.
match_option;
simpl;
trivial.
rewrite lookup_update_neq by eauto.
rewrite σ
inn.
exists d'.
split;
trivial.
rewrite update_first_update_first_neq_swap;
eauto.
-
Case "
NNRSimpLet"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1 [
eqq2 ?]] ];
subst;
simpl.
invcs typ.
+
simpl in eqq1.
apply some_lift in eqq1.
destruct eqq1 as [?
eqq1 ?];
subst.
rewrite <- (
nnrs_imp_expr_unflatten_read_eval _ _ _ brand_relation_brands σ
c _ _ _
eqq1 σ
inn ft).
case_eq (
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e₁);
simpl;
trivial
;
intros ?
eveqq.
match_destr_in eqq2;
unfold equiv,
complement in *.
*
subst.
invcs eqq2.
destruct (
in_update_break_first _ σ
inn d')
as [?[? [? [
eqq2 nin]]]]
;
subst.
rewrite eqq2.
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some d0)::
x)
x2 x0 v d)
;
simpl ;
intros HH1.
cut_to HH1; [|
tauto].
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some d0)::
x)
x2 x0 v d')
;
simpl ;
intros HH2.
cut_to HH2; [|
tauto].
unfold lift2P,
var in *.
repeat match_option_in HH1
;
rewrite eqq0 in HH2
;
try contradiction
;
repeat match_option_in HH2
;
try contradiction.
apply nnrs_imp_stmt_eval_domain_stack in eqq.
apply nnrs_imp_stmt_eval_domain_stack in eqq3.
fuse_tt.
rewrite lookup_app.
rewrite lookup_nin_none; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
exists o0.
rewrite update_app_nin; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
specialize (
HH1 ((
s,
o1)::
x5)
o2 x6);
simpl in HH1.
cut_to HH1; [|
unfold domain in *;
congruence |
trivial].
specialize (
HH2 ((
s,
o)::
x3)
o0 x4);
simpl in HH2.
cut_to HH2; [|
unfold domain in *;
congruence |
trivial].
destruct HH1;
subst.
fuse_tt.
split;
trivial.
*
assert (σ
_bt_cons :
pd_bindings_type ((
v0,
Some d0) :: σ) ((
v0, τ0) :: Γ)).
{
econstructor;
simpl;
trivial.
split;
trivial;
intros.
invcs H.
eapply nnrs_imp_expr_eval_preserves_types in eveqq;
eauto.
}
specialize (
IHs _ ((
v0,
Some d0)::σ)
d eqq2 ((
v0, τ0) :: Γ) σ
_bt_cons τ).
cut_to IHs;
simpl;
trivial;
try solve [
match_destr;
congruence].
specialize (
IHs _ ft).
simpl in IHs.
unfold var in *.
destruct (
equiv_dec v v0);
try congruence.
unfold lift2P in *.
do 2
match_option_in IHs
;
try contradiction.
generalize (
nnrs_imp_stmt_eval_domain_stack eqq)
;
generalize (
nnrs_imp_stmt_eval_domain_stack eqq0)
;
intros.
fuse_tt.
destruct (
equiv_dec v s0); [
congruence| ].
match_option_in IHs.
destruct IHs as [
dd' [
HH1 HH2]].
invcs HH1.
exists dd';
split;
trivial.
+
simpl in eqq1;
invcs eqq1.
match_destr_in eqq2;
unfold equiv,
complement in *.
*
subst.
invcs eqq2.
destruct (
in_update_break_first _ σ
inn d')
as [?[? [? [
eqq2 nin]]]]
;
subst.
rewrite eqq2.
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
None)::
x)
x1 x0 v d)
;
simpl ;
intros HH1.
cut_to HH1; [|
tauto].
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
None)::
x)
x1 x0 v d')
;
simpl ;
intros HH2.
cut_to HH2; [|
tauto].
unfold lift2P,
var in *.
repeat match_option_in HH1
;
rewrite eqq0 in HH2
;
try contradiction
;
repeat match_option_in HH2
;
try contradiction.
apply nnrs_imp_stmt_eval_domain_stack in eqq.
apply nnrs_imp_stmt_eval_domain_stack in eqq1.
fuse_tt.
rewrite lookup_app.
rewrite lookup_nin_none; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
exists o0.
rewrite update_app_nin; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
specialize (
HH1 ((
s,
o1)::
x4)
o2 x5);
simpl in HH1.
cut_to HH1; [|
unfold domain in *;
congruence |
trivial].
specialize (
HH2 ((
s,
o)::
x2)
o0 x3);
simpl in HH2.
cut_to HH2; [|
unfold domain in *;
congruence |
trivial].
destruct HH1;
subst.
fuse_tt.
split;
trivial.
*
assert (σ
_bt_cons :
pd_bindings_type ((
v0,
None) :: σ) ((
v0, τ0) :: Γ)).
{
econstructor;
simpl;
trivial.
split;
trivial;
intros.
invcs H.
}
specialize (
IHs _ ((
v0,
None)::σ)
d eqq2 ((
v0, τ0) :: Γ) σ
_bt_cons τ).
cut_to IHs;
simpl;
trivial;
try solve [
match_destr;
congruence].
specialize (
IHs _ ft).
simpl in IHs.
unfold var in *.
destruct (
equiv_dec v v0);
try congruence.
unfold lift2P in *.
do 2
match_option_in IHs
;
try contradiction.
generalize (
nnrs_imp_stmt_eval_domain_stack eqq)
;
generalize (
nnrs_imp_stmt_eval_domain_stack eqq0)
;
intros.
fuse_tt.
destruct (
equiv_dec v s0); [
congruence| ].
match_option_in IHs.
destruct IHs as [
dd' [
HH1 HH2]].
invcs HH1.
exists dd';
split;
trivial.
-
Case "
NNRSimpFor"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1 [
eqq2 ?]] ];
subst;
simpl.
invcs typ.
rewrite <- (
nnrs_imp_expr_unflatten_read_eval _ _ _ brand_relation_brands σ
c _ _ _
eqq1 σ
inn ft).
case_eq (
nnrs_imp_expr_eval brand_relation_brands σ
c σ
n);
simpl;
trivial
;
intros ?
eveqq.
eapply nnrs_imp_expr_eval_preserves_types in eveqq;
eauto.
dtype_inverter.
invcs eveqq;
rtype_equalizer;
subst.
clear x n eqq1 H2.
revert σ Γ
d d' σ
inn σ
_bt H4 Γ
inn ft.
induction d0;
intros σ Γ
d d' σ
inn σ
_bt typ Γ
inn ft;
simpl;
unfold var in *.
+
rewrite σ
inn;
eauto.
+
invcs H1.
specialize (
IHd0 H3);
clear H3.
match_destr_in eqq2;
unfold equiv,
complement in *.
*
subst.
invcs eqq2.
destruct (
in_update_break_first _ σ
inn d')
as [?[? [? [
eqq2 nin]]]]
;
subst.
rewrite eqq2.
clear eqq2.
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some a)::
x)
x1 x0 v d)
;
simpl ;
intros HH1.
cut_to HH1; [|
tauto].
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some a)::
x)
x1 x0 v d')
;
simpl ;
intros HH2.
cut_to HH2; [|
tauto].
unfold lift2P,
var in *.
repeat match_option_in HH1
;
rewrite eqq0 in HH2
;
try contradiction
;
repeat match_option_in HH2
;
try contradiction.
generalize (
nnrs_imp_stmt_eval_domain_stack eqq).
generalize (
nnrs_imp_stmt_eval_domain_stack eqq1).
fuse_tt.
specialize (
HH1 ((
s,
o)::
x2)
o0 x3);
simpl in HH1.
cut_to HH1; [|
unfold domain in *;
congruence |
trivial].
specialize (
HH2 ((
s,
o1)::
x4)
o2 x5);
simpl in HH2.
cut_to HH2; [|
unfold domain in *;
congruence |
trivial].
destruct HH1;
subst.
fuse_tt.
{
eapply nnrs_imp_stmt_eval_preserves_types in eqq;
eauto.
-
specialize (
IHd0 (
x4 ++ (
s,
o0) ::
x5) Γ
o0 o2).
{
cut_to IHd0;
trivial.
-
unfold lift2P in *.
rewrite update_app_nin in IHd0; [ |
unfold domain in *;
congruence].
simpl in IHd0.
destruct (
equiv_dec s s); [|
congruence].
trivial.
-
rewrite lookup_app.
rewrite lookup_nin_none;
simpl.
+
destruct (
equiv_dec s s); [|
congruence];
trivial.
+
unfold domain in *;
congruence.
-
invcs eqq;
auto.
}
-
econstructor;
simpl;
trivial;
split;
trivial;
intros ?
eqqq;
invcs eqqq;
trivial.
}
*
assert (σ
_bt_cons :
pd_bindings_type ((
v0,
Some a) :: σ) ((
v0, τ0) :: Γ)).
{
econstructor;
simpl;
trivial.
split;
trivial;
intros.
invcs H;
trivial.
}
specialize (
IHs _ ((
v0,
Some a)::σ)
d eqq2 ((
v0, τ0) :: Γ) σ
_bt_cons τ).
cut_to IHs;
simpl;
trivial;
try solve [
match_destr;
congruence].
specialize (
IHs _ ft).
simpl in IHs.
unfold var in *.
destruct (
equiv_dec v v0);
try congruence.
unfold lift2P in *.
do 2
match_option_in IHs
;
try contradiction.
generalize (
nnrs_imp_stmt_eval_domain_stack eqq)
;
generalize (
nnrs_imp_stmt_eval_domain_stack eqq0)
;
intros.
fuse_tt.
destruct (
equiv_dec v s0); [
congruence| ].
match_option_in IHs;
try contradiction.
destruct IHs as [
dd' [
HH1 HH2]].
invcs HH1.
clear H3.
generalize (
nnrs_imp_stmt_eval_preserves_types _ σ
c_bt σ
_bt_cons typ _ eqq)
;
intros p_bt.
invcs p_bt.
specialize (
IHd0 p1 Γ
o1 dd').
cut_to IHd0;
trivial.
-
Case "
NNRSimpIf"%
string.
unfold lift3 in eqq.
repeat match_option_in eqq.
invcs eqq;
simpl in *.
invcs typ.
rewrite <- (
nnrs_imp_expr_unflatten_read_eval _ _ _ brand_relation_brands σ
c _ _ _
eqq0 σ
inn ft).
match_option;
simpl;
trivial.
destruct d0;
simpl;
trivial.
destruct b;
eauto.
-
Case "
NNRSimpEither"%
string.
unfold lift3 in eqq.
repeat match_option_in eqq.
invcs eqq;
simpl in *.
invcs typ.
rewrite <- (
nnrs_imp_expr_unflatten_read_eval _ _ _ brand_relation_brands σ
c _ _ _
eqq0 σ
inn ft).
match_option;
simpl;
trivial.
eapply nnrs_imp_expr_eval_preserves_types in eqq;
eauto.
destruct d0;
simpl;
trivial
;
invcs eqq;
rtype_equalizer;
subst.
+
match_destr_in eqq1;
unfold equiv,
complement in *.
*
subst.
invcs eqq1.
destruct (
in_update_break_first _ σ
inn d')
as [?[? [? [
eqq1 nin]]]]
;
subst.
rewrite eqq1.
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some d0)::
x)
x0 n1 v d)
;
simpl ;
intros HH1.
cut_to HH1; [|
tauto].
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some d0)::
x)
x0 n1 v d')
;
simpl ;
intros HH2.
cut_to HH2; [|
tauto].
unfold lift2P,
var in *.
repeat match_option_in HH1
;
rewrite eqq3 in HH2
;
try contradiction
;
repeat match_option_in HH2
;
try contradiction.
apply nnrs_imp_stmt_eval_domain_stack in eqq.
apply nnrs_imp_stmt_eval_domain_stack in eqq4.
fuse_tt.
rewrite lookup_app.
rewrite lookup_nin_none; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
exists o0.
rewrite update_app_nin; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
specialize (
HH1 ((
s,
o1)::
x3)
o2 x4);
simpl in HH1.
cut_to HH1; [|
unfold domain in *;
congruence |
trivial].
specialize (
HH2 ((
s,
o)::
x1)
o0 x2);
simpl in HH2.
cut_to HH2; [|
unfold domain in *;
congruence |
trivial].
destruct HH1;
subst.
fuse_tt.
split;
trivial.
*
assert (σ
_bt_cons :
pd_bindings_type ((
v0,
Some d0) :: σ) ((
v0, τ
l) :: Γ)).
{
econstructor;
simpl;
trivial.
split;
trivial;
intros.
invcs H;
trivial.
}
specialize (
IHs1 _ ((
v0,
Some d0)::σ)
d eqq1 ((
v0, τ
l) :: Γ) σ
_bt_cons τ).
cut_to IHs1;
simpl;
trivial;
try solve [
match_destr;
congruence].
specialize (
IHs1 _ ft).
simpl in IHs1.
unfold var in *.
destruct (
equiv_dec v v0);
try congruence.
unfold lift2P in *.
do 2
match_option_in IHs1
;
try contradiction.
generalize (
nnrs_imp_stmt_eval_domain_stack eqq)
;
generalize (
nnrs_imp_stmt_eval_domain_stack eqq3)
;
intros.
fuse_tt.
destruct (
equiv_dec v s); [
congruence| ].
match_option_in IHs1.
destruct IHs1 as [
dd' [
HH1 HH2]].
invcs HH1.
exists dd';
split;
trivial.
+
match_destr_in eqq2;
unfold equiv,
complement in *.
*
subst.
invcs eqq2.
destruct (
in_update_break_first _ σ
inn d')
as [?[? [? [
eqq2 nin]]]]
;
subst.
rewrite eqq2.
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some d0)::
x)
x0 n2 v d)
;
simpl ;
intros HH1.
cut_to HH1; [|
tauto].
generalize (
nnrs_imp_stmt_eval_unused brand_relation_brands σ
c ((
v,
Some d0)::
x)
x0 n2 v d')
;
simpl ;
intros HH2.
cut_to HH2; [|
tauto].
unfold lift2P,
var in *.
repeat match_option_in HH1
;
rewrite eqq3 in HH2
;
try contradiction
;
repeat match_option_in HH2
;
try contradiction.
apply nnrs_imp_stmt_eval_domain_stack in eqq.
apply nnrs_imp_stmt_eval_domain_stack in eqq4.
fuse_tt.
rewrite lookup_app.
rewrite lookup_nin_none; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
exists o0.
rewrite update_app_nin; [|
unfold domain in *;
congruence].
simpl.
destruct (
equiv_dec s s); [|
congruence].
specialize (
HH1 ((
s,
o1)::
x3)
o2 x4);
simpl in HH1.
cut_to HH1; [|
unfold domain in *;
congruence |
trivial].
specialize (
HH2 ((
s,
o)::
x1)
o0 x2);
simpl in HH2.
cut_to HH2; [|
unfold domain in *;
congruence |
trivial].
destruct HH1;
subst.
fuse_tt.
split;
trivial.
*
assert (σ
_bt_cons :
pd_bindings_type ((
v1,
Some d0) :: σ) ((
v1, τ
r) :: Γ)).
{
econstructor;
simpl;
trivial.
split;
trivial;
intros.
invcs H;
trivial.
}
specialize (
IHs2 _ ((
v1,
Some d0)::σ)
d eqq2 ((
v1, τ
r) :: Γ) σ
_bt_cons τ).
cut_to IHs2;
simpl;
trivial;
try solve [
match_destr;
congruence].
specialize (
IHs2 _ ft).
simpl in IHs2.
unfold var in *.
destruct (
equiv_dec v v1);
try congruence.
unfold lift2P in *.
do 2
match_option_in IHs2
;
try contradiction.
generalize (
nnrs_imp_stmt_eval_domain_stack eqq)
;
generalize (
nnrs_imp_stmt_eval_domain_stack eqq3)
;
intros.
fuse_tt.
destruct (
equiv_dec v s); [
congruence| ].
match_option_in IHs2.
destruct IHs2 as [
dd' [
HH1 HH2]].
invcs HH1.
exists dd';
split;
trivial.
Qed.
End eval.
Section typ.
Lemma nnrs_imp_expr_unflatten_init_type {
e e':
nnrs_imp_expr}:
nnrs_imp_expr_unflatten_init e =
Some e' ->
forall {Γ
c Γ τ},
[ Γ
c ; Γ ⊢
e ▷
Coll (
Coll τ) ] ->
[ Γ
c ; Γ ⊢
e' ▷
Coll τ ].
Proof.
revert e'.
nnrs_imp_expr_cases (
induction e)
Case
;
simpl ;
intros e'
eqq Γ
c Γ τ
typ
;
try discriminate.
-
Case "
NNRSimpConst"%
string.
destruct d;
simpl in *
;
invcs eqq.
invcs typ.
invcs H2.
apply Coll_right_inv in H1;
subst.
destruct l;
invcs H0;
simpl.
+
repeat econstructor.
+
simpl in H3;
invcs H3.
invcs H2;
rtype_equalizer;
subst.
destruct d;
try discriminate.
destruct l;
try discriminate.
invcs H1.
econstructor.
rewrite <-
H.
econstructor;
trivial.
-
Case "
NNRSimpBinop"%
string.
destruct b;
try discriminate.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ.
invcs H3.
apply Coll_right_inv in H;
subst.
econstructor;
eauto.
econstructor.
-
Case "
NNRSimpUnop"%
string.
destruct u;
try discriminate.
destruct e;
try discriminate.
+
destruct d;
try discriminate.
invcs typ.
invcs H2.
apply Coll_right_inv in H;
subst.
invcs eqq;
trivial.
+
destruct u;
try discriminate.
invcs eqq.
invcs typ.
invcs H2.
apply Coll_right_inv in H;
subst.
trivial.
Qed.
Lemma nnrs_imp_expr_unflatten_read_type e e'
v :
nnrs_imp_expr_unflatten_read e v =
Some e' ->
forall {Γ
c Γ τ
o},
[ Γ
c ; Γ ⊢
e ▷ τ
o] ->
forall τ,
lookup equiv_dec Γ
v =
Some (
Coll τ) ->
[ Γ
c ; (
update_first equiv_dec Γ
v τ) ⊢
e' ▷ τ
o ].
Proof.
revert e'.
nnrs_imp_expr_cases (
induction e)
Case
;
simpl ;
intros e'
eqq Γ
c Γ τ
o typ τ
inn.
-
Case "
NNRSimpGetConstant"%
string.
invcs eqq.
invcs typ.
econstructor;
trivial.
-
Case "
NNRSimpVar"%
string.
match_destr_in eqq.
invcs eqq;
simpl.
invcs typ.
econstructor.
rewrite lookup_update_neq;
trivial.
eauto.
-
Case "
NNRSimpConst"%
string.
invcs eqq;
simpl;
trivial.
invcs typ.
econstructor;
trivial.
-
Case "
NNRSimpBinop"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ.
econstructor;
eauto.
-
Case "
NNRSimpUnop"%
string.
invcs typ.
destruct u
;
try solve [
apply some_lift in eqq
;
destruct eqq as [
eqq1 eqq2]
;
subst;
simpl
;
econstructor;
eauto].
destruct e
;
try solve [
apply some_lift in eqq
;
destruct eqq as [
eqq1 eqq2]
;
subst;
simpl
;
econstructor;
eauto].
invcs H2.
invcs H4.
match_destr_in eqq.
+
invcs eqq;
simpl.
rewrite e in *.
unfold var in *.
rewrite inn in H1;
invcs H1;
rtype_equalizer.
apply Coll_right_inv in H0;
subst.
econstructor.
rewrite lookup_update_eq_in;
try congruence.
apply lookup_in_domain in inn;
trivial.
+
invcs eqq;
simpl.
econstructor;
econstructor.
rewrite lookup_update_neq;
eauto.
-
Case "
NNRSimpGroupBy"%
string.
apply some_lift in eqq.
destruct eqq as [??];
subst;
simpl.
invcs typ.
econstructor;
trivial.
eauto.
Qed.
Lemma nnrs_imp_expr_unflatten_write_type e e'
v :
nnrs_imp_expr_unflatten_write e v =
Some e' ->
forall {Γ
c Γ τ
o},
[ Γ
c ; Γ ⊢
e ▷
Coll (
Coll τ
o)] ->
forall τ,
lookup equiv_dec Γ
v =
Some (
Coll τ) ->
[ Γ
c ; (
update_first equiv_dec Γ
v τ) ⊢
e' ▷
Coll τ
o ].
Proof.
revert e'.
nnrs_imp_expr_cases (
induction e)
Case
;
simpl ;
intros e'
eqq Γ
c Γ τ
o typ τ
inn
;
try discriminate.
-
Case "
NNRSimpVar"%
string.
match_destr_in eqq.
rewrite e in *;
clear v0 e.
invcs eqq;
simpl.
invcs typ.
rewrite inn in H1.
invcs H1.
apply Coll_right_inv in H0;
subst.
econstructor.
rewrite lookup_update_eq_in;
eauto.
apply lookup_in_domain in inn;
trivial.
-
Case "
NNRSimpConst"%
string.
invcs typ.
destruct d;
simpl;
try discriminate.
destruct l;
simpl;
try discriminate.
+
invcs eqq.
econstructor.
repeat econstructor.
+
destruct d;
simpl;
try discriminate.
destruct l;
simpl;
try discriminate.
invcs eqq.
econstructor.
simpl in H1.
invcs H1.
apply Coll_right_inv in H0;
subst.
invcs H2;
trivial.
-
Case "
NNRSimpBinop"%
string.
destruct b;
try discriminate.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ.
invcs H3.
apply Coll_right_inv in H;
subst.
econstructor;
eauto.
econstructor.
-
Case "
NNRSimpUnop"%
string.
invcs typ.
destruct u;
try discriminate.
match_destr_in eqq.
invcs eqq.
invcs H2.
apply Coll_right_inv in H;
subst.
apply (
nnrs_imp_expr_type_update_first_irrelevant Γ
c nil)
;
simpl;
tauto.
Qed.
Lemma nnrs_imp_stmt_unflatten_type s s'
v :
nnrs_imp_stmt_unflatten s v =
Some s' ->
forall {Γ
c Γ},
[ Γ
c ; Γ ⊢
s] ->
forall τ,
lookup equiv_dec Γ
v =
Some (
Coll (
Coll τ)) ->
[ Γ
c ; (
update_first equiv_dec Γ
v (
Coll τ)) ⊢
s'].
Proof.
revert s'
;
nnrs_imp_stmt_cases (
induction s)
Case
;
simpl in *;
intros s'
eqq Γ
c Γ
typ τ
inn.
-
Case "
NNRSimpSkip"%
string.
invcs eqq.
econstructor.
-
Case "
NNRSimpSeq"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ.
econstructor;
eauto.
-
Case "
NNRSimpAssign"%
string.
apply some_lift in eqq.
destruct eqq as [??];
subst;
simpl.
invcs typ.
match_destr_in e;
unfold equiv,
complement in *.
+
subst.
unfold equiv_dec,
string_eqdec in *.
rewrite inn in H3.
invcs H3.
econstructor.
*
eapply nnrs_imp_expr_unflatten_write_type in e;
eauto.
*
rewrite lookup_update_eq_in;
eauto.
apply lookup_in_domain in inn;
trivial.
+
econstructor.
*
eapply nnrs_imp_expr_unflatten_read_type in e;
eauto.
*
rewrite lookup_update_neq;
eauto.
-
Case "
NNRSimpLet"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ;
simpl in *.
+
apply some_lift in eqq1.
destruct eqq1 as [?
eqq1 ?];
subst;
simpl.
econstructor.
*
eapply nnrs_imp_expr_unflatten_read_type in eqq1;
eauto.
* {
match_destr_in eqq2;
unfold equiv,
complement in *.
-
invcs eqq2.
apply (
nnrs_imp_stmt_type_update_first_irrelevant Γ
c ((
v, τ0) ::
nil))
;
simpl;
tauto.
-
specialize (
IHs _ eqq2 _ _ H4).
simpl in IHs.
unfold var in *.
destruct (
equiv_dec v v0); [
congruence | ].
eauto.
}
+
invcs eqq1.
match_destr_in eqq2;
unfold equiv,
complement in *.
*
invcs eqq2.
econstructor;
trivial.
apply (
nnrs_imp_stmt_type_update_first_irrelevant Γ
c ((
v, τ0) ::
nil))
;
simpl;
tauto.
* {
econstructor.
-
rewrite <- (
nnrs_imp_stmt_unflatten_var_usage eqq2);
trivial.
-
specialize (
IHs _ eqq2 _ _ H4).
simpl in IHs.
unfold var in *.
destruct (
equiv_dec v v0); [
congruence | ].
eauto.
}
-
Case "
NNRSimpFor"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ.
eapply nnrs_imp_expr_unflatten_read_type in eqq1;
eauto.
econstructor;
trivial;
eauto.
match_destr_in eqq2;
unfold equiv,
complement in *.
+
invcs eqq2.
apply (
nnrs_imp_stmt_type_update_first_irrelevant Γ
c ((
v, τ0) ::
nil))
;
simpl;
tauto.
+
specialize (
IHs _ eqq2 _ _ H4).
simpl in IHs.
unfold var in *.
destruct (
equiv_dec v v0); [
congruence | ].
eauto.
-
Case "
NNRSimpIf"%
string.
unfold lift3 in eqq.
repeat match_option_in eqq.
invcs eqq;
simpl.
invcs typ.
eapply nnrs_imp_expr_unflatten_read_type in eqq0;
eauto.
econstructor;
eauto.
-
Case "
NNRSimpEither"%
string.
unfold lift3 in eqq.
repeat match_option_in eqq.
invcs eqq;
simpl.
invcs typ.
eapply nnrs_imp_expr_unflatten_read_type in eqq0;
eauto.
econstructor;
eauto.
+
match_destr_in eqq1;
unfold equiv,
complement in *.
*
invcs eqq1.
apply (
nnrs_imp_stmt_type_update_first_irrelevant Γ
c ((
v, τ
l) ::
nil))
;
simpl;
tauto.
*
specialize (
IHs1 _ eqq1 _ _ H6).
simpl in IHs1.
unfold var in *.
destruct (
equiv_dec v v0); [
congruence | ].
eauto.
+
match_destr_in eqq2;
unfold equiv,
complement in *.
*
invcs eqq2.
apply (
nnrs_imp_stmt_type_update_first_irrelevant Γ
c ((
v, τ
r) ::
nil))
;
simpl;
tauto.
*
specialize (
IHs2 _ eqq2 _ _ H7).
simpl in IHs2.
unfold var in *.
destruct (
equiv_dec v v1); [
congruence | ].
eauto.
Qed.
End typ.
Section type_enrich.
Lemma nnrs_imp_expr_unflatten_read_enrich_type {
e e'
v} :
nnrs_imp_expr_unflatten_read e v =
Some e' ->
forall {Γ
c Γ τ
o},
[ Γ
c ; Γ ⊢
e ▷ τ
o] ->
forall τ,
In v (
nnrs_imp_expr_free_vars e) ->
lookup equiv_dec Γ
v =
Some τ ->
exists τ', τ =
Coll (
Coll τ').
Proof.
revert e'.
nnrs_imp_expr_cases (
induction e)
Case
;
simpl ;
intros e'
eqq Γ
c Γ τ
o typ τ
inn1 inn2
;
try contradiction.
-
Case "
NNRSimpVar"%
string.
match_destr_in eqq.
intuition.
-
Case "
NNRSimpBinop"%
string.
apply some_lift2 in eqq.
destruct eqq as [?[?
eqq1[
eqq2 ?]]];
subst.
invcs typ.
rewrite in_app_iff in inn1.
destruct inn1 as [
inn1|
inn1];
eauto.
-
Case "
NNRSimpUnop"%
string.
invcs typ.
destruct u
;
try solve [
apply some_lift in eqq
;
destruct eqq as [
eqq1 eqq2]
;
subst;
simpl
;
invcs H2;
eauto].
invcs H2.
destruct e
;
try solve [
apply some_lift in eqq
;
destruct eqq as [
eqq1 eqq2]
;
subst;
simpl;
eauto].
simpl in inn1.
match_destr_in eqq; [ |
intuition congruence].
invcs eqq.
invcs H4.
intuition;
subst.
rewrite H1 in inn2.
invcs inn2.
eauto.
-
Case "
NNRSimpGroupBy"%
string.
apply some_lift in eqq.
destruct eqq as [?
eqq ?].
subst;
simpl.
invcs typ.
eauto.
Qed.
Lemma nnrs_imp_stmt_unflatten_read_out_type s s'
v :
nnrs_imp_stmt_unflatten s v =
Some s' ->
nnrs_imp_stmt_read_out s v =
true ->
forall {Γ
c Γ},
[ Γ
c ; Γ ⊢
s] ->
forall τ,
lookup equiv_dec Γ
v =
Some τ ->
exists τ', τ =
Coll (
Coll τ').
Proof.
End type_enrich.
Section unflatten_safe.
Lemma nnrs_imp_stmt_unflatten_safe_eval s s'
v σ
c σ
d :
nnrs_imp_stmt_unflatten_safe s v =
Some s' ->
forall Γ
c,
bindings_type σ
c Γ
c ->
forall Γ,
pd_bindings_type σ Γ ->
forall τ,
lookup equiv_dec σ
v =
Some d ->
lookup equiv_dec Γ
v =
Some τ ->
[ Γ
c ; Γ ⊢
s ] ->
forall d',
lift2P flattens_to d d' ->
lift2P
(
fun σ₁' σ₂' =>
match lookup equiv_dec σ₁'
v with
|
Some dd =>
exists dd',
σ₂' =
update_first equiv_dec σ₁'
v dd'
/\
lift2P flattens_to dd dd'
|
None =>
False
end
)
(
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ)
(
nnrs_imp_stmt_eval brand_relation_brands σ
c s' (
update_first equiv_dec σ
v d')).
Proof.
Lemma nnrs_imp_stmt_unflatten_safe_type s s'
v :
nnrs_imp_stmt_unflatten_safe s v =
Some s' ->
forall {Γ
c Γ},
[ Γ
c ; Γ ⊢
s] ->
forall τ,
lookup equiv_dec Γ
v =
Some τ ->
exists τ',
[ Γ
c ; (
update_first equiv_dec Γ
v (
Coll τ')) ⊢
s']
/\ τ =
Coll (
Coll τ').
Proof.
Lemma nnrs_imp_stmt_unflatten_safe_var_usage {
s s'
v}:
nnrs_imp_stmt_unflatten_safe s v =
Some s' ->
forall v',
nnrs_imp_stmt_var_usage s v' =
nnrs_imp_stmt_var_usage s'
v'.
Proof.
Lemma nnrs_imp_stmt_unflatten_safe_var_usage_sub {
s x s'} :
nnrs_imp_stmt_unflatten_safe s x =
Some s' ->
stmt_var_usage_sub s s'.
Proof.
End unflatten_safe.
End TNNRSimpUnflatten.