36
37:- module(prolog_explain,
38 [ explain/1,
39 explain/2
40 ]). 41:- autoload(library(apply),[maplist/2,maplist/3]). 42:- autoload(library(lists),[flatten/2]). 43:- autoload(library(prolog_code), [pi_head/2]). 44
45:- if(exists_source(library(pldoc/man_index))). 46:- autoload(library(pldoc/man_index), [man_object_property/2]). 47:- endif.
77explain(Item) :-
78 explain(Item, Explanation),
79 writeln(Explanation),
80 fail.
81explain(_).
82
83
91explain(Var, Explanation) :-
92 var(Var),
93 !,
94 utter(Explanation, '"~w" is an unbound variable', [Var]).
95explain(I, Explanation) :-
96 integer(I),
97 !,
98 utter(Explanation, '"~w" is an integer', [I]).
99explain(F, Explanation) :-
100 float(F),
101 !,
102 utter(Explanation, '"~w" is a floating point number', [F]).
103explain(S, Explanation) :-
104 string(S),
105 !,
106 utter(Explanation, '"~w" is a string', S).
107explain([], Explanation) :-
108 !,
109 utter(Explanation, '"[]" is a special constant denoting an empty list', []).
110explain(A, Explanation) :-
111 atom(A),
112 utter(Explanation, '"~w" is an atom', [A]).
113explain(A, Explanation) :-
114 atom(A),
115 current_op(Pri, F, A),
116 op_type(F, Type),
117 utter(Explanation, '"~w" is a ~w (~w) operator of priority ~d',
118 [A, Type, F, Pri]).
119explain(A, Explanation) :-
120 atom(A),
121 !,
122 explain_atom(A, Explanation).
123explain([H|T], Explanation) :-
124 is_list(T),
125 !,
126 List = [H|T],
127 length(List, L),
128 ( utter(Explanation, '"~p" is a proper list with ~d elements',
129 [List, L])
130 ; maplist(printable, List),
131 utter(Explanation, '~t~4|Text is "~s"', [List])
132 ).
133explain([H|T], Explanation) :-
134 !,
135 length([H|T], L),
136 !,
137 utter(Explanation, '"~p" is a not-closed list with ~d elements',
138 [[H|T], L]).
139explain(Name/Arity, Explanation) :-
140 atom(Name),
141 integer(Arity),
142 !,
143 functor(Head, Name, Arity),
144 known_predicate(Module:Head),
145 ( Module == system
146 -> true
147 ; \+ predicate_property(Module:Head, imported_from(_))
148 ),
149 explain_predicate(Module:Head, Explanation).
150explain(Module:Name/Arity, Explanation) :-
151 atom(Module), atom(Name), integer(Arity),
152 !,
153 functor(Head, Name, Arity),
154 explain_predicate(Module:Head, Explanation).
155explain(Module:Head, Explanation) :-
156 callable(Head),
157 !,
158 explain_predicate(Module:Head, Explanation).
159explain(Dict, Explanation) :-
160 is_dict(Dict, Tag),
161 !,
162 utter(Explanation, '"~W" is a dict with tag ~q',
163 [Dict, [quoted(true), numbervars(true)], Tag]).
164explain(Term, Explanation) :-
165 numbervars(Term, 0, _, [singletons(true)]),
166 utter(Explanation, '"~W" is a compound term',
167 [Term, [quoted(true), numbervars(true)]]).
168explain(Term, Explanation) :-
169 explain_functor(Term, Explanation).
177known_predicate(M:Head) :-
178 var(M),
179 current_predicate(_, M2:Head),
180 ( predicate_property(M2:Head, imported_from(M))
181 -> true
182 ; M = M2
183 ),
184 !.
185known_predicate(Pred) :-
186 predicate_property(Pred, undefined).
187known_predicate(_:Head) :-
188 functor(Head, Name, Arity),
189 '$in_library'(Name, Arity, _Path).
190
191op_type(X, prefix) :-
192 atom_chars(X, [f, _]).
193op_type(X, infix) :-
194 atom_chars(X, [_, f, _]).
195op_type(X, postfix) :-
196 atom_chars(X, [_, f]).
197
198printable(C) :-
199 integer(C),
200 code_type(C, graph).
201
202
203 206
207explain_atom(A, Explanation) :-
208 referenced(A, Explanation).
209explain_atom(A, Explanation) :-
210 current_predicate(A, Module:Head),
211 ( Module == system
212 -> true
213 ; \+ predicate_property(Module:Head, imported_from(_))
214 ),
215 explain_predicate(Module:Head, Explanation).
216explain_atom(A, Explanation) :-
217 predicate_property(Module:Head, undefined),
218 functor(Head, A, _),
219 explain_predicate(Module:Head, Explanation).
220
221
222 225
226explain_functor(Head, Explanation) :-
227 referenced(Head, Explanation).
228explain_functor(Head, Explanation) :-
229 current_predicate(_, Module:Head),
230 \+ predicate_property(Module:Head, imported_from(_)),
231 explain_predicate(Module:Head, Explanation).
232explain_functor(Head, Explanation) :-
233 predicate_property(M:Head, undefined),
234 ( functor(Head, N, A),
235 utter(Explanation,
236 '~w:~w/~d is an undefined predicate', [M,N,A])
237 ; referenced(M:Head, Explanation)
238 ).
239
240
241 244
245lproperty(built_in, ' built-in', []).
246lproperty(dynamic, ' dynamic', []).
247lproperty(multifile, ' multifile', []).
248lproperty(transparent, ' meta', []).
249
250tproperty(imported_from(Module), ' imported from module ~w', [Module]).
251tproperty(file(File), ' defined in~n~t~4|~w', [File]).
252tproperty(line_count(Number), ':~d', [Number]).
253tproperty(autoload, ' that can be autoloaded', []).
254
255combine_utterances(Pairs, Explanation) :-
256 maplist(first, Pairs, Fmts),
257 atomic_list_concat(Fmts, Format),
258 maplist(second, Pairs, ArgList),
259 flatten(ArgList, Args),
260 utter(Explanation, Format, Args).
261
262first(A-_B, A).
263second(_A-B, B).
267explain_predicate(Pred, Explanation) :-
268 Pred = Module:Head,
269 functor(Head, Name, Arity),
270
271 ( predicate_property(Pred, undefined)
272 -> utter(Explanation,
273 '~w:~w/~d is an undefined predicate', [Module,Name,Arity])
274 ; ( var(Module)
275 -> U0 = '~w/~d is a' - [Name, Arity]
276 ; U0 = '~w:~w/~d is a' - [Module, Name, Arity]
277 ),
278 findall(Fmt-Arg, (lproperty(Prop, Fmt, Arg),
279 predicate_property(Pred, Prop)),
280 U1),
281 U2 = ' predicate' - [],
282 findall(Fmt-Arg, (tproperty(Prop, Fmt, Arg),
283 predicate_property(Pred, Prop)),
284 U3),
285 flatten([U0, U1, U2, U3], Utters),
286 combine_utterances(Utters, Explanation)
287 ).
288:- if(current_predicate(man_object_property/2)). 289explain_predicate(Pred, Explanation) :-
290 Pred = _Module:Head,
291 functor(Head, Name, Arity),
292 man_object_property(Name/Arity, summary(Summary)),
293 source_file(Pred, File),
294 current_prolog_flag(home, Home),
295 sub_atom(File, 0, _, _, Home),
296 utter(Explanation, '~t~4|Summary: ``~w''''', [Summary]).
297:- endif. 298explain_predicate(Pred, Explanation) :-
299 referenced(Pred, Explanation).
300
301 304
305referenced(Term, Explanation) :-
306 current_predicate(_, Module:Head),
307 ( predicate_property(Module:Head, built_in)
308 -> current_prolog_flag(access_level, system)
309 ; true
310 ),
311 \+ predicate_property(Module:Head, imported_from(_)),
312 Module:Head \= help_index:predicate(_,_,_,_,_),
313 nth_clause(Module:Head, N, Ref),
314 '$xr_member'(Ref, Term),
315 utter_referenced(Module:Head, N, Ref,
316 'Referenced', Explanation).
317referenced(_:Head, Explanation) :-
318 current_predicate(_, Module:Head),
319 ( predicate_property(Module:Head, built_in)
320 -> current_prolog_flag(access_level, system)
321 ; true
322 ),
323 \+ predicate_property(Module:Head, imported_from(_)),
324 nth_clause(Module:Head, N, Ref),
325 '$xr_member'(Ref, Head),
326 utter_referenced(Module:Head, N, Ref,
327 'Possibly referenced', Explanation).
328
329utter_referenced(_Module:class(_,_,_,_,_,_), _, _, _, _) :-
330 current_prolog_flag(xpce, true),
331 !,
332 fail.
333utter_referenced(_Module:lazy_send_method(_,_,_), _, _, _, _) :-
334 current_prolog_flag(xpce, true),
335 !,
336 fail.
337utter_referenced(_Module:lazy_get_method(_,_,_), _, _, _, _) :-
338 current_prolog_flag(xpce, true),
339 !,
340 fail.
341utter_referenced(From, _, _, _, _) :-
342 hide_reference(From),
343 !,
344 fail.
345utter_referenced(pce_xref:defined(_,_,_), _, _, _, _) :-
346 !,
347 fail.
348utter_referenced(pce_xref:called(_,_,_), _, _, _, _) :-
349 !,
350 fail.
351utter_referenced(pce_principal:send_implementation(_, _, _),
352 _, Ref, Text, Explanation) :-
353 current_prolog_flag(xpce, true),
354 !,
355 xpce_method_id(Ref, Id),
356 utter(Explanation, '~t~4|~w from ~w', [Text, Id]).
357utter_referenced(pce_principal:get_implementation(Id, _, _, _),
358 _, Ref, Text, Explanation) :-
359 current_prolog_flag(xpce, true),
360 !,
361 xpce_method_id(Ref, Id),
362 utter(Explanation, '~t~4|~w from ~w', [Text, Id]).
363utter_referenced(Head, N, Ref, Text, Explanation) :-
364 clause_property(Ref, file(File)),
365 clause_property(Ref, line_count(Line)),
366 !,
367 pi_head(PI, Head),
368 utter(Explanation,
369 '~t~4|~w from ~d-th clause of ~q at ~w:~d',
370 [Text, N, PI, File, Line]).
371utter_referenced(Head, N, _Ref, Text, Explanation) :-
372 pi_head(PI, Head),
373 utter(Explanation,
374 '~t~4|~w from ~d-th clause of ~q',
375 [Text, N, PI]).
376
377xpce_method_id(Ref, Id) :-
378 clause(Head, _Body, Ref),
379 strip_module(Head, _, H),
380 arg(1, H, Id).
381
382hide_reference(pce_xref:exported(_,_)).
383hide_reference(pce_xref:defined(_,_,_)).
384hide_reference(pce_xref:called(_,_,_)).
385hide_reference(prolog_xref:pred_mode(_,_,_)).
386hide_reference(prolog_xref:exported(_,_)).
387hide_reference(prolog_xref:dynamic(_,_,_)).
388hide_reference(prolog_xref:imported(_,_,_)).
389hide_reference(prolog_xref:pred_comment(_,_,_,_)).
390hide_reference(_:'$mode'(_,_)).
391
392
393 396
397utter(Explanation, Fmt, Args) :-
398 format(string(Explanation), Fmt, Args)
Describe Prolog Terms
The library(explain) describes prolog-terms. The most useful functionality is its cross-referencing function.
Note that PceEmacs can jump to definitions and gxref/0 can be used for an overview of dependencies. */