36
37:- module(check,
38 [ check/0, 39 list_undefined/0, 40 list_undefined/1, 41 list_autoload/0, 42 list_redefined/0, 43 list_cross_module_calls/0, 44 list_cross_module_calls/1, 45 list_void_declarations/0, 46 list_trivial_fails/0, 47 list_trivial_fails/1, 48 list_format_errors/0, 49 list_format_errors/1, 50 list_strings/0, 51 list_strings/1, 52 list_rationals/0, 53 list_rationals/1 54 ]). 55:- autoload(library(apply),[maplist/2]). 56:- autoload(library(lists),[member/2,append/3]). 57:- autoload(library(occurs),[sub_term/2]). 58:- autoload(library(option),[merge_options/3,option/3]). 59:- autoload(library(pairs),
60 [group_pairs_by_key/2,map_list_to_pairs/3,pairs_values/2]). 61:- autoload(library(prolog_clause),
62 [clause_info/4,predicate_name/2,clause_name/2]). 63:- autoload(library(prolog_code),[pi_head/2]). 64:- autoload(library(prolog_codewalk),
65 [prolog_walk_code/1,prolog_program_clause/2]). 66:- autoload(library(prolog_format),[format_types/2]). 67
68
69:- set_prolog_flag(generate_debug_info, false). 70
71:- multifile
72 trivial_fail_goal/1,
73 string_predicate/1,
74 valid_string_goal/1,
75 checker/2. 76
77:- dynamic checker/2. 78
79
91
92:- predicate_options(list_undefined/1, 1,
93 [ module_class(list(oneof([user,library,system])))
94 ]). 95
109
110check :-
111 checker(Checker, Message),
112 print_message(informational,check(pass(Message))),
113 catch(Checker,E,print_message(error,E)),
114 fail.
115check.
116
131
132:- thread_local
133 undef/2. 134
135list_undefined :-
136 list_undefined([]).
137
138list_undefined(Options) :-
139 merge_options(Options,
140 [ module_class([user])
141 ],
142 WalkOptions),
143 call_cleanup(
144 prolog_walk_code([ undefined(trace),
145 on_trace(found_undef)
146 | WalkOptions
147 ]),
148 collect_undef(Grouped)),
149 ( Grouped == []
150 -> true
151 ; print_message(warning, check(undefined_procedures, Grouped))
152 ).
153
155
156:- public
157 found_undef/3,
158 collect_undef/1. 159
160collect_undef(Grouped) :-
161 findall(PI-From, retract(undef(PI, From)), Pairs),
162 keysort(Pairs, Sorted),
163 group_pairs_by_key(Sorted, Grouped).
164
165found_undef(To, _Caller, From) :-
166 goal_pi(To, PI),
167 ( undef(PI, From)
168 -> true
169 ; compiled(PI)
170 -> true
171 ; not_always_present(PI)
172 -> true
173 ; assertz(undef(PI,From))
174 ).
175
176compiled(system:'$call_cleanup'/0). 177compiled(system:'$catch'/0).
178compiled(system:'$cut'/0).
179compiled(system:'$reset'/0).
180compiled(system:'$call_continuation'/1).
181compiled(system:'$shift'/1).
182compiled('$engines':'$yield'/0).
183
188
189not_always_present(_:win_folder/2) :-
190 \+ current_prolog_flag(windows, true).
191not_always_present(_:win_add_dll_directory/2) :-
192 \+ current_prolog_flag(windows, true).
193
194
195goal_pi(M:Head, M:Name/Arity) :-
196 functor(Head, Name, Arity).
197
208
209list_autoload :-
210 setup_call_cleanup(
211 ( current_prolog_flag(access_level, OldLevel),
212 current_prolog_flag(autoload, OldAutoLoad),
213 set_prolog_flag(access_level, system),
214 set_prolog_flag(autoload, false)
215 ),
216 list_autoload_(OldLevel),
217 ( set_prolog_flag(access_level, OldLevel),
218 set_prolog_flag(autoload, OldAutoLoad)
219 )).
220
221list_autoload_(SystemMode) :-
222 ( setof(Lib-Pred,
223 autoload_predicate(Module, Lib, Pred, SystemMode),
224 Pairs),
225 print_message(informational,
226 check(autoload(Module, Pairs))),
227 fail
228 ; true
229 ).
230
231autoload_predicate(Module, Library, Name/Arity, SystemMode) :-
232 predicate_property(Module:Head, undefined),
233 check_module_enabled(Module, SystemMode),
234 ( \+ predicate_property(Module:Head, imported_from(_)),
235 functor(Head, Name, Arity),
236 '$find_library'(Module, Name, Arity, _LoadModule, Library),
237 referenced(Module:Head, Module, _)
238 -> true
239 ).
240
241check_module_enabled(_, system) :- !.
242check_module_enabled(Module, _) :-
243 \+ import_module(Module, system).
244
248
249referenced(Term, Module, Ref) :-
250 Goal = Module:_Head,
251 current_predicate(_, Goal),
252 '$get_predicate_attribute'(Goal, system, 0),
253 \+ '$get_predicate_attribute'(Goal, imported, _),
254 nth_clause(Goal, _, Ref),
255 '$xr_member'(Ref, Term).
256
262
263list_redefined :-
264 setup_call_cleanup(
265 ( current_prolog_flag(access_level, OldLevel),
266 set_prolog_flag(access_level, system)
267 ),
268 list_redefined_,
269 set_prolog_flag(access_level, OldLevel)).
270
271list_redefined_ :-
272 current_module(Module),
273 Module \== system,
274 current_predicate(_, Module:Head),
275 \+ predicate_property(Module:Head, imported_from(_)),
276 ( global_module(Super),
277 Super \== Module,
278 '$c_current_predicate'(_, Super:Head),
279 \+ redefined_ok(Head),
280 '$syspreds':'$defined_predicate'(Super:Head),
281 \+ predicate_property(Super:Head, (dynamic)),
282 \+ predicate_property(Super:Head, imported_from(Module)),
283 functor(Head, Name, Arity)
284 -> print_message(informational,
285 check(redefined(Module, Super, Name/Arity)))
286 ),
287 fail.
288list_redefined_.
289
290redefined_ok('$mode'(_,_)).
291redefined_ok('$pldoc'(_,_,_,_)).
292redefined_ok('$pred_option'(_,_,_,_)).
293redefined_ok('$table_mode'(_,_,_)).
294redefined_ok('$tabled'(_,_)).
295redefined_ok('$exported_op'(_,_,_)).
296redefined_ok('$autoload'(_,_,_)).
297
298global_module(user).
299global_module(system).
300
306
307list_cross_module_calls :-
308 list_cross_module_calls([]).
309
310list_cross_module_calls(Options) :-
311 call_cleanup(
312 list_cross_module_calls_guarded(Options),
313 retractall(cross_module_call(_,_,_))).
314
315list_cross_module_calls_guarded(Options) :-
316 merge_options(Options,
317 [ module_class([user])
318 ],
319 WalkOptions),
320 prolog_walk_code([ trace_reference(_),
321 trace_condition(cross_module_call),
322 on_trace(write_call)
323 | WalkOptions
324 ]).
325
326:- thread_local
327 cross_module_call/3. 328
329:- public
330 cross_module_call/2,
331 write_call/3. 332
333cross_module_call(Callee, Context) :-
334 \+ same_module_call(Callee, Context).
335
336same_module_call(Callee, Context) :-
337 caller_module(Context, MCaller),
338 Callee = (MCallee:_),
339 ( ( MCaller = MCallee
340 ; predicate_property(Callee, exported)
341 ; predicate_property(Callee, built_in)
342 ; predicate_property(Callee, public)
343 ; clause_property(Context.get(clause), module(MCallee))
344 ; predicate_property(Callee, multifile)
345 )
346 -> true
347 ).
348
349caller_module(Context, MCaller) :-
350 Caller = Context.caller,
351 ( Caller = (MCaller:_)
352 -> true
353 ; Caller == '<initialization>',
354 MCaller = Context.module
355 ).
356
357write_call(Callee, Caller, Position) :-
358 cross_module_call(Callee, Caller, Position),
359 !.
360write_call(Callee, Caller, Position) :-
361 ( cross_module_call(_,_,_)
362 -> true
363 ; print_message(warning, check(cross_module_calls))
364 ),
365 asserta(cross_module_call(Callee, Caller, Position)),
366 print_message(warning,
367 check(cross_module_call(Callee, Caller, Position))).
368
372
373list_void_declarations :-
374 P = _:_,
375 ( predicate_property(P, undefined),
376 ( '$get_predicate_attribute'(P, meta_predicate, Pattern),
377 print_message(warning,
378 check(void_declaration(P, meta_predicate(Pattern))))
379 ; void_attribute(Attr),
380 '$get_predicate_attribute'(P, Attr, 1),
381 print_message(warning,
382 check(void_declaration(P, Attr)))
383 ),
384 fail
385 ; true
386 ).
387
388void_attribute(public).
389void_attribute(volatile).
390
401
402:- thread_local
403 trivial_fail/2. 404
405list_trivial_fails :-
406 list_trivial_fails([]).
407
408list_trivial_fails(Options) :-
409 merge_options(Options,
410 [ module_class([user]),
411 infer_meta_predicates(false),
412 autoload(false),
413 evaluate(false),
414 trace_reference(_),
415 on_trace(check_trivial_fail)
416 ],
417 WalkOptions),
418
419 prolog_walk_code([ source(false)
420 | WalkOptions
421 ]),
422 findall(CRef, retract(trivial_fail(clause(CRef), _)), Clauses),
423 ( Clauses == []
424 -> true
425 ; print_message(warning, check(trivial_failures)),
426 prolog_walk_code([ clauses(Clauses)
427 | WalkOptions
428 ]),
429 findall(Goal-From, retract(trivial_fail(From, Goal)), Pairs),
430 keysort(Pairs, Sorted),
431 group_pairs_by_key(Sorted, Grouped),
432 maplist(report_trivial_fail, Grouped)
433 ).
434
439
440trivial_fail_goal(pce_expansion:pce_class(_, _, template, _, _, _)).
441trivial_fail_goal(pce_host:property(system_source_prefix(_))).
442
443:- public
444 check_trivial_fail/3. 445
446check_trivial_fail(MGoal0, _Caller, From) :-
447 ( MGoal0 = M:Goal,
448 atom(M),
449 callable(Goal),
450 predicate_property(MGoal0, interpreted),
451 \+ predicate_property(MGoal0, dynamic),
452 \+ predicate_property(MGoal0, multifile),
453 \+ trivial_fail_goal(MGoal0)
454 -> ( predicate_property(MGoal0, meta_predicate(Meta))
455 -> qualify_meta_goal(MGoal0, Meta, MGoal)
456 ; MGoal = MGoal0
457 ),
458 ( clause(MGoal, _)
459 -> true
460 ; assertz(trivial_fail(From, MGoal))
461 )
462 ; true
463 ).
464
465report_trivial_fail(Goal-FromList) :-
466 print_message(warning, check(trivial_failure(Goal, FromList))).
467
471
472qualify_meta_goal(M:Goal0, Meta, M:Goal) :-
473 functor(Goal0, F, N),
474 functor(Goal, F, N),
475 qualify_meta_goal(1, M, Meta, Goal0, Goal).
476
477qualify_meta_goal(N, M, Meta, Goal0, Goal) :-
478 arg(N, Meta, ArgM),
479 !,
480 arg(N, Goal0, Arg0),
481 arg(N, Goal, Arg),
482 N1 is N + 1,
483 ( module_qualified(ArgM)
484 -> add_module(Arg0, M, Arg)
485 ; Arg = Arg0
486 ),
487 meta_goal(N1, Meta, Goal0, Goal).
488meta_goal(_, _, _, _).
489
490add_module(Arg, M, M:Arg) :-
491 var(Arg),
492 !.
493add_module(M:Arg, _, MArg) :-
494 !,
495 add_module(Arg, M, MArg).
496add_module(Arg, M, M:Arg).
497
498module_qualified(N) :- integer(N), !.
499module_qualified(:).
500module_qualified(^).
501
502
517
518list_strings :-
519 list_strings([module_class([user])]).
520
521list_strings(Options) :-
522 ( prolog_program_clause(ClauseRef, Options),
523 clause(Head, Body, ClauseRef),
524 \+ ( predicate_indicator(Head, PI),
525 string_predicate(PI)
526 ),
527 make_clause(Head, Body, Clause),
528 findall(T,
529 ( sub_term(T, Head),
530 string(T)
531 ; Head = M:_,
532 goal_in_body(Goal, M, Body),
533 ( valid_string_goal(Goal)
534 -> fail
535 ; sub_term(T, Goal),
536 string(T)
537 )
538 ), Ts0),
539 sort(Ts0, Ts),
540 member(T, Ts),
541 message_context(ClauseRef, T, Clause, Context),
542 print_message(warning,
543 check(string_in_clause(T, Context))),
544 fail
545 ; true
546 ).
547
548make_clause(Head, true, Head) :- !.
549make_clause(Head, Body, (Head:-Body)).
550
567
568list_rationals :-
569 list_rationals([module_class([user])]).
570
571list_rationals(Options) :-
572 ( option(arithmetic(DoArith), Options, false),
573 prolog_program_clause(ClauseRef, Options),
574 clause(Head, Body, ClauseRef),
575 make_clause(Head, Body, Clause),
576 findall(T,
577 ( sub_term(T, Head),
578 rational(T),
579 \+ integer(T)
580 ; Head = M:_,
581 goal_in_body(Goal, M, Body),
582 nonvar(Goal),
583 ( DoArith == false,
584 valid_rational_goal(Goal)
585 -> fail
586 ; sub_term(T, Goal),
587 rational(T),
588 \+ integer(T)
589 )
590 ), Ts0),
591 sort(Ts0, Ts),
592 member(T, Ts),
593 message_context(ClauseRef, T, Clause, Context),
594 print_message(warning,
595 check(rational_in_clause(T, Context))),
596 fail
597 ; true
598 ).
599
600
601valid_rational_goal(_ is _).
602valid_rational_goal(_ =:= _).
603valid_rational_goal(_ < _).
604valid_rational_goal(_ > _).
605valid_rational_goal(_ =< _).
606valid_rational_goal(_ >= _).
607
608
613
614list_format_errors :-
615 list_format_errors([module_class([user])]).
616
617list_format_errors(Options) :-
618 ( prolog_program_clause(ClauseRef, Options),
619 clause(Head, Body, ClauseRef),
620 make_clause(Head, Body, Clause),
621 Head = M:_,
622 goal_in_body(Goal, M, Body),
623 format_warning(Goal, Msg),
624 message_context(ClauseRef, Goal, Clause, Context),
625 print_message(warning, check(Msg, Goal, Context)),
626 fail
627 ; true
628 ).
629
630format_warning(system:format(Format, Args), Msg) :-
631 ground(Format),
632 ( is_list(Args)
633 -> length(Args, ArgC)
634 ; nonvar(Args)
635 -> ArgC = 1
636 ),
637 E = error(Formal,_),
638 catch(format_types(Format, Types), E, true),
639 ( var(Formal)
640 -> length(Types, TypeC),
641 TypeC =\= ArgC,
642 Msg = format_argc(TypeC, ArgC)
643 ; Msg = format_template(Formal)
644 ).
645format_warning(system:format(_Stream, Format, Args), Msg) :-
646 format_warning(system:format(Format, Args), Msg).
647format_warning(prolog_debug:debug(_Channel, Format, Args), Msg) :-
648 format_warning(system:format(Format, Args), Msg).
649
650
654
655goal_in_body(M:G, M, G) :-
656 var(G),
657 !.
658goal_in_body(G, _, M:G0) :-
659 atom(M),
660 !,
661 goal_in_body(G, M, G0).
662goal_in_body(G, M, Control) :-
663 nonvar(Control),
664 control(Control, Subs),
665 !,
666 member(Sub, Subs),
667 goal_in_body(G, M, Sub).
668goal_in_body(G, M, G0) :-
669 callable(G0),
670 ( atom(M)
671 -> TM = M
672 ; TM = system
673 ),
674 predicate_property(TM:G0, meta_predicate(Spec)),
675 !,
676 ( strip_goals(G0, Spec, G1),
677 simple_goal_in_body(G, M, G1)
678 ; arg(I, Spec, Meta),
679 arg(I, G0, G1),
680 extend(Meta, G1, G2),
681 goal_in_body(G, M, G2)
682 ).
683goal_in_body(G, M, G0) :-
684 simple_goal_in_body(G, M, G0).
685
686simple_goal_in_body(G, M, G0) :-
687 ( atom(M),
688 callable(G0),
689 predicate_property(M:G0, imported_from(M2))
690 -> G = M2:G0
691 ; G = M:G0
692 ).
693
694control((A,B), [A,B]).
695control((A;B), [A,B]).
696control((A->B), [A,B]).
697control((A*->B), [A,B]).
698control((\+A), [A]).
699
700strip_goals(G0, Spec, G) :-
701 functor(G0, Name, Arity),
702 functor(G, Name, Arity),
703 strip_goal_args(1, G0, Spec, G).
704
705strip_goal_args(I, G0, Spec, G) :-
706 arg(I, G0, A0),
707 !,
708 arg(I, Spec, M),
709 ( extend(M, A0, _)
710 -> arg(I, G, '<meta-goal>')
711 ; arg(I, G, A0)
712 ),
713 I2 is I + 1,
714 strip_goal_args(I2, G0, Spec, G).
715strip_goal_args(_, _, _, _).
716
717extend(I, G0, G) :-
718 callable(G0),
719 integer(I), I>0,
720 !,
721 length(L, I),
722 extend_list(G0, L, G).
723extend(0, G, G).
724extend(^, G, G).
725
726extend_list(M:G0, L, M:G) :-
727 !,
728 callable(G0),
729 extend_list(G0, L, G).
730extend_list(G0, L, G) :-
731 G0 =.. List,
732 append(List, L, All),
733 G =.. All.
734
735
739
740message_context(ClauseRef, Term, Clause, file_term_position(File, TermPos)) :-
741 clause_info(ClauseRef, File, Layout, _Vars),
742 ( Term = _:Goal,
743 prolog_codewalk:subterm_pos(Goal, Clause, ==, Layout, TermPos)
744 ; prolog_codewalk:subterm_pos(Term, Clause, ==, Layout, TermPos)
745 ),
746 !.
747message_context(ClauseRef, _String, _Clause, file(File, Line, -1, _)) :-
748 clause_property(ClauseRef, file(File)),
749 clause_property(ClauseRef, line_count(Line)),
750 !.
751message_context(ClauseRef, _String, _Clause, clause(ClauseRef)).
752
753
754:- meta_predicate
755 predicate_indicator(:, -). 756
757predicate_indicator(Module:Head, Module:Name/Arity) :-
758 functor(Head, Name, Arity).
759predicate_indicator(Module:Head, Module:Name//DCGArity) :-
760 functor(Head, Name, Arity),
761 DCGArity is Arity-2.
762
767
768string_predicate(_:'$pldoc'/4).
769string_predicate(pce_principal:send_implementation/3).
770string_predicate(pce_principal:pce_lazy_get_method/3).
771string_predicate(pce_principal:pce_lazy_send_method/3).
772string_predicate(pce_principal:pce_class/6).
773string_predicate(prolog_xref:pred_comment/4).
774string_predicate(prolog_xref:module_comment/3).
775string_predicate(pldoc_process:structured_comment//2).
776string_predicate(pldoc_process:structured_command_start/3).
777string_predicate(pldoc_process:separator_line//0).
778string_predicate(pldoc_register:mydoc/3).
779string_predicate(http_header:separators/1).
780
786
788valid_string_goal(system:format(S)) :- string(S).
789valid_string_goal(system:format(S,_)) :- string(S).
790valid_string_goal(system:format(_,S,_)) :- string(S).
791valid_string_goal(system:string_codes(S,_)) :- string(S).
792valid_string_goal(system:string_code(_,S,_)) :- string(S).
793valid_string_goal(system:throw(msg(S,_))) :- string(S).
794valid_string_goal('$dcg':phrase(S,_,_)) :- string(S).
795valid_string_goal('$dcg':phrase(S,_)) :- string(S).
796valid_string_goal(system: is(_,_)). 797valid_string_goal(system: =:=(_,_)).
798valid_string_goal(system: >(_,_)).
799valid_string_goal(system: <(_,_)).
800valid_string_goal(system: >=(_,_)).
801valid_string_goal(system: =<(_,_)).
803valid_string_goal(dcg_basics:string_without(S,_,_,_)) :- string(S).
804valid_string_goal(git:read_url(S,_,_)) :- string(S).
805valid_string_goal(tipc:tipc_subscribe(_,_,_,_,S)) :- string(S).
806valid_string_goal(charsio:format_to_chars(Format,_,_)) :- string(Format).
807valid_string_goal(charsio:format_to_chars(Format,_,_,_)) :- string(Format).
808valid_string_goal(codesio:format_to_codes(Format,_,_)) :- string(Format).
809valid_string_goal(codesio:format_to_codes(Format,_,_,_)) :- string(Format).
810
811
812 815
835
836checker(list_undefined, 'undefined predicates').
837checker(list_trivial_fails, 'trivial failures').
838checker(list_format_errors, 'format/2,3 and debug/3 templates').
839checker(list_redefined, 'redefined system and global predicates').
840checker(list_void_declarations, 'predicates with declarations but without clauses').
841checker(list_autoload, 'predicates that need autoloading').
842
843
844 847
848:- multifile
849 prolog:message/3. 850
851prolog:message(check(pass(Comment))) -->
852 [ 'Checking ~w ...'-[Comment] ].
853prolog:message(check(find_references(Preds))) -->
854 { length(Preds, N)
855 },
856 [ 'Scanning for references to ~D possibly undefined predicates'-[N] ].
857prolog:message(check(undefined_procedures, Grouped)) -->
858 [ 'The predicates below are not defined. If these are defined', nl,
859 'at runtime using assert/1, use :- dynamic Name/Arity.', nl, nl
860 ],
861 undefined_procedures(Grouped).
862prolog:message(check(undefined_unreferenced_predicates)) -->
863 [ 'The predicates below are not defined, and are not', nl,
864 'referenced.', nl, nl
865 ].
866prolog:message(check(undefined_unreferenced(Pred))) -->
867 predicate(Pred).
868prolog:message(check(autoload(Module, Pairs))) -->
869 { module_property(Module, file(Path))
870 },
871 !,
872 [ 'Into module ~w ('-[Module] ],
873 short_filename(Path),
874 [ ')', nl ],
875 autoload(Pairs).
876prolog:message(check(autoload(Module, Pairs))) -->
877 [ 'Into module ~w'-[Module], nl ],
878 autoload(Pairs).
879prolog:message(check(redefined(In, From, Pred))) -->
880 predicate(In:Pred),
881 redefined(In, From).
882prolog:message(check(cross_module_calls)) -->
883 [ 'Qualified calls to private predicates'-[] ].
884prolog:message(check(cross_module_call(Callee, _Caller, Location))) -->
885 { pi_head(PI, Callee) },
886 [ ' '-[] ],
887 '$messages':swi_location(Location),
888 [ 'Cross-module call to ~p'-[PI] ].
889prolog:message(check(trivial_failures)) -->
890 [ 'The following goals fail because there are no matching clauses.' ].
891prolog:message(check(trivial_failure(Goal, Refs))) -->
892 { map_list_to_pairs(sort_reference_key, Refs, Keyed),
893 keysort(Keyed, KeySorted),
894 pairs_values(KeySorted, SortedRefs)
895 },
896 goal(Goal),
897 [ ', which is called from'-[], nl ],
898 referenced_by(SortedRefs).
899prolog:message(check(string_in_clause(String, Context))) -->
900 '$messages':swi_location(Context),
901 [ 'String ~q'-[String] ].
902prolog:message(check(rational_in_clause(String, Context))) -->
903 '$messages':swi_location(Context),
904 [ 'Rational ~q'-[String] ].
905prolog:message(check(Msg, Goal, Context)) -->
906 '$messages':swi_location(Context),
907 { pi_head(PI, Goal) },
908 [ nl, ' '-[] ],
909 predicate(PI),
910 [ ': '-[] ],
911 check_message(Msg).
912prolog:message(check(void_declaration(P, Decl))) -->
913 predicate(P),
914 [ ' is declared as ~p, but has no clauses'-[Decl] ].
915
916undefined_procedures([]) -->
917 [].
918undefined_procedures([H|T]) -->
919 undefined_procedure(H),
920 undefined_procedures(T).
921
922undefined_procedure(Pred-Refs) -->
923 { map_list_to_pairs(sort_reference_key, Refs, Keyed),
924 keysort(Keyed, KeySorted),
925 pairs_values(KeySorted, SortedRefs)
926 },
927 predicate(Pred),
928 [ ', which is referenced by', nl ],
929 referenced_by(SortedRefs).
930
931redefined(user, system) -->
932 [ '~t~30| System predicate redefined globally' ].
933redefined(_, system) -->
934 [ '~t~30| Redefined system predicate' ].
935redefined(_, user) -->
936 [ '~t~30| Redefined global predicate' ].
937
938goal(user:Goal) -->
939 !,
940 [ '~p'-[Goal] ].
941goal(Goal) -->
942 !,
943 [ '~p'-[Goal] ].
944
945predicate(Module:Name/Arity) -->
946 { atom(Module),
947 atom(Name),
948 integer(Arity),
949 functor(Head, Name, Arity),
950 predicate_name(Module:Head, PName)
951 },
952 !,
953 [ '~w'-[PName] ].
954predicate(Module:Head) -->
955 { atom(Module),
956 callable(Head),
957 predicate_name(Module:Head, PName)
958 },
959 !,
960 [ '~w'-[PName] ].
961predicate(Name/Arity) -->
962 { atom(Name),
963 integer(Arity)
964 },
965 !,
966 predicate(user:Name/Arity).
967
968autoload([]) -->
969 [].
970autoload([Lib-Pred|T]) -->
971 [ ' ' ],
972 predicate(Pred),
973 [ '~t~24| from ' ],
974 short_filename(Lib),
975 [ nl ],
976 autoload(T).
977
981
982sort_reference_key(Term, key(M:Name/Arity, N, ClausePos)) :-
983 clause_ref(Term, ClauseRef, ClausePos),
984 !,
985 nth_clause(Pred, N, ClauseRef),
986 strip_module(Pred, M, Head),
987 functor(Head, Name, Arity).
988sort_reference_key(Term, Term).
989
990clause_ref(clause_term_position(ClauseRef, TermPos), ClauseRef, ClausePos) :-
991 arg(1, TermPos, ClausePos).
992clause_ref(clause(ClauseRef), ClauseRef, 0).
993
994
995referenced_by([]) -->
996 [].
997referenced_by([Ref|T]) -->
998 ['\t'], prolog:message_location(Ref),
999 predicate_indicator(Ref),
1000 [ nl ],
1001 referenced_by(T).
1002
1003predicate_indicator(clause_term_position(ClauseRef, _)) -->
1004 { nonvar(ClauseRef) },
1005 !,
1006 predicate_indicator(clause(ClauseRef)).
1007predicate_indicator(clause(ClauseRef)) -->
1008 { clause_name(ClauseRef, Name) },
1009 [ '~w'-[Name] ].
1010predicate_indicator(file_term_position(_,_)) -->
1011 [ '(initialization)' ].
1012predicate_indicator(file(_,_,_,_)) -->
1013 [ '(initialization)' ].
1014
1015
1016short_filename(Path) -->
1017 { short_filename(Path, Spec)
1018 },
1019 [ '~q'-[Spec] ].
1020
1021short_filename(Path, Spec) :-
1022 absolute_file_name('', Here),
1023 atom_concat(Here, Local0, Path),
1024 !,
1025 remove_leading_slash(Local0, Spec).
1026short_filename(Path, Spec) :-
1027 findall(LenAlias, aliased_path(Path, LenAlias), Keyed),
1028 keysort(Keyed, [_-Spec|_]).
1029short_filename(Path, Path).
1030
1031aliased_path(Path, Len-Spec) :-
1032 setof(Alias, Spec^(user:file_search_path(Alias, Spec)), Aliases),
1033 member(Alias, Aliases),
1034 Term =.. [Alias, '.'],
1035 absolute_file_name(Term,
1036 [ file_type(directory),
1037 file_errors(fail),
1038 solutions(all)
1039 ], Prefix),
1040 atom_concat(Prefix, Local0, Path),
1041 remove_leading_slash(Local0, Local),
1042 atom_length(Local, Len),
1043 Spec =.. [Alias, Local].
1044
1045remove_leading_slash(Path, Local) :-
1046 atom_concat(/, Local, Path),
1047 !.
1048remove_leading_slash(Path, Path).
1049
1050check_message(format_argc(Expected, InList)) -->
1051 [ 'Template requires ~w arguments, got ~w'-[Expected, InList] ].
1052check_message(format_template(Formal)) -->
1053 { message_to_string(error(Formal, _), Msg) },
1054 [ 'Invalid template: ~s'-[Msg] ]