src/HOL/Tools/record.ML
changeset 35138 ad213c602ec1
parent 35137 405bb7e38057
child 35142 495c623f1e3c
equal deleted inserted replaced
35137:405bb7e38057 35138:ad213c602ec1
     7 Extensible records with structural subtyping.
     7 Extensible records with structural subtyping.
     8 *)
     8 *)
     9 
     9 
    10 signature BASIC_RECORD =
    10 signature BASIC_RECORD =
    11 sig
    11 sig
       
    12   type record_info =
       
    13    {args: (string * sort) list,
       
    14     parent: (typ list * string) option,
       
    15     fields: (string * typ) list,
       
    16     extension: (string * typ list),
       
    17     ext_induct: thm, ext_inject: thm, ext_surjective: thm, ext_split: thm, ext_def: thm,
       
    18     select_convs: thm list, update_convs: thm list, select_defs: thm list, update_defs: thm list,
       
    19     fold_congs: thm list, unfold_congs: thm list, splits: thm list, defs: thm list,
       
    20     surjective: thm, equality: thm, induct_scheme: thm, induct: thm, cases_scheme: thm,
       
    21     cases: thm, simps: thm list, iffs: thm list}
       
    22   val get_record: theory -> string -> record_info option
       
    23   val the_record: theory -> string -> record_info
    12   val record_simproc: simproc
    24   val record_simproc: simproc
    13   val record_eq_simproc: simproc
    25   val record_eq_simproc: simproc
    14   val record_upd_simproc: simproc
    26   val record_upd_simproc: simproc
    15   val record_split_simproc: (term -> int) -> simproc
    27   val record_split_simproc: (term -> int) -> simproc
    16   val record_ex_sel_eq_simproc: simproc
    28   val record_ex_sel_eq_simproc: simproc
   335 type record_info =
   347 type record_info =
   336  {args: (string * sort) list,
   348  {args: (string * sort) list,
   337   parent: (typ list * string) option,
   349   parent: (typ list * string) option,
   338   fields: (string * typ) list,
   350   fields: (string * typ) list,
   339   extension: (string * typ list),
   351   extension: (string * typ list),
       
   352 
       
   353   ext_induct: thm,
       
   354   ext_inject: thm,
       
   355   ext_surjective: thm,
       
   356   ext_split: thm,
       
   357   ext_def: thm,
       
   358 
       
   359   select_convs: thm list,
       
   360   update_convs: thm list,
       
   361   select_defs: thm list,
       
   362   update_defs: thm list,
       
   363   fold_congs: thm list,
       
   364   unfold_congs: thm list,
       
   365   splits: thm list,
       
   366   defs: thm list,
       
   367 
       
   368   surjective: thm,
       
   369   equality: thm,
       
   370   induct_scheme: thm,
   340   induct: thm,
   371   induct: thm,
   341   extdef: thm};
   372   cases_scheme: thm,
   342 
   373   cases: thm,
   343 fun make_record_info args parent fields extension induct extdef =
   374 
       
   375   simps: thm list,
       
   376   iffs: thm list};
       
   377 
       
   378 fun make_record_info args parent fields extension
       
   379     ext_induct ext_inject ext_surjective ext_split ext_def
       
   380     select_convs update_convs select_defs update_defs fold_congs unfold_congs splits defs
       
   381     surjective equality induct_scheme induct cases_scheme cases
       
   382     simps iffs : record_info =
   344  {args = args, parent = parent, fields = fields, extension = extension,
   383  {args = args, parent = parent, fields = fields, extension = extension,
   345   induct = induct, extdef = extdef}: record_info;
   384   ext_induct = ext_induct, ext_inject = ext_inject, ext_surjective = ext_surjective,
   346 
   385   ext_split = ext_split, ext_def = ext_def, select_convs = select_convs,
       
   386   update_convs = update_convs, select_defs = select_defs, update_defs = update_defs,
       
   387   fold_congs = fold_congs, unfold_congs = unfold_congs, splits = splits, defs = defs,
       
   388   surjective = surjective, equality = equality, induct_scheme = induct_scheme,
       
   389   induct = induct, cases_scheme = cases_scheme, cases = cases, simps = simps, iffs = iffs};
   347 
   390 
   348 type parent_info =
   391 type parent_info =
   349  {name: string,
   392  {name: string,
   350   fields: (string * typ) list,
   393   fields: (string * typ) list,
   351   extension: (string * typ list),
   394   extension: (string * typ list),
   352   induct: thm,
   395   induct_scheme: thm,
   353   extdef: thm};
   396   ext_def: thm};
   354 
   397 
   355 fun make_parent_info name fields extension induct extdef =
   398 fun make_parent_info name fields extension ext_def induct_scheme : parent_info =
   356  {name = name, fields = fields, extension = extension,
   399  {name = name, fields = fields, extension = extension,
   357   induct = induct, extdef = extdef}: parent_info;
   400   ext_def = ext_def, induct_scheme = induct_scheme};
   358 
   401 
   359 
   402 
   360 (* theory data *)
   403 (* theory data *)
   361 
   404 
   362 type record_data =
   405 type record_data =
   454 
   497 
   455 (* access 'records' *)
   498 (* access 'records' *)
   456 
   499 
   457 val get_record = Symtab.lookup o #records o Records_Data.get;
   500 val get_record = Symtab.lookup o #records o Records_Data.get;
   458 
   501 
       
   502 fun the_record thy name =
       
   503   (case get_record thy name of
       
   504     SOME info => info
       
   505   | NONE => error ("Unknown record type " ^ quote name));
       
   506 
   459 fun put_record name info thy =
   507 fun put_record name info thy =
   460   let
   508   let
   461     val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields, fieldext} =
   509     val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields, fieldext} =
   462       Records_Data.get thy;
   510       Records_Data.get thy;
   463     val data = make_record_data (Symtab.update (name, info) records)
   511     val data = make_record_data (Symtab.update (name, info) records)
   623 fun add_parents _ NONE parents = parents
   671 fun add_parents _ NONE parents = parents
   624   | add_parents thy (SOME (types, name)) parents =
   672   | add_parents thy (SOME (types, name)) parents =
   625       let
   673       let
   626         fun err msg = error (msg ^ " parent record " ^ quote name);
   674         fun err msg = error (msg ^ " parent record " ^ quote name);
   627 
   675 
   628         val {args, parent, fields, extension, induct, extdef} =
   676         val {args, parent, fields, extension, induct_scheme, ext_def, ...} =
   629           (case get_record thy name of SOME info => info | NONE => err "Unknown");
   677           (case get_record thy name of SOME info => info | NONE => err "Unknown");
   630         val _ = if length types <> length args then err "Bad number of arguments for" else ();
   678         val _ = if length types <> length args then err "Bad number of arguments for" else ();
   631 
   679 
   632         fun bad_inst ((x, S), T) =
   680         fun bad_inst ((x, S), T) =
   633           if Sign.of_sort thy (T, S) then NONE else SOME x
   681           if Sign.of_sort thy (T, S) then NONE else SOME x
   639         val parent' = Option.map (apfst (map subst)) parent;
   687         val parent' = Option.map (apfst (map subst)) parent;
   640         val fields' = map (apsnd subst) fields;
   688         val fields' = map (apsnd subst) fields;
   641         val extension' = apsnd (map subst) extension;
   689         val extension' = apsnd (map subst) extension;
   642       in
   690       in
   643         add_parents thy parent'
   691         add_parents thy parent'
   644           (make_parent_info name fields' extension' induct extdef :: parents)
   692           (make_parent_info name fields' extension' ext_def induct_scheme :: parents)
   645       end;
   693       end;
   646 
   694 
   647 
   695 
   648 
   696 
   649 (** concrete syntax for records **)
   697 (** concrete syntax for records **)
  1781             resolve_tac prems 2 THEN
  1829             resolve_tac prems 2 THEN
  1782             asm_simp_tac HOL_ss 1)
  1830             asm_simp_tac HOL_ss 1)
  1783       end;
  1831       end;
  1784     val induct = timeit_msg "record extension induct proof:" induct_prf;
  1832     val induct = timeit_msg "record extension induct proof:" induct_prf;
  1785 
  1833 
  1786     val ([inject', induct', surjective', split_meta'], thm_thy) =
  1834     val ([induct', inject', surjective', split_meta'], thm_thy) =
  1787       defs_thy
  1835       defs_thy
  1788       |> PureThy.add_thms (map (Thm.no_attributes o apfst Binding.name)
  1836       |> PureThy.add_thms (map (Thm.no_attributes o apfst Binding.name)
  1789            [("ext_inject", inject),
  1837            [("ext_induct", induct),
  1790             ("ext_induct", induct),
  1838             ("ext_inject", inject),
  1791             ("ext_surjective", surject),
  1839             ("ext_surjective", surject),
  1792             ("ext_split", split_meta)])
  1840             ("ext_split", split_meta)])
  1793       ||> Code.add_default_eqn ext_def;
  1841       ||> Code.add_default_eqn ext_def;
  1794 
  1842 
  1795   in (thm_thy, extT, induct', inject', split_meta', ext_def) end;
  1843   in ((extT, induct', inject', surjective', split_meta', ext_def), thm_thy) end;
  1796 
  1844 
  1797 fun chunks [] [] = []
  1845 fun chunks [] [] = []
  1798   | chunks [] xs = [xs]
  1846   | chunks [] xs = [xs]
  1799   | chunks (l :: ls) xs = take l xs :: chunks ls (drop l xs);
  1847   | chunks (l :: ls) xs = take l xs :: chunks ls (drop l xs);
  1800 
  1848 
  1893     val all_named_vars_more = all_named_vars @ [(full_moreN, more)];
  1941     val all_named_vars_more = all_named_vars @ [(full_moreN, more)];
  1894 
  1942 
  1895 
  1943 
  1896     (* 1st stage: extension_thy *)
  1944     (* 1st stage: extension_thy *)
  1897 
  1945 
  1898     val (extension_thy, extT, ext_induct, ext_inject, ext_split, ext_def) =
  1946     val ((extT, ext_induct, ext_inject, ext_surjective, ext_split, ext_def), extension_thy) =
  1899       thy
  1947       thy
  1900       |> Sign.add_path base_name
  1948       |> Sign.add_path base_name
  1901       |> extension_definition extN fields alphas_ext zeta moreT more vars;
  1949       |> extension_definition extN fields alphas_ext zeta moreT more vars;
  1902 
  1950 
  1903     val _ = timing_msg "record preparing definitions";
  1951     val _ = timing_msg "record preparing definitions";
  1977     (*record (scheme) type abbreviation*)
  2025     (*record (scheme) type abbreviation*)
  1978     val recordT_specs =
  2026     val recordT_specs =
  1979       [(Binding.suffix_name schemeN b, alphas @ [zeta], rec_schemeT0, Syntax.NoSyn),
  2027       [(Binding.suffix_name schemeN b, alphas @ [zeta], rec_schemeT0, Syntax.NoSyn),
  1980         (b, alphas, recT0, Syntax.NoSyn)];
  2028         (b, alphas, recT0, Syntax.NoSyn)];
  1981 
  2029 
  1982     val ext_defs = ext_def :: map #extdef parents;
  2030     val ext_defs = ext_def :: map #ext_def parents;
  1983 
  2031 
  1984     (*Theorems from the iso_tuple intros.
  2032     (*Theorems from the iso_tuple intros.
  1985       By unfolding ext_defs from r_rec0 we create a tree of constructor
  2033       By unfolding ext_defs from r_rec0 we create a tree of constructor
  1986       calls (many of them Pair, but others as well). The introduction
  2034       calls (many of them Pair, but others as well). The introduction
  1987       rules for update_accessor_eq_assist can unify two different ways
  2035       rules for update_accessor_eq_assist can unify two different ways
  2180         val ua_congs = map (Drule.export_without_context o simplify fold_ss) upd_acc_cong_assists;
  2228         val ua_congs = map (Drule.export_without_context o simplify fold_ss) upd_acc_cong_assists;
  2181       in (ua_congs RL [updacc_foldE], ua_congs RL [updacc_unfoldE]) end;
  2229       in (ua_congs RL [updacc_foldE], ua_congs RL [updacc_unfoldE]) end;
  2182     val (fold_congs, unfold_congs) =
  2230     val (fold_congs, unfold_congs) =
  2183       timeit_msg "record upd fold/unfold congs:" get_upd_acc_congs;
  2231       timeit_msg "record upd fold/unfold congs:" get_upd_acc_congs;
  2184 
  2232 
  2185     val parent_induct = if null parents then [] else [#induct (hd (rev parents))];
  2233     val parent_induct = Option.map #induct_scheme (try List.last parents);
  2186 
  2234 
  2187     fun induct_scheme_prf () =
  2235     fun induct_scheme_prf () =
  2188       prove_standard [] induct_scheme_prop
  2236       prove_standard [] induct_scheme_prop
  2189         (fn _ =>
  2237         (fn _ =>
  2190           EVERY
  2238           EVERY
  2191            [if null parent_induct then all_tac else try_param_tac rN (hd parent_induct) 1,
  2239            [case parent_induct of NONE => all_tac | SOME ind => try_param_tac rN ind 1,
  2192             try_param_tac rN ext_induct 1,
  2240             try_param_tac rN ext_induct 1,
  2193             asm_simp_tac HOL_basic_ss 1]);
  2241             asm_simp_tac HOL_basic_ss 1]);
  2194     val induct_scheme = timeit_msg "record induct_scheme proof:" induct_scheme_prf;
  2242     val induct_scheme = timeit_msg "record induct_scheme proof:" induct_scheme_prf;
  2195 
  2243 
  2196     fun induct_prf () =
  2244     fun induct_prf () =
  2309           end);
  2357           end);
  2310     val equality = timeit_msg "record equality proof:" equality_prf;
  2358     val equality = timeit_msg "record equality proof:" equality_prf;
  2311 
  2359 
  2312     val ((([sel_convs', upd_convs', sel_defs', upd_defs',
  2360     val ((([sel_convs', upd_convs', sel_defs', upd_defs',
  2313             fold_congs', unfold_congs',
  2361             fold_congs', unfold_congs',
  2314           [split_meta', split_object', split_ex'], derived_defs'],
  2362           splits' as [split_meta', split_object', split_ex'], derived_defs'],
  2315           [surjective', equality']),
  2363           [surjective', equality']),
  2316           [induct_scheme', induct', cases_scheme', cases']), thms_thy) =
  2364           [induct_scheme', induct', cases_scheme', cases']), thms_thy) =
  2317       defs_thy
  2365       defs_thy
  2318       |> (PureThy.add_thmss o map (Thm.no_attributes o apfst Binding.name))
  2366       |> (PureThy.add_thmss o map (Thm.no_attributes o apfst Binding.name))
  2319          [("select_convs", sel_convs_standard),
  2367          [("select_convs", sel_convs_standard),
  2335 
  2383 
  2336     val sel_upd_simps = sel_convs' @ upd_convs';
  2384     val sel_upd_simps = sel_convs' @ upd_convs';
  2337     val sel_upd_defs = sel_defs' @ upd_defs';
  2385     val sel_upd_defs = sel_defs' @ upd_defs';
  2338     val iffs = [ext_inject]
  2386     val iffs = [ext_inject]
  2339     val depth = parent_len + 1;
  2387     val depth = parent_len + 1;
       
  2388 
       
  2389     val ([simps', iffs'], thms_thy') =
       
  2390       thms_thy
       
  2391       |> PureThy.add_thmss
       
  2392           [((Binding.name "simps", sel_upd_simps), [Simplifier.simp_add]),
       
  2393            ((Binding.name "iffs", iffs), [iff_add])];
       
  2394 
       
  2395     val info =
       
  2396       make_record_info args parent fields extension
       
  2397         ext_induct ext_inject ext_surjective ext_split ext_def
       
  2398         sel_convs' upd_convs' sel_defs' upd_defs' fold_congs' unfold_congs' splits' derived_defs'
       
  2399         surjective' equality' induct_scheme' induct' cases_scheme' cases' simps' iffs';
       
  2400 
  2340     val final_thy =
  2401     val final_thy =
  2341       thms_thy
  2402       thms_thy'
  2342       |> (snd oo PureThy.add_thmss)
  2403       |> put_record name info
  2343           [((Binding.name "simps", sel_upd_simps), [Simplifier.simp_add]),
       
  2344            ((Binding.name "iffs", iffs), [iff_add])]
       
  2345       |> put_record name (make_record_info args parent fields extension induct_scheme' ext_def)
       
  2346       |> put_sel_upd names full_moreN depth sel_upd_simps sel_upd_defs (fold_congs', unfold_congs')
  2404       |> put_sel_upd names full_moreN depth sel_upd_simps sel_upd_defs (fold_congs', unfold_congs')
  2347       |> add_record_equalities extension_id equality'
  2405       |> add_record_equalities extension_id equality'
  2348       |> add_extinjects ext_inject
  2406       |> add_extinjects ext_inject
  2349       |> add_extsplit extension_name ext_split
  2407       |> add_extsplit extension_name ext_split
  2350       |> add_record_splits extension_id (split_meta', split_object', split_ex', induct_scheme')
  2408       |> add_record_splits extension_id (split_meta', split_object', split_ex', induct_scheme')