Require Import String.
Require Import List.
Require Import Sumbool.
Require Import Arith.
Require Import Bool.
Require Import Eqdep_dec.
Require Import RelationClasses.
Require Import EquivDec.
Require Import Utils.
Require Import Types.
Require Import ForeignData.
Require Import DataModel.
Require Import ForeignDataTyping.
Require Import TData.
Require Import RConsistentSubtype.
Section TDataInfer.
Context {
fdata:
foreign_data}.
Context {
ftype:
foreign_type}.
Context {
fdtyping:
foreign_data_typing}.
Context {
m:
brand_model}.
Fixpoint infer_data_type (
d:
data) :
option rtype
:=
match d with
|
dunit =>
Some Unit
|
dnat n =>
Some Nat
|
dfloat n =>
Some Float
|
dbool b =>
Some Bool
|
dstring s =>
Some String
|
dcoll ld =>
lift Coll
((
fix infer_data_type_dcoll ld :
option rtype
:=
match ld with
|
nil =>
Some ⊥
|
d::
ld' =>
lift2 join (
infer_data_type d) (
infer_data_type_dcoll ld')
end
)
ld)
|
drec lsd =>
match (
fix infer_data_type_drec lsd :
option (
list(
string*
rtype))
:=
match lsd with
|
nil =>
Some nil
| (
s,
d)::
lsd' =>
match (
infer_data_type d), (
infer_data_type_drec lsd')
with
|
Some r,
Some lsr' =>
Some ((
s,
r)::
lsr')
|
_,
_ =>
None
end
end
)
lsd with
|
Some l =>
RecMaybe Closed l
|
None =>
None
end
|
dleft d =>
lift (
fun t =>
Either t ⊥) (
infer_data_type d)
|
dright d =>
lift (
fun t =>
Either ⊥
t) (
infer_data_type d)
|
dbrand b d =>
match is_canon_brands_dec brand_relation_brands b with
|
left pf =>
match infer_data_type d with
|
Some t =>
if subtype_dec t (
brands_type b)
then Some (
Brand b)
else Some ⊤
|
None =>
None
end
|
right _ =>
None
end
|
dforeign df =>
lift Foreign (
foreign_data_typing_infer df)
end.
Lemma infer_data_type_drec_domain {
d:
list (
string*
data)} {
r'} :
(
fix infer_data_type_drec lsd :
option (
list(
string*
rtype))
:=
match lsd with
|
nil =>
Some nil
| (
s,
d)::
lsd' =>
match (
infer_data_type d), (
infer_data_type_drec lsd')
with
|
Some r,
Some lsr' =>
Some ((
s,
r)::
lsr')
|
_,
_ =>
None
end
end
)
d =
Some r' ->
domain d =
domain r'.
Proof.
revert r'.
induction d;
simpl.
-
inversion 1;
subst.
simpl;
trivial.
-
destruct a.
destruct (
infer_data_type d0);
try discriminate.
case_option;
try discriminate.
intros;
simpl in *.
inversion H0;
subst.
simpl;
f_equal.
eauto.
Qed.
Lemma infer_data_type_normalized' {
d} :
data_normalized brand_relation_brands d ->
{τ |
infer_data_type d =
Some τ}.
Proof.
induction d;
intros dn
;
try solve [
simpl;
eexists;
invcs dn;
reflexivity].
-
simpl.
induction c.
+
eexists;
simpl;
reflexivity.
+
invcs H.
destruct (
IHc H3).
*
invcs dn.
invcs H0.
constructor;
trivial.
*
apply some_lift in e.
destruct e as [?
eqs ?];
subst.
rewrite eqs.
{
destruct H2.
-
invcs dn.
invcs H0;
trivial.
-
rewrite e;
simpl.
eexists;
reflexivity.
}
-
induction r;
simpl.
+
eexists;
reflexivity.
+
destruct a.
invcs H.
destruct (
IHr H3).
*
invcs dn.
invcs H0.
constructor;
trivial.
eapply is_list_sorted_cons_inv;
eauto.
*
simpl in e.
case_option_in e;
try discriminate.
destruct (
RecMaybe_some_pf e)
as [
pf ?];
subst.
{
destruct H2.
-
invcs dn.
invcs H0.
trivial.
-
simpl in e0.
rewrite e0.
assert (
pff:
is_list_sorted ODT_lt_dec (
domain ((
s,
x)::
l)) =
true).
+
rewrite domain_cons.
rewrite <- (
infer_data_type_drec_domain eqs).
invcs dn;
simpl in *;
trivial.
+
rewrite (
RecMaybe_pf_some Closed _ pff).
eexists;
reflexivity.
}
-
destruct IHd.
+
invcs dn;
trivial.
+
simpl;
rewrite e;
simpl.
eexists;
reflexivity.
-
destruct IHd.
+
invcs dn;
trivial.
+
simpl;
rewrite e;
simpl.
eexists;
reflexivity.
-
destruct IHd.
+
invcs dn;
trivial.
+
simpl;
rewrite e;
simpl.
match_destr.
*
match_destr;
eexists;
reflexivity.
*
elim n.
invcs dn;
tauto.
-
simpl.
destruct (@
foreign_data_typing_infer_normalized _ _ _ fd).
+
invcs dn;
trivial.
+
rewrite e.
simpl.
eexists;
reflexivity.
Qed.
Theorem infer_data_type_normalized {
d} :
data_normalized brand_relation_brands d ->
{τ |
infer_data_type d =
Some τ}.
Proof.
case_eq (
infer_data_type d);
intros.
-
eexists;
reflexivity.
-
apply infer_data_type_normalized'
in H0.
destruct H0;
congruence.
Defined.
Theorem infer_data_type_correct {
d τ} :
infer_data_type d =
Some τ ->
d ▹ τ.
Proof.
Local Hint Constructors data_type Forall Forallt :
qcert.
revert τ.
induction d;
simpl;
try solve[
inversion 1;
subst;
eauto 2
with qcert].
-
intros τ
eqs.
apply some_lift in eqs.
destruct eqs as [
t ? ?];
subst τ.
constructor.
revert t H e.
induction c;
simpl;
intros; [
eauto|].
invcs H.
unfold lift2 in e.
case_option_in e;
try discriminate.
case_option_in e;
try discriminate.
specialize (
IHc _ H3 eqs0).
invcs e.
constructor.
+
rewrite <- (
rtype_join_subtype_l);
auto.
+
revert IHc.
apply Forall_impl.
intros.
rewrite <- (
rtype_join_subtype_r);
auto.
-
intros τ
eqs.
case_option_in eqs;
try discriminate.
destruct (
RecMaybe_some_pf eqs)
as [
pf ?];
subst.
clear eqs;
rename eqs0 into eqs.
revert r l pf eqs H.
induction r;
simpl;
intros.
+
invcs eqs.
apply dtrec_full;
constructor.
+
destruct a.
invcs H.
case_option_in eqs;
try discriminate.
case_option_in eqs;
try discriminate.
invcs eqs.
specialize (
IHr _ (
is_list_sorted_cons_inv _ pf)
eqs1 H3).
specialize (
H2 _ eqs0);
simpl in H2.
apply dtrec_closed_inv in IHr.
apply dtrec_full.
constructor;
simpl;
tauto.
-
intros τ
eqs.
apply some_lift in eqs.
destruct eqs as [
t ? ?];
subst τ.
qeauto.
-
intros τ
eqs.
apply some_lift in eqs.
destruct eqs as [
t ? ?];
subst τ.
qeauto.
-
intros τ
eqs.
case_option_in eqs
;
match_case_in eqs;
intros ?
re1;
rewrite re1 in eqs
;
try discriminate.
match_case_in eqs;
intros ?
re2;
rewrite re2 in eqs
;
try discriminate.
invcs eqs.
constructor;
trivial.
+
qeauto.
+
rewrite Forall_forall.
intros ?
inn τ
look.
specialize (
IHd _ eqs0).
rewrite <- (
brands_type_sub_part _ _ _ look inn).
rewrite <-
s.
trivial.
+
reflexivity.
+
invcs eqs.
constructor.
constructor;
trivial.
qeauto.
-
intros τ
eqs.
apply some_lift in eqs.
destruct eqs as [
t ? ?];
subst τ.
apply foreign_data_typing_infer_correct in e.
qeauto.
Qed.
Theorem infer_data_type_least {
d τ₁ τ₂} :
infer_data_type d =
Some τ₁ ->
d ▹τ₂ ->
τ₁ <: τ₂.
Proof.
Local Hint Constructors subtype :
qcert.
revert τ₁ τ₂.
induction d;
simpl;
try solve[
inversion 1;
subst;
intros;
destruct (
istop τ₂);
subst;
trivial;
dtype_inverter;
trivial
|
intros;
invcs H;
invcs H0;
auto 2
with qcert].
-
intros τ₁ τ₂
eqs ht.
apply some_lift in eqs.
destruct eqs as [?
eqs' ?];
subst.
destruct (
istop τ₂);
subst;
qtrivial.
destruct (
data_type_dcoll_inv e ht)
as [τ₂' ?];
subst.
constructor.
clear e.
invcs ht.
rtype_equalizer.
subst.
revert x H H2 eqs';
clear.
induction c;
simpl;
intros τ
fl1 fl2 eqs;
invcs eqs;
qtrivial.
unfold lift2 in H0.
case_option_in H0;
try discriminate.
case_option_in H0;
try discriminate.
invcs H0.
invcs fl1.
invcs fl2.
apply (
join_least (
olattice:=
rtype_olattice)).
+
apply H1;
eauto.
+
apply IHc;
eauto.
-
intros τ₁ τ₂
eqs ht.
case_option_in eqs;
try discriminate.
destruct (
RecMaybe_some_pf eqs)
as [
pf ?];
subst.
clear eqs;
rename eqs0 into eqs.
invcs ht;
qtrivial.
constructor.
+
intros s τ
look.
apply lookup_in in look.
generalize (
sublist_In H1 _ look);
intros inn2.
clear H1 H2 rl_sub look pf0.
revert rl pf'
l pf H inn2 H3 eqs.
clear.
induction r;
intros
;
invcs H3;
invcs H;
invcs inn2.
*
destruct a.
case_option_in eqs;
try discriminate.
case_option_in eqs;
try discriminate.
simpl in H2;
destruct H2;
subst.
invcs eqs.
simpl.
match_destr; [|
congruence].
eexists;
split; [
reflexivity|].
eauto.
*
destruct a.
case_option_in eqs;
try discriminate.
case_option_in eqs;
try discriminate.
simpl in H2;
destruct H2;
subst.
invcs eqs.
destruct (
IHr _ (
is_list_sorted_cons_inv _ pf')
_ (
is_list_sorted_cons_inv _ pf));
trivial.
simpl.
match_destr; [|
eauto].
apply is_list_sorted_NoDup_strlt in pf.
subst s.
invcs pf.
destruct H0 as [
inn _].
apply lookup_in in inn.
apply in_dom in inn.
intuition.
+
intuition;
subst.
rewrite <- (
infer_data_type_drec_domain eqs)
in H2.
rewrite <- (
sorted_forall_same_domain H3).
trivial.
-
intros τ₁ τ₂
eqs ht.
apply some_lift in eqs.
destruct eqs as [?
eqs' ?];
subst.
destruct (
istop τ₂);
subst;
qtrivial.
destruct (
data_type_dleft_inv e ht)
as [τ₂' [? ?]];
subst.
clear e.
invcs ht;
rtype_equalizer.
subst.
qeauto.
-
intros τ₁ τ₂
eqs ht.
apply some_lift in eqs.
destruct eqs as [?
eqs' ?];
subst.
destruct (
istop τ₂);
subst;
qtrivial.
destruct (
data_type_dright_inv e ht)
as [τ₂' [? ?]];
subst.
clear e.
invcs ht;
rtype_equalizer.
subst.
qeauto.
-
intros τ₁ τ₂
eqs ht.
match_destr_in eqs.
case_option_in eqs;
try discriminate.
match_destr_in eqs.
+
invcs eqs.
destruct (
istop τ₂);
subst;
qtrivial.
invcs ht;
qtrivial.
qeauto.
+
invcs eqs.
cut (τ₂ = ⊤); [
intros;
subst;
reflexivity | ].
invcs ht;
trivial.
elim n.
revert H3 IHd eqs0.
clear.
rewrite brands_type_alt.
induction b;
simpl;
qtrivial;
intros.
invcs H3.
specialize (
IHb H2 IHd eqs0).
rewrite fold_right_app.
revert IHb.
simpl.
generalize (
fold_right rtype_meet ⊤ (
brands_type_list b)).
intros.
match_case;
intros τ2
look.
simpl.
rewrite Forall_forall in H2.
apply (
meet_most (
olattice:=
rtype_olattice));
trivial.
apply IHd;
eauto.
-
intros τ₁ τ₂
eqs ht.
apply some_lift in eqs.
destruct eqs as [
t ? ?];
subst.
invcs ht;
qtrivial.
constructor.
eapply foreign_data_typing_infer_least;
eauto.
Qed.
Theorem data_has_principal_type {
d} :
data_normalized brand_relation_brands d ->
{τ |
d ▹τ & (
forall τ',
d ▹τ' -> τ <: τ')}.
Proof.
Theorem infer_data_type_complete {
d τ} :
d ▹τ -> {τ' |
infer_data_type d =
Some τ'}.
Proof.
Lemma normalized_data_type_infer {
d τ} :
infer_data_type d =
Some τ ->
data_normalized brand_relation_brands d.
Proof.
Section dt_dec.
We can compute if the data_type relation holds using
by seeing if its inferred type (if any) is a subtype of the
given type.
Theorem data_type_dec d τ : {
data_type d τ} + {~
data_type d τ}.
Proof.
End dt_dec.
End TDataInfer.