1 (* Title: Pure/Tools/find_consts.ML
2 Author: Timothy Bourke and Gerwin Klein, NICTA
4 Hoogle-like (http://www-users.cs.york.ac.uk/~ndm/hoogle) searching by
5 type over constants, but matching is not fuzzy.
8 signature FIND_CONSTS =
14 val find_consts : Proof.context -> (bool * criterion) list -> unit
17 structure Find_Consts : FIND_CONSTS =
28 (* matching types/consts *)
30 fun matches_subtype thy typat =
31 Term.exists_subtype (fn ty => Sign.typ_instance thy (ty, typat));
33 fun check_const pred (nm, (ty, _)) =
34 if pred (nm, ty) then SOME (Term.size_of_typ ty) else NONE;
36 fun opt_not f (c as (_, (ty, _))) =
37 if is_some (f c) then NONE else SOME (Term.size_of_typ ty);
39 fun filter_const _ NONE = NONE
40 | filter_const f (SOME (c, r)) =
43 | SOME i => SOME (c, Int.min (r, i)));
48 fun pretty_criterion (b, c) =
50 fun prfx s = if b then s else "-" ^ s;
53 Strict pat => Pretty.str (prfx "strict: " ^ quote pat)
54 | Loose pat => Pretty.str (prfx (quote pat))
55 | Name name => Pretty.str (prfx "name: " ^ quote name))
58 fun pretty_const ctxt (nm, ty) =
60 val ty' = Logic.unvarifyT_global ty;
63 [Pretty.str nm, Pretty.str " ::", Pretty.brk 1,
64 Pretty.quote (Syntax.pretty_typ ctxt ty')]
70 fun find_consts ctxt raw_criteria =
72 val start = Timing.start ();
74 val thy = Proof_Context.theory_of ctxt;
75 val low_ranking = 10000;
77 fun user_visible consts (nm, _) =
78 if Consts.is_concealed consts nm then NONE else SOME low_ranking;
80 fun make_pattern crit =
82 val raw_T = Syntax.parse_typ ctxt crit;
85 (Proof_Context.set_mode Proof_Context.mode_pattern ctxt)
86 (Term.dummy_pattern raw_T);
87 in Term.type_of t end;
89 fun make_match (Strict arg) =
90 let val qty = make_pattern arg; in
93 val tye = Sign.typ_match thy (qty, ty) Vartab.empty;
95 Vartab.fold (fn (_, (_, t)) => fn n => Term.size_of_typ t + n) tye 0;
96 in SOME sub_size end handle Type.TYPE_MATCH => NONE
98 | make_match (Loose arg) =
99 check_const (matches_subtype thy (make_pattern arg) o snd)
100 | make_match (Name arg) = check_const (match_string arg o fst);
102 fun make_criterion (b, crit) = (if b then I else opt_not) (make_match crit);
103 val criteria = map make_criterion raw_criteria;
105 val consts = Sign.consts_of thy;
106 val (_, consts_tab) = #constants (Consts.dest consts);
108 fold filter_const (user_visible consts :: criteria)
109 (SOME (c, low_ranking));
112 Symtab.fold (cons o eval_entry) consts_tab []
114 |> sort (rev_order o int_ord o pairself snd)
115 |> map (apsnd fst o fst);
117 val end_msg = " in " ^ Time.toString (#cpu (Timing.result start)) ^ " secs";
119 Pretty.big_list "searched for:" (map pretty_criterion raw_criteria) ::
123 then "nothing found" ^ end_msg
124 else "found " ^ string_of_int (length matches) ^ " constant(s)" ^ end_msg ^ ":") ::
126 map (pretty_const ctxt) matches
127 end |> Pretty.chunks |> Pretty.writeln;
135 Parse.reserved "strict" |-- Parse.!!! (Parse.$$$ ":" |-- Parse.xname) >> Strict ||
136 Parse.reserved "name" |-- Parse.!!! (Parse.$$$ ":" |-- Parse.xname) >> Name ||
137 Parse.xname >> Loose;
142 Outer_Syntax.improper_command "find_consts" "search constants by type pattern" Keyword.diag
143 (Scan.repeat ((Scan.option Parse.minus >> is_none) -- criterion)
144 >> (fn spec => Toplevel.no_timing o
145 Toplevel.keep (fn state => find_consts (Toplevel.context_of state) spec)));