36
37:- module(prolog_jiti,
38 [ jiti_list/0,
39 jiti_list/1, 40 jiti_suggest_modes/1, 41 jiti_suggest_modes/0
42 ]). 43:- autoload(library(apply), [maplist/2, foldl/4, convlist/3]). 44:- autoload(library(dcg/basics), [number//1]). 45:- autoload(library(ansi_term), [ansi_format/3, ansi_hyperlink/3]). 46:- autoload(library(prolog_code), [pi_head/2, most_general_goal/2]). 47:- autoload(library(listing), [portray_clause/1]). 48:- autoload(library(lists), [append/2]). 49:- autoload(library(ordsets), [ord_subtract/3]). 50
51
52:- meta_predicate
53 jiti_list(:),
54 jiti_suggest_modes(:). 55
63
64
96
97jiti_list :-
98 jiti_list(_:_).
99
100jiti_list(Spec) :-
101 spec_head(Spec, Head),
102 !,
103 jiti_list(Head).
104jiti_list(Head) :-
105 tty_width(TTYW),
106 findall(PI-Indexed,
107 ( predicate_property(Head, indexed(Indexed)),
108 \+ predicate_property(Head, imported_from(_)),
109 pi_head(PI, Head)
110 ), Pairs0),
111 sort(Pairs0, Pairs),
112 PredColW is TTYW-47,
113 TableWidth is TTYW-1,
114 ansi_format(bold, 'Predicate~*|~w ~t~10+~w ~t~w~14+ ~t~w~9+ ~t~w~6+ ~t~w~6+~n',
115 [PredColW, '#Clauses', 'Index','Buckets','Speedup','Coll','Flags']),
116 format('~`\u2015t~*|~n', [TableWidth]),
117 maplist(print_indexes(PredColW), Pairs).
118
119print_indexes(PredColW, PI-List) :-
120 foldl(print_index(PredColW, PI), List, 1, _).
121
122:- det(print_index/5). 123print_index(PredColW, PI0, Dict, N, N1) :-
124 pi_head(PI0, Head),
125 head_pi(Head, PI), 126 N1 is N+1,
127 _{arguments:Args, position:Pos,
128 buckets:Buckets, speedup:Speedup, list:List, realised:R,
129 collisions:Collisions0} :< Dict,
130 predicate_property(Head, number_of_clauses(CCount)),
131 phrase(iarg_spec(Pos, Args), ArgsS),
132 phrase(iflags(List, R), Flags),
133 istyle(R, Style),
134 icoll(R, List, Collisions0, Collisions),
135 CCountColZ is PredColW+8,
136 ( N == 1
137 -> format_pi(PI),
138 format(' ~t~D~*| ', [CCount, CCountColZ])
139 ; format(' ~t~*| ', [CCountColZ])
140 ),
141 ansi_format(Style, '~|~s ~t~D~14+ ~t~1f~9+ ~t~w~6+ ~s~n',
142 [ArgsS,Buckets,Speedup,Collisions,Flags]).
143
144format_pi(PI) :-
145 pi_head(PI, Head),
146 predicate_property(Head, file(File)),
147 predicate_property(Head, line_count(Line)),
148 !,
149 format(string(Label), '~q', [PI]),
150 ansi_hyperlink(user_output, File:Line, Label).
151format_pi(PI) :-
152 format('~q', [PI]).
153
155
156iarg_spec([], [N]) ==>
157 number(N).
158iarg_spec([], List) ==>
159 plus_list(List).
160iarg_spec(Deep, Args) ==>
161 deep_list(Deep),
162 iarg_spec([], Args).
163
164plus_list([H|T]) -->
165 number(H),
166 ( {T==[]}
167 -> []
168 ; "+",
169 plus_list(T)
170 ).
171
172deep_list([Last]) -->
173 !,
174 number(Last),
175 ":".
176deep_list([H|T]) -->
177 number(H),
178 "/",
179 deep_list(T).
180
181
182iflags(true, R) ==> "L", irealised(R).
183iflags(false, R) ==> "", irealised(R).
184
185irealised(false) ==> "V".
186irealised(true) ==> "".
187
188istyle(true, code).
189istyle(false, comment).
190
191icoll(true, false, Collisions0, Collisions) =>
192 Collisions = Collisions0.
193icoll(_, _, _, Collisions) =>
194 Collisions = '-'.
195
196head_pi(Head, PI) :-
197 predicate_property(Head, non_terminal),
198 !,
199 pi_head(PI0, Head),
200 dcg_pi(PI0, PI).
201head_pi(Head, PI) :-
202 pi_head(PI, Head).
203
204dcg_pi(M:Name/Arity, DCG) =>
205 Arity2 is Arity-2,
206 DCG = M:Name//Arity2.
207dcg_pi(Name/Arity, DCG) =>
208 Arity2 is Arity-2,
209 DCG = Name//Arity2.
210
211
212 215
239
240jiti_suggest_modes :-
241 jiti_suggest_modes(_:_).
242
243jiti_suggest_modes(Partial) :-
244 spec_head(Partial, Head),
245 !,
246 jiti_suggest_modes(Head).
247jiti_suggest_modes(Head) :-
248 Head = M:_,
249 freeze(M, module_property(M, class(user))),
250 findall(Head-Indexed,
251 ( predicate_property(Head, indexed(Indexed)),
252 \+ predicate_property(Head, imported_from(_))
253 ), Pairs),
254 convlist(suggest_mode, Pairs, Modes),
255 ( Modes == []
256 -> print_message(informational, jiti(no_modes(Head)))
257 ; maplist(portray_clause, Modes)
258 ).
259
260suggest_mode((M:Head)-Indexes, (:- mode(M:GenHead))) :-
261 convlist(not_realised_index_arg, Indexes, FArgs),
262 convlist(realised_index_arg, Indexes, ArgsL),
263 append(ArgsL, Realised),
264 sort(FArgs, Sargs),
265 sort(Realised, RArgs),
266 ord_subtract(Sargs, RArgs, Args),
267 Args \== [],
268 !,
269 most_general_goal(Head, GenHead),
270 make_mode(Args, GenHead).
271
272not_realised_index_arg(Index, Arg) :-
273 _{ arguments:[Arg], position:[], realised:false } :< Index.
274
275realised_index_arg(Index, Args) :-
276 _{ arguments:Args, position:[], realised:true } :< Index.
277
278make_mode([], GenHead) =>
279 functor(GenHead, _, Arity),
280 set_any(1, Arity, GenHead).
281make_mode([H|T], GenHead) =>
282 arg(H, GenHead, -),
283 make_mode(T, GenHead).
284
285set_any(I, Arity, GenHead), arg(I, GenHead, Var) =>
286 ( var(Var)
287 -> Var = '?'
288 ; true
289 ),
290 I2 is I+1,
291 set_any(I2, Arity, GenHead).
292set_any(_, _, _) =>
293 true.
294
295
296 299
300spec_head(Module:Name/Arity, Head), atom(Name), integer(Arity) =>
301 Head = Module:Head0,
302 functor(Head0, Name, Arity).
303spec_head(Module:Name/Arity, Head), atom(Name), var(Arity) =>
304 Head = Module:Head0,
305 freeze(Head0, functor(Head0, Name, _)).
306spec_head(Module:Name, Head), atom(Name) =>
307 Head = Module:Head0,
308 freeze(Head0, functor(Head0, Name, _)).
309spec_head(_, _) =>
310 fail.
311
312 315
316tty_width(W) :-
317 catch(tty_size(_, TtyW), _, fail),
318 !,
319 W is max(65, TtyW).
320tty_width(80).
321
322 325
326:- multifile prolog:message//1. 327
328prolog:message(jiti(no_modes(M:Head))) -->
329 { var(Head) },
330 [ 'No mode suggestions for predicates in module ~p'-[M] ].
331prolog:message(jiti(no_modes(Head))) -->
332 { numbervars(Head, 0, _, [singletons(true)]) },
333 [ 'No mode suggestions for ~p'-[Head] ]