7 |
7 |
8 signature FIND_THEOREMS = |
8 signature FIND_THEOREMS = |
9 sig |
9 sig |
10 datatype 'term criterion = |
10 datatype 'term criterion = |
11 Name of string | Intro | Elim | Dest | Solves | Simp of 'term | Pattern of 'term |
11 Name of string | Intro | Elim | Dest | Solves | Simp of 'term | Pattern of 'term |
12 |
|
13 datatype theorem = |
|
14 Internal of Facts.ref * thm | External of Facts.ref * term |
|
15 |
|
16 type 'term query = { |
12 type 'term query = { |
17 goal: thm option, |
13 goal: thm option, |
18 limit: int option, |
14 limit: int option, |
19 rem_dups: bool, |
15 rem_dups: bool, |
20 criteria: (bool * 'term criterion) list |
16 criteria: (bool * 'term criterion) list |
21 } |
17 } |
22 |
|
23 val read_criterion: Proof.context -> string criterion -> term criterion |
|
24 val read_query: Position.T -> string -> (bool * string criterion) list |
18 val read_query: Position.T -> string -> (bool * string criterion) list |
25 |
|
26 val find_theorems: Proof.context -> thm option -> int option -> bool -> |
19 val find_theorems: Proof.context -> thm option -> int option -> bool -> |
27 (bool * term criterion) list -> int option * (Facts.ref * thm) list |
20 (bool * term criterion) list -> int option * (Facts.ref * thm) list |
28 val find_theorems_cmd: Proof.context -> thm option -> int option -> bool -> |
21 val find_theorems_cmd: Proof.context -> thm option -> int option -> bool -> |
29 (bool * string criterion) list -> int option * (Facts.ref * thm) list |
22 (bool * string criterion) list -> int option * (Facts.ref * thm) list |
30 |
|
31 val filter_theorems: Proof.context -> theorem list -> term query -> |
|
32 int option * theorem list |
|
33 val filter_theorems_cmd: Proof.context -> theorem list -> string query -> |
|
34 int option * theorem list |
|
35 |
|
36 val pretty_theorem: Proof.context -> theorem -> Pretty.T |
|
37 val pretty_thm: Proof.context -> Facts.ref * thm -> Pretty.T |
23 val pretty_thm: Proof.context -> Facts.ref * thm -> Pretty.T |
38 end; |
24 end; |
39 |
25 |
40 structure Find_Theorems: FIND_THEOREMS = |
26 structure Find_Theorems: FIND_THEOREMS = |
41 struct |
27 struct |
167 fun subst_size pat = |
153 fun subst_size pat = |
168 let val (_, subst) = |
154 let val (_, subst) = |
169 Pattern.match thy (if po then (pat, obj) else (obj, pat)) (Vartab.empty, Vartab.empty) |
155 Pattern.match thy (if po then (pat, obj) else (obj, pat)) (Vartab.empty, Vartab.empty) |
170 in Vartab.fold (fn (_, (_, t)) => fn n => size_of_term t + n) subst 0 end; |
156 in Vartab.fold (fn (_, (_, t)) => fn n => size_of_term t + n) subst 0 end; |
171 |
157 |
172 fun bestmatch [] = NONE |
158 fun best_match [] = NONE |
173 | bestmatch xs = SOME (foldl1 Int.min xs); |
159 | best_match xs = SOME (foldl1 Int.min xs); |
174 |
160 |
175 val match_thm = matches o refine_term; |
161 val match_thm = matches o refine_term; |
176 in |
162 in |
177 map (subst_size o refine_term) (filter match_thm (extract_terms term_src)) |
163 map (subst_size o refine_term) (filter match_thm (extract_terms term_src)) |
178 |> bestmatch |
164 |> best_match |
179 end; |
165 end; |
180 |
166 |
181 |
167 |
182 (* filter_name *) |
168 (* filter_name *) |
183 |
169 |
220 val rule = prop_of theorem; |
206 val rule = prop_of theorem; |
221 val prems = Logic.prems_of_goal goal 1; |
207 val prems = Logic.prems_of_goal goal 1; |
222 val goal_concl = Logic.concl_of_goal goal 1; |
208 val goal_concl = Logic.concl_of_goal goal 1; |
223 val rule_mp = hd (Logic.strip_imp_prems rule); |
209 val rule_mp = hd (Logic.strip_imp_prems rule); |
224 val rule_concl = Logic.strip_imp_concl rule; |
210 val rule_concl = Logic.strip_imp_concl rule; |
225 fun combine t1 t2 = Const ("*combine*", dummyT --> dummyT) $ (t1 $ t2); |
211 fun combine t1 t2 = Const ("*combine*", dummyT --> dummyT) $ (t1 $ t2); (* FIXME ?? *) |
226 val rule_tree = combine rule_mp rule_concl; |
212 val rule_tree = combine rule_mp rule_concl; |
227 fun goal_tree prem = combine prem goal_concl; |
213 fun goal_tree prem = combine prem goal_concl; |
228 fun try_subst prem = is_matching_thm (single, I) ctxt true (goal_tree prem) rule_tree; |
214 fun try_subst prem = is_matching_thm (single, I) ctxt true (goal_tree prem) rule_tree; |
229 val successful = prems |> map_filter try_subst; |
215 val successful = prems |> map_filter try_subst; |
230 in |
216 in |
242 Proof_Context.theory_of ctxt |
228 Proof_Context.theory_of ctxt |
243 |> Context_Position.set_visible_global (Context_Position.is_visible ctxt); |
229 |> Context_Position.set_visible_global (Context_Position.is_visible ctxt); |
244 val ctxt' = Proof_Context.transfer thy' ctxt; |
230 val ctxt' = Proof_Context.transfer thy' ctxt; |
245 val goal' = Thm.transfer thy' goal; |
231 val goal' = Thm.transfer thy' goal; |
246 |
232 |
247 fun etacn thm i = |
233 fun limited_etac thm i = |
248 Seq.take (Options.default_int @{option find_theorems_tac_limit}) o etac thm i; |
234 Seq.take (Options.default_int @{option find_theorems_tac_limit}) o etac thm i; |
249 fun try_thm thm = |
235 fun try_thm thm = |
250 if Thm.no_prems thm then rtac thm 1 goal' |
236 if Thm.no_prems thm then rtac thm 1 goal' |
251 else (etacn thm THEN_ALL_NEW (Goal.norm_hhf_tac THEN' Method.assm_tac ctxt')) 1 goal'; |
237 else (limited_etac thm THEN_ALL_NEW (Goal.norm_hhf_tac THEN' Method.assm_tac ctxt')) 1 goal'; |
252 in |
238 in |
253 fn Internal (_, thm) => |
239 fn Internal (_, thm) => |
254 if is_some (Seq.pull (try_thm thm)) |
240 if is_some (Seq.pull (try_thm thm)) |
255 then SOME (Thm.nprems_of thm, 0) else NONE |
241 then SOME (Thm.nprems_of thm, 0) else NONE |
256 | External _ => NONE |
242 | External _ => NONE |
453 else pair NONE o Seq.list_of o Seq.take (the opt_limit) o lazy_filter filters; |
442 else pair NONE o Seq.list_of o Seq.take (the opt_limit) o lazy_filter filters; |
454 |
443 |
455 in find theorems end; |
444 in find theorems end; |
456 |
445 |
457 fun filter_theorems_cmd ctxt theorems raw_query = |
446 fun filter_theorems_cmd ctxt theorems raw_query = |
458 filter_theorems ctxt theorems (map_criteria |
447 filter_theorems ctxt theorems (map_criteria (map (apsnd (read_criterion ctxt))) raw_query); |
459 (map (apsnd (read_criterion ctxt))) raw_query); |
448 |
|
449 |
|
450 (* find_theorems *) |
|
451 |
|
452 local |
460 |
453 |
461 fun gen_find_theorems filter ctxt opt_goal opt_limit rem_dups raw_criteria = |
454 fun gen_find_theorems filter ctxt opt_goal opt_limit rem_dups raw_criteria = |
462 let |
455 let |
463 val assms = |
456 val assms = |
464 Proof_Context.get_fact ctxt (Facts.named "local.assms") |
457 Proof_Context.get_fact ctxt (Facts.named "local.assms") |
469 filter ctxt (map Internal (all_facts_of ctxt)) |
462 filter ctxt (map Internal (all_facts_of ctxt)) |
470 {goal = opt_goal', limit = opt_limit, rem_dups = rem_dups, criteria = raw_criteria} |
463 {goal = opt_goal', limit = opt_limit, rem_dups = rem_dups, criteria = raw_criteria} |
471 |> apsnd (map (fn Internal f => f)) |
464 |> apsnd (map (fn Internal f => f)) |
472 end; |
465 end; |
473 |
466 |
|
467 in |
|
468 |
474 val find_theorems = gen_find_theorems filter_theorems; |
469 val find_theorems = gen_find_theorems filter_theorems; |
475 val find_theorems_cmd = gen_find_theorems filter_theorems_cmd; |
470 val find_theorems_cmd = gen_find_theorems filter_theorems_cmd; |
|
471 |
|
472 end; |
|
473 |
|
474 |
|
475 (* pretty_theorems *) |
|
476 |
|
477 local |
476 |
478 |
477 fun pretty_ref ctxt thmref = |
479 fun pretty_ref ctxt thmref = |
478 let |
480 let |
479 val (name, sel) = |
481 val (name, sel) = |
480 (case thmref of |
482 (case thmref of |
488 fun pretty_theorem ctxt (Internal (thmref, thm)) = |
490 fun pretty_theorem ctxt (Internal (thmref, thm)) = |
489 Pretty.block (pretty_ref ctxt thmref @ [Display.pretty_thm ctxt thm]) |
491 Pretty.block (pretty_ref ctxt thmref @ [Display.pretty_thm ctxt thm]) |
490 | pretty_theorem ctxt (External (thmref, prop)) = |
492 | pretty_theorem ctxt (External (thmref, prop)) = |
491 Pretty.block (pretty_ref ctxt thmref @ [Syntax.unparse_term ctxt prop]); |
493 Pretty.block (pretty_ref ctxt thmref @ [Syntax.unparse_term ctxt prop]); |
492 |
494 |
|
495 in |
|
496 |
493 fun pretty_thm ctxt (thmref, thm) = pretty_theorem ctxt (Internal (thmref, thm)); |
497 fun pretty_thm ctxt (thmref, thm) = pretty_theorem ctxt (Internal (thmref, thm)); |
494 |
498 |
495 fun pretty_theorems ctxt opt_goal opt_limit rem_dups raw_criteria = |
499 fun pretty_theorems state opt_limit rem_dups raw_criteria = |
496 let |
500 let |
|
501 val ctxt = Proof.context_of state; |
|
502 val opt_goal = try Proof.simple_goal state |> Option.map #goal; |
497 val criteria = map (apsnd (read_criterion ctxt)) raw_criteria; |
503 val criteria = map (apsnd (read_criterion ctxt)) raw_criteria; |
|
504 |
498 val (opt_found, theorems) = |
505 val (opt_found, theorems) = |
499 filter_theorems ctxt (map Internal (all_facts_of ctxt)) |
506 filter_theorems ctxt (map Internal (all_facts_of ctxt)) |
500 {goal = opt_goal, limit = opt_limit, rem_dups = rem_dups, criteria = criteria}; |
507 {goal = opt_goal, limit = opt_limit, rem_dups = rem_dups, criteria = criteria}; |
501 val returned = length theorems; |
508 val returned = length theorems; |
502 |
509 |
515 else |
522 else |
516 [Pretty.str (tally_msg ^ ":"), Pretty.str ""] @ |
523 [Pretty.str (tally_msg ^ ":"), Pretty.str ""] @ |
517 grouped 10 Par_List.map (Pretty.item o single o pretty_theorem ctxt) theorems) |
524 grouped 10 Par_List.map (Pretty.item o single o pretty_theorem ctxt) theorems) |
518 end |> Pretty.fbreaks |> curry Pretty.blk 0; |
525 end |> Pretty.fbreaks |> curry Pretty.blk 0; |
519 |
526 |
520 fun pretty_theorems_cmd state opt_lim rem_dups spec = |
527 end; |
521 let |
|
522 val ctxt = Toplevel.context_of state; |
|
523 val opt_goal = try (Proof.simple_goal o Toplevel.proof_of) state |> Option.map #goal; |
|
524 in pretty_theorems ctxt opt_goal opt_lim rem_dups spec end; |
|
525 |
528 |
526 |
529 |
527 |
530 |
528 (** Isar command syntax **) |
531 (** Isar command syntax **) |
|
532 |
|
533 fun proof_state st = |
|
534 (case try Toplevel.proof_of st of |
|
535 SOME state => state |
|
536 | NONE => Proof.init (Toplevel.context_of st)); |
529 |
537 |
530 local |
538 local |
531 |
539 |
532 val criterion = |
540 val criterion = |
533 Parse.reserved "name" |-- Parse.!!! (Parse.$$$ ":" |-- Parse.xname) >> Name || |
541 Parse.reserved "name" |-- Parse.!!! (Parse.$$$ ":" |-- Parse.xname) >> Name || |
556 |
564 |
557 val _ = |
565 val _ = |
558 Outer_Syntax.improper_command @{command_spec "find_theorems"} |
566 Outer_Syntax.improper_command @{command_spec "find_theorems"} |
559 "find theorems meeting specified criteria" |
567 "find theorems meeting specified criteria" |
560 (options -- query >> (fn ((opt_lim, rem_dups), spec) => |
568 (options -- query >> (fn ((opt_lim, rem_dups), spec) => |
561 Toplevel.keep (fn state => |
569 Toplevel.keep (fn st => |
562 Pretty.writeln (pretty_theorems_cmd state opt_lim rem_dups spec)))); |
570 Pretty.writeln (pretty_theorems (proof_state st) opt_lim rem_dups spec)))); |
563 |
571 |
564 end; |
572 end; |
565 |
573 |
566 |
574 |
567 |
575 |
568 (** PIDE query operation **) |
576 (** PIDE query operation **) |
569 |
577 |
570 val _ = |
578 val _ = |
571 Query_Operation.register "find_theorems" (fn st => fn args => |
579 Query_Operation.register "find_theorems" (fn st => fn args => |
572 if can Toplevel.theory_of st then |
580 if can Toplevel.context_of st then |
573 Pretty.string_of (pretty_theorems_cmd st NONE false (maps (read_query Position.none) args)) |
581 Pretty.string_of |
574 else error "Unknown theory context"); |
582 (pretty_theorems (proof_state st) NONE false (maps (read_query Position.none) args)) |
575 |
583 else error "Unknown context"); |
576 end; |
584 |
|
585 end; |