Qcert.Basic.Typing.TOps


Section TOps.



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 : datadata_type d τ) d1
    Forall (fun d : datadata_type d τ) d2
    Forall (fun d : datadata_type d τ) (bunion d1 d2).

  Lemma bminus_in_remove (x a:data) (d1 d2:list data) :
    In x (bminus d1 (remove_one a d2)) In x (bminus d1 d2).

  Lemma forall_typed_bminus {τ} d1 d2:
    Forall (fun d : datadata_type d τ) d1
    Forall (fun d : datadata_type d τ) d2
    Forall (fun d : datadata_type d τ) (bminus d1 d2).

  Lemma forall_typed_bmin {τ} d1 d2:
    Forall (fun d : datadata_type d τ) d1
    Forall (fun d : datadata_type d τ) d2
    Forall (fun d : datadata_type d τ) (bmin d1 d2).

  Lemma forall_typed_bmax {τ} d1 d2:
    Forall (fun d : datadata_type d τ) d1
    Forall (fun d : datadata_type d τ) d2
    Forall (fun d : datadata_type d τ) (bmax d1 d2).

  Lemma forall_in_weaken {A} (P Q:A Prop) l:
    ( x : A, P x In x l Q x)
     ( x : A, In x l Q x).

  Lemma forall_typed_bdistinct {τ} d1:
    Forall (fun d : datadata_type d τ) d1
    Forall (fun d : datadata_type d τ) (bdistinct d1).

  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.

  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'
    ( d'', assoc_lookupr ODT_eqdec l s = Some d'' data_type d'' d').

  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 τ τ).

  Lemma concat_well_typed τ τ} d1 d2 pf1 pf2 pf3:
    rec_concat_sort τ τ = τ
    data_type d1 (Rec Closed τ pf1)
    data_type d2 (Rec Closed τ pf2)
     dl dl0 d3,
      d1 = drec dl
      d2 = drec dl0
      ((rec_sort (dl ++ dl0)) = d3)
      data_type (drec d3) (Rec Closed τ pf3).

  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).

  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).

Main type-soundness lemma for binary operators


  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'
                                   | NoneTop
                                 end
                   )) l.

  Lemma mapTopNotSub_domain s l2 l :
    domain (mapTopNotSub s l2 l) = domain l.

  Lemma mapTopNotSub_in {s l x} l2:
    In (fst x) s In x l In x (mapTopNotSub s l2 l).

  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).

    Lemma in_mapTopNotSub {s l x} l2:
    In (fst x) s In x (mapTopNotSub s l2 l) In x l.

  Lemma mapTopNotSub_in_sublist {s l x} l2 :
    sublist s l
      In x s In x (mapTopNotSub (domain s) l2 l).

  Lemma mapTopNotSub_sublist {s l s'} l2:
    sublist s l
    sublist s s'
    sublist s (mapTopNotSub (domain s') l2 l).

  Lemma mapTopNotSub_sublist_same {s l} l2:
    sublist s l
    sublist s (mapTopNotSub (domain s) l2 l).

  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))).

  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.


  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).

  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
         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'.

  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)).

  Lemma typed_binop_yields_typed_data τ τout} (d1 d2:data) (b:binOp) :
    (d1 τ) (d2 τ) (binOp_type b τ τ τout)
    ( x, fun_of_binop brand_relation_brands b d1 d2 = Some x x τout).

  Definition canon_brands_alt {br:brand_relation} (b:brands) :=
    fold_right meet [] (map (fun xx::nil) b).

  Lemma canon_brands_alt_is_canon {br:brand_relation} (b:brands) :
    is_canon_brands brand_relation_brands (canon_brands_alt b).

  Lemma canon_brands_fold_right_hoist {br:brand_relation} (l:list brands) :
    fold_right
      (fun a b : brandscanon_brands brand_relation_brands (a ++ b))
      [] l =
    canon_brands brand_relation_brands
                 (fold_right (fun a b : brands ⇒ (a ++ b))
                             [] l).

  Lemma canon_brands_alt_equiv {br:brand_relation} (b:brands) :
    canon_brands brand_relation_brands b
    = canon_brands_alt b.


Main type-soundness lemma for unary operators
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.

  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.

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].