Require Import String.
Require Import List.
Require Import Bool.
Require Import Arith.
Require Import EquivDec.
Require Import Morphisms.
Require Import Permutation.
Require Import Eqdep_dec.
Require Import Utils.
Require Import DataSystem.
Require Import cNNRCSystem.
Require Import NNRCRuntime.
Require Import cNNRCTypes.
Require Import TNNRC.
Section TNNRCStratify.
Context {
m:
basic_model}.
Fixpoint type_substs Γ
c (Γ:
tbindings) (
sdefs:
list (
var*
nnrc)) (τ
defs:
tbindings) :
Prop
:=
match sdefs, τ
defs with
|
nil,
nil =>
True
| (
v₁,
n)::
sdefs', (
v₂, τ)::τ
defs' =>
v₁ =
v₂ /\
nnrc_type Γ
c Γ
n τ
/\
type_substs Γ
c ((
v₂,τ)::Γ)
sdefs' τ
defs'
|
_,
_ =>
False
end.
Lemma type_substs_domain_eq {Γ
c} {Γ:
tbindings} {
sdefs:
list (
var*
nnrc)} {τ
defs:
tbindings} :
type_substs Γ
c Γ
sdefs τ
defs ->
domain sdefs =
domain τ
defs.
Proof.
revert τdefs Γ .
induction sdefs; destruct τdefs; simpl; trivial; intros Γ typ
; try contradiction; destruct a; try contradiction.
destruct p; simpl in *.
intuition; subst.
f_equal.
eauto.
Qed.
Lemma type_substs_app Γ
c Γ
sdefs1 τ
defs1 sdefs2 τ
defs2 :
type_substs Γ
c Γ
sdefs1 τ
defs1 ->
type_substs Γ
c (
rev τ
defs1++Γ)
sdefs2 τ
defs2 ->
type_substs Γ
c Γ (
sdefs1++
sdefs2) (τ
defs1++τ
defs2).
Proof.
revert Γ
sdefs2 τ
defs1 τ
defs2.
induction sdefs1;
simpl;
intros Γ
sdefs2 τ
defs1 τ
defs2 ts1 ts2.
-
match_destr_in ts1;
try contradiction.
-
destruct a.
match_destr_in ts1;
try contradiction.
destruct p.
destruct ts1 as [? [
ts11 ts12]];
subst;
simpl.
repeat (
split;
trivial).
apply IHsdefs1;
trivial.
simpl in ts2.
repeat rewrite app_ass in ts2;
simpl in ts2.
trivial.
Qed.
Lemma stratify1_aux_preserves_types_fw
{
e:
nnrc} {
required_kind:
nnrcKind} {
bound_vars:
list var} {
sdefs1 n sdefs2} :
stratify1_aux e required_kind bound_vars sdefs1 = (
n,
sdefs2) ->
forall τ
defs1 Γ
c Γ τ,
type_substs Γ
c Γ
sdefs1 τ
defs1 ->
nnrc_type Γ
c (
rev τ
defs1 ++ Γ)
e τ ->
exists τ
defs2,
type_substs Γ
c Γ
sdefs2 τ
defs2
/\
nnrc_type Γ
c (
rev τ
defs2 ++ Γ)
n τ.
Proof.
Lemma mk_expr_from_vars_preserves_types_fw
{
n:
nnrc} {
sdefs τ
defs}
{ Γ
c Γ τ} :
type_substs Γ
c Γ
sdefs τ
defs ->
nnrc_type Γ
c (
rev τ
defs ++ Γ)
n τ ->
nnrc_type Γ
c Γ (
mk_expr_from_vars (
n,
sdefs)) τ.
Proof.
unfold mk_expr_from_vars.
revert τ
defs n Γ.
induction sdefs;
intros τ
defs Γ;
destruct τ
defs;
simpl;
intros n typs typn
;
try destruct a as [?
n2];
try contradiction;
trivial.
destruct p as [? τ2].
destruct typs as [? [
typn1 typs]];
subst.
simpl.
unfold nnrc_type in *;
simpl.
rewrite app_ass in typn.
simpl in typn.
simpl in *.
econstructor;
eauto.
Qed.
Lemma stratify_aux_preserves_types_fw
(
e:
nnrc) (
required_kind:
nnrcKind) (
bound_vars:
list var)
n sdefs :
incl (
nnrc_free_vars e)
bound_vars ->
stratify_aux e required_kind bound_vars = (
n,
sdefs) ->
forall Γ
c Γ τ,
nnrc_type Γ
c Γ
e τ ->
exists τ
defs,
type_substs Γ
c Γ
sdefs τ
defs
/\
nnrc_type Γ
c (
rev τ
defs ++ Γ)
n τ.
Proof.
Lemma mk_expr_from_vars_stratify_aux_preserves_types_fw
{Γ
c Γ} (
e:
nnrc) {τ} :
nnrc_type Γ
c Γ
e τ ->
forall (
required_kind:
nnrcKind) (
bound_vars:
list var),
incl (
nnrc_free_vars e)
bound_vars ->
nnrc_type Γ
c Γ (
mk_expr_from_vars (
stratify_aux e required_kind bound_vars)) τ.
Proof.
Theorem stratify_preserves_types_fw
{Γ
c Γ} (
e:
nnrc) {τ} :
nnrc_type Γ
c Γ
e τ ->
nnrc_type Γ
c Γ (
stratify e) τ.
Proof.
Lemma type_substs_app_inv Γ
c Γ
sdefs1 τ
defs1 sdefs2 τ
defs2 :
type_substs Γ
c Γ (
sdefs1++
sdefs2) (τ
defs1++τ
defs2) ->
length sdefs1 =
length τ
defs1 ->
type_substs Γ
c Γ
sdefs1 τ
defs1 /\
type_substs Γ
c (
rev τ
defs1++Γ)
sdefs2 τ
defs2.
Proof.
revert Γ
sdefs2 τ
defs1 τ
defs2.
induction sdefs1;
simpl;
intros Γ
sdefs2 τ
defs1 τ
defs2 ts1 ts2.
-
match_destr;
simpl in *;
qeauto.
-
destruct a.
match_destr;
simpl in *;
try discriminate.
destruct p.
destruct ts1 as [? [
ts11 ts12]];
subst;
simpl.
invcs ts2.
destruct (
IHsdefs1 _ _ _ _ ts12 H0).
repeat (
split;
trivial).
repeat rewrite app_ass;
simpl.
trivial.
Qed.
Lemma type_substs_app_inv_ex {Γ
c Γ
sdefs1 sdefs2 τ
defs} :
type_substs Γ
c Γ (
sdefs1++
sdefs2) τ
defs ->
exists τ
defs1 τ
defs2,
τ
defs = τ
defs1 ++ τ
defs2 /\
type_substs Γ
c Γ
sdefs1 τ
defs1 /\
type_substs Γ
c (
rev τ
defs1++Γ)
sdefs2 τ
defs2.
Proof.
revert Γ
sdefs2 τ
defs.
induction sdefs1;
simpl;
intros Γ
sdefs2 τ
defs ts.
-
exists nil, τ
defs;
simpl;
tauto.
-
destruct a.
match_destr_in ts;
simpl in *;
try contradiction.
destruct p.
destruct ts as [? [
ts11 ts12]];
subst;
simpl.
destruct (
IHsdefs1 _ _ _ ts12)
as [τ
defs1 [τ
defs2 [? [
typs1 typs2]]]];
subst.
exists ((
s,
r)::τ
defs1), τ
defs2;
simpl;
intuition.
repeat rewrite app_ass;
simpl.
trivial.
Qed.
Lemma stratify1_aux_preserves_types_bk
{
e:
nnrc} {
required_kind:
nnrcKind} {
bound_vars:
list var} {
sdefs1 n sdefs2} :
stratify1_aux e required_kind bound_vars sdefs1 = (
n,
sdefs2) ->
forall τ
defs2 Γ
c Γ τ,
type_substs Γ
c Γ
sdefs2 τ
defs2 ->
nnrc_type Γ
c (
rev τ
defs2 ++ Γ)
n τ ->
exists τ
defs1,
type_substs Γ
c Γ
sdefs1 τ
defs1
/\
nnrc_type Γ
c (
rev τ
defs1 ++ Γ)
e τ.
Proof.
Opaque fresh_var.
destruct required_kind;
simpl;
intros eqq;
invcs eqq;
intros.
-
generalize (
type_substs_domain_eq H);
intros deq.
rewrite domain_app in deq;
simpl in deq.
assert (
nnil:τ
defs2 <>
nil).
{
destruct τ
defs2;
simpl in deq;
try discriminate.
symmetry in deq;
apply app_cons_not_nil in deq;
tauto.
}
destruct (
exists_last nnil)
as [τ
defs2' [[
x τ2] ?]];
subst.
rewrite domain_app in deq;
simpl in deq.
apply app_inj_tail in deq.
destruct deq as [
deq ?];
subst.
apply type_substs_app_inv in H.
+
destruct H as [
typs1 typs2].
exists τ
defs2';
split;
trivial.
simpl in typs2.
invcs H0.
rewrite rev_app_distr in H2.
simpl in H2.
match_destr_in H2;
try congruence.
invcs H2.
intuition.
+
rewrite <-
domain_length,
deq,
domain_length;
trivial.
-
qeauto.
Qed.
Lemma mk_expr_from_vars_preserves_types_bk
{
n:
nnrc} {
sdefs}
{ Γ
c Γ τ} :
nnrc_type Γ
c Γ (
mk_expr_from_vars (
n,
sdefs)) τ ->
exists τ
defs,
type_substs Γ
c Γ
sdefs τ
defs /\
nnrc_type Γ
c (
rev τ
defs ++ Γ)
n τ.
Proof.
unfold mk_expr_from_vars.
revert n Γ.
induction sdefs;
simpl;
intros n Γ
typ.
-
exists nil;
simpl;
qeauto.
-
destruct a;
unfold nnrc_type in *;
simpl in *.
invcs typ.
specialize (
IHsdefs _ _ H5).
destruct IHsdefs as [τ
defs [
typs typn]].
exists ((
v,τ₁)::τ
defs);
intuition.
simpl.
rewrite app_ass;
simpl.
trivial.
Qed.
Lemma stratify_aux_preserves_types_bk
(
e:
nnrc) (
required_kind:
nnrcKind) (
bound_vars:
list var)
n sdefs :
incl (
nnrc_free_vars e)
bound_vars ->
stratify_aux e required_kind bound_vars = (
n,
sdefs) ->
forall Γ
c Γ τ
defs,
type_substs Γ
c Γ
sdefs τ
defs ->
forall τ,
nnrc_type Γ
c (
rev τ
defs ++ Γ)
n τ ->
nnrc_type Γ
c Γ
e τ.
Proof.
Lemma mk_expr_from_vars_stratify_aux_preserves_types_bk
{Γ
c Γ} (
e:
nnrc) {τ} :
forall (
required_kind:
nnrcKind) (
bound_vars:
list var),
incl (
nnrc_free_vars e)
bound_vars ->
nnrc_type Γ
c Γ (
mk_expr_from_vars (
stratify_aux e required_kind bound_vars)) τ ->
nnrc_type Γ
c Γ
e τ.
Proof.
Theorem stratify_preserves_types_bk
{Γ
c Γ} (
e:
nnrc) {τ} :
nnrc_type Γ
c Γ (
stratify e) τ ->
nnrc_type Γ
c Γ
e τ.
Proof.
Theorem stratify_preserves_types
Γ
c Γ (
e:
nnrc) τ :
nnrc_type Γ
c Γ
e τ <->
nnrc_type Γ
c Γ (
stratify e) τ.
Proof.
End TNNRCStratify.