11signature BINDER_INDUCTIVE =
22sig
3- val binder_inductive_cmd: (string * (string * string list) list option) * (string list option * string list option)
3+ datatype options = No_Equiv | No_Refresh | Verbose
4+
5+ val binder_inductive_cmd: ((options list * string) * (string * string list) list option) * (string list option * string list option)
46 -> local_theory -> Proof.state;
7+
8+ val config_parser: options list parser;
59end
610
711structure Binder_Inductive : BINDER_INDUCTIVE =
@@ -22,7 +26,9 @@ fun collapse (Inl x) = x
2226fun mk_insert x S =
2327 Const (@{const_name Set.insert}, fastype_of x --> fastype_of S --> fastype_of S) $ x $ S;
2428
25- fun binder_inductive_cmd ((pred_name, binds_opt), perms_supps) no_defs_lthy =
29+ datatype options = No_Equiv | No_Refresh | Verbose
30+
31+ fun binder_inductive_cmd (((options, pred_name), binds_opt), perms_supps) no_defs_lthy =
2632 let
2733 val binds = the_default [] binds_opt;
2834
@@ -74,6 +80,10 @@ fun binder_inductive_cmd ((pred_name, binds_opt), perms_supps) no_defs_lthy =
7480
7581 val param_Ts = map (Term.typ_subst_TVars subst) param_Ts;
7682
83+ val param_sugars = map (fn T => Option.mapPartial (fn s =>
84+ MRBNF_Sugar.binder_sugar_of no_defs_lthy s
85+ ) (try (fn () => fst (dest_Type T)) ())) param_Ts;
86+
7787 fun collect_binders (Free _) = []
7888 | collect_binders (Var _) = []
7989 | collect_binders (Bound _) = []
@@ -373,17 +383,21 @@ fun binder_inductive_cmd ((pred_name, binds_opt), perms_supps) no_defs_lthy =
373383 val perms_specified = map (fn Inl _ => false | _ => true ) raw_perms;
374384 val supps_specified = map (fn Inl _ => false | _ => true ) raw_supps;
375385 val one_specified = map2 (fn a => fn b => a orelse b) perms_specified supps_specified;
386+
376387 fun keep_perm xs = cond_keep xs perms_specified;
377388 fun keep_supp xs = cond_keep xs supps_specified;
378389 fun keep_both xs = cond_keep xs one_specified;
379390 fun keep_binders xs = cond_keep xs binders_specified;
380391
392+ fun option x t f = if member (op =) options x then t else f;
393+
381394 val defs = map snd (perms @ supps);
395+ val verbose = member (op =) options Verbose;
382396
383397 val goals = map (single o rpair []) (
384398 keep_perm perm_id0_goals @ keep_perm perm_comp_goals @ keep_both supp_seminat_goals
385399 @ keep_both perm_support_goals @ keep_supp supp_small_goals @ flat (keep_binders B_small_goals)
386- @ [G_equiv_goal, G_refresh_goal]
400+ @ option No_Equiv [G_equiv_goal] [] @ option No_Refresh [ G_refresh_goal] [ ]
387401 );
388402 fun after_qed thmss lthy =
389403 let
@@ -445,15 +459,14 @@ fun binder_inductive_cmd ((pred_name, binds_opt), perms_supps) no_defs_lthy =
445459 val m2 = length (filter not one_specified);
446460 val m3 = length (filter not supps_specified);
447461 val m4 = length (filter not binders_specified);
448- val (((((((perm_id0s, perm_comps), supp_seminats), perm_supports), supp_smalls), B_smalls), G_equiv ), G_refresh ) = map hd thmss
462+ val (((((((perm_id0s, perm_comps), supp_seminats), perm_supports), supp_smalls), B_smalls), G_equivs ), G_refreshs ) = map hd thmss
449463 |> chop (n - m)
450464 ||>> chop (n - m)
451465 ||>> chop (n - m2)
452466 ||>> chop (n - m2)
453467 ||>> chop (num_vars * (n - m3))
454468 ||>> chop (length bind_ts - m4)
455- ||>> apfst hd o chop 1
456- ||> hd;
469+ ||>> chop (option No_Equiv 1 0 );
457470
458471 fun map_id0_of_mr_bnf (Inl mrbnf) = [MRBNF_Def.map_id0_of_mrbnf mrbnf]
459472 | map_id0_of_mr_bnf (Inr (Inl bnf)) = [BNF_Def.map_id0_of_bnf bnf]
@@ -601,6 +614,138 @@ fun binder_inductive_cmd ((pred_name, binds_opt), perms_supps) no_defs_lthy =
601614
602615 val perm_ids = map (fn thm => thm RS fun_cong RS @{thm trans[OF _ id_apply]}) perm_id0s;
603616
617+ val G_equiv = if member (op =) options No_Equiv then hd G_equivs else
618+ Goal.prove_sorry lthy [] [] G_equiv_goal (fn {context=ctxt, ...} => EVERY1 [
619+ K (Local_Defs.unfold0_tac ctxt [snd G]),
620+ REPEAT_DETERM o EVERY' [
621+ TRY o etac ctxt @{thm disj_forward},
622+ REPEAT_DETERM o eresolve_tac ctxt [exE, conjE],
623+ REPEAT_DETERM_N (length param_Ts + 1 ) o etac ctxt @{thm subst[OF sym]},
624+ Subgoal.FOCUS_PARAMS (fn {context=ctxt, params, ...} =>
625+ let
626+ val (fs, args) = map (Thm.term_of o snd) params
627+ |> drop 2
628+ |> chop 1
629+ ||> drop (length param_Ts);
630+ val (mr_bnfs, ts) = apfst (map snd o flat) (split_list (map (fn x => case find_index (curry (op =) (fastype_of x)) param_Ts of
631+ ~1 => (case find_index (curry (op =) (fastype_of x)) var_Ts of
632+ ~1 => apsnd (fn t => t $ x) (build_permute_for fs var_Ts (fastype_of x))
633+ | n => ([], nth fs n $ x))
634+ | n => ([], Term.list_comb (fst (nth perms n), fs) $ x)
635+ ) args));
636+ val equiv_commute = Named_Theorems.get ctxt " MRBNF_Recursor.equiv_commute" ;
637+ val equiv = Named_Theorems.get ctxt " MRBNF_Recursor.equiv" @ equiv_commute;
638+ val equiv_simps = Named_Theorems.get ctxt " MRBNF_Recursor.equiv_simps"
639+ val monos = Inductive.get_monos ctxt
640+ val set_maps = maps set_map_of_mr_bnf mr_bnfs;
641+ in EVERY1 [
642+ EVERY' (map (fn t => rtac ctxt (
643+ infer_instantiate' ctxt [NONE , SOME (Thm.cterm_of ctxt t)] exI
644+ )) ts),
645+ SELECT_GOAL (Local_Defs.unfold0_tac ctxt (map snd perms)),
646+ rtac ctxt conjI,
647+ SELECT_GOAL (Local_Defs.unfold0_tac ctxt (@{thms image_Un} @ equiv_simps)),
648+ REPEAT_DETERM o rtac ctxt @{thm arg_cong2[of _ _ _ _ " (\< union>)" ]},
649+ REPEAT_DETERM1 o EVERY' [
650+ resolve_tac ctxt @{thms image_single[symmetric] image_empty refl} ORELSE' EVERY' [
651+ resolve_tac ctxt (map (fn thm => thm RS sym) (set_maps @ equiv_simps) @ equiv_simps),
652+ REPEAT_DETERM o assume_tac ctxt
653+ ]
654+ ],
655+ K (Local_Defs.unfold0_tac ctxt @{thms id_apply}),
656+ K (Local_Defs.unfold0_tac ctxt @{thms id_def[symmetric]}),
657+ REPEAT_DETERM o EVERY' [
658+ TRY o rtac ctxt conjI,
659+ SELECT_GOAL (EVERY1 [
660+ REPEAT_DETERM1 o FIRST' [
661+ assume_tac ctxt,
662+ eresolve_tac ctxt [conjE],
663+ resolve_tac ctxt @{thms conjI refl TrueI bij_imp_bij_inv supp_inv_bound},
664+ rtac ctxt impI THEN' eresolve_tac ctxt @{thms injD[OF bij_is_inj, rotated -1 ]},
665+ EVERY' [
666+ SELECT_GOAL (Local_Defs.unfold0_tac ctxt (map_filter (try (fn thm => thm RS sym)) equiv_commute)),
667+ REPEAT_DETERM1 o EVERY' [
668+ EqSubst.eqsubst_tac ctxt [0 ] (map (Local_Defs.unfold0 ctxt (map snd perms)) perm_comps),
669+ REPEAT_DETERM1 o (assume_tac ctxt ORELSE' resolve_tac ctxt @{thms supp_inv_bound bij_imp_bij_inv})
670+ ],
671+ K (Local_Defs.unfold0_tac ctxt @{thms inv_o_simp1 inv_o_simp2 inv_simp1 inv_simp2}),
672+ K (Local_Defs.unfold0_tac ctxt (map (Local_Defs.unfold0 ctxt (map snd perms)) perm_ids)),
673+ assume_tac ctxt
674+ ],
675+ eresolve_tac ctxt (map_filter (try (fn thm => Drule.rotate_prems ~1 thm)) equiv),
676+ CHANGED o SELECT_GOAL (Local_Defs.unfold0_tac ctxt (equiv @ equiv_simps @ flat (map_filter (Option.map #permute_simps) param_sugars))),
677+ eresolve_tac ctxt (map (fn thm => Drule.rotate_prems ~1 (thm RS mp)) monos),
678+ resolve_tac ctxt monos,
679+ CHANGED o SELECT_GOAL (Local_Defs.unfold0_tac ctxt (flat (map_filter (Option.map (map (fn thm => thm RS sym) o #permute_simps)) param_sugars)))
680+ ]
681+ ])
682+ ]
683+ ] end
684+ ) ctxt
685+ ]
686+ ]);
687+ val _ = (verbose ? @{print}) G_equiv
688+
689+ val G_refresh = if member (op =) options No_Refresh then hd (G_refreshs) else
690+ let
691+ val var_rules = map (fn thm =>
692+ let val t = Logic.unvarify_global (Thm.prop_of thm)
693+ in (map Free (rev (Term.add_frees t [])), t) end
694+ ) intrs;
695+
696+ fun collect_permutes _ (Free _) = []
697+ | collect_permutes _ (Var _) = []
698+ | collect_permutes _ (Bound _) = []
699+ | collect_permutes _ (Const _) = []
700+ | collect_permutes vars (Abs (_, _, t)) = collect_permutes vars t
701+ | collect_permutes vars (t as (t1 $ t2)) = case try (dest_Type o Term.body_type o fastype_of) t of
702+ NONE => collect_permutes vars t1 @ collect_permutes vars t2
703+ | SOME (s, _) => (case MRBNF_Sugar.binder_sugar_of no_defs_lthy s of
704+ NONE => collect_permutes vars t1 @ collect_permutes vars t2
705+ | SOME sugar =>
706+ let val (ctor, args) = Term.strip_comb t
707+ in case (map_filter I (map_index (fn (i, (t, _)) =>
708+ if (op =) (apply2 (fst o dest_Const) (t, ctor)) then
709+ SOME i else NONE
710+ ) (#ctors sugar))) of
711+ [] => collect_permutes vars t1 @ collect_permutes vars t2
712+ | ctor_idx::_ => (case nth (hd (#bsetss sugar)) ctor_idx of
713+ NONE => maps (collect_permutes vars) args
714+ | SOME _ =>
715+ let
716+ val arg_Ts = Term.binder_types (fastype_of ctor);
717+ val permute_bounds = nth (#permute_bounds sugar) ctor_idx;
718+ val var_args = map (fn t => if member (op =) vars t then SOME t else NONE ) args;
719+ val result = map_filter I (map2 (fn NONE => K NONE
720+ | SOME perm => Option.map (fn x => (x, perm))
721+ ) permute_bounds var_args);
722+
723+ val tyenv = @{fold 2 } (fn NONE => K I | SOME perm => fn T =>
724+ Sign.typ_match (Proof_Context.theory_of no_defs_lthy) (body_type (fastype_of perm), T)
725+ ) permute_bounds arg_Ts Vartab.empty;
726+
727+ in map (apsnd (Envir.subst_term (tyenv, Vartab.empty))) result
728+ @ maps (collect_permutes vars) args
729+ end
730+ )
731+ end
732+ );
733+ fun isNONE NONE = true
734+ | isNONE _ = false
735+ val permute_bounds = map (distinct (op =) o uncurry collect_permutes) var_rules;
736+ val matrix = map2 (fn (vars, _) => fn perms =>
737+ let val inner = map (AList.lookup (op =) perms) vars;
738+ in if forall isNONE inner then NONE else SOME inner end
739+ ) var_rules permute_bounds;
740+ val _ = (verbose ? @{print}) (map (Option.map (map (Option.map (Thm.cterm_of lthy)))) matrix)
741+ in Goal.prove_sorry lthy [] [] G_refresh_goal (fn {context=ctxt, ...} => EVERY1 [
742+ K (Local_Defs.unfold0_tac ctxt (snd G :: map snd perms)),
743+ Subgoal.FOCUS (fn {context=ctxt, prems, ...} =>
744+ refreshability_tac_internal verbose (map fst supps) matrix (nth prems 2 ) (nth prems 1 ) supp_smalls (map snd supps) ctxt
745+ ) ctxt
746+ ]) end ;
747+ val _ = (verbose ? @{print}) G_refresh
748+
604749 fun mk_induct mono = Drule.rotate_prems ~1 (
605750 apply_n @{thm le_funD} n (@{thm lfp_induct} OF [mono])
606751 RS @{thm le_boolD}
@@ -1009,12 +1154,20 @@ val parse_perm_supps =
10091154 >> (fn ps => fold extract_perm_supp ps (NONE , NONE ))
10101155 || Scan.succeed (NONE , NONE );
10111156
1012- val binder_inductive_parser = Parse.name -- Scan.option (
1157+ val options_parser = Parse.group (fn () => " option" )
1158+ ((Parse.reserved " no_auto_equiv" >> K No_Equiv)
1159+ || (Parse.reserved " no_auto_refresh" >> K No_Refresh)
1160+ || (Parse.reserved " verbose" >> K Verbose))
1161+
1162+ val config_parser = Scan.optional (@{keyword " (" } |--
1163+ Parse.!!! (Parse.list1 options_parser) --| @{keyword " )" }) []
1164+
1165+ val binder_inductive_parser = config_parser -- Parse.name -- Scan.option (
10131166 @{keyword where } |-- Parse.enum1 " |" (Parse.name --| @{keyword binds} -- Parse.and_list Parse.term)
10141167 ) -- parse_perm_supps
10151168
10161169val _ =
10171170 Outer_Syntax.local_theory_to_proof \<^command_keyword>\<open >make_binder_inductive\<close> " derive strengthened induction theorems for inductive predicates"
10181171 (binder_inductive_parser >> binder_inductive_cmd);
10191172
1020- end
1173+ end
0 commit comments