Section TOps.
Require Import String List ZArith.
Require Import Compare_dec.
Require Import Utils Types BasicRuntime.
Require Import ForeignDataTyping ForeignOpsTyping TUtil TData TDataSort.
Require Import Program.
Typing rules for unary operators
Section u.
Context {
fdata:
foreign_data}.
Context {
fuop:
foreign_unary_op}.
Context {
ftype:
foreign_type}.
Context {
fdtyping:
foreign_data_typing}.
Context {
m:
brand_model}.
Context {
fuoptyping:
foreign_unary_op_typing}.
Inductive unaryOp_type :
unaryOp ->
rtype ->
rtype ->
Prop :=
|
ATIdOp τ :
unaryOp_type AIdOp τ τ
|
ATNeg:
unaryOp_type ANeg Bool Bool
|
ATColl {τ} :
unaryOp_type AColl τ (
Coll τ)
|
ATSingleton τ :
unaryOp_type ASingleton (
Coll τ) (
Option τ)
|
ATFlatten τ:
unaryOp_type AFlatten (
Coll (
Coll τ)) (
Coll τ)
|
ATDistinct τ:
unaryOp_type ADistinct (
Coll τ) (
Coll τ)
|
ATOrderBy {τ}
k sl pf1 pf2:
sublist (
List.map fst sl) (
domain τ) ->
order_by_has_sortable_type τ (
List.map fst sl) ->
unaryOp_type (
AOrderBy sl) (
Coll (
Rec k τ
pf1)) (
Coll (
Rec k τ
pf2))
|
ATRec {τ}
s pf :
unaryOp_type (
ARec s) τ (
Rec Closed ((
s,τ)::
nil)
pf)
|
ATDot {τ' τ
out}
k s pf :
tdot τ'
s =
Some τ
out ->
unaryOp_type (
ADot s) (
Rec k τ'
pf) τ
out
|
ATRecRemove {τ}
k s pf1 pf2 :
unaryOp_type (
ARecRemove s) (
Rec k τ
pf1) (
Rec k (
rremove τ
s)
pf2)
|
ATRecProject {τ}
k sl pf1 pf2 :
sublist sl (
domain τ) ->
unaryOp_type (
ARecProject sl) (
Rec k τ
pf1) (
Rec Closed (
rproject τ
sl)
pf2)
|
ATCount τ:
unaryOp_type ACount (
Coll τ)
Nat
|
ATSum :
unaryOp_type ASum (
Coll Nat)
Nat
|
ATNumMin :
unaryOp_type ANumMin (
Coll Nat)
Nat
|
ATNumMax :
unaryOp_type ANumMax (
Coll Nat)
Nat
|
ATArithMean :
unaryOp_type AArithMean (
Coll Nat)
Nat
|
ATToString τ:
unaryOp_type AToString τ
String
|
ATSubstring start olen:
unaryOp_type (
ASubstring start olen)
String String
|
ATLike pat oescape:
unaryOp_type (
ALike pat oescape)
String Bool
|
ATLeft τ
l τ
r:
unaryOp_type ALeft τ
l (
Either τ
l τ
r)
|
ATRight τ
l τ
r:
unaryOp_type ARight τ
r (
Either τ
l τ
r)
|
ATBrand b :
unaryOp_type (
ABrand b) (
brands_type b) (
Brand b)
|
ATUnbrand {
bs} :
unaryOp_type AUnbrand (
Brand bs) (
brands_type bs)
|
ATCast br {
bs} :
unaryOp_type (
ACast br) (
Brand bs) (
Option (
Brand br))
|
ATUArith (
u:
ArithUOp) :
unaryOp_type (
AUArith u)
Nat Nat
|
ATForeignUnaryOp {
fu τ
in τ
out} :
foreign_unary_op_typing_has_type fu τ
in τ
out ->
unaryOp_type (
AForeignUnaryOp fu) τ
in τ
out.
End u.
Tactic Notation "
unaryOp_type_cases"
tactic(
first)
ident(
c) :=
first;
[
Case_aux c "
ATIdOp"%
string
|
Case_aux c "
ATNeg"%
string
|
Case_aux c "
ATColl"%
string
|
Case_aux c "
ATSingleton"%
string
|
Case_aux c "
ATFlatten"%
string
|
Case_aux c "
ATDistinct"%
string
|
Case_aux c "
ATOrderBy"%
string
|
Case_aux c "
ATRec"%
string
|
Case_aux c "
ATDot"%
string
|
Case_aux c "
ATRecRemove"%
string
|
Case_aux c "
ATRecProject"%
string
|
Case_aux c "
ATCount"%
string
|
Case_aux c "
ATSum"%
string
|
Case_aux c "
ATNumMin"%
string
|
Case_aux c "
ATNumMax"%
string
|
Case_aux c "
ATArithMean"%
string
|
Case_aux c "
ATToString"%
string
|
Case_aux c "
ATSubstring"%
string
|
Case_aux c "
ATLike"%
string
|
Case_aux c "
ATLeft"%
string
|
Case_aux c "
ATRight"%
string
|
Case_aux c "
ATBrand"%
string
|
Case_aux c "
ATUnbrand"%
string
|
Case_aux c "
ATCast"%
string
|
Case_aux c "
ATUArith"%
string
|
Case_aux c "
ATForeignUnaryOp"%
string].
Typing rules for binary operators
Section b.
Context {
fdata:
foreign_data}.
Context {
fbop:
foreign_binary_op}.
Context {
ftype:
foreign_type}.
Context {
fdtyping:
foreign_data_typing}.
Context {
m:
brand_model}.
Context {
fboptyping:
foreign_binary_op_typing}.
Inductive binOp_type:
binOp ->
rtype ->
rtype ->
rtype ->
Prop :=
|
ATEq {τ} :
binOp_type AEq τ τ
Bool
|
ATConcat {τ₁ τ₂ τ₃}
pf1 pf2 pf3 :
rec_concat_sort τ₁ τ₂ = τ₃ ->
binOp_type AConcat (
Rec Closed τ₁
pf1) (
Rec Closed τ₂
pf2) (
Rec Closed τ₃
pf3)
|
ATMergeConcat {τ₁ τ₂ τ₃}
pf1 pf2 pf3 :
merge_bindings τ₁ τ₂ =
Some τ₃ ->
binOp_type AMergeConcat (
Rec Closed τ₁
pf1) (
Rec Closed τ₂
pf2) (
Coll (
Rec Closed τ₃
pf3))
|
ATMergeConcatOpen {τ₁ τ₂ τ₃}
pf1 pf2 pf3 :
merge_bindings τ₁ τ₂ =
Some τ₃ ->
binOp_type AMergeConcat (
Rec Open τ₁
pf1) (
Rec Open τ₂
pf2) (
Coll (
Rec Open τ₃
pf3))
|
ATAnd :
binOp_type AAnd Bool Bool Bool
|
ATOr :
binOp_type AOr Bool Bool Bool
|
ATBArith (
b:
ArithBOp) :
binOp_type (
ABArith b)
Nat Nat Nat
|
ATLt :
binOp_type ALt Nat Nat Bool
|
ATLe :
binOp_type ALe Nat Nat Bool
|
ATUnion {τ} :
binOp_type AUnion (
Coll τ) (
Coll τ) (
Coll τ)
|
ATMinus {τ} :
binOp_type AMinus (
Coll τ) (
Coll τ) (
Coll τ)
|
ATMin {τ} :
binOp_type AMin (
Coll τ) (
Coll τ) (
Coll τ)
|
ATMax {τ} :
binOp_type AMax (
Coll τ) (
Coll τ) (
Coll τ)
|
ATContains {τ} :
binOp_type AContains τ (
Coll τ)
Bool
|
ATSConcat :
binOp_type ASConcat String String String
|
ATForeignBinaryOp {
fb τ
in₁ τ
in₂ τ
out} :
foreign_binary_op_typing_has_type fb τ
in₁ τ
in₂ τ
out ->
binOp_type (
AForeignBinaryOp fb) τ
in₁ τ
in₂ τ
out
.
End b.
Tactic Notation "
binOp_type_cases"
tactic(
first)
ident(
c) :=
first;
[
Case_aux c "
ATEq"%
string
|
Case_aux c "
ATConcat"%
string
|
Case_aux c "
ATMergeConcat"%
string
|
Case_aux c "
ATMergeConcatOpen"%
string
|
Case_aux c "
ATAnd"%
string
|
Case_aux c "
ATOr"%
string
|
Case_aux c "
ATBArith"%
string
|
Case_aux c "
ATLt"%
string
|
Case_aux c "
ATLe"%
string
|
Case_aux c "
ATUnion"%
string
|
Case_aux c "
ATMinus"%
string
|
Case_aux c "
ATMin"%
string
|
Case_aux c "
ATMax"%
string
|
Case_aux c "
ATContains"%
string
|
Case_aux c "
ATSConcat"%
string
|
Case_aux c "
ATForeignBinaryOp"%
string].
Type soundness lemmas for individual operations
Context {
fdata:
foreign_data}.
Context {
fuop:
foreign_unary_op}.
Context {
fbop:
foreign_binary_op}.
Context {
ftype:
foreign_type}.
Context {
fdtyping:
foreign_data_typing}.
Context {
h:
brand_model}.
Context {
fuoptyping:
foreign_unary_op_typing}.
Context {
fboptyping:
foreign_binary_op_typing}.
Lemma forall_typed_bunion {τ}
d1 d2:
Forall (
fun d :
data =>
data_type d τ)
d1 ->
Forall (
fun d :
data =>
data_type d τ)
d2 ->
Forall (
fun d :
data =>
data_type d τ) (
bunion d1 d2).
Proof.
intros;
rewrite Forall_forall in *.
induction d1.
simpl in *;
intros.
apply H0;
assumption.
simpl in *;
intros.
elim H1;
intros;
clear H1.
apply (
H x).
left;
assumption.
assert (
forall x :
data,
In x d1 ->
data_type x τ).
intros.
apply (
H x0).
right;
assumption.
apply IHd1;
assumption.
Qed.
Lemma bminus_in_remove (
x a:
data) (
d1 d2:
list data) :
In x (
bminus d1 (
remove_one a d2)) ->
In x (
bminus d1 d2).
Proof.
revert d2.
induction d1;
simpl;
intros.
-
induction d2;
simpl in *.
assumption.
revert H.
elim (
EquivDec.equiv_dec a a0);
unfold EquivDec.equiv_dec;
intros.
rewrite <-
a1.
right;
assumption.
simpl in H.
elim H;
intros;
clear H.
left;
assumption.
right;
apply (
IHd2 H0).
-
specialize (
IHd1 (
remove_one a0 d2)).
apply IHd1.
rewrite remove_one_comm;
assumption.
Qed.
Lemma forall_typed_bminus {τ}
d1 d2:
Forall (
fun d :
data =>
data_type d τ)
d1 ->
Forall (
fun d :
data =>
data_type d τ)
d2 ->
Forall (
fun d :
data =>
data_type d τ) (
bminus d1 d2).
Proof.
intros;
rewrite Forall_forall in *.
induction d1.
simpl in *;
intros.
apply H0;
assumption.
simpl in *;
intros.
assert (
forall x :
data,
In x d1 ->
data_type x τ).
intros.
apply (
H x0).
right;
assumption.
assert (
In x (
bminus d1 d2))
by (
apply bminus_in_remove with (
a:=
a);
assumption).
apply IHd1;
assumption.
Qed.
Lemma forall_typed_bmin {τ}
d1 d2:
Forall (
fun d :
data =>
data_type d τ)
d1 ->
Forall (
fun d :
data =>
data_type d τ)
d2 ->
Forall (
fun d :
data =>
data_type d τ) (
bmin d1 d2).
Proof.
Lemma forall_typed_bmax {τ}
d1 d2:
Forall (
fun d :
data =>
data_type d τ)
d1 ->
Forall (
fun d :
data =>
data_type d τ)
d2 ->
Forall (
fun d :
data =>
data_type d τ) (
bmax d1 d2).
Proof.
Lemma forall_in_weaken {
A} (
P Q:
A ->
Prop)
l:
(
forall x :
A,
P x \/
In x l ->
Q x)
-> (
forall x :
A,
In x l ->
Q x).
Proof.
intros.
induction l.
simpl in H; contradiction.
simpl in *.
specialize (H x). elim H0; intros; clear H0; apply H.
right; left; assumption.
right; right; assumption.
Qed.
Lemma forall_typed_bdistinct {τ}
d1:
Forall (
fun d :
data =>
data_type d τ)
d1 ->
Forall (
fun d :
data =>
data_type d τ) (
bdistinct d1).
Proof.
intros;
rewrite Forall_forall in *.
intros.
induction d1.
simpl in *.
contradiction.
simpl in *.
assert (
forall x :
data,
In x d1 ->
data_type x τ)
by (
apply (
forall_in_weaken (
fun x =>
a =
x));
assumption).
destruct (
mult (
bdistinct d1)
a).
elim H0;
intros;
clear H0.
rewrite <-
H2 in *.
apply (
H a).
left;
reflexivity.
specialize (
IHd1 H1 H2);
assumption.
specialize (
IHd1 H1 H0);
assumption.
Qed.
Lemma Forall2_lookupr_none (
l :
list (
string *
data)) (
l' :
list (
string *
rtype)) (
s:
string):
(
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r))
l l') ->
assoc_lookupr ODT_eqdec l'
s =
None ->
assoc_lookupr ODT_eqdec l s =
None.
Proof.
intros.
induction H;
simpl in *.
reflexivity.
destruct x;
destruct y;
simpl in *.
elim H;
intros;
clear H.
rewrite H2 in *;
clear H2 H3.
revert H0 IHForall2.
elim (
assoc_lookupr string_eqdec l'
s);
try congruence.
elim (
string_eqdec s s1);
intros;
try congruence.
specialize (
IHForall2 H0);
rewrite IHForall2.
reflexivity.
Qed.
Lemma Forall2_lookupr_some (
l :
list (
string *
data)) (
l' :
list (
string *
rtype)) (
s:
string) (
d':
rtype):
(
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r))
l l') ->
assoc_lookupr ODT_eqdec l'
s =
Some d' ->
(
exists d'',
assoc_lookupr ODT_eqdec l s =
Some d'' /\
data_type d''
d').
Proof.
intros.
induction H;
simpl in *.
-
elim H0;
intros;
congruence.
-
destruct x;
destruct y;
simpl in *.
assert ((
exists d,
assoc_lookupr string_eqdec l'
s =
Some d) \/
assoc_lookupr string_eqdec l'
s =
None)
by (
destruct (
assoc_lookupr string_eqdec l'
s);
[
left;
exists r0;
reflexivity|
right;
reflexivity]).
elim H2;
intros;
clear H2.
elim H3;
intros;
clear H3.
revert H0 IHForall2.
rewrite H2;
intros.
elim (
IHForall2 H0);
intros;
clear IHForall2.
elim H3;
intros;
clear H3.
rewrite H4.
exists x0.
split;[
reflexivity|
assumption].
clear IHForall2;
assert (
assoc_lookupr string_eqdec l s =
None)
by apply (
Forall2_lookupr_none l l'
s H1 H3).
rewrite H3 in *;
rewrite H2 in *;
clear H2 H3.
elim H;
intros;
clear H.
rewrite H2 in *;
clear H2.
revert H0;
elim (
string_eqdec s s1);
intros.
exists d;
split;
try reflexivity.
inversion H0;
rewrite H2 in *;
assumption.
congruence.
Qed.
Lemma rec_concat_with_drec_concat_well_typed dl dl0 τ₁ τ₂:
is_list_sorted ODT_lt_dec (
domain τ₁) =
true ->
is_list_sorted ODT_lt_dec (
domain τ₂) =
true ->
is_list_sorted ODT_lt_dec (
domain (
rec_concat_sort τ₁ τ₂)) =
true ->
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r))
dl τ₁ ->
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r))
dl0 τ₂ ->
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r)) (
rec_sort (
dl ++
dl0))
(
rec_concat_sort τ₁ τ₂).
Proof.
Lemma concat_well_typed {τ₁ τ₂ τ₃}
d1 d2 pf1 pf2 pf3:
rec_concat_sort τ₁ τ₂ = τ₃ ->
data_type d1 (
Rec Closed τ₁
pf1) ->
data_type d2 (
Rec Closed τ₂
pf2) ->
exists dl dl0 d3,
d1 =
drec dl /\
d2 =
drec dl0 /\
((
rec_sort (
dl ++
dl0)) =
d3) /\
data_type (
drec d3) (
Rec Closed τ₃
pf3).
Proof.
Lemma rremove_well_typed τ
s dl:
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r))
dl τ ->
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r)) (
rremove dl s)
(
rremove τ
s).
Proof.
intros F2.
induction F2; simpl; trivial.
destruct H; simpl in *.
rewrite H.
match_destr.
auto.
Qed.
Lemma rproject_well_typed τ
rl s dl:
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r))
dl rl ->
sublist s (
domain τ) ->
sublist τ
rl ->
is_list_sorted ODT_lt_dec (
domain τ) =
true ->
is_list_sorted ODT_lt_dec (
domain rl) =
true ->
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
data_type (
snd d) (
snd r)) (
rproject dl s)
(
rproject τ
s).
Proof.
Main type-soundness lemma for binary operators
Require Import RelationClasses EquivDec.
Existing Instance rec_field_lt_strict.
Definition mapTopNotSub s l2 (
l:
list (
string*
rtype)) :=
map (
fun xy => (
fst xy,
if in_dec string_dec (
fst xy)
s
then snd xy
else match lookup string_dec l2 (
fst xy)
with
|
Some y' =>
y'
|
None =>
Top
end
))
l.
Lemma mapTopNotSub_domain s l2 l :
domain (
mapTopNotSub s l2 l) =
domain l.
Proof.
induction l; simpl; congruence.
Qed.
Lemma mapTopNotSub_in {
s l x}
l2:
In (
fst x)
s ->
In x l ->
In x (
mapTopNotSub s l2 l).
Proof.
induction l; simpl; intuition.
subst. destruct x; simpl in *.
match_destr; intuition.
Qed.
Lemma mapTopNotSub_in2 {
s l x y}
l2:
~
In x s ->
In x (
domain l) ->
lookup string_dec l2 x =
Some y ->
In (
x,
y) (
mapTopNotSub s l2 l).
Proof.
induction l; simpl; intuition.
subst.
match_destr; intuition.
rewrite H1. intuition.
Qed.
Lemma in_mapTopNotSub {
s l x}
l2:
In (
fst x)
s ->
In x (
mapTopNotSub s l2 l) ->
In x l.
Proof.
induction l; simpl; intuition.
destruct a; subst. simpl in *.
match_destr; intuition.
Qed.
Lemma mapTopNotSub_in_sublist {
s l x}
l2 :
sublist s l ->
In x s ->
In x (
mapTopNotSub (
domain s)
l2 l).
Proof.
Lemma mapTopNotSub_sublist {
s l s'}
l2:
sublist s l ->
sublist s s' ->
sublist s (
mapTopNotSub (
domain s')
l2 l).
Proof.
revert s s'.
induction l;
inversion 1;
subst.
-
constructor.
-
simpl;
intros.
destruct a;
simpl in *.
match_destr.
+
apply sublist_cons.
apply IHl;
trivial.
eapply sublist_skip_l;
eauto.
+
elim n.
eapply in_dom.
eapply (
sublist_In H0).
simpl.
left;
reflexivity.
-
simpl;
intros.
destruct a;
simpl in *.
apply sublist_skip;
auto.
Qed.
Lemma mapTopNotSub_sublist_same {
s l}
l2:
sublist s l ->
sublist s (
mapTopNotSub (
domain s)
l2 l).
Proof.
Lemma mapTopNotSub_in_inv {
s l2 l x} :
In x (
mapTopNotSub s l2 l) ->
(
In (
fst x)
s /\
In x l) \/
(~
In (
fst x)
s /\
(
In x l2 \/
(~
In (
fst x) (
domain l2) /\
snd x =
Top))).
Proof.
induction l;
simpl;
intuition.
destruct x.
destruct a;
simpl in *.
inversion H0;
simpl in *;
subst.
match_destr;
intuition.
right;
split;
trivial.
match_case;
intros.
-
left.
eapply lookup_in;
eauto.
-
apply lookup_none_nin in H.
intuition.
Qed.
Lemma mapTopNotSub_compatible {
t1 t2}
rl1 rl2 :
NoDup (
domain rl1) ->
NoDup (
domain rl2) ->
sublist t1 rl1 ->
sublist t2 rl2 ->
compatible t1 t2 =
true ->
compatible (
mapTopNotSub (
domain t1)
t2 rl1)
(
mapTopNotSub (
domain t2)
t1 rl2) =
true.
Proof.
Require Import Bool.
Lemma Forall2_compat_mapTopNotSub {
x x0 rl rl0 t2}
t1:
is_list_sorted ODT_lt_dec (
domain rl) =
true ->
is_list_sorted ODT_lt_dec (
domain rl0) =
true ->
sublist t2 rl0 ->
Forall2 (
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x rl ->
Forall2 (
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x0 rl0 ->
compatible x x0 =
true ->
Forall2
(
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x (
mapTopNotSub t1 t2 rl).
Proof.
Lemma Forall2_compat_app_strengthen {
x x0 rl rl0 t1 t2}:
is_list_sorted ODT_lt_dec (
domain rl) =
true ->
is_list_sorted ODT_lt_dec (
domain rl0) =
true ->
sublist t1 rl ->
sublist t2 rl0 ->
compatible t1 t2 =
true ->
Forall2 (
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x rl ->
Forall2 (
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x0 rl0 ->
compatible x x0 =
true ->
exists rl'
rl0',
compatible rl'
rl0' =
true /\
sublist t1 rl' /\
sublist t2 rl0' /\
Forall2 (
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x rl' /\
Forall2 (
fun (
d :
string *
data) (
r :
string *
rtype) =>
fst d =
fst r /\
snd d ▹
snd r)
x0 rl0'.
Proof.
Lemma sorted_sublists_sorted_concat (τ₁ τ₂
rl rl0:
list (
string*
rtype)):
is_list_sorted ODT_lt_dec (
domain τ₁) =
true ->
is_list_sorted ODT_lt_dec (
domain τ₂) =
true ->
is_list_sorted ODT_lt_dec (
domain rl) =
true ->
is_list_sorted ODT_lt_dec (
domain rl0) =
true ->
compatible rl rl0 =
true ->
sublist τ₁
rl ->
sublist τ₂
rl0 ->
sublist (
rec_sort (τ₁ ++ τ₂)) (
rec_sort (
rl ++
rl0)).
Proof.
Lemma typed_binop_yields_typed_data {τ₁ τ₂ τ
out} (
d1 d2:
data) (
b:
binOp) :
(
d1 ▹ τ₁) -> (
d2 ▹ τ₂) -> (
binOp_type b τ₁ τ₂ τ
out) ->
(
exists x,
fun_of_binop brand_relation_brands b d1 d2 =
Some x /\
x ▹ τ
out).
Proof.
Definition canon_brands_alt {
br:
brand_relation} (
b:
brands) :=
fold_right meet [] (
map (
fun x =>
x::
nil)
b).
Lemma canon_brands_alt_is_canon {
br:
brand_relation} (
b:
brands) :
is_canon_brands brand_relation_brands (
canon_brands_alt b).
Proof.
Lemma canon_brands_fold_right_hoist {
br:
brand_relation} (
l:
list brands) :
fold_right
(
fun a b :
brands =>
canon_brands brand_relation_brands (
a ++
b))
[]
l =
canon_brands brand_relation_brands
(
fold_right (
fun a b :
brands => (
a ++
b))
[]
l).
Proof.
Lemma canon_brands_alt_equiv {
br:
brand_relation} (
b:
brands) :
canon_brands brand_relation_brands b
=
canon_brands_alt b.
Proof.
Require Import Permutation.
Main type-soundness lemma for unary operators
Lemma typed_unop_yields_typed_data {τ₁ τ
out} (
d1:
data) (
u:
unaryOp) :
(
d1 ▹ τ₁) -> (
unaryOp_type u τ₁ τ
out) ->
(
exists x,
fun_of_unaryop brand_relation_brands u d1 =
Some x /\
x ▹ τ
out).
Proof.
Hint Resolve dtsome dtnone.
intros.
unaryOp_type_cases (
dependent induction H0)
Case;
simpl.
-
Case "
ATIdOp"%
string.
eauto.
-
Case "
ATNeg"%
string.
dependent induction H;
simpl.
exists (
dbool (
negb b)).
split; [
reflexivity|
apply dtbool].
-
Case "
ATColl"%
string.
exists (
dcoll [
d1]);
split;
try
reflexivity.
apply dtcoll;
apply Forall_forall;
intros.
elim H0;
intros.
rewrite <-
H1;
assumption.
contradiction.
-
Case "
ATSingleton"%
string.
inversion H;
rtype_equalizer.
subst.
repeat (
destruct dl;
eauto).
inversion H2;
subst.
eauto.
-
Case "
ATFlatten"%
string.
dependent induction H.
rewrite Forall_forall in *.
unfold rflatten.
induction dl;
simpl in *.
exists (
dcoll []).
split;
try reflexivity.
apply dtcoll;
apply Forall_nil.
assert (
forall x :
data,
In x dl ->
data_type x r)
by
(
intros;
apply (
H x0);
right;
assumption).
elim (
IHdl H0);
clear IHdl H0;
intros.
elim H0;
clear H0;
intros.
unfold lift in H0.
assert (
exists a',
oflat_map
(
fun x :
data =>
match x with
|
dcoll y =>
Some y
|
_ =>
None
end)
dl =
Some a' /\
x0 = (
dcoll a')).
revert H0.
destruct (
oflat_map
(
fun x1 :
data =>
match x1 with
|
dcoll y =>
Some y
|
_ =>
None
end)
dl);
intros.
inversion H0.
exists l;
split;
reflexivity.
congruence.
elim H2;
clear H2;
intros.
elim H2;
clear H2;
intros.
rewrite H2;
clear H2 H0.
assert (
data_type a r)
by (
apply (
H a);
left;
reflexivity).
assert (
r =
Coll τ)
by (
apply rtype_fequal;
assumption).
rewrite H2 in *;
clear H2.
dependent induction H0.
assert (
r0 = τ)
by (
apply rtype_fequal;
assumption).
simpl.
exists (
dcoll (
dl0 ++
x1));
split;
try reflexivity.
apply dtcoll.
dependent induction H1.
assert (
r1 = τ)
by (
apply rtype_fequal;
assumption).
apply Forall_app;
rewrite Forall_forall in *.
rewrite H2 in *;
assumption.
rewrite H3 in *;
assumption.
-
Case "
ATDistinct"%
string.
dependent induction H.
autorewrite with alg.
exists (
dcoll (
bdistinct dl)).
split; [
reflexivity|
apply dtcoll].
assert (
r = τ)
by (
apply rtype_fequal;
assumption).
rewrite H0 in *.
apply forall_typed_bdistinct;
assumption.
-
Case "
ATOrderBy"%
string.
intros.
apply (
order_by_well_typed d1 sl H H0 H1).
-
Case "
ATRec"%
string.
exists (
drec [(
s,
d1)]).
split; [
reflexivity|
apply dtrec_full].
apply Forall2_cons.
split; [
reflexivity|
assumption].
apply Forall2_nil.
-
Case "
ATDot"%
string.
dependent induction H.
rtype_equalizer;
subst.
unfold tdot in *.
unfold edot in *.
apply (
Forall2_lookupr_some _ _ _ _ H1).
eapply assoc_lookupr_nodup_sublist;
eauto.
-
Case "
ATRecRemove"%
string.
dependent induction H;
rtype_equalizer.
subst.
exists (
drec (
rremove dl s));
split;
try reflexivity.
eapply dtrec;
try (
apply rremove_well_typed;
try eassumption).
+
apply is_sorted_rremove;
trivial.
+
apply sublist_filter;
trivial.
+
intuition;
congruence.
-
Case "
ATRecProject"%
string.
dependent induction H.
rtype_equalizer ;
subst.
exists (
drec (
rproject dl sl));
split;
try reflexivity.
apply dtrec_full.
clear H0 pf1.
apply (
rproject_well_typed τ
rl);
try assumption.
-
Case "
ATCount"%
string.
dependent induction H.
autorewrite with alg.
exists (
dnat (
Z_of_nat (
bcount dl))).
split; [
reflexivity|
apply dtnat].
-
Case "
ATSum"%
string.
dependent induction H.
revert r x H.
induction dl;
simpl; [
eauto|
intros].
inversion H;
subst.
destruct (
IHdl r x H3)
as [
x0 [
x0eq x0d]].
destruct H2;
try solve[
simpl in x;
discriminate].
simpl in *.
destruct (
some_lift x0eq);
subst.
rewrite e.
simpl.
eauto.
-
Case "
ATNumMin"%
string.
dependent induction H.
destruct r.
destruct x0;
simpl in x;
try congruence.
induction dl.
rewrite Forall_forall in H.
unfold lifted_min;
simpl.
exists (
dnat 0).
auto.
inversion H.
subst.
specialize (
IHdl H3).
elim IHdl;
clear IHdl;
intros.
elim H0;
clear H0;
intros.
unfold lifted_min in *.
unfold lift in *.
unfold lifted_zbag in *.
assert (
Nat = (
exist (
fun τ₀ :
rtype₀ =>
wf_rtype₀ τ₀ =
true)
Nat₀
e))
by (
apply rtype_fequal;
reflexivity).
rewrite <-
H4 in H2.
destruct (
data_type_Nat_inv H2);
subst.
simpl.
destruct (
rmap (
ondnat (
fun x3 :
Z =>
x3))
dl);
try congruence.
simpl.
exists (
dnat (
fold_right (
fun x3 y :
Z =>
Z.min x3 y)
x1 l)).
split; [
reflexivity|
auto].
-
Case "
ATNumMax"%
string.
dependent induction H.
destruct r.
destruct x0;
simpl in x;
try congruence.
induction dl.
rewrite Forall_forall in H.
unfold lifted_max;
simpl.
exists (
dnat 0).
auto.
inversion H.
subst.
specialize (
IHdl H3).
elim IHdl;
clear IHdl;
intros.
elim H0;
clear H0;
intros.
unfold lifted_max in *.
unfold lift in *.
unfold lifted_zbag in *.
assert (
Nat = (
exist (
fun τ₀ :
rtype₀ =>
wf_rtype₀ τ₀ =
true)
Nat₀
e))
by (
apply rtype_fequal;
reflexivity).
rewrite <-
H4 in H2.
destruct (
data_type_Nat_inv H2);
subst.
simpl.
destruct (
rmap (
ondnat (
fun x3 :
Z =>
x3))
dl);
try congruence.
simpl.
exists (
dnat (
fold_right (
fun x3 y :
Z =>
Z.max x3 y)
x1 l)).
split; [
reflexivity|
auto].
-
Case "
ATArithMean"%
string.
assert(
dsum_pf:
exists x :
data,
lift dnat (
lift_oncoll dsum d1) =
Some x /\
x ▹
Nat).
{
dependent induction H.
revert r x H.
induction dl;
simpl; [
eauto|
intros].
inversion H;
subst.
destruct (
IHdl r x H3)
as [
x0 [
x0eq x0d]].
destruct H2;
try solve[
simpl in x;
discriminate].
simpl in *.
destruct (
some_lift x0eq);
subst.
rewrite e.
simpl.
eauto.
}
destruct dsum_pf as [
x [
xeq xtyp]].
dtype_inverter.
apply some_lift in xeq.
destruct xeq as [?
eqq1 eqq2].
simpl in eqq1.
inversion eqq2;
clear eqq2;
subst.
destruct (
is_nil_dec d1);
simpl.
+
subst;
simpl;
eauto.
+
exists (
dnat (
Z.quot x (
Z_of_nat (
length d1)))).
split; [ |
constructor ].
unfold darithmean.
rewrite eqq1;
simpl.
destruct d1;
simpl;
congruence.
-
Case "
ATToString"%
string.
eauto.
-
Case "
ATSubstring"%
string.
dtype_inverter.
eauto.
-
Case "
ATLike"%
string.
dtype_inverter.
eauto.
-
Case "
ATLeft"%
string.
eauto.
-
Case "
ATRight"%
string.
eauto.
-
Case "
ATBrand"%
string.
eexists;
split;
try reflexivity.
apply dtbrand'.
+
eauto.
+
rewrite brands_type_of_canon;
trivial.
+
rewrite canon_brands_equiv;
reflexivity.
-
Case "
ATUnbrand"%
string.
destruct d1;
try solve[
inversion H].
apply dtbrand'
_inv in H.
destruct H as [
isc [
dt subb]].
eexists;
split;
try reflexivity.
rewrite subb in dt.
trivial.
-
Case "
ATCast"%
string.
inversion H;
subst.
match_destr; [|
eauto].
econstructor;
split;
try reflexivity.
constructor.
econstructor;
eauto.
-
Case "
ATUArith"%
string.
dependent induction H;
simpl.
eauto.
-
Case "
ATForeignUnaryOp"%
string.
eapply foreign_unary_op_typing_sound;
eauto.
Qed.
Additional auxiliary lemmas
Lemma tdot_rec_concat_sort_neq {
A} (
l:
list (
string*
A))
a b xv :
a <>
b ->
tdot (
rec_concat_sort l [(
a,
xv)])
b =
tdot (
rec_sort l)
b.
Proof.
Lemma tdot_rec_concat_sort_eq {
A} (
l :
list (
string *
A))
a b :
~
In a (
domain l) ->
tdot (
rec_concat_sort l [(
a,
b)])
a =
Some b.
Proof.
End TOps.
Tactic Notation "
unaryOp_type_cases"
tactic(
first)
ident(
c) :=
first;
[
Case_aux c "
ATIdOp"%
string
|
Case_aux c "
ATNeg"%
string
|
Case_aux c "
ATColl"%
string
|
Case_aux c "
ATSingleton"%
string
|
Case_aux c "
ATFlatten"%
string
|
Case_aux c "
ATDistinct"%
string
|
Case_aux c "
ATOrderBy"%
string
|
Case_aux c "
ATRec"%
string
|
Case_aux c "
ATDot"%
string
|
Case_aux c "
ATRecRemove"%
string
|
Case_aux c "
ATRecProject"%
string
|
Case_aux c "
ATCount"%
string
|
Case_aux c "
ATSum"%
string
|
Case_aux c "
ATNumMin"%
string
|
Case_aux c "
ATNumMax"%
string
|
Case_aux c "
ATArithMean"%
string
|
Case_aux c "
ATToString"%
string
|
Case_aux c "
ATSubstring"%
string
|
Case_aux c "
ATLike"%
string
|
Case_aux c "
ATLeft"%
string
|
Case_aux c "
ATRight"%
string
|
Case_aux c "
ATBrand"%
string
|
Case_aux c "
ATUnbrand"%
string
|
Case_aux c "
ATCast"%
string
|
Case_aux c "
ATUArith"%
string
|
Case_aux c "
ATForeignUnaryOp"%
string].
Tactic Notation "
binOp_type_cases"
tactic(
first)
ident(
c) :=
first;
[
Case_aux c "
ATEq"%
string
|
Case_aux c "
ATConcat"%
string
|
Case_aux c "
ATMergeConcat"%
string
|
Case_aux c "
ATMergeConcatOpen"%
string
|
Case_aux c "
ATAnd"%
string
|
Case_aux c "
ATOr"%
string
|
Case_aux c "
ATBArith"%
string
|
Case_aux c "
ATLt"%
string
|
Case_aux c "
ATLe"%
string
|
Case_aux c "
ATUnion"%
string
|
Case_aux c "
ATMinus"%
string
|
Case_aux c "
ATMin"%
string
|
Case_aux c "
ATMax"%
string
|
Case_aux c "
ATContains"%
string
|
Case_aux c "
ATSConcat"%
string
|
Case_aux c "
ATForeignBinaryOp"%
string].