View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org/projects/xpce/
    6    Copyright (c)  2006-2025, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9                              SWI-Prolog Solutions b.v.
   10    All rights reserved.
   11
   12    Redistribution and use in source and binary forms, with or without
   13    modification, are permitted provided that the following conditions
   14    are met:
   15
   16    1. Redistributions of source code must retain the above copyright
   17       notice, this list of conditions and the following disclaimer.
   18
   19    2. Redistributions in binary form must reproduce the above copyright
   20       notice, this list of conditions and the following disclaimer in
   21       the documentation and/or other materials provided with the
   22       distribution.
   23
   24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   25    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   26    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   27    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   28    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   29    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   30    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   31    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   32    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   34    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35    POSSIBILITY OF SUCH DAMAGE.
   36*/
   37
   38:- module(prolog_xref,
   39          [ xref_source/1,              % +Source
   40            xref_source/2,              % +Source, +Options
   41            xref_called/3,              % ?Source, ?Callable, ?By
   42            xref_called/4,              % ?Source, ?Callable, ?By, ?Cond
   43            xref_called/5,              % ?Source, ?Callable, ?By, ?Cond, ?Line
   44            xref_defined/3,             % ?Source. ?Callable, -How
   45            xref_definition_line/2,     % +How, -Line
   46            xref_exported/2,            % ?Source, ?Callable
   47            xref_module/2,              % ?Source, ?Module
   48            xref_uses_file/3,           % ?Source, ?Spec, ?Path
   49            xref_op/2,                  % ?Source, ?Op
   50            xref_prolog_flag/4,         % ?Source, ?Flag, ?Value, ?Line
   51            xref_comment/3,             % ?Source, ?Title, ?Comment
   52            xref_comment/4,             % ?Source, ?Head, ?Summary, ?Comment
   53            xref_mode/3,                % ?Source, ?Mode, ?Det
   54            xref_option/2,              % ?Source, ?Option
   55            xref_clean/1,               % +Source
   56            xref_current_source/1,      % ?Source
   57            xref_done/2,                % +Source, -When
   58            xref_built_in/1,            % ?Callable
   59            xref_source_file/3,         % +Spec, -Path, +Source
   60            xref_source_file/4,         % +Spec, -Path, +Source, +Options
   61            xref_public_list/3,         % +File, +Src, +Options
   62            xref_public_list/4,         % +File, -Path, -Export, +Src
   63            xref_public_list/6,         % +File, -Path, -Module, -Export, -Meta, +Src
   64            xref_public_list/7,         % +File, -Path, -Module, -Export, -Public, -Meta, +Src
   65            xref_meta/3,                % +Source, +Goal, -Called
   66            xref_meta/2,                % +Goal, -Called
   67            xref_hook/1,                % ?Callable
   68                                        % XPCE class references
   69            xref_used_class/2,          % ?Source, ?ClassName
   70            xref_defined_class/3        % ?Source, ?ClassName, -How
   71          ]).   72:- autoload(library(apply),[maplist/2,partition/4,maplist/3]).   73:- use_module(library(debug),[debug/3]).   74:- autoload(library(dialect),[expects_dialect/1]).   75:- autoload(library(error),[must_be/2,instantiation_error/1]).   76:- autoload(library(lists),[member/2,append/2,append/3,select/3]).   77:- autoload(library(operators),[push_op/3]).   78:- autoload(library(option),[option/2,option/3]).   79:- autoload(library(ordsets),[ord_intersect/2,ord_intersection/3]).   80:- autoload(library(prolog_code), [pi_head/2]).   81:- autoload(library(prolog_source),
   82	    [ prolog_canonical_source/2,
   83	      prolog_open_source/2,
   84	      prolog_close_source/1,
   85	      prolog_read_source_term/4,
   86              prolog_file_directives/3
   87	    ]).   88
   89:- if(exists_source(library(shlib))).   90:- autoload(library(shlib),[current_foreign_library/2]).   91:- endif.   92:- autoload(library(solution_sequences),[distinct/2,limit/2]).   93
   94:- if(exists_source(library(pldoc))).   95:- use_module(library(pldoc), []).      % Must be loaded before doc_process
   96:- use_module(library(pldoc/doc_process)).   97
   98:- endif.   99
  100:- predicate_options(xref_source/2, 2,
  101                     [ silent(boolean),
  102                       module(atom),
  103                       register_called(oneof([all,non_iso,non_built_in])),
  104                       comments(oneof([store,collect,ignore])),
  105                       process_include(boolean),
  106                       stream(stream)
  107                     ]).  108
  109
  110:- dynamic
  111    called/5,                       % Head, Src, From, Cond, Line
  112    (dynamic)/3,                    % Head, Src, Line
  113    (thread_local)/3,               % Head, Src, Line
  114    (multifile)/3,                  % Head, Src, Line
  115    (public)/3,                     % Head, Src, Line
  116    (declared)/4,	            % Head, How, Src, Line
  117    defined/3,                      % Head, Src, Line
  118    meta_goal/3,                    % Head, Called, Src
  119    foreign/3,                      % Head, Src, Line
  120    constraint/3,                   % Head, Src, Line
  121    imported/3,                     % Head, Src, From
  122    exported/2,                     % Head, Src
  123    xmodule/2,                      % Module, Src
  124    uses_file/3,                    % Spec, Src, Path
  125    xop/2,                          % Src, Op
  126    source/2,                       % Src, Time
  127    used_class/2,                   % Name, Src
  128    defined_class/5,                % Name, Super, Summary, Src, Line
  129    (mode)/2,                       % Mode, Src
  130    xoption/2,                      % Src, Option
  131    xflag/4,                        % Name, Value, Src, Line
  132    grammar_rule/2,                 % Head, Src
  133    module_comment/3,               % Src, Title, Comment
  134    pred_comment/4,                 % Head, Src, Summary, Comment
  135    pred_comment_link/3,            % Head, Src, HeadTo
  136    pred_mode/3.                    % Head, Src, Det
  137
  138:- create_prolog_flag(xref, false, [type(boolean)]).

Prolog cross-referencer data collection

This library collects information on defined and used objects in Prolog source files. Typically these are predicates, but we expect the library to deal with other types of objects in the future. The library is a building block for tools doing dependency tracking in applications. Dependency tracking is useful to reveal the structure of an unknown program or detect missing components at compile time, but also for program transformation or minimising a program saved state by only saving the reachable objects.

The library is exploited by two graphical tools in the SWI-Prolog environment: the XPCE front-end started by gxref/0, and library(prolog_colour), which exploits this library for its syntax highlighting.

For all predicates described below, Source is the source that is processed. This is normally a filename in any notation acceptable to the file loading predicates (see load_files/2). Input handling is done by the library(prolog_source), which may be hooked to process any source that can be translated into a Prolog stream holding Prolog source text. Callable is a callable term (see callable/1). Callables do not carry a module qualifier unless the referred predicate is not in the module defined by Source.

See also
- Where this library analyses source text, library(prolog_codewalk) may be used to analyse loaded code. The library(check) exploits library(prolog_codewalk) to report on e.g., undefined predicates.
bug
- meta_predicate/1 declarations take the module into consideration. Predicates that are both available as meta-predicate and normal (in different modules) are handled as meta-predicate in all places.
  175:- predicate_options(xref_source_file/4, 4,
  176                     [ file_type(oneof([txt,prolog,directory])),
  177                       silent(boolean)
  178                     ]).  179:- predicate_options(xref_public_list/3, 3,
  180                     [ path(-atom),
  181                       module(-atom),
  182                       exports(-list(any)),
  183                       public(-list(any)),
  184                       meta(-list(any)),
  185                       silent(boolean)
  186                     ]).  187
  188
  189                 /*******************************
  190                 *            HOOKS             *
  191                 *******************************/
 prolog:called_by(+Goal, +Module, +Context, -Called) is semidet
True when Called is a list of callable terms called from Goal, handled by the predicate Module:Goal and executed in the context of the module Context. Elements of Called may be qualified. If not, they are called in the context of the module Context.
 prolog:called_by(+Goal, -ListOfCalled)
If this succeeds, the cross-referencer assumes Goal may call any of the goals in ListOfCalled. If this call fails, default meta-goal analysis is used to determine additional called goals.
deprecated
- New code should use prolog:called_by/4
 prolog:meta_goal(+Goal, -Pattern)
Define meta-predicates. See the examples in this file for details.
 prolog:hook(Goal)
True if Goal is a hook that is called spontaneously (e.g., from foreign code).
  218:- multifile
  219    prolog:called_by/4,             % +Goal, +Module, +Context, -Called
  220    prolog:called_by/2,             % +Goal, -Called
  221    prolog:meta_goal/2,             % +Goal, -Pattern
  222    prolog:hook/1,                  % +Callable
  223    prolog:generated_predicate/1,   % :PI
  224    prolog:no_autoload_module/1,    % Module is not suitable for autoloading.
  225    prolog:xref_source_time/2.      % +Source, =Modified
  226
  227:- meta_predicate
  228    prolog:generated_predicate(:).  229
  230:- meta_predicate
  231    process_predicates(2, +, +).  232
  233                 /*******************************
  234                 *           BUILT-INS          *
  235                 *******************************/
 hide_called(:Callable, +Src) is semidet
True when the cross-referencer should not include Callable as being called. This is determined by the option register_called.
  243hide_called(Callable, Src) :-
  244    xoption(Src, register_called(Which)),
  245    !,
  246    mode_hide_called(Which, Callable).
  247hide_called(Callable, _) :-
  248    mode_hide_called(non_built_in, Callable).
  249
  250mode_hide_called(all, _) :- !, fail.
  251mode_hide_called(non_iso, _:Goal) :-
  252    goal_name_arity(Goal, Name, Arity),
  253    current_predicate(system:Name/Arity),
  254    predicate_property(system:Goal, iso).
  255mode_hide_called(non_built_in, _:Goal) :-
  256    goal_name_arity(Goal, Name, Arity),
  257    current_predicate(system:Name/Arity),
  258    predicate_property(system:Goal, built_in).
  259mode_hide_called(non_built_in, M:Goal) :-
  260    goal_name_arity(Goal, Name, Arity),
  261    current_predicate(M:Name/Arity),
  262    predicate_property(M:Goal, built_in).
 built_in_predicate(+Callable)
True if Callable is a built-in
  268system_predicate(Goal) :-
  269    goal_name_arity(Goal, Name, Arity),
  270    current_predicate(system:Name/Arity),   % avoid autoloading
  271    predicate_property(system:Goal, built_in),
  272    !.
  273
  274
  275                /********************************
  276                *            TOPLEVEL           *
  277                ********************************/
  278
  279verbose(Src) :-
  280    \+ xoption(Src, silent(true)).
  281
  282:- thread_local
  283    xref_input/2.                   % File, Stream
 xref_source(+Source) is det
 xref_source(+Source, +Options) is det
Generate the cross-reference data for Source if not already done and the source is not modified. Checking for modifications is only done for files. Options processed:
silent(+Boolean)
If true (default false), emit warning messages.
module(+Module)
Define the initial context module to work in.
register_called(+Which)
Determines which calls are registerd. Which is one of all, non_iso or non_built_in (default).
comments(+CommentHandling)
How to handle comments. If store, comments are stored into the database as if the file was compiled. If collect, comments are entered to the xref database and made available through xref_mode/2 and xref_comment/4. If ignore, comments are simply ignored. Default is to collect comments.
process_include(+Boolean)
Process the content of included files (default is true).
stream(+Stream)
Process the input from Stream rather than opening Source.
Arguments:
Source- File specification or XPCE buffer
  313xref_source(Source) :-
  314    xref_source(Source, []).
  315
  316xref_source(Source, Options) :-
  317    prolog_canonical_source(Source, Src),
  318    (   last_modified(Source, Modified)
  319    ->  (   source(Src, Modified)
  320        ->  true
  321        ;   xref_clean(Src),
  322            assert(source(Src, Modified)),
  323            do_xref(Src, Options)
  324        )
  325    ;   xref_clean(Src),
  326        get_time(Now),
  327        assert(source(Src, Now)),
  328        do_xref(Src, Options)
  329    ).
  330
  331do_xref(Src, Options) :-
  332    must_be(list, Options),
  333    setup_call_cleanup(
  334        xref_setup(Src, In, Options, State),
  335        collect(Src, Src, In, Options),
  336        xref_cleanup(State)).
  337
  338last_modified(Source, Modified) :-
  339    prolog:xref_source_time(Source, Modified),
  340    !.
  341last_modified(Source, Modified) :-
  342    atom(Source),
  343    \+ is_global_url(Source),
  344    exists_file(Source),
  345    time_file(Source, Modified).
  346
  347is_global_url(File) :-
  348    sub_atom(File, B, _, _, '://'),
  349    !,
  350    B > 1,
  351    sub_atom(File, 0, B, _, Scheme),
  352    atom_codes(Scheme, Codes),
  353    maplist(between(0'a, 0'z), Codes).
  354
  355xref_setup(Src, In, Options, state(CleanIn, Dialect, Xref, [SRef|HRefs])) :-
  356    maplist(assert_option(Src), Options),
  357    assert_default_options(Src),
  358    current_prolog_flag(emulated_dialect, Dialect),
  359    (   option(stream(Stream), Options)
  360    ->  In = Stream,
  361        CleanIn = true
  362    ;   prolog_open_source(Src, In),
  363        CleanIn = prolog_close_source(In)
  364    ),
  365    set_initial_mode(In, Options),
  366    asserta(xref_input(Src, In), SRef),
  367    set_xref(Xref),
  368    (   verbose(Src)
  369    ->  HRefs = []
  370    ;   asserta((user:thread_message_hook(_,Level,_) :-
  371                     hide_message(Level)),
  372                Ref),
  373        HRefs = [Ref]
  374    ).
  375
  376hide_message(warning).
  377hide_message(error).
  378hide_message(informational).
  379
  380assert_option(_, Var) :-
  381    var(Var),
  382    !,
  383    instantiation_error(Var).
  384assert_option(Src, silent(Boolean)) :-
  385    !,
  386    must_be(boolean, Boolean),
  387    assert(xoption(Src, silent(Boolean))).
  388assert_option(Src, register_called(Which)) :-
  389    !,
  390    must_be(oneof([all,non_iso,non_built_in]), Which),
  391    assert(xoption(Src, register_called(Which))).
  392assert_option(Src, comments(CommentHandling)) :-
  393    !,
  394    must_be(oneof([store,collect,ignore]), CommentHandling),
  395    assert(xoption(Src, comments(CommentHandling))).
  396assert_option(Src, module(Module)) :-
  397    !,
  398    must_be(atom, Module),
  399    assert(xoption(Src, module(Module))).
  400assert_option(Src, process_include(Boolean)) :-
  401    !,
  402    must_be(boolean, Boolean),
  403    assert(xoption(Src, process_include(Boolean))).
  404assert_option(_, _).
  405
  406assert_default_options(Src) :-
  407    (   xref_option_default(Opt),
  408        generalise_term(Opt, Gen),
  409        (   xoption(Src, Gen)
  410        ->  true
  411        ;   assertz(xoption(Src, Opt))
  412        ),
  413        fail
  414    ;   true
  415    ).
  416
  417xref_option_default(silent(false)).
  418xref_option_default(register_called(non_built_in)).
  419xref_option_default(comments(collect)).
  420xref_option_default(process_include(true)).
 xref_cleanup(+State) is det
Restore processing state according to the saved State.
  426xref_cleanup(state(CleanIn, Dialect, Xref, Refs)) :-
  427    call(CleanIn),
  428    set_prolog_flag(emulated_dialect, Dialect),
  429    set_prolog_flag(xref, Xref),
  430    maplist(erase, Refs).
  431
  432set_xref(Xref) :-
  433    current_prolog_flag(xref, Xref),
  434    set_prolog_flag(xref, true).
  435
  436:- meta_predicate
  437    with_xref(0).  438
  439with_xref(Goal) :-
  440    setup_call_cleanup(
  441        push_prolog_flag(xref, true),
  442        Goal,
  443        pop_prolog_flag(xref)).
 set_initial_mode(+Stream, +Options) is det
Set the initial mode for processing this file in the cross-referencer. If the file is loaded, we use information from the previous load context, setting the appropriate module and dialect.
  453set_initial_mode(_Stream, Options) :-
  454    option(module(Module), Options),
  455    !,
  456    '$set_source_module'(Module).
  457set_initial_mode(Stream, _) :-
  458    stream_property(Stream, file_name(Path)),
  459    source_file_property(Path, load_context(M, _, Opts)),
  460    !,
  461    '$set_source_module'(M),
  462    (   option(dialect(Dialect), Opts)
  463    ->  expects_dialect(Dialect)
  464    ;   true
  465    ).
  466set_initial_mode(_, _) :-
  467    '$set_source_module'(user).
 xref_input_stream(-Stream) is det
Current input stream for cross-referencer.
  473xref_input_stream(Stream) :-
  474    xref_input(_, Var),
  475    !,
  476    Stream = Var.
 xref_push_op(Source, +Prec, +Type, :Name)
Define operators into the default source module and register them to be undone by pop_operators/0.
  483xref_push_op(Src, P, T, N0) :-
  484    '$current_source_module'(M0),
  485    strip_module(M0:N0, M, N),
  486    (   is_list(N),
  487        N \== []
  488    ->  maplist(push_op(Src, P, T, M), N)
  489    ;   push_op(Src, P, T, M, N)
  490    ).
  491
  492push_op(Src, P, T, M0, N0) :-
  493    strip_module(M0:N0, M, N),
  494    Name = M:N,
  495    valid_op(op(P,T,Name)),
  496    push_op(P, T, Name),
  497    assert_op(Src, op(P,T,Name)),
  498    debug(xref(op), ':- ~w.', [op(P,T,Name)]).
  499
  500valid_op(op(P,T,M:N)) :-
  501    atom(M),
  502    valid_op_name(N),
  503    integer(P),
  504    between(0, 1200, P),
  505    atom(T),
  506    op_type(T).
  507
  508valid_op_name(N) :-
  509    atom(N),
  510    !.
  511valid_op_name(N) :-
  512    N == [].
  513
  514op_type(xf).
  515op_type(yf).
  516op_type(fx).
  517op_type(fy).
  518op_type(xfx).
  519op_type(xfy).
  520op_type(yfx).
 xref_set_prolog_flag(+Flag, +Value, +Src, +Line)
Called when a directive sets a Prolog flag.
  526xref_set_prolog_flag(Flag, Value, Src, Line) :-
  527    atom(Flag),
  528    !,
  529    assertz(xflag(Flag, Value, Src, Line)).
  530xref_set_prolog_flag(_, _, _, _).
 xref_clean(+Source) is det
Reset the database for the given source.
  536xref_clean(Source) :-
  537    prolog_canonical_source(Source, Src),
  538    retractall(called(_, Src, _Origin, _Cond, _Line)),
  539    retractall(dynamic(_, Src, Line)),
  540    retractall(multifile(_, Src, Line)),
  541    retractall(public(_, Src, Line)),
  542    retractall(declared(_, _, Src, Line)),
  543    retractall(defined(_, Src, Line)),
  544    retractall(meta_goal(_, _, Src)),
  545    retractall(foreign(_, Src, Line)),
  546    retractall(constraint(_, Src, Line)),
  547    retractall(imported(_, Src, _From)),
  548    retractall(exported(_, Src)),
  549    retractall(uses_file(_, Src, _)),
  550    retractall(xmodule(_, Src)),
  551    retractall(xop(Src, _)),
  552    retractall(grammar_rule(_, Src)),
  553    retractall(xoption(Src, _)),
  554    retractall(xflag(_Name, _Value, Src, Line)),
  555    retractall(source(Src, _)),
  556    retractall(used_class(_, Src)),
  557    retractall(defined_class(_, _, _, Src, _)),
  558    retractall(mode(_, Src)),
  559    retractall(module_comment(Src, _, _)),
  560    retractall(pred_comment(_, Src, _, _)),
  561    retractall(pred_comment_link(_, Src, _)),
  562    retractall(pred_mode(_, Src, _)).
  563
  564
  565                 /*******************************
  566                 *          READ RESULTS        *
  567                 *******************************/
 xref_current_source(?Source)
Check what sources have been analysed.
  573xref_current_source(Source) :-
  574    source(Source, _Time).
 xref_done(+Source, -Time) is det
Cross-reference executed at Time
  581xref_done(Source, Time) :-
  582    prolog_canonical_source(Source, Src),
  583    source(Src, Time).
 xref_called(?Source, ?Called, ?By) is nondet
 xref_called(?Source, ?Called, ?By, ?Cond) is nondet
 xref_called(?Source, ?Called, ?By, ?Cond, ?Line) is nondet
True when By is called from Called in Source. Note that xref_called/3 and xref_called/4 use distinct/2 to return only distinct Called-By pairs. The xref_called/5 version may return duplicate Called-By if Called is called from multiple clauses in By, but at most one call per clause.
Arguments:
By- is a head term or one of the reserved terms '<directive>'(Line) or '<public>'(Line), indicating the call is from an (often initialization/1) directive or there is a public/1 directive that claims the predicate is called from in some untractable way.
Cond- is the (accumulated) condition as defined by :- if(Cond) under which the calling code is compiled.
Line- is the start line of the calling clause.
  605xref_called(Source, Called, By) :-
  606    xref_called(Source, Called, By, _).
  607
  608xref_called(Source, Called, By, Cond) :-
  609    canonical_source(Source, Src),
  610    distinct(Called-By, called(Called, Src, By, Cond, _)).
  611
  612xref_called(Source, Called, By, Cond, Line) :-
  613    canonical_source(Source, Src),
  614    called(Called, Src, By, Cond, Line).
 xref_defined(?Source, +Goal, ?How) is nondet
Test if Goal is accessible in Source. If this is the case, How specifies the reason why the predicate is accessible. Note that this predicate does not deal with built-in or global predicates, just locally defined and imported ones. How is one of of the terms below. Location is one of Line (an integer) or File:Line if the definition comes from an included (using :- include(File)) directive.
  636xref_defined(Source, Called, How) :-
  637    nonvar(Source),
  638    !,
  639    canonical_source(Source, Src),
  640    xref_defined2(How, Src, Called).
  641xref_defined(Source, Called, How) :-
  642    xref_defined2(How, Src, Called),
  643    canonical_source(Source, Src).
  644
  645xref_defined2(dynamic(Line), Src, Called) :-
  646    dynamic(Called, Src, Line).
  647xref_defined2(thread_local(Line), Src, Called) :-
  648    thread_local(Called, Src, Line).
  649xref_defined2(multifile(Line), Src, Called) :-
  650    multifile(Called, Src, Line).
  651xref_defined2(public(Line), Src, Called) :-
  652    public(Called, Src, Line).
  653xref_defined2(local(Line), Src, Called) :-
  654    defined(Called, Src, Line).
  655xref_defined2(foreign(Line), Src, Called) :-
  656    foreign(Called, Src, Line).
  657xref_defined2(constraint(Line), Src, Called) :-
  658    (   constraint(Called, Src, Line)
  659    ->  true
  660    ;   declared(Called, chr_constraint, Src, Line)
  661    ).
  662xref_defined2(imported(From), Src, Called) :-
  663    imported(Called, Src, From).
  664xref_defined2(dcg, Src, Called) :-
  665    grammar_rule(Called, Src).
 xref_definition_line(+How, -Line)
If the 3th argument of xref_defined contains line info, return this in Line.
  673xref_definition_line(local(Line),        Line).
  674xref_definition_line(dynamic(Line),      Line).
  675xref_definition_line(thread_local(Line), Line).
  676xref_definition_line(multifile(Line),    Line).
  677xref_definition_line(public(Line),       Line).
  678xref_definition_line(constraint(Line),   Line).
  679xref_definition_line(foreign(Line),      Line).
 xref_exported(?Source, ?Head) is nondet
True when Source exports Head.
  686xref_exported(Source, Called) :-
  687    prolog_canonical_source(Source, Src),
  688    exported(Called, Src).
 xref_module(?Source, ?Module) is nondet
True if Module is defined in Source.
  694xref_module(Source, Module) :-
  695    nonvar(Source),
  696    !,
  697    prolog_canonical_source(Source, Src),
  698    xmodule(Module, Src).
  699xref_module(Source, Module) :-
  700    xmodule(Module, Src),
  701    prolog_canonical_source(Source, Src).
 xref_uses_file(?Source, ?Spec, ?Path) is nondet
True when Source tries to load a file using Spec.
Arguments:
Spec- is a specification for absolute_file_name/3
Path- is either an absolute file name of the target file or the atom <not_found>.
  711xref_uses_file(Source, Spec, Path) :-
  712    prolog_canonical_source(Source, Src),
  713    uses_file(Spec, Src, Path).
 xref_op(?Source, Op) is nondet
Give the operators active inside the module. This is intended to setup the environment for incremental parsing of a term from the source-file.
Arguments:
Op- Term of the form op(Priority, Type, Name)
  723xref_op(Source, Op) :-
  724    prolog_canonical_source(Source, Src),
  725    xop(Src, Op).
 xref_prolog_flag(?Source, ?Flag, ?Value, ?Line) is nondet
True when Flag is set to Value at Line in Source. This is intended to support incremental parsing of a term from the source-file.
  733xref_prolog_flag(Source, Flag, Value, Line) :-
  734    prolog_canonical_source(Source, Src),
  735    xflag(Flag, Value, Src, Line).
  736
  737xref_built_in(Head) :-
  738    system_predicate(Head).
  739
  740xref_used_class(Source, Class) :-
  741    prolog_canonical_source(Source, Src),
  742    used_class(Class, Src).
  743
  744xref_defined_class(Source, Class, local(Line, Super, Summary)) :-
  745    prolog_canonical_source(Source, Src),
  746    defined_class(Class, Super, Summary, Src, Line),
  747    integer(Line),
  748    !.
  749xref_defined_class(Source, Class, file(File)) :-
  750    prolog_canonical_source(Source, Src),
  751    defined_class(Class, _, _, Src, file(File)).
  752
  753:- thread_local
  754    current_cond/1,
  755    source_line/1,
  756    current_test_unit/2.  757
  758current_source_line(Line) :-
  759    source_line(Var),
  760    !,
  761    Line = Var.
 collect(+Source, +File, +Stream, +Options)
Process data from Source. If File \== Source, we are processing an included file. Stream is the stream from which we read the program.
  769collect(Src, File, In, Options) :-
  770    (   Src == File
  771    ->  SrcSpec = Line
  772    ;   SrcSpec = (File:Line)
  773    ),
  774    (   current_prolog_flag(xref_store_comments, OldStore)
  775    ->  true
  776    ;   OldStore = false
  777    ),
  778    option(comments(CommentHandling), Options, collect),
  779    (   CommentHandling == ignore
  780    ->  CommentOptions = [],
  781        Comments = []
  782    ;   CommentHandling == store
  783    ->  CommentOptions = [ process_comment(true) ],
  784        Comments = [],
  785	set_prolog_flag(xref_store_comments, true)
  786    ;   CommentOptions = [ comments(Comments) ]
  787    ),
  788    repeat,
  789        E = error(_,_),
  790        catch(prolog_read_source_term(
  791                  In, Term, Expanded,
  792                  [ term_position(TermPos)
  793                  | CommentOptions
  794                  ]),
  795              E, report_syntax_error(E, Src, [])),
  796        update_condition(Term),
  797        stream_position_data(line_count, TermPos, Line),
  798        setup_call_cleanup(
  799            asserta(source_line(SrcSpec), Ref),
  800            catch(process(Expanded, Comments, Term, TermPos, Src, EOF),
  801                  E, print_message(error, E)),
  802            erase(Ref)),
  803        EOF == true,
  804    !,
  805    set_prolog_flag(xref_store_comments, OldStore).
  806
  807report_syntax_error(_, _, Options) :-
  808    option(silent(true), Options),
  809    !,
  810    fail.
  811report_syntax_error(E, Src, _Options) :-
  812    (   verbose(Src)
  813    ->  print_message(error, E)
  814    ;   true
  815    ),
  816    fail.
 update_condition(+Term) is det
Update the condition under which the current code is compiled.
  822update_condition((:-Directive)) :-
  823    !,
  824    update_cond(Directive).
  825update_condition(_).
  826
  827update_cond(if(Cond)) :-
  828    !,
  829    asserta(current_cond(Cond)).
  830update_cond(else) :-
  831    retract(current_cond(C0)),
  832    !,
  833    assert(current_cond(\+C0)).
  834update_cond(elif(Cond)) :-
  835    retract(current_cond(C0)),
  836    !,
  837    assert(current_cond((\+C0,Cond))).
  838update_cond(endif) :-
  839    retract(current_cond(_)),
  840    !.
  841update_cond(_).
 current_condition(-Condition) is det
Condition is the current compilation condition as defined by the :- if/1 directive and friends.
  848current_condition(Condition) :-
  849    \+ current_cond(_),
  850    !,
  851    Condition = true.
  852current_condition(Condition) :-
  853    findall(C, current_cond(C), List),
  854    list_to_conj(List, Condition).
  855
  856list_to_conj([], true).
  857list_to_conj([C], C) :- !.
  858list_to_conj([H|T], (H,C)) :-
  859    list_to_conj(T, C).
  860
  861
  862                 /*******************************
  863                 *           PROCESS            *
  864                 *******************************/
 process(+Expanded, +Comments, +Term, +TermPos, +Src, -EOF) is det
Process a source term that has been subject to term expansion as well as its optional leading structured comments.
Arguments:
TermPos- is the term position that describes the start of the term. We need this to find leading comments.
EOF- is unified with a boolean to indicate whether or not processing was stopped because end_of_file was processed.
  876process(Expanded, Comments, Term0, TermPos, Src, EOF) :-
  877    is_list(Expanded),                          % term_expansion into list.
  878    !,
  879    (   member(Term, Expanded),
  880        process(Term, Term0, Src),
  881        Term == end_of_file
  882    ->  EOF = true
  883    ;   EOF = false
  884    ),
  885    xref_comments(Comments, TermPos, Src).
  886process(end_of_file, _, _, _, _, true) :-
  887    !.
  888process(Term, Comments, Term0, TermPos, Src, false) :-
  889    process(Term, Term0, Src),
  890    xref_comments(Comments, TermPos, Src).
 process(+Term, +Term0, +Src) is det
  894process(_, Term0, _) :-
  895    ignore_raw_term(Term0),
  896    !.
  897process(Head :- Body, Head0 --> _, Src) :-
  898    pi_head(F/A, Head),
  899    pi_head(F/A0, Head0),
  900    A =:= A0 + 2,
  901    !,
  902    assert_grammar_rule(Src, Head),
  903    process((Head :- Body), Src).
  904process(Term, _Term0, Src) :-
  905    process(Term, Src).
  906
  907ignore_raw_term((:- predicate_options(_,_,_))).
 process(+Term, +Src) is det
  911process(Var, _) :-
  912    var(Var),
  913    !.                    % Warn?
  914process(end_of_file, _) :- !.
  915process((:- Directive), Src) :-
  916    !,
  917    process_directive(Directive, Src),
  918    !.
  919process((?- Directive), Src) :-
  920    !,
  921    process_directive(Directive, Src),
  922    !.
  923process((Head :- Body), Src) :-
  924    !,
  925    assert_defined(Src, Head),
  926    process_body(Body, Head, Src).
  927process((Left => Body), Src) :-
  928    !,
  929    (   nonvar(Left),
  930        Left = (Head, Guard)
  931    ->  assert_defined(Src, Head),
  932        process_body(Guard, Head, Src),
  933        process_body(Body, Head, Src)
  934    ;   assert_defined(Src, Left),
  935        process_body(Body, Left, Src)
  936    ).
  937process(?=>(Head, Body), Src) :-
  938    !,
  939    assert_defined(Src, Head),
  940    process_body(Body, Head, Src).
  941process('$source_location'(_File, _Line):Clause, Src) :-
  942    !,
  943    process(Clause, Src).
  944process(Term, Src) :-
  945    process_chr(Term, Src),
  946    !.
  947process(M:(Head :- Body), Src) :-
  948    !,
  949    process((M:Head :- M:Body), Src).
  950process(Head, Src) :-
  951    assert_defined(Src, Head).
  952
  953
  954                 /*******************************
  955                 *            COMMENTS          *
  956                 *******************************/
 xref_comments(+Comments, +FilePos, +Src) is det
  960xref_comments([], _Pos, _Src).
  961:- if(current_predicate(parse_comment/3)).  962xref_comments([Pos-Comment|T], TermPos, Src) :-
  963    (   Pos @> TermPos              % comments inside term
  964    ->  true
  965    ;   stream_position_data(line_count, Pos, Line),
  966        FilePos = Src:Line,
  967        (   parse_comment(Comment, FilePos, Parsed)
  968        ->  assert_comments(Parsed, Src)
  969        ;   true
  970        ),
  971        xref_comments(T, TermPos, Src)
  972    ).
  973
  974assert_comments([], _).
  975assert_comments([H|T], Src) :-
  976    assert_comment(H, Src),
  977    assert_comments(T, Src).
  978
  979assert_comment(section(_Id, Title, Comment), Src) :-
  980    assertz(module_comment(Src, Title, Comment)).
  981assert_comment(predicate(PI, Summary, Comment), Src) :-
  982    pi_to_head(PI, Src, Head),
  983    assertz(pred_comment(Head, Src, Summary, Comment)).
  984assert_comment(link(PI, PITo), Src) :-
  985    pi_to_head(PI, Src, Head),
  986    pi_to_head(PITo, Src, HeadTo),
  987    assertz(pred_comment_link(Head, Src, HeadTo)).
  988assert_comment(mode(Head, Det), Src) :-
  989    assertz(pred_mode(Head, Src, Det)).
  990
  991pi_to_head(PI, Src, Head) :-
  992    pi_to_head(PI, Head0),
  993    (   Head0 = _:_
  994    ->  strip_module(Head0, M, Plain),
  995        (   xmodule(M, Src)
  996        ->  Head = Plain
  997        ;   Head = M:Plain
  998        )
  999    ;   Head = Head0
 1000    ).
 1001:- endif.
 xref_comment(?Source, ?Title, ?Comment) is nondet
Is true when Source has a section comment with Title and Comment
 1007xref_comment(Source, Title, Comment) :-
 1008    canonical_source(Source, Src),
 1009    module_comment(Src, Title, Comment).
 xref_comment(?Source, ?Head, ?Summary, ?Comment) is nondet
Is true when Head in Source has the given PlDoc comment.
 1015xref_comment(Source, Head, Summary, Comment) :-
 1016    canonical_source(Source, Src),
 1017    (   pred_comment(Head, Src, Summary, Comment)
 1018    ;   pred_comment_link(Head, Src, HeadTo),
 1019        pred_comment(HeadTo, Src, Summary, Comment)
 1020    ).
 xref_mode(?Source, ?Mode, ?Det) is nondet
Is true when Source provides a predicate with Mode and determinism.
 1027xref_mode(Source, Mode, Det) :-
 1028    canonical_source(Source, Src),
 1029    pred_mode(Mode, Src, Det).
 xref_option(?Source, ?Option) is nondet
True when Source was processed using Option. Options are defined with xref_source/2.
 1036xref_option(Source, Option) :-
 1037    canonical_source(Source, Src),
 1038    xoption(Src, Option).
 1039
 1040
 1041                 /********************************
 1042                 *           DIRECTIVES         *
 1043                 ********************************/
 1044
 1045process_directive(Var, _) :-
 1046    var(Var),
 1047    !.                    % error, but that isn't our business
 1048process_directive(Dir, _Src) :-
 1049    debug(xref(directive), 'Processing :- ~q', [Dir]),
 1050    fail.
 1051process_directive((A,B), Src) :-       % TBD: what about other control
 1052    !,
 1053    process_directive(A, Src),      % structures?
 1054    process_directive(B, Src).
 1055process_directive(List, Src) :-
 1056    is_list(List),
 1057    !,
 1058    process_directive(consult(List), Src).
 1059process_directive(use_module(File, Import), Src) :-
 1060    process_use_module2(File, Import, Src, false).
 1061process_directive(autoload(File, Import), Src) :-
 1062    process_use_module2(File, Import, Src, false).
 1063process_directive(require(Import), Src) :-
 1064    process_requires(Import, Src).
 1065process_directive(expects_dialect(Dialect), Src) :-
 1066    process_directive(use_module(library(dialect/Dialect)), Src),
 1067    expects_dialect(Dialect).
 1068process_directive(reexport(File, Import), Src) :-
 1069    process_use_module2(File, Import, Src, true).
 1070process_directive(reexport(Modules), Src) :-
 1071    process_use_module(Modules, Src, true).
 1072process_directive(autoload(Modules), Src) :-
 1073    process_use_module(Modules, Src, false).
 1074process_directive(use_module(Modules), Src) :-
 1075    process_use_module(Modules, Src, false).
 1076process_directive(consult(Modules), Src) :-
 1077    process_use_module(Modules, Src, false).
 1078process_directive(ensure_loaded(Modules), Src) :-
 1079    process_use_module(Modules, Src, false).
 1080process_directive(load_files(Files, _Options), Src) :-
 1081    process_use_module(Files, Src, false).
 1082process_directive(include(Files), Src) :-
 1083    process_include(Files, Src).
 1084process_directive(dynamic(Dynamic), Src) :-
 1085    process_predicates(assert_dynamic, Dynamic, Src).
 1086process_directive(dynamic(Dynamic, _Options), Src) :-
 1087    process_predicates(assert_dynamic, Dynamic, Src).
 1088process_directive(thread_local(Dynamic), Src) :-
 1089    process_predicates(assert_thread_local, Dynamic, Src).
 1090process_directive(multifile(Dynamic), Src) :-
 1091    process_predicates(assert_multifile, Dynamic, Src).
 1092process_directive(public(Public), Src) :-
 1093    process_predicates(assert_public, Public, Src).
 1094process_directive(export(Export), Src) :-
 1095    process_predicates(assert_export, Export, Src).
 1096process_directive(import(Import), Src) :-
 1097    process_import(Import, Src).
 1098process_directive(module(Module, Export), Src) :-
 1099    assert_module(Src, Module),
 1100    assert_module_export(Src, Export).
 1101process_directive(module(Module, Export, Import), Src) :-
 1102    assert_module(Src, Module),
 1103    assert_module_export(Src, Export),
 1104    assert_module3(Import, Src).
 1105process_directive(begin_tests(Unit, _Options), Src) :-
 1106    enter_test_unit(Unit, Src).
 1107process_directive(begin_tests(Unit), Src) :-
 1108    enter_test_unit(Unit, Src).
 1109process_directive(end_tests(Unit), Src) :-
 1110    leave_test_unit(Unit, Src).
 1111process_directive('$set_source_module'(system), Src) :-
 1112    assert_module(Src, system).     % hack for handling boot/init.pl
 1113process_directive(pce_begin_class_definition(Name, Meta, Super, Doc), Src) :-
 1114    assert_defined_class(Src, Name, Meta, Super, Doc).
 1115process_directive(pce_autoload(Name, From), Src) :-
 1116    assert_defined_class(Src, Name, imported_from(From)).
 1117
 1118process_directive(op(P, A, N), Src) :-
 1119    xref_push_op(Src, P, A, N).
 1120process_directive(set_prolog_flag(Flag, Value), Src) :-
 1121    (   Flag == character_escapes
 1122    ->  set_prolog_flag(character_escapes, Value)
 1123    ;   true
 1124    ),
 1125    current_source_line(Line),
 1126    xref_set_prolog_flag(Flag, Value, Src, Line).
 1127process_directive(style_check(X), _) :-
 1128    style_check(X).
 1129process_directive(encoding(Enc), _) :-
 1130    (   xref_input_stream(Stream)
 1131    ->  catch(set_stream(Stream, encoding(Enc)), error(_,_), true)
 1132    ;   true                        % can this happen?
 1133    ).
 1134process_directive(pce_expansion:push_compile_operators, _) :-
 1135    '$current_source_module'(SM),
 1136    call(pce_expansion:push_compile_operators(SM)). % call to avoid xref
 1137process_directive(pce_expansion:pop_compile_operators, _) :-
 1138    call(pce_expansion:pop_compile_operators).
 1139process_directive(meta_predicate(Meta), Src) :-
 1140    process_meta_predicate(Meta, Src).
 1141process_directive(arithmetic_function(FSpec), Src) :-
 1142    arith_callable(FSpec, Goal),
 1143    !,
 1144    current_source_line(Line),
 1145    assert_called(Src, '<directive>'(Line), Goal, Line).
 1146process_directive(format_predicate(_, Goal), Src) :-
 1147    !,
 1148    current_source_line(Line),
 1149    assert_called(Src, '<directive>'(Line), Goal, Line).
 1150process_directive(if(Cond), Src) :-
 1151    !,
 1152    current_source_line(Line),
 1153    assert_called(Src, '<directive>'(Line), Cond, Line).
 1154process_directive(elif(Cond), Src) :-
 1155    !,
 1156    current_source_line(Line),
 1157    assert_called(Src, '<directive>'(Line), Cond, Line).
 1158process_directive(else, _) :- !.
 1159process_directive(endif, _) :- !.
 1160process_directive(Goal, Src) :-
 1161    current_source_line(Line),
 1162    process_body(Goal, '<directive>'(Line), Src).
 process_meta_predicate(+Decl, +Src)
Create meta_goal/3 facts from the meta-goal declaration.
 1168process_meta_predicate((A,B), Src) :-
 1169    !,
 1170    process_meta_predicate(A, Src),
 1171    process_meta_predicate(B, Src).
 1172process_meta_predicate(Decl, Src) :-
 1173    process_meta_head(Src, Decl).
 1174
 1175process_meta_head(Src, Decl) :-         % swapped arguments for maplist
 1176    compound(Decl),
 1177    compound_name_arity(Decl, Name, Arity),
 1178    compound_name_arity(Head, Name, Arity),
 1179    meta_args(1, Arity, Decl, Head, Meta),
 1180    (   (   prolog:meta_goal(Head, _)
 1181        ;   prolog:called_by(Head, _, _, _)
 1182        ;   prolog:called_by(Head, _)
 1183        ;   meta_goal(Head, Meta, _Src)
 1184        )
 1185    ->  true
 1186    ;   warn_late_meta_predicate(Decl, Src),
 1187        retractall(meta_goal(Head, _, Src)),
 1188        assert(meta_goal(Head, Meta, Src))
 1189    ).
 1190
 1191meta_args(I, Arity, _, _, []) :-
 1192    I > Arity,
 1193    !.
 1194meta_args(I, Arity, Decl, Head, [H|T]) :-               % 0
 1195    arg(I, Decl, 0),
 1196    !,
 1197    arg(I, Head, H),
 1198    I2 is I + 1,
 1199    meta_args(I2, Arity, Decl, Head, T).
 1200meta_args(I, Arity, Decl, Head, [H|T]) :-               % ^
 1201    arg(I, Decl, ^),
 1202    !,
 1203    arg(I, Head, EH),
 1204    setof_goal(EH, H),
 1205    I2 is I + 1,
 1206    meta_args(I2, Arity, Decl, Head, T).
 1207meta_args(I, Arity, Decl, Head, [//(H)|T]) :-
 1208    arg(I, Decl, //),
 1209    !,
 1210    arg(I, Head, H),
 1211    I2 is I + 1,
 1212    meta_args(I2, Arity, Decl, Head, T).
 1213meta_args(I, Arity, Decl, Head, [H+A|T]) :-             % I --> H+I
 1214    arg(I, Decl, A),
 1215    integer(A), A > 0,
 1216    !,
 1217    arg(I, Head, H),
 1218    I2 is I + 1,
 1219    meta_args(I2, Arity, Decl, Head, T).
 1220meta_args(I, Arity, Decl, Head, Meta) :-
 1221    I2 is I + 1,
 1222    meta_args(I2, Arity, Decl, Head, Meta).
 1223
 1224
 1225warn_late_meta_predicate(Decl, Src) :-
 1226    xref_called(Src, Decl, By),
 1227    !,
 1228    print_message(warning, meta_predicate_after_call(Decl, By)).
 1229warn_late_meta_predicate(_, _).
 1230
 1231
 1232              /********************************
 1233              *             BODY              *
 1234              ********************************/
 xref_meta(+Source, +Head, -Called) is semidet
True when Head calls Called in Source.
Arguments:
Called- is a list of called terms, terms of the form Term+Extra or terms of the form //(Term).
 1243xref_meta(Source, Head, Called) :-
 1244    canonical_source(Source, Src),
 1245    xref_meta_src(Head, Called, Src).
 xref_meta(+Head, -Called) is semidet
 xref_meta_src(+Head, -Called, +Src) is semidet
True when Called is a list of terms called from Head. Each element in Called can be of the form Term+Int, which means that Term must be extended with Int additional arguments. The variant xref_meta/3 first queries the local context.
deprecated
- New code should use xref_meta/3.
To be done
- Split predifined in several categories. E.g., the ISO predicates cannot be redefined.
- Rely on the meta_predicate property for many predicates.
 1260xref_meta_src(Head, Called, Src) :-
 1261    meta_goal(Head, Called, Src),
 1262    !.
 1263xref_meta_src(Head, Called, _) :-
 1264    xref_meta(Head, Called),
 1265    !.
 1266xref_meta_src(Head, Called, _) :-
 1267    compound(Head),
 1268    compound_name_arity(Head, Name, Arity),
 1269    apply_pred(Name),
 1270    Arity > 5,
 1271    !,
 1272    Extra is Arity - 1,
 1273    arg(1, Head, G),
 1274    Called = [G+Extra].
 1275xref_meta_src(Head, Called, _) :-
 1276    with_xref(predicate_property('$xref_tmp':Head, meta_predicate(Meta))),
 1277    !,
 1278    Meta =.. [_|Args],
 1279    meta_args(Args, 1, Head, Called).
 1280
 1281meta_args([], _, _, []).
 1282meta_args([H0|T0], I, Head, [H|T]) :-
 1283    xargs(H0, N),
 1284    !,
 1285    arg(I, Head, A),
 1286    (   N == 0
 1287    ->  H = A
 1288    ;   H = (A+N)
 1289    ),
 1290    I2 is I+1,
 1291    meta_args(T0, I2, Head, T).
 1292meta_args([_|T0], I, Head, T) :-
 1293    I2 is I+1,
 1294    meta_args(T0, I2, Head, T).
 1295
 1296xargs(N, N) :- integer(N), !.
 1297xargs(//, 2).
 1298xargs(^, 0).
 1299
 1300apply_pred(call).                               % built-in
 1301apply_pred(maplist).                            % library(apply_macros)
 1302
 1303xref_meta((A, B),               [A, B]).
 1304xref_meta((A; B),               [A, B]).
 1305xref_meta((A| B),               [A, B]).
 1306xref_meta((A -> B),             [A, B]).
 1307xref_meta((A *-> B),            [A, B]).
 1308xref_meta(findall(_V,G,_L),     [G]).
 1309xref_meta(findall(_V,G,_L,_T),  [G]).
 1310xref_meta(findnsols(_N,_V,G,_L),    [G]).
 1311xref_meta(findnsols(_N,_V,G,_L,_T), [G]).
 1312xref_meta(setof(_V, EG, _L),    [G]) :-
 1313    setof_goal(EG, G).
 1314xref_meta(bagof(_V, EG, _L),    [G]) :-
 1315    setof_goal(EG, G).
 1316xref_meta(forall(A, B),         [A, B]).
 1317xref_meta(maplist(G,_),         [G+1]).
 1318xref_meta(maplist(G,_,_),       [G+2]).
 1319xref_meta(maplist(G,_,_,_),     [G+3]).
 1320xref_meta(maplist(G,_,_,_,_),   [G+4]).
 1321xref_meta(map_list_to_pairs(G,_,_), [G+2]).
 1322xref_meta(map_assoc(G, _),      [G+1]).
 1323xref_meta(map_assoc(G, _, _),   [G+2]).
 1324xref_meta(checklist(G, _L),     [G+1]).
 1325xref_meta(sublist(G, _, _),     [G+1]).
 1326xref_meta(include(G, _, _),     [G+1]).
 1327xref_meta(exclude(G, _, _),     [G+1]).
 1328xref_meta(partition(G, _, _, _, _),     [G+2]).
 1329xref_meta(partition(G, _, _, _),[G+1]).
 1330xref_meta(call(G),              [G]).
 1331xref_meta(call(G, _),           [G+1]).
 1332xref_meta(call(G, _, _),        [G+2]).
 1333xref_meta(call(G, _, _, _),     [G+3]).
 1334xref_meta(call(G, _, _, _, _),  [G+4]).
 1335xref_meta(not(G),               [G]).
 1336xref_meta(notrace(G),           [G]).
 1337xref_meta('$notrace'(G),        [G]).
 1338xref_meta(\+(G),                [G]).
 1339xref_meta(ignore(G),            [G]).
 1340xref_meta(once(G),              [G]).
 1341xref_meta(initialization(G),    [G]).
 1342xref_meta(initialization(G,_),  [G]).
 1343xref_meta(retract(Rule),        [G]) :- head_of(Rule, G).
 1344xref_meta(clause(G, _),         [G]).
 1345xref_meta(clause(G, _, _),      [G]).
 1346xref_meta(phrase(G, _A),        [//(G)]).
 1347xref_meta(phrase(G, _A, _R),    [//(G)]).
 1348xref_meta(call_dcg(G, _A, _R),  [//(G)]).
 1349xref_meta(phrase_from_file(G,_),[//(G)]).
 1350xref_meta(catch(A, _, B),       [A, B]).
 1351xref_meta(catch_with_backtrace(A, _, B), [A, B]).
 1352xref_meta(thread_create(A,_,_), [A]).
 1353xref_meta(thread_create(A,_),   [A]).
 1354xref_meta(thread_signal(_,A),   [A]).
 1355xref_meta(thread_idle(A,_),     [A]).
 1356xref_meta(thread_at_exit(A),    [A]).
 1357xref_meta(thread_initialization(A), [A]).
 1358xref_meta(engine_create(_,A,_), [A]).
 1359xref_meta(engine_create(_,A,_,_), [A]).
 1360xref_meta(transaction(A),       [A]).
 1361xref_meta(transaction(A,B,_),   [A,B]).
 1362xref_meta(snapshot(A),          [A]).
 1363xref_meta(predsort(A,_,_),      [A+3]).
 1364xref_meta(call_cleanup(A, B),   [A, B]).
 1365xref_meta(call_cleanup(A, _, B),[A, B]).
 1366xref_meta(setup_call_cleanup(A, B, C),[A, B, C]).
 1367xref_meta(setup_call_catcher_cleanup(A, B, _, C),[A, B, C]).
 1368xref_meta(call_residue_vars(A,_), [A]).
 1369xref_meta(with_mutex(_,A),      [A]).
 1370xref_meta(assume(G),            [G]).   % library(debug)
 1371xref_meta(assertion(G),         [G]).   % library(debug)
 1372xref_meta(freeze(_, G),         [G]).
 1373xref_meta(when(C, A),           [C, A]).
 1374xref_meta(time(G),              [G]).   % development system
 1375xref_meta(call_time(G, _),      [G]).   % development system
 1376xref_meta(call_time(G, _, _),   [G]).   % development system
 1377xref_meta(profile(G),           [G]).
 1378xref_meta(at_halt(G),           [G]).
 1379xref_meta(call_with_time_limit(_, G), [G]).
 1380xref_meta(call_with_depth_limit(G, _, _), [G]).
 1381xref_meta(call_with_inference_limit(G, _, _), [G]).
 1382xref_meta(alarm(_, G, _),       [G]).
 1383xref_meta(alarm(_, G, _, _),    [G]).
 1384xref_meta('$add_directive_wic'(G), [G]).
 1385xref_meta(with_output_to(_, G), [G]).
 1386xref_meta(if(G),                [G]).
 1387xref_meta(elif(G),              [G]).
 1388xref_meta(meta_options(G,_,_),  [G+1]).
 1389xref_meta(on_signal(_,_,H),     [H+1]) :- H \== default.
 1390xref_meta(distinct(G),          [G]).   % library(solution_sequences)
 1391xref_meta(distinct(_, G),       [G]).
 1392xref_meta(order_by(_, G),       [G]).
 1393xref_meta(limit(_, G),          [G]).
 1394xref_meta(offset(_, G),         [G]).
 1395xref_meta(reset(G,_,_),         [G]).
 1396xref_meta(prolog_listen(Ev,G),  [G+N]) :- event_xargs(Ev, N).
 1397xref_meta(prolog_listen(Ev,G,_),[G+N]) :- event_xargs(Ev, N).
 1398xref_meta(tnot(G),		[G]).
 1399xref_meta(not_exists(G),	[G]).
 1400xref_meta(with_tty_raw(G),	[G]).
 1401xref_meta(residual_goals(G),    [G+2]).
 1402
 1403                                        % XPCE meta-predicates
 1404xref_meta(pce_global(_, new(_)), _) :- !, fail.
 1405xref_meta(pce_global(_, B),     [B+1]).
 1406xref_meta(ifmaintainer(G),      [G]).   % used in manual
 1407xref_meta(listen(_, G),         [G]).   % library(broadcast)
 1408xref_meta(listen(_, _, G),      [G]).
 1409xref_meta(in_pce_thread(G),     [G]).
 1410
 1411xref_meta(G, Meta) :-                   % call user extensions
 1412    prolog:meta_goal(G, Meta).
 1413xref_meta(G, Meta) :-                   % Generated from :- meta_predicate
 1414    meta_goal(G, Meta, _Src).
 1415
 1416setof_goal(EG, G) :-
 1417    var(EG), !, G = EG.
 1418setof_goal(_^EG, G) :-
 1419    !,
 1420    setof_goal(EG, G).
 1421setof_goal(G, G).
 1422
 1423event_xargs(abort,            0).
 1424event_xargs(erase,            1).
 1425event_xargs(break,            3).
 1426event_xargs(frame_finished,   1).
 1427event_xargs(thread_exit,      1).
 1428event_xargs(this_thread_exit, 0).
 1429event_xargs(PI,               2) :- pi_to_head(PI, _).
 head_of(+Rule, -Head)
Get the head for a retract call.
 1435head_of(Var, _) :-
 1436    var(Var), !, fail.
 1437head_of((Head :- _), Head).
 1438head_of(Head, Head).
 xref_hook(?Callable)
Definition of known hooks. Hooks that can be called in any module are unqualified. Other hooks are qualified with the module where they are called.
 1446xref_hook(Hook) :-
 1447    prolog:hook(Hook).
 1448xref_hook(Hook) :-
 1449    hook(Hook).
 1450
 1451
 1452hook(attr_portray_hook(_,_)).
 1453hook(attr_unify_hook(_,_)).
 1454hook(attribute_goals(_,_,_)).
 1455hook(goal_expansion(_,_)).
 1456hook(term_expansion(_,_)).
 1457hook(goal_expansion(_,_,_,_)).
 1458hook(term_expansion(_,_,_,_)).
 1459hook(resource(_,_,_)).
 1460hook('$pred_option'(_,_,_,_)).
 1461hook('$nowarn_autoload'(_,_)).
 1462
 1463hook(emacs_prolog_colours:goal_classification(_,_)).
 1464hook(emacs_prolog_colours:goal_colours(_,_)).
 1465hook(emacs_prolog_colours:identify(_,_)).
 1466hook(emacs_prolog_colours:style(_,_)).
 1467hook(emacs_prolog_colours:term_colours(_,_)).
 1468hook(pce_principal:get_implementation(_,_,_,_)).
 1469hook(pce_principal:pce_class(_,_,_,_,_,_)).
 1470hook(pce_principal:pce_lazy_get_method(_,_,_)).
 1471hook(pce_principal:pce_lazy_send_method(_,_,_)).
 1472hook(pce_principal:pce_uses_template(_,_)).
 1473hook(pce_principal:send_implementation(_,_,_)).
 1474hook(predicate_options:option_decl(_,_,_)).
 1475hook(prolog:debug_control_hook(_)).
 1476hook(prolog:error_message(_,_,_)).
 1477hook(prolog:expand_answer(_,_,_)).
 1478hook(prolog:general_exception(_,_)).
 1479hook(prolog:help_hook(_)).
 1480hook(prolog:locate_clauses(_,_)).
 1481hook(prolog:message(_,_,_)).
 1482hook(prolog:message_context(_,_,_)).
 1483hook(prolog:message_line_element(_,_)).
 1484hook(prolog:message_location(_,_,_)).
 1485hook(prolog:predicate_summary(_,_)).
 1486hook(prolog:prolog_exception_hook(_,_,_,_,_)).
 1487hook(prolog:residual_goals(_,_)).
 1488hook(prolog_edit:load).
 1489hook(prolog_edit:locate(_,_,_)).
 1490hook(sandbox:safe_directive(_)).
 1491hook(sandbox:safe_global_variable(_)).
 1492hook(sandbox:safe_meta(_,_)).
 1493hook(sandbox:safe_meta_predicate(_)).
 1494hook(sandbox:safe_primitive(_)).
 1495hook(sandbox:safe_prolog_flag(_,_)).
 1496hook(shlib:unload_all_foreign_libraries).
 1497hook(system:'$foreign_registered'(_, _)).
 1498hook(user:exception(_,_,_)).
 1499hook(user:expand_answer(_,_)).
 1500hook(user:expand_query(_,_,_,_)).
 1501hook(user:file_search_path(_,_)).
 1502hook(user:library_directory(_)).
 1503hook(user:message_hook(_,_,_)).
 1504hook(prolog:message_action(_,_)).
 1505hook(user:portray(_)).
 1506hook(user:prolog_clause_name(_,_)).
 1507hook(user:prolog_list_goal(_)).
 1508hook(user:prolog_predicate_name(_,_)).
 1509hook(user:prolog_trace_interception(_,_,_,_)).
 arith_callable(+Spec, -Callable)
Translate argument of arithmetic_function/1 into a callable term
 1515arith_callable(Var, _) :-
 1516    var(Var), !, fail.
 1517arith_callable(Module:Spec, Module:Goal) :-
 1518    !,
 1519    arith_callable(Spec, Goal).
 1520arith_callable(Name/Arity, Goal) :-
 1521    PredArity is Arity + 1,
 1522    functor(Goal, Name, PredArity).
 process_body(+Body, +Origin, +Src) is det
Process a callable body (body of a clause or directive). Origin describes the origin of the call. Partial evaluation may lead to non-determinism, which is why we backtrack over process_goal/3.

We limit the number of explored paths to 100 to avoid getting trapped in this analysis.

 1533process_body(Body, Origin, Src) :-
 1534    forall(limit(100, process_goal(Body, Origin, Src, _Partial)),
 1535           true).
 process_goal(+Goal, +Origin, +Src, ?Partial) is multi
Xref Goal. The argument Partial is bound to true if there was a partial evalation inside Goal that has bound variables.
 1542process_goal(Var, _, _, _) :-
 1543    var(Var),
 1544    !.
 1545process_goal(_:Goal, _, _, _) :-
 1546    var(Goal),
 1547    !.
 1548process_goal(Goal, Origin, Src, P) :-
 1549    Goal = (_,_),                               % problems
 1550    !,
 1551    phrase(conjunction(Goal), Goals),
 1552    process_conjunction(Goals, Origin, Src, P).
 1553process_goal(Goal, Origin, Src, _) :-           % Final disjunction, no
 1554    Goal = (_;_),                               % problems
 1555    !,
 1556    phrase(disjunction(Goal), Goals),
 1557    forall(member(G, Goals),
 1558           process_body(G, Origin, Src)).
 1559process_goal(Goal, Origin, Src, P) :-
 1560    (   (   xmodule(M, Src)
 1561        ->  true
 1562        ;   M = user
 1563        ),
 1564        pi_head(PI, M:Goal),
 1565        (   current_predicate(PI),
 1566            predicate_property(M:Goal, imported_from(IM))
 1567        ->  true
 1568        ;   PI = M:Name/Arity,
 1569            '$find_library'(M, Name, Arity, IM, _Library)
 1570        ->  true
 1571        ;   IM = M
 1572        ),
 1573        prolog:called_by(Goal, IM, M, Called)
 1574    ;   prolog:called_by(Goal, Called)
 1575    ),
 1576    !,
 1577    must_be(list, Called),
 1578    current_source_line(Here),
 1579    assert_called(Src, Origin, Goal, Here),
 1580    process_called_list(Called, Origin, Src, P).
 1581process_goal(Goal, Origin, Src, _) :-
 1582    process_xpce_goal(Goal, Origin, Src),
 1583    !.
 1584process_goal(load_foreign_library(File), _Origin, Src, _) :-
 1585    process_foreign(File, Src).
 1586process_goal(load_foreign_library(File, _Init), _Origin, Src, _) :-
 1587    process_foreign(File, Src).
 1588process_goal(use_foreign_library(File), _Origin, Src, _) :-
 1589    process_foreign(File, Src).
 1590process_goal(use_foreign_library(File, _Init), _Origin, Src, _) :-
 1591    process_foreign(File, Src).
 1592process_goal(Goal, Origin, Src, P) :-
 1593    xref_meta_src(Goal, Metas, Src),
 1594    !,
 1595    current_source_line(Here),
 1596    assert_called(Src, Origin, Goal, Here),
 1597    process_called_list(Metas, Origin, Src, P).
 1598process_goal(Goal, Origin, Src, _) :-
 1599    asserting_goal(Goal, Rule),
 1600    !,
 1601    current_source_line(Here),
 1602    assert_called(Src, Origin, Goal, Here),
 1603    process_assert(Rule, Origin, Src).
 1604process_goal(Goal, Origin, Src, P) :-
 1605    partial_evaluate(Goal, P),
 1606    current_source_line(Here),
 1607    assert_called(Src, Origin, Goal, Here).
 1608
 1609disjunction(Var)   --> {var(Var), !}, [Var].
 1610disjunction((A;B)) --> !, disjunction(A), disjunction(B).
 1611disjunction(G)     --> [G].
 1612
 1613conjunction(Var)   --> {var(Var), !}, [Var].
 1614conjunction((A,B)) --> !, conjunction(A), conjunction(B).
 1615conjunction(G)     --> [G].
 1616
 1617shares_vars(RVars, T) :-
 1618    term_variables(T, TVars0),
 1619    sort(TVars0, TVars),
 1620    ord_intersect(RVars, TVars).
 1621
 1622process_conjunction([], _, _, _).
 1623process_conjunction([Disj|Rest], Origin, Src, P) :-
 1624    nonvar(Disj),
 1625    Disj = (_;_),
 1626    Rest \== [],
 1627    !,
 1628    phrase(disjunction(Disj), Goals),
 1629    term_variables(Rest, RVars0),
 1630    sort(RVars0, RVars),
 1631    partition(shares_vars(RVars), Goals, Sharing, NonSHaring),
 1632    forall(member(G, NonSHaring),
 1633           process_body(G, Origin, Src)),
 1634    (   Sharing == []
 1635    ->  true
 1636    ;   maplist(term_variables, Sharing, GVars0),
 1637        append(GVars0, GVars1),
 1638        sort(GVars1, GVars),
 1639        ord_intersection(GVars, RVars, SVars),
 1640        VT =.. [v|SVars],
 1641        findall(VT,
 1642                (   member(G, Sharing),
 1643                    process_goal(G, Origin, Src, PS),
 1644                    PS == true
 1645                ),
 1646                Alts0),
 1647        (   Alts0 == []
 1648        ->  true
 1649        ;   (   true
 1650            ;   P = true,
 1651                sort(Alts0, Alts1),
 1652                variants(Alts1, 10, Alts),
 1653                member(VT, Alts)
 1654            )
 1655        )
 1656    ),
 1657    process_conjunction(Rest, Origin, Src, P).
 1658process_conjunction([H|T], Origin, Src, P) :-
 1659    process_goal(H, Origin, Src, P),
 1660    process_conjunction(T, Origin, Src, P).
 1661
 1662
 1663process_called_list([], _, _, _).
 1664process_called_list([H|T], Origin, Src, P) :-
 1665    process_meta(H, Origin, Src, P),
 1666    process_called_list(T, Origin, Src, P).
 1667
 1668process_meta(A+N, Origin, Src, P) :-
 1669    !,
 1670    (   extend(A, N, AX)
 1671    ->  process_goal(AX, Origin, Src, P)
 1672    ;   true
 1673    ).
 1674process_meta(//(A), Origin, Src, P) :-
 1675    !,
 1676    process_dcg_goal(A, Origin, Src, P).
 1677process_meta(G, Origin, Src, P) :-
 1678    process_goal(G, Origin, Src, P).
 process_dcg_goal(+Grammar, +Origin, +Src, ?Partial) is det
Process meta-arguments that are tagged with //, such as phrase/3.
 1685process_dcg_goal(Var, _, _, _) :-
 1686    var(Var),
 1687    !.
 1688process_dcg_goal((A,B), Origin, Src, P) :-
 1689    !,
 1690    process_dcg_goal(A, Origin, Src, P),
 1691    process_dcg_goal(B, Origin, Src, P).
 1692process_dcg_goal((A;B), Origin, Src, P) :-
 1693    !,
 1694    process_dcg_goal(A, Origin, Src, P),
 1695    process_dcg_goal(B, Origin, Src, P).
 1696process_dcg_goal((A|B), Origin, Src, P) :-
 1697    !,
 1698    process_dcg_goal(A, Origin, Src, P),
 1699    process_dcg_goal(B, Origin, Src, P).
 1700process_dcg_goal((A->B), Origin, Src, P) :-
 1701    !,
 1702    process_dcg_goal(A, Origin, Src, P),
 1703    process_dcg_goal(B, Origin, Src, P).
 1704process_dcg_goal((A*->B), Origin, Src, P) :-
 1705    !,
 1706    process_dcg_goal(A, Origin, Src, P),
 1707    process_dcg_goal(B, Origin, Src, P).
 1708process_dcg_goal({Goal}, Origin, Src, P) :-
 1709    !,
 1710    process_goal(Goal, Origin, Src, P).
 1711process_dcg_goal(List, _Origin, _Src, _) :-
 1712    is_list(List),
 1713    !.               % terminal
 1714process_dcg_goal(List, _Origin, _Src, _) :-
 1715    string(List),
 1716    !.                % terminal
 1717process_dcg_goal(Callable, Origin, Src, P) :-
 1718    extend(Callable, 2, Goal),
 1719    !,
 1720    process_goal(Goal, Origin, Src, P).
 1721process_dcg_goal(_, _, _, _).
 1722
 1723
 1724extend(Var, _, _) :-
 1725    var(Var), !, fail.
 1726extend(M:G, N, M:GX) :-
 1727    !,
 1728    callable(G),
 1729    extend(G, N, GX).
 1730extend(G, N, GX) :-
 1731    (   compound(G)
 1732    ->  compound_name_arguments(G, Name, Args),
 1733        length(Rest, N),
 1734        append(Args, Rest, NArgs),
 1735        compound_name_arguments(GX, Name, NArgs)
 1736    ;   atom(G)
 1737    ->  length(NArgs, N),
 1738        compound_name_arguments(GX, G, NArgs)
 1739    ).
 1740
 1741asserting_goal(assert(Rule), Rule).
 1742asserting_goal(asserta(Rule), Rule).
 1743asserting_goal(assertz(Rule), Rule).
 1744asserting_goal(assert(Rule,_), Rule).
 1745asserting_goal(asserta(Rule,_), Rule).
 1746asserting_goal(assertz(Rule,_), Rule).
 1747
 1748process_assert(0, _, _) :- !.           % catch variables
 1749process_assert((_:-Body), Origin, Src) :-
 1750    !,
 1751    process_body(Body, Origin, Src).
 1752process_assert(_, _, _).
 variants(+SortedList, +Max, -Variants) is det
 1756variants([], _, []).
 1757variants([H|T], Max, List) :-
 1758    variants(T, H, Max, List).
 1759
 1760variants([], H, _, [H]).
 1761variants(_, _, 0, []) :- !.
 1762variants([H|T], V, Max, List) :-
 1763    (   H =@= V
 1764    ->  variants(T, V, Max, List)
 1765    ;   List = [V|List2],
 1766        Max1 is Max-1,
 1767        variants(T, H, Max1, List2)
 1768    ).
 partial_evaluate(+Goal, ?Parrial) is det
Perform partial evaluation on Goal to trap cases such as below.
      T = hello(X),
      findall(T, T, List),
To be done
- Make this user extensible? What about non-deterministic bindings?
 1782partial_evaluate(Goal, P) :-
 1783    eval(Goal),
 1784    !,
 1785    P = true.
 1786partial_evaluate(_, _).
 1787
 1788eval(X = Y) :-
 1789    unify_with_occurs_check(X, Y).
 1790
 1791		 /*******************************
 1792		 *        PLUNIT SUPPORT	*
 1793		 *******************************/
 1794
 1795enter_test_unit(Unit, _Src) :-
 1796    current_source_line(Line),
 1797    asserta(current_test_unit(Unit, Line)).
 1798
 1799leave_test_unit(Unit, _Src) :-
 1800    retractall(current_test_unit(Unit, _)).
 1801
 1802
 1803                 /*******************************
 1804                 *          XPCE STUFF          *
 1805                 *******************************/
 1806
 1807pce_goal(new(_,_), new(-, new)).
 1808pce_goal(send(_,_), send(arg, msg)).
 1809pce_goal(send_class(_,_,_), send_class(arg, arg, msg)).
 1810pce_goal(get(_,_,_), get(arg, msg, -)).
 1811pce_goal(get_class(_,_,_,_), get_class(arg, arg, msg, -)).
 1812pce_goal(get_chain(_,_,_), get_chain(arg, msg, -)).
 1813pce_goal(get_object(_,_,_), get_object(arg, msg, -)).
 1814
 1815process_xpce_goal(G, Origin, Src) :-
 1816    pce_goal(G, Process),
 1817    !,
 1818    current_source_line(Here),
 1819    assert_called(Src, Origin, G, Here),
 1820    (   arg(I, Process, How),
 1821        arg(I, G, Term),
 1822        process_xpce_arg(How, Term, Origin, Src),
 1823        fail
 1824    ;   true
 1825    ).
 1826
 1827process_xpce_arg(new, Term, Origin, Src) :-
 1828    callable(Term),
 1829    process_new(Term, Origin, Src).
 1830process_xpce_arg(arg, Term, Origin, Src) :-
 1831    compound(Term),
 1832    process_new(Term, Origin, Src).
 1833process_xpce_arg(msg, Term, Origin, Src) :-
 1834    compound(Term),
 1835    (   arg(_, Term, Arg),
 1836        process_xpce_arg(arg, Arg, Origin, Src),
 1837        fail
 1838    ;   true
 1839    ).
 1840
 1841process_new(_M:_Term, _, _) :- !.       % TBD: Calls on other modules!
 1842process_new(Term, Origin, Src) :-
 1843    assert_new(Src, Origin, Term),
 1844    (   compound(Term),
 1845        arg(_, Term, Arg),
 1846        process_xpce_arg(arg, Arg, Origin, Src),
 1847        fail
 1848    ;   true
 1849    ).
 1850
 1851assert_new(_, _, Term) :-
 1852    \+ callable(Term),
 1853    !.
 1854assert_new(Src, Origin, Control) :-
 1855    functor_name(Control, Class),
 1856    pce_control_class(Class),
 1857    !,
 1858    forall(arg(_, Control, Arg),
 1859           assert_new(Src, Origin, Arg)).
 1860assert_new(Src, Origin, Term) :-
 1861    compound(Term),
 1862    arg(1, Term, Prolog),
 1863    Prolog == @(prolog),
 1864    (   Term =.. [message, _, Selector | T],
 1865        atom(Selector)
 1866    ->  Called =.. [Selector|T],
 1867        process_body(Called, Origin, Src)
 1868    ;   Term =.. [?, _, Selector | T],
 1869        atom(Selector)
 1870    ->  append(T, [_R], T2),
 1871        Called =.. [Selector|T2],
 1872        process_body(Called, Origin, Src)
 1873    ),
 1874    fail.
 1875assert_new(_, _, @(_)) :- !.
 1876assert_new(Src, _, Term) :-
 1877    functor_name(Term, Name),
 1878    assert_used_class(Src, Name).
 1879
 1880
 1881pce_control_class(and).
 1882pce_control_class(or).
 1883pce_control_class(if).
 1884pce_control_class(not).
 1885
 1886
 1887                /********************************
 1888                *       INCLUDED MODULES        *
 1889                ********************************/
 process_use_module(+Modules, +Src, +Rexport) is det
 1893process_use_module(_Module:_Files, _, _) :- !.  % loaded in another module
 1894process_use_module([], _, _) :- !.
 1895process_use_module([H|T], Src, Reexport) :-
 1896    !,
 1897    process_use_module(H, Src, Reexport),
 1898    process_use_module(T, Src, Reexport).
 1899process_use_module(library(pce), Src, Reexport) :-     % bit special
 1900    !,
 1901    xref_public_list(library(pce), Path, Exports, Src),
 1902    forall(member(Import, Exports),
 1903           process_pce_import(Import, Src, Path, Reexport)).
 1904process_use_module(File, Src, Reexport) :-
 1905    load_module_if_needed(File),
 1906    (   xoption(Src, silent(Silent))
 1907    ->  Extra = [silent(Silent)]
 1908    ;   Extra = [silent(true)]
 1909    ),
 1910    (   xref_public_list(File, Src,
 1911                         [ path(Path),
 1912                           module(M),
 1913                           exports(Exports),
 1914                           public(Public),
 1915                           meta(Meta)
 1916                         | Extra
 1917                         ])
 1918    ->  assert(uses_file(File, Src, Path)),
 1919        assert_import(Src, Exports, _, Path, Reexport),
 1920        assert_xmodule_callable(Exports, M, Src, Path),
 1921        assert_xmodule_callable(Public, M, Src, Path),
 1922        maplist(process_meta_head(Src), Meta),
 1923        (   File = library(chr)     % hacky
 1924        ->  assert(mode(chr, Src))
 1925        ;   true
 1926        )
 1927    ;   assert(uses_file(File, Src, '<not_found>'))
 1928    ).
 1929
 1930process_pce_import(Name/Arity, Src, Path, Reexport) :-
 1931    atom(Name),
 1932    integer(Arity),
 1933    !,
 1934    functor(Term, Name, Arity),
 1935    (   \+ system_predicate(Term),
 1936        \+ Term = pce_error(_)      % hack!?
 1937    ->  assert_import(Src, [Name/Arity], _, Path, Reexport)
 1938    ;   true
 1939    ).
 1940process_pce_import(op(P,T,N), Src, _, _) :-
 1941    xref_push_op(Src, P, T, N).
 process_use_module2(+File, +Import, +Src, +Reexport) is det
Process use_module/2 and reexport/2.
 1947process_use_module2(File, Import, Src, Reexport) :-
 1948    load_module_if_needed(File),
 1949    (   catch(xref_public_list(File, Src,
 1950                               [ path(Path),
 1951                                 exports(Export),
 1952                                 meta(Meta)
 1953                               ]),
 1954              error(_,_),
 1955              fail)
 1956    ->  assertz(uses_file(File, Src, Path)),
 1957        assert_import(Src, Import, Export, Path, Reexport),
 1958        forall((  member(Head, Meta),
 1959                  imported(Head, _, Path)
 1960               ),
 1961               process_meta_head(Src, Head))
 1962    ;   assertz(uses_file(File, Src, '<not_found>'))
 1963    ).
 load_module_if_needed(+File)
Load a module explicitly if it is not suitable for autoloading. Typically this is the case if the module provides essential term and/or goal expansion rulses.
 1972load_module_if_needed(File) :-
 1973    prolog:no_autoload_module(File),
 1974    !,
 1975    use_module(File, []).
 1976load_module_if_needed(_).
 1977
 1978prolog:no_autoload_module(library(apply_macros)).
 1979prolog:no_autoload_module(library(arithmetic)).
 1980prolog:no_autoload_module(library(record)).
 1981prolog:no_autoload_module(library(persistency)).
 1982prolog:no_autoload_module(library(pldoc)).
 1983prolog:no_autoload_module(library(settings)).
 1984prolog:no_autoload_module(library(debug)).
 1985prolog:no_autoload_module(library(plunit)).
 1986prolog:no_autoload_module(library(macros)).
 1987prolog:no_autoload_module(library(yall)).
 process_requires(+Import, +Src)
 1992process_requires(Import, Src) :-
 1993    is_list(Import),
 1994    !,
 1995    require_list(Import, Src).
 1996process_requires(Var, _Src) :-
 1997    var(Var),
 1998    !.
 1999process_requires((A,B), Src) :-
 2000    !,
 2001    process_requires(A, Src),
 2002    process_requires(B, Src).
 2003process_requires(PI, Src) :-
 2004    requires(PI, Src).
 2005
 2006require_list([], _).
 2007require_list([H|T], Src) :-
 2008    requires(H, Src),
 2009    require_list(T, Src).
 2010
 2011requires(PI, _Src) :-
 2012    '$pi_head'(PI, Head),
 2013    '$get_predicate_attribute'(system:Head, defined, 1),
 2014    !.
 2015requires(PI, Src) :-
 2016    '$pi_head'(PI, Head),
 2017    '$pi_head'(Name/Arity, Head),
 2018    '$find_library'(_Module, Name, Arity, _LoadModule, Library),
 2019    (   imported(Head, Src, Library)
 2020    ->  true
 2021    ;   assertz(imported(Head, Src, Library))
 2022    ).
 xref_public_list(+Spec, +Source, +Options) is semidet
Find meta-information about File. If Spec resolves to a Prolog source file, this predicate reads all terms upto the first term that is not a directive. If Spec resolves to a SWI-Prolog `.qlf` file, it extracts part of the information from the QLF file. It uses the module and meta_predicate directives to assemble the information in Options. Options processed:
path(-Path)
Path is the full path name of the referenced file. If Spec resolves to a .qlf file, Path is the name of the embedded Prolog file.
module(-Module)
Module is the module defines in Spec.
exports(-Exports)
Exports is a list of predicate indicators and operators collected from the module/2 term and reexport declarations.
public -Public
Public declarations of the file. Currently always [] for .qlf files.
meta(-Meta)
Meta is a list of heads as they appear in meta_predicate/1 declarations. Currently always [] for .qlf files.
silent(+Boolean)
Do not print any messages or raise exceptions on errors.

The information collected by this predicate is cached. The cached data is considered valid as long as the modification time of the file does not change.

Arguments:
Source- is the file from which Spec is referenced.
 2058xref_public_list(File, Src, Options) :-
 2059    option(path(Source), Options, _),
 2060    option(module(Module), Options, _),
 2061    option(exports(Exports), Options, _),
 2062    option(public(Public), Options, _),
 2063    option(meta(Meta), Options, _),
 2064    xref_source_file(File, Path, Src, Options),
 2065    public_list(Path, Source, Module, Meta, Exports, Public, Options).
 xref_public_list(+File, -Path, -Export, +Src) is semidet
 xref_public_list(+File, -Path, -Module, -Export, -Meta, +Src) is semidet
 xref_public_list(+File, -Path, -Module, -Export, -Public, -Meta, +Src) is semidet
Find meta-information about File. This predicate reads all terms upto the first term that is not a directive. It uses the module and meta_predicate directives to assemble the information described below.

These predicates fail if File is not a module-file.

Arguments:
File- is a file speficiation for prolog_open_source/2 or a .qlf file name. Note this makes a stream a valid input.
Path- is the canonical path to File
Module- is the module defined in Path
Export- is a list of predicate indicators.
Meta- is a list of heads as they appear in meta_predicate/1 declarations.
Src- is the place from which File is referenced.
deprecated
- New code should use xref_public_list/3, which unifies all variations using an option list.
 2089xref_public_list(File, Source, Export, Src) :-
 2090    xref_source_file(File, Path, Src),
 2091    public_list(Path, Source, _, _, Export, _, []).
 2092xref_public_list(File, Source, Module, Export, Meta, Src) :-
 2093    xref_source_file(File, Path, Src),
 2094    public_list(Path, Source, Module, Meta, Export, _, []).
 2095xref_public_list(File, Source, Module, Export, Public, Meta, Src) :-
 2096    xref_source_file(File, Path, Src),
 2097    public_list(Path, Source, Module, Meta, Export, Public, []).
 public_list(+Path, -Source, -Module, -Meta, -Export, -Public, +Options) is det
Read the public information for Path. Options supported are:
silent(+Boolean)
If true, ignore (syntax) errors. If not specified the default is inherited from xref_source/2.
 2108:- dynamic  public_list_cache/7. 2109:- volatile public_list_cache/7. 2110
 2111public_list(Path, Source, Module, Meta, Export, Public, _Options) :-
 2112    \+ is_stream(Path),
 2113    public_list_cache(Path, Source, Modified,
 2114                      Module0, Meta0, Export0, Public0),
 2115    time_file(Path, ModifiedNow),
 2116    (   abs(Modified-ModifiedNow) < 0.0001
 2117    ->  !,
 2118        t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0)
 2119    ;   retractall(public_list_cache(Path, _, _, _, _, _, _)),
 2120        fail
 2121    ).
 2122public_list(Path, Source, Module, Meta, Export, Public, Options) :-
 2123    public_list_nc(Path, Source, Module0, Meta0, Export0, Public0, Options),
 2124    (   Error = error(_,_),
 2125        catch(time_file(Path, Modified), Error, fail)
 2126    ->  asserta(public_list_cache(Path, Source, Modified,
 2127                                  Module0, Meta0, Export0, Public0))
 2128    ;   true
 2129    ),
 2130    t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0).
 2131
 2132public_list_nc(Path, Source, Module, Meta, Export, Public, _Options) :-
 2133    \+ is_stream(Path),
 2134    public_list_from_index(Path, Module, Meta, Export, Public),
 2135    !,
 2136    qlf_pl_file(Path, Source).
 2137public_list_nc(Path, Source, Module, [], Export, [], _Options) :-
 2138    \+ is_stream(Path),
 2139    is_qlf_file(Path),
 2140    !,
 2141    '$qlf_module'(Path, Info),
 2142    _{module:Module, exports:Export, file:Source} :< Info.
 2143public_list_nc(Path, Path, Module, Meta, Export, Public, Options) :-
 2144    (   is_stream(Path)
 2145    ;   exists_file(Path)
 2146    ),
 2147    !,
 2148    prolog_file_directives(Path, Directives, Options),
 2149    public_list(Directives, Path, Module, Meta, [], Export, [], Public, []).
 2150public_list_nc(Path, Path, Module, [], Export, [], _Options) :-
 2151    \+ is_stream(Path),
 2152    qlf_pl_file(QlfFile, Path),
 2153    '$qlf_module'(QlfFile, Info),
 2154    _{module:Module, exports:Export} :< Info.
 2155
 2156public_list([(:- module(Module, Export0))|Decls], Path,
 2157            Module, Meta, MT, Export, Rest, Public, PT) :-
 2158    !,
 2159    (   is_list(Export0)
 2160    ->  append(Export0, Reexport, Export)
 2161    ;   Reexport = Export
 2162    ),
 2163    public_list_(Decls, Path, Meta, MT, Reexport, Rest, Public, PT).
 2164public_list([(:- encoding(_))|Decls], Path,
 2165            Module, Meta, MT, Export, Rest, Public, PT) :-
 2166    public_list(Decls, Path, Module, Meta, MT, Export, Rest, Public, PT).
 2167
 2168public_list_([], _, Meta, Meta, Export, Export, Public, Public).
 2169public_list_([(:-(Dir))|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 2170    public_list_1(Dir, Path, Meta, MT0, Export, Rest0, Public, PT0),
 2171    !,
 2172    public_list_(T, Path, MT0, MT, Rest0, Rest, PT0, PT).
 2173public_list_([_|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 2174    public_list_(T, Path, Meta, MT, Export, Rest, Public, PT).
 2175
 2176public_list_1(reexport(Spec), Path, Meta, MT, Reexport, Rest, Public, PT) :-
 2177    reexport_files(Spec, Path, Meta, MT, Reexport, Rest, Public, PT).
 2178public_list_1(reexport(Spec, Import), Path, Meta, Meta, Reexport, Rest, Public, Public) :-
 2179    public_from_import(Import, Spec, Path, Reexport, Rest).
 2180public_list_1(meta_predicate(Decl), _Path, Meta, MT, Export, Export, Public, Public) :-
 2181    phrase(meta_decls(Decl), Meta, MT).
 2182public_list_1(public(Decl), _Path, Meta, Meta, Export, Export, Public, PT) :-
 2183    phrase(public_decls(Decl), Public, PT).
 reexport_files(+Files, +Src, -Meta, ?MetaTail, -Exports, ?ExportsTail, -Public, ?PublicTail)
 2189reexport_files([], _, Meta, Meta, Export, Export, Public, Public) :- !.
 2190reexport_files([H|T], Src, Meta, MT, Export, ET, Public, PT) :-
 2191    !,
 2192    xref_source_file(H, Path, Src),
 2193    public_list(Path, _Source, _Module, Meta0, Export0, Public0, []),
 2194    append(Meta0, MT1, Meta),
 2195    append(Export0, ET1, Export),
 2196    append(Public0, PT1, Public),
 2197    reexport_files(T, Src, MT1, MT, ET1, ET, PT1, PT).
 2198reexport_files(Spec, Src, Meta, MT, Export, ET, Public, PT) :-
 2199    xref_source_file(Spec, Path, Src),
 2200    public_list(Path, _Source, _Module, Meta0, Export0, Public0, []),
 2201    append(Meta0, MT, Meta),
 2202    append(Export0, ET, Export),
 2203    append(Public0, PT, Public).
 2204
 2205public_from_import(except(Map), Path, Src, Export, Rest) :-
 2206    !,
 2207    xref_public_list(Path, _, AllExports, Src),
 2208    except(Map, AllExports, NewExports),
 2209    append(NewExports, Rest, Export).
 2210public_from_import(Import, _, _, Export, Rest) :-
 2211    import_name_map(Import, Export, Rest).
 except(+Remove, +AllExports, -Exports)
 2216except([], Exports, Exports).
 2217except([PI0 as NewName|Map], Exports0, Exports) :-
 2218    !,
 2219    canonical_pi(PI0, PI),
 2220    map_as(Exports0, PI, NewName, Exports1),
 2221    except(Map, Exports1, Exports).
 2222except([PI0|Map], Exports0, Exports) :-
 2223    canonical_pi(PI0, PI),
 2224    select(PI2, Exports0, Exports1),
 2225    same_pi(PI, PI2),
 2226    !,
 2227    except(Map, Exports1, Exports).
 2228
 2229
 2230map_as([PI|T], Repl, As, [PI2|T])  :-
 2231    same_pi(Repl, PI),
 2232    !,
 2233    pi_as(PI, As, PI2).
 2234map_as([H|T0], Repl, As, [H|T])  :-
 2235    map_as(T0, Repl, As, T).
 2236
 2237pi_as(_/Arity, Name, Name/Arity).
 2238pi_as(_//Arity, Name, Name//Arity).
 2239
 2240import_name_map([], L, L).
 2241import_name_map([_/Arity as NewName|T0], [NewName/Arity|T], Tail) :-
 2242    !,
 2243    import_name_map(T0, T, Tail).
 2244import_name_map([_//Arity as NewName|T0], [NewName//Arity|T], Tail) :-
 2245    !,
 2246    import_name_map(T0, T, Tail).
 2247import_name_map([H|T0], [H|T], Tail) :-
 2248    import_name_map(T0, T, Tail).
 2249
 2250canonical_pi(Name//Arity0, PI) :-
 2251    integer(Arity0),
 2252    !,
 2253    PI = Name/Arity,
 2254    Arity is Arity0 + 2.
 2255canonical_pi(PI, PI).
 2256
 2257same_pi(Canonical, PI2) :-
 2258    canonical_pi(PI2, Canonical).
 2259
 2260meta_decls(Var) -->
 2261    { var(Var) },
 2262    !.
 2263meta_decls((A,B)) -->
 2264    !,
 2265    meta_decls(A),
 2266    meta_decls(B).
 2267meta_decls(A) -->
 2268    [A].
 2269
 2270public_decls(Var) -->
 2271    { var(Var) },
 2272    !.
 2273public_decls((A,B)) -->
 2274    !,
 2275    public_decls(A),
 2276    public_decls(B).
 2277public_decls(A) -->
 2278    [A].
 public_list_from_index(+Path, -Module, -Meta, -Exports, -Public) is semidet
Read the exports for Path from the INDEX.pl file in the same directory.
 2285public_list_from_index(Path, Module, Meta, Export, Public) :-
 2286    file_name_extension(BasePath, _Ext, Path),
 2287    file_directory_name(BasePath, Dir),
 2288    atom_concat(Dir, '/INDEX.pl', IndexFile),
 2289    exists_file(IndexFile),
 2290    file_base_name(BasePath, Base),
 2291    setup_call_cleanup(
 2292        '$push_input_context'(autoload_index),
 2293        setup_call_cleanup(
 2294            open(IndexFile, read, In),
 2295            index_public_list(In, Base, Module, Meta, Export, Public),
 2296            close(In)),
 2297        '$pop_input_context').
 2298
 2299index_public_list(In, Base, Module, Meta, Export, Public) :-
 2300    read_term(In, Term, []),
 2301    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2302
 2303index_public_list(end_of_file, _In, _Base, _Module, [], [], []).
 2304index_public_list(index(op:Op, Module, Base), In, Base, Module, Meta, [Op|Export], Public) :-
 2305    !,
 2306    read_term(In, Term, []),
 2307    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2308index_public_list(index((public):Head, Module, Base), In, Base, Module, Meta, Export, [PI|Public]) :-
 2309    !,
 2310    pi_head(PI, Head),
 2311    read_term(In, Term, []),
 2312    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2313index_public_list(index(Head, Module, Base), In, Base, Module, Meta, [PI|Export], Public) :-
 2314    !,
 2315    pi_head(PI, Head),
 2316    (   meta_mode(Head)
 2317    ->  Meta = [Head|MetaT]
 2318    ;   Meta = MetaT
 2319    ),
 2320    read_term(In, Term, []),
 2321    index_public_list(Term, In, Base, Module, MetaT, Export, Public).
 2322index_public_list(index(Name, Arity, Module, Base), In, Base, Module, Meta, [Name/Arity|Export], Public) :-
 2323    !,
 2324    read_term(In, Term, []),
 2325    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2326index_public_list(_, In, Base, Module, Meta, Export, Public) :-
 2327    read_term(In, Term, []),
 2328    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2329
 2330meta_mode(H) :-
 2331    compound(H),
 2332    arg(_, H, A),
 2333    meta_arg(A),
 2334    !.
 2335
 2336meta_arg(I) :-
 2337    integer(I),
 2338    !.
 2339meta_arg(:).
 2340meta_arg(^).
 2341meta_arg(//).
 2342
 2343                 /*******************************
 2344                 *             INCLUDE          *
 2345                 *******************************/
 2346
 2347process_include([], _) :- !.
 2348process_include([H|T], Src) :-
 2349    !,
 2350    process_include(H, Src),
 2351    process_include(T, Src).
 2352process_include(File, Src) :-
 2353    callable(File),
 2354    !,
 2355    (   once(xref_input(ParentSrc, _)),
 2356        xref_source_file(File, Path, ParentSrc)
 2357    ->  (   (   uses_file(_, Src, Path)
 2358            ;   Path == Src
 2359            )
 2360        ->  true
 2361        ;   assert(uses_file(File, Src, Path)),
 2362            (   xoption(Src, process_include(true))
 2363            ->  findall(O, xoption(Src, O), Options),
 2364                setup_call_cleanup(
 2365                    open_include_file(Path, In, Refs),
 2366                    collect(Src, Path, In, Options),
 2367                    close_include(In, Refs))
 2368            ;   true
 2369            )
 2370        )
 2371    ;   assert(uses_file(File, Src, '<not_found>'))
 2372    ).
 2373process_include(_, _).
 open_include_file(+Path, -In, -Refs)
Opens an :- include(File) referenced file. Note that we cannot use prolog_open_source/2 because we should not safe/restore the lexical context.
 2381open_include_file(Path, In, [Ref]) :-
 2382    once(xref_input(_, Parent)),
 2383    stream_property(Parent, encoding(Enc)),
 2384    '$push_input_context'(xref_include),
 2385    catch((   prolog:xref_open_source(Path, In)
 2386          ->  catch(set_stream(In, encoding(Enc)),
 2387                    error(_,_), true)       % deal with non-file input
 2388          ;   include_encoding(Enc, Options),
 2389              open(Path, read, In, Options)
 2390          ), E,
 2391          ( '$pop_input_context', throw(E))),
 2392    catch((   peek_char(In, #)              % Deal with #! script
 2393          ->  skip(In, 10)
 2394          ;   true
 2395          ), E,
 2396          ( close_include(In, []), throw(E))),
 2397    asserta(xref_input(Path, In), Ref).
 2398
 2399include_encoding(wchar_t, []) :- !.
 2400include_encoding(Enc, [encoding(Enc)]).
 2401
 2402
 2403close_include(In, Refs) :-
 2404    maplist(erase, Refs),
 2405    close(In, [force(true)]),
 2406    '$pop_input_context'.
 process_foreign(+Spec, +Src)
Process a load_foreign_library/1 call.
 2412process_foreign(Spec, Src) :-
 2413    ground(Spec),
 2414    current_foreign_library(Spec, Defined),
 2415    !,
 2416    (   xmodule(Module, Src)
 2417    ->  true
 2418    ;   Module = user
 2419    ),
 2420    process_foreign_defined(Defined, Module, Src).
 2421process_foreign(_, _).
 2422
 2423process_foreign_defined([], _, _).
 2424process_foreign_defined([H|T], M, Src) :-
 2425    (   H = M:Head
 2426    ->  assert_foreign(Src, Head)
 2427    ;   assert_foreign(Src, H)
 2428    ),
 2429    process_foreign_defined(T, M, Src).
 2430
 2431
 2432                 /*******************************
 2433                 *          CHR SUPPORT         *
 2434                 *******************************/
 2435
 2436/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2437This part of the file supports CHR. Our choice is between making special
 2438hooks to make CHR expansion work and  then handle the (complex) expanded
 2439code or process the  CHR  source   directly.  The  latter looks simpler,
 2440though I don't like the idea  of   adding  support for libraries to this
 2441module.  A  file  is  supposed  to  be  a    CHR   file  if  it  uses  a
 2442use_module(library(chr) or contains a :-   constraint/1 directive. As an
 2443extra bonus we get the source-locations right :-)
 2444- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2445
 2446process_chr(@(_Name, Rule), Src) :-
 2447    mode(chr, Src),
 2448    process_chr(Rule, Src).
 2449process_chr(pragma(Rule, _Pragma), Src) :-
 2450    mode(chr, Src),
 2451    process_chr(Rule, Src).
 2452process_chr(<=>(Head, Body), Src) :-
 2453    mode(chr, Src),
 2454    chr_head(Head, Src, H),
 2455    chr_body(Body, H, Src).
 2456process_chr(==>(Head, Body), Src) :-
 2457    mode(chr, Src),
 2458    chr_head(Head, H, Src),
 2459    chr_body(Body, H, Src).
 2460process_chr((:- chr_constraint(Decls)), Src) :-
 2461    (   mode(chr, Src)
 2462    ->  true
 2463    ;   assert(mode(chr, Src))
 2464    ),
 2465    chr_decls(Decls, Src).
 2466
 2467chr_decls((A,B), Src) =>
 2468    chr_decls(A, Src),
 2469    chr_decls(B, Src).
 2470chr_decls(Head, Src) =>
 2471    generalise_term(Head, Gen),
 2472    (   declared(Gen, chr_constraint, Src, _)
 2473    ->  true
 2474    ;   current_source_line(Line),
 2475        assertz(declared(Gen, chr_constraint, Src, Line))
 2476    ).
 2477
 2478chr_head(X, _, _) :-
 2479    var(X),
 2480    !.                      % Illegal.  Warn?
 2481chr_head(\(A,B), Src, H) :-
 2482    chr_head(A, Src, H),
 2483    process_body(B, H, Src).
 2484chr_head((H0,B), Src, H) :-
 2485    chr_defined(H0, Src, H),
 2486    process_body(B, H, Src).
 2487chr_head(H0, Src, H) :-
 2488    chr_defined(H0, Src, H).
 2489
 2490chr_defined(X, _, _) :-
 2491    var(X),
 2492    !.
 2493chr_defined(#(C,_Id), Src, C) :-
 2494    !,
 2495    assert_constraint(Src, C).
 2496chr_defined(A, Src, A) :-
 2497    assert_constraint(Src, A).
 2498
 2499chr_body(X, From, Src) :-
 2500    var(X),
 2501    !,
 2502    process_body(X, From, Src).
 2503chr_body('|'(Guard, Goals), H, Src) :-
 2504    !,
 2505    chr_body(Guard, H, Src),
 2506    chr_body(Goals, H, Src).
 2507chr_body(G, From, Src) :-
 2508    process_body(G, From, Src).
 2509
 2510assert_constraint(_, Head) :-
 2511    var(Head),
 2512    !.
 2513assert_constraint(Src, Head) :-
 2514    constraint(Head, Src, _),
 2515    !.
 2516assert_constraint(Src, Head) :-
 2517    generalise_term(Head, Term),
 2518    current_source_line(Line),
 2519    assert(constraint(Term, Src, Line)).
 2520
 2521
 2522                /********************************
 2523                *       PHASE 1 ASSERTIONS      *
 2524                ********************************/
 assert_called(+Src, +From, +Head, +Line) is det
Assert the fact that Head is called by From in Src. We do not assert called system predicates.
 2531assert_called(_, _, Var, _) :-
 2532    var(Var),
 2533    !.
 2534assert_called(Src, From, Goal, Line) :-
 2535    var(From),
 2536    !,
 2537    assert_called(Src, '<unknown>', Goal, Line).
 2538assert_called(_, _, Goal, _) :-
 2539    expand_hide_called(Goal),
 2540    !.
 2541assert_called(Src, Origin, M:G, Line) :-
 2542    !,
 2543    (   atom(M),
 2544        callable(G)
 2545    ->  current_condition(Cond),
 2546        (   xmodule(M, Src)         % explicit call to own module
 2547        ->  assert_called(Src, Origin, G, Line)
 2548        ;   called(M:G, Src, Origin, Cond, Line) % already registered
 2549        ->  true
 2550        ;   hide_called(M:G, Src)           % not interesting (now)
 2551        ->  true
 2552        ;   generalise(Origin, OTerm),
 2553            generalise(G, GTerm)
 2554        ->  assert(called(M:GTerm, Src, OTerm, Cond, Line))
 2555        ;   true
 2556        )
 2557    ;   true                        % call to variable module
 2558    ).
 2559assert_called(Src, _, Goal, _) :-
 2560    (   xmodule(M, Src)
 2561    ->  M \== system
 2562    ;   M = user
 2563    ),
 2564    hide_called(M:Goal, Src),
 2565    !.
 2566assert_called(Src, Origin, Goal, Line) :-
 2567    current_condition(Cond),
 2568    (   called(Goal, Src, Origin, Cond, Line)
 2569    ->  true
 2570    ;   generalise(Origin, OTerm),
 2571        generalise(Goal, Term)
 2572    ->  assert(called(Term, Src, OTerm, Cond, Line))
 2573    ;   true
 2574    ).
 expand_hide_called(:Callable) is semidet
Goals that should not turn up as being called. Hack. Eventually we should deal with that using an XPCE plugin.
 2582expand_hide_called(pce_principal:send_implementation(_, _, _)).
 2583expand_hide_called(pce_principal:get_implementation(_, _, _, _)).
 2584expand_hide_called(pce_principal:pce_lazy_get_method(_,_,_)).
 2585expand_hide_called(pce_principal:pce_lazy_send_method(_,_,_)).
 2586
 2587assert_defined(Src, Goal) :-
 2588    Goal = test(_Test),
 2589    current_test_unit(Unit, Line),
 2590    assert_called(Src, '<test_unit>'(Unit), Goal, Line),
 2591    fail.
 2592assert_defined(Src, Goal) :-
 2593    Goal = test(_Test, _Options),
 2594    current_test_unit(Unit, Line),
 2595    assert_called(Src, '<test_unit>'(Unit), Goal, Line),
 2596    fail.
 2597assert_defined(Src, Goal) :-
 2598    defined(Goal, Src, _),
 2599    !.
 2600assert_defined(Src, Goal) :-
 2601    generalise(Goal, Term),
 2602    current_source_line(Line),
 2603    assert(defined(Term, Src, Line)).
 2604
 2605assert_foreign(Src, Goal) :-
 2606    foreign(Goal, Src, _),
 2607    !.
 2608assert_foreign(Src, Goal) :-
 2609    generalise(Goal, Term),
 2610    current_source_line(Line),
 2611    assert(foreign(Term, Src, Line)).
 2612
 2613assert_grammar_rule(Src, Goal) :-
 2614    grammar_rule(Goal, Src),
 2615    !.
 2616assert_grammar_rule(Src, Goal) :-
 2617    generalise(Goal, Term),
 2618    assert(grammar_rule(Term, Src)).
 assert_import(+Src, +Import, +ExportList, +From, +Reexport) is det
Asserts imports into Src. Import is the import specification, ExportList is the list of known exported predicates or unbound if this need not be checked and From is the file from which the public predicates come. If Reexport is true, re-export the imported predicates.
To be done
- Tighter type-checking on Import.
 2631assert_import(_, [], _, _, _) :- !.
 2632assert_import(Src, [H|T], Export, From, Reexport) :-
 2633    !,
 2634    assert_import(Src, H, Export, From, Reexport),
 2635    assert_import(Src, T, Export, From, Reexport).
 2636assert_import(Src, except(Except), Export, From, Reexport) :-
 2637    !,
 2638    is_list(Export),
 2639    !,
 2640    except(Except, Export, Import),
 2641    assert_import(Src, Import, _All, From, Reexport).
 2642assert_import(Src, Import as Name, Export, From, Reexport) :-
 2643    !,
 2644    pi_to_head(Import, Term0),
 2645    rename_goal(Term0, Name, Term),
 2646    (   in_export_list(Term0, Export)
 2647    ->  assert(imported(Term, Src, From)),
 2648        assert_reexport(Reexport, Src, Term)
 2649    ;   current_source_line(Line),
 2650        assert_called(Src, '<directive>'(Line), Term0, Line)
 2651    ).
 2652assert_import(Src, Import, Export, From, Reexport) :-
 2653    pi_to_head(Import, Term),
 2654    !,
 2655    (   in_export_list(Term, Export)
 2656    ->  assert(imported(Term, Src, From)),
 2657        assert_reexport(Reexport, Src, Term)
 2658    ;   current_source_line(Line),
 2659        assert_called(Src, '<directive>'(Line), Term, Line)
 2660    ).
 2661assert_import(Src, op(P,T,N), _, _, _) :-
 2662    xref_push_op(Src, P,T,N).
 2663
 2664in_export_list(_Head, Export) :-
 2665    var(Export),
 2666    !.
 2667in_export_list(Head, Export) :-
 2668    member(PI, Export),
 2669    pi_to_head(PI, Head).
 2670
 2671assert_reexport(false, _, _) :- !.
 2672assert_reexport(true, Src, Term) :-
 2673    assert(exported(Term, Src)).
 process_import(:Import, +Src)
Process an import/1 directive
 2679process_import(M:PI, Src) :-
 2680    pi_to_head(PI, Head),
 2681    !,
 2682    (   atom(M),
 2683        current_module(M),
 2684        module_property(M, file(From))
 2685    ->  true
 2686    ;   From = '<unknown>'
 2687    ),
 2688    assert(imported(Head, Src, From)).
 2689process_import(_, _).
 assert_xmodule_callable(PIs, Module, Src, From)
We can call all exports and public predicates of an imported module using Module:Goal.
To be done
- Should we distinguish this from normal imported?
 2698assert_xmodule_callable([], _, _, _).
 2699assert_xmodule_callable([PI|T], M, Src, From) :-
 2700    (   pi_to_head(M:PI, Head)
 2701    ->  assert(imported(Head, Src, From))
 2702    ;   true
 2703    ),
 2704    assert_xmodule_callable(T, M, Src, From).
 assert_op(+Src, +Op) is det
Arguments:
Op- Ground term op(Priority, Type, Name).
 2711assert_op(Src, op(P,T,M:N)) :-
 2712    (   '$current_source_module'(M)
 2713    ->  Name = N
 2714    ;   Name = M:N
 2715    ),
 2716    (   xop(Src, op(P,T,Name))
 2717    ->  true
 2718    ;   assert(xop(Src, op(P,T,Name)))
 2719    ).
 assert_module(+Src, +Module)
Assert we are loading code into Module. This is also used to exploit local term-expansion and other rules.
 2726assert_module(Src, Module) :-
 2727    xmodule(Module, Src),
 2728    !.
 2729assert_module(Src, Module) :-
 2730    '$set_source_module'(Module),
 2731    assert(xmodule(Module, Src)),
 2732    (   module_property(Module, class(system))
 2733    ->  retractall(xoption(Src, register_called(_))),
 2734        assert(xoption(Src, register_called(all)))
 2735    ;   true
 2736    ).
 2737
 2738assert_module_export(_, []) :- !.
 2739assert_module_export(Src, [H|T]) :-
 2740    !,
 2741    assert_module_export(Src, H),
 2742    assert_module_export(Src, T).
 2743assert_module_export(Src, PI) :-
 2744    pi_to_head(PI, Term),
 2745    !,
 2746    assert(exported(Term, Src)).
 2747assert_module_export(Src, op(P, A, N)) :-
 2748    xref_push_op(Src, P, A, N).
 assert_module3(+Import, +Src)
Handle 3th argument of module/3 declaration.
 2754assert_module3([], _) :- !.
 2755assert_module3([H|T], Src) :-
 2756    !,
 2757    assert_module3(H, Src),
 2758    assert_module3(T, Src).
 2759assert_module3(Option, Src) :-
 2760    process_use_module(library(dialect/Option), Src, false).
 process_predicates(:Closure, +Predicates, +Src)
Process areguments of dynamic, etc., using call(Closure, PI, Src). Handles both lists of specifications and (PI,...) specifications.
 2769process_predicates(Closure, Preds, Src) :-
 2770    is_list(Preds),
 2771    !,
 2772    process_predicate_list(Preds, Closure, Src).
 2773process_predicates(Closure, as(Preds, _Options), Src) :-
 2774    !,
 2775    process_predicates(Closure, Preds, Src).
 2776process_predicates(Closure, Preds, Src) :-
 2777    process_predicate_comma(Preds, Closure, Src).
 2778
 2779process_predicate_list([], _, _).
 2780process_predicate_list([H|T], Closure, Src) :-
 2781    (   nonvar(H)
 2782    ->  call(Closure, H, Src)
 2783    ;   true
 2784    ),
 2785    process_predicate_list(T, Closure, Src).
 2786
 2787process_predicate_comma(Var, _, _) :-
 2788    var(Var),
 2789    !.
 2790process_predicate_comma(M:(A,B), Closure, Src) :-
 2791    !,
 2792    process_predicate_comma(M:A, Closure, Src),
 2793    process_predicate_comma(M:B, Closure, Src).
 2794process_predicate_comma((A,B), Closure, Src) :-
 2795    !,
 2796    process_predicate_comma(A, Closure, Src),
 2797    process_predicate_comma(B, Closure, Src).
 2798process_predicate_comma(as(Spec, _Options), Closure, Src) :-
 2799    !,
 2800    process_predicate_comma(Spec, Closure, Src).
 2801process_predicate_comma(A, Closure, Src) :-
 2802    call(Closure, A, Src).
 2803
 2804
 2805assert_dynamic(PI, Src) :-
 2806    pi_to_head(PI, Term),
 2807    (   thread_local(Term, Src, _)  % dynamic after thread_local has
 2808    ->  true                        % no effect
 2809    ;   current_source_line(Line),
 2810        assert(dynamic(Term, Src, Line))
 2811    ).
 2812
 2813assert_thread_local(PI, Src) :-
 2814    pi_to_head(PI, Term),
 2815    current_source_line(Line),
 2816    assert(thread_local(Term, Src, Line)).
 2817
 2818assert_multifile(PI, Src) :-                    % :- multifile(Spec)
 2819    pi_to_head(PI, Term),
 2820    current_source_line(Line),
 2821    assert(multifile(Term, Src, Line)).
 2822
 2823assert_public(PI, Src) :-                       % :- public(Spec)
 2824    pi_to_head(PI, Term),
 2825    current_source_line(Line),
 2826    assert_called(Src, '<public>'(Line), Term, Line),
 2827    assert(public(Term, Src, Line)).
 2828
 2829assert_export(PI, Src) :-                       % :- export(Spec)
 2830    pi_to_head(PI, Term),
 2831    !,
 2832    assert(exported(Term, Src)).
 pi_to_head(+PI, -Head) is semidet
Translate Name/Arity or Name//Arity to a callable term. Fails if PI is not a predicate indicator.
 2839pi_to_head(Var, _) :-
 2840    var(Var), !, fail.
 2841pi_to_head(M:PI, M:Term) :-
 2842    !,
 2843    pi_to_head(PI, Term).
 2844pi_to_head(Name/Arity, Term) :-
 2845    functor(Term, Name, Arity).
 2846pi_to_head(Name//DCGArity, Term) :-
 2847    Arity is DCGArity+2,
 2848    functor(Term, Name, Arity).
 2849
 2850
 2851assert_used_class(Src, Name) :-
 2852    used_class(Name, Src),
 2853    !.
 2854assert_used_class(Src, Name) :-
 2855    assert(used_class(Name, Src)).
 2856
 2857assert_defined_class(Src, Name, _Meta, _Super, _) :-
 2858    defined_class(Name, _, _, Src, _),
 2859    !.
 2860assert_defined_class(_, _, _, -, _) :- !.               % :- pce_extend_class
 2861assert_defined_class(Src, Name, Meta, Super, Summary) :-
 2862    current_source_line(Line),
 2863    (   Summary == @(default)
 2864    ->  Atom = ''
 2865    ;   is_list(Summary)
 2866    ->  atom_codes(Atom, Summary)
 2867    ;   string(Summary)
 2868    ->  atom_concat(Summary, '', Atom)
 2869    ),
 2870    assert(defined_class(Name, Super, Atom, Src, Line)),
 2871    (   Meta = @(_)
 2872    ->  true
 2873    ;   assert_used_class(Src, Meta)
 2874    ),
 2875    assert_used_class(Src, Super).
 2876
 2877assert_defined_class(Src, Name, imported_from(_File)) :-
 2878    defined_class(Name, _, _, Src, _),
 2879    !.
 2880assert_defined_class(Src, Name, imported_from(File)) :-
 2881    assert(defined_class(Name, _, '', Src, file(File))).
 2882
 2883
 2884                /********************************
 2885                *            UTILITIES          *
 2886                ********************************/
 generalise(+Callable, -General)
Generalise a callable term.
 2892generalise(Var, Var) :-
 2893    var(Var),
 2894    !.                    % error?
 2895generalise(pce_principal:send_implementation(Id, _, _),
 2896           pce_principal:send_implementation(Id, _, _)) :-
 2897    atom(Id),
 2898    !.
 2899generalise(pce_principal:get_implementation(Id, _, _, _),
 2900           pce_principal:get_implementation(Id, _, _, _)) :-
 2901    atom(Id),
 2902    !.
 2903generalise('<directive>'(Line), '<directive>'(Line)) :- !.
 2904generalise(test(Test), test(Test)) :-
 2905    current_test_unit(_,_),
 2906    ground(Test),
 2907    !.
 2908generalise(test(Test, _), test(Test, _)) :-
 2909    current_test_unit(_,_),
 2910    ground(Test),
 2911    !.
 2912generalise('<test_unit>'(Line), '<test_unit>'(Line)) :- !.
 2913generalise(Module:Goal0, Module:Goal) :-
 2914    atom(Module),
 2915    !,
 2916    generalise(Goal0, Goal).
 2917generalise(Term0, Term) :-
 2918    callable(Term0),
 2919    generalise_term(Term0, Term).
 2920
 2921
 2922                 /*******************************
 2923                 *      SOURCE MANAGEMENT       *
 2924                 *******************************/
 2925
 2926/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2927This section of the file contains   hookable  predicates to reason about
 2928sources. The built-in code here  can  only   deal  with  files. The XPCE
 2929library(pce_prolog_xref) provides hooks to deal with XPCE objects, so we
 2930can do cross-referencing on PceEmacs edit   buffers.  Other examples for
 2931hooking can be databases, (HTTP) URIs, etc.
 2932- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2933
 2934:- multifile
 2935    prolog:xref_source_directory/2, % +Source, -Dir
 2936    prolog:xref_source_file/3.      % +Spec, -Path, +Options
 xref_source_file(+Spec, -File, +Src) is semidet
 xref_source_file(+Spec, -File, +Src, +Options) is semidet
Find named source file from Spec, relative to Src.
 2944xref_source_file(Plain, File, Source) :-
 2945    xref_source_file(Plain, File, Source, []).
 2946
 2947xref_source_file(QSpec, File, Source, Options) :-
 2948    nonvar(QSpec), QSpec = _:Spec,
 2949    !,
 2950    must_be(acyclic, Spec),
 2951    xref_source_file(Spec, File, Source, Options).
 2952xref_source_file(Spec, File, _Source, _Options) :-
 2953    is_stream(Spec), !,
 2954    File = Spec.
 2955xref_source_file(Spec, File, Source, Options) :-
 2956    nonvar(Spec),
 2957    prolog:xref_source_file(Spec, File,
 2958                            [ relative_to(Source)
 2959                            | Options
 2960                            ]),
 2961    !.
 2962xref_source_file(Plain, File, Source, Options) :-
 2963    atom(Plain),
 2964    \+ is_absolute_file_name(Plain),
 2965    (   prolog:xref_source_directory(Source, Dir)
 2966    ->  true
 2967    ;   atom(Source),
 2968        file_directory_name(Source, Dir)
 2969    ),
 2970    atomic_list_concat([Dir, /, Plain], Spec0),
 2971    absolute_file_name(Spec0, Spec),
 2972    do_xref_source_file(Spec, File, Options),
 2973    !.
 2974xref_source_file(Spec, File, Source, Options) :-
 2975    do_xref_source_file(Spec, File,
 2976                        [ relative_to(Source)
 2977                        | Options
 2978                        ]),
 2979    !.
 2980xref_source_file(_, _, _, Options) :-
 2981    option(silent(true), Options),
 2982    !,
 2983    fail.
 2984xref_source_file(Spec, _, Src, _Options) :-
 2985    verbose(Src),
 2986    print_message(warning, error(existence_error(file, Spec), _)),
 2987    fail.
 2988
 2989do_xref_source_file(Spec, File, Options) :-
 2990    nonvar(Spec),
 2991    option(file_type(Type), Options, prolog),
 2992    absolute_file_name(Spec, File0,
 2993                       [ file_type(Type),
 2994                         access(read),
 2995                         file_errors(fail)
 2996                       ]),
 2997    !,
 2998    qlf_pl_file(File0, File).
 2999do_xref_source_file(Spec, File, Options) :-
 3000    atom(Spec), % handle absolute /file/to/source.pl without sources
 3001    file_name_extension(Base, Ext, Spec),
 3002    user:prolog_file_type(Ext, source),
 3003    option(file_type(prolog), Options, prolog),
 3004    absolute_file_name(Base, File0,
 3005                       [ file_type(prolog),
 3006                         access(read),
 3007                         file_errors(fail)
 3008                       ]),
 3009    qlf_pl_file(File0, File).
 qlf_pl_file(?QlfFile, ?PlFile) is semidet
 3013qlf_pl_file(QlfFile, PlFile) :-
 3014    nonvar(QlfFile),
 3015    is_qlf_file(QlfFile),
 3016    !,
 3017    '$qlf_module'(QlfFile, Info),
 3018    #{file:PlFile} :< Info.
 3019qlf_pl_file(QlfFile, PlFile) :-
 3020    nonvar(PlFile),
 3021    !,
 3022    (   file_name_extension(Base, Ext, PlFile),
 3023        user:prolog_file_type(Ext, source)
 3024    ->  true
 3025    ),
 3026    (   user:prolog_file_type(QlfExt, qlf),
 3027        file_name_extension(Base, QlfExt, QlfFile),
 3028        exists_file(QlfFile)
 3029    ->  true
 3030    ),
 3031    '$qlf_module'(QlfFile, Info),
 3032    #{file:PlFile} :< Info,
 3033    !.
 3034qlf_pl_file(PlFile, PlFile).
 3035
 3036is_qlf_file(QlfFile) :-
 3037    file_name_extension(_, Ext, QlfFile),
 3038    user:prolog_file_type(Ext, qlf),
 3039    !.
 canonical_source(?Source, ?Src) is det
Src is the canonical version of Source if Source is given.
 3045canonical_source(Source, Src) :-
 3046    (   ground(Source)
 3047    ->  prolog_canonical_source(Source, Src)
 3048    ;   Source = Src
 3049    ).
 goal_name_arity(+Goal, -Name, -Arity)
Generalized version of functor/3 that can deal with name() goals.
 3056goal_name_arity(Goal, Name, Arity) :-
 3057    (   compound(Goal)
 3058    ->  compound_name_arity(Goal, Name, Arity)
 3059    ;   atom(Goal)
 3060    ->  Name = Goal, Arity = 0
 3061    ).
 3062
 3063generalise_term(Specific, General) :-
 3064    (   compound(Specific)
 3065    ->  compound_name_arity(Specific, Name, Arity),
 3066        compound_name_arity(General, Name, Arity)
 3067    ;   General = Specific
 3068    ).
 3069
 3070functor_name(Term, Name) :-
 3071    (   compound(Term)
 3072    ->  compound_name_arity(Term, Name, _)
 3073    ;   atom(Term)
 3074    ->  Name = Term
 3075    ).
 3076
 3077rename_goal(Goal0, Name, Goal) :-
 3078    (   compound(Goal0)
 3079    ->  compound_name_arity(Goal0, _, Arity),
 3080        compound_name_arity(Goal, Name, Arity)
 3081    ;   Goal = Name
 3082    ).
 3083
 3084
 3085                /*******************************
 3086                *           MESSAGES           *
 3087                *******************************/<
 3088
 3089:- multifile prolog:message//1.
 3090
 3091prolog:message(meta_predicate_after_call(Decl, By)) -->
 3092    { pi_head(ByPI, By) },
 3093    [ ansi(code, ':- meta_predicate(~p)', [Decl]),
 3094      ' declaration appears after call from '-[],
 3095      ansi(code, '~p', [ByPI])
 3096    ]