src/HOL/Tools/record_package.ML
changeset 11934 6c1bf72430b6
parent 11927 96f267adc029
child 11940 80365073b8b3
equal deleted inserted replaced
11933:acfea249b03c 11934:6c1bf72430b6
    69 fun prefix_base s = NameSpace.map_base (fn bname => s ^ bname);
    69 fun prefix_base s = NameSpace.map_base (fn bname => s ^ bname);
    70 
    70 
    71 val Trueprop = HOLogic.mk_Trueprop;
    71 val Trueprop = HOLogic.mk_Trueprop;
    72 fun All xs t = Term.list_all_free (xs, t);
    72 fun All xs t = Term.list_all_free (xs, t);
    73 
    73 
    74 infix 0 :== === ==>;
    74 infix 9 $$;
       
    75 infix 0 :== ===;
       
    76 infixr 0 ==>;
       
    77 
       
    78 val (op $$) = Term.list_comb;
    75 val (op :==) = Logic.mk_defpair;
    79 val (op :==) = Logic.mk_defpair;
    76 val (op ===) = Trueprop o HOLogic.mk_eq;
    80 val (op ===) = Trueprop o HOLogic.mk_eq;
    77 val (op ==>) = Logic.mk_implies;
    81 val (op ==>) = Logic.mk_implies;
    78 
    82 
    79 
    83 
   107 val fieldN = "_field";
   111 val fieldN = "_field";
   108 val fstN = "_val";
   112 val fstN = "_val";
   109 val sndN = "_more";
   113 val sndN = "_more";
   110 val updateN = "_update";
   114 val updateN = "_update";
   111 val makeN = "make";
   115 val makeN = "make";
   112 val make_schemeN = "make_scheme";
   116 val extendN = "extend";
   113 val recordN = "record";
   117 val truncateN = "truncate";
       
   118 
   114 
   119 
   115 (*see typedef_package.ML*)
   120 (*see typedef_package.ML*)
   116 val RepN = "Rep_";
   121 val RepN = "Rep_";
   117 val AbsN = "Abs_";
   122 val AbsN = "Abs_";
   118 
   123 
   201 
   206 
   202 fun mk_sel r c =
   207 fun mk_sel r c =
   203   let val rT = fastype_of r
   208   let val rT = fastype_of r
   204   in Const (mk_selC rT (c, find_fieldT c rT)) $ r end;
   209   in Const (mk_selC rT (c, find_fieldT c rT)) $ r end;
   205 
   210 
       
   211 fun mk_named_sels names r = names ~~ map (mk_sel r) names;
       
   212 
   206 val mk_moreC = mk_selC;
   213 val mk_moreC = mk_selC;
   207 
   214 
   208 fun mk_more r c =
   215 fun mk_more r c =
   209   let val rT = fastype_of r
   216   let val rT = fastype_of r
   210   in Const (mk_moreC rT (c, snd (dest_recordT rT))) $ r end;
   217   in Const (mk_moreC rT (c, snd (dest_recordT rT))) $ r end;
   221 val mk_more_updateC = mk_updateC;
   228 val mk_more_updateC = mk_updateC;
   222 
   229 
   223 fun mk_more_update r (c, x) =
   230 fun mk_more_update r (c, x) =
   224   let val rT = fastype_of r
   231   let val rT = fastype_of r
   225   in Const (mk_more_updateC rT (c, snd (dest_recordT rT))) $ x $ r end;
   232   in Const (mk_more_updateC rT (c, snd (dest_recordT rT))) $ x $ r end;
   226 
       
   227 
       
   228 (* make *)
       
   229 
       
   230 fun mk_makeC rT (c, Ts) = (c, Ts ---> rT);
       
   231 
   233 
   232 
   234 
   233 
   235 
   234 (** concrete syntax for records **)
   236 (** concrete syntax for records **)
   235 
   237 
   261 fun record_update_tr [t, u] =
   263 fun record_update_tr [t, u] =
   262       foldr (op $) (rev (gen_fields_tr "_updates" "_update" updateN u), t)
   264       foldr (op $) (rev (gen_fields_tr "_updates" "_update" updateN u), t)
   263   | record_update_tr ts = raise TERM ("record_update_tr", ts);
   265   | record_update_tr ts = raise TERM ("record_update_tr", ts);
   264 
   266 
   265 
   267 
   266 fun update_name_tr (Free (x, T) :: ts) = Term.list_comb (Free (suffix updateN x, T), ts)
   268 fun update_name_tr (Free (x, T) :: ts) = Free (suffix updateN x, T) $$ ts
   267   | update_name_tr (Const (x, T) :: ts) = Term.list_comb (Const (suffix updateN x, T), ts)
   269   | update_name_tr (Const (x, T) :: ts) = Const (suffix updateN x, T) $$ ts
   268   | update_name_tr (((c as Const ("_constrain", _)) $ t $ ty) :: ts) =
   270   | update_name_tr (((c as Const ("_constrain", _)) $ t $ ty) :: ts) =
   269       Term.list_comb (c $ update_name_tr [t] $
   271       (c $ update_name_tr [t] $ (Syntax.const "fun" $ ty $ Syntax.const "dummy")) $$ ts
   270         (Syntax.const "fun" $ ty $ Syntax.const "dummy"), ts)
       
   271   | update_name_tr ts = raise TERM ("update_name_tr", ts);
   272   | update_name_tr ts = raise TERM ("update_name_tr", ts);
   272 
   273 
   273 
   274 
   274 val parse_translation =
   275 val parse_translation =
   275  [("_record_type", record_type_tr),
   276  [("_record_type", record_type_tr),
   698     val all_xs_more = all_xs @ [moreN];
   699     val all_xs_more = all_xs @ [moreN];
   699 
   700 
   700     val parent_more = funpow parent_len mk_snd;
   701     val parent_more = funpow parent_len mk_snd;
   701     val idxs = 0 upto (len - 1);
   702     val idxs = 0 upto (len - 1);
   702 
   703 
       
   704     val parentT = if null parent_fields then [] else [mk_recordT (parent_fields, HOLogic.unitT)];
       
   705     val r_parent = if null parent_fields then [] else [Free (rN, hd parentT)];
       
   706 
   703     val rec_schemeT = mk_recordT (all_fields, moreT);
   707     val rec_schemeT = mk_recordT (all_fields, moreT);
   704     val rec_scheme = mk_record (all_named_vars, more);
   708     val rec_scheme = mk_record (all_named_vars, more);
   705     val recT = mk_recordT (all_fields, HOLogic.unitT);
   709     val recT = mk_recordT (all_fields, HOLogic.unitT);
   706     val rec_ = mk_record (all_named_vars, HOLogic.unit);
   710     val rec_ = mk_record (all_named_vars, HOLogic.unit);
   707     val r = Free (rN, rec_schemeT);
   711     val r_scheme = Free (rN, rec_schemeT);
   708     val r' = Free (rN, recT);
   712     val r = Free (rN, recT);
   709 
   713 
   710 
   714 
   711     (* prepare print translation functions *)
   715     (* prepare print translation functions *)
   712 
   716 
   713     val field_tr's =
   717     val field_tr's =
   718 
   722 
   719     val sel_decls = map (mk_selC rec_schemeT) bfields @
   723     val sel_decls = map (mk_selC rec_schemeT) bfields @
   720       [mk_moreC rec_schemeT (moreN, moreT)];
   724       [mk_moreC rec_schemeT (moreN, moreT)];
   721     val update_decls = map (mk_updateC rec_schemeT) bfields @
   725     val update_decls = map (mk_updateC rec_schemeT) bfields @
   722       [mk_more_updateC rec_schemeT (moreN, moreT)];
   726       [mk_more_updateC rec_schemeT (moreN, moreT)];
   723     val make_decls =
   727     val make_decl = (makeN, parentT ---> types ---> recT);
   724       [(mk_makeC rec_schemeT (make_schemeN, all_types @ [moreT])),
   728     val extend_decl = (extendN, recT --> moreT --> rec_schemeT);
   725        (mk_makeC recT (makeN, all_types))];
   729     val truncate_decl = (truncateN, rec_schemeT --> recT);
   726     val record_decl = (recordN, rec_schemeT --> recT);
       
   727 
   730 
   728 
   731 
   729     (* prepare definitions *)
   732     (* prepare definitions *)
   730 
   733 
   731     (*record (scheme) type abbreviation*)
   734     (*record (scheme) type abbreviation*)
   733       [(suffix schemeN bname, alphas @ [zeta], rec_schemeT, Syntax.NoSyn),
   736       [(suffix schemeN bname, alphas @ [zeta], rec_schemeT, Syntax.NoSyn),
   734         (bname, alphas, recT, Syntax.NoSyn)];
   737         (bname, alphas, recT, Syntax.NoSyn)];
   735 
   738 
   736     (*selectors*)
   739     (*selectors*)
   737     fun mk_sel_spec (i, c) =
   740     fun mk_sel_spec (i, c) =
   738       mk_sel r c :== mk_fst (funpow i mk_snd (parent_more r));
   741       mk_sel r_scheme c :== mk_fst (funpow i mk_snd (parent_more r_scheme));
   739     val sel_specs =
   742     val sel_specs =
   740       ListPair.map mk_sel_spec (idxs, names) @
   743       ListPair.map mk_sel_spec (idxs, names) @
   741         [more_part r :== funpow len mk_snd (parent_more r)];
   744         [more_part r_scheme :== funpow len mk_snd (parent_more r_scheme)];
   742 
   745 
   743     (*updates*)
   746     (*updates*)
   744     val all_sels = all_names ~~ map (mk_sel r) all_names;
   747     val all_sels = mk_named_sels all_names r_scheme;
   745     fun mk_upd_spec (i, (c, x)) =
   748     fun mk_upd_spec (i, (c, x)) =
   746       mk_update r (c, x) :==
   749       mk_update r_scheme (c, x) :==
   747         mk_record (nth_update (c, x) (parent_len + i, all_sels), more_part r)
   750         mk_record (nth_update (c, x) (parent_len + i, all_sels), more_part r_scheme)
   748     val update_specs =
   751     val update_specs =
   749       ListPair.map mk_upd_spec (idxs, named_vars) @
   752       ListPair.map mk_upd_spec (idxs, named_vars) @
   750         [more_part_update r more :== mk_record (all_sels, more)];
   753         [more_part_update r_scheme more :== mk_record (all_sels, more)];
   751 
   754 
   752     (*makes*)
   755     (*derived operations*)
   753     val make_scheme = Const (mk_makeC rec_schemeT (full make_schemeN, all_types @ [moreT]));
   756     val make_spec = Const (full makeN, parentT ---> types ---> recT) $$ r_parent $$ vars :==
   754     val make = Const (mk_makeC recT (full makeN, all_types));
   757       mk_record (flat (map (mk_named_sels parent_names) r_parent) @ named_vars, HOLogic.unit);
   755     val make_specs =
   758     val extend_spec = Const (full extendN, recT --> moreT --> rec_schemeT) $ r $ more :==
   756       [list_comb (make_scheme, all_vars) $ more :== rec_scheme,
   759       mk_record (mk_named_sels all_names r, more);
   757         list_comb (make, all_vars) :== rec_];
   760     val truncate_spec = Const (full truncateN, rec_schemeT --> recT) $ r_scheme :==
   758     val record_spec =
   761       mk_record (all_sels, HOLogic.unit);
   759       Const (full recordN, rec_schemeT --> recT) $ r :== mk_record (all_sels, HOLogic.unit);
       
   760 
   762 
   761 
   763 
   762     (* prepare propositions *)
   764     (* prepare propositions *)
   763 
   765 
   764     (*selectors*)
   766     (*selectors*)
   777         let val more' = Free (variant all_xs (moreN ^ "'"), moreT)
   779         let val more' = Free (variant all_xs (moreN ^ "'"), moreT)
   778         in [more_part_update rec_scheme more' === mk_record (all_named_vars, more')] end;
   780         in [more_part_update rec_scheme more' === mk_record (all_named_vars, more')] end;
   779 
   781 
   780     (*equality*)
   782     (*equality*)
   781     fun mk_sel_eq (t, T) =
   783     fun mk_sel_eq (t, T) =
   782       let val t' = Term.abstract_over (r, t)
   784       let val t' = Term.abstract_over (r_scheme, t)
   783       in Trueprop (HOLogic.eq_const T $ Term.incr_boundvars 1 t' $ t') end;
   785       in Trueprop (HOLogic.eq_const T $ Term.incr_boundvars 1 t' $ t') end;
   784     val sel_eqs = map2 mk_sel_eq (map (mk_sel r) all_names @ [more_part r], all_types @ [moreT]);
   786     val sel_eqs =
       
   787       map2 mk_sel_eq (map (mk_sel r_scheme) all_names @ [more_part r_scheme], all_types @ [moreT]);
   785     val equality_prop =
   788     val equality_prop =
   786       Term.all rec_schemeT $ (Abs ("r", rec_schemeT,
   789       Term.all rec_schemeT $ (Abs ("r", rec_schemeT,
   787         Term.all rec_schemeT $ (Abs ("r'", rec_schemeT,
   790         Term.all rec_schemeT $ (Abs ("r'", rec_schemeT,
   788           Logic.list_implies (sel_eqs,
   791           Logic.list_implies (sel_eqs,
   789             Trueprop (HOLogic.eq_const rec_schemeT $ Bound 1 $ Bound 0))))));
   792             Trueprop (HOLogic.eq_const rec_schemeT $ Bound 1 $ Bound 0))))));
   790 
   793 
   791     (*induct*)
   794     (*induct*)
   792     val P = Free ("P", rec_schemeT --> HOLogic.boolT);
   795     val P = Free ("P", rec_schemeT --> HOLogic.boolT);
   793     val P' = Free ("P", recT --> HOLogic.boolT);
   796     val P' = Free ("P", recT --> HOLogic.boolT);
   794     val induct_scheme_prop =
   797     val induct_scheme_prop =
   795       All (all_xs_more ~~ all_types_more) (Trueprop (P $ rec_scheme)) ==> Trueprop (P $ r);
   798       All (all_xs_more ~~ all_types_more) (Trueprop (P $ rec_scheme)) ==> Trueprop (P $ r_scheme);
   796     val induct_prop = All (all_xs ~~ all_types) (Trueprop (P' $ rec_)) ==> Trueprop (P' $ r');
   799     val induct_prop = All (all_xs ~~ all_types) (Trueprop (P' $ rec_)) ==> Trueprop (P' $ r);
   797 
   800 
   798     (*cases*)
   801     (*cases*)
   799     val C = Trueprop (Free (variant all_xs_more "C", HOLogic.boolT));
   802     val C = Trueprop (Free (variant all_xs_more "C", HOLogic.boolT));
   800     val cases_scheme_prop = All (all_xs_more ~~ all_types_more) ((r === rec_scheme) ==> C) ==> C;
   803     val cases_scheme_prop =
   801     val cases_prop = All (all_xs ~~ all_types) ((r' === rec_) ==> C) ==> C;
   804       All (all_xs_more ~~ all_types_more) ((r_scheme === rec_scheme) ==> C) ==> C;
       
   805     val cases_prop = All (all_xs ~~ all_types) ((r === rec_) ==> C) ==> C;
   802 
   806 
   803 
   807 
   804     (* 1st stage: fields_thy *)
   808     (* 1st stage: fields_thy *)
   805 
   809 
   806     val (fields_thy, field_simps, field_injects, field_splits, field_inducts, field_cases) =
   810     val (fields_thy, field_simps, field_injects, field_splits, field_inducts, field_cases) =
   811     val named_splits = map2 (fn (c, th) => (suffix field_typeN c, th)) (names, field_splits);
   815     val named_splits = map2 (fn (c, th) => (suffix field_typeN c, th)) (names, field_splits);
   812 
   816 
   813 
   817 
   814     (* 2nd stage: defs_thy *)
   818     (* 2nd stage: defs_thy *)
   815 
   819 
   816     val (defs_thy, (((sel_defs, update_defs), make_defs), [record_def])) =
   820     val (defs_thy, (((sel_defs, update_defs), derived_defs))) =
   817       fields_thy
   821       fields_thy
   818       |> add_record_splits named_splits
   822       |> add_record_splits named_splits
   819       |> Theory.parent_path
   823       |> Theory.parent_path
   820       |> Theory.add_tyabbrs_i recordT_specs     (*not made part of record name space!*)
   824       |> Theory.add_tyabbrs_i recordT_specs     (*not made part of record name space!*)
   821       |> Theory.add_path bname
   825       |> Theory.add_path bname
   822       |> Theory.add_trfuns ([], [], field_tr's, [])
   826       |> Theory.add_trfuns ([], [], field_tr's, [])
   823       |> (Theory.add_consts_i o map Syntax.no_syn)
   827       |> (Theory.add_consts_i o map Syntax.no_syn)
   824         (sel_decls @ update_decls @ make_decls @ [record_decl])
   828         (sel_decls @ update_decls @ [make_decl, extend_decl, truncate_decl])
   825       |> (PureThy.add_defs_i false o map Thm.no_attributes) sel_specs
   829       |> (PureThy.add_defs_i false o map Thm.no_attributes) sel_specs
   826       |>>> (PureThy.add_defs_i false o map Thm.no_attributes) update_specs
   830       |>>> (PureThy.add_defs_i false o map Thm.no_attributes) update_specs
   827       |>>> (PureThy.add_defs_i false o map Thm.no_attributes) make_specs
   831       |>>> (PureThy.add_defs_i false o map Thm.no_attributes)
   828       |>>> (PureThy.add_defs_i false o map Thm.no_attributes) [record_spec];
   832         [make_spec, extend_spec, truncate_spec];
   829 
   833 
   830     val defs_sg = Theory.sign_of defs_thy;
   834     val defs_sg = Theory.sign_of defs_thy;
   831 
   835 
   832 
   836 
   833     (* 3rd stage: thms_thy *)
   837     (* 3rd stage: thms_thy *)
   866     val thms_thy =
   870     val thms_thy =
   867       defs_thy
   871       defs_thy
   868       |> (#1 oo (PureThy.add_thmss o map Thm.no_attributes))
   872       |> (#1 oo (PureThy.add_thmss o map Thm.no_attributes))
   869         [("select_defs", sel_defs),
   873         [("select_defs", sel_defs),
   870           ("update_defs", update_defs),
   874           ("update_defs", update_defs),
   871           ("make_defs", make_defs),
   875           ("derived_defs", derived_defs),
   872           ("select_convs", sel_convs),
   876           ("select_convs", sel_convs),
   873           ("update_convs", update_convs)]
   877           ("update_convs", update_convs)]
   874       |> (#1 oo PureThy.add_thms)
   878       |> (#1 oo PureThy.add_thms)
   875           [(("equality", equality), [Classical.xtra_intro_global]),
   879           [(("equality", equality), [Classical.xtra_intro_global]),
   876            (("induct_scheme", induct_scheme),
   880            (("induct_scheme", induct_scheme),