wenzelm@30143
|
1 |
(* Title: Pure/Tools/find_consts.ML
|
kleing@29821
|
2 |
Author: Timothy Bourke and Gerwin Klein, NICTA
|
kleing@29821
|
3 |
|
wenzelm@30143
|
4 |
Hoogle-like (http://www-users.cs.york.ac.uk/~ndm/hoogle) searching by
|
wenzelm@30143
|
5 |
type over constants, but matching is not fuzzy.
|
kleing@29821
|
6 |
*)
|
kleing@29821
|
7 |
|
kleing@29821
|
8 |
signature FIND_CONSTS =
|
kleing@29821
|
9 |
sig
|
wenzelm@30143
|
10 |
datatype criterion =
|
wenzelm@30143
|
11 |
Strict of string
|
wenzelm@30143
|
12 |
| Loose of string
|
wenzelm@30143
|
13 |
| Name of string
|
kleing@29821
|
14 |
val find_consts : Proof.context -> (bool * criterion) list -> unit
|
kleing@29821
|
15 |
end;
|
kleing@29821
|
16 |
|
wenzelm@33309
|
17 |
structure Find_Consts : FIND_CONSTS =
|
kleing@29821
|
18 |
struct
|
kleing@29821
|
19 |
|
wenzelm@30143
|
20 |
(* search criteria *)
|
wenzelm@30143
|
21 |
|
wenzelm@30143
|
22 |
datatype criterion =
|
wenzelm@30143
|
23 |
Strict of string
|
wenzelm@30143
|
24 |
| Loose of string
|
wenzelm@30143
|
25 |
| Name of string;
|
kleing@29821
|
26 |
|
wenzelm@31686
|
27 |
|
wenzelm@30143
|
28 |
(* matching types/consts *)
|
wenzelm@30143
|
29 |
|
wenzelm@30143
|
30 |
fun matches_subtype thy typat =
|
wenzelm@38594
|
31 |
Term.exists_subtype (fn ty => Sign.typ_instance thy (ty, typat));
|
kleing@29821
|
32 |
|
wenzelm@38594
|
33 |
fun check_const pred (nm, (ty, _)) =
|
wenzelm@38594
|
34 |
if pred (nm, ty) then SOME (Term.size_of_typ ty) else NONE;
|
kleing@29821
|
35 |
|
wenzelm@30143
|
36 |
fun opt_not f (c as (_, (ty, _))) =
|
wenzelm@38594
|
37 |
if is_some (f c) then NONE else SOME (Term.size_of_typ ty);
|
kleing@29821
|
38 |
|
wenzelm@47853
|
39 |
fun filter_const _ _ NONE = NONE
|
wenzelm@47853
|
40 |
| filter_const c f (SOME rank) =
|
wenzelm@31686
|
41 |
(case f c of
|
wenzelm@31686
|
42 |
NONE => NONE
|
wenzelm@47853
|
43 |
| SOME i => SOME (Int.min (rank, i)));
|
wenzelm@30143
|
44 |
|
wenzelm@30143
|
45 |
|
wenzelm@30143
|
46 |
(* pretty results *)
|
kleing@29832
|
47 |
|
kleing@29832
|
48 |
fun pretty_criterion (b, c) =
|
kleing@29832
|
49 |
let
|
kleing@29832
|
50 |
fun prfx s = if b then s else "-" ^ s;
|
kleing@29832
|
51 |
in
|
kleing@29832
|
52 |
(case c of
|
kleing@29832
|
53 |
Strict pat => Pretty.str (prfx "strict: " ^ quote pat)
|
kleing@29832
|
54 |
| Loose pat => Pretty.str (prfx (quote pat))
|
kleing@29832
|
55 |
| Name name => Pretty.str (prfx "name: " ^ quote name))
|
kleing@29832
|
56 |
end;
|
kleing@29832
|
57 |
|
wenzelm@30143
|
58 |
fun pretty_const ctxt (nm, ty) =
|
wenzelm@30143
|
59 |
let
|
wenzelm@35845
|
60 |
val ty' = Logic.unvarifyT_global ty;
|
kleing@29832
|
61 |
in
|
wenzelm@30143
|
62 |
Pretty.block
|
wenzelm@38595
|
63 |
[Pretty.str nm, Pretty.str " ::", Pretty.brk 1,
|
wenzelm@30143
|
64 |
Pretty.quote (Syntax.pretty_typ ctxt ty')]
|
kleing@29832
|
65 |
end;
|
kleing@29832
|
66 |
|
wenzelm@31686
|
67 |
|
wenzelm@30143
|
68 |
(* find_consts *)
|
wenzelm@30143
|
69 |
|
wenzelm@30143
|
70 |
fun find_consts ctxt raw_criteria =
|
wenzelm@30143
|
71 |
let
|
wenzelm@43231
|
72 |
val thy = Proof_Context.theory_of ctxt;
|
kleing@29821
|
73 |
val low_ranking = 10000;
|
kleing@29821
|
74 |
|
wenzelm@33160
|
75 |
fun user_visible consts (nm, _) =
|
wenzelm@33160
|
76 |
if Consts.is_concealed consts nm then NONE else SOME low_ranking;
|
Timothy@30206
|
77 |
|
Timothy@30207
|
78 |
fun make_pattern crit =
|
Timothy@30207
|
79 |
let
|
Timothy@30207
|
80 |
val raw_T = Syntax.parse_typ ctxt crit;
|
wenzelm@31686
|
81 |
val t =
|
wenzelm@31686
|
82 |
Syntax.check_term
|
wenzelm@43231
|
83 |
(Proof_Context.set_mode Proof_Context.mode_pattern ctxt)
|
wenzelm@31686
|
84 |
(Term.dummy_pattern raw_T);
|
Timothy@30207
|
85 |
in Term.type_of t end;
|
kleing@29821
|
86 |
|
kleing@29821
|
87 |
fun make_match (Strict arg) =
|
kleing@29821
|
88 |
let val qty = make_pattern arg; in
|
wenzelm@30143
|
89 |
fn (_, (ty, _)) =>
|
wenzelm@30143
|
90 |
let
|
kleing@29821
|
91 |
val tye = Sign.typ_match thy (qty, ty) Vartab.empty;
|
wenzelm@31686
|
92 |
val sub_size =
|
wenzelm@31686
|
93 |
Vartab.fold (fn (_, (_, t)) => fn n => Term.size_of_typ t + n) tye 0;
|
wenzelm@32797
|
94 |
in SOME sub_size end handle Type.TYPE_MATCH => NONE
|
kleing@29821
|
95 |
end
|
kleing@29821
|
96 |
| make_match (Loose arg) =
|
kleing@29821
|
97 |
check_const (matches_subtype thy (make_pattern arg) o snd)
|
kleing@29821
|
98 |
| make_match (Name arg) = check_const (match_string arg o fst);
|
kleing@29821
|
99 |
|
kleing@29821
|
100 |
fun make_criterion (b, crit) = (if b then I else opt_not) (make_match crit);
|
Timothy@30206
|
101 |
val criteria = map make_criterion raw_criteria;
|
kleing@29821
|
102 |
|
Timothy@30206
|
103 |
val consts = Sign.consts_of thy;
|
wenzelm@31686
|
104 |
val (_, consts_tab) = #constants (Consts.dest consts);
|
wenzelm@31686
|
105 |
fun eval_entry c =
|
wenzelm@47853
|
106 |
fold (filter_const c) (user_visible consts :: criteria) (SOME low_ranking);
|
kleing@29821
|
107 |
|
wenzelm@30143
|
108 |
val matches =
|
wenzelm@47853
|
109 |
Symtab.fold (fn c => (case eval_entry c of NONE => I | SOME rank => cons (rank, c)))
|
wenzelm@47853
|
110 |
consts_tab []
|
wenzelm@47853
|
111 |
|> sort (prod_ord (rev_order o int_ord) (string_ord o pairself fst))
|
wenzelm@47853
|
112 |
|> map (apsnd fst o snd);
|
kleing@29821
|
113 |
in
|
wenzelm@38594
|
114 |
Pretty.big_list "searched for:" (map pretty_criterion raw_criteria) ::
|
wenzelm@38594
|
115 |
Pretty.str "" ::
|
wenzelm@38594
|
116 |
Pretty.str
|
wenzelm@38594
|
117 |
(if null matches
|
wenzelm@47587
|
118 |
then "nothing found"
|
wenzelm@47587
|
119 |
else "found " ^ string_of_int (length matches) ^ " constant(s):") ::
|
wenzelm@38594
|
120 |
Pretty.str "" ::
|
wenzelm@38594
|
121 |
map (pretty_const ctxt) matches
|
wenzelm@38594
|
122 |
end |> Pretty.chunks |> Pretty.writeln;
|
kleing@29821
|
123 |
|
wenzelm@30142
|
124 |
|
wenzelm@30143
|
125 |
(* command syntax *)
|
wenzelm@30142
|
126 |
|
wenzelm@38593
|
127 |
local
|
wenzelm@30142
|
128 |
|
wenzelm@30142
|
129 |
val criterion =
|
wenzelm@36950
|
130 |
Parse.reserved "strict" |-- Parse.!!! (Parse.$$$ ":" |-- Parse.xname) >> Strict ||
|
wenzelm@36950
|
131 |
Parse.reserved "name" |-- Parse.!!! (Parse.$$$ ":" |-- Parse.xname) >> Name ||
|
wenzelm@36950
|
132 |
Parse.xname >> Loose;
|
wenzelm@30142
|
133 |
|
wenzelm@38593
|
134 |
in
|
wenzelm@38593
|
135 |
|
wenzelm@30142
|
136 |
val _ =
|
wenzelm@47836
|
137 |
Outer_Syntax.improper_command ("find_consts", Keyword.diag) "search constants by type pattern"
|
wenzelm@36950
|
138 |
(Scan.repeat ((Scan.option Parse.minus >> is_none) -- criterion)
|
wenzelm@38593
|
139 |
>> (fn spec => Toplevel.no_timing o
|
wenzelm@38593
|
140 |
Toplevel.keep (fn state => find_consts (Toplevel.context_of state) spec)));
|
wenzelm@30142
|
141 |
|
kleing@29821
|
142 |
end;
|
kleing@29821
|
143 |
|
wenzelm@38593
|
144 |
end;
|
wenzelm@38593
|
145 |
|