(* Simple query tool for theorem collections. Syntax: find_in_thms pattern* in thm+ *) theory Find_In_Theorems imports Names_Of_Thm keywords "find_in_theorems" :: diag begin ML \ structure Find_In_Theorems = struct (* filter_pattern *) fun expand_abs t = let val m = Term.maxidx_of_term t + 1; val vs = strip_abs_vars t; val ts = map_index (fn (k, (_, T)) => Var ((Name.aT, m + k), T)) vs; in betapplys (t, ts) end; fun get_names t = Term.add_const_names t (Term.add_free_names t []); (* Does pat match a subterm of obj? *) fun matches_subterm thy (pat, obj) = let fun msub bounds obj = Pattern.matches thy (pat, obj) orelse (case obj of Abs (_, T, t) => msub (bounds + 1) (snd (Term.dest_abs (Name.bound bounds, T, t))) | t $ u => msub bounds t orelse msub bounds u | _ => false) in msub 0 obj end; fun filter_pattern ctxt pat = let val pat' = (expand_abs o Envir.eta_contract) pat; fun check thm = matches_subterm (Proof_Context.theory_of ctxt) (pat', Thm.full_prop_of thm); in check end; val _ = Outer_Syntax.command \<^command_keyword>\find_in_theorems\ "find theorems matching specified patterns in theorem collection" (Scan.repeat Parse.term -- (\<^keyword>\in\ |-- Parse.thms1) >> (fn (pats,thms) => Toplevel.keep (fn st => let val ctxt = Toplevel.context_of st fun is_plain (Facts.Named (_,NONE), []) = true | is_plain _ = false fun prt_of (r,s) = if is_plain (r,s) then Pretty.str (Facts.string_of_ref r) else Pretty.enclose "\" "\" [ Pretty.str (Facts.string_of_ref r), Pretty.list "[" "]" (map (Token.pretty_src ctxt) s)] val thms = thms ~~ map (Attrib.eval_thms ctxt o single) thms |> map (apfst prt_of #> apsnd (tag_list 1)) |> map (fn (name,ls) => map (fn (i,thm) => ((name,i),thm)) ls) |> flat val pats = map (Proof_Context.read_term_pattern ctxt) pats val filters = map (filter_pattern ctxt) pats fun flt (_,thm) = forall (fn flt => flt thm) filters val thms = filter flt thms val names_of = Names_Of_Thm.names_of_thm {dynamic=false, rdups=true} ctxt fun pretty_name_of thm = case names_of thm of [] => Pretty.str "" | x::_ => Pretty.block [Names_Of_Thm.pretty_ref ctxt x, Pretty.str ":", Pretty.brk 1] fun pretty_thm ((n,i),thm) = Pretty.block [ pretty_name_of thm, n,Pretty.enclose "(" ")" [Pretty.str (string_of_int i)],Pretty.str ":",Pretty.brk 1, Thm.pretty_thm ctxt thm] val _ = map pretty_thm thms |> Pretty.big_list "Results" |> Pretty.writeln in () end))); end \ end