660 |> Seq.map (fn (fact_insts, env) => do_inst fact_insts env text ctxt') |
660 |> Seq.map (fn (fact_insts, env) => do_inst fact_insts env text ctxt') |
661 end; |
661 end; |
662 |
662 |
663 fun make_term_matches ctxt get = |
663 fun make_term_matches ctxt get = |
664 let |
664 let |
665 val pats' = |
665 val pats' = map |
666 map |
666 (fn ((SOME _, _), _) => error "Cannot name term match" |
667 (fn ((SOME _, _), _) => error "Cannot name term match" |
667 | ((_, x), t) => (((NONE, x), []), Logic.mk_term t)) pats; |
668 | ((_, x), t) => (((NONE, x), []), Logic.mk_term t)) pats; |
|
669 |
668 |
670 val thm_of = Drule.mk_term o Thm.cterm_of ctxt; |
669 val thm_of = Drule.mk_term o Thm.cterm_of ctxt; |
671 fun get' t = get (Logic.dest_term t) |> map thm_of; |
670 fun get' t = get (Logic.dest_term t) |> map thm_of; |
672 in |
671 in |
673 match_facts ctxt fixes pats' get' |
672 match_facts ctxt fixes pats' get' |
674 |> Seq.map (fn (fact_insts, env) => do_inst fact_insts env text ctxt) |
673 |> Seq.map (fn (fact_insts, env) => do_inst fact_insts env text ctxt) |
675 end; |
674 end; |
676 in |
675 in |
677 (case m of |
676 (case m of |
678 Match_Fact net => |
677 Match_Fact net => |
679 Seq.map (fn (text, ctxt') => Method_Closure.method_evaluate text ctxt' using goal) |
678 Seq.map (fn (text, ctxt') => Method_Closure.method_evaluate text ctxt' using st) |
680 (make_fact_matches goal_ctxt (Item_Net.retrieve net)) |
679 (make_fact_matches goal_ctxt (Item_Net.retrieve net)) |
681 | Match_Term net => |
680 | Match_Term net => |
682 Seq.map (fn (text, ctxt') => Method_Closure.method_evaluate text ctxt' using goal) |
681 Seq.map (fn (text, ctxt') => Method_Closure.method_evaluate text ctxt' using st) |
683 (make_term_matches goal_ctxt (Item_Net.retrieve net)) |
682 (make_term_matches goal_ctxt (Item_Net.retrieve net)) |
684 | match_kind => |
683 | match_kind => |
685 if Thm.no_prems goal then Seq.empty |
684 if Thm.no_prems st then Seq.empty |
686 else |
685 else |
687 let |
686 let |
688 fun focus_cases f g = |
687 fun focus_cases f g = |
689 (case match_kind of |
688 (case match_kind of |
690 Match_Prems b => f b |
689 Match_Prems b => f b |
691 | Match_Concl => g |
690 | Match_Concl => g |
692 | _ => raise Fail "Match kind fell through"); |
691 | _ => raise Fail "Match kind fell through"); |
693 |
692 |
694 val (goal_thins, goal) = get_thinned_prems goal; |
693 val (goal_thins, st') = get_thinned_prems st; |
695 |
694 |
696 val ((local_premids, {context = focus_ctxt, params, asms, concl, ...}), focused_goal) = |
695 val ((local_premids, {context = focus_ctxt, params, asms, concl, ...}), focused_goal) = |
697 focus_cases (K Subgoal.focus_prems) focus_concl goal_ctxt 1 NONE goal |
696 focus_cases (K Subgoal.focus_prems) focus_concl goal_ctxt 1 NONE st' |
698 |>> augment_focus; |
697 |>> augment_focus; |
699 |
698 |
700 val texts = |
699 val texts = |
701 focus_cases |
700 focus_cases |
702 (fn is_local => fn _ => |
701 (fn is_local => fn _ => |
704 (Item_Net.retrieve (focus_prems focus_ctxt |> snd) |
703 (Item_Net.retrieve (focus_prems focus_ctxt |> snd) |
705 #> filter_out (member (eq_fst (op =)) goal_thins) |
704 #> filter_out (member (eq_fst (op =)) goal_thins) |
706 #> is_local ? filter (fn (p, _) => exists (fn id' => id' = p) local_premids) |
705 #> is_local ? filter (fn (p, _) => exists (fn id' => id' = p) local_premids) |
707 #> order_list)) |
706 #> order_list)) |
708 (fn _ => |
707 (fn _ => |
709 make_term_matches focus_ctxt (fn _ => [Logic.strip_imp_concl (Thm.term_of concl)])) |
708 make_term_matches focus_ctxt |
|
709 (fn _ => [Logic.strip_imp_concl (Thm.term_of concl)])) |
710 (); |
710 (); |
711 |
711 |
712 (*TODO: How to handle cases? *) |
712 (*TODO: How to handle cases? *) |
713 |
713 |
714 fun do_retrofit inner_ctxt goal' = |
714 fun do_retrofit inner_ctxt st1 = |
715 let |
715 let |
716 val (goal'_thins, goal') = get_thinned_prems goal'; |
716 val (goal_thins', st2) = get_thinned_prems st1; |
717 |
717 |
718 val thinned_prems = |
718 val thinned_prems = |
719 ((subtract (eq_fst (op =)) |
719 ((subtract (eq_fst (op =)) |
720 (focus_prems inner_ctxt |> snd |> Item_Net.content) |
720 (focus_prems inner_ctxt |> snd |> Item_Net.content) |
721 (focus_prems focus_ctxt |> snd |> Item_Net.content)) |
721 (focus_prems focus_ctxt |> snd |> Item_Net.content)) |
724 |> (fn [chyp] => (id, (SOME chyp, NONE)) |
724 |> (fn [chyp] => (id, (SOME chyp, NONE)) |
725 | _ => error "Prem should have only one hyp"))); |
725 | _ => error "Prem should have only one hyp"))); |
726 |
726 |
727 val all_thinned_prems = |
727 val all_thinned_prems = |
728 thinned_prems @ |
728 thinned_prems @ |
729 map (fn (id, prem) => (id, (NONE, SOME prem))) (goal'_thins @ goal_thins); |
729 map (fn (id, prem) => (id, (NONE, SOME prem))) (goal_thins' @ goal_thins); |
730 |
730 |
731 val (thinned_local_prems, thinned_extra_prems) = |
731 val (thinned_local_prems, thinned_extra_prems) = |
732 List.partition (fn (id, _) => member (op =) local_premids id) all_thinned_prems; |
732 List.partition (fn (id, _) => member (op =) local_premids id) all_thinned_prems; |
733 |
733 |
734 val local_thins = |
734 val local_thins = |
735 thinned_local_prems |
735 thinned_local_prems |> map |
736 |> map (fn (_, (SOME t, _)) => Thm.term_of t |
736 (fn (_, (SOME t, _)) => Thm.term_of t |
737 | (_, (_, SOME pt)) => Thm.term_of pt |> Logic.dest_term); |
737 | (_, (_, SOME pt)) => Thm.term_of pt |> Logic.dest_term); |
738 |
738 |
739 val extra_thins = |
739 val extra_thins = |
740 thinned_extra_prems |
740 thinned_extra_prems |> map |
741 |> map (fn (id, (SOME ct, _)) => (id, Drule.mk_term ct |> Thm.cprop_of) |
741 (fn (id, (SOME ct, _)) => (id, Drule.mk_term ct |> Thm.cprop_of) |
742 | (id, (_, SOME pt)) => (id, pt)) |
742 | (id, (_, SOME pt)) => (id, pt)) |
743 |> map (hyp_from_ctermid inner_ctxt); |
743 |> map (hyp_from_ctermid inner_ctxt); |
744 |
744 |
745 val n_subgoals = Thm.nprems_of goal'; |
745 val n_subgoals = Thm.nprems_of st2; |
746 fun prep_filter t = |
746 fun prep_filter t = |
747 Term.subst_bounds (map (Thm.term_of o snd) params |> rev, Term.strip_all_body t); |
747 Term.subst_bounds (map (Thm.term_of o snd) params |> rev, Term.strip_all_body t); |
748 fun filter_test prems t = |
748 fun filter_test prems t = |
749 if member (op =) prems t then SOME (remove1 (op aconv) t prems) else NONE; |
749 if member (op =) prems t then SOME (remove1 (op aconv) t prems) else NONE; |
750 in |
750 in |
751 Subgoal.retrofit inner_ctxt goal_ctxt params asms 1 goal' goal |> |
751 Subgoal.retrofit inner_ctxt goal_ctxt params asms 1 st2 st |> |
752 (if n_subgoals = 0 orelse null local_thins then I |
752 (if n_subgoals = 0 orelse null local_thins then I |
753 else |
753 else |
754 Seq.map (Goal.restrict 1 n_subgoals) |
754 Seq.map (Goal.restrict 1 n_subgoals) |
755 #> Seq.maps (ALLGOALS (fn i => |
755 #> Seq.maps (ALLGOALS (fn i => |
756 DETERM (filter_prems_tac' goal_ctxt prep_filter filter_test local_thins i))) |
756 DETERM (filter_prems_tac' goal_ctxt prep_filter filter_test local_thins i))) |
757 #> Seq.map (Goal.unrestrict 1)) |
757 #> Seq.map (Goal.unrestrict 1)) |
758 |> Seq.map (fold Thm.weaken extra_thins) |
758 |> Seq.map (fold Thm.weaken extra_thins) |
759 end; |
759 end; |
760 |
760 |
761 fun apply_text (text, ctxt') = |
761 fun apply_text (text, ctxt') = |
762 let |
762 DROP_CASES (Method_Closure.method_evaluate text ctxt' using) focused_goal |
763 val goal' = |
763 |> Seq.maps (DETERM (do_retrofit ctxt')) |
764 DROP_CASES (Method_Closure.method_evaluate text ctxt' using) focused_goal |
764 |> Seq.map (pair ([]: Rule_Cases.cases)); |
765 |> Seq.maps (DETERM (do_retrofit ctxt')) |
765 in Seq.map apply_text texts end) |
766 |> Seq.map (fn goal => ([]: Rule_Cases.cases, goal)); |
|
767 in goal' end; |
|
768 in |
|
769 Seq.map apply_text texts |
|
770 end) |
|
771 end; |
766 end; |
772 |
767 |
773 val _ = |
768 val _ = |
774 Theory.setup |
769 Theory.setup |
775 (Method.setup @{binding match} |
770 (Method.setup @{binding match} |