Require Import String.
Require Import List.
Require Import Arith.
Require Import Program.
Require Import EquivDec.
Require Import Morphisms.
Require Import Utils.
Require Import DataSystem.
Require Import NNRS.
Require Import NNRSEval.
Require Import NNRSSem.
Require Import NNRSSemEval.
Require Import NNRSVars.
Import ListNotations.
Local Open Scope list_scope.
Section TNNRS.
Typing rules for NNRS
Context {
m:
basic_model}.
Definition pd_tbindings :=
list (
string*
option rtype).
Definition mc_tbindings :=
list (
string*
rtype).
Definition md_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 pd_bindings_type (
b:
pd_bindings) (
t:
pd_tbindings)
:=
Forall2 (
fun xy1 xy2 =>
(
fst xy1) = (
fst xy2)
/\
lift2Pr data_type (
snd xy1) (
snd xy2))
b t.
Definition mc_bindings_type (
b:
mc_bindings) (
t:
mc_tbindings)
:=
Forall2 (
fun xy1 xy2 =>
(
fst xy1) = (
fst xy2)
/\
Forall (
fun d =>
data_type d (
snd xy2)) (
snd xy1))
b t.
Definition md_bindings_type (
b:
md_bindings) (
t:
md_tbindings)
:=
Forall2 (
fun xy1 xy2 =>
(
fst xy1) = (
fst xy2)
/\
forall d,
Some d =
snd xy1 ->
data_type d (
snd xy2))
b t.
Section typ.
Context (Γ
c:
tbindings).
Reserved Notation "[ Γ ⊢
e ▷ τ ]".
Inductive nnrs_expr_type :
pd_tbindings ->
nnrs_expr ->
rtype ->
Prop :=
|
type_NNRSGetConstant {τ} Γ
s :
tdot Γ
c s =
Some τ ->
[ Γ ⊢
NNRSGetConstant s ▷ τ ]
|
type_NNRSVar {τ} Γ
v :
lookup equiv_dec Γ
v =
Some (
Some τ) ->
[ Γ ⊢
NNRSVar v ▷ τ ]
|
type_NNRSConst {τ} Γ
c :
normalize_data brand_relation_brands c ▹ τ ->
[ Γ ⊢
NNRSConst c ▷ τ ]
|
type_NNRSBinop {τ₁ τ₂ τ} Γ
b e₁
e₂ :
binary_op_type b τ₁ τ₂ τ ->
[ Γ ⊢
e₁ ▷ τ₁ ] ->
[ Γ ⊢
e₂ ▷ τ₂ ] ->
[ Γ ⊢
NNRSBinop b e₁
e₂ ▷ τ ]
|
type_NNRSUnop {τ₁ τ} Γ
u e :
unary_op_type u τ₁ τ ->
[ Γ ⊢
e ▷ τ₁ ] ->
[ Γ ⊢
NNRSUnop u e ▷ τ ]
|
type_NNRSGroupBy {τ
l k pf} Γ
g sl e :
sublist sl (
domain τ
l) ->
[ Γ ⊢
e ▷
Coll (
Rec k τ
l pf) ] ->
[ Γ ⊢
NNRSGroupBy g sl e ▷
GroupBy_type g sl k τ
l pf ]
where
"[ Γ ⊢
e ▷ τ ]" := (
nnrs_expr_type Γ
e τ) :
nnrs_scope
.
Notation "[ Γ ⊢
e ▷ τ ]" := (
nnrs_expr_type Γ
e τ) :
nnrs_scope.
Fixpoint nnrs_stmt_must_assign (
s:
nnrs_stmt) (
x:
var) :
Prop
:=
match s with
|
NNRSSeq s₁
s₂ =>
nnrs_stmt_must_assign s₁
x \/
nnrs_stmt_must_assign s₂
x
|
NNRSLet v e₁
s₂ =>
nnrs_stmt_must_assign s₂
x
|
NNRSLetMut v s₁
s₂ =>
(
v <>
x /\
nnrs_stmt_must_assign s₁
x) \/
nnrs_stmt_must_assign s₂
x
|
NNRSLetMutColl v s₁
s₂ =>
nnrs_stmt_must_assign s₁
x \/
nnrs_stmt_must_assign s₂
x
|
NNRSAssign v e =>
v =
x
|
NNRSPush v e =>
False
|
NNRSFor v e s₀ =>
False
|
NNRSIf e s₁
s₂ =>
nnrs_stmt_must_assign s₁
x /\
nnrs_stmt_must_assign s₂
x
|
NNRSEither e x₁
s₁
x₂
s₂ =>
nnrs_stmt_must_assign s₁
x /\
nnrs_stmt_must_assign s₂
x
end.
Reserved Notation "[ Γ , Δ
c , Δ
d ⊢
s ]".
Inductive nnrs_stmt_type :
pd_tbindings ->
mc_tbindings ->
md_tbindings ->
nnrs_stmt ->
Prop :=
|
type_NNRSSeq Γ Δ
c Δ
d s₁
s₂ :
[ Γ , Δ
c , Δ
d ⊢
s₁ ] ->
[ Γ , Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSSeq s₁
s₂ ]
|
type_NNRSLet Γ Δ
c Δ
d τ
x e₁
s₂ :
[ Γ ⊢
e₁ ▷ τ ] ->
[ (
x,
Some τ)::Γ , Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSLet x e₁
s₂ ]
|
type_NNRSLetMutDef Γ Δ
c Δ
d τ
x s₁
s₂ :
nnrs_stmt_must_assign s₁
x ->
[ Γ , Δ
c , (
x,τ)::Δ
d ⊢
s₁ ] ->
[ (
x,
Some τ)::Γ, Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSLetMut x s₁
s₂ ]
|
type_NNRSLetMutNotUsed Γ Δ
c Δ
d x τ
s₁
s₂ :
[ Γ , Δ
c , (
x,τ)::Δ
d ⊢
s₁ ] ->
[ (
x,
None)::Γ, Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSLetMut x s₁
s₂ ]
|
type_NNRSLetMutColl Γ Δ
c Δ
d τ
x s₁
s₂ :
[ Γ , (
x,τ)::Δ
c , Δ
d ⊢
s₁ ] ->
[ (
x,
Some (
Coll τ))::Γ, Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSLetMutColl x s₁
s₂ ]
|
type_NNRSAssign Γ Δ
c Δ
d τ
x e :
[ Γ ⊢
e ▷ τ ] ->
lookup string_dec Δ
d x =
Some τ ->
[ Γ , Δ
c , Δ
d ⊢
NNRSAssign x e ]
|
type_NNRSPush Γ Δ
c Δ
d τ
x e :
[ Γ ⊢
e ▷ τ ] ->
lookup string_dec Δ
c x =
Some τ ->
[ Γ , Δ
c , Δ
d ⊢
NNRSPush x e ]
|
type_NNRSFor Γ Δ
c Δ
d τ
x e₁
s₂ :
[ Γ ⊢
e₁ ▷
Coll τ ] ->
[ (
x,
Some τ)::Γ , Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSFor x e₁
s₂ ]
|
type_NNRSIf Γ Δ
c Δ
d e s₁
s₂ :
[ Γ ⊢
e ▷
Bool] ->
[ Γ , Δ
c , Δ
d ⊢
s₁ ] ->
[ Γ , Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSIf e s₁
s₂ ]
|
type_NNRSEither Γ Δ
c Δ
d τ
l τ
r e x₁
s₁
x₂
s₂ :
[ Γ ⊢
e ▷
Either τ
l τ
r] ->
[ (
x₁,
Some τ
l)::Γ , Δ
c , Δ
d ⊢
s₁ ] ->
[ (
x₂,
Some τ
r)::Γ , Δ
c , Δ
d ⊢
s₂ ] ->
[ Γ , Δ
c , Δ
d ⊢
NNRSEither e x₁
s₁
x₂
s₂ ]
where
"[ Γ , Δ
c , Δ
d ⊢
s ]" := (
nnrs_stmt_type Γ Δ
c Δ
d s) :
nnrs_scope
.
Notation "[ Γ , Δ
c , Δ
d ⊢
s ]" := (
nnrs_stmt_type Γ Δ
c Δ
d s) :
nnrs_scope.
End typ.
Notation "[ Γ
c ; Γ ⊢
e ▷ τ ]" := (
nnrs_expr_type Γ
c Γ
e τ) :
nnrs_scope.
Notation "[ Γ
c ; Γ , Δ
c , Δ
d ⊢
s ]" := (
nnrs_stmt_type Γ
c Γ Δ
c Δ
d s) :
nnrs_scope.
Local Open Scope nnrs.
Definition nnrs_type Γ
c (
si:
nnrs) τ
:=
let (
s,
ret) :=
si in
[ Γ
c ;
nil ,
nil , (
ret, τ)::
nil ⊢
s ].
Notation "[ Γ
c ⊢
si ▷ τ ]" := (
nnrs_type Γ
c si τ) :
nnrs_scope.
Lemma typed_nnrs_expr_yields_typed_data {σ
c Γ
c} {σ Γ} {
e τ} :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
[ Γ
c ; Γ ⊢
e ▷ τ ] ->
exists d,
nnrs_expr_eval brand_relation_brands σ
c σ
e =
Some d
/\
d ▹ τ.
Proof.
Theorem typed_nnrs_expr_yields_typed_data_compute {σ
c Γ
c} {σ Γ} {
e τ} :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
[ Γ
c ; Γ ⊢
e ▷ τ ] ->
{
d |
nnrs_expr_eval brand_relation_brands σ
c σ
e =
Some d
&
d ▹ τ}.
Proof.
Lemma nnrs_stmt_md_preserves_some {
s σ
c σ ψ
c ψ
d σ' ψ
c' ψ
d'} :
nnrs_stmt_eval brand_relation_brands σ
c σ ψ
c ψ
d s =
Some (σ', ψ
c', ψ
d') ->
Forall2 (
preserves_Some snd) ψ
d ψ
d'.
Proof.
revert σ ψ
c ψ
d σ' ψ
c' ψ
d'.
induction s;
simpl;
intros σ ψ
c ψ
d σ' ψ
c' ψ
d'
eqq1;
simpl.
-
match_option_in eqq1.
destruct p as [[??]?].
specialize (
IHs1 _ _ _ _ _ _ eqq).
specialize (
IHs2 _ _ _ _ _ _ eqq1).
etransitivity;
eauto.
-
repeat match_option_in eqq1.
destruct p as [[??]?].
destruct p;
try discriminate.
invcs eqq1.
apply (
IHs _ _ _ _ _ _ eqq0).
-
match_option_in eqq1.
destruct p as [[??]?].
destruct m1;
try discriminate.
destruct p0;
simpl in *.
specialize (
IHs1 _ _ _ _ _ _ eqq);
subst.
invcs IHs1.
match_option_in eqq1.
destruct p0 as [[??]?].
destruct p0;
simpl in *;
try discriminate.
invcs eqq1.
specialize (
IHs2 _ _ _ _ _ _ eqq0);
subst.
etransitivity;
eauto.
-
match_option_in eqq1.
destruct p as [[??]?].
destruct m0;
try discriminate.
destruct p0;
simpl in *.
specialize (
IHs1 _ _ _ _ _ _ eqq);
subst.
match_option_in eqq1.
destruct p0 as [[??]?].
destruct p0;
simpl in *;
try discriminate.
invcs eqq1.
specialize (
IHs2 _ _ _ _ _ _ eqq0);
subst.
etransitivity;
eauto.
-
match_option_in eqq1.
match_option_in eqq1.
invcs eqq1.
apply Forall2_preserves_Some_snd_update_first.
-
match_option_in eqq1.
match_option_in eqq1.
invcs eqq1.
reflexivity.
-
match_option_in eqq1.
destruct d;
try discriminate.
clear eqq.
revert σ ψ
c ψ
d σ' ψ
c' ψ
d'
eqq1.
induction l;
intros σ ψ
c ψ
d σ' ψ
c' ψ
d'
eqq1.
+
invcs eqq1;
reflexivity.
+
match_option_in eqq1.
destruct p as [[??]?].
destruct p;
try discriminate.
specialize (
IHs _ _ _ _ _ _ eqq).
specialize (
IHl _ _ _ _ _ _ eqq1).
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 as [[??]?]
;
destruct p;
simpl in *;
try discriminate
;
invcs eqq1
;
eauto.
Qed.
Lemma nnrs_stmt_md_preserves_some2 {
s σ
c σ ψ
c ψ
d σ' ψ
c' ψ
d'} :
nnrs_stmt_eval brand_relation_brands σ
c σ ψ
c ψ
d s =
Some (σ', ψ
c', ψ
d') ->
Forall2 (
fun d1 d2 =>
fst d1 =
fst d2 /\
flip (
preserves_Some id) (
snd d1) (
snd d2)) ψ
d' ψ
d.
Proof.
Lemma nnrs_stmt_preserves_md_some_cons {
s x σ
c σ ψ
c i ψ
d σ' ψ
c'
o l} :
nnrs_stmt_eval brand_relation_brands σ
c σ ψ
c ((
x,
Some i) :: ψ
d)
s =
Some (σ', ψ
c', (
x,
o) ::
l) ->
exists d,
o =
Some d.
Proof.
Lemma nnrs_stmt_must_assign_assigns {
s x σ
c σ ψ
c ψ
d σ' ψ
c' ψ
d'} :
nnrs_stmt_must_assign s x ->
nnrs_stmt_eval brand_relation_brands σ
c σ ψ
c ψ
d s =
Some (σ', ψ
c', ψ
d') ->
In x (
domain ψ
d) ->
exists d,
lookup string_dec ψ
d'
x =
Some (
Some d).
Proof.
revert σ ψ
c ψ
d σ' ψ
c' ψ
d'.
induction s;
simpl;
intros σ ψ
c ψ
d σ' ψ
c' ψ
d'
ma eqq1 inn;
simpl.
-
match_option_in eqq1.
destruct p as [[??]?].
generalize (
nnrs_stmt_md_preserves_some2 eqq1);
intros F.
destruct ma.
+
destruct (
IHs1 _ _ _ _ _ _ H eqq inn).
destruct (
Forall2_lookup_some F H0)
as [
dd [??]].
unfold flip,
id,
preserves_Some in H2.
destruct (
H2 _ (
eq_refl _));
subst.
eauto.
+
apply (
IHs2 _ _ _ _ _ _ H eqq1).
generalize (
nnrs_stmt_eval_mdenv_domain_stack eqq)
;
intros domeq1.
congruence.
-
repeat match_option_in eqq1.
destruct p as [[??]?].
destruct p;
try discriminate.
invcs eqq1.
eauto.
-
match_option_in eqq1.
destruct p as [[??]?].
destruct m1;
try discriminate.
destruct p0.
match_option_in eqq1.
destruct p0 as [[??]?].
destruct p0;
try discriminate.
invcs eqq1.
generalize (
nnrs_stmt_md_preserves_some2 eqq0);
intros F.
destruct ma as [[
neq ma]|
ma].
+
destruct (
IHs1 _ _ _ _ _ _ ma eqq); [
simpl;
eauto | ].
simpl in H.
generalize (
nnrs_stmt_eval_mdenv_domain_stack eqq)
;
intros domeq.
simpl in domeq;
invcs domeq.
match_destr_in H.
*
congruence.
*
destruct (
Forall2_lookup_some F H)
as [
dd [??]].
unfold flip,
id,
preserves_Some in H1.
destruct (
H1 _ (
eq_refl _));
subst.
eauto.
+
apply (
IHs2 _ _ _ _ _ _ ma eqq0).
generalize (
nnrs_stmt_eval_mdenv_domain_stack eqq)
;
intros domeq1.
simpl in domeq1;
invcs domeq1.
congruence.
-
match_option_in eqq1.
destruct p as [[??]?].
destruct m0;
try discriminate.
destruct p0.
match_option_in eqq1.
destruct p0 as [[??]?].
destruct p0;
try discriminate.
invcs eqq1.
generalize (
nnrs_stmt_md_preserves_some2 eqq0);
intros F.
destruct ma as [
ma|
ma].
+
destruct (
IHs1 _ _ _ _ _ _ ma eqq); [
simpl;
eauto | ].
destruct (
Forall2_lookup_some F H)
as [
dd [??]].
unfold flip,
id,
preserves_Some in H1.
destruct (
H1 _ (
eq_refl _));
subst.
eauto.
+
destruct (
IHs2 _ _ _ _ _ _ ma eqq0); [
simpl;
eauto | ];
eauto.
generalize (
nnrs_stmt_eval_mdenv_domain_stack eqq)
;
intros domeq1.
simpl in domeq1;
invcs domeq1.
congruence.
-
repeat match_option_in eqq1.
invcs eqq1.
generalize (
lookup_update_eq_in equiv_dec inn (
n:=
Some d));
intros HH.
unfold equiv_dec,
string_eqdec in *.
eauto.
-
contradiction.
-
contradiction.
-
match_option_in eqq1.
destruct ma as [
ma1 ma2].
destruct d;
try discriminate.
destruct b;
eauto.
-
match_option_in eqq1.
destruct ma as [
ma1 ma2].
destruct d;
try discriminate
;
match_option_in eqq1
;
destruct p as [[??]?]
;
destruct p;
try discriminate
;
invcs eqq1
;
eauto.
Qed.
Lemma nnrs_stmt_must_assign_assigns_cons {
s x σ
c σ ψ
c i ψ
d σ' ψ
c'
o l} :
nnrs_stmt_must_assign s x ->
nnrs_stmt_eval brand_relation_brands σ
c σ ψ
c ((
x,
i) :: ψ
d)
s =
Some (σ', ψ
c', (
x,
o) ::
l) ->
exists d,
o =
Some d.
Proof.
Lemma mc_bindings_type_lookup_back {ψ
c Δ
c τ
d x} :
mc_bindings_type ψ
c Δ
c ->
lookup string_dec Δ
c x =
Some τ
d ->
exists dl,
lookup string_dec ψ
c x =
Some dl
/\
Forall (
fun d =>
d ▹ τ
d)
dl.
Proof.
intro mcb; induction mcb; simpl; try discriminate.
destruct x0; destruct y; destruct H; simpl in *; subst.
match_case; intros.
invcs H1; subst.
eauto.
Qed.
Lemma md_bindings_type_lookup_back {ψ
d Δ
d τ
d x} :
md_bindings_type ψ
d Δ
d ->
lookup string_dec Δ
d x =
Some τ
d ->
exists o,
lookup string_dec ψ
d x =
Some o
/\
forall d :
data,
Some d =
o ->
d ▹ τ
d.
Proof.
intro mdb; induction mdb; simpl; try discriminate.
destruct x0; destruct y; destruct H; simpl in *; subst.
match_case; intros.
invcs H1.
eauto.
Qed.
Lemma mc_bindings_type_update_first_same ψ
c Δ
c x dl τ
d :
mc_bindings_type ψ
c Δ
c ->
lookup string_dec Δ
c x =
Some τ
d ->
Forall (
fun d =>
d ▹ τ
d)
dl ->
mc_bindings_type (
update_first string_dec ψ
c x dl) Δ
c.
Proof.
intro mcb; induction mcb; simpl; try discriminate.
destruct x0; destruct y; destruct H; simpl in *; subst.
match_case; intros.
- invcs H1; subst.
constructor; simpl; intuition.
- constructor; eauto 3.
apply IHmcb; eauto.
Qed.
Lemma md_bindings_type_update_first_same ψ
d Δ
d x d τ
d :
md_bindings_type ψ
d Δ
d ->
lookup string_dec Δ
d x =
Some τ
d ->
d ▹ τ
d ->
md_bindings_type (
update_first string_dec ψ
d x (
Some d)) Δ
d.
Proof.
intro mdb; induction mdb; simpl; try discriminate.
destruct x0; destruct y; destruct H; simpl in *; subst.
match_case; intros.
- invcs H1; subst.
constructor; simpl; intuition.
invcs H1; trivial.
- constructor; eauto 3.
apply IHmdb; eauto.
Qed.
Main lemma for the type correctness of NNNRC
Theorem typed_nnrs_stmt_yields_typed_data {σ
c σ ψ
c ψ
d} {Γ
c Γ Δ
c Δ
d} (
s:
nnrs_stmt) :
bindings_type σ
c Γ
c ->
pd_bindings_type σ Γ ->
mc_bindings_type ψ
c Δ
c ->
md_bindings_type ψ
d Δ
d ->
[ Γ
c ; Γ , Δ
c , Δ
d ⊢
s ] ->
(
exists σ' ψ
c' ψ
d',
(
nnrs_stmt_eval brand_relation_brands σ
c σ ψ
c ψ
d s) =
Some (σ', ψ
c', ψ
d')
/\
pd_bindings_type σ' Γ
/\
mc_bindings_type ψ
c' Δ
c
/\
md_bindings_type ψ
d' Δ
d).
Proof.
intros typσ
c typσ
typψ
c typψ
d typs.
revert σ ψ
c ψ
d typσ
typψ
c typψ
d.
dependent induction typs;
simpl;
intros σ ψ
c ψ
d typσ
typψ
c typψ
d.
-
destruct (
IHtyps1 _ _ _ typσ
typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]].
unfold var in *;
rewrite eqq1.
destruct (
IHtyps2 _ _ _ typσ'
typψ
c'
typψ
d')
as [σ'' [ψ
c'' [ψ
d'' [
eqq2 [
typσ'' [
typψ
c''
typψ
d'']]]]]].
rewrite eqq2.
do 3
eexists;
split;
try reflexivity.
eauto.
-
destruct (
typed_nnrs_expr_yields_typed_data typσ
c typσ
H)
as [
d [
eqq typd]].
rewrite eqq.
assert (
typσ
cons:
pd_bindings_type ((
x,
Some d)::σ) ((
x,
Some τ) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
tauto. }
destruct (
IHtyps _ _ _ typσ
cons typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]].
unfold var in *;
rewrite eqq1.
invcs typσ';
simpl in *.
do 3
eexists;
split;
try reflexivity.
tauto.
-
assert (
typψ
dcons:
md_bindings_type ((
x,
None)::ψ
d) ((
x, τ) :: Δ
d)).
{
unfold md_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
trivial.
intros;
discriminate.
}
destruct (
IHtyps1 _ _ _ typσ
typψ
c typψ
dcons)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]].
unfold var in *;
rewrite eqq1.
invcs typψ
d' ;
simpl in *.
destruct x0;
destruct H3;
simpl in *;
subst.
destruct (
nnrs_stmt_must_assign_assigns_cons H eqq1)
as [
d ?]
;
subst.
assert (
typσ
cons:
pd_bindings_type ((
x,
Some d)::σ') ((
x,
Some τ) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto. }
destruct (
IHtyps2 _ _ _ typσ
cons typψ
c'
H4)
as [σ'' [ψ
c'' [ψ
d'' [
eqq2 [
typσ'' [
typψ
c''
typψ
d'']]]]]].
rewrite eqq2.
destruct σ'';
invcs typσ''.
do 3
eexists;
split;
try reflexivity.
eauto.
-
assert (
typψ
dcons:
md_bindings_type ((
x,
None)::ψ
d) ((
x, τ) :: Δ
d)).
{
unfold md_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
trivial.
intros;
discriminate.
}
destruct (
IHtyps1 _ _ _ typσ
typψ
c typψ
dcons)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]].
unfold var in *;
rewrite eqq1.
invcs typψ
d' ;
simpl in *.
destruct x0;
destruct H2;
simpl in *;
subst.
assert (
typσ
cons:
pd_bindings_type ((
x,
o)::σ') ((
x,
None) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto.
destruct o;
simpl;
trivial. }
destruct (
IHtyps2 _ _ _ typσ
cons typψ
c'
H3)
as [σ'' [ψ
c'' [ψ
d'' [
eqq2 [
typσ'' [
typψ
c''
typψ
d'']]]]]].
rewrite eqq2.
destruct σ'';
invcs typσ''.
do 3
eexists;
split;
try reflexivity.
eauto.
-
assert (
typψ
ccons:
mc_bindings_type ((
x,[])::ψ
c) ((
x, τ) :: Δ
c)).
{
unfold md_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
trivial.
}
destruct (
IHtyps1 _ _ _ typσ
typψ
ccons typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]].
unfold var in *;
rewrite eqq1.
invcs typψ
c' ;
simpl in *.
destruct x0;
destruct H2;
simpl in *;
subst.
assert (
typσ
cons:
pd_bindings_type ((
x,
Some (
dcoll l0))::σ') ((
x,
Some (
Coll τ)) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto.
constructor;
trivial. }
destruct (
IHtyps2 _ _ _ typσ
cons H3 typψ
d')
as [σ'' [ψ
c'' [ψ
d'' [
eqq2 [
typσ'' [
typψ
c''
typψ
d'']]]]]].
rewrite eqq2.
invcs typσ''.
do 3
eexists;
split;
try reflexivity.
eauto.
-
destruct (
typed_nnrs_expr_yields_typed_data typσ
c typσ
H)
as [
d [
eqq typd]].
rewrite eqq.
destruct (
md_bindings_type_lookup_back typψ
d H0)
as [? [
eqq1 ?]].
rewrite eqq1.
do 3
eexists;
split;
try reflexivity.
intuition.
eapply md_bindings_type_update_first_same;
eauto.
-
destruct (
typed_nnrs_expr_yields_typed_data typσ
c typσ
H)
as [
d [
eqq typd]].
rewrite eqq.
destruct (
mc_bindings_type_lookup_back typψ
c H0)
as [
dd [
eqq1 typdd]].
rewrite eqq1.
do 3
eexists;
split;
try reflexivity.
intuition.
eapply mc_bindings_type_update_first_same;
eauto.
apply Forall_app;
trivial.
constructor;
trivial.
-
destruct (
typed_nnrs_expr_yields_typed_data typσ
c typσ
H)
as [
d [
eqq typd]].
rewrite eqq.
invcs typd;
rtype_equalizer;
subst.
clear eqq H.
revert σ ψ
c ψ
d typσ
typψ
c typψ
d.
induction dl;
intros σ ψ
c ψ
d typσ
typψ
c typψ
d.
+
do 3
eexists;
split;
try reflexivity.
eauto.
+
invcs H2.
assert (
typσ
cons:
pd_bindings_type ((
x,
Some a)::σ) ((
x,
Some τ) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto. }
destruct (
IHtyps _ _ _ typσ
cons typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]].
unfold var in *;
rewrite eqq1.
invcs typσ' ;
simpl in *.
destruct (
IHdl H3 _ _ _ H5 typψ
c'
typψ
d')
as [σ'' [ψ
c'' [ψ
d'' [
eqq2 [
typσ'' [
typψ
c''
typψ
d'']]]]]].
unfold var in *;
rewrite eqq2.
do 3
eexists;
split;
try reflexivity.
eauto.
-
destruct (
typed_nnrs_expr_yields_typed_data typσ
c typσ
H)
as [
d [
eqq typd]].
rewrite eqq.
invcs typd.
destruct b.
+
destruct (
IHtyps1 _ _ _ typσ
typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]]
;
unfold var in *;
rewrite eqq1.
do 3
eexists;
split;
try reflexivity
;
eauto.
+
destruct (
IHtyps2 _ _ _ typσ
typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq2 [
typσ' [
typψ
c'
typψ
d']]]]]]
;
unfold var in *;
rewrite eqq2.
do 3
eexists;
split;
try reflexivity
;
eauto.
-
destruct (
typed_nnrs_expr_yields_typed_data typσ
c typσ
H)
as [
d [
eqq typd]].
rewrite eqq.
invcs typd;
rtype_equalizer;
subst.
+
assert (
typσ
cons:
pd_bindings_type ((
x₁,
Some d0)::σ) ((
x₁,
Some τ
l) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto. }
destruct (
IHtyps1 _ _ _ typσ
cons typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]]
;
unfold var in *;
rewrite eqq1.
invcs typσ'.
do 3
eexists;
split;
try reflexivity
;
eauto.
+
assert (
typσ
cons:
pd_bindings_type ((
x₂,
Some d0)::σ) ((
x₂,
Some τ
r) :: Γ)).
{
unfold pd_bindings_type in *;
simpl;
constructor;
trivial;
simpl;
split;
auto. }
destruct (
IHtyps2 _ _ _ typσ
cons typψ
c typψ
d)
as [σ' [ψ
c' [ψ
d' [
eqq2 [
typσ' [
typψ
c'
typψ
d']]]]]]
;
unfold var in *;
rewrite eqq2.
invcs typσ'.
do 3
eexists;
split;
try reflexivity
;
eauto.
Qed.
Theorem typed_nnrs_yields_typed_data {σ
c} {Γ
c} {τ} {
si:
nnrs}:
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists o,
nnrs_eval brand_relation_brands σ
c si =
Some o
/\
forall d,
o =
Some d ->
d ▹ τ.
Proof.
destruct si as [
q ret];
simpl.
intros typσ
c typq.
destruct (@
typed_nnrs_stmt_yields_typed_data
σ
c nil nil [(
ret,
None)]
Γ
c nil nil [(
ret, τ)]
q)
as [σ' [ψ
c' [ψ
d' [
eqq1 [
typσ' [
typψ
c'
typψ
d']]]]]]
;
trivial;
try solve[
constructor].
-
constructor;
trivial.
simpl;
intuition discriminate.
-
rewrite eqq1.
invcs typψ
d'.
destruct x;
simpl in *.
eexists;
split;
try reflexivity.
intros;
subst;
intuition.
Qed.
Theorem typed_nnrs_yields_typed_data_used {σ
c} {Γ
c} {τ} {
si:
nnrs}:
nnrs_stmt_must_assign (
fst si) (
snd si) ->
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists d,
nnrs_eval brand_relation_brands σ
c si =
Some (
Some d)
/\
d ▹ τ.
Proof.
Theorem typed_nnrs_top_yields_typed_data {σ
c} {Γ
c} {τ} {
si:
nnrs}:
bindings_type σ
c Γ
c ->
[
rec_sort Γ
c ⊢
si ▷ τ ] ->
forall d,
nnrs_eval_top brand_relation_brands σ
c si =
Some d
->
d ▹ τ.
Proof.
Theorem typed_nnrs_top_yields_typed_data_used {σ
c} {Γ
c} {τ} {
si:
nnrs}:
nnrs_stmt_must_assign (
fst si) (
snd si) ->
bindings_type σ
c Γ
c ->
[
rec_sort Γ
c ⊢
si ▷ τ ] ->
exists d,
nnrs_eval_top brand_relation_brands σ
c si =
Some d
/\
d ▹ τ.
Proof.
Section sem.
Theorem typed_nnrs_yields_typed_data_sem {σ
c} {Γ
c} {τ} {
si:
nnrs}:
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists o,
[
brand_relation_brands , σ
c ⊢
si ⇓
o ]
/\
forall d,
o =
Some d ->
d ▹ τ.
Proof.
Theorem typed_nnrs_yields_typed_data_used_sem {σ
c} {Γ
c} {τ} {
si:
nnrs}:
nnrs_stmt_must_assign (
fst si) (
snd si) ->
bindings_type σ
c Γ
c ->
[ Γ
c ⊢
si ▷ τ ] ->
exists d,
[
brand_relation_brands , σ
c ⊢
si ⇓
Some d ]
/\
d ▹ τ.
Proof.
End sem.
Global Instance nnrs_expr_type_lookup_equiv_prop :
Proper (
eq ==>
lookup_equiv ==>
eq ==>
eq ==>
iff)
nnrs_expr_type.
Proof.
Global Instance nnrs_stmt_type_lookup_equiv_prop :
Proper (
eq ==>
lookup_equiv ==>
lookup_equiv ==>
lookup_equiv ==>
eq ==>
iff)
nnrs_stmt_type.
Proof.
Local Hint Constructors nnrs_stmt_type :
qcert.
cut (
Proper (
eq ==>
lookup_equiv ==>
lookup_equiv ==>
lookup_equiv ==>
eq ==>
impl)
nnrs_stmt_type)
;
unfold Proper,
respectful,
iff,
impl;
intros;
subst;
[
unfold lookup_equiv in *;
intuition;
eauto | ].
rename y3 into s.
rename y into Γ
c.
rename x0 into Γ₁.
rename x1 into Δ
c₁.
rename x2 into Δ
d₁.
rename y0 into Γ₂.
rename y1 into Δ
c₂.
rename y2 into Δ
d₂.
rename H0 into Γ
eqq.
rename H1 into Δ
ceqq.
rename H2 into Δ
deqq.
rename H4 into typ.
revert Γ₁ Δ
c₁ Δ
d₁ Γ₂ Δ
c₂ Δ
d₂ Γ
eqq Δ
ceqq Δ
deqq typ.
induction s;
simpl;
intros Γ₁ Δ
c₁ Δ
d₁ Γ₂ Δ
c₂ Δ
d₂ Γ
eqq Δ
ceqq Δ
deqq typ
;
invcs typ
;
try solve [
econstructor;
trivial
; [
try solve [
rewrite <- Γ
eqq;
eauto] | .. ]
;
first [
eapply IHs |
eapply IHs1 |
eapply IHs2]
;
eauto;
unfold lookup_equiv;
simpl;
intros;
match_destr
].
-
econstructor;
eauto.
+
rewrite <- Γ
eqq;
eauto.
+
rewrite <- Δ
deqq;
eauto.
-
econstructor;
eauto.
+
rewrite <- Γ
eqq;
eauto.
+
rewrite <- Δ
ceqq;
eauto.
Qed.
Section unused.
Local Open Scope nnrs.
Local Hint Constructors nnrs_expr_type :
qcert.
Local Hint Constructors nnrs_stmt_type :
qcert.
Section remove.
Lemma nnrs_expr_type_unused_remove_env Γ
c l Γ
e v τ τ
o:
(
In v (
domain l) \/
~
In v (
nnrs_expr_free_vars e)) ->
[ Γ
c ;
l++(
v,τ)::Γ ⊢
e ▷ τ
o ] ->
[ Γ
c ;
l++Γ ⊢
e ▷ τ
o ].
Proof.
revert l Γ τ
o.
nnrs_expr_cases (
induction e)
Case
;
simpl;
intros ll Γ τ
o inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn
;
eauto 3
with qcert.
-
Case "
NNRSVar"%
string.
econstructor.
repeat rewrite lookup_app in *
;
simpl in *.
match_option
;
rewrite eqq in H1;
try congruence.
apply lookup_none_nin in eqq.
match_destr_in H1;
unfold equiv,
complement in *.
subst;
intuition.
-
Case "
NNRSBinop"%
string.
econstructor;
intuition eauto.
Qed.
Lemma nnrs_stmt_type_unused_remove_env Γ
c l Γ Δ
c Δ
d s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_stmt_free_env_vars s)) ->
[ Γ
c ;
l++(
v,τ)::Γ , Δ
c , Δ
d ⊢
s ] ->
[ Γ
c ;
l++Γ , Δ
c , Δ
d ⊢
s ].
Proof.
Local Hint Resolve nnrs_expr_type_unused_remove_env :
qcert.
revert l Γ Δ
c Δ
d τ.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l Γ Δ
c Δ
d τ
inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn.
-
Case "
NNRSSeq"%
string.
econstructor;
intuition eauto.
-
Case "
NNRSLet"%
string.
econstructor.
+
eapply nnrs_expr_type_unused_remove_env;
eauto.
tauto.
+
specialize (
IHs ((
v0,
Some τ0) ::
l));
simpl in IHs.
eapply IHs;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSLetMut"%
string.
econstructor;
trivial.
+
intuition eauto.
+
specialize (
IHs2 ((
v0,
Some τ0) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSLetMut"%
string.
eapply type_NNRSLetMutNotUsed.
+
intuition eauto.
+
specialize (
IHs2 ((
v0,
None) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSLetMutColl"%
string.
econstructor.
+
intuition eauto.
+
specialize (
IHs2 ((
v0,
Some (
Coll τ0)) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSAssign"%
string.
qeauto.
-
Case "
NNRSPush"%
string.
qeauto.
-
Case "
NNRSFor"%
string.
econstructor.
+
eapply nnrs_expr_type_unused_remove_env;[|
eauto];
tauto.
+
specialize (
IHs ((
v0,
Some τ0) ::
l));
simpl in IHs.
eapply IHs;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSIf"%
string.
econstructor;
intuition qeauto.
-
Case "
NNRSEither"%
string.
econstructor.
+
eapply nnrs_expr_type_unused_remove_env;[|
eauto];
tauto.
+
specialize (
IHs1 ((
v0,
Some τ
l) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition.
destruct (
remove_nin_inv H);
eauto.
+
specialize (
IHs2 ((
v1,
Some τ
r) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition.
destruct (
remove_nin_inv H2);
eauto.
Qed.
Lemma nnrs_stmt_type_unused_remove_mdenv Γ
c l Γ Δ
c Δ
d s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_stmt_free_mdenv_vars s)) ->
[ Γ
c ; Γ , Δ
c ,
l++(
v,τ)::Δ
d ⊢
s ] ->
[ Γ
c ; Γ , Δ
c ,
l++Δ
d ⊢
s ].
Proof.
revert l Γ Δ
c Δ
d τ.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l Γ Δ
c Δ
d τ
inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn
;
try solve [
econstructor;
intuition eauto].
-
Case "
NNRSLetMut"%
string.
econstructor;
trivial.
+
specialize (
IHs1 ((
v0, τ0) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition.
destruct (
remove_nin_inv H0);
eauto.
+
intuition eauto.
-
Case "
NNRSLetMut"%
string.
eapply type_NNRSLetMutNotUsed.
+
specialize (
IHs1 ((
v0, τ0) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition;
destruct (
remove_nin_inv H0);
eauto.
+
intuition eauto.
-
Case "
NNRSAssign"%
string.
econstructor;
eauto.
repeat rewrite lookup_app in *
;
simpl in *.
match_option
;
rewrite eqq in H5;
try congruence.
apply lookup_none_nin in eqq.
match_destr_in H5;
unfold equiv,
complement in *.
subst;
intuition.
Qed.
Lemma nnrs_stmt_type_unused_remove_mcenv Γ
c l Γ Δ
c Δ
d s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_stmt_free_mcenv_vars s)) ->
[ Γ
c ; Γ ,
l++(
v,τ)::Δ
c , Δ
d ⊢
s ] ->
[ Γ
c ; Γ ,
l++Δ
c , Δ
d ⊢
s ].
Proof.
revert l Γ Δ
c Δ
d τ.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l Γ Δ
c Δ
d τ
inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn
;
try solve [
econstructor;
intuition eauto].
-
Case "
NNRSLetMutColl"%
string.
econstructor.
+
specialize (
IHs1 ((
v0, τ0) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition.
destruct (
remove_nin_inv H0);
eauto.
+
intuition eauto.
-
Case "
NNRSPush"%
string.
econstructor;
eauto.
repeat rewrite lookup_app in *
;
simpl in *.
match_option
;
rewrite eqq in H5;
try congruence.
apply lookup_none_nin in eqq.
match_destr_in H5;
unfold equiv,
complement in *.
subst;
intuition.
Qed.
End remove.
Section add.
Lemma nnrs_expr_type_unused_add_env Γ
c l Γ
e v τ τ
o:
(
In v (
domain l) \/
~
In v (
nnrs_expr_free_vars e)) ->
[ Γ
c ;
l++Γ ⊢
e ▷ τ
o ] ->
[ Γ
c ;
l++(
v,τ)::Γ ⊢
e ▷ τ
o ].
Proof.
revert l Γ τ
o.
nnrs_expr_cases (
induction e)
Case
;
simpl;
intros ll Γ τ
o inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn
;
eauto 3
with qcert.
-
Case "
NNRSVar"%
string.
econstructor.
repeat rewrite lookup_app in *
;
simpl in *.
match_option
;
rewrite eqq in H1;
try congruence.
apply lookup_none_nin in eqq.
match_destr;
unfold equiv,
complement in *.
subst;
intuition.
-
Case "
NNRSBinop"%
string.
econstructor;
intuition eauto.
Qed.
Lemma nnrs_stmt_type_unused_add_env Γ
c l Γ Δ
c Δ
d s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_stmt_free_env_vars s)) ->
[ Γ
c ;
l++Γ , Δ
c , Δ
d ⊢
s ] ->
[ Γ
c ;
l++(
v,τ)::Γ , Δ
c , Δ
d ⊢
s ].
Proof.
Local Hint Resolve nnrs_expr_type_unused_add_env :
qcert.
revert l Γ Δ
c Δ
d τ.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l Γ Δ
c Δ
d τ
inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn.
-
Case "
NNRSSeq"%
string.
econstructor;
intuition eauto.
-
Case "
NNRSLet"%
string.
econstructor.
+
eapply nnrs_expr_type_unused_add_env;
eauto.
tauto.
+
specialize (
IHs ((
v0,
Some τ0) ::
l));
simpl in IHs.
eapply IHs;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSLetMut"%
string.
econstructor;
trivial.
+
intuition eauto.
+
specialize (
IHs2 ((
v0,
Some τ0) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSLetMut"%
string.
eapply type_NNRSLetMutNotUsed.
+
intuition eauto.
+
specialize (
IHs2 ((
v0,
None) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSLetMutColl"%
string.
econstructor.
+
intuition eauto.
+
specialize (
IHs2 ((
v0,
Some (
Coll τ0)) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSAssign"%
string.
qeauto.
-
Case "
NNRSPush"%
string.
qeauto.
-
Case "
NNRSFor"%
string.
econstructor.
+
eapply nnrs_expr_type_unused_add_env;[|
eauto];
tauto.
+
specialize (
IHs ((
v0,
Some τ0) ::
l));
simpl in IHs.
eapply IHs;
eauto.
intuition;
destruct (
remove_nin_inv H1);
eauto.
-
Case "
NNRSIf"%
string.
econstructor;
intuition qeauto.
-
Case "
NNRSEither"%
string.
econstructor.
+
eapply nnrs_expr_type_unused_add_env;[|
eauto];
tauto.
+
specialize (
IHs1 ((
v0,
Some τ
l) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition.
destruct (
remove_nin_inv H);
eauto.
+
specialize (
IHs2 ((
v1,
Some τ
r) ::
l));
simpl in IHs2.
eapply IHs2;
eauto.
intuition.
destruct (
remove_nin_inv H2);
eauto.
Qed.
Lemma nnrs_stmt_type_unused_add_mdenv Γ
c l Γ Δ
c Δ
d s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_stmt_free_mdenv_vars s)) ->
[ Γ
c ; Γ , Δ
c ,
l++Δ
d ⊢
s ] ->
[ Γ
c ; Γ , Δ
c ,
l++(
v,τ)::Δ
d ⊢
s ].
Proof.
revert l Γ Δ
c Δ
d τ.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l Γ Δ
c Δ
d τ
inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn
;
try solve [
econstructor;
intuition eauto].
-
Case "
NNRSLetMut"%
string.
econstructor;
trivial.
+
specialize (
IHs1 ((
v0, τ0) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition.
destruct (
remove_nin_inv H0);
eauto.
+
intuition eauto.
-
Case "
NNRSLetMut"%
string.
eapply type_NNRSLetMutNotUsed.
+
specialize (
IHs1 ((
v0, τ0) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition;
destruct (
remove_nin_inv H0);
eauto.
+
intuition eauto.
-
Case "
NNRSAssign"%
string.
econstructor;
eauto.
repeat rewrite lookup_app in *
;
simpl in *.
match_option
;
rewrite eqq in H5;
try congruence.
apply lookup_none_nin in eqq.
match_destr;
unfold equiv,
complement in *.
subst;
intuition.
Qed.
Lemma nnrs_stmt_type_unused_add_mcenv Γ
c l Γ Δ
c Δ
d s v τ:
(
In v (
domain l) \/
~
In v (
nnrs_stmt_free_mcenv_vars s)) ->
[ Γ
c ; Γ ,
l++Δ
c , Δ
d ⊢
s ] ->
[ Γ
c ; Γ ,
l++(
v,τ)::Δ
c , Δ
d ⊢
s ].
Proof.
revert l Γ Δ
c Δ
d τ.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l Γ Δ
c Δ
d τ
inn typ
;
invcs typ
;
repeat rewrite in_app_iff in inn
;
try solve [
econstructor;
intuition eauto].
-
Case "
NNRSLetMutColl"%
string.
econstructor.
+
specialize (
IHs1 ((
v0, τ0) ::
l));
simpl in IHs1.
eapply IHs1;
eauto.
intuition.
destruct (
remove_nin_inv H0);
eauto.
+
intuition eauto.
-
Case "
NNRSPush"%
string.
econstructor;
eauto.
repeat rewrite lookup_app in *
;
simpl in *.
match_option
;
rewrite eqq in H5;
try congruence.
apply lookup_none_nin in eqq.
match_destr;
unfold equiv,
complement in *.
subst;
intuition.
Qed.
End add.
End unused.
Lemma nnrs_stmt_must_assign_is_free s x :
nnrs_stmt_must_assign s x ->
In x (
nnrs_stmt_free_mdenv_vars s).
Proof.
Lemma nnrs_expr_unused_tenv_free_env {Γ
c Γ
e τ}:
[Γ
c; Γ ⊢
e ▷ τ] ->
forall x,
lookup equiv_dec Γ
x =
Some None ->
~
In x (
nnrs_expr_free_vars e).
Proof.
revert τ.
induction e;
simpl
;
intros τ
typ x eqq
;
invcs typ
;
simpl in *
;
repeat rewrite in_app_iff
;
try solve[
intuition eauto].
-
destruct (
v ==
x);
unfold equiv,
complement in *
;
subst;
intuition congruence.
Qed.
Lemma nnrs_expr_type_env_in_none_some {
l1 Γ
c Γ
v e τ} :
[Γ
c;
l1++(
v,
None) :: Γ ⊢
e ▷ τ] ->
~
In v (
domain l1) ->
forall τ',
[Γ
c;
l1++(
v,
Some τ') :: Γ ⊢
e ▷ τ].
Proof.
Local Hint Constructors nnrs_expr_type :
qcert.
revert τ.
induction e;
intros τ
typ nin τ'
;
invcs typ;
qeauto.
econstructor.
repeat rewrite lookup_app in *.
match_destr;
simpl in *.
match_destr.
Qed.
Lemma nnrs_stmt_type_env_in_none_some {
l1 Γ
c Γ Δ
c Δ
d v s} :
[Γ
c;
l1++(
v,
None) :: Γ, Δ
c, Δ
d ⊢
s] ->
~
In v (
domain l1) ->
forall τ,
[Γ
c;
l1++(
v,
Some τ) :: Γ, Δ
c, Δ
d ⊢
s].
Proof.
Local Hint Constructors nnrs_stmt_type :
qcert.
revert l1 Γ Δ
c Δ
d.
nnrs_stmt_cases (
induction s)
Case
;
simpl;
intros l1 Γ Δ
c Δ
d typ nin τ
;
invcs typ.
-
Case "
NNRSSeq"%
string.
qeauto.
-
Case "
NNRSLet"%
string.
econstructor.
+
apply nnrs_expr_type_env_in_none_some;
eauto.
+
destruct (
v ==
v0);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v0,
Some τ0) ::
l1))
in H6
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v0,
Some τ0) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs ((
v0,
Some τ0) ::
l1))
;
simpl;
intuition.
-
Case "
NNRSLetMut"%
string.
econstructor;
eauto.
+
destruct (
v ==
v0);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v0,
Some τ0) ::
l1))
in H7
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v0,
Some τ0) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs2 ((
v0,
Some τ0) ::
l1))
;
simpl;
intuition.
-
Case "
NNRSLetMut"%
string.
eapply type_NNRSLetMutNotUsed;
eauto.
+
destruct (
v ==
v0);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v0,
None) ::
l1))
in H6
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v0,
None) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs2 ((
v0,
None) ::
l1))
;
simpl;
intuition.
-
Case "
NNRSLetMutColl"%
string.
econstructor;
eauto.
+
destruct (
v ==
v0);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v0,
Some (
Coll τ0)) ::
l1))
in H6
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v0,
Some (
Coll τ0)) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs2 ((
v0,
Some (
Coll τ0)) ::
l1))
;
simpl;
intuition.
-
Case "
NNRSAssign"%
string.
econstructor;
eauto.
apply nnrs_expr_type_env_in_none_some;
eauto.
-
Case "
NNRSPush"%
string.
econstructor;
eauto.
apply nnrs_expr_type_env_in_none_some;
eauto.
-
Case "
NNRSFor"%
string.
econstructor.
+
apply nnrs_expr_type_env_in_none_some;
eauto.
+
destruct (
v ==
v0);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v0,
Some τ0) ::
l1))
in H6
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v0,
Some τ0) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs ((
v0,
Some τ0) ::
l1))
;
simpl;
intuition.
-
Case "
NNRSIf"%
string.
econstructor;
eauto.
apply nnrs_expr_type_env_in_none_some;
eauto.
-
Case "
NNRSEither"%
string.
econstructor.
+
apply nnrs_expr_type_env_in_none_some;
eauto.
+
destruct (
v ==
v0);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v0,
Some τ
l) ::
l1))
in H8
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v0,
Some τ
l) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs1 ((
v0,
Some τ
l) ::
l1))
;
simpl;
intuition.
+
destruct (
v ==
v1);
unfold equiv,
complement in *.
*
subst.
apply (
nnrs_stmt_type_unused_remove_env Γ
c ((
v1,
Some τ
r) ::
l1))
in H9
;
simpl;
try tauto.
apply (
nnrs_stmt_type_unused_add_env Γ
c ((
v1,
Some τ
r) ::
l1))
;
simpl;
try tauto.
*
apply (
IHs2 ((
v1,
Some τ
r) ::
l1))
;
simpl;
intuition.
Qed.
Lemma nnrs_stmt_type_env_cons_none_some {Γ
c Γ Δ
c Δ
d v s} :
[Γ
c; (
v,
None) :: Γ, Δ
c, Δ
d ⊢
s] ->
forall τ,
[Γ
c; (
v,
Some τ) :: Γ, Δ
c, Δ
d ⊢
s].
Proof.
End TNNRS.
Notation "[ Γ
c ; Γ ⊢
e ▷ τ ]" := (
nnrs_expr_type Γ
c Γ
e τ) :
nnrs_scope.
Notation "[ Γ
c ; Γ , Δ
c , Δ
d ⊢
s ]" := (
nnrs_stmt_type Γ
c Γ Δ
c Δ
d s) :
nnrs_scope.
Notation "[ Γ
c ⊢
si ▷ τ ]" := (
nnrs_type Γ
c si τ) :
nnrs_scope.