1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 1985-2018, University of Amsterdam 7 VU University Amsterdam 8 CWI, Amsterdam 9 All rights reserved. 10 11 Redistribution and use in source and binary forms, with or without 12 modification, are permitted provided that the following conditions 13 are met: 14 15 1. Redistributions of source code must retain the above copyright 16 notice, this list of conditions and the following disclaimer. 17 18 2. Redistributions in binary form must reproduce the above copyright 19 notice, this list of conditions and the following disclaimer in 20 the documentation and/or other materials provided with the 21 distribution. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 POSSIBILITY OF SUCH DAMAGE. 35*/ 36 37:- module(check, 38 [ check/0, % run all checks 39 list_undefined/0, % list undefined predicates 40 list_undefined/1, % +Options 41 list_autoload/0, % list predicates that need autoloading 42 list_redefined/0, % list redefinitions 43 list_void_declarations/0, % list declarations with no clauses 44 list_trivial_fails/0, % list goals that trivially fail 45 list_trivial_fails/1, % +Options 46 list_strings/0, % list string objects in clauses 47 list_strings/1 % +Options 48 ]). 49:- use_module(library(lists)). 50:- use_module(library(pairs)). 51:- use_module(library(option)). 52:- use_module(library(apply)). 53:- use_module(library(prolog_codewalk)). 54:- use_module(library(occurs)). 55 56:- set_prolog_flag(generate_debug_info, false). 57 58:- multifile 59 trivial_fail_goal/1, 60 string_predicate/1, 61 valid_string_goal/1, 62 checker/2. 63 64:- dynamic checker/2.
79:- predicate_options(list_undefined/1, 1,
80 [ module_class(list(oneof([user,library])))
81 ]).
97check :- 98 checker(Checker, Message), 99 print_message(informational,check(pass(Message))), 100 catch(Checker,E,print_message(error,E)), 101 fail. 102check.
[user]
. For example, to include the
libraries into the examination, use [user,library]
.119:- thread_local 120 undef/2. 121 122list_undefined :- 123 list_undefined([]). 124 125list_undefined(Options) :- 126 merge_options(Options, 127 [ module_class([user]) 128 ], 129 WalkOptions), 130 call_cleanup( 131 prolog_walk_code([ undefined(trace), 132 on_trace(found_undef) 133 | WalkOptions 134 ]), 135 collect_undef(Grouped)), 136 ( Grouped == [] 137 -> true 138 ; print_message(warning, check(undefined_procedures, Grouped)) 139 ). 140 141% The following predicates are used from library(prolog_autoload). 142 143:- public 144 found_undef/3, 145 collect_undef/1. 146 147collect_undef(Grouped) :- 148 findall(PI-From, retract(undef(PI, From)), Pairs), 149 keysort(Pairs, Sorted), 150 group_pairs_by_key(Sorted, Grouped). 151 152found_undef(To, _Caller, From) :- 153 goal_pi(To, PI), 154 ( undef(PI, From) 155 -> true 156 ; compiled(PI) 157 -> true 158 ; not_always_present(PI) 159 -> true 160 ; assertz(undef(PI,From)) 161 ). 162 163compiled(system:'$call_cleanup'/0). % compiled to VM instructions 164compiled(system:'$catch'/0). 165compiled(system:'$cut'/0). 166compiled(system:'$reset'/0). 167compiled(system:'$call_continuation'/1). 168compiled(system:'$shift'/1). 169compiled('$engines':'$yield'/0).
176not_always_present(_:win_folder/2) :- 177 \+ current_prolog_flag(windows, true). 178not_always_present(_:win_add_dll_directory/2) :- 179 \+ current_prolog_flag(windows, true). 180 181 182goal_pi(M:Head, M:Name/Arity) :- 183 functor(Head, Name, Arity).
196list_autoload :- 197 setup_call_cleanup( 198 ( current_prolog_flag(access_level, OldLevel), 199 current_prolog_flag(autoload, OldAutoLoad), 200 set_prolog_flag(access_level, system), 201 set_prolog_flag(autoload, false) 202 ), 203 list_autoload_(OldLevel), 204 ( set_prolog_flag(access_level, OldLevel), 205 set_prolog_flag(autoload, OldAutoLoad) 206 )). 207 208list_autoload_(SystemMode) :- 209 ( setof(Lib-Pred, 210 autoload_predicate(Module, Lib, Pred, SystemMode), 211 Pairs), 212 print_message(informational, 213 check(autoload(Module, Pairs))), 214 fail 215 ; true 216 ). 217 218autoload_predicate(Module, Library, Name/Arity, SystemMode) :- 219 predicate_property(Module:Head, undefined), 220 check_module_enabled(Module, SystemMode), 221 ( \+ predicate_property(Module:Head, imported_from(_)), 222 functor(Head, Name, Arity), 223 '$find_library'(Module, Name, Arity, _LoadModule, Library), 224 referenced(Module:Head, Module, _) 225 -> true 226 ). 227 228check_module_enabled(_, system) :- !. 229check_module_enabled(Module, _) :- 230 \+ import_module(Module, system).
236referenced(Term, Module, Ref) :-
237 Goal = Module:_Head,
238 current_predicate(_, Goal),
239 '$get_predicate_attribute'(Goal, system, 0),
240 \+ '$get_predicate_attribute'(Goal, imported, _),
241 nth_clause(Goal, _, Ref),
242 '$xr_member'(Ref, Term).
user
as
well as in a normal module; that is, predicates for which the
local definition overrules the global default definition.250list_redefined :- 251 setup_call_cleanup( 252 ( current_prolog_flag(access_level, OldLevel), 253 set_prolog_flag(access_level, system) 254 ), 255 list_redefined_, 256 set_prolog_flag(access_level, OldLevel)). 257 258list_redefined_ :- 259 current_module(Module), 260 Module \== system, 261 current_predicate(_, Module:Head), 262 \+ predicate_property(Module:Head, imported_from(_)), 263 ( global_module(Super), 264 Super \== Module, 265 '$c_current_predicate'(_, Super:Head), 266 \+ redefined_ok(Head), 267 '$syspreds':'$defined_predicate'(Super:Head), 268 \+ predicate_property(Super:Head, (dynamic)), 269 \+ predicate_property(Super:Head, imported_from(Module)), 270 functor(Head, Name, Arity) 271 -> print_message(informational, 272 check(redefined(Module, Super, Name/Arity))) 273 ), 274 fail. 275list_redefined_. 276 277redefined_ok('$mode'(_,_)). 278redefined_ok('$pldoc'(_,_,_,_)). 279redefined_ok('$pred_option'(_,_,_,_)). 280 281global_module(user). 282global_module(system).
288list_void_declarations :- 289 P = _:_, 290 ( predicate_property(P, undefined), 291 ( '$get_predicate_attribute'(P, meta_predicate, Pattern), 292 print_message(warning, 293 check(void_declaration(P, meta_predicate(Pattern)))) 294 ; void_attribute(Attr), 295 '$get_predicate_attribute'(P, Attr, 1), 296 print_message(warning, 297 check(void_declaration(P, Attr))) 298 ), 299 fail 300 ; true 301 ). 302 303void_attribute(public). 304void_attribute(volatile).
[user]
. For example, to include the
libraries into the examination, use [user,library]
.317:- thread_local 318 trivial_fail/2. 319 320list_trivial_fails :- 321 list_trivial_fails([]). 322 323list_trivial_fails(Options) :- 324 merge_options(Options, 325 [ module_class([user]), 326 infer_meta_predicates(false), 327 autoload(false), 328 evaluate(false), 329 trace_reference(_), 330 on_trace(check_trivial_fail) 331 ], 332 WalkOptions), 333 334 prolog_walk_code([ source(false) 335 | WalkOptions 336 ]), 337 findall(CRef, retract(trivial_fail(clause(CRef), _)), Clauses), 338 ( Clauses == [] 339 -> true 340 ; print_message(warning, check(trivial_failures)), 341 prolog_walk_code([ clauses(Clauses) 342 | WalkOptions 343 ]), 344 findall(Goal-From, retract(trivial_fail(From, Goal)), Pairs), 345 keysort(Pairs, Sorted), 346 group_pairs_by_key(Sorted, Grouped), 347 maplist(report_trivial_fail, Grouped) 348 ).
355trivial_fail_goal(pce_expansion:pce_class(_, _, template, _, _, _)). 356trivial_fail_goal(pce_host:property(system_source_prefix(_))). 357 358:- public 359 check_trivial_fail/3. 360 361check_trivial_fail(MGoal0, _Caller, From) :- 362 ( MGoal0 = M:Goal, 363 atom(M), 364 callable(Goal), 365 predicate_property(MGoal0, interpreted), 366 \+ predicate_property(MGoal0, dynamic), 367 \+ predicate_property(MGoal0, multifile), 368 \+ trivial_fail_goal(MGoal0) 369 -> ( predicate_property(MGoal0, meta_predicate(Meta)) 370 -> qualify_meta_goal(MGoal0, Meta, MGoal) 371 ; MGoal = MGoal0 372 ), 373 ( clause(MGoal, _) 374 -> true 375 ; assertz(trivial_fail(From, MGoal)) 376 ) 377 ; true 378 ). 379 380report_trivial_fail(Goal-FromList) :- 381 print_message(warning, check(trivial_failure(Goal, FromList))).
387qualify_meta_goal(M:Goal0, Meta, M:Goal) :- 388 functor(Goal0, F, N), 389 functor(Goal, F, N), 390 qualify_meta_goal(1, M, Meta, Goal0, Goal). 391 392qualify_meta_goal(N, M, Meta, Goal0, Goal) :- 393 arg(N, Meta, ArgM), 394 !, 395 arg(N, Goal0, Arg0), 396 arg(N, Goal, Arg), 397 N1 is N + 1, 398 ( module_qualified(ArgM) 399 -> add_module(Arg0, M, Arg) 400 ; Arg = Arg0 401 ), 402 meta_goal(N1, Meta, Goal0, Goal). 403meta_goal(_, _, _, _). 404 405add_module(Arg, M, M:Arg) :- 406 var(Arg), 407 !. 408add_module(M:Arg, _, MArg) :- 409 !, 410 add_module(Arg, M, MArg). 411add_module(Arg, M, M:Arg). 412 413module_qualified(N) :- integer(N), !. 414module_qualified(:). 415module_qualified(^).
double_quotes
from codes
to string
, creating packed string
objects. Warnings may be suppressed using the following
multifile hooks:
433list_strings :- 434 list_strings([module_class([user])]). 435 436list_strings(Options) :- 437 ( prolog_program_clause(ClauseRef, Options), 438 clause(Head, Body, ClauseRef), 439 \+ ( predicate_indicator(Head, PI), 440 string_predicate(PI) 441 ), 442 make_clause(Head, Body, Clause), 443 findall(T, 444 ( sub_term(T, Head), 445 string(T) 446 ; Head = M:_, 447 goal_in_body(Goal, M, Body), 448 ( valid_string_goal(Goal) 449 -> fail 450 ; sub_term(T, Goal), 451 string(T) 452 ) 453 ), Ts0), 454 sort(Ts0, Ts), 455 member(T, Ts), 456 message_context(ClauseRef, T, Clause, Context), 457 print_message(warning, 458 check(string_in_clause(T, Context))), 459 fail 460 ; true 461 ). 462 463make_clause(Head, true, Head) :- !. 464make_clause(Head, Body, (Head:-Body)).
470goal_in_body(M:G, M, G) :- 471 var(G), 472 !. 473goal_in_body(G, _, M:G0) :- 474 atom(M), 475 !, 476 goal_in_body(G, M, G0). 477goal_in_body(G, M, Control) :- 478 nonvar(Control), 479 control(Control, Subs), 480 !, 481 member(Sub, Subs), 482 goal_in_body(G, M, Sub). 483goal_in_body(G, M, G0) :- 484 callable(G0), 485 ( atom(M) 486 -> TM = M 487 ; TM = system 488 ), 489 predicate_property(TM:G0, meta_predicate(Spec)), 490 !, 491 ( strip_goals(G0, Spec, G1), 492 simple_goal_in_body(G, M, G1) 493 ; arg(I, Spec, Meta), 494 arg(I, G0, G1), 495 extend(Meta, G1, G2), 496 goal_in_body(G, M, G2) 497 ). 498goal_in_body(G, M, G0) :- 499 simple_goal_in_body(G, M, G0). 500 501simple_goal_in_body(G, M, G0) :- 502 ( atom(M), 503 callable(G0), 504 predicate_property(M:G0, imported_from(M2)) 505 -> G = M2:G0 506 ; G = M:G0 507 ). 508 509control((A,B), [A,B]). 510control((A;B), [A,B]). 511control((A->B), [A,B]). 512control((A*->B), [A,B]). 513control((\+A), [A]). 514 515strip_goals(G0, Spec, G) :- 516 functor(G0, Name, Arity), 517 functor(G, Name, Arity), 518 strip_goal_args(1, G0, Spec, G). 519 520strip_goal_args(I, G0, Spec, G) :- 521 arg(I, G0, A0), 522 !, 523 arg(I, Spec, M), 524 ( extend(M, A0, _) 525 -> arg(I, G, '<meta-goal>') 526 ; arg(I, G, A0) 527 ), 528 I2 is I + 1, 529 strip_goal_args(I2, G0, Spec, G). 530strip_goal_args(_, _, _, _). 531 532extend(I, G0, G) :- 533 callable(G0), 534 integer(I), I>0, 535 !, 536 length(L, I), 537 extend_list(G0, L, G). 538extend(0, G, G). 539extend(^, G, G). 540 541extend_list(M:G0, L, M:G) :- 542 !, 543 callable(G0), 544 extend_list(G0, L, G). 545extend_list(G0, L, G) :- 546 G0 =.. List, 547 append(List, L, All), 548 G =.. All. 549 550 551message_context(ClauseRef, String, Clause, file_term_position(File, StringPos)) :- 552 clause_info(ClauseRef, File, TermPos, _Vars), 553 prolog_codewalk:subterm_pos(String, Clause, ==, TermPos, StringPos), 554 !. 555message_context(ClauseRef, _String, _Clause, file(File, Line, -1, _)) :- 556 clause_property(ClauseRef, file(File)), 557 clause_property(ClauseRef, line_count(Line)), 558 !. 559message_context(ClauseRef, _String, _Clause, clause(ClauseRef)). 560 561 562:- meta_predicate 563 predicate_indicator( , ). 564 565predicate_indicator(Module:Head, Module:Name/Arity) :- 566 functor(Head, Name, Arity). 567predicate_indicator(Module:Head, Module:Name//DCGArity) :- 568 functor(Head, Name, Arity), 569 DCGArity is Arity-2.
576string_predicate(_:'$pldoc'/4). 577string_predicate(pce_principal:send_implementation/3). 578string_predicate(pce_principal:pce_lazy_get_method/3). 579string_predicate(pce_principal:pce_lazy_send_method/3). 580string_predicate(pce_principal:pce_class/6). 581string_predicate(prolog_xref:pred_comment/4). 582string_predicate(prolog_xref:module_comment/3). 583string_predicate(pldoc_process:structured_comment//2). 584string_predicate(pldoc_process:structured_command_start/3). 585string_predicate(pldoc_process:separator_line//0). 586string_predicate(pldoc_register:mydoc/3). 587string_predicate(http_header:separators/1).
format("Hello world~n")
is considered proper use of
string constants.595% system predicates 596valid_string_goal(system:format(S)) :- string(S). 597valid_string_goal(system:format(S,_)) :- string(S). 598valid_string_goal(system:format(_,S,_)) :- string(S). 599valid_string_goal(system:string_codes(S,_)) :- string(S). 600valid_string_goal(system:string_code(_,S,_)) :- string(S). 601valid_string_goal(system:throw(msg(S,_))) :- string(S). 602valid_string_goal('$dcg':phrase(S,_,_)) :- string(S). 603valid_string_goal('$dcg':phrase(S,_)) :- string(S). 604valid_string_goal(system: is(_,_)). % arithmetic allows for "x" 605valid_string_goal(system: =:=(_,_)). 606valid_string_goal(system: >(_,_)). 607valid_string_goal(system: <(_,_)). 608valid_string_goal(system: >=(_,_)). 609valid_string_goal(system: =<(_,_)). 610% library stuff 611valid_string_goal(dcg_basics:string_without(S,_,_,_)) :- string(S). 612valid_string_goal(git:read_url(S,_,_)) :- string(S). 613valid_string_goal(tipc:tipc_subscribe(_,_,_,_,S)) :- string(S). 614valid_string_goal(charsio:format_to_chars(Format,_,_)) :- string(Format). 615valid_string_goal(charsio:format_to_chars(Format,_,_,_)) :- string(Format). 616valid_string_goal(codesio:format_to_codes(Format,_,_)) :- string(Format). 617valid_string_goal(codesio:format_to_codes(Format,_,_,_)) :- string(Format). 618 619 620 /******************************* 621 * EXTENSION HOOKS * 622 *******************************/
my_checks
module defines a predicate list_format_mistakes/0:
:- multifile check:checker/2. check:checker(my_checks:list_format_mistakes, "errors with format/2 arguments").
The predicate is dynamic, so you can disable checks with retract/1. For example, to stop reporting redefined predicates:
retract(check:checker(list_redefined,_)).
644checker(list_undefined, 'undefined predicates'). 645checker(list_trivial_fails, 'trivial failures'). 646checker(list_redefined, 'redefined system and global predicates'). 647checker(list_void_declarations, 'predicates with declarations but without clauses'). 648checker(list_autoload, 'predicates that need autoloading'). 649 650 651 /******************************* 652 * MESSAGES * 653 *******************************/ 654 655:- multifile 656 prolog:message/3. 657 658prologmessage(check(pass(Comment))) --> 659 [ 'Checking ~w ...'-[Comment] ]. 660prologmessage(check(find_references(Preds))) --> 661 { length(Preds, N) 662 }, 663 [ 'Scanning for references to ~D possibly undefined predicates'-[N] ]. 664prologmessage(check(undefined_procedures, Grouped)) --> 665 [ 'The predicates below are not defined. If these are defined', nl, 666 'at runtime using assert/1, use :- dynamic Name/Arity.', nl, nl 667 ], 668 undefined_procedures(Grouped). 669prologmessage(check(undefined_unreferenced_predicates)) --> 670 [ 'The predicates below are not defined, and are not', nl, 671 'referenced.', nl, nl 672 ]. 673prologmessage(check(undefined_unreferenced(Pred))) --> 674 predicate(Pred). 675prologmessage(check(autoload(Module, Pairs))) --> 676 { module_property(Module, file(Path)) 677 }, 678 !, 679 [ 'Into module ~w ('-[Module] ], 680 short_filename(Path), 681 [ ')', nl ], 682 autoload(Pairs). 683prologmessage(check(autoload(Module, Pairs))) --> 684 [ 'Into module ~w'-[Module], nl ], 685 autoload(Pairs). 686prologmessage(check(redefined(In, From, Pred))) --> 687 predicate(In:Pred), 688 redefined(In, From). 689prologmessage(check(trivial_failures)) --> 690 [ 'The following goals fail because there are no matching clauses.' ]. 691prologmessage(check(trivial_failure(Goal, Refs))) --> 692 { map_list_to_pairs(sort_reference_key, Refs, Keyed), 693 keysort(Keyed, KeySorted), 694 pairs_values(KeySorted, SortedRefs) 695 }, 696 goal(Goal), 697 [ ', which is called from'-[], nl ], 698 referenced_by(SortedRefs). 699prologmessage(check(string_in_clause(String, Context))) --> 700 prolog:message_location(Context), 701 [ 'String ~q'-[String] ]. 702prologmessage(check(void_declaration(P, Decl))) --> 703 predicate(P), 704 [ ' is declared as ~p, but has no clauses'-[Decl] ]. 705 706undefined_procedures([]) --> 707 []. 708undefined_procedures([H|T]) --> 709 undefined_procedure(H), 710 undefined_procedures(T). 711 712undefined_procedure(Pred-Refs) --> 713 { map_list_to_pairs(sort_reference_key, Refs, Keyed), 714 keysort(Keyed, KeySorted), 715 pairs_values(KeySorted, SortedRefs) 716 }, 717 predicate(Pred), 718 [ ', which is referenced by', nl ], 719 referenced_by(SortedRefs). 720 721redefined(user, system) --> 722 [ '~t~30| System predicate redefined globally' ]. 723redefined(_, system) --> 724 [ '~t~30| Redefined system predicate' ]. 725redefined(_, user) --> 726 [ '~t~30| Redefined global predicate' ]. 727 728goal(user:Goal) --> 729 !, 730 [ '~p'-[Goal] ]. 731goal(Goal) --> 732 !, 733 [ '~p'-[Goal] ]. 734 735predicate(Module:Name/Arity) --> 736 { atom(Module), 737 atom(Name), 738 integer(Arity), 739 functor(Head, Name, Arity), 740 predicate_name(Module:Head, PName) 741 }, 742 !, 743 [ '~w'-[PName] ]. 744predicate(Module:Head) --> 745 { atom(Module), 746 callable(Head), 747 predicate_name(Module:Head, PName) 748 }, 749 !, 750 [ '~w'-[PName] ]. 751predicate(Name/Arity) --> 752 { atom(Name), 753 integer(Arity) 754 }, 755 !, 756 predicate(user:Name/Arity). 757 758autoload([]) --> 759 []. 760autoload([Lib-Pred|T]) --> 761 [ ' ' ], 762 predicate(Pred), 763 [ '~t~24| from ' ], 764 short_filename(Lib), 765 [ nl ], 766 autoload(T).
772sort_reference_key(Term, key(M:Name/Arity, N, ClausePos)) :- 773 clause_ref(Term, ClauseRef, ClausePos), 774 !, 775 nth_clause(Pred, N, ClauseRef), 776 strip_module(Pred, M, Head), 777 functor(Head, Name, Arity). 778sort_reference_key(Term, Term). 779 780clause_ref(clause_term_position(ClauseRef, TermPos), ClauseRef, ClausePos) :- 781 arg(1, TermPos, ClausePos). 782clause_ref(clause(ClauseRef), ClauseRef, 0). 783 784 785referenced_by([]) --> 786 []. 787referenced_by([Ref|T]) --> 788 ['\t'], prolog:message_location(Ref), 789 predicate_indicator(Ref), 790 [ nl ], 791 referenced_by(T). 792 793predicate_indicator(clause_term_position(ClauseRef, _)) --> 794 { nonvar(ClauseRef) }, 795 !, 796 predicate_indicator(clause(ClauseRef)). 797predicate_indicator(clause(ClauseRef)) --> 798 { clause_name(ClauseRef, Name) }, 799 [ '~w'-[Name] ]. 800predicate_indicator(file_term_position(_,_)) --> 801 [ '(initialization)' ]. 802predicate_indicator(file(_,_,_,_)) --> 803 [ '(initialization)' ]. 804 805 806short_filename(Path) --> 807 { short_filename(Path, Spec) 808 }, 809 [ '~q'-[Spec] ]. 810 811short_filename(Path, Spec) :- 812 absolute_file_name('', Here), 813 atom_concat(Here, Local0, Path), 814 !, 815 remove_leading_slash(Local0, Spec). 816short_filename(Path, Spec) :- 817 findall(LenAlias, aliased_path(Path, LenAlias), Keyed), 818 keysort(Keyed, [_-Spec|_]). 819short_filename(Path, Path). 820 821aliased_path(Path, Len-Spec) :- 822 setof(Alias, Spec^(user:file_search_path(Alias, Spec)), Aliases), 823 member(Alias, Aliases), 824 Term =.. [Alias, '.'], 825 absolute_file_name(Term, 826 [ file_type(directory), 827 file_errors(fail), 828 solutions(all) 829 ], Prefix), 830 atom_concat(Prefix, Local0, Path), 831 remove_leading_slash(Local0, Local), 832 atom_length(Local, Len), 833 Spec =.. [Alias, Local]. 834 835remove_leading_slash(Path, Local) :- 836 atom_concat(/, Local, Path), 837 !. 838remove_leading_slash(Path, Path)
Consistency checking
This library provides some consistency checks for the loaded Prolog program. The predicate make/0 runs list_undefined/0 to find undefined predicates in `user' modules.
library(prolog_xref)
implements `offline' cross-referencinglibrary(prolog_codewalk)
implements `online' analysis */