src/HOL/Eisbach/match_method.ML
changeset 61839 6f47a66afcd3
parent 61838 5f43c7f3d691
child 61840 a3793600cb93
equal deleted inserted replaced
61838:5f43c7f3d691 61839:6f47a66afcd3
   648   in
   648   in
   649     all_matches
   649     all_matches
   650     |> Seq.map (apsnd (morphism_env morphism))
   650     |> Seq.map (apsnd (morphism_env morphism))
   651   end;
   651   end;
   652 
   652 
   653 fun real_match using goal_ctxt fixes m text pats goal =
   653 fun real_match using goal_ctxt fixes m text pats st =
   654   let
   654   let
   655     fun make_fact_matches ctxt get =
   655     fun make_fact_matches ctxt get =
   656       let
   656       let
   657         val (pats', ctxt') = fold_map prep_fact_pat pats ctxt;
   657         val (pats', ctxt') = fold_map prep_fact_pat pats ctxt;
   658       in
   658       in
   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}