62 fun message s = if ! quiet_mode then () else writeln s; |
64 fun message s = if ! quiet_mode then () else writeln s; |
63 |
65 |
64 |
66 |
65 (* fundamental syntax *) |
67 (* fundamental syntax *) |
66 |
68 |
67 infix 0 :== ===; |
69 fun prefix_base s = NameSpace.map_base (fn bname => s ^ bname); |
68 |
70 |
|
71 val Trueprop = HOLogic.mk_Trueprop; |
|
72 fun All xs t = Term.list_all_free (xs, t); |
|
73 |
|
74 infix 0 :== === ==>; |
69 val (op :==) = Logic.mk_defpair; |
75 val (op :==) = Logic.mk_defpair; |
70 val (op ===) = HOLogic.mk_Trueprop o HOLogic.mk_eq; |
76 val (op ===) = Trueprop o HOLogic.mk_eq; |
71 |
77 val (op ==>) = Logic.mk_implies; |
72 fun prefix_base s = NameSpace.map_base (fn bname => s ^ bname); |
78 |
73 |
79 |
74 |
80 (* proof tools *) |
75 (* proof by simplification *) |
81 |
|
82 fun prove_goal sign goal tacs = |
|
83 Goals.prove_goalw_cterm [] (Thm.cterm_of sign goal) tacs |
|
84 handle ERROR => error ("The error(s) above occurred while trying to prove " ^ |
|
85 quote (Sign.string_of_term sign goal)); |
76 |
86 |
77 fun prove_simp sign ss tacs simps = |
87 fun prove_simp sign ss tacs simps = |
78 let |
88 let |
79 val ss' = Simplifier.addsimps (ss, simps); |
89 val ss' = Simplifier.addsimps (ss, simps); |
80 |
90 fun prove goal = prove_goal sign goal |
81 fun prove goal = |
91 (K (tacs @ [ALLGOALS (Simplifier.asm_full_simp_tac ss')])); |
82 Goals.prove_goalw_cterm [] (Thm.cterm_of sign goal) |
|
83 (K (tacs @ [ALLGOALS (Simplifier.asm_full_simp_tac ss')])) |
|
84 handle ERROR => error ("The error(s) above occurred while trying to prove " |
|
85 ^ quote (Sign.string_of_term sign goal)); |
|
86 in prove end; |
92 in prove end; |
87 |
93 |
|
94 fun try_param_tac x s rule i st = |
|
95 res_inst_tac [(x, (case Tactic.innermost_params i st of [] => s | (p, _) :: _ => p))] rule i st; |
|
96 |
88 |
97 |
89 |
98 |
90 (*** syntax operations ***) |
99 (*** syntax operations ***) |
91 |
100 |
92 (** name components **) |
101 (** name components **) |
93 |
102 |
94 val recordN = "record"; |
103 val rN = "r"; |
95 val moreN = "more"; |
104 val moreN = "more"; |
96 val schemeN = "_scheme"; |
105 val schemeN = "_scheme"; |
97 val field_typeN = "_field_type"; |
106 val field_typeN = "_field_type"; |
98 val fieldN = "_field"; |
107 val fieldN = "_field"; |
99 val fstN = "_val"; |
108 val fstN = "_val"; |
100 val sndN = "_more"; |
109 val sndN = "_more"; |
101 val updateN = "_update"; |
110 val updateN = "_update"; |
102 val makeN = "make"; |
111 val makeN = "make"; |
103 val make_schemeN = "make_scheme"; |
112 val make_schemeN = "make_scheme"; |
|
113 val recordN = "record"; |
104 |
114 |
105 (*see typedef_package.ML*) |
115 (*see typedef_package.ML*) |
106 val RepN = "Rep_"; |
116 val RepN = "Rep_"; |
107 val AbsN = "Abs_"; |
117 val AbsN = "Abs_"; |
108 |
118 |
384 [Pretty.block [prt_typ (Type (name, Ts)), Pretty.str " +"]]; |
404 [Pretty.block [prt_typ (Type (name, Ts)), Pretty.str " +"]]; |
385 |
405 |
386 fun pretty_field (c, T) = Pretty.block |
406 fun pretty_field (c, T) = Pretty.block |
387 [Pretty.str (ext_const c), Pretty.str " ::", Pretty.brk 1, Pretty.quote (prt_typ T)]; |
407 [Pretty.str (ext_const c), Pretty.str " ::", Pretty.brk 1, Pretty.quote (prt_typ T)]; |
388 |
408 |
389 fun pretty_record (name, {args, parent, fields, simps = _}) = Pretty.block (Pretty.fbreaks |
409 fun pretty_record (name, {args, parent, fields, simps = _, induct = _, cases = _}) = |
390 (Pretty.block [prt_typ (Type (name, map TFree args)), Pretty.str " = "] :: |
410 Pretty.block (Pretty.fbreaks (Pretty.block |
|
411 [prt_typ (Type (name, map TFree args)), Pretty.str " = "] :: |
391 pretty_parent parent @ map pretty_field fields)); |
412 pretty_parent parent @ map pretty_field fields)); |
392 in |
413 in |
393 map pretty_record (Sign.cond_extern_table sg Sign.typeK recs) |
414 map pretty_record (Sign.cond_extern_table sg Sign.typeK recs) |
394 |> Pretty.chunks |> Pretty.writeln |
415 |> Pretty.chunks |> Pretty.writeln |
395 end; |
416 end; |
463 val inst = map fst args ~~ types; |
484 val inst = map fst args ~~ types; |
464 val subst = Term.map_type_tfree (fn (x, _) => the (assoc (inst, x))); |
485 val subst = Term.map_type_tfree (fn (x, _) => the (assoc (inst, x))); |
465 in |
486 in |
466 if not (null bads) then |
487 if not (null bads) then |
467 err ("Ill-sorted instantiation of " ^ commas bads ^ " in") |
488 err ("Ill-sorted instantiation of " ^ commas bads ^ " in") |
468 else (apsome (apfst (map subst)) parent, map (apsnd subst) fields, simps) |
489 else (apsome (apfst (map subst)) parent, map (apsnd subst) fields, simps, induct, cases) |
469 end; |
490 end; |
470 |
491 |
471 fun add_parents thy (None, parents) = parents |
492 fun add_parents thy (None, parents) = parents |
472 | add_parents thy (Some (types, name), parents) = |
493 | add_parents thy (Some (types, name), parents) = |
473 let val (pparent, pfields, psimps) = inst_record thy (types, name) |
494 let val (parent, fields, simps, induct, cases) = inst_record thy (types, name) |
474 in add_parents thy (pparent, {name = name, fields = pfields, simps = psimps} :: parents) end; |
495 in add_parents thy (parent, make_parent_info name fields simps induct cases :: parents) end; |
475 |
496 |
476 |
497 |
477 |
498 |
478 (** record simproc **) |
499 (** record simproc **) |
479 |
500 |
608 |
629 |
609 fun make th = map (fn prod_type => Drule.standard (th OF [prod_type])) prod_types; |
630 fun make th = map (fn prod_type => Drule.standard (th OF [prod_type])) prod_types; |
610 |
631 |
611 val field_injects = make product_type_inject; |
632 val field_injects = make product_type_inject; |
612 val dest_convs = make product_type_conv1 @ make product_type_conv2; |
633 val dest_convs = make product_type_conv1 @ make product_type_conv2; |
|
634 val field_inducts = make product_type_induct; |
|
635 val field_cases = make product_type_cases; |
613 val field_splits = make product_type_split_paired_all; |
636 val field_splits = make product_type_split_paired_all; |
614 |
637 |
615 val thms_thy = |
638 val thms_thy = |
616 defs_thy |
639 defs_thy |
617 |> (#1 oo (PureThy.add_thmss o map Thm.no_attributes)) |
640 |> (PureThy.add_thmss o map Thm.no_attributes) |
618 [("field_defs", field_defs), |
641 [("field_defs", field_defs), |
619 ("dest_defs", dest_defs1 @ dest_defs2), |
642 ("dest_defs", dest_defs1 @ dest_defs2), |
620 ("dest_convs", dest_convs), |
643 ("dest_convs", dest_convs), |
621 ("field_splits", field_splits)]; |
644 ("field_inducts", field_inducts), |
622 |
645 ("field_cases", field_cases), |
623 in (thms_thy, dest_convs, field_injects, field_splits) end; |
646 ("field_splits", field_splits)] |> #1; |
|
647 |
|
648 in (thms_thy, dest_convs, field_injects, field_splits, field_inducts, field_cases) end; |
624 |
649 |
625 |
650 |
626 (* record_definition *) |
651 (* record_definition *) |
627 |
652 |
628 fun record_definition (args, bname) parent (parents: parent_info list) bfields thy = |
653 fun record_definition (args, bname) parent (parents: parent_info list) bfields thy = |
634 |
659 |
635 (* basic components *) |
660 (* basic components *) |
636 |
661 |
637 val alphas = map fst args; |
662 val alphas = map fst args; |
638 val name = Sign.full_name sign bname; (*not made part of record name space!*) |
663 val name = Sign.full_name sign bname; (*not made part of record name space!*) |
|
664 |
|
665 val previous = if null parents then None else Some (last_elem parents); |
639 |
666 |
640 val parent_fields = flat (map #fields parents); |
667 val parent_fields = flat (map #fields parents); |
641 val parent_names = map fst parent_fields; |
668 val parent_names = map fst parent_fields; |
642 val parent_types = map snd parent_fields; |
669 val parent_types = map snd parent_fields; |
643 val parent_len = length parent_fields; |
670 val parent_len = length parent_fields; |
644 val parent_xs = variantlist (map (base o fst) parent_fields, [moreN, recordN]); |
671 val parent_xs = variantlist (map (base o fst) parent_fields, [moreN, rN]); |
645 val parent_vars = ListPair.map Free (parent_xs, parent_types); |
672 val parent_vars = ListPair.map Free (parent_xs, parent_types); |
646 val parent_named_vars = parent_names ~~ parent_vars; |
673 val parent_named_vars = parent_names ~~ parent_vars; |
647 |
674 |
648 val fields = map (apfst full) bfields; |
675 val fields = map (apfst full) bfields; |
649 val names = map fst fields; |
676 val names = map fst fields; |
650 val types = map snd fields; |
677 val types = map snd fields; |
651 val len = length fields; |
678 val len = length fields; |
652 val xs = variantlist (map fst bfields, moreN :: recordN :: parent_xs); |
679 val xs = variantlist (map fst bfields, moreN :: rN :: parent_xs); |
653 val vars = ListPair.map Free (xs, types); |
680 val vars = ListPair.map Free (xs, types); |
654 val named_vars = names ~~ vars; |
681 val named_vars = names ~~ vars; |
655 |
682 |
656 val all_fields = parent_fields @ fields; |
683 val all_fields = parent_fields @ fields; |
657 val all_names = parent_names @ names; |
684 val all_names = parent_names @ names; |
665 val moreT = TFree (zeta, moreS); |
692 val moreT = TFree (zeta, moreS); |
666 val more = Free (moreN, moreT); |
693 val more = Free (moreN, moreT); |
667 val full_moreN = full moreN; |
694 val full_moreN = full moreN; |
668 fun more_part t = mk_more t full_moreN; |
695 fun more_part t = mk_more t full_moreN; |
669 fun more_part_update t x = mk_more_update t (full_moreN, x); |
696 fun more_part_update t x = mk_more_update t (full_moreN, x); |
|
697 val all_types_more = all_types @ [moreT]; |
|
698 val all_xs_more = all_xs @ [moreN]; |
670 |
699 |
671 val parent_more = funpow parent_len mk_snd; |
700 val parent_more = funpow parent_len mk_snd; |
672 val idxs = 0 upto (len - 1); |
701 val idxs = 0 upto (len - 1); |
673 |
702 |
674 val rec_schemeT = mk_recordT (all_fields, moreT); |
703 val rec_schemeT = mk_recordT (all_fields, moreT); |
675 val rec_scheme = mk_record (all_named_vars, more); |
704 val rec_scheme = mk_record (all_named_vars, more); |
676 val r = Free (recordN, rec_schemeT); |
|
677 val recT = mk_recordT (all_fields, HOLogic.unitT); |
705 val recT = mk_recordT (all_fields, HOLogic.unitT); |
|
706 val rec_ = mk_record (all_named_vars, HOLogic.unit); |
|
707 val r = Free (rN, rec_schemeT); |
|
708 val r' = Free (rN, recT); |
678 |
709 |
679 |
710 |
680 (* prepare print translation functions *) |
711 (* prepare print translation functions *) |
681 |
712 |
682 val field_tr's = |
713 val field_tr's = |
744 in [more_part_update rec_scheme more' === mk_record (all_named_vars, more')] end; |
778 in [more_part_update rec_scheme more' === mk_record (all_named_vars, more')] end; |
745 |
779 |
746 (*equality*) |
780 (*equality*) |
747 fun mk_sel_eq (t, T) = |
781 fun mk_sel_eq (t, T) = |
748 let val t' = Term.abstract_over (r, t) |
782 let val t' = Term.abstract_over (r, t) |
749 in HOLogic.mk_Trueprop (HOLogic.eq_const T $ Term.incr_boundvars 1 t' $ t') end; |
783 in Trueprop (HOLogic.eq_const T $ Term.incr_boundvars 1 t' $ t') end; |
750 val sel_eqs = map2 mk_sel_eq (map (mk_sel r) all_names @ [more_part r], all_types @ [moreT]); |
784 val sel_eqs = map2 mk_sel_eq (map (mk_sel r) all_names @ [more_part r], all_types @ [moreT]); |
751 val equality_prop = |
785 val equality_prop = |
752 Term.all rec_schemeT $ (Abs ("r", rec_schemeT, |
786 Term.all rec_schemeT $ (Abs ("r", rec_schemeT, |
753 Term.all rec_schemeT $ (Abs ("r'", rec_schemeT, |
787 Term.all rec_schemeT $ (Abs ("r'", rec_schemeT, |
754 Logic.list_implies (sel_eqs, |
788 Logic.list_implies (sel_eqs, |
755 HOLogic.mk_Trueprop (HOLogic.eq_const rec_schemeT $ Bound 1 $ Bound 0)))))); |
789 Trueprop (HOLogic.eq_const rec_schemeT $ Bound 1 $ Bound 0)))))); |
|
790 |
|
791 (*induct*) |
|
792 val P = Free ("P", rec_schemeT --> HOLogic.boolT); |
|
793 val P' = Free ("P", recT --> HOLogic.boolT); |
|
794 val induct_scheme_prop = |
|
795 All (all_xs_more ~~ all_types_more) (Trueprop (P $ rec_scheme)) ==> Trueprop (P $ r); |
|
796 val induct_prop = All (all_xs ~~ all_types) (Trueprop (P' $ rec_)) ==> Trueprop (P' $ r'); |
|
797 |
|
798 (*cases*) |
|
799 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; |
|
801 val cases_prop = All (all_xs ~~ all_types) ((r' === rec_) ==> C) ==> C; |
756 |
802 |
757 |
803 |
758 (* 1st stage: fields_thy *) |
804 (* 1st stage: fields_thy *) |
759 |
805 |
760 val (fields_thy, field_simps, field_injects, field_splits) = |
806 val (fields_thy, field_simps, field_injects, field_splits, field_inducts, field_cases) = |
761 thy |
807 thy |
762 |> Theory.add_path bname |
808 |> Theory.add_path bname |
763 |> field_definitions fields names xs alphas zeta moreT more vars named_vars; |
809 |> field_definitions fields names xs alphas zeta moreT more vars named_vars; |
764 |
810 |
765 val named_splits = map2 (fn (c, th) => (suffix field_typeN c, th)) (names, field_splits); |
811 val named_splits = map2 (fn (c, th) => (suffix field_typeN c, th)) (names, field_splits); |
766 |
812 |
767 |
813 |
768 (* 2nd stage: defs_thy *) |
814 (* 2nd stage: defs_thy *) |
769 |
815 |
770 val (defs_thy, ((sel_defs, update_defs), make_defs)) = |
816 val (defs_thy, (((sel_defs, update_defs), make_defs), [record_def])) = |
771 fields_thy |
817 fields_thy |
772 |> add_record_splits named_splits |
818 |> add_record_splits named_splits |
773 |> Theory.parent_path |
819 |> Theory.parent_path |
774 |> Theory.add_tyabbrs_i recordT_specs (*not made part of record name space!*) |
820 |> Theory.add_tyabbrs_i recordT_specs (*not made part of record name space!*) |
775 |> Theory.add_path bname |
821 |> Theory.add_path bname |
776 |> Theory.add_trfuns ([], [], field_tr's, []) |
822 |> Theory.add_trfuns ([], [], field_tr's, []) |
777 |> (Theory.add_consts_i o map Syntax.no_syn) |
823 |> (Theory.add_consts_i o map Syntax.no_syn) |
778 (sel_decls @ update_decls @ make_decls) |
824 (sel_decls @ update_decls @ make_decls @ [record_decl]) |
779 |> (PureThy.add_defs_i false o map Thm.no_attributes) sel_specs |
825 |> (PureThy.add_defs_i false o map Thm.no_attributes) sel_specs |
780 |>>> (PureThy.add_defs_i false o map Thm.no_attributes) update_specs |
826 |>>> (PureThy.add_defs_i false o map Thm.no_attributes) update_specs |
781 |>>> (PureThy.add_defs_i false o map Thm.no_attributes) make_specs; |
827 |>>> (PureThy.add_defs_i false o map Thm.no_attributes) make_specs |
|
828 |>>> (PureThy.add_defs_i false o map Thm.no_attributes) [record_spec]; |
|
829 |
|
830 val defs_sg = Theory.sign_of defs_thy; |
782 |
831 |
783 |
832 |
784 (* 3rd stage: thms_thy *) |
833 (* 3rd stage: thms_thy *) |
785 |
834 |
786 val parent_simps = flat (map #simps parents); |
835 val parent_simps = flat (map #simps parents); |
787 val prove = prove_simp (Theory.sign_of defs_thy) HOL_basic_ss []; |
836 val prove = prove_simp defs_sg HOL_basic_ss []; |
788 val prove' = prove_simp (Theory.sign_of defs_thy) HOL_ss; |
837 val prove' = prove_simp defs_sg HOL_ss; |
789 |
838 |
790 val sel_convs = map (prove (parent_simps @ sel_defs @ field_simps)) sel_props; |
839 val sel_convs = map (prove (parent_simps @ sel_defs @ field_simps)) sel_props; |
791 val update_convs = map (prove (parent_simps @ update_defs @ sel_convs)) update_props; |
840 val update_convs = map (prove (parent_simps @ update_defs @ sel_convs)) update_props; |
792 val equality = |
841 val equality = |
793 prove' [ALLGOALS record_split_tac] (parent_simps @ sel_convs @ field_injects) equality_prop; |
842 prove' [ALLGOALS record_split_tac] (parent_simps @ sel_convs @ field_injects) equality_prop; |
794 |
843 |
795 val simps = field_simps @ sel_convs @ update_convs @ make_defs @ [equality]; |
844 val induct_scheme = prove_goal defs_sg induct_scheme_prop (fn prems => |
|
845 (case previous of Some {induct, ...} => res_inst_tac [(rN, rN)] induct 1 |
|
846 | None => all_tac) :: map (fn rule => try_param_tac "p" rN rule 1) field_inducts @ |
|
847 [resolve_tac prems 1]); |
|
848 |
|
849 val induct = prove_goal defs_sg induct_prop (fn prems => |
|
850 [res_inst_tac [(rN, rN)] induct_scheme 1, |
|
851 try_param_tac "x" "more" unit_induct 1, resolve_tac prems 1]); |
|
852 |
|
853 val cases_scheme = prove_goal defs_sg cases_scheme_prop (fn prems => |
|
854 Method.insert_tac prems 1 :: |
|
855 (case previous of Some {cases, ...} => try_param_tac rN rN cases 1 |
|
856 | None => all_tac) :: map (fn rule => try_param_tac "p" rN rule 1) field_cases @ |
|
857 [Simplifier.asm_full_simp_tac HOL_basic_ss 1]); |
|
858 |
|
859 val cases = prove_goal defs_sg cases_prop (fn prems => |
|
860 [Method.insert_tac prems 1, res_inst_tac [(rN, rN)] cases_scheme 1, |
|
861 Simplifier.asm_full_simp_tac (HOL_basic_ss addsimps [unit_all_eq1]) 1]); |
|
862 |
|
863 val simps = field_simps @ sel_convs @ update_convs @ [equality]; |
796 val iffs = field_injects; |
864 val iffs = field_injects; |
797 |
865 |
798 val thms_thy = |
866 val thms_thy = |
799 defs_thy |
867 defs_thy |
800 |> (#1 oo (PureThy.add_thmss o map Thm.no_attributes)) |
868 |> (#1 oo (PureThy.add_thmss o map Thm.no_attributes)) |
802 ("update_defs", update_defs), |
870 ("update_defs", update_defs), |
803 ("make_defs", make_defs), |
871 ("make_defs", make_defs), |
804 ("select_convs", sel_convs), |
872 ("select_convs", sel_convs), |
805 ("update_convs", update_convs)] |
873 ("update_convs", update_convs)] |
806 |> (#1 oo PureThy.add_thms) |
874 |> (#1 oo PureThy.add_thms) |
807 [(("equality", equality), [Classical.xtra_intro_global])] |
875 [(("equality", equality), [Classical.xtra_intro_global]), |
|
876 (("induct_scheme", induct_scheme), |
|
877 [InductAttrib.induct_type_global (suffix schemeN name)]), |
|
878 (("induct", induct), [InductAttrib.induct_type_global name]), |
|
879 (("cases_scheme", cases_scheme), |
|
880 [InductAttrib.cases_type_global (suffix schemeN name)]), |
|
881 (("cases", cases), [InductAttrib.cases_type_global name])] |
808 |> (#1 oo PureThy.add_thmss) |
882 |> (#1 oo PureThy.add_thmss) |
809 [(("simps", simps), [Simplifier.simp_add_global]), |
883 [(("simps", simps), [Simplifier.simp_add_global]), |
810 (("iffs", iffs), [iff_add_global])]; |
884 (("iffs", iffs), [iff_add_global])]; |
811 |
885 |
812 |
886 |
813 (* 4th stage: final_thy *) |
887 (* 4th stage: final_thy *) |
814 |
888 |
815 val final_thy = |
889 val final_thy = |
816 thms_thy |
890 thms_thy |
817 |> put_record name {args = args, parent = parent, fields = fields, simps = simps} |
891 |> put_record name (make_record_info args parent fields simps induct_scheme cases_scheme) |
818 |> put_sel_upd (names @ [full_moreN]) (field_simps @ sel_defs @ update_defs) |
892 |> put_sel_upd (names @ [full_moreN]) (field_simps @ sel_defs @ update_defs) |
819 |> Theory.parent_path; |
893 |> Theory.parent_path; |
820 |
894 |
821 in (final_thy, {simps = simps, iffs = iffs}) end; |
895 in (final_thy, {simps = simps, iffs = iffs}) end; |
822 |
896 |