Require Import String.
Require Import Bool.
Require Import List.
Require Import Arith.
Require Import Program.
Require Import EquivDec.
Require Import Morphisms.
Require Import Utils.
Require Import DataSystem.
Require Import NNRSimp.
Require Import NNRSimpVars.
Require Import NNRSimpUsage.
Require Import NNRSimpEval.
Require Import NNRSimpSem.
Require Import NNRSimpSemEval.
Import ListNotations.
Local Open Scope list_scope.
Section TNNRSimp.
Typing rules for NNRSimp
Context {
m:
basic_model}.
Definition pd_tbindings :=
list (
string*
rtype).
Definition preserves_Some {
A B} (
f:
A->
option B) (
xd yd:
A) :
Prop
:=
forall xd',
f xd =
Some xd' ->
exists yd',
f yd =
Some yd'.
Global Instance preserves_Some_pre {
A B} (
f:
A->
option B)
:
PreOrder (
preserves_Some f).
Proof.
Lemma Forall2_preserves_Some_snd_update_first {
B}
l v (
d:
B) :
Forall2 (
preserves_Some snd)
l (
update_first string_dec l v (
Some d)).
Proof.
induction l; simpl; trivial.
destruct a.
match_destr.
- subst.
constructor; try reflexivity.
red; simpl; intros; subst; eauto.
- constructor; eauto.
reflexivity.
Qed.
Definition has_some_parts {
A B} {
dec:
EqDec A eq} (
someparts:
list A) (
l:
list (
A*
option B)) :
Prop
:=
Forall (
fun x =>
match lookup equiv_dec l x with
|
None =>
True
|
Some None =>
False
|
Some (
Some _) =>
True
end)
someparts.
Lemma has_some_parts_app {
A B} {
dec:
EqDec A eq}
l1 l2 (σ:
list (
A*
option B)) :
has_some_parts (
l1 ++
l2) σ <->
has_some_parts l1 σ /\
has_some_parts l2 σ.
Proof.
Global Instance has_some_parts_incl_proper {
A B dec}:
Proper ((@
incl A) -->
lookup_incl -->
impl) (@
has_some_parts A B dec).
Proof.
intros x y inclxy l1 l2 eql.
unfold has_some_parts,
equiv_dec.
repeat rewrite Forall_forall.
intros H ?
inn.
unfold flip in *.
specialize (
inclxy _ inn).
specialize (
H _ inclxy).
match_option.
apply eql in eqq.
rewrite eqq in H.
match_destr.
Qed.
Definition pd_bindings_type
(
b:
pd_bindings)
(
t:
pd_tbindings)
:=
Forall2 (
fun xy1 xy2 =>
(
fst xy1) = (
fst xy2)
/\
forall d,
snd xy1 =
Some d ->
d ▹
snd xy2)
b t.
Lemma pd_bindings_type_in_normalized {Γ σ} :
pd_bindings_type σ Γ ->
forall d,
In (
Some d) (
map snd σ) ->
data_normalized brand_relation_brands d.
Proof.
unfold pd_bindings_type.
intros typ d inn.
rewrite in_map_iff in inn.
destruct inn as [[??][?
inn]];
simpl in *;
subst.
apply (
Forall2_In_l typ)
in inn.
destruct inn as [[??][?[?
dt]]];
simpl in *;
subst.
specialize (
dt _ (
eq_refl _)).
qeauto.
Qed.
Lemma pd_bindings_type_cut_down_to {σ Γ} :
pd_bindings_type σ Γ ->
forall l,
pd_bindings_type (
cut_down_to σ
l) (
cut_down_to Γ
l).
Proof.
induction 1; simpl; intros.
- constructor.
- destruct H as [eqq1 ?].
rewrite eqq1.
match_destr.
constructor.
+ tauto.
+ apply IHForall2.
Qed.
Section typ.
Context (Γ
c:
tbindings).
Reserved Notation "[ Γ ⊢
e ▷ τ ]".
Inductive nnrs_imp_expr_type :
pd_tbindings ->
nnrs_imp_expr ->
rtype ->
Prop :=
|
type_NNRSimpGetConstant {τ} Γ
s :
tdot Γ
c s =
Some τ ->
[ Γ ⊢
NNRSimpGetConstant s ▷ τ ]
|
type_NNRSimpVar {τ} Γ
v :
lookup equiv_dec Γ
v = (
Some τ) ->
[ Γ ⊢
NNRSimpVar v ▷ τ ]
|
type_NNRSimpConst {τ} Γ
c :
normalize_data brand_relation_brands c ▹ τ ->
[ Γ ⊢
NNRSimpConst c ▷ τ ]
|
type_NNRSimpBinop {τ₁ τ₂ τ} Γ
b e₁
e₂ :
binary_op_type b τ₁ τ₂ τ ->
[ Γ ⊢
e₁ ▷ τ₁ ] ->
[ Γ ⊢
e₂ ▷ τ₂ ] ->
[ Γ ⊢
NNRSimpBinop b e₁
e₂ ▷ τ ]
|
type_NNRSimpUnop {τ₁ τ} Γ
u e :
unary_op_type u τ₁ τ ->
[ Γ ⊢
e ▷ τ₁ ] ->
[ Γ ⊢
NNRSimpUnop u e ▷ τ ]
|
type_NNRSimpGroupBy {τ
l k pf} Γ
g sl e :
sublist sl (
domain τ
l) ->
[ Γ ⊢
e ▷
Coll (
Rec k τ
l pf) ] ->
[ Γ ⊢
NNRSimpGroupBy g sl e ▷
GroupBy_type g sl k τ
l pf ]
where
"[ Γ ⊢
e ▷ τ ]" := (
nnrs_imp_expr_type Γ
e τ) :
nnrs_imp_scope
.
Notation "[ Γ ⊢
e ▷ τ ]" := (
nnrs_imp_expr_type Γ
e τ) :
nnrs_imp_scope.
Reserved Notation "[ Γ ⊢
s ]".
Inductive nnrs_imp_stmt_type :
pd_tbindings ->
nnrs_imp_stmt ->
Prop :=
|
type_NNRSimpSkip Γ :
[ Γ ⊢
NNRSimpSkip ]
|
type_NNRSimpSeq Γ
s₁
s₂ :
[ Γ ⊢
s₁ ] ->
[ Γ ⊢
s₂ ] ->
[ Γ ⊢
NNRSimpSeq s₁
s₂ ]
|
type_NNRSimpLetDef Γ τ
x e₁
s₂ :
[ Γ ⊢
e₁ ▷ τ ] ->
[ (
x,τ)::Γ ⊢
s₂ ] ->
[ Γ ⊢
NNRSimpLet x (
Some e₁)
s₂ ]
|
type_NNRSimpLetNone Γ τ
x s₂ :
nnrs_imp_stmt_var_usage s₂
x <>
VarMayBeUsedWithoutAssignment ->
[ (
x,τ)::Γ ⊢
s₂ ] ->
[ Γ ⊢
NNRSimpLet x None s₂ ]
|
type_NNRSimpAssign Γ τ
x e :
[ Γ ⊢
e ▷ τ ] ->
lookup string_dec Γ
x =
Some τ ->
[ Γ ⊢
NNRSimpAssign x e ]
|
type_NNRSimpFor Γ τ
x e₁
s₂ :
[ Γ ⊢
e₁ ▷
Coll τ ] ->
[ (
x,τ)::Γ ⊢
s₂ ] ->
[ Γ ⊢
NNRSimpFor x e₁
s₂ ]
|
type_NNRSimpIf Γ
e s₁
s₂ :
[ Γ ⊢
e ▷
Bool] ->
[ Γ ⊢
s₁ ] ->
[ Γ ⊢
s₂ ] ->
[ Γ ⊢
NNRSimpIf e s₁
s₂ ]
|
type_NNRSimpEither Γ τ
l τ
r e x₁
s₁
x₂
s₂ :
[ Γ ⊢
e ▷
Either τ
l τ
r] ->
[ (
x₁,τ
l)::Γ ⊢
s₁ ] ->
[ (
x₂,τ
r)::Γ ⊢
s₂ ] ->
[ Γ ⊢
NNRSimpEither e x₁
s₁
x₂
s₂ ]
where
"[ Γ ⊢
s ]" := (
nnrs_imp_stmt_type Γ
s) :
nnrs_imp_scope
.
Notation "[ Γ ⊢
s ]" := (
nnrs_imp_stmt_type Γ
s) :
nnrs_imp_scope.
End typ.
Notation "[ Γ
c ; Γ ⊢
e ▷ τ ]" := (
nnrs_imp_expr_type Γ
c Γ
e τ) :
nnrs_imp_scope.
Notation "[ Γ
c ; Γ ⊢
s ]" := (
nnrs_imp_stmt_type Γ
c Γ
s) :
nnrs_imp_scope.
Local Hint Immediate type_NNRSimpSkip :
qcert.
Local Open Scope nnrs_imp.
Definition nnrs_imp_type Γ
c (
si:
nnrs_imp) τ
:=
let (
s,
ret) :=
si in
nnrs_imp_stmt_var_usage s ret <>
VarMayBeUsedWithoutAssignment
/\ [ Γ
c ; (
ret, τ)::
nil ⊢
s ].
Notation "[ Γ
c ⊢
si ▷ τ ]" := (
nnrs_imp_type Γ
c si τ) :
nnrs_imp_scope.
Definition nnrs_imp_returns (
si:
nnrs_imp)
:=
nnrs_imp_stmt_var_usage (
fst si) (
snd si) =
VarMustBeAssigned.
Lemma typed_nnrs_imp_expr_yields_typed_data {σ
c Γ
c} {σ Γ} {
e τ} :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
has_some_parts (
nnrs_imp_expr_free_vars e) σ ->
[ Γ
c ; Γ ⊢
e ▷ τ ] ->
exists d,
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e =
Some d
/\
d ▹ τ.
Proof.
Lemma typed_nnrs_imp_expr_yields_typed_data_gen {σ
c Γ
c} {σ Γ} {
e τ} {
alreadydefined} :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
has_some_parts alreadydefined σ ->
[ Γ
c ; Γ ⊢
e ▷ τ ] ->
incl (
nnrs_imp_expr_free_vars e)
alreadydefined ->
exists d,
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e =
Some d
/\
d ▹ τ.
Proof.
Theorem typed_nnrs_imp_expr_yields_typed_data_compute {σ
c Γ
c} {σ Γ} {
e τ} :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
has_some_parts (
nnrs_imp_expr_free_vars e) σ ->
[ Γ
c ; Γ ⊢
e ▷ τ ] ->
{
d |
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e =
Some d
&
d ▹ τ}.
Proof.
Lemma nnrs_imp_expr_eval_preserves_types {σ
c Γ
c} {σ Γ} {
e τ} :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
[ Γ
c ; Γ ⊢
e ▷ τ ] ->
forall d,
nnrs_imp_expr_eval brand_relation_brands σ
c σ
e =
Some d ->
d ▹ τ.
Proof.
intros Γ
ctyp Γ
typ etyp d eqq.
dependent induction etyp;
simpl in *.
-
unfold tdot in *.
red in Γ
ctyp.
assert (Γ
ctyp':
Forall2
(
fun (
x :
string *
rtype) (
y :
string *
data) =>
fst x =
fst y /\ (
fun x y =>
data_type y x) (
snd x) (
snd y))
Γ
c σ
c).
{
apply Forall2_flip in Γ
ctyp.
simpl in Γ
ctyp.
revert Γ
ctyp.
apply Forall2_incl;
intuition.
}
destruct (
Forall2_lookupr_some Γ
ctyp'
eqq)
as [? [
eqq1 eqq2]].
unfold edot in H.
rewrite eqq1 in H;
invcs H.
trivial.
-
unfold id in eqq.
apply some_olift in eqq.
simpl in eqq.
destruct eqq as [?
eqq ?];
subst.
destruct (
Forall2_lookup_some Γ
typ H
(
P:=(
fun xy1 xy2 =>
forall d :
data,
xy1 =
Some d ->
d ▹
xy2)))
as [?[
eqq1 ?]].
rewrite eqq1 in eqq;
invcs eqq.
auto.
-
invcs eqq;
trivial.
-
apply some_olift2 in eqq.
destruct eqq as [
d1 [
d2 d1eq [
d2eq beq]]].
specialize (
IHetyp1 Γ
typ _ d1eq).
specialize (
IHetyp2 Γ
typ _ d2eq).
destruct (
typed_binary_op_yields_typed_data _ _ _ IHetyp1 IHetyp2 H)
as [? [
eqq1 ?]].
rewrite eqq1 in beq;
invcs beq;
trivial.
-
apply some_olift in eqq.
destruct eqq as [
d1 d1eq oeq].
specialize (
IHetyp Γ
typ _ d1eq).
destruct (
typed_unary_op_yields_typed_data _ _ IHetyp H)
as [? [
eqq1 ?]].
rewrite eqq1 in oeq;
invcs oeq;
trivial.
-
match_option_in eqq.
specialize (
IHetyp Γ
typ _ eqq0).
dtype_inverter.
destruct (
typed_group_by_nested_eval_table_yields_typed_data IHetyp g sl H)
as [? [
eqq1 ?]].
rewrite eqq1 in eqq;
invcs eqq;
trivial.
Qed.
Lemma typed_nnrs_imp_expr_vars_in_ctxt {Γ
c Γ} {
e:
nnrs_imp_expr} {τ} :
[Γ
c; Γ ⊢
e ▷ τ] ->
forall x,
nnrs_imp_expr_may_use e x =
true ->
In x (
domain Γ).
Proof.
intros typexpr;
dependent induction typexpr;
simpl;
intros ?
eqq;
try discriminate.
-
unfold equiv_decb in eqq.
match_destr_in eqq;
red in e;
subst.
apply lookup_in_domain in H;
trivial.
-
apply orb_prop in eqq;
intuition.
-
intuition.
-
intuition.
Qed.
Lemma typed_nnrs_imp_stmt_vars_in_ctxt {Γ
c Γ} {
s:
nnrs_imp_stmt} :
[ Γ
c ; Γ ⊢
s ] ->
(
forall x,
nnrs_imp_stmt_var_usage s x <>
VarNotUsedAndNotAssigned ->
In x (
domain Γ)).
Proof.
intros typs.
dependent induction typs;
simpl;
intros v neq;
unfold equiv_decb,
var in *.
-
congruence.
-
specialize (
IHtyps1 v)
;
specialize (
IHtyps2 v)
;
match_destr_in neq
;
tauto.
-
match_case_in neq;
intros eqq;
rewrite eqq in neq.
+
eapply typed_nnrs_imp_expr_vars_in_ctxt;
eauto.
+
destruct (
x ==
v); [
congruence | ].
specialize (
IHtyps _ neq).
unfold equiv,
complement in *.
simpl in IHtyps;
tauto.
-
destruct (
x ==
v); [
congruence | ].
specialize (
IHtyps _ neq).
unfold equiv,
complement in *.
simpl in IHtyps;
tauto.
-
match_case_in neq;
intros eqq;
rewrite eqq in neq.
+
eapply typed_nnrs_imp_expr_vars_in_ctxt;
eauto.
+
destruct (
x ==
v); [|
congruence].
red in e0;
subst.
apply lookup_in_domain in H0;
trivial.
-
case_eq (
nnrs_imp_expr_may_use e₁
v);
intros eqq1;
rewrite eqq1 in neq.
+
eapply typed_nnrs_imp_expr_vars_in_ctxt;
eauto.
+
destruct (
x ==
v); [
congruence | ].
match_case_in neq;
intros eqq2;
rewrite eqq2 in neq.
*
congruence.
*
specialize (
IHtyps v).
unfold equiv,
complement in *.
rewrite eqq2 in IHtyps.
simpl in IHtyps.
intuition.
*
congruence.
-
case_eq (
nnrs_imp_expr_may_use e v);
intros eqq1;
rewrite eqq1 in neq.
+
eapply typed_nnrs_imp_expr_vars_in_ctxt;
eauto.
+ {
match_case_in neq;
intros eqq2;
rewrite eqq2 in neq.
-
match_case_in neq;
intros eqq3;
rewrite eqq3 in neq
;
eapply IHtyps1;
congruence.
-
eapply IHtyps1;
congruence.
-
match_case_in neq;
intros eqq3;
rewrite eqq3 in neq;
try congruence.
eapply IHtyps2;
congruence.
}
-
case_eq (
nnrs_imp_expr_may_use e v);
intros eqq1;
rewrite eqq1 in neq.
+
eapply typed_nnrs_imp_expr_vars_in_ctxt;
eauto.
+ {
destruct (
x₁ ==
v).
+
destruct (
x₂ ==
v); [
congruence | ].
specialize (
IHtyps2 v);
simpl in IHtyps2.
unfold equiv,
complement in *.
match_destr_in neq;
intuition congruence.
+
specialize (
IHtyps1 v);
simpl in IHtyps1.
unfold equiv,
complement in *.
match_destr_in neq.
*
destruct (
x₂ ==
v); [
congruence | ].
match_destr_in neq;
intuition congruence.
*
intuition congruence.
*
destruct (
x₂ ==
v); [
congruence | ].
specialize (
IHtyps2 v);
simpl in IHtyps2.
unfold equiv,
complement in *.
match_destr_in neq;
intuition congruence.
}
Qed.
Lemma nnrs_imp_stmt_env_preserves_some {
s σ
c σ σ' } :
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ =
Some σ' ->
Forall2 (
preserves_Some snd) σ σ'.
Proof.
revert σ σ'.
induction s;
simpl;
intros σ σ'
eqq1;
simpl.
-
invcs eqq1;
reflexivity.
-
apply some_olift in eqq1.
destruct eqq1 as [?
eqq1 eqq2].
specialize (
IHs1 _ _ eqq1).
specialize (
IHs2 _ _ (
symmetry eqq2)).
etransitivity;
eauto.
-
repeat match_option_in eqq1.
invcs eqq1.
apply Forall2_preserves_Some_snd_update_first.
-
match_option_in eqq1;
subst.
+
apply some_olift in eqq1.
destruct eqq1 as [?
eqq1 eqq2].
apply some_lift in eqq1.
destruct eqq1 as [?
eqq1 ?];
subst.
match_option_in eqq2.
destruct p;
try discriminate.
invcs eqq2.
specialize (
IHs _ _ eqq).
invcs IHs;
trivial.
+
match_option_in eqq1.
destruct p;
try discriminate.
invcs eqq1.
specialize (
IHs _ _ eqq).
invcs IHs;
trivial.
-
match_option_in eqq1.
destruct d;
try discriminate.
clear eqq.
revert σ σ'
eqq1.
induction l;
intros σ σ'
eqq1.
+
invcs eqq1;
reflexivity.
+
match_option_in eqq1.
destruct p;
try discriminate.
specialize (
IHs _ _ eqq).
specialize (
IHl _ _ eqq1).
invcs IHs.
etransitivity;
eauto.
-
match_option_in eqq1.
destruct d;
try discriminate.
clear eqq.
destruct b;
eauto.
-
match_option_in eqq1.
destruct d;
try discriminate
;
clear eqq
;
match_option_in eqq1
;
destruct p;
simpl in *;
try discriminate
;
invcs eqq1.
+
specialize (
IHs1 _ _ eqq).
invcs IHs1;
trivial.
+
specialize (
IHs2 _ _ eqq).
invcs IHs2;
trivial.
Qed.
Lemma nnrs_imp_stmt_preserves_has_some_parts_skip alreadydefined σ
c s σ₁ σ₂ σ₁' σ₂' :
nnrs_imp_stmt_eval brand_relation_brands σ
c s (σ₁++σ₂) =
Some (σ₁'++σ₂') ->
domain σ₁ =
domain σ₁' ->
has_some_parts alreadydefined σ₂ ->
has_some_parts alreadydefined σ₂'.
Proof.
Lemma nnrs_imp_stmt_preserves_has_some_parts alreadydefined σ
c s σ σ' :
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ =
Some σ' ->
has_some_parts alreadydefined σ ->
has_some_parts alreadydefined σ'.
Proof.
Lemma has_some_parts_cons_some {
A B} {
dec:
EqDec A eq}
alreadydefined (σ:
list (
A*
option B))
v x :
has_some_parts alreadydefined σ ->
has_some_parts (
v ::
alreadydefined) ((
v,
Some x) :: σ).
Proof.
intros.
constructor.
-
simpl.
destruct (
v ==
v); [ |
congruence].
trivial.
-
revert H.
apply Forall_impl;
simpl;
intros a inn.
destruct (
a ==
v);
trivial.
Qed.
Lemma has_some_parts_cons_none {
A B} {
dec:
EqDec A eq}
alreadydefined (σ:
list (
A*
option B))
v :
has_some_parts alreadydefined σ ->
has_some_parts (
remove equiv_dec v alreadydefined) ((
v,
None) :: σ).
Proof.
unfold has_some_parts.
repeat rewrite Forall_forall.
intros F x inn.
apply remove_inv in inn.
destruct inn as [
inn neq].
simpl.
destruct (
x ==
v);
try congruence.
apply F;
trivial.
Qed.
Lemma nnrs_imp_stmt_assigns_has_some_parts {σ
c s σ σ'} :
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ =
Some σ' ->
forall ll,
has_some_parts (
filter (
fun x =>
nnrs_imp_stmt_var_usage s x ==
b VarMustBeAssigned)
ll) σ' .
Proof.
Theorem typed_nnrs_imp_stmt_yields_typed_data {σ
c σ} {Γ
c Γ} {
alreadydefined} (
s:
nnrs_imp_stmt) :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
has_some_parts alreadydefined σ ->
(
forall x,
nnrs_imp_stmt_var_usage s x =
VarMayBeUsedWithoutAssignment ->
In x alreadydefined) ->
[ Γ
c ; Γ ⊢
s ] ->
exists σ',
(
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ) =
Some σ'
/\
pd_bindings_type σ' Γ
/\
has_some_parts (
alreadydefined
++
(
filter (
fun x =>
nnrs_imp_stmt_var_usage s x ==
b VarMustBeAssigned))
(
domain Γ))
σ'.
Proof.
intros typσ
c typσ
hasparts enoughdefined typs.
revert alreadydefined σ
typσ
hasparts enoughdefined.
dependent induction typs;
simpl;
intros alreadydefined σ
typσ
hasparts enoughdefined.
-
rewrite false_filter_nil.
+
rewrite app_nil_r;
eauto.
+
intuition.
-
specialize (
IHtyps1 _ _ typσ
hasparts).
cut_to IHtyps1; [ |
intros ?
eqq1;
apply enoughdefined;
rewrite eqq1;
trivial].
destruct IHtyps1 as [σ' [
eqq1 [
typσ'
hasparts']]].
unfold var in *;
rewrite eqq1;
simpl.
specialize (
IHtyps2 _ _ typσ'
hasparts').
cut_to IHtyps2.
+
destruct IHtyps2 as [σ'' [
eqq2 [
typσ''
hasparts'']]].
rewrite eqq2.
eexists;
split;
try reflexivity.
split;
trivial.
unfold has_some_parts in *.
repeat rewrite Forall_forall in *.
intros x inn.
specialize (
hasparts''
x).
repeat rewrite in_app_iff in *.
destruct inn as [
inn|
inn]; [
tauto | ].
repeat rewrite filter_In in *.
match_destr.
destruct o;
trivial.
intuition.
destruct (
nnrs_imp_stmt_var_usage s₁
x);
congruence.
+
intros.
rewrite in_app_iff,
filter_In.
specialize (
enoughdefined x).
generalize (
typed_nnrs_imp_stmt_vars_in_ctxt typs2 x);
intros.
match_destr_in enoughdefined
;
intuition congruence.
-
destruct (
typed_nnrs_imp_expr_yields_typed_data_gen typσ
c typσ
hasparts H)
as [
d [
eqq typd]].
{
intros v inn.
apply enoughdefined.
apply nnrs_imp_expr_may_use_free_vars in inn.
rewrite inn;
trivial.
}
rewrite eqq;
simpl.
assert (
typσ
cons:
pd_bindings_type ((
x,
Some d)::σ) ((
x, τ) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
simpl;
trivial.
split;
trivial.
intros ?
eqqq;
invcs eqqq;
eauto. }
assert (
haspartscons:
has_some_parts (
alreadydefined++[
x]) (((
x,
Some d)::σ))).
{
apply Forall_app;
unfold has_some_parts in *;
rewrite Forall_forall in *.
-
simpl;
intros ? ?.
destruct (
equiv_dec x0 x);
trivial.
apply hasparts;
trivial.
-
simpl;
intros ? [?|?];
try contradiction.
destruct (
equiv_dec x0 x);
trivial.
congruence.
}
destruct (
IHtyps _ _ typσ
cons haspartscons)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros y eqqy.
specialize (
enoughdefined y).
rewrite eqqy in enoughdefined.
rewrite in_app_iff;
simpl.
match_destr_in enoughdefined;
eauto.
unfold equiv_decb,
var in enoughdefined.
destruct (
x ==
y);
eauto.
}
unfold var in *;
rewrite eqq1.
invcs typσ';
simpl in *.
destruct H3;
subst.
destruct x0;
simpl in *.
eexists;
split;
try reflexivity.
split;
trivial.
generalize (
nnrs_imp_stmt_preserves_has_some_parts_skip alreadydefined
σ
c s₂ ((
s,
Some d)::
nil) σ ((
s,
o) ::
nil)
l)
;
simpl;
intros pres.
specialize (
pres eqq1 (
eq_refl _)
hasparts).
apply Forall_app;
unfold has_some_parts in *;
trivial.
rewrite Forall_forall in *.
intros x inn;
unfold var in *.
specialize (
hasparts'
x);
simpl in hasparts'.
apply filter_In in inn.
destruct inn as [
inn eqq2].
destruct (
nnrs_imp_expr_may_use e₁
x);
try discriminate.
unfold equiv_decb in *.
destruct (
s ==
x);
try discriminate.
match_destr_in eqq2;
try discriminate.
cut_to hasparts'.
+
destruct (
x ==
s);
try congruence.
+
apply in_app_iff;
right.
match_destr;
simpl; [
right | ]
;
apply filter_In;
rewrite e;
eauto.
-
assert (
typσ
cons:
pd_bindings_type ((
x,
None)::σ) ((
x, τ) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
simpl;
trivial.
split;
trivial.
intros ?
eqqq;
invcs eqqq;
eauto. }
assert (
haspartscons:
has_some_parts (
remove equiv_dec x alreadydefined) (((
x,
None)::σ))).
{
unfold has_some_parts in *;
rewrite Forall_forall in *.
simpl;
intros ?
inn.
apply remove_inv in inn.
destruct inn as [
inn neq].
specialize (
hasparts _ inn).
destruct (
equiv_dec x0 x);
trivial.
congruence.
}
destruct (
IHtyps _ _ typσ
cons haspartscons)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros y eqqy.
apply remove_in_neq; [
congruence | ].
specialize (
enoughdefined y).
rewrite eqqy in enoughdefined.
unfold equiv_decb,
var in *.
destruct (
x ==
y);
eauto 3.
congruence.
}
unfold var in *;
rewrite eqq1.
invcs typσ';
simpl in *.
destruct H3;
subst.
destruct x0;
simpl in *.
eexists;
split;
try reflexivity.
split;
trivial.
generalize (
nnrs_imp_stmt_preserves_has_some_parts_skip alreadydefined
σ
c s₂ ((
s,
None)::
nil) σ ((
s,
o) ::
nil)
l)
;
simpl;
intros pres.
specialize (
pres eqq1 (
eq_refl _)
hasparts).
apply Forall_app;
unfold has_some_parts in *;
trivial.
rewrite Forall_forall in *.
intros x inn;
unfold var in *.
specialize (
hasparts'
x);
simpl in hasparts'.
apply filter_In in inn.
destruct inn as [
inn eqq2].
rewrite in_app_iff in hasparts'.
unfold equiv_decb in *.
destruct (
s ==
x);
try discriminate.
match_destr_in eqq2;
try discriminate.
destruct (
x ==
s);
try congruence.
apply hasparts'.
right.
match_destr;
simpl; [
right | ]
;
apply filter_In;
rewrite e;
eauto.
-
destruct (
typed_nnrs_imp_expr_yields_typed_data_gen typσ
c typσ
hasparts H)
as [
d [
eqq typd]].
{
intros v inn.
apply enoughdefined.
apply nnrs_imp_expr_may_use_free_vars in inn.
rewrite inn;
trivial.
}
rewrite eqq;
simpl.
destruct (
Forall2_lookup_some typσ
H0
(
P:=(
fun xy1 xy2 =>
forall d :
data,
xy1 =
Some d ->
d ▹
xy2)))
as [?[
eqq2 ?]].
rewrite eqq2.
eexists;
split;
try reflexivity.
split.
+
clear H.
revert H0 H1 typd.
revert typσ.
clear;
intros typσ.
induction typσ;
simpl; [
constructor | ];
intros.
destruct H;
destruct y;
destruct x1;
simpl in *;
subst.
destruct (
string_dec x s).
*
invcs H0.
constructor;
trivial;
simpl.
split;
trivial.
intros ?
eqq3;
invcs eqq3;
trivial.
*
constructor;
simpl;
eauto.
apply IHtypσ;
eauto.
+
unfold has_some_parts in *;
rewrite Forall_forall in *;
intros ?
inn.
rewrite in_app_iff in inn.
string_dec_to_equiv.
destruct (
x ==
x1).
*
unfold equiv in *;
subst.
rewrite lookup_update_eq_in;
trivial.
eapply lookup_in_domain;
eauto.
*
rewrite lookup_update_neq;
trivial.
{
destruct inn as [
inn |
inn].
-
apply hasparts;
trivial.
-
apply filter_In in inn.
destruct inn as [
inn eqq1].
match_destr_in eqq1.
unfold equiv_decb,
var in *.
destruct (
x ==
x1); [
congruence | ].
discriminate.
}
-
destruct (
typed_nnrs_imp_expr_yields_typed_data_gen typσ
c typσ
hasparts H)
as [
d [
eqq typd]].
{
intros v inn.
apply enoughdefined.
apply nnrs_imp_expr_may_use_free_vars in inn.
rewrite inn;
trivial.
}
rewrite eqq;
simpl.
clear H eqq.
invcs typd;
rtype_equalizer;
subst.
revert σ
typσ
hasparts.
induction dl;
intros σ
typσ
hasparts.
+
eexists;
split;
try reflexivity.
split;
trivial.
unfold has_some_parts,
var in *.
repeat rewrite Forall_forall in *.
intros y inn.
rewrite in_app_iff in inn.
specialize (
enoughdefined y).
specialize (
hasparts y).
destruct inn as [
inn |
inn].
*
apply hasparts;
trivial.
*
apply filter_In in inn.
destruct inn as [
inn neq].
match_destr_in neq.
unfold equiv_decb in *.
destruct (
x ==
y);
try discriminate.
destruct (
nnrs_imp_stmt_var_usage s₂
y);
try discriminate.
+
invcs H1.
assert (
typσ
cons:
pd_bindings_type ((
x,
Some a)::σ) ((
x, τ) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto.
intros ?
eqqq;
invcs eqqq;
trivial.
}
assert (
haspartscons:
has_some_parts (
alreadydefined++[
x]) (((
x,
Some a)::σ))).
{
apply Forall_app;
unfold has_some_parts in *;
rewrite Forall_forall in *.
-
simpl;
intros ? ?.
destruct (
equiv_dec x0 x);
trivial.
apply hasparts;
trivial.
-
simpl;
intros ? [?|?];
try contradiction.
destruct (
equiv_dec x0 x);
trivial.
congruence.
}
destruct (
IHtyps _ _ typσ
cons haspartscons)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros ?
eqq.
apply in_app_iff;
simpl.
specialize (
enoughdefined x0).
unfold equiv_decb,
var in *.
destruct (
x ==
x0);
unfold equiv in *;
subst;
eauto.
left.
apply enoughdefined.
rewrite eqq.
match_destr.
}
unfold var in *;
rewrite eqq1.
invcs typσ'.
destruct x0;
destruct H4;
simpl in *;
subst.
generalize (
nnrs_imp_stmt_preserves_has_some_parts_skip alreadydefined
σ
c s₂ ((
x,
Some a)::
nil) σ ((
x,
o) ::
nil)
l)
;
simpl;
intros pres.
specialize (
pres eqq1 (
eq_refl _)
hasparts).
specialize (
IHdl H3 _ H5 pres).
destruct IHdl as [σ' [
eqq2 [
pd2 hp2]]].
rewrite eqq2.
eexists;
split;
try reflexivity.
split;
trivial.
-
destruct (
typed_nnrs_imp_expr_yields_typed_data_gen typσ
c typσ
hasparts H)
as [
d [
eqq typd]].
{
intros v inn.
apply enoughdefined.
apply nnrs_imp_expr_may_use_free_vars in inn.
rewrite inn;
trivial.
}
rewrite eqq;
simpl.
clear H eqq.
invcs typd.
destruct b.
+
destruct (
IHtyps1 _ _ typσ
hasparts)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros y inn.
specialize (
enoughdefined y).
match_destr_in enoughdefined;
eauto.
rewrite inn in enoughdefined.
eauto.
}
rewrite eqq1.
eexists;
split;
try reflexivity.
split;
trivial.
unfold has_some_parts in *;
rewrite Forall_forall in *;
intros ?
inn.
specialize (
hasparts'
x).
repeat rewrite in_app_iff in *.
apply hasparts'.
destruct inn as [
inn |
inn]; [
eauto | ].
apply filter_In in inn.
destruct inn as [
inn neq].
match_destr_in neq.
right;
apply filter_In.
split;
trivial.
unfold equiv_decb,
var in *.
destruct (
nnrs_imp_stmt_var_usage s₁
x);
simpl;
trivial
;
destruct (
nnrs_imp_stmt_var_usage s₂
x);
simpl;
trivial.
+
destruct (
IHtyps2 _ _ typσ
hasparts)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros y inn.
specialize (
enoughdefined y).
match_destr_in enoughdefined;
eauto.
rewrite inn in enoughdefined.
match_destr_in enoughdefined;
eauto.
}
rewrite eqq1.
eexists;
split;
try reflexivity.
split;
trivial.
unfold has_some_parts in *;
rewrite Forall_forall in *;
intros ?
inn.
specialize (
hasparts'
x).
repeat rewrite in_app_iff in *.
apply hasparts'.
destruct inn as [
inn |
inn]; [
eauto | ].
apply filter_In in inn.
destruct inn as [
inn neq].
match_destr_in neq.
right;
apply filter_In.
split;
trivial.
unfold equiv_decb,
var in *.
destruct (
nnrs_imp_stmt_var_usage s₁
x);
simpl;
trivial
;
destruct (
nnrs_imp_stmt_var_usage s₂
x);
simpl;
trivial.
-
destruct (
typed_nnrs_imp_expr_yields_typed_data_gen typσ
c typσ
hasparts H)
as [
d [
eqq typd]].
{
intros v inn.
apply enoughdefined.
apply nnrs_imp_expr_may_use_free_vars in inn.
rewrite inn;
trivial.
}
rewrite eqq;
simpl.
clear H eqq.
invcs typd;
rtype_equalizer;
subst.
+
assert (
typσ
cons:
pd_bindings_type ((
x₁,
Some d0)::σ) ((
x₁, τ
l) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto.
intros ?
eqqq;
invcs eqqq;
trivial.
}
assert (
haspartscons:
has_some_parts (
alreadydefined++[
x₁]) (((
x₁,
Some d0)::σ))).
{
apply Forall_app;
unfold has_some_parts in *;
rewrite Forall_forall in *.
-
simpl;
intros ? ?.
destruct (
equiv_dec x x₁);
trivial.
apply hasparts;
trivial.
-
simpl;
intros ? [?|?];
try contradiction.
destruct (
equiv_dec x x₁);
trivial.
congruence.
}
destruct (
IHtyps1 _ _ typσ
cons haspartscons)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros ?
eqq.
apply in_app_iff;
simpl.
specialize (
enoughdefined x).
unfold equiv_decb,
var in *.
destruct (
x₁ ==
x);
unfold equiv in *;
subst;
eauto.
left.
apply enoughdefined.
rewrite eqq.
match_destr.
}
unfold var in *;
rewrite eqq1.
invcs typσ'.
destruct x;
destruct H3;
simpl in *;
subst.
generalize (
nnrs_imp_stmt_preserves_has_some_parts_skip alreadydefined
σ
c s₁ ((
x₁,
Some d0)::
nil) σ ((
x₁,
o) ::
nil)
l)
;
simpl;
intros pres.
specialize (
pres eqq1 (
eq_refl _)
hasparts).
eexists;
split;
try reflexivity.
split;
trivial.
apply Forall_app;
unfold has_some_parts in *;
trivial.
rewrite Forall_forall in *.
intros x inn;
unfold var in *.
specialize (
hasparts'
x);
simpl in hasparts'.
apply filter_In in inn.
destruct inn as [
inn eqq2].
rewrite in_app_iff in hasparts'.
match_destr_in eqq2;
try discriminate.
unfold equiv_decb,
var in *.
destruct (
x₁ ==
x)
;
destruct (
x₂ ==
x);
try discriminate
;
case_eq (
nnrs_imp_stmt_var_usage s₁
x);
intros eqq3;
try rewrite eqq3 in *;
try discriminate
;
case_eq (
nnrs_imp_stmt_var_usage s₂
x);
intros eqq4;
try rewrite eqq4 in *;
try discriminate.
destruct (
x ==
x₁);
try congruence.
apply hasparts'.
right.
match_destr;
simpl; [
right | ]
;
apply filter_In
;
rewrite eqq3;
simpl;
eauto.
+
assert (
typσ
cons:
pd_bindings_type ((
x₂,
Some d0)::σ) ((
x₂, τ
r) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto.
intros ?
eqqq;
invcs eqqq;
trivial.
}
assert (
haspartscons:
has_some_parts (
alreadydefined++[
x₂]) (((
x₂,
Some d0)::σ))).
{
apply Forall_app;
unfold has_some_parts in *;
rewrite Forall_forall in *.
-
simpl;
intros ? ?.
destruct (
equiv_dec x x₂);
trivial.
apply hasparts;
trivial.
-
simpl;
intros ? [?|?];
try contradiction.
destruct (
equiv_dec x x₂);
trivial.
congruence.
}
destruct (
IHtyps2 _ _ typσ
cons haspartscons)
as [σ' [
eqq1 [
typσ'
hasparts']]].
{
intros ?
eqq.
apply in_app_iff;
simpl.
specialize (
enoughdefined x).
unfold equiv_decb,
var in *.
destruct (
x₂ ==
x);
unfold equiv in *;
subst;
eauto.
left.
apply enoughdefined.
rewrite eqq.
repeat match_destr.
}
unfold var in *;
rewrite eqq1.
invcs typσ'.
destruct x;
destruct H3;
simpl in *;
subst.
generalize (
nnrs_imp_stmt_preserves_has_some_parts_skip alreadydefined
σ
c s₂ ((
x₂,
Some d0)::
nil) σ ((
x₂,
o) ::
nil)
l)
;
simpl;
intros pres.
specialize (
pres eqq1 (
eq_refl _)
hasparts).
eexists;
split;
try reflexivity.
split;
trivial.
apply Forall_app;
unfold has_some_parts in *;
trivial.
rewrite Forall_forall in *.
intros x inn;
unfold var in *.
specialize (
hasparts'
x);
simpl in hasparts'.
apply filter_In in inn.
destruct inn as [
inn eqq2].
rewrite in_app_iff in hasparts'.
match_destr_in eqq2;
try discriminate.
unfold equiv_decb,
var in *.
destruct (
x₁ ==
x)
;
destruct (
x₂ ==
x);
try discriminate
;
case_eq (
nnrs_imp_stmt_var_usage s₁
x);
intros eqq3;
try rewrite eqq3 in *;
try discriminate
;
case_eq (
nnrs_imp_stmt_var_usage s₂
x);
intros eqq4;
try rewrite eqq4 in *;
try discriminate.
destruct (
x ==
x₂);
try congruence.
apply hasparts'.
right.
match_destr;
simpl; [
right | ]
;
apply filter_In
;
rewrite eqq4;
simpl;
eauto.
Qed.
Theorem nnrs_imp_stmt_eval_preserves_types {σ
c σ} {Γ
c Γ} (
s:
nnrs_imp_stmt) :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
[ Γ
c ; Γ ⊢
s ] ->
forall σ',
nnrs_imp_stmt_eval brand_relation_brands σ
c s σ =
Some σ' ->
pd_bindings_type σ' Γ.
Proof.
intros typσ
c typσ
typs.
revert σ
typσ.
dependent induction typs;
simpl;
intros σ
typσ σ'
eqq.
-
invcs eqq;
eauto.
-
apply some_olift in eqq.
destruct eqq as [?
eqq1 eqq2].
specialize (
IHtyps1 _ typσ
_ eqq1).
specialize (
IHtyps2 _ IHtyps1 _ (
symmetry eqq2)).
trivial.
-
apply some_olift in eqq.
destruct eqq as [?
eqq1 eqq2].
apply some_lift in eqq1.
destruct eqq1 as [?
eqq1 ?];
subst.
match_option_in eqq2.
destruct p;
try discriminate.
invcs eqq2.
apply IHtyps in eqq.
+
invcs eqq;
trivial.
+
constructor;
trivial;
simpl.
split;
trivial.
intros ?
eqq2;
invcs eqq2.
eapply nnrs_imp_expr_eval_preserves_types;
eauto.
-
match_option_in eqq.
destruct p;
try discriminate.
invcs eqq.
apply IHtyps in eqq0.
+
invcs eqq0;
trivial.
+
constructor;
trivial;
simpl.
intuition;
discriminate.
-
match_option_in eqq.
match_option_in eqq.
invcs eqq.
eapply nnrs_imp_expr_eval_preserves_types in eqq0;
eauto.
clear H.
unfold pd_bindings_type in *.
induction typσ;
simpl.
+
constructor.
+
destruct x0.
destruct y.
simpl in *.
destruct H as [??];
simpl in *;
subst.
match_destr;
constructor;
simpl;
eauto.
invcs eqq1.
split;
trivial.
intros ?
eqq1;
invcs eqq1.
invcs H0;
trivial.
-
match_option_in eqq.
eapply nnrs_imp_expr_eval_preserves_types in eqq0;
eauto.
destruct d;
try discriminate.
invcs eqq0;
rtype_equalizer;
subst.
revert σ
typσ σ'
eqq H2.
induction l;
simpl;
intros σ
typσ σ'
eqq eqq1.
+
invcs eqq;
trivial.
+
match_option_in eqq.
invcs eqq1.
destruct p;
try discriminate.
apply IHtyps in eqq0.
*
apply IHl in eqq;
trivial.
invcs eqq0;
trivial.
*
constructor;
simpl;
eauto.
split;
trivial;
intros ?
eqq1;
invcs eqq1;
trivial.
-
match_option_in eqq.
eapply nnrs_imp_expr_eval_preserves_types in eqq0;
eauto.
invcs eqq0.
destruct b;
eauto.
-
match_option_in eqq.
eapply nnrs_imp_expr_eval_preserves_types in eqq0;
eauto.
invcs eqq0;
rtype_equalizer;
subst
;
match_option_in eqq
;
destruct p;
try discriminate
;
invcs eqq.
+
eapply IHtyps1 in eqq0.
*
invcs eqq0;
trivial.
*
econstructor;
simpl;
eauto.
split;
trivial;
intros ?
eqq1;
invcs eqq1;
trivial.
+
eapply IHtyps2 in eqq0.
*
invcs eqq0;
trivial.
*
econstructor;
simpl;
eauto.
split;
trivial;
intros ?
eqq1;
invcs eqq1;
trivial.
Qed.
Lemma typed_nnrs_imp_yields_typed_data_aux {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists o,
nnrs_imp_eval brand_relation_brands σ
c si =
Some o
/\ (
forall d,
o =
Some d ->
d ▹ τ)
/\ (
nnrs_imp_stmt_var_usage (
fst si) (
snd si) ==
b VarMustBeAssigned =
true ->
exists d,
o =
Some d).
Proof.
destruct si as [
q ret];
simpl.
intros typσ
c [
neq typq].
destruct (@
typed_nnrs_imp_stmt_yields_typed_data
σ
c [(
ret,
None)]
Γ
c [(
ret, τ)]
nil q)
as [σ' [
eqq1 [
typσ'
eqq]]]
;
simpl;
trivial ;
try solve[
constructor].
-
constructor;
trivial.
simpl;
intuition discriminate.
-
generalize (
typed_nnrs_imp_stmt_vars_in_ctxt typq);
intros.
simpl in H.
specialize (
H x).
cut_to H.
+
destruct H;
trivial.
subst.
congruence.
+
congruence.
-
rewrite eqq1.
invcs typσ'.
destruct x;
simpl in *.
eexists;
split;
try reflexivity.
intros;
subst;
intuition.
unfold has_some_parts in eqq.
rewrite H1 in eqq.
simpl in eqq.
invcs eqq.
unfold var in *.
destruct (
equiv_dec ret ret);
try congruence.
destruct o;
try contradiction.
eauto.
Qed.
Theorem typed_nnrs_imp_yields_typed_data {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists o,
nnrs_imp_eval brand_relation_brands σ
c si =
Some o
/\
forall d,
o =
Some d ->
d ▹ τ.
Proof.
Theorem typed_nnrs_imp_yields_typed_data_used {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
nnrs_imp_returns si ->
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists d,
nnrs_imp_eval brand_relation_brands σ
c si =
Some (
Some d)
/\
d ▹ τ.
Proof.
Theorem nnrs_imp_eval_preserves_types {σ
c} {Γ
c τ} (
si:
nnrs_imp) :
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
forall d,
nnrs_imp_eval brand_relation_brands σ
c si =
Some (
Some d) ->
d ▹ τ.
Proof.
intros bt typ d eqq.
destruct si as [
s ret].
destruct typ as [
ne typ].
assert (
pd:
pd_bindings_type [(
ret,
None)]
[(
ret, τ)]).
{
constructor;
simpl;
eauto.
intuition;
discriminate.
}
unfold nnrs_imp_eval in eqq.
match_option_in eqq.
repeat (
destruct p;
try discriminate).
invcs eqq.
generalize (
nnrs_imp_stmt_eval_preserves_types s bt pd typ _ eqq0);
intros pd2.
invcs pd2;
simpl in *.
intuition eauto.
Qed.
Theorem typed_nnrs_imp_top_yields_typed_data {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
bindings_type σ
c Γ
c ->
[
rec_sort Γ
c ⊢
si ▷ τ ] ->
forall d,
nnrs_imp_eval_top brand_relation_brands σ
c si =
Some d
->
d ▹ τ.
Proof.
Theorem typed_nnrs_imp_top_yields_typed_data_used {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
nnrs_imp_returns si ->
bindings_type σ
c Γ
c ->
[
rec_sort Γ
c ⊢
si ▷ τ ] ->
exists d,
nnrs_imp_eval_top brand_relation_brands σ
c si =
Some d
/\
d ▹ τ.
Proof.
Theorem nnrs_imp_top_eval_preserves_types {σ
c} {Γ
c τ} (
si:
nnrs_imp) :
bindings_type σ
c Γ
c ->
[
rec_sort Γ
c ⊢
si ▷ τ ] ->
forall d,
nnrs_imp_eval_top brand_relation_brands σ
c si =
Some d ->
d ▹ τ.
Proof.
Section sem.
Theorem typed_nnrs_imp_yields_typed_data_sem {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists o,
[
brand_relation_brands , σ
c ⊢
si ⇓
o ]
/\
forall d,
o =
Some d ->
d ▹ τ.
Proof.
Theorem typed_nnrs_imp_yields_typed_data_used_sem {σ
c} {Γ
c} {τ} {
si:
nnrs_imp}:
nnrs_imp_returns si ->
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists d,
[
brand_relation_brands , σ
c ⊢
si ⇓
Some d ]
/\
d ▹ τ.
Proof.
End sem.
Global Instance nnrs_imp_expr_type_lookup_equiv_prop :
Proper (
eq ==>
lookup_equiv ==>
eq ==>
eq ==>
iff)
nnrs_imp_expr_type.
Proof.
Global Instance nnrs_imp_stmt_type_lookup_equiv_prop :
Proper (
eq ==>
lookup_equiv ==>
eq ==>
iff)
nnrs_imp_stmt_type.
Proof.
Local Hint Constructors nnrs_imp_stmt_type :
qcert.
cut (
Proper (
eq ==>
lookup_equiv ==>
eq ==>
impl)
nnrs_imp_stmt_type)
;
unfold Proper,
respectful,
iff,
impl;
intros;
subst;
[
unfold lookup_equiv in *;
intuition;
eauto | ].
rename x0 into Γ₁.
rename y0 into Γ₂.
rename y1 into s.
rename H0 into Γ
eqq.
rename H2 into typ.
revert Γ₁ Γ₂ Γ
eqq typ.
induction s;
simpl;
intros Γ₁ Γ₂ Γ
eqq typ
;
qtrivial
;
invcs typ
;
try solve [
econstructor;
qtrivial
; [
try solve [
rewrite <- Γ
eqq;
qeauto] | .. ]
;
first [
eapply IHs |
eapply IHs1 |
eapply IHs2]
;
qeauto;
unfold lookup_equiv;
simpl;
intros;
match_destr
].
-
econstructor;
eauto
;
rewrite <- Γ
eqq;
eauto.
Qed.
Lemma nnrs_imp_expr_type_lookup_equiv_on {Γ
c Γ₁
e τ} :
[ Γ
c ; Γ₁ ⊢
e ▷ τ ] ->
forall Γ₂,
lookup_equiv_on (
nnrs_imp_expr_free_vars e) Γ₁ Γ₂ ->
[ Γ
c ; Γ₂ ⊢
e ▷ τ ].
Proof.
revert Γ₁ τ.
induction e;
intros Γ₁ τ
typ Γ₂
leo
;
invcs typ;
simpl in *;
subst;
econstructor;
eauto 3.
-
rewrite <-
leo;
simpl;
tauto.
-
eapply IHe1;
eauto.
unfold lookup_equiv_on in *;
intuition.
-
eapply IHe2;
eauto.
unfold lookup_equiv_on in *;
intuition.
Qed.
Lemma nnrs_imp_stmt_type_lookup_equiv_on {Γ
c Γ₁
s} :
[ Γ
c ; Γ₁ ⊢
s ] ->
forall Γ₂,
lookup_equiv_on (
nnrs_imp_stmt_free_vars s) Γ₁ Γ₂ ->
[ Γ
c ; Γ₂ ⊢
s ].
Proof.
Lemma nnrs_imp_expr_type_has_free_vars {Γ
c Γ
e τ} :
[Γ
c; Γ ⊢
e ▷ τ] ->
incl (
nnrs_imp_expr_free_vars e) (
domain Γ).
Proof.
intros typ x inn.
revert τ
typ inn.
induction e;
simpl;
intros τ
typ inn
;
try contradiction
;
invcs typ
;
repeat rewrite in_app_iff in *
;
intuition eauto.
-
apply lookup_in_domain in H1.
subst;
trivial.
Qed.
Lemma nnrs_imp_stmt_type_has_free_vars {Γ
c Γ
s} :
[Γ
c; Γ ⊢
s] ->
incl (
nnrs_imp_stmt_free_vars s) (
domain Γ).
Proof.
intros typ x inn.
revert Γ
typ inn.
induction s;
simpl;
intros Γ
typ inn
;
try contradiction
;
invcs typ
;
repeat rewrite in_app_iff in *
;
intuition eauto
;
try solve [
eapply nnrs_imp_expr_type_has_free_vars;
eauto]
;
simpl in *
;
try contradiction
;
try solve [
apply remove_inv in H
;
intuition eauto
;
specialize (
IHs _ H4)
;
simpl in IHs
;
intuition].
-
apply lookup_in_domain in H3.
subst;
trivial.
-
apply remove_inv in H0.
intuition eauto.
specialize (
IHs1 _ H6).
simpl in IHs1.
intuition.
-
apply remove_inv in H0.
intuition eauto.
specialize (
IHs2 _ H7).
simpl in IHs2.
intuition.
Qed.
Lemma nnrs_imp_expr_type_impl_free_vars_incl (Γ
c :
tbindings)
e₁
e₂ τ:
(
forall (Γ :
pd_tbindings),
[Γ
c; Γ ⊢
e₁ ▷ τ] ->
[Γ
c; Γ ⊢
e₂ ▷ τ]) ->
forall Γ,
[Γ
c; Γ ⊢
e₁ ▷ τ] ->
incl (
nnrs_imp_expr_free_vars e₂) (
nnrs_imp_expr_free_vars e₁).
Proof.
Lemma nnrs_imp_stmt_type_impl_free_vars_incl Γ
c s₁
s₂:
(
forall (Γ :
pd_tbindings),
[Γ
c; Γ ⊢
s₁] ->
[Γ
c; Γ ⊢
s₂]) ->
forall Γ,
[Γ
c; Γ ⊢
s₁] ->
incl (
nnrs_imp_stmt_free_vars s₂) (
nnrs_imp_stmt_free_vars s₁).
Proof.
Section swap.
Lemma nnrs_imp_expr_type_swap Γ
c l Γ
e v₁
v₂ τ₁ τ₂ τ
o:
v₁ <>
v₂ ->
[ Γ
c ;
l++(
v₁,τ₁)::(
v₂, τ₂)::Γ ⊢
e ▷ τ
o ] ->
[ Γ
c ;
l++(
v₂,τ₂)::(
v₁, τ₁)::Γ ⊢
e ▷ τ
o ].
Proof.
Lemma nnrs_imp_stmt_type_swap Γ
c l Γ
s v₁
v₂ τ₁ τ₂:
v₁ <>
v₂ ->
[ Γ
c ;
l++(
v₁,τ₁)::(
v₂, τ₂)::Γ ⊢
s ] ->
[ Γ
c ;
l++(
v₂,τ₂)::(
v₁, τ₁)::Γ ⊢
s ].
Proof.
End swap.
Section unused.
Lemma nnrs_imp_expr_type_unused_remove Γ
c l Γ
e v τ τ
o:
(
In v (
domain l) \/
~
In v (
nnrs_imp_expr_free_vars e)) ->
[ Γ
c ;
l++(
v,τ)::Γ ⊢
e ▷ τ
o ] ->
[ Γ
c ;
l++Γ ⊢
e ▷ τ
o ].
Proof.
Lemma nnrs_imp_stmt_type_unused_remove Γ
c l Γ
s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_imp_stmt_free_vars s)) ->
[ Γ
c ;
l++(
v,τ)::Γ ⊢
s ] ->
[ Γ
c ;
l++Γ ⊢
s ].
Proof.
Lemma nnrs_imp_expr_type_unused_add Γ
c l Γ
e v τ
o:
(
In v (
domain l) \/
~
In v (
nnrs_imp_expr_free_vars e)) ->
[ Γ
c ;
l++Γ ⊢
e ▷ τ
o ] ->
forall τ,
[ Γ
c ;
l++(
v,τ)::Γ ⊢
e ▷ τ
o ].
Proof.
Lemma nnrs_imp_stmt_type_unused_add Γ
c l Γ
s v:
(
In v (
domain l) \/
~
In v (
nnrs_imp_stmt_free_vars s)) ->
[ Γ
c ;
l++Γ ⊢
s ] ->
forall τ,
[ Γ
c ;
l++(
v,τ)::Γ ⊢
s ].
Proof.
Lemma nnrs_imp_expr_type_unused_irrelevant Γ
c l Γ
e v τ₁ τ
o:
(
In v (
domain l) \/
~
In v (
nnrs_imp_expr_free_vars e)) ->
[ Γ
c ;
l++(
v,τ₁)::Γ ⊢
e ▷ τ
o ] ->
forall τ₂,
[ Γ
c ;
l++(
v,τ₂)::Γ ⊢
e ▷ τ
o ].
Proof.
Lemma nnrs_imp_stmt_type_unused_irrelevant Γ
c l Γ
s v τ₁ :
(
In v (
domain l) \/
~
In v (
nnrs_imp_stmt_free_vars s)) ->
[ Γ
c ;
l++(
v,τ₁)::Γ ⊢
s ] ->
forall τ₂,
[ Γ
c ;
l++(
v,τ₂)::Γ ⊢
s ].
Proof.
Section update.
Lemma nnrs_imp_expr_type_update_first_irrelevant Γ
c l Γ τ
o e v :
(
In v (
domain l) \/
~
In v (
nnrs_imp_expr_free_vars e)) ->
[ Γ
c ;
l++ Γ ⊢
e ▷ τ
o ] ->
forall τ,
[ Γ
c ;
l++
update_first equiv_dec Γ
v τ ⊢
e ▷ τ
o ].
Proof.
Lemma nnrs_imp_stmt_type_update_first_irrelevant Γ
c l Γ
s v :
(
In v (
domain l) \/
~
In v (
nnrs_imp_stmt_free_vars s)) ->
[ Γ
c ;
l++ Γ ⊢
s ] ->
forall τ,
[ Γ
c ;
l++
update_first equiv_dec Γ
v τ ⊢
s ].
Proof.
End update.
End unused.
End TNNRSimp.
Notation "[ Γ
c ; Γ ⊢
e ▷ τ ]" := (
nnrs_imp_expr_type Γ
c Γ
e τ) :
nnrs_imp_scope.
Notation "[ Γ
c ; Γ ⊢
s ]" := (
nnrs_imp_stmt_type Γ
c Γ
s) :
nnrs_imp_scope.
Notation "[ Γ
c ⊢
si ▷ τ ]" := (
nnrs_imp_type Γ
c si τ) :
nnrs_imp_scope.