7 |
7 |
8 signature BNF_FP_SUGAR = |
8 signature BNF_FP_SUGAR = |
9 sig |
9 sig |
10 val datatypes: bool -> |
10 val datatypes: bool -> |
11 (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list -> |
11 (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list -> |
12 BNF_Def.BNF list -> local_theory -> |
12 BNF_Def.BNF list -> local_theory -> BNF_FP.fp_result * local_theory) -> |
13 (BNF_Def.BNF list * term list * term list * term list * term list * thm * thm list * |
|
14 thm list * thm list * thm list * thm list list * thm list * thm list * thm list) * |
|
15 local_theory) -> |
|
16 bool * ((((typ * sort) list * binding) * mixfix) * ((((binding * binding) * |
13 bool * ((((typ * sort) list * binding) * mixfix) * ((((binding * binding) * |
17 (binding * typ) list) * (binding * term) list) * mixfix) list) list -> |
14 (binding * typ) list) * (binding * term) list) * mixfix) list) list -> |
18 local_theory -> local_theory |
15 local_theory -> local_theory |
19 val parse_datatype_cmd: bool -> |
16 val parse_datatype_cmd: bool -> |
20 (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list -> |
17 (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list -> |
21 BNF_Def.BNF list -> local_theory -> |
18 BNF_Def.BNF list -> local_theory -> BNF_FP.fp_result * local_theory) -> |
22 (BNF_Def.BNF list * term list * term list * term list * term list * thm * thm list * |
|
23 thm list * thm list * thm list * thm list list * thm list * thm list * thm list) * |
|
24 local_theory) -> |
|
25 (local_theory -> local_theory) parser |
19 (local_theory -> local_theory) parser |
26 end; |
20 end; |
27 |
21 |
28 structure BNF_FP_Sugar : BNF_FP_SUGAR = |
22 structure BNF_FP_Sugar : BNF_FP_SUGAR = |
29 struct |
23 struct |
94 fun mk_map live Ts Us t = |
90 fun mk_map live Ts Us t = |
95 let val (Type (_, Ts0), Type (_, Us0)) = strip_typeN (live + 1) (fastype_of t) |>> List.last in |
91 let val (Type (_, Ts0), Type (_, Us0)) = strip_typeN (live + 1) (fastype_of t) |>> List.last in |
96 Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t |
92 Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t |
97 end; |
93 end; |
98 |
94 |
|
95 fun mk_rel live Ts Us t = |
|
96 let val [Type (_, Ts0), Type (_, Us0)] = binder_types (snd (strip_typeN live (fastype_of t))) in |
|
97 Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t |
|
98 end; |
|
99 |
99 fun liveness_of_fp_bnf n bnf = |
100 fun liveness_of_fp_bnf n bnf = |
100 (case T_of_bnf bnf of |
101 (case T_of_bnf bnf of |
101 Type (_, Ts) => map (not o member (op =) (deads_of_bnf bnf)) Ts |
102 Type (_, Ts) => map (not o member (op =) (deads_of_bnf bnf)) Ts |
102 | _ => replicate n false); |
103 | _ => replicate n false); |
103 |
104 |
116 if length As = length As' then map2 merge_type_arg As As' else cannot_merge_types (); |
117 if length As = length As' then map2 merge_type_arg As As' else cannot_merge_types (); |
117 |
118 |
118 fun is_triv_implies thm = |
119 fun is_triv_implies thm = |
119 op aconv (Logic.dest_implies (Thm.prop_of thm)) |
120 op aconv (Logic.dest_implies (Thm.prop_of thm)) |
120 handle TERM _ => false; |
121 handle TERM _ => false; |
|
122 |
|
123 fun reassoc_conjs thm = |
|
124 reassoc_conjs (thm RS @{thm conj_assoc[THEN iffD1]}) |
|
125 handle THM _ => thm; |
121 |
126 |
122 fun type_args_constrained_of (((cAs, _), _), _) = cAs; |
127 fun type_args_constrained_of (((cAs, _), _), _) = cAs; |
123 fun type_binding_of (((_, b), _), _) = b; |
128 fun type_binding_of (((_, b), _), _) = b; |
124 fun mixfix_of ((_, mx), _) = mx; |
129 fun mixfix_of ((_, mx), _) = mx; |
125 fun ctr_specs_of (_, ctr_specs) = ctr_specs; |
130 fun ctr_specs_of (_, ctr_specs) = ctr_specs; |
203 val _ = (case subtract (op =) (map dest_TFree As) rhs_As' of |
208 val _ = (case subtract (op =) (map dest_TFree As) rhs_As' of |
204 [] => () |
209 [] => () |
205 | A' :: _ => error ("Extra type variable on right-hand side: " ^ |
210 | A' :: _ => error ("Extra type variable on right-hand side: " ^ |
206 quote (Syntax.string_of_typ no_defs_lthy (TFree A')))); |
211 quote (Syntax.string_of_typ no_defs_lthy (TFree A')))); |
207 |
212 |
208 fun eq_fpT (T as Type (s, Us)) (Type (s', Us')) = |
213 fun eq_fpT_check (T as Type (s, Us)) (Type (s', Us')) = |
209 s = s' andalso (Us = Us' orelse error ("Illegal occurrence of recursive type " ^ |
214 s = s' andalso (Us = Us' orelse error ("Illegal occurrence of recursive type " ^ |
210 quote (Syntax.string_of_typ fake_lthy T))) |
215 quote (Syntax.string_of_typ fake_lthy T))) |
211 | eq_fpT _ _ = false; |
216 | eq_fpT_check _ _ = false; |
212 |
217 |
213 fun freeze_fp (T as Type (s, Us)) = |
218 fun freeze_fp (T as Type (s, Us)) = |
214 (case find_index (eq_fpT T) fake_Ts of ~1 => Type (s, map freeze_fp Us) | j => nth Xs j) |
219 (case find_index (eq_fpT_check T) fake_Ts of |
|
220 ~1 => Type (s, map freeze_fp Us) |
|
221 | kk => nth Xs kk) |
215 | freeze_fp T = T; |
222 | freeze_fp T = T; |
216 |
223 |
217 val ctr_TsssXs = map (map (map freeze_fp)) fake_ctr_Tsss; |
224 val ctr_TsssXs = map (map (map freeze_fp)) fake_ctr_Tsss; |
218 val ctr_sum_prod_TsXs = map (mk_sumTN_balanced o map HOLogic.mk_tupleT) ctr_TsssXs; |
225 val ctr_sum_prod_TsXs = map (mk_sumTN_balanced o map HOLogic.mk_tupleT) ctr_TsssXs; |
219 |
226 |
220 val fp_eqs = |
227 val fp_eqs = |
221 map dest_TFree Xs ~~ map (Term.typ_subst_atomic (As ~~ unsorted_As)) ctr_sum_prod_TsXs; |
228 map dest_TFree Xs ~~ map (Term.typ_subst_atomic (As ~~ unsorted_As)) ctr_sum_prod_TsXs; |
222 |
229 |
223 (* TODO: clean up list *) |
230 (* TODO: clean up list *) |
224 val (pre_bnfs, ((fp_bnfs as any_fp_bnf :: _, dtors0, ctors0, fp_folds0, fp_recs0, fp_induct, |
231 val (pre_bnfs, ((fp_bnfs as any_fp_bnf :: _, dtors0, ctors0, fp_folds0, fp_recs0, fp_induct, |
225 dtor_ctors, ctor_dtors, ctor_injects, fp_map_thms, fp_set_thmss, fp_rel_thms, |
232 fp_strong_induct, dtor_ctors, ctor_dtors, ctor_injects, fp_map_thms, fp_set_thmss, |
226 fp_fold_thms, fp_rec_thms), lthy)) = |
233 fp_rel_thms, fp_fold_thms, fp_rec_thms), lthy)) = |
227 fp_bnf construct_fp fp_bs mixfixes (map dest_TFree unsorted_As) fp_eqs no_defs_lthy0; |
234 fp_bnf construct_fp fp_bs mixfixes (map dest_TFree unsorted_As) fp_eqs no_defs_lthy0; |
228 |
235 |
229 val timer = time (Timer.startRealTimer ()); |
236 val timer = time (Timer.startRealTimer ()); |
230 |
237 |
231 fun add_nesty_bnf_names Us = |
238 fun add_nesty_bnf_names Us = |
277 val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_fold))); |
284 val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_fold))); |
278 val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_rec))); |
285 val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_rec))); |
279 |
286 |
280 val (((fold_only as (gss, _, _), rec_only as (hss, _, _)), |
287 val (((fold_only as (gss, _, _), rec_only as (hss, _, _)), |
281 (zs, cs, cpss, unfold_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))), |
288 (zs, cs, cpss, unfold_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))), |
282 names_lthy) = |
289 names_lthy0) = |
283 if lfp then |
290 if lfp then |
284 let |
291 let |
285 val y_Tsss = |
292 val y_Tsss = |
286 map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type) |
293 map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type) |
287 ns mss fp_fold_fun_Ts; |
294 ns mss fp_fold_fun_Ts; |
518 |
525 |
519 val rel_infos = (ctr_defs' ~~ xss ~~ cxIns, ctr_defs' ~~ yss ~~ cyIns); |
526 val rel_infos = (ctr_defs' ~~ xss ~~ cxIns, ctr_defs' ~~ yss ~~ cyIns); |
520 |
527 |
521 fun mk_rel_thm postproc ctr_defs' xs cxIn ys cyIn = |
528 fun mk_rel_thm postproc ctr_defs' xs cxIn ys cyIn = |
522 fold_thms lthy ctr_defs' |
529 fold_thms lthy ctr_defs' |
523 (unfold_thms lthy (pre_rel_def :: |
530 (unfold_thms lthy (pre_rel_def :: (if lfp then [] else [dtor_ctor]) @ |
524 (if lfp then [] else [dtor_ctor]) @ sum_prod_thms_rel) |
531 sum_prod_thms_rel) |
525 (cterm_instantiate_pos (nones @ [SOME cxIn, SOME cyIn]) fp_rel_thm)) |
532 (cterm_instantiate_pos (nones @ [SOME cxIn, SOME cyIn]) fp_rel_thm)) |
526 |> postproc |> thaw (xs @ ys); |
533 |> postproc |> thaw (xs @ ys); |
527 |
534 |
528 fun mk_pos_rel_thm (((ctr_def', xs), cxIn), ((_, ys), cyIn)) = |
535 fun mk_pos_rel_thm (((ctr_def', xs), cxIn), ((_, ys), cyIn)) = |
529 mk_rel_thm (perhaps (try (fn th => th RS @{thm eq_sym_Unity_imp}))) [ctr_def'] |
536 mk_rel_thm (unfold_thms lthy @{thms eq_sym_Unity_conv}) [ctr_def'] xs cxIn ys cyIn; |
530 xs cxIn ys cyIn; |
|
531 |
537 |
532 val pos_rel_thms = map mk_pos_rel_thm (op ~~ rel_infos); |
538 val pos_rel_thms = map mk_pos_rel_thm (op ~~ rel_infos); |
533 |
539 |
534 fun mk_half_neg_rel_thm (((xctr_def', xs), cxIn), ((yctr_def', ys), cyIn)) = |
540 fun mk_half_neg_rel_thm (((xctr_def', xs), cxIn), ((yctr_def', ys), cyIn)) = |
535 mk_rel_thm (fn thm => thm RS @{thm eq_False[THEN iffD1]}) [xctr_def', yctr_def'] |
541 mk_rel_thm (fn thm => thm RS @{thm eq_False[THEN iffD1]}) [xctr_def', yctr_def'] |
645 fun build_map build_arg (Type (s, Ts)) (Type (_, Us)) = |
651 fun build_map build_arg (Type (s, Ts)) (Type (_, Us)) = |
646 let |
652 let |
647 val bnf = the (bnf_of lthy s); |
653 val bnf = the (bnf_of lthy s); |
648 val live = live_of_bnf bnf; |
654 val live = live_of_bnf bnf; |
649 val mapx = mk_map live Ts Us (map_of_bnf bnf); |
655 val mapx = mk_map live Ts Us (map_of_bnf bnf); |
650 val TUs = map dest_funT (fst (strip_typeN live (fastype_of mapx))); |
656 val TUs' = map dest_funT (fst (strip_typeN live (fastype_of mapx))); |
651 val args = map build_arg TUs; |
657 in Term.list_comb (mapx, map build_arg TUs') end; |
652 in Term.list_comb (mapx, args) end; |
|
653 |
658 |
654 (* TODO: Add map, sets, rel simps *) |
659 (* TODO: Add map, sets, rel simps *) |
655 val mk_simp_thmss = |
660 val mk_simp_thmss = |
656 map3 (fn (_, _, injects, distincts, cases, _, _, _) => fn rec_likes => fn fold_likes => |
661 map3 (fn (_, _, _, injects, distincts, cases, _, _, _) => fn rec_likes => fn fold_likes => |
657 injects @ distincts @ cases @ rec_likes @ fold_likes); |
662 injects @ distincts @ cases @ rec_likes @ fold_likes); |
658 |
663 |
659 fun derive_induct_fold_rec_thms_for_types (((ctrss, xsss, ctr_defss, wrap_ress), (folds, recs, |
664 fun derive_induct_fold_rec_thms_for_types (((ctrss, xsss, ctr_defss, wrap_ress), (folds, recs, |
660 fold_defs, rec_defs)), lthy) = |
665 fold_defs, rec_defs)), lthy) = |
661 let |
666 let |
662 val (((phis, phis'), us'), names_lthy) = |
667 val (((ps, ps'), us'), names_lthy) = |
663 lthy |
668 lthy |
664 |> mk_Frees' "P" (map mk_pred1T fpTs) |
669 |> mk_Frees' "P" (map mk_pred1T fpTs) |
665 ||>> Variable.variant_fixes fp_b_names; |
670 ||>> Variable.variant_fixes fp_b_names; |
666 |
671 |
667 val us = map2 (curry Free) us' fpTs; |
672 val us = map2 (curry Free) us' fpTs; |
702 val xysets = map (pair x) (ys ~~ sets); |
707 val xysets = map (pair x) (ys ~~ sets); |
703 val ppremss = map (mk_raw_prem_prems names_lthy') ys; |
708 val ppremss = map (mk_raw_prem_prems names_lthy') ys; |
704 in |
709 in |
705 flat (map2 (map o apfst o cons) xysets ppremss) |
710 flat (map2 (map o apfst o cons) xysets ppremss) |
706 end) |
711 end) |
707 | i => [([], (i + 1, x))]) |
712 | kk => [([], (kk + 1, x))]) |
708 | mk_raw_prem_prems _ _ = []; |
713 | mk_raw_prem_prems _ _ = []; |
709 |
714 |
710 fun close_prem_prem xs t = |
715 fun close_prem_prem xs t = |
711 fold_rev Logic.all (map Free (drop (nn + length xs) |
716 fold_rev Logic.all (map Free (drop (nn + length xs) |
712 (rev (Term.add_frees t (map dest_Free xs @ phis'))))) t; |
717 (rev (Term.add_frees t (map dest_Free xs @ ps'))))) t; |
713 |
718 |
714 fun mk_prem_prem xs (xysets, (j, x)) = |
719 fun mk_prem_prem xs (xysets, (j, x)) = |
715 close_prem_prem xs (Logic.list_implies (map (fn (x', (y, set)) => |
720 close_prem_prem xs (Logic.list_implies (map (fn (x', (y, set)) => |
716 HOLogic.mk_Trueprop (HOLogic.mk_mem (y, set $ x'))) xysets, |
721 HOLogic.mk_Trueprop (HOLogic.mk_mem (y, set $ x'))) xysets, |
717 HOLogic.mk_Trueprop (nth phis (j - 1) $ x))); |
722 HOLogic.mk_Trueprop (nth ps (j - 1) $ x))); |
718 |
723 |
719 fun mk_raw_prem phi ctr ctr_Ts = |
724 fun mk_raw_prem phi ctr ctr_Ts = |
720 let |
725 let |
721 val (xs, names_lthy') = names_lthy |> mk_Frees "x" ctr_Ts; |
726 val (xs, names_lthy') = names_lthy |> mk_Frees "x" ctr_Ts; |
722 val pprems = maps (mk_raw_prem_prems names_lthy') xs; |
727 val pprems = maps (mk_raw_prem_prems names_lthy') xs; |
723 in (xs, pprems, HOLogic.mk_Trueprop (phi $ Term.list_comb (ctr, xs))) end; |
728 in (xs, pprems, HOLogic.mk_Trueprop (phi $ Term.list_comb (ctr, xs))) end; |
724 |
729 |
725 fun mk_prem (xs, raw_pprems, concl) = |
730 fun mk_prem (xs, raw_pprems, concl) = |
726 fold_rev Logic.all xs (Logic.list_implies (map (mk_prem_prem xs) raw_pprems, concl)); |
731 fold_rev Logic.all xs (Logic.list_implies (map (mk_prem_prem xs) raw_pprems, concl)); |
727 |
732 |
728 val raw_premss = map3 (map2 o mk_raw_prem) phis ctrss ctr_Tsss; |
733 val raw_premss = map3 (map2 o mk_raw_prem) ps ctrss ctr_Tsss; |
729 |
734 |
730 val goal = |
735 val goal = |
731 Library.foldr (Logic.list_implies o apfst (map mk_prem)) (raw_premss, |
736 Library.foldr (Logic.list_implies o apfst (map mk_prem)) (raw_premss, |
732 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 (curry (op $)) phis us))); |
737 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 (curry (op $)) ps us))); |
733 |
738 |
734 val kksss = map (map (map (fst o snd) o #2)) raw_premss; |
739 val kksss = map (map (map (fst o snd) o #2)) raw_premss; |
735 |
740 |
736 val ctor_induct' = fp_induct OF (map mk_sumEN_tupled_balanced mss); |
741 val ctor_induct' = fp_induct OF (map mk_sumEN_tupled_balanced mss); |
737 |
742 |
738 val induct_thm = |
743 val thm = |
739 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
744 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
740 mk_induct_tac ctxt nn ns mss kksss (flat ctr_defss) ctor_induct' |
745 mk_induct_tac ctxt nn ns mss kksss (flat ctr_defss) ctor_induct' |
741 nested_set_natural's pre_set_defss) |
746 nested_set_natural's pre_set_defss) |
742 |> singleton (Proof_Context.export names_lthy lthy) |
747 |> singleton (Proof_Context.export names_lthy lthy) |
|
748 |> Thm.close_derivation; |
743 in |
749 in |
744 `(conj_dests nn) induct_thm |
750 `(conj_dests nn) thm |
745 end; |
751 end; |
746 |
752 |
747 (* TODO: Generate nicer names in case of clashes *) |
753 (* TODO: Generate nicer names in case of clashes *) |
748 val induct_cases = Datatype_Prop.indexify_names (maps (map base_name_of_ctr) ctrss); |
754 val induct_cases = Datatype_Prop.indexify_names (maps (map base_name_of_ctr) ctrss); |
749 |
755 |
755 |
761 |
756 fun mk_goal fss frec_like xctr f xs fxs = |
762 fun mk_goal fss frec_like xctr f xs fxs = |
757 fold_rev (fold_rev Logic.all) (xs :: fss) |
763 fold_rev (fold_rev Logic.all) (xs :: fss) |
758 (mk_Trueprop_eq (frec_like $ xctr, Term.list_comb (f, fxs))); |
764 (mk_Trueprop_eq (frec_like $ xctr, Term.list_comb (f, fxs))); |
759 |
765 |
760 fun build_call frec_likes maybe_tick (T, U) = |
766 fun build_rec_like frec_likes maybe_tick (T, U) = |
761 if T = U then |
767 if T = U then |
762 id_const T |
768 id_const T |
763 else |
769 else |
764 (case find_index (curry (op =) T) fpTs of |
770 (case find_index (curry (op =) T) fpTs of |
765 ~1 => build_map (build_call frec_likes maybe_tick) T U |
771 ~1 => build_map (build_rec_like frec_likes maybe_tick) T U |
766 | j => maybe_tick (nth us j) (nth frec_likes j)); |
772 | kk => maybe_tick (nth us kk) (nth frec_likes kk)); |
767 |
773 |
768 fun mk_U maybe_mk_prodT = |
774 fun mk_U maybe_mk_prodT = |
769 typ_subst (map2 (fn fpT => fn C => (fpT, maybe_mk_prodT fpT C)) fpTs Cs); |
775 typ_subst (map2 (fn fpT => fn C => (fpT, maybe_mk_prodT fpT C)) fpTs Cs); |
770 |
776 |
771 fun intr_calls frec_likes maybe_cons maybe_tick maybe_mk_prodT (x as Free (_, T)) = |
777 fun intr_rec_likes frec_likes maybe_cons maybe_tick maybe_mk_prodT (x as Free (_, T)) = |
772 if member (op =) fpTs T then |
778 if member (op =) fpTs T then |
773 maybe_cons x [build_call frec_likes (K I) (T, mk_U (K I) T) $ x] |
779 maybe_cons x [build_rec_like frec_likes (K I) (T, mk_U (K I) T) $ x] |
774 else if exists_fp_subtype T then |
780 else if exists_fp_subtype T then |
775 [build_call frec_likes maybe_tick (T, mk_U maybe_mk_prodT T) $ x] |
781 [build_rec_like frec_likes maybe_tick (T, mk_U maybe_mk_prodT T) $ x] |
776 else |
782 else |
777 [x]; |
783 [x]; |
778 |
784 |
779 val gxsss = map (map (maps (intr_calls gfolds (K I) (K I) (K I)))) xsss; |
785 val gxsss = map (map (maps (intr_rec_likes gfolds (K I) (K I) (K I)))) xsss; |
780 val hxsss = map (map (maps (intr_calls hrecs cons tick (curry HOLogic.mk_prodT)))) xsss; |
786 val hxsss = |
|
787 map (map (maps (intr_rec_likes hrecs cons tick (curry HOLogic.mk_prodT)))) xsss; |
781 |
788 |
782 val fold_goalss = map5 (map4 o mk_goal gss) gfolds xctrss gss xsss gxsss; |
789 val fold_goalss = map5 (map4 o mk_goal gss) gfolds xctrss gss xsss gxsss; |
783 val rec_goalss = map5 (map4 o mk_goal hss) hrecs xctrss hss xsss hxsss; |
790 val rec_goalss = map5 (map4 o mk_goal hss) hrecs xctrss hss xsss hxsss; |
784 |
791 |
785 val fold_tacss = |
792 val fold_tacss = |
820 end; |
829 end; |
821 |
830 |
822 fun derive_coinduct_unfold_corec_thms_for_types (((ctrss, _, ctr_defss, wrap_ress), (unfolds, |
831 fun derive_coinduct_unfold_corec_thms_for_types (((ctrss, _, ctr_defss, wrap_ress), (unfolds, |
823 corecs, unfold_defs, corec_defs)), lthy) = |
832 corecs, unfold_defs, corec_defs)), lthy) = |
824 let |
833 let |
|
834 val nesting_rel_eqs = map rel_eq_of_bnf nesting_bnfs; |
|
835 |
825 val discss = map (map (mk_disc_or_sel As) o #1) wrap_ress; |
836 val discss = map (map (mk_disc_or_sel As) o #1) wrap_ress; |
826 val selsss = map #2 wrap_ress; |
837 val selsss = map (map (map (mk_disc_or_sel As)) o #2) wrap_ress; |
827 val disc_thmsss = map #6 wrap_ress; |
838 val exhaust_thms = map #3 wrap_ress; |
828 val discIss = map #7 wrap_ress; |
839 val disc_thmsss = map #7 wrap_ress; |
829 val sel_thmsss = map #8 wrap_ress; |
840 val discIss = map #8 wrap_ress; |
830 |
841 val sel_thmsss = map #9 wrap_ress; |
831 val (us', _) = |
842 |
|
843 val (((rs, us'), vs'), names_lthy) = |
832 lthy |
844 lthy |
833 |> Variable.variant_fixes fp_b_names; |
845 |> mk_Frees "R" (map (fn T => mk_pred2T T T) fpTs) |
|
846 ||>> Variable.variant_fixes fp_b_names |
|
847 ||>> Variable.variant_fixes (map (suffix "'") fp_b_names); |
834 |
848 |
835 val us = map2 (curry Free) us' fpTs; |
849 val us = map2 (curry Free) us' fpTs; |
836 |
850 val udiscss = map2 (map o rapp) us discss; |
837 val (coinduct_thms, coinduct_thm) = |
851 val uselsss = map2 (map o map o rapp) us selsss; |
|
852 |
|
853 val vs = map2 (curry Free) vs' fpTs; |
|
854 val vdiscss = map2 (map o rapp) vs discss; |
|
855 val vselsss = map2 (map o map o rapp) vs selsss; |
|
856 |
|
857 val ((coinduct_thms, coinduct_thm), (strong_coinduct_thms, strong_coinduct_thm)) = |
838 let |
858 let |
|
859 val uvrs = map3 (fn r => fn u => fn v => r $ u $ v) rs us vs; |
|
860 val uv_eqs = map2 (curry HOLogic.mk_eq) us vs; |
|
861 val strong_rs = |
|
862 map4 (fn u => fn v => fn uvr => fn uv_eq => |
|
863 fold_rev Term.lambda [u, v] (HOLogic.mk_disj (uvr, uv_eq))) us vs uvrs uv_eqs; |
|
864 |
|
865 fun build_rel_step build_arg (Type (s, Ts)) = |
|
866 let |
|
867 val bnf = the (bnf_of lthy s); |
|
868 val live = live_of_bnf bnf; |
|
869 val rel = mk_rel live Ts Ts (rel_of_bnf bnf); |
|
870 val Ts' = map domain_type (fst (strip_typeN live (fastype_of rel))); |
|
871 in Term.list_comb (rel, map build_arg Ts') end; |
|
872 |
|
873 fun build_rel rs' T = |
|
874 (case find_index (curry (op =) T) fpTs of |
|
875 ~1 => |
|
876 if exists_fp_subtype T then build_rel_step (build_rel rs') T |
|
877 else HOLogic.eq_const T |
|
878 | kk => nth rs' kk); |
|
879 |
|
880 fun build_rel_app rs' usel vsel = |
|
881 fold rapp [usel, vsel] (build_rel rs' (fastype_of usel)); |
|
882 |
|
883 fun mk_prem_ctr_concls rs' n k udisc usels vdisc vsels = |
|
884 (if k = n then [] else [HOLogic.mk_eq (udisc, vdisc)]) @ |
|
885 (if null usels then |
|
886 [] |
|
887 else |
|
888 [Library.foldr HOLogic.mk_imp (if n = 1 then [] else [udisc, vdisc], |
|
889 Library.foldr1 HOLogic.mk_conj (map2 (build_rel_app rs') usels vsels))]); |
|
890 |
|
891 fun mk_prem_concl rs' n udiscs uselss vdiscs vselss = |
|
892 Library.foldr1 HOLogic.mk_conj |
|
893 (flat (map5 (mk_prem_ctr_concls rs' n) (1 upto n) udiscs uselss vdiscs vselss)) |
|
894 handle List.Empty => @{term True}; |
|
895 |
|
896 fun mk_prem rs' uvr u v n udiscs uselss vdiscs vselss = |
|
897 fold_rev Logic.all [u, v] (Logic.mk_implies (HOLogic.mk_Trueprop uvr, |
|
898 HOLogic.mk_Trueprop (mk_prem_concl rs' n udiscs uselss vdiscs vselss))); |
|
899 |
|
900 val concl = |
|
901 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj |
|
902 (map3 (fn uvr => fn u => fn v => HOLogic.mk_imp (uvr, HOLogic.mk_eq (u, v))) |
|
903 uvrs us vs)); |
|
904 |
|
905 fun mk_goal rs' = |
|
906 Logic.list_implies (map8 (mk_prem rs') uvrs us vs ns udiscss uselsss vdiscss vselsss, |
|
907 concl); |
|
908 |
|
909 val goal = mk_goal rs; |
|
910 val strong_goal = mk_goal strong_rs; |
|
911 |
|
912 fun prove dtor_coinduct' goal = |
|
913 Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} => |
|
914 mk_coinduct_tac ctxt nesting_rel_eqs nn ns dtor_coinduct' pre_rel_defs dtor_ctors |
|
915 exhaust_thms ctr_defss disc_thmsss sel_thmsss) |
|
916 |> singleton (Proof_Context.export names_lthy lthy) |
|
917 |> Thm.close_derivation; |
|
918 |
839 fun postproc nn thm = |
919 fun postproc nn thm = |
840 Thm.permute_prems 0 nn |
920 Thm.permute_prems 0 nn |
841 (if nn = 1 then thm RS mp else funpow nn (fn thm => thm RS @{thm mp_conj}) thm) |
921 (if nn = 1 then thm RS mp |
842 |> Drule.zero_var_indexes; |
922 else funpow nn (fn thm => reassoc_conjs (thm RS mp_conj)) thm) |
843 |
923 |> Drule.zero_var_indexes |
844 val coinduct_thm = fp_induct; |
924 |> `(conj_dests nn); |
845 in |
925 in |
846 `(conj_dests nn) coinduct_thm |
926 (postproc nn (prove fp_induct goal), postproc nn (prove fp_strong_induct strong_goal)) |
847 end; |
927 end; |
848 |
928 |
849 fun mk_maybe_not pos = not pos ? HOLogic.mk_not; |
929 fun mk_maybe_not pos = not pos ? HOLogic.mk_not; |
850 |
930 |
851 val z = the_single zs; |
931 val z = the_single zs; |
857 fun mk_goal pfss c cps fcorec_like n k ctr m cfs' = |
937 fun mk_goal pfss c cps fcorec_like n k ctr m cfs' = |
858 fold_rev (fold_rev Logic.all) ([c] :: pfss) |
938 fold_rev (fold_rev Logic.all) ([c] :: pfss) |
859 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps, |
939 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps, |
860 mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs')))); |
940 mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs')))); |
861 |
941 |
862 fun build_call frec_likes maybe_tack (T, U) = |
942 fun build_corec_like fcorec_likes maybe_tack (T, U) = |
863 if T = U then |
943 if T = U then |
864 id_const T |
944 id_const T |
865 else |
945 else |
866 (case find_index (curry (op =) U) fpTs of |
946 (case find_index (curry (op =) U) fpTs of |
867 ~1 => build_map (build_call frec_likes maybe_tack) T U |
947 ~1 => build_map (build_corec_like fcorec_likes maybe_tack) T U |
868 | j => maybe_tack (nth cs j, nth us j) (nth frec_likes j)); |
948 | kk => maybe_tack (nth cs kk, nth us kk) (nth fcorec_likes kk)); |
869 |
949 |
870 fun mk_U maybe_mk_sumT = |
950 fun mk_U maybe_mk_sumT = |
871 typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs); |
951 typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs); |
872 |
952 |
873 fun intr_calls frec_likes maybe_mk_sumT maybe_tack cqf = |
953 fun intr_corec_likes fcorec_likes maybe_mk_sumT maybe_tack cqf = |
874 let val T = fastype_of cqf in |
954 let val T = fastype_of cqf in |
875 if exists_subtype (member (op =) Cs) T then |
955 if exists_subtype (member (op =) Cs) T then |
876 build_call frec_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf |
956 build_corec_like fcorec_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf |
877 else |
957 else |
878 cqf |
958 cqf |
879 end; |
959 end; |
880 |
960 |
881 val crgsss' = map (map (map (intr_calls gunfolds (K I) (K I)))) crgsss; |
961 val crgsss' = map (map (map (intr_corec_likes gunfolds (K I) (K I)))) crgsss; |
882 val cshsss' = map (map (map (intr_calls hcorecs (curry mk_sumT) (tack z)))) cshsss; |
962 val cshsss' = |
|
963 map (map (map (intr_corec_likes hcorecs (curry mk_sumT) (tack z)))) cshsss; |
883 |
964 |
884 val unfold_goalss = |
965 val unfold_goalss = |
885 map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss'; |
966 map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss'; |
886 val corec_goalss = |
967 val corec_goalss = |
887 map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss'; |
968 map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss'; |
981 val anonymous_notes = |
1062 val anonymous_notes = |
982 [(flat safe_unfold_thmss @ flat safe_corec_thmss, simp_attrs)] |
1063 [(flat safe_unfold_thmss @ flat safe_corec_thmss, simp_attrs)] |
983 |> map (fn (thms, attrs) => ((Binding.empty, attrs), [(thms, [])])); |
1064 |> map (fn (thms, attrs) => ((Binding.empty, attrs), [(thms, [])])); |
984 |
1065 |
985 val common_notes = |
1066 val common_notes = |
986 (if nn > 1 then [(coinductN, [coinduct_thm], [])] (* FIXME: attribs *) else []) |
1067 (if nn > 1 then |
|
1068 (* FIXME: attribs *) |
|
1069 [(coinductN, [coinduct_thm], []), |
|
1070 (strong_coinductN, [strong_coinduct_thm], [])] |
|
1071 else |
|
1072 []) |
987 |> map (fn (thmN, thms, attrs) => |
1073 |> map (fn (thmN, thms, attrs) => |
988 ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])])); |
1074 ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])])); |
989 |
1075 |
990 val notes = |
1076 val notes = |
991 [(coinductN, map single coinduct_thms, []), (* FIXME: attribs *) |
1077 [(coinductN, map single coinduct_thms, []), (* FIXME: attribs *) |
995 (disc_unfold_iffsN, disc_unfold_iff_thmss, simp_attrs), |
1081 (disc_unfold_iffsN, disc_unfold_iff_thmss, simp_attrs), |
996 (disc_unfoldsN, disc_unfold_thmss, simp_attrs), |
1082 (disc_unfoldsN, disc_unfold_thmss, simp_attrs), |
997 (sel_unfoldsN, sel_unfold_thmss, simp_attrs), |
1083 (sel_unfoldsN, sel_unfold_thmss, simp_attrs), |
998 (sel_corecsN, sel_corec_thmss, simp_attrs), |
1084 (sel_corecsN, sel_corec_thmss, simp_attrs), |
999 (simpsN, simp_thmss, []), |
1085 (simpsN, simp_thmss, []), |
|
1086 (strong_coinductN, map single strong_coinduct_thms, []), (* FIXME: attribs *) |
1000 (unfoldsN, unfold_thmss, [])] |
1087 (unfoldsN, unfold_thmss, [])] |
1001 |> maps (fn (thmN, thmss, attrs) => |
1088 |> maps (fn (thmN, thmss, attrs) => |
1002 map_filter (fn (_, []) => NONE | (b, thms) => |
1089 map_filter (fn (_, []) => NONE | (b, thms) => |
1003 SOME ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs), |
1090 SOME ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs), |
1004 [(thms, [])])) (fp_bs ~~ thmss)); |
1091 [(thms, [])])) (fp_bs ~~ thmss)); |