Require Import Bool.
Require Import String.
Require Import List.
Require Import Compare_dec.
Require Import Eqdep_dec.
Require Import Program.
Require Import Utils.
Require Import DataSystem.
Require Import cNRAEnv.
Require Import cNRAEnvEq.
Require Import NRASystem.
Import ListNotations.
Local Open Scope list_scope.
Section TcNRAEnv.
Local Open Scope nraenv_core_scope.
Typing for NRA
Section typ.
Context {
m:
basic_model}.
Context (τ
constants:
tbindings).
Inductive nraenv_core_type :
nraenv_core ->
rtype ->
rtype ->
rtype ->
Prop :=
|
type_cNRAEnvGetConstant {τ
env τ
in τ
out}
s :
tdot τ
constants s =
Some τ
out ->
nraenv_core_type (
cNRAEnvGetConstant s) τ
env τ
in τ
out
|
type_cNRAEnvID {τ
env τ} :
nraenv_core_type cNRAEnvID τ
env τ τ
|
type_cNRAEnvConst {τ
env τ
in τ
out}
c :
data_type (
normalize_data brand_relation_brands c) τ
out ->
nraenv_core_type (
cNRAEnvConst c) τ
env τ
in τ
out
|
type_cNRAEnvBinop {τ
env τ
in τ₁ τ₂ τ
out}
b op1 op2 :
binary_op_type b τ₁ τ₂ τ
out ->
nraenv_core_type op1 τ
env τ
in τ₁ ->
nraenv_core_type op2 τ
env τ
in τ₂ ->
nraenv_core_type (
cNRAEnvBinop b op1 op2) τ
env τ
in τ
out
|
type_cNRAEnvUnop {τ
env τ
in τ τ
out}
u op :
unary_op_type u τ τ
out ->
nraenv_core_type op τ
env τ
in τ ->
nraenv_core_type (
cNRAEnvUnop u op) τ
env τ
in τ
out
|
type_cNRAEnvMap {τ
env τ
in τ₁ τ₂}
op1 op2 :
nraenv_core_type op1 τ
env τ₁ τ₂ ->
nraenv_core_type op2 τ
env τ
in (
Coll τ₁) ->
nraenv_core_type (
cNRAEnvMap op1 op2) τ
env τ
in (
Coll τ₂)
|
type_cNRAEnvMapProduct {τ
env τ
in τ₁ τ₂ τ₃}
op1 op2 pf1 pf2 pf3 :
nraenv_core_type op1 τ
env (
Rec Closed τ₁
pf1) (
Coll (
Rec Closed τ₂
pf2)) ->
nraenv_core_type op2 τ
env τ
in (
Coll (
Rec Closed τ₁
pf1)) ->
rec_concat_sort τ₁ τ₂ = τ₃ ->
nraenv_core_type (
cNRAEnvMapProduct op1 op2) τ
env τ
in (
Coll (
Rec Closed τ₃
pf3))
|
type_cNRAEnvProduct {τ
env τ
in τ₁ τ₂ τ₃}
op1 op2 pf1 pf2 pf3 :
nraenv_core_type op1 τ
env τ
in (
Coll (
Rec Closed τ₁
pf1)) ->
nraenv_core_type op2 τ
env τ
in (
Coll (
Rec Closed τ₂
pf2)) ->
rec_concat_sort τ₁ τ₂ = τ₃ ->
nraenv_core_type (
cNRAEnvProduct op1 op2) τ
env τ
in (
Coll (
Rec Closed τ₃
pf3))
|
type_cNRAEnvSelect {τ
env τ
in τ}
op1 op2 :
nraenv_core_type op1 τ
env τ
Bool ->
nraenv_core_type op2 τ
env τ
in (
Coll τ) ->
nraenv_core_type (
cNRAEnvSelect op1 op2) τ
env τ
in (
Coll τ)
|
type_cNRAEnvDefault {τ
env τ
in τ}
op1 op2 :
nraenv_core_type op1 τ
env τ
in (
Coll τ) ->
nraenv_core_type op2 τ
env τ
in (
Coll τ) ->
nraenv_core_type (
cNRAEnvDefault op1 op2) τ
env τ
in (
Coll τ)
|
type_cNRAEnvEither {τ
env τ
l τ
r τ
out}
opl opr :
nraenv_core_type opl τ
env τ
l τ
out ->
nraenv_core_type opr τ
env τ
r τ
out ->
nraenv_core_type (
cNRAEnvEither opl opr) τ
env (
Either τ
l τ
r) τ
out
|
type_cNRAEnvEitherConcat {τ
env τ
in rll pfl rlr pfr rlo pfo lo ro}
op1 op2 pflo pfro :
nraenv_core_type op1 τ
env τ
in (
Either (
Rec Closed rll pfl) (
Rec Closed rlr pfr)) ->
nraenv_core_type op2 τ
env τ
in (
Rec Closed rlo pfo) ->
rec_concat_sort rll rlo =
lo ->
rec_concat_sort rlr rlo =
ro ->
nraenv_core_type (
cNRAEnvEitherConcat op1 op2) τ
env τ
in (
Either (
Rec Closed lo pflo) (
Rec Closed ro pfro))
|
type_cNRAEnvApp {τ
env τ
in τ1 τ2}
op2 op1 :
nraenv_core_type op1 τ
env τ
in τ1 ->
nraenv_core_type op2 τ
env τ1 τ2 ->
nraenv_core_type (
cNRAEnvApp op2 op1) τ
env τ
in τ2
|
type_cNRAEnvEnv {τ
env τ
in} :
nraenv_core_type cNRAEnvEnv τ
env τ
in τ
env
|
type_cNRAEnvAppEnv {τ
env τ
env' τ
in τ2}
op2 op1 :
nraenv_core_type op1 τ
env τ
in τ
env' ->
nraenv_core_type op2 τ
env' τ
in τ2 ->
nraenv_core_type (
cNRAEnvAppEnv op2 op1) τ
env τ
in τ2
|
type_cNRAEnvMapEnv {τ
env τ
in τ₂}
op1 :
nraenv_core_type op1 τ
env τ
in τ₂ ->
nraenv_core_type (
cNRAEnvMapEnv op1) (
Coll τ
env) τ
in (
Coll τ₂).
End typ.
Notation "
Op ▷
A >=>
B ⊣
C ;
E" := (
nraenv_core_type C Op E A B) (
at level 70).
Type lemmas for individual algebraic expressions
Context {
m:
basic_model}.
Lemma lift_map_typed {τ
c} {τ
env τ₁ τ₂ :
rtype}
c (
op1 :
nraenv_core) (
env:
data) (
dl :
list data) :
(
bindings_type c τ
c) ->
(
env ▹ τ
env) ->
(
Forall (
fun d :
data =>
data_type d τ₁)
dl) ->
(
op1 ▷ τ₁ >=> τ₂ ⊣ τ
c; τ
env) ->
(
forall d :
data,
data_type d τ₁ ->
exists x :
data,
brand_relation_brands ⊢ₑ
op1 @ₑ
d ⊣
c;
env =
Some x /\
x ▹ τ₂) ->
exists x :
list data, (
lift_map (
nraenv_core_eval brand_relation_brands c op1 env)
dl =
Some x) /\
data_type (
dcoll x) (
Coll τ₂).
Proof.
intros dt_c;
intros.
induction dl;
simpl;
intros.
-
exists (@
nil data);
split; [
reflexivity|
apply dtcoll;
apply Forall_nil].
-
inversion H0;
clear H0.
elim (
H2 a);
intros;
try assumption.
elim H0;
intros;
clear H0.
rewrite H7;
clear H7.
specialize (
IHdl H6);
clear H6.
elim IHdl;
intros;
clear IHdl.
elim H0;
intros;
clear H0.
dependent induction H7.
rewrite H6.
exists (
x0 ::
x1).
split;
try reflexivity.
apply dtcoll.
apply Forall_cons;
try assumption.
assert (
r = τ₂)
by (
apply rtype_fequal;
assumption).
rewrite <-
H3;
assumption.
Qed.
Lemma lift_map_env_typed {τ
c} {τ
env τ₁ τ₂ :
rtype}
c (
op1 :
nraenv_core) (
x0:
data) (
dl :
list data) :
bindings_type c τ
c ->
(
x0 ▹ τ₁) ->
(
Forall (
fun d :
data =>
data_type d τ
env)
dl) ->
(
op1 ▷ τ₁ >=> τ₂ ⊣ τ
c;τ
env) ->
(
forall env :
data,
data_type env τ
env ->
forall d :
data,
data_type d τ₁ ->
exists x :
data,
brand_relation_brands ⊢ₑ
op1 @ₑ
d ⊣
c;
env =
Some x /\
data_type x τ₂) ->
exists x :
list data, (
lift_map (
fun env' => (
nraenv_core_eval brand_relation_brands c op1 env'
x0))
dl =
Some x) /\
data_type (
dcoll x) (
Coll τ₂).
Proof.
intros dt_c.
induction dl;
simpl;
intros.
-
exists (@
nil data);
split; [
reflexivity|
apply dtcoll;
apply Forall_nil].
-
inversion H0;
clear H0 H4 l H3 x.
elim (
H2 a H5 x0);
intros;
try assumption.
elim H0;
intros;
clear H0.
rewrite H3;
clear H3;
simpl in *.
specialize (
IHdl H H6);
clear H6.
elim IHdl;
intros;
clear IHdl;
trivial.
elim H0;
intros;
clear H0.
dependent induction H6.
rewrite H3;
clear H3;
simpl.
exists (
x2 ::
x1).
split;
try reflexivity.
apply dtcoll.
apply Forall_cons;
try assumption.
assert (
r = τ₂)
by (
apply rtype_fequal;
assumption).
rewrite <-
H3;
assumption.
eauto.
Qed.
Lemma recover_rec k d r τ
pf:
data_type d r ->
`
r =
Rec₀
k
(
map
(
fun x :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x, ` (
snd x))) τ) ->
data_type d (
Rec k τ
pf).
Proof.
intros.
assert (
Rec k τ
pf =
r).
unfold Rec.
apply rtype_fequal.
rewrite H0.
reflexivity.
rewrite H1;
assumption.
Qed.
Lemma recover_rec_forall k l r τ
pf:
Forall (
fun d :
data =>
data_type d r)
l ->
`
r =
Rec₀
k
(
map
(
fun x :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x, ` (
snd x))) τ) ->
Forall (
fun d :
data =>
data_type d (
Rec k τ
pf))
l.
Proof.
Lemma omap_concat_typed_env
(τ
env:
rtype) (τ₁ τ₂ τ₃:
list (
string *
rtype)) (
env:
data) (
dl2:
list data)
(
x :
list (
string *
data))
pf1 pf2 pf3:
(
data_type env τ
env) ->
(
forall x :
data,
In x dl2 ->
data_type x (
Rec Closed τ₂
pf2)) ->
rec_concat_sort τ₁ τ₂ = τ₃ ->
data_type (
drec x) (
Rec Closed τ₁
pf1) ->
(
exists y :
list data,
lift_map (
fun x1 :
data =>
orecconcat (
drec x)
x1)
dl2
=
Some y /\
data_type (
dcoll y) (
Coll (
Rec Closed τ₃
pf3))).
Proof.
Lemma oproduct_typed_env {τ₁ τ₂ τ₃:
list (
string *
rtype)} (
dl dl0:
list data)
pf1 pf2 pf3:
Forall (
fun d :
data =>
data_type d (
Rec Closed τ₂
pf2))
dl0 ->
Forall (
fun d :
data =>
data_type d (
Rec Closed τ₁
pf1))
dl ->
rec_concat_sort τ₁ τ₂ = τ₃ ->
exists x :
list data, (
oproduct dl dl0 =
Some x) /\
data_type (
dcoll x) (
Coll (
Rec Closed τ₃
pf3)).
Proof.
Lemma data_type_concat l1 l2 τ:
data_type (
dcoll l1) (
Coll τ) ->
data_type (
dcoll l2) (
Coll τ) ->
data_type (
dcoll (
l1 ++
l2)) (
Coll τ).
Proof.
intros.
dependent induction H.
dependent induction H0.
apply dtcoll.
apply Forall_app;
rewrite Forall_forall in *;
assert (
r = τ)
by (
apply rtype_fequal;
assumption);
assert (
r0 = τ)
by (
apply rtype_fequal;
assumption);
rewrite H1 in H;
rewrite H2 in H0;
assumption.
Qed.
Lemma omap_product_typed_env {τ
c} {τ
env:
rtype} {τ₁ τ₂ τ₃ :
list (
string *
rtype)} (
op1 :
nraenv_core)
c (
env:
data) (
dl:
list data)
pf1 pf2 pf3:
bindings_type c τ
c ->
env ▹ τ
env ->
rec_concat_sort τ₁ τ₂ = τ₃ ->
Forall (
fun d :
data =>
data_type d (
Rec Closed τ₁
pf1))
dl ->
(
op1 ▷
Rec Closed τ₁
pf1 >=>
Coll (
Rec Closed τ₂
pf2) ⊣ τ
c;τ
env) ->
(
forall d :
data,
data_type d (
Rec Closed τ₁
pf1) ->
exists x :
data,
brand_relation_brands ⊢ₑ
op1 @ₑ
d ⊣
c;
env =
Some x /\
data_type x (
Coll (
Rec Closed τ₂
pf2))) ->
exists x :
list data, (
omap_product (
nraenv_core_eval brand_relation_brands c op1 env)
dl =
Some x) /\
data_type (
dcoll x) (
Coll (
Rec Closed τ₃
pf3)).
Proof.
Lemma omap_product_typed2_env {τ
c} {τ
env:
rtype} {τ₁ τ₂ τ₃ :
list (
string *
rtype)} τ
in c (
op1 :
nraenv_core) (
env:
data)
y (
dl:
list data)
pf1 pf2 pf3:
bindings_type c τ
c ->
env▹ τ
env ->
rec_concat_sort τ₁ τ₂ = τ₃ ->
Forall (
fun d :
data =>
data_type d (
Rec Closed τ₁
pf1))
dl ->
(
op1 ▷ τ
in >=>
Coll (
Rec Closed τ₂
pf2) ⊣ τ
c;τ
env) ->
(
forall d :
data,
data_type d (
Rec Closed τ₁
pf1) ->
exists x :
data,
brand_relation_brands ⊢ₑ
op1 @ₑ
y ⊣
c;
env =
Some x /\
data_type x (
Coll (
Rec Closed τ₂
pf2))) ->
exists x :
list data, (
omap_product (
fun z =>
brand_relation_brands ⊢ₑ
op1@ₑ
y ⊣
c;
env)
dl =
Some x) /\
data_type (
dcoll x) (
Coll (
Rec Closed τ₃
pf3)).
Proof.
Main typing soundness theorem for NRAEnv
Theorem typed_nraenv_core_yields_typed_data {τ
c} {τ
env τ
in τ
out}
c (
env:
data) (
d:
data) (
op:
nraenv_core):
bindings_type c τ
c ->
(
env ▹ τ
env) -> (
d ▹ τ
in) -> (
op ▷ τ
in >=> τ
out ⊣ τ
c;τ
env) ->
(
exists x, (
brand_relation_brands ⊢ₑ
op @ₑ
d ⊣
c;
env =
Some x /\ (
x ▹ τ
out))).
Proof.
intros dt_c Henv.
intros.
revert env Henv d H.
dependent induction H0;
simpl;
intros.
-
unfold tdot in *.
unfold edot in *.
destruct (
Forall2_lookupr_some dt_c H)
as [? [
eqq1 eqq2]].
rewrite eqq1.
eauto.
-
exists d;
split; [
reflexivity|
assumption].
-
exists (
normalize_data brand_relation_brands c0);
split;
try reflexivity.
assumption.
-
elim (
IHnraenv_core_type1 env Henv d H0);
elim (
IHnraenv_core_type2 env Henv d H0);
intros.
elim H1;
elim H2;
intros;
clear H1 H2.
rewrite H3;
simpl.
rewrite H5;
simpl.
apply (
typed_binary_op_yields_typed_data x0 x b H4 H6);
assumption.
-
elim (
IHnraenv_core_type env Henv d H1);
intros.
elim H2;
intros;
clear H2.
rewrite H3.
apply (
typed_unary_op_yields_typed_data x u H4);
assumption.
-
elim (
IHnraenv_core_type2 env Henv d H);
intros;
clear H IHnraenv_core_type2.
elim H0;
intros;
clear H0.
rewrite H;
clear H.
invcs H1.
rtype_equalizer.
subst.
assert (
EE :
exists x :
list data, (
lift_map (
nraenv_core_eval brand_relation_brands c op1 env)
dl =
Some x)
/\
data_type (
dcoll x) (
Coll τ₂)).
+
apply (@
lift_map_typed τ
c τ
env τ₁ τ₂
c op1 env dl dt_c Henv);
trivial.
apply IHnraenv_core_type1;
trivial.
+
destruct EE as [? [
eqq dt]].
simpl.
rewrite eqq;
simpl.
eexists;
split;
try reflexivity.
trivial.
-
elim (
IHnraenv_core_type2 env Henv d H0);
intros;
clear IHnraenv_core_type2 H0.
elim H1;
intros;
clear H1.
rewrite H0;
clear H0.
invcs H2.
assert (
EE :
exists x :
list data, (
omap_product (
nraenv_core_eval brand_relation_brands c op1 env)
dl =
Some x) /\
data_type (
dcoll x) (
Coll (
Rec Closed (
rec_concat_sort τ₁ τ₂)
pf3))).
+
apply (
omap_product_typed_env op1 c env dl pf1 pf2 pf3 dt_c Henv);
try assumption;
try reflexivity.
apply recover_rec_forall with (
r:=
r);
assumption.
apply IHnraenv_core_type1;
assumption.
+
destruct EE as [? [
eqq typ]].
simpl;
rewrite eqq;
simpl.
eexists;
split;
try reflexivity.
trivial.
-
elim (
IHnraenv_core_type1 env Henv d H0);
intros;
clear IHnraenv_core_type1.
elim H1;
intros;
clear H1.
rewrite H2;
clear H2;
invcs H3.
assert (
EE :
exists x :
list data, (
omap_product (
fun _ :
data =>
brand_relation_brands ⊢ₑ
op2 @ₑ
d ⊣
c;
env)
dl =
Some x) /\
data_type (
dcoll x) (
Coll (
Rec Closed (
rec_concat_sort τ₁ τ₂)
pf3))).
+
apply (@
omap_product_typed2_env τ
c τ
env τ₁ τ₂ (
rec_concat_sort τ₁ τ₂) τ
in c op2 env d dl pf1 pf2 pf3);
try assumption;
try reflexivity.
apply recover_rec_forall with (
r:=
r);
assumption.
destruct (
IHnraenv_core_type2 env Henv d H0)
as [? [
eqq dt]].
rewrite eqq.
intros.
eexists;
split;
try reflexivity.
trivial.
+
destruct EE as [? [
eqq typ]].
simpl;
rewrite eqq;
simpl.
eexists;
split;
try reflexivity.
trivial.
-
elim (
IHnraenv_core_type2 env Henv d H);
intros;
clear IHnraenv_core_type2.
elim H0;
intros;
clear H0.
rewrite H1;
clear H1 H0_0.
invcs H2.
rtype_equalizer.
subst.
assert (
exists c2,
(
lift_filter
(
fun x' :
data =>
match brand_relation_brands ⊢ₑ
op1 @ₑ
x' ⊣
c;
env with
|
Some (
dbool b) =>
Some b
|
_ =>
None
end)
dl) =
Some c2 /\
Forall (
fun d :
data =>
data_type d τ)
c2).
+
induction dl.
*
exists (@
nil data).
split.
reflexivity.
apply Forall_nil.
*
rewrite Forall_forall in *;
intros.
assert (
forall x :
data,
In x dl ->
data_type x τ)
by intuition.
assert (
data_type a τ)
by (
simpl in *;
intuition).
destruct (
IHnraenv_core_type1 env Henv a H1)
as [? [
eqq dt]].
simpl;
rewrite eqq;
simpl.
dtype_inverter.
destruct (
IHdl H0)
as [? [
eqq1 dt1]].
rewrite eqq1;
simpl.
assert (
data_type a τ)
by (
simpl in *;
intuition).
destruct x0;
simpl;
eexists;
split;
try reflexivity;
trivial.
constructor;
trivial.
+
destruct H0 as [? [
eqq dt]].
simpl;
rewrite eqq;
simpl.
eexists;
split;
try reflexivity;
trivial.
constructor;
trivial.
-
elim (
IHnraenv_core_type1 env Henv d H);
elim (
IHnraenv_core_type2 env Henv d H);
intros.
elim H0;
elim H1;
intros;
clear H0 H1 H.
rewrite H2.
rewrite H4.
clear H2 H4.
simpl.
invcs H3;
invcs H5;
rtype_equalizer.
subst.
destruct dl.
+
eexists;
split;
try reflexivity;
trivial.
constructor;
trivial.
+
eexists;
split;
try reflexivity;
trivial.
constructor;
trivial.
-
destruct (
data_type_Either_inv H)
as [[
dd[?
ddtyp]]|[
dd[?
ddtyp]]];
subst;
eauto.
-
destruct (
IHnraenv_core_type2 env Henv d H1)
as [? [??]].
rewrite H2.
destruct (
IHnraenv_core_type1 env Henv d H1)
as [? [??]].
rewrite H4.
destruct (
data_type_Rec_inv H3);
subst.
destruct (
data_type_Either_inv H5)
as [[
dd[?
ddtyp]]|[
dd[?
ddtyp]]];
subst;
eauto;
destruct (
data_type_Rec_inv ddtyp);
subst;
(
eexists;
split;[
reflexivity| ];
econstructor;
eapply dtrec_rec_concat_sort;
eauto).
-
elim (
IHnraenv_core_type1 env Henv d H);
intros.
elim H0;
intros;
clear H0 H.
rewrite H1;
simpl.
elim (
IHnraenv_core_type2 env Henv x H2);
intros.
elim H;
intros;
clear H.
rewrite H0;
simpl.
exists x0;
split;[
reflexivity|
assumption].
-
exists env;
split; [
reflexivity|
assumption].
-
elim (
IHnraenv_core_type1 env Henv d H);
intros.
elim H0;
intros;
clear H0.
rewrite H1;
simpl.
elim (
IHnraenv_core_type2 x H2 d H);
intros.
elim H0;
intros;
clear H0.
rewrite H3;
simpl.
exists x0;
split;[
reflexivity|
assumption].
-
intros.
invcs Henv;
rtype_equalizer.
subst;
simpl.
assert (
exists x :
list data, (
lift_map (
fun env' :
data => (
nraenv_core_eval brand_relation_brands c op1 env'
d))
dl =
Some x) /\
data_type (
dcoll x) (
Coll τ₂)).
*
apply (@
lift_map_env_typed τ
c τ
env τ
in τ₂);
try assumption.
*
destruct H1 as [? [
eqq dt]].
rewrite eqq;
simpl.
eexists;
split;
try reflexivity;
trivial.
Qed.
Local Hint Constructors nra_type unary_op_type binary_op_type :
qcert.
Local Hint Resolve ATdot ATnra_data :
qcert.
Corrolaries of the main type soudness theorem
Definition typed_nraenv_core_total {τ
c} {τ
env τ
in τ
out} (
op:
nraenv_core) (
HOpT:
op ▷ τ
in >=> τ
out ⊣ τ
c;τ
env)
c (
env:
data) (
d:
data)
(
dt_c:
bindings_type c τ
c) :
(
env ▹ τ
env) ->
(
d ▹ τ
in) ->
{
x:
data |
x ▹ τ
out }.
Proof.
Definition tnraenv_core_eval {τ
c} {τ
env τ
in τ
out} (
op:
nraenv_core) (
HOpT:
op ▷ τ
in >=> τ
out ⊣ τ
c;τ
env)
c (
env:
data) (
d:
data)
(
dt_c:
bindings_type c τ
c) :
(
env ▹ τ
env) -> (
d ▹ τ
in) ->
data.
Proof.
Theorem typed_nraenv_core_to_typed_nra {τ
c} {τ
env τ
in τ
out} (
op:
nraenv_core):
(
nraenv_core_type τ
c op τ
env τ
in τ
out) -> (
nra_type τ
c (
nra_of_nraenv_core op) (
nra_context_type τ
env τ
in) τ
out).
Proof.
intros.
dependent induction H;
simpl;
intros.
-
unfold nra_bind,
nra_context_type.
econstructor;
eauto.
-
qeauto.
-
qeauto.
-
qeauto.
-
qeauto.
-
apply (@
type_NRAMap m τ
c (
nra_context_type τ
env τ
in) (
nra_context_type τ
env τ₁) τ₂);
try assumption.
eapply ATunnest_two.
eapply (
type_NRAUnop).
qeauto.
unfold nra_wrap_a1,
nra_double.
eapply type_NRABinop.
qeauto.
eapply (
type_NRAUnop).
qeauto.
eapply type_NRAUnop;
qeauto.
eapply type_OpDot.
unfold tdot,
edot;
simpl.
qauto.
eapply (
type_NRAUnop).
qeauto.
eauto.
unfold tdot,
edot;
auto.
reflexivity.
reflexivity.
-
apply (@
type_NRAMap m τ
c (
nra_context_type τ
env τ
in) (
Rec Closed (("
PBIND"%
string, τ
env) :: ("
PDATA"%
string, (
Rec Closed τ₁
pf1)) :: ("
PDATA2"%
string, (
Rec Closed τ₂
pf2)) ::
nil) (
eq_refl _))).
econstructor;
qeauto.
econstructor;
qeauto.
econstructor;
qeauto.
reflexivity.
econstructor;
qeauto.
econstructor;
qeauto.
reflexivity.
apply (@
type_NRAMapProduct m τ
c (
nra_context_type τ
env τ
in)
[("
PBIND"%
string, τ
env); ("
PDATA"%
string,
Rec Closed τ₁
pf1)]
[("
PDATA2"%
string, (
Rec Closed τ₂
pf2))]
[("
PBIND"%
string, τ
env); ("
PDATA"%
string,
Rec Closed τ₁
pf1); ("
PDATA2"%
string,
Rec Closed τ₂
pf2)]
(
NRAMap (
NRAUnop (
OpRec "
PDATA2")
NRAID) (
nra_of_nraenv_core op1))
(
unnest_two "
a1" "
PDATA" (
NRAUnop OpBag (
nra_wrap_a1 (
nra_of_nraenv_core op2))))
eq_refl eq_refl
);
try reflexivity.
qeauto.
unfold nra_wrap_a1.
apply (
ATunnest_two "
a1" "
PDATA" (
NRAUnop OpBag (
nra_double "
PBIND" "
a1"
nra_bind (
nra_of_nraenv_core op2))) τ
c (
nra_context_type τ
env τ
in) [("
PBIND"%
string, τ
env); ("
a1"%
string,
Coll (
Rec Closed τ₁
pf1))]
eq_refl (
Rec Closed τ₁
pf1));
try reflexivity.
apply (@
type_NRAUnop m τ
c (
nra_context_type τ
env τ
in) (
Rec Closed [("
PBIND"%
string, τ
env); ("
a1"%
string,
Coll (
Rec Closed τ₁
pf1))]
eq_refl)).
econstructor;
eauto.
unfold nra_double,
nra_bind.
apply (@
type_NRABinop m τ
c (
nra_context_type τ
env τ
in) (
Rec Closed [("
PBIND"%
string, τ
env)]
eq_refl) (
Rec Closed [("
a1"%
string,
Coll (
Rec Closed τ₁
pf1))]
eq_refl));
try eauto.
econstructor;
qeauto.
econstructor;
qeauto.
econstructor;
qeauto.
-
qeauto.
-
econstructor;
eauto.
2: {
econstructor;
eauto.
eapply ATunnest_two.
+
econstructor;
qeauto.
unfold nra_wrap_a1,
nra_double.
eapply type_NRABinop.
*
econstructor;
reflexivity.
*
econstructor;
qeauto.
econstructor;
qeauto.
eapply type_OpDot;
unfold tdot,
edot;
simpl;
eauto.
*
econstructor;
qeauto.
+
unfold tdot,
edot;
simpl;
eauto.
+
econstructor;
eauto. }
*
econstructor;
qeauto.
eapply type_OpDot;
unfold tdot,
edot;
simpl;
eauto.
-
qeauto.
-
econstructor.
+
econstructor;
try reflexivity.
* {
econstructor.
-
econstructor;
qeauto.
econstructor;
qeauto.
reflexivity.
-
econstructor;
qeauto.
}
* {
econstructor;
qeauto.
-
econstructor;
qeauto.
econstructor;
qeauto.
econstructor;
qeauto.
}
+
econstructor;
qeauto.
-
qeauto.
-
apply (@
type_NRAApp m τ
c (
nra_context_type τ
env τ
in) (
nra_context_type τ
env τ1) τ2).
+
unfold nra_context,
nra_bind,
nra_context_type,
nra_double;
simpl.
unfold nra_wrap.
apply (@
type_NRABinop m τ
c (
Rec Closed [("
PBIND"%
string, τ
env); ("
PDATA"%
string, τ
in)]
eq_refl) (
Rec Closed (("
PBIND"%
string, τ
env)::
nil) (
eq_refl _)) (
Rec Closed (("
PDATA"%
string, τ1)::
nil) (
eq_refl _)));
repeat (
econstructor;
qeauto).
+
trivial.
-
unfold nra_bind,
nra_context_type.
qeauto.
-
apply (@
type_NRAApp m τ
c (
nra_context_type τ
env τ
in) (
nra_context_type τ
env' τ
in) τ2).
+
unfold nra_context,
nra_bind,
nra_context_type,
nra_double;
simpl.
apply (@
type_NRABinop m τ
c (
Rec Closed [("
PBIND"%
string, τ
env); ("
PDATA"%
string, τ
in)]
eq_refl) (
Rec Closed (("
PBIND"%
string, τ
env')::
nil) (
eq_refl _)) (
Rec Closed (("
PDATA"%
string, τ
in)::
nil) (
eq_refl _))).
econstructor;
qeauto.
do 3 (
econstructor;
qeauto).
do 3 (
econstructor;
qeauto).
+
trivial.
-
econstructor;
qeauto.
eapply ATunnest_two.
+
econstructor;
qeauto.
unfold nra_wrap_bind_a1,
nra_double.
eapply type_NRABinop;
qeauto.
*
do 3 (
econstructor;
qeauto).
reflexivity.
+
reflexivity.
+
simpl;
trivial.
Unshelve.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
qeauto.
Qed.
Lemma fold_nra_context_type (
env d: {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true})
pf :
Rec Closed [("
PBIND"%
string,
env); ("
PDATA"%
string,
d)]
pf
=
nra_context_type env d.
Proof.
Ltac defst l
:=
match l with
| @
nil (
string*
rtype₀) =>
constr:(@
nil (
string*
rtype))
|
cons (?
x,
proj1_sig ?
y) ?
l' =>
let l'' :=
defst l'
in
constr:(
cons (
x,
y)
l'')
end.
Ltac rec_proj_simpler
:=
repeat
match goal with
| [
H:
Rec₀ ?
k ?
l =
proj1_sig ?τ |-
_ ] =>
symmetry in H
| [
H:
proj1_sig ?τ =
Rec₀ ?
k ?
l |-
_ ] =>
let ll :=
defst l in
let HH:=
fresh "
eqq"
in
generalize (@
Rec₀
_eq_proj1_Rec _ _ τ
k ll);
intros HH;
simpl in HH;
specialize (
HH H);
clear H;
destruct HH;
try subst τ
end.
Lemma UIP_bool {
a b:
bool} (
pf1 pf2:
a =
b) :
pf1 =
pf2.
Proof.
Ltac nra_inverter_ext
:=
simpl in *;
match goal with
| [
H:@
nra_type _ _ (
unnest_two _ _ _)
_ (
Coll _) |-
_ ] =>
apply ATunnest_two_inv in H;
destruct H as [? [? [? [? [? [? [?[??]]]]]]]]
| [
H:
prod _ _ |-
_ ] =>
destruct H;
simpl in *;
try subst
| [
H:
context [
Rec Closed [("
PBIND"%
string, ?
env); ("
PDATA"%
string, ?
d)] ?
pf ] |-
_ ] =>
unfold rtype in H;
rewrite (
fold_nra_context_type env d pf)
in H
| [
H:
Rec₀ ?
k ?
l =
proj1_sig ?τ |-
_ ] =>
symmetry in H
| [
H:
proj1_sig ?τ =
Rec₀ ?
k ?
l |-
_ ] =>
let ll :=
defst l in
let HH:=
fresh "
eqq"
in
generalize (@
Rec₀
_eq_proj1_Rec _ _ τ
k ll);
intros HH;
simpl in HH;
specialize (
HH H);
clear H;
destruct HH;
try subst τ
| [
H:
proj1_sig _ =
Rec₀
Closed
(
map
(
fun x :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x, ` (
snd x)))
_) |-
_ ]
=>
let Hpf :=
fresh "
spf"
in
apply Rec₀
_eq_proj1_Rec in H;
destruct H as [?
Hpf]
| [
H1:@
eq bool ?
a ?
b,
H2:@
eq bool ?
a ?
b |-
_] =>
destruct (
UIP_bool H1 H2)
end.
Ltac nra_inverter2 :=
repeat (
try unfold nra_wrap,
nra_wrap_a1,
nra_wrap_bind_a1,
nra_context,
nra_double,
nra_bind,
nra_wrap in *; (
nra_inverter_ext ||
nra_inverter);
try subst).
Ltac tdot_inverter :=
repeat
match goal with
| [
H:
tdot _ _ =
Some _ |-
_ ] =>
let HH:=
fresh "
eqq"
in
inversion H as [
HH];
match type of HH with
| ?
x1 = ?
x2 =>
try (
subst x2 ||
subst x1);
clear H
|
_ =>
fail 1
end
end.
Lemma typed_nraenv_core_to_typed_nra_inv' {
k τ
c τ
env τ
in τ
out pf} (
op:
nraenv_core):
nra_type τ
c (
nra_of_nraenv_core op) (
Rec k [("
PBIND"%
string, τ
env); ("
PDATA"%
string, τ
in)]
pf) τ
out ->
nraenv_core_type τ
c op τ
env τ
in τ
out.
Proof.
Local Hint Constructors nraenv_core_type :
qcert.
revert k τ
env τ
in τ
out pf.
induction op;
simpl;
intros.
-
inversion H;
clear H;
subst.
econstructor;
trivial.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
-
nra_inverter2;
try tdot_inverter;
qeauto.
Qed.
Theorem typed_nraenv_core_to_typed_nra_inv {τ
c} {τ
env τ
in τ
out} (
op:
nraenv_core):
nra_type τ
c (
nra_of_nraenv_core op) (
nra_context_type τ
env τ
in) τ
out ->
nraenv_core_type τ
c op τ
env τ
in τ
out.
Proof.
Lemma typed_nraenv_core_const_sort_f {τ
c op τ
env τ
in τ
out} :
nraenv_core_type (
rec_sort τ
c)
op τ
env τ
in τ
out ->
nraenv_core_type τ
c op τ
env τ
in τ
out.
Proof.
revert τ
c op τ
env τ
in τ
out.
induction op;
simpl;
inversion 1;
rtype_equalizer;
subst;
qeauto.
unfold tdot,
edot in *.
rewrite (
assoc_lookupr_drec_sort (
odt:=
ODT_string))
in H1.
econstructor.
apply H1.
Qed.
Lemma typed_nraenv_core_const_sort_b {τ
c op τ
env τ
in τ
out} :
nraenv_core_type τ
c op τ
env τ
in τ
out ->
nraenv_core_type (
rec_sort τ
c)
op τ
env τ
in τ
out.
Proof.
Lemma typed_nraenv_core_const_sort τ
c op τ
env τ
in τ
out :
nraenv_core_type (
rec_sort τ
c)
op τ
env τ
in τ
out <->
nraenv_core_type τ
c op τ
env τ
in τ
out.
Proof.
End TcNRAEnv.
Notation "
Op ▷
A >=>
B ⊣
C ;
E" := (
nraenv_core_type C Op E A B) (
at level 70).
Notation "
Op @▷
d ⊣
C ;
e" := (
tnraenv_core_eval C Op e d) (
at level 70).
Global Hint Constructors nraenv_core_type :
qcert.
Global Hint Constructors unary_op_type :
qcert.
Global Hint Constructors binary_op_type :
qcert.
Ltac nraenv_core_inverter :=
match goal with
| [
H:
Coll _ =
Coll _ |-
_] =>
inversion H;
clear H
| [
H: `?τ₁ =
Coll₀ (`?τ₂) |-
_] =>
rewrite (
Coll_right_inv τ₁ τ₂)
in H;
subst
| [
H:
Coll₀ (`?τ₂) = `?τ₁ |-
_] =>
symmetry in H
| [
H:
cNRAEnvID ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvEnv ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvMap _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvMapProduct _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvMapEnv _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvDefault _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvApp _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvAppEnv _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvEither _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvEitherConcat _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvProduct _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvSelect _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvUnop _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvBinop _ _ _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H:
cNRAEnvConst _ ▷
_ >=>
_ ⊣
_ ;
_ |-
_ ] =>
inversion H;
clear H
| [
H: (
_,
_) = (
_,
_) |-
_ ] =>
inversion H;
clear H
| [
H:
map (
fun x2 :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x2, ` (
snd x2))) ?
x0 = [] |-
_] =>
apply (
map_rtype_nil x0)
in H;
simpl in H;
subst
| [
H: (
map
(
fun x :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x,
proj1_sig (
snd x)))
_)
=
(
map
(
fun x' :
string * {τ₀' :
rtype₀ |
wf_rtype₀ τ₀' =
true} =>
(
fst x',
proj1_sig (
snd x')))
_) |-
_ ] =>
apply map_rtype_fequal in H;
trivial
| [
H:
Rec _ _ _ =
Rec _ _ _ |-
_ ] =>
generalize (
Rec_inv H);
clear H;
intro H;
try subst
| [
H:
context [(
_::
nil) =
map
(
fun x :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x,
proj1_sig (
snd x)))
_] |-
_] =>
symmetry in H
| [
H:
context [
map
(
fun x :
string * {τ₀ :
rtype₀ |
wf_rtype₀ τ₀ =
true} =>
(
fst x,
proj1_sig (
snd x)))
_ = (
_::
nil) ] |-
_] =>
apply map_eq_cons in H;
destruct H as [? [? [? [??]]]]
| [
H:
Coll₀
_ =
Coll₀
_ |-
_ ] =>
inversion H;
clear H
| [
H:
Rec₀
_ _ =
Rec₀
_ _ |-
_ ] =>
inversion H;
clear H
| [
H:
_ ▷
_ >=>
snd ?
x ⊣
_ ;
_ |-
_] =>
destruct x;
simpl in *;
subst
| [
H:
unary_op_type OpBag _ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type OpFlatten _ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type (
OpRec _)
_ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type (
OpDot _)
_ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type (
OpRecProject _)
_ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type (
OpRecRemove _)
_ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type OpLeft _ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
unary_op_type OpRight _ _ |-
_ ] =>
inversion H;
clear H;
subst
| [
H:
binary_op_type OpRecConcat _ _ _ |-
_ ] =>
inversion H;
clear H
| [
H:
binary_op_type OpAnd _ _ _ |-
_ ] =>
inversion H;
clear H
| [
H:
binary_op_type OpRecMerge _ _ _ |-
_ ] =>
inversion H;
clear H
end;
try rtype_equalizer;
try assumption;
try subst;
simpl in *;
try nraenv_core_inverter.
Ltac nraenv_core_inferer :=
try nraenv_core_inverter;
subst;
try qeauto.
Ltac input_well_typed :=
repeat progress
match goal with
| [
HO:?
op ▷ ?τ
in >=> ?τ
out ⊣ ?τ
c ; ?τ
env,
HI:?
x ▹ ?τ
in,
HC:
bindings_type ?
c ?τ
c,
HE:?
env ▹ ?τ
env
|-
context [(
nraenv_core_eval ?
h ?
c ?
op ?
env ?
x)]] =>
let xout :=
fresh "
dout"
in
let xtype :=
fresh "τ
out"
in
let xeval :=
fresh "
eout"
in
destruct (
typed_nraenv_core_yields_typed_data c _ _ op HC HE HI HO)
as [
xout [
xeval xtype]];
rewrite xeval in *;
simpl
end.