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