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/3]). 45:- autoload(library(ansi_term), [ansi_format/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(Head-Indexed,
107 ( predicate_property(Head, indexed(Indexed)),
108 \+ predicate_property(Head, imported_from(_))
109 ), Pairs),
110 PredColW is TTYW-41,
111 TableWidth is TTYW-1,
112 ansi_format(bold, 'Predicate~*|~w ~t~10+~w ~t~w~14+ ~t~w~9+ ~t~w~7+~n',
113 [PredColW, '#Clauses', 'Index','Buckets','Speedup','Flags']),
114 format('~`\u2015t~*|~n', [TableWidth]),
115 maplist(print_indexes(PredColW), Pairs).
116
117print_indexes(PredColW, Head-List) :-
118 foldl(print_index(PredColW, Head), List, 1, _).
119
120:- det(print_index/5). 121print_index(PredColW, QHead, Dict, N, N1) :-
122 QHead = (M:Head),
123 N1 is N+1,
124 _{arguments:Args, position:Pos,
125 buckets:Buckets, speedup:Speedup, list:List, realised:R} :< Dict,
126 predicate_property(M:Head, number_of_clauses(CCount)),
127 head_pi(QHead, PI),
128 phrase(iarg_spec(Pos, Args), ArgsS),
129 phrase(iflags(List, R), Flags),
130 istyle(R, Style),
131 CCountColZ is PredColW+8,
132 ( N == 1
133 -> ansi_format(bold, '~q', [PI]),
134 format(' ~t~D~*| ', [CCount, CCountColZ])
135 ; format(' ~t~*| ', [CCountColZ])
136 ),
137 ansi_format(Style, '~|~s ~t~D~14+ ~t~1f~9+ ~s~n',
138 [ArgsS,Buckets,Speedup,Flags]).
139
140iarg_spec([], [N]) ==>
141 number(N).
142iarg_spec([], List) ==>
143 plus_list(List).
144iarg_spec(Deep, Args) ==>
145 deep_list(Deep),
146 iarg_spec([], Args).
147
148plus_list([H|T]) -->
149 number(H),
150 ( {T==[]}
151 -> []
152 ; "+",
153 plus_list(T)
154 ).
155
156deep_list([Last]) -->
157 !,
158 number(Last),
159 ":".
160deep_list([H|T]) -->
161 number(H),
162 "/",
163 deep_list(T).
164
165
166iflags(true, R) ==> "L", irealised(R).
167iflags(false, R) ==> "", irealised(R).
168
169irealised(false) ==> "V".
170irealised(true) ==> "".
171
172istyle(true, code).
173istyle(false, comment).
174
175head_pi(Head, PI) :-
176 predicate_property(Head, non_terminal),
177 !,
178 pi_head(PI0, Head),
179 dcg_pi(PI0, PI).
180head_pi(Head, PI) :-
181 pi_head(PI, Head).
182
183dcg_pi(M:Name/Arity, DCG) =>
184 Arity2 is Arity-2,
185 DCG = M:Name//Arity2.
186dcg_pi(Name/Arity, DCG) =>
187 Arity2 is Arity-2,
188 DCG = Name//Arity2.
189
190
191 194
218
219jiti_suggest_modes :-
220 jiti_suggest_modes(_:_).
221
222jiti_suggest_modes(Partial) :-
223 spec_head(Partial, Head),
224 !,
225 jiti_suggest_modes(Head).
226jiti_suggest_modes(Head) :-
227 Head = M:_,
228 freeze(M, module_property(M, class(user))),
229 findall(Head-Indexed,
230 ( predicate_property(Head, indexed(Indexed)),
231 \+ predicate_property(Head, imported_from(_))
232 ), Pairs),
233 convlist(suggest_mode, Pairs, Modes),
234 ( Modes == []
235 -> print_message(informational, jiti(no_modes(Head)))
236 ; maplist(portray_clause, Modes)
237 ).
238
239suggest_mode((M:Head)-Indexes, (:- mode(M:GenHead))) :-
240 convlist(not_realised_index_arg, Indexes, FArgs),
241 convlist(realised_index_arg, Indexes, ArgsL),
242 append(ArgsL, Realised),
243 sort(FArgs, Sargs),
244 sort(Realised, RArgs),
245 ord_subtract(Sargs, RArgs, Args),
246 Args \== [],
247 !,
248 most_general_goal(Head, GenHead),
249 make_mode(Args, GenHead).
250
251not_realised_index_arg(Index, Arg) :-
252 _{ arguments:[Arg], position:[], realised:false } :< Index.
253
254realised_index_arg(Index, Args) :-
255 _{ arguments:Args, position:[], realised:true } :< Index.
256
257make_mode([], GenHead) =>
258 functor(GenHead, _, Arity),
259 set_any(1, Arity, GenHead).
260make_mode([H|T], GenHead) =>
261 arg(H, GenHead, -),
262 make_mode(T, GenHead).
263
264set_any(I, Arity, GenHead), arg(I, GenHead, Var) =>
265 ( var(Var)
266 -> Var = '?'
267 ; true
268 ),
269 I2 is I+1,
270 set_any(I2, Arity, GenHead).
271set_any(_, _, _) =>
272 true.
273
274
275 278
279spec_head(Module:Name/Arity, Head), atom(Name), integer(Arity) =>
280 Head = Module:Head0,
281 functor(Head0, Name, Arity).
282spec_head(Module:Name/Arity, Head), atom(Name), var(Arity) =>
283 Head = Module:Head0,
284 freeze(Head0, functor(Head0, Name, _)).
285spec_head(Module:Name, Head), atom(Name) =>
286 Head = Module:Head0,
287 freeze(Head0, functor(Head0, Name, _)).
288spec_head(_, _) =>
289 fail.
290
291 294
295tty_width(W) :-
296 catch(tty_size(_, TtyW), _, fail),
297 !,
298 W is max(65, TtyW).
299tty_width(80).
300
301 304
305:- multifile prolog:message//1. 306
307prolog:message(jiti(no_modes(M:Head))) -->
308 { var(Head) },
309 [ 'No mode suggestions for predicates in module ~p'-[M] ].
310prolog:message(jiti(no_modes(Head))) -->
311 { numbervars(Head, 0, _, [singletons(true)]) },
312 [ 'No mode suggestions for ~p'-[Head] ]