View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        jan@swi-prolog.org
    5    WWW:           https://www.swi-prolog.org
    6    Copyright (c)  2006-2026, 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_object_comment/4,      % ?Source, ?Object, ?Summary, ?Comment
   54            xref_object_signature/3,    % ?Source, ?Object, ?Signature
   55            xref_mode/3,                % ?Source, ?Mode, ?Det
   56            xref_option/2,              % ?Source, ?Option
   57            xref_clean/1,               % +Source
   58            xref_current_source/1,      % ?Source
   59            xref_done/2,                % +Source, -When
   60            xref_built_in/1,            % ?Callable
   61            xref_source_file/3,         % +Spec, -Path, +Source
   62            xref_source_file/4,         % +Spec, -Path, +Source, +Options
   63            xref_public_list/3,         % +File, +Src, +Options
   64            xref_public_list/4,         % +File, -Path, -Export, +Src
   65            xref_public_list/6,         % +File, -Path, -Module, -Export, -Meta, +Src
   66            xref_public_list/7,         % +File, -Path, -Module, -Export, -Public, -Meta, +Src
   67            xref_meta/3,                % +Source, +Goal, -Called
   68            xref_meta/2,                % +Goal, -Called
   69            xref_hook/1,                % ?Callable
   70                                        % XPCE class references
   71            xref_used_class/2,          % ?Source, ?ClassName
   72            xref_defined_class/3        % ?Source, ?ClassName, -How
   73          ]).   74:- autoload(library(apply),[maplist/2,partition/4,maplist/3]).   75:- use_module(library(debug),[debug/3]).   76:- autoload(library(dialect),[expects_dialect/1]).   77:- autoload(library(error),[must_be/2,instantiation_error/1]).   78:- autoload(library(lists),[member/2,append/2,append/3,select/3]).   79:- autoload(library(operators),[push_op/3]).   80:- autoload(library(option),[option/2,option/3]).   81:- autoload(library(ordsets),[ord_intersect/2,ord_intersection/3]).   82:- autoload(library(prolog_code), [pi_head/2]).   83:- autoload(library(prolog_source),
   84	    [ prolog_canonical_source/2,
   85	      prolog_open_source/2,
   86	      prolog_close_source/1,
   87	      prolog_read_source_term/4,
   88              prolog_file_directives/3
   89	    ]).   90
   91:- if(exists_source(library(shlib))).   92:- autoload(library(shlib),[current_foreign_library/2]).   93:- endif.   94:- autoload(library(solution_sequences),[distinct/2,limit/2]).   95
   96:- if(exists_source(library(pldoc))).   97:- use_module(library(pldoc), []).      % Must be loaded before doc_process
   98:- use_module(library(pldoc/doc_process)).   99
  100:- endif.  101
  102:- predicate_options(xref_source/2, 2,
  103                     [ silent(boolean),
  104                       module(atom),
  105                       register_called(oneof([all,non_iso,non_built_in])),
  106                       comments(oneof([store,collect,ignore])),
  107                       process_include(boolean),
  108                       stream(stream)
  109                     ]).  110
  111
  112:- dynamic
  113    called/5,                       % Head, Src, From, Cond, Line
  114    (dynamic)/3,                    % Head, Src, Line
  115    (thread_local)/3,               % Head, Src, Line
  116    (multifile)/3,                  % Head, Src, Line
  117    (public)/3,                     % Head, Src, Line
  118    (declared)/4,	            % Head, How, Src, Line
  119    defined/3,                      % Head, Src, Line
  120    meta_goal/3,                    % Head, Called, Src
  121    foreign/3,                      % Head, Src, Line
  122    constraint/3,                   % Head, Src, Line
  123    imported/3,                     % Head, Src, From
  124    exported/2,                     % Head, Src
  125    xmodule/2,                      % Module, Src
  126    uses_file/3,                    % Spec, Src, Path
  127    xop/2,                          % Src, Op
  128    source/2,                       % Src, Time
  129    used_class/2,                   % Name, Src
  130    defined_class/5,                % Name, Super, Summary, Src, Line
  131    (mode)/2,                       % Mode, Src
  132    xoption/2,                      % Src, Option
  133    xflag/4,                        % Name, Value, Src, Line
  134    grammar_rule/2,                 % Head, Src
  135    module_comment/3,               % Src, Title, Comment
  136    pred_comment/4,                 % Head, Src, Summary, Comment
  137    pred_comment_link/3,            % Head, Src, HeadTo
  138    pred_mode/3,                    % Head, Src, Det
  139    object_comment/4,               % Object, Src, Summary, Comment
  140    object_signature/3.             % Object, Src, Signature
  141
  142:- 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.
  179:- predicate_options(xref_source_file/4, 4,
  180                     [ file_type(oneof([txt,prolog,directory])),
  181                       silent(boolean)
  182                     ]).  183:- predicate_options(xref_public_list/3, 3,
  184                     [ path(-atom),
  185                       module(-atom),
  186                       exports(-list(any)),
  187                       public(-list(any)),
  188                       meta(-list(any)),
  189                       silent(boolean)
  190                     ]).  191
  192
  193                 /*******************************
  194                 *            HOOKS             *
  195                 *******************************/
 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).
  222:- multifile
  223    prolog:called_by/4,             % +Goal, +Module, +Context, -Called
  224    prolog:called_by/2,             % +Goal, -Called
  225    prolog:meta_goal/2,             % +Goal, -Pattern
  226    prolog:hook/1,                  % +Callable
  227    prolog:generated_predicate/1,   % :PI
  228    prolog:no_autoload_module/1,    % Module is not suitable for autoloading.
  229    prolog:xref_source_time/2.      % +Source, =Modified
  230
  231:- meta_predicate
  232    prolog:generated_predicate(:).  233
  234:- meta_predicate
  235    process_predicates(2, +, +).  236
  237                 /*******************************
  238                 *           BUILT-INS          *
  239                 *******************************/
 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.
  247hide_called(Callable, Src) :-
  248    xoption(Src, register_called(Which)),
  249    !,
  250    mode_hide_called(Which, Callable).
  251hide_called(Callable, _) :-
  252    mode_hide_called(non_built_in, Callable).
  253
  254mode_hide_called(all, _) :- !, fail.
  255mode_hide_called(non_iso, _:Goal) :-
  256    goal_name_arity(Goal, Name, Arity),
  257    current_predicate(system:Name/Arity),
  258    predicate_property(system:Goal, iso).
  259mode_hide_called(non_built_in, _:Goal) :-
  260    goal_name_arity(Goal, Name, Arity),
  261    current_predicate(system:Name/Arity),
  262    predicate_property(system:Goal, built_in).
  263mode_hide_called(non_built_in, M:Goal) :-
  264    goal_name_arity(Goal, Name, Arity),
  265    current_predicate(M:Name/Arity),
  266    predicate_property(M:Goal, built_in).
 built_in_predicate(+Callable)
True if Callable is a built-in
  272system_predicate(Goal) :-
  273    goal_name_arity(Goal, Name, Arity),
  274    current_predicate(system:Name/Arity),   % avoid autoloading
  275    predicate_property(system:Goal, built_in),
  276    !.
  277
  278
  279                /********************************
  280                *            TOPLEVEL           *
  281                ********************************/
  282
  283verbose(Src) :-
  284    \+ xoption(Src, silent(true)).
  285
  286:- thread_local
  287    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
  317xref_source(Source) :-
  318    xref_source(Source, []).
  319
  320xref_source(Source, Options) :-
  321    prolog_canonical_source(Source, Src),
  322    (   last_modified(Source, Modified)
  323    ->  (   source(Src, Modified)
  324        ->  true
  325        ;   xref_clean(Src),
  326            assert(source(Src, Modified)),
  327            do_xref(Src, Options)
  328        )
  329    ;   xref_clean(Src),
  330        get_time(Now),
  331        assert(source(Src, Now)),
  332        do_xref(Src, Options)
  333    ).
  334
  335do_xref(Src, Options) :-
  336    must_be(list, Options),
  337    setup_call_cleanup(
  338        xref_setup(Src, In, Options, State),
  339        collect(Src, Src, In, Options),
  340        xref_cleanup(State)).
  341
  342last_modified(Source, Modified) :-
  343    prolog:xref_source_time(Source, Modified),
  344    !.
  345last_modified(Source, Modified) :-
  346    atom(Source),
  347    \+ is_global_url(Source),
  348    exists_file(Source),
  349    time_file(Source, Modified).
  350
  351is_global_url(File) :-
  352    sub_atom(File, B, _, _, '://'),
  353    !,
  354    B > 1,
  355    sub_atom(File, 0, B, _, Scheme),
  356    atom_codes(Scheme, Codes),
  357    maplist(between(0'a, 0'z), Codes).
  358
  359xref_setup(Src, In, Options, state(CleanIn, Dialect, Xref, [SRef|HRefs])) :-
  360    maplist(assert_option(Src), Options),
  361    assert_default_options(Src),
  362    current_prolog_flag(emulated_dialect, Dialect),
  363    (   option(stream(Stream), Options)
  364    ->  In = Stream,
  365        CleanIn = true
  366    ;   prolog_open_source(Src, In),
  367        CleanIn = prolog_close_source(In)
  368    ),
  369    set_initial_mode(In, Options),
  370    asserta(xref_input(Src, In), SRef),
  371    set_xref(Xref),
  372    (   verbose(Src)
  373    ->  HRefs = []
  374    ;   asserta((user:thread_message_hook(_,Level,_) :-
  375                     hide_message(Level)),
  376                Ref),
  377        HRefs = [Ref]
  378    ).
  379
  380hide_message(warning).
  381hide_message(error).
  382hide_message(informational).
  383
  384assert_option(_, Var) :-
  385    var(Var),
  386    !,
  387    instantiation_error(Var).
  388assert_option(Src, silent(Boolean)) :-
  389    !,
  390    must_be(boolean, Boolean),
  391    assert(xoption(Src, silent(Boolean))).
  392assert_option(Src, register_called(Which)) :-
  393    !,
  394    must_be(oneof([all,non_iso,non_built_in]), Which),
  395    assert(xoption(Src, register_called(Which))).
  396assert_option(Src, comments(CommentHandling)) :-
  397    !,
  398    must_be(oneof([store,collect,ignore]), CommentHandling),
  399    assert(xoption(Src, comments(CommentHandling))).
  400assert_option(Src, module(Module)) :-
  401    !,
  402    must_be(atom, Module),
  403    assert(xoption(Src, module(Module))).
  404assert_option(Src, process_include(Boolean)) :-
  405    !,
  406    must_be(boolean, Boolean),
  407    assert(xoption(Src, process_include(Boolean))).
  408assert_option(_, _).
  409
  410assert_default_options(Src) :-
  411    (   xref_option_default(Opt),
  412        generalise_term(Opt, Gen),
  413        (   xoption(Src, Gen)
  414        ->  true
  415        ;   assertz(xoption(Src, Opt))
  416        ),
  417        fail
  418    ;   true
  419    ).
  420
  421xref_option_default(silent(false)).
  422xref_option_default(register_called(non_built_in)).
  423xref_option_default(comments(collect)).
  424xref_option_default(process_include(true)).
 xref_cleanup(+State) is det
Restore processing state according to the saved State.
  430xref_cleanup(state(CleanIn, Dialect, Xref, Refs)) :-
  431    call(CleanIn),
  432    set_prolog_flag(emulated_dialect, Dialect),
  433    set_prolog_flag(xref, Xref),
  434    maplist(erase, Refs).
  435
  436set_xref(Xref) :-
  437    current_prolog_flag(xref, Xref),
  438    set_prolog_flag(xref, true).
  439
  440:- meta_predicate
  441    with_xref(0).  442
  443with_xref(Goal) :-
  444    setup_call_cleanup(
  445        push_prolog_flag(xref, true),
  446        Goal,
  447        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.
  457set_initial_mode(_Stream, Options) :-
  458    option(module(Module), Options),
  459    !,
  460    '$set_source_module'(Module).
  461set_initial_mode(Stream, _) :-
  462    stream_property(Stream, file_name(Path)),
  463    source_file_property(Path, load_context(M, _, Opts)),
  464    !,
  465    '$set_source_module'(M),
  466    (   option(dialect(Dialect), Opts)
  467    ->  expects_dialect(Dialect)
  468    ;   true
  469    ).
  470set_initial_mode(_, _) :-
  471    '$set_source_module'(user).
 xref_input_stream(-Stream) is det
Current input stream for cross-referencer.
  477xref_input_stream(Stream) :-
  478    xref_input(_, Var),
  479    !,
  480    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.
  487xref_push_op(Src, P, T, N0) :-
  488    '$current_source_module'(M0),
  489    strip_module(M0:N0, M, N),
  490    (   is_list(N),
  491        N \== []
  492    ->  maplist(push_op(Src, P, T, M), N)
  493    ;   push_op(Src, P, T, M, N)
  494    ).
  495
  496push_op(Src, P, T, M0, N0) :-
  497    strip_module(M0:N0, M, N),
  498    Name = M:N,
  499    valid_op(op(P,T,Name)),
  500    push_op(P, T, Name),
  501    assert_op(Src, op(P,T,Name)),
  502    debug(xref(op), ':- ~w.', [op(P,T,Name)]).
  503
  504valid_op(op(P,T,M:N)) :-
  505    atom(M),
  506    valid_op_name(N),
  507    integer(P),
  508    between(0, 1200, P),
  509    atom(T),
  510    op_type(T).
  511
  512valid_op_name(N) :-
  513    atom(N),
  514    !.
  515valid_op_name(N) :-
  516    N == [].
  517
  518op_type(xf).
  519op_type(yf).
  520op_type(fx).
  521op_type(fy).
  522op_type(xfx).
  523op_type(xfy).
  524op_type(yfx).
 xref_set_prolog_flag(+Flag, +Value, +Src, +Line)
Called when a directive sets a Prolog flag.
  530xref_set_prolog_flag(Flag, Value, Src, Line) :-
  531    atom(Flag),
  532    !,
  533    assertz(xflag(Flag, Value, Src, Line)).
  534xref_set_prolog_flag(_, _, _, _).
 xref_clean(+Source) is det
Reset the database for the given source.
  540xref_clean(Source) :-
  541    prolog_canonical_source(Source, Src),
  542    retractall(called(_, Src, _Origin, _Cond, _Line)),
  543    retractall(dynamic(_, Src, Line)),
  544    retractall(multifile(_, Src, Line)),
  545    retractall(public(_, Src, Line)),
  546    retractall(declared(_, _, Src, Line)),
  547    retractall(defined(_, Src, Line)),
  548    retractall(meta_goal(_, _, Src)),
  549    retractall(foreign(_, Src, Line)),
  550    retractall(constraint(_, Src, Line)),
  551    retractall(imported(_, Src, _From)),
  552    retractall(exported(_, Src)),
  553    retractall(uses_file(_, Src, _)),
  554    retractall(xmodule(_, Src)),
  555    retractall(xop(Src, _)),
  556    retractall(grammar_rule(_, Src)),
  557    retractall(xoption(Src, _)),
  558    retractall(xflag(_Name, _Value, Src, Line)),
  559    retractall(source(Src, _)),
  560    retractall(used_class(_, Src)),
  561    retractall(defined_class(_, _, _, Src, _)),
  562    retractall(mode(_, Src)),
  563    retractall(module_comment(Src, _, _)),
  564    retractall(pred_comment(_, Src, _, _)),
  565    retractall(pred_comment_link(_, Src, _)),
  566    retractall(pred_mode(_, Src, _)),
  567    retractall(object_comment(_, Src, _, _)),
  568    retractall(object_signature(_, Src, _)).
  569
  570
  571                 /*******************************
  572                 *          READ RESULTS        *
  573                 *******************************/
 xref_current_source(?Source)
Check what sources have been analysed.
  579xref_current_source(Source) :-
  580    source(Source, _Time).
 xref_done(+Source, -Time) is det
Cross-reference executed at Time
  587xref_done(Source, Time) :-
  588    prolog_canonical_source(Source, Src),
  589    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.
  611xref_called(Source, Called, By) :-
  612    xref_called(Source, Called, By, _).
  613
  614xref_called(Source, Called, By, Cond) :-
  615    canonical_source(Source, Src),
  616    distinct(Called-By, called(Called, Src, By, Cond, _)).
  617
  618xref_called(Source, Called, By, Cond, Line) :-
  619    canonical_source(Source, Src),
  620    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.
  642xref_defined(Source, Called, How) :-
  643    nonvar(Source),
  644    !,
  645    canonical_source(Source, Src),
  646    xref_defined2(How, Src, Called).
  647xref_defined(Source, Called, How) :-
  648    xref_defined2(How, Src, Called),
  649    canonical_source(Source, Src).
  650
  651xref_defined2(dynamic(Line), Src, Called) :-
  652    dynamic(Called, Src, Line).
  653xref_defined2(thread_local(Line), Src, Called) :-
  654    thread_local(Called, Src, Line).
  655xref_defined2(multifile(Line), Src, Called) :-
  656    multifile(Called, Src, Line).
  657xref_defined2(public(Line), Src, Called) :-
  658    public(Called, Src, Line).
  659xref_defined2(local(Line), Src, Called) :-
  660    defined(Called, Src, Line).
  661xref_defined2(foreign(Line), Src, Called) :-
  662    foreign(Called, Src, Line).
  663xref_defined2(constraint(Line), Src, Called) :-
  664    (   constraint(Called, Src, Line)
  665    ->  true
  666    ;   declared(Called, chr_constraint, Src, Line)
  667    ).
  668xref_defined2(imported(From), Src, Called) :-
  669    imported(Called, Src, From).
  670xref_defined2(dcg, Src, Called) :-
  671    grammar_rule(Called, Src).
 xref_definition_line(+How, -Line)
If the 3th argument of xref_defined contains line info, return this in Line.
  679xref_definition_line(local(Line),        Line).
  680xref_definition_line(dynamic(Line),      Line).
  681xref_definition_line(thread_local(Line), Line).
  682xref_definition_line(multifile(Line),    Line).
  683xref_definition_line(public(Line),       Line).
  684xref_definition_line(constraint(Line),   Line).
  685xref_definition_line(foreign(Line),      Line).
 xref_exported(?Source, ?Head) is nondet
True when Source exports Head.
  692xref_exported(Source, Called) :-
  693    prolog_canonical_source(Source, Src),
  694    exported(Called, Src).
 xref_module(?Source, ?Module) is nondet
True if Module is defined in Source.
  700xref_module(Source, Module) :-
  701    nonvar(Source),
  702    !,
  703    prolog_canonical_source(Source, Src),
  704    xmodule(Module, Src).
  705xref_module(Source, Module) :-
  706    xmodule(Module, Src),
  707    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>.
  717xref_uses_file(Source, Spec, Path) :-
  718    prolog_canonical_source(Source, Src),
  719    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)
  729xref_op(Source, Op) :-
  730    prolog_canonical_source(Source, Src),
  731    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.
  739xref_prolog_flag(Source, Flag, Value, Line) :-
  740    prolog_canonical_source(Source, Src),
  741    xflag(Flag, Value, Src, Line).
  742
  743xref_built_in(Head) :-
  744    system_predicate(Head).
  745
  746xref_used_class(Source, Class) :-
  747    prolog_canonical_source(Source, Src),
  748    used_class(Class, Src).
  749
  750xref_defined_class(Source, Class, local(Line, Super, Summary)) :-
  751    prolog_canonical_source(Source, Src),
  752    defined_class(Class, Super, Summary, Src, Line),
  753    integer(Line),
  754    !.
  755xref_defined_class(Source, Class, file(File)) :-
  756    prolog_canonical_source(Source, Src),
  757    defined_class(Class, _, _, Src, file(File)).
  758
  759:- thread_local
  760    current_cond/1,
  761    source_line/1,
  762    current_test_unit/2.  763
  764current_source_line(Line) :-
  765    source_line(Var),
  766    !,
  767    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.
  775collect(Src, File, In, Options) :-
  776    (   Src == File
  777    ->  SrcSpec = Line
  778    ;   SrcSpec = (File:Line)
  779    ),
  780    (   current_prolog_flag(xref_store_comments, OldStore)
  781    ->  true
  782    ;   OldStore = false
  783    ),
  784    option(comments(CommentHandling), Options, collect),
  785    (   CommentHandling == ignore
  786    ->  CommentOptions = [],
  787        Comments = []
  788    ;   CommentHandling == store
  789    ->  CommentOptions = [ process_comment(true) ],
  790        Comments = [],
  791	set_prolog_flag(xref_store_comments, true)
  792    ;   CommentOptions = [ comments(Comments) ]
  793    ),
  794    repeat,
  795        E = error(_,_),
  796        catch(prolog_read_source_term(
  797                  In, Term, Expanded,
  798                  [ term_position(TermPos),
  799                    variable_names(VarNames)
  800                  | CommentOptions
  801                  ]),
  802              E, report_syntax_error(E, Src, [])),
  803        update_condition(Term),
  804        stream_position_data(line_count, TermPos, Line),
  805        setup_call_cleanup(
  806            asserta(source_line(SrcSpec), Ref),
  807            catch(process(Expanded, Comments, Term, VarNames, TermPos,
  808                          Src, EOF),
  809                  E, print_message(error, E)),
  810            erase(Ref)),
  811        EOF == true,
  812    !,
  813    set_prolog_flag(xref_store_comments, OldStore).
  814
  815report_syntax_error(_, _, Options) :-
  816    option(silent(true), Options),
  817    !,
  818    fail.
  819report_syntax_error(E, Src, _Options) :-
  820    (   verbose(Src)
  821    ->  print_message(error, E)
  822    ;   true
  823    ),
  824    fail.
 update_condition(+Term) is det
Update the condition under which the current code is compiled.
  830update_condition((:-Directive)) :-
  831    !,
  832    update_cond(Directive).
  833update_condition(_).
  834
  835update_cond(if(Cond)) :-
  836    !,
  837    asserta(current_cond(Cond)).
  838update_cond(else) :-
  839    retract(current_cond(C0)),
  840    !,
  841    assert(current_cond(\+C0)).
  842update_cond(elif(Cond)) :-
  843    retract(current_cond(C0)),
  844    !,
  845    assert(current_cond((\+C0,Cond))).
  846update_cond(endif) :-
  847    retract(current_cond(_)),
  848    !.
  849update_cond(_).
 current_condition(-Condition) is det
Condition is the current compilation condition as defined by the :- if/1 directive and friends.
  856current_condition(Condition) :-
  857    \+ current_cond(_),
  858    !,
  859    Condition = true.
  860current_condition(Condition) :-
  861    findall(C, current_cond(C), List),
  862    list_to_conj(List, Condition).
  863
  864list_to_conj([], true).
  865list_to_conj([C], C) :- !.
  866list_to_conj([H|T], (H,C)) :-
  867    list_to_conj(T, C).
  868
  869
  870                 /*******************************
  871                 *           PROCESS            *
  872                 *******************************/
 process(+Expanded, +Comments, +Term, +VarNames, +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:
VarNames- is a list Name=Var for the variables of Term. It is passed to the comment processing.
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.
  887process(Expanded, Comments, Term0, VarNames, TermPos, Src, EOF) :-
  888    is_list(Expanded),                          % term_expansion into list.
  889    !,
  890    (   member(Term, Expanded),
  891        process(Term, Term0, Src),
  892        Term == end_of_file
  893    ->  EOF = true
  894    ;   EOF = false
  895    ),
  896    xref_comments(Comments, TermPos, Term0, VarNames, Src).
  897process(end_of_file, _, _, _, _, _, true) :-
  898    !.
  899process(Term, Comments, Term0, VarNames, TermPos, Src, false) :-
  900    process(Term, Term0, Src),
  901    xref_comments(Comments, TermPos, Term0, VarNames, Src).
 process(+Term, +Term0, +Src) is det
  905process(_, Term0, _) :-
  906    ignore_raw_term(Term0),
  907    !.
  908process(Head :- Body, Head0 --> _, Src) :-
  909    pi_head(F/A, Head),
  910    pi_head(F/A0, Head0),
  911    A =:= A0 + 2,
  912    !,
  913    assert_grammar_rule(Src, Head),
  914    process((Head :- Body), Src).
  915process(Term, _Term0, Src) :-
  916    process(Term, Src).
  917
  918ignore_raw_term((:- predicate_options(_,_,_))).
 process(+Term, +Src) is det
  922process(Var, _) :-
  923    var(Var),
  924    !.                    % Warn?
  925process(end_of_file, _) :- !.
  926process((:- Directive), Src) :-
  927    !,
  928    process_directive(Directive, Src),
  929    !.
  930process((?- Directive), Src) :-
  931    !,
  932    process_directive(Directive, Src),
  933    !.
  934process((Head :- Body), Src) :-
  935    !,
  936    assert_defined(Src, Head),
  937    process_body(Body, Head, Src).
  938process((Left => Body), Src) :-
  939    !,
  940    (   nonvar(Left),
  941        Left = (Head, Guard)
  942    ->  assert_defined(Src, Head),
  943        process_body(Guard, Head, Src),
  944        process_body(Body, Head, Src)
  945    ;   assert_defined(Src, Left),
  946        process_body(Body, Left, Src)
  947    ).
  948process(?=>(Head, Body), Src) :-
  949    !,
  950    assert_defined(Src, Head),
  951    process_body(Body, Head, Src).
  952process('$source_location'(_File, _Line):Clause, Src) :-
  953    !,
  954    process(Clause, Src).
  955process(Term, Src) :-
  956    process_chr(Term, Src),
  957    !.
  958process(M:(Head :- Body), Src) :-
  959    !,
  960    process((M:Head :- M:Body), Src).
  961process(Head, Src) :-
  962    assert_defined(Src, Head).
  963
  964
  965                 /*******************************
  966                 *            COMMENTS          *
  967                 *******************************/
 xref_comments(+Comments, +FilePos, +Term, +VarNames, +Src) is det
Process the structured comments before Term. The last comment before Term is parsed with Term and VarNames, a list Name=Var for the variables of Term.
  975xref_comments([], _Pos, _Term, _VarNames, _Src).
  976:- if(current_predicate(parse_comment/5)).  977xref_comments([Pos-Comment|T], TermPos, Term, VarNames, Src) :-
  978    (   Pos @> TermPos              % comments inside term
  979    ->  true
  980    ;   stream_position_data(line_count, Pos, Line),
  981        FilePos = Src:Line,
  982        (   last_comment(T, TermPos)
  983        ->  CTerm = Term
  984        ;   true
  985        ),
  986        (   parse_comment(Comment, FilePos, CTerm, VarNames, Parsed)
  987        ->  assert_comments(Parsed, Src)
  988        ;   true
  989        ),
  990        xref_comments(T, TermPos, Term, VarNames, Src)
  991    ).
  992
  993last_comment([], _).
  994last_comment([Pos-_|_], TermPos) :-
  995    Pos @> TermPos.
  996
  997assert_comments([], _).
  998assert_comments([H|T], Src) :-
  999    assert_comment(H, Src),
 1000    assert_comments(T, Src).
 1001
 1002assert_comment(section(Id, Title, Comment), Src) :-
 1003    (   Id = module(_)
 1004    ->  assertz(module_comment(Src, Title, Comment))
 1005    ;   true
 1006    ).
 1007assert_comment(predicate(PI, Summary, Comment), Src) :-
 1008    pi_to_head(PI, Src, Head),
 1009    assertz(pred_comment(Head, Src, Summary, Comment)).
 1010assert_comment(link(PI, PITo), Src) :-
 1011    pi_to_head(PI, Src, Head),
 1012    pi_to_head(PITo, Src, HeadTo),
 1013    assertz(pred_comment_link(Head, Src, HeadTo)).
 1014assert_comment(mode(Head, Det), Src) :-
 1015    assertz(pred_mode(Head, Src, Det)).
 1016assert_comment(object(Object, Summary, Comment), Src) :-
 1017    assertz(object_comment(Object, Src, Summary, Comment)).
 1018assert_comment(signature(Object, Signature), Src) :-
 1019    assertz(object_signature(Object, Src, Signature)).
 1020
 1021pi_to_head(PI, Src, Head) :-
 1022    pi_to_head(PI, Head0),
 1023    (   Head0 = _:_
 1024    ->  strip_module(Head0, M, Plain),
 1025        (   xmodule(M, Src)
 1026        ->  Head = Plain
 1027        ;   Head = M:Plain
 1028        )
 1029    ;   Head = Head0
 1030    ).
 1031:- endif.
 xref_comment(?Source, ?Title, ?Comment) is nondet
Is true when Source has a section comment with Title and Comment
 1037xref_comment(Source, Title, Comment) :-
 1038    canonical_source(Source, Src),
 1039    module_comment(Src, Title, Comment).
 xref_comment(?Source, ?Head, ?Summary, ?Comment) is nondet
Is true when Head in Source has the given PlDoc comment.
 1045xref_comment(Source, Head, Summary, Comment) :-
 1046    canonical_source(Source, Src),
 1047    (   pred_comment(Head, Src, Summary, Comment)
 1048    ;   pred_comment_link(Head, Src, HeadTo),
 1049        pred_comment(HeadTo, Src, Summary, Comment)
 1050    ).
 xref_object_comment(?Source, ?Object, ?Summary, ?Comment) is nondet
Is true when Object in Source has the given PlDoc comment. Such objects are created by the hook doc_compile_comment/5, e.g., xpce(Class, Kind, Name) for the members of xpce classes.
 1058xref_object_comment(Source, Object, Summary, Comment) :-
 1059    canonical_source(Source, Src),
 1060    object_comment(Object, Src, Summary, Comment).
 xref_object_signature(?Source, ?Object, ?Signature) is nondet
Is true when Object in Source has Signature as provided by the hook doc_compile_comment/5.
 1067xref_object_signature(Source, Object, Signature) :-
 1068    canonical_source(Source, Src),
 1069    object_signature(Object, Src, Signature).
 xref_mode(?Source, ?Mode, ?Det) is nondet
Is true when Source provides a predicate with Mode and determinism.
 1076xref_mode(Source, Mode, Det) :-
 1077    canonical_source(Source, Src),
 1078    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.
 1085xref_option(Source, Option) :-
 1086    canonical_source(Source, Src),
 1087    xoption(Src, Option).
 1088
 1089
 1090                 /********************************
 1091                 *           DIRECTIVES         *
 1092                 ********************************/
 1093
 1094process_directive(Var, _) :-
 1095    var(Var),
 1096    !.                    % error, but that isn't our business
 1097process_directive(Dir, _Src) :-
 1098    debug(xref(directive), 'Processing :- ~q', [Dir]),
 1099    fail.
 1100process_directive((A,B), Src) :-       % TBD: what about other control
 1101    !,
 1102    process_directive(A, Src),      % structures?
 1103    process_directive(B, Src).
 1104process_directive(List, Src) :-
 1105    is_list(List),
 1106    !,
 1107    process_directive(consult(List), Src).
 1108process_directive(use_module(File, Import), Src) :-
 1109    process_use_module2(File, Import, Src, false).
 1110process_directive(autoload(File, Import), Src) :-
 1111    process_use_module2(File, Import, Src, false).
 1112process_directive(require(Import), Src) :-
 1113    process_requires(Import, Src).
 1114process_directive(expects_dialect(Dialect), Src) :-
 1115    process_directive(use_module(library(dialect/Dialect)), Src),
 1116    expects_dialect(Dialect).
 1117process_directive(reexport(File, Import), Src) :-
 1118    process_use_module2(File, Import, Src, true).
 1119process_directive(reexport(Modules), Src) :-
 1120    process_use_module(Modules, Src, true).
 1121process_directive(autoload(Modules), Src) :-
 1122    process_use_module(Modules, Src, false).
 1123process_directive(use_module(Modules), Src) :-
 1124    process_use_module(Modules, Src, false).
 1125process_directive(consult(Modules), Src) :-
 1126    process_use_module(Modules, Src, false).
 1127process_directive(ensure_loaded(Modules), Src) :-
 1128    process_use_module(Modules, Src, false).
 1129process_directive(load_files(Files, _Options), Src) :-
 1130    process_use_module(Files, Src, false).
 1131process_directive(include(Files), Src) :-
 1132    process_include(Files, Src).
 1133process_directive(dynamic(Dynamic), Src) :-
 1134    process_predicates(assert_dynamic, Dynamic, Src).
 1135process_directive(dynamic(Dynamic, _Options), Src) :-
 1136    process_predicates(assert_dynamic, Dynamic, Src).
 1137process_directive(thread_local(Dynamic), Src) :-
 1138    process_predicates(assert_thread_local, Dynamic, Src).
 1139process_directive(multifile(Dynamic), Src) :-
 1140    process_predicates(assert_multifile, Dynamic, Src).
 1141process_directive(public(Public), Src) :-
 1142    process_predicates(assert_public, Public, Src).
 1143process_directive(export(Export), Src) :-
 1144    process_predicates(assert_export, Export, Src).
 1145process_directive(import(Import), Src) :-
 1146    process_import(Import, Src).
 1147process_directive(module(Module, Export), Src) :-
 1148    assert_module(Src, Module),
 1149    assert_module_export(Src, Export).
 1150process_directive(module(Module, Export, Import), Src) :-
 1151    assert_module(Src, Module),
 1152    assert_module_export(Src, Export),
 1153    assert_module3(Import, Src).
 1154process_directive(begin_tests(Unit, _Options), Src) :-
 1155    enter_test_unit(Unit, Src).
 1156process_directive(begin_tests(Unit), Src) :-
 1157    enter_test_unit(Unit, Src).
 1158process_directive(end_tests(Unit), Src) :-
 1159    leave_test_unit(Unit, Src).
 1160process_directive('$set_source_module'(system), Src) :-
 1161    assert_module(Src, system).     % hack for handling boot/init.pl
 1162process_directive(pce_begin_class_definition(Name, Meta, Super, Doc), Src) :-
 1163    assert_defined_class(Src, Name, Meta, Super, Doc).
 1164process_directive(pce_autoload(Name, From), Src) :-
 1165    assert_defined_class(Src, Name, imported_from(From)).
 1166
 1167process_directive(op(P, A, N), Src) :-
 1168    xref_push_op(Src, P, A, N).
 1169process_directive(set_prolog_flag(Flag, Value), Src) :-
 1170    (   Flag == character_escapes
 1171    ->  set_prolog_flag(character_escapes, Value)
 1172    ;   true
 1173    ),
 1174    current_source_line(Line),
 1175    xref_set_prolog_flag(Flag, Value, Src, Line).
 1176process_directive(style_check(X), _) :-
 1177    style_check(X).
 1178process_directive(encoding(Enc), _) :-
 1179    (   xref_input_stream(Stream)
 1180    ->  catch(set_stream(Stream, encoding(Enc)), error(_,_), true)
 1181    ;   true                        % can this happen?
 1182    ).
 1183process_directive(pce_expansion:push_compile_operators, _) :-
 1184    '$current_source_module'(SM),
 1185    call(pce_expansion:push_compile_operators(SM)). % call to avoid xref
 1186process_directive(pce_expansion:pop_compile_operators, _) :-
 1187    call(pce_expansion:pop_compile_operators).
 1188process_directive(meta_predicate(Meta), Src) :-
 1189    process_meta_predicate(Meta, Src).
 1190process_directive(arithmetic_function(FSpec), Src) :-
 1191    arith_callable(FSpec, Goal),
 1192    !,
 1193    current_source_line(Line),
 1194    assert_called(Src, '<directive>'(Line), Goal, Line).
 1195process_directive(format_predicate(_, Goal), Src) :-
 1196    !,
 1197    current_source_line(Line),
 1198    assert_called(Src, '<directive>'(Line), Goal, Line).
 1199process_directive(if(Cond), Src) :-
 1200    !,
 1201    current_source_line(Line),
 1202    assert_called(Src, '<directive>'(Line), Cond, Line).
 1203process_directive(elif(Cond), Src) :-
 1204    !,
 1205    current_source_line(Line),
 1206    assert_called(Src, '<directive>'(Line), Cond, Line).
 1207process_directive(else, _) :- !.
 1208process_directive(endif, _) :- !.
 1209process_directive(Goal, Src) :-
 1210    current_source_line(Line),
 1211    process_body(Goal, '<directive>'(Line), Src).
 process_meta_predicate(+Decl, +Src)
Create meta_goal/3 facts from the meta-goal declaration.
 1217process_meta_predicate((A,B), Src) :-
 1218    !,
 1219    process_meta_predicate(A, Src),
 1220    process_meta_predicate(B, Src).
 1221process_meta_predicate(Decl, Src) :-
 1222    process_meta_head(Src, Decl).
 1223
 1224process_meta_head(Src, Decl) :-         % swapped arguments for maplist
 1225    compound(Decl),
 1226    compound_name_arity(Decl, Name, Arity),
 1227    compound_name_arity(Head, Name, Arity),
 1228    meta_args(1, Arity, Decl, Head, Meta),
 1229    (   (   prolog:meta_goal(Head, _)
 1230        ;   prolog:called_by(Head, _, _, _)
 1231        ;   prolog:called_by(Head, _)
 1232        ;   meta_goal(Head, Meta, _Src)
 1233        )
 1234    ->  true
 1235    ;   warn_late_meta_predicate(Decl, Src),
 1236        retractall(meta_goal(Head, _, Src)),
 1237        assert(meta_goal(Head, Meta, Src))
 1238    ).
 1239
 1240meta_args(I, Arity, _, _, []) :-
 1241    I > Arity,
 1242    !.
 1243meta_args(I, Arity, Decl, Head, [H|T]) :-               % 0
 1244    arg(I, Decl, 0),
 1245    !,
 1246    arg(I, Head, H),
 1247    I2 is I + 1,
 1248    meta_args(I2, Arity, Decl, Head, T).
 1249meta_args(I, Arity, Decl, Head, [H|T]) :-               % ^
 1250    arg(I, Decl, ^),
 1251    !,
 1252    arg(I, Head, EH),
 1253    setof_goal(EH, H),
 1254    I2 is I + 1,
 1255    meta_args(I2, Arity, Decl, Head, T).
 1256meta_args(I, Arity, Decl, Head, [//(H)|T]) :-
 1257    arg(I, Decl, //),
 1258    !,
 1259    arg(I, Head, H),
 1260    I2 is I + 1,
 1261    meta_args(I2, Arity, Decl, Head, T).
 1262meta_args(I, Arity, Decl, Head, [H+A|T]) :-             % I --> H+I
 1263    arg(I, Decl, A),
 1264    integer(A), A > 0,
 1265    !,
 1266    arg(I, Head, H),
 1267    I2 is I + 1,
 1268    meta_args(I2, Arity, Decl, Head, T).
 1269meta_args(I, Arity, Decl, Head, Meta) :-
 1270    I2 is I + 1,
 1271    meta_args(I2, Arity, Decl, Head, Meta).
 1272
 1273
 1274warn_late_meta_predicate(Decl, Src) :-
 1275    xref_called(Src, Decl, By),
 1276    !,
 1277    print_message(warning, meta_predicate_after_call(Decl, By)).
 1278warn_late_meta_predicate(_, _).
 1279
 1280
 1281              /********************************
 1282              *             BODY              *
 1283              ********************************/
 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).
 1292xref_meta(Source, Head, Called) :-
 1293    canonical_source(Source, Src),
 1294    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.
 1309xref_meta_src(Head, Called, Src) :-
 1310    meta_goal(Head, Called, Src),
 1311    !.
 1312xref_meta_src(Head, Called, _) :-
 1313    xref_meta(Head, Called),
 1314    !.
 1315xref_meta_src(Head, Called, _) :-
 1316    compound(Head),
 1317    compound_name_arity(Head, Name, Arity),
 1318    apply_pred(Name),
 1319    Arity > 5,
 1320    !,
 1321    Extra is Arity - 1,
 1322    arg(1, Head, G),
 1323    Called = [G+Extra].
 1324xref_meta_src(Head, Called, _) :-
 1325    with_xref(predicate_property('$xref_tmp':Head, meta_predicate(Meta))),
 1326    !,
 1327    Meta =.. [_|Args],
 1328    meta_args(Args, 1, Head, Called).
 1329
 1330meta_args([], _, _, []).
 1331meta_args([H0|T0], I, Head, [H|T]) :-
 1332    xargs(H0, N),
 1333    !,
 1334    arg(I, Head, A),
 1335    (   N == 0
 1336    ->  H = A
 1337    ;   H = (A+N)
 1338    ),
 1339    I2 is I+1,
 1340    meta_args(T0, I2, Head, T).
 1341meta_args([_|T0], I, Head, T) :-
 1342    I2 is I+1,
 1343    meta_args(T0, I2, Head, T).
 1344
 1345xargs(N, N) :- integer(N), !.
 1346xargs(//, 2).
 1347xargs(^, 0).
 1348
 1349apply_pred(call).                               % built-in
 1350apply_pred(maplist).                            % library(apply_macros)
 1351
 1352xref_meta((A, B),               [A, B]).
 1353xref_meta((A; B),               [A, B]).
 1354xref_meta((A| B),               [A, B]).
 1355xref_meta((A -> B),             [A, B]).
 1356xref_meta((A *-> B),            [A, B]).
 1357xref_meta(findall(_V,G,_L),     [G]).
 1358xref_meta(findall(_V,G,_L,_T),  [G]).
 1359xref_meta(findnsols(_N,_V,G,_L),    [G]).
 1360xref_meta(findnsols(_N,_V,G,_L,_T), [G]).
 1361xref_meta(setof(_V, EG, _L),    [G]) :-
 1362    setof_goal(EG, G).
 1363xref_meta(bagof(_V, EG, _L),    [G]) :-
 1364    setof_goal(EG, G).
 1365xref_meta(aggregate(_V, EG, _L), [G]) :-
 1366    setof_goal(EG, G).
 1367xref_meta(aggregate(_V, _D, EG, _L), [G]) :-
 1368    setof_goal(EG, G).
 1369xref_meta(forall(A, B),         [A, B]).
 1370xref_meta(maplist(G,_),         [G+1]).
 1371xref_meta(maplist(G,_,_),       [G+2]).
 1372xref_meta(maplist(G,_,_,_),     [G+3]).
 1373xref_meta(maplist(G,_,_,_,_),   [G+4]).
 1374xref_meta(map_list_to_pairs(G,_,_), [G+2]).
 1375xref_meta(map_assoc(G, _),      [G+1]).
 1376xref_meta(map_assoc(G, _, _),   [G+2]).
 1377xref_meta(checklist(G, _L),     [G+1]).
 1378xref_meta(sublist(G, _, _),     [G+1]).
 1379xref_meta(include(G, _, _),     [G+1]).
 1380xref_meta(exclude(G, _, _),     [G+1]).
 1381xref_meta(partition(G, _, _, _, _),     [G+2]).
 1382xref_meta(partition(G, _, _, _),[G+1]).
 1383xref_meta(call(G),              [G]).
 1384xref_meta(call(G, _),           [G+1]).
 1385xref_meta(call(G, _, _),        [G+2]).
 1386xref_meta(call(G, _, _, _),     [G+3]).
 1387xref_meta(call(G, _, _, _, _),  [G+4]).
 1388xref_meta(not(G),               [G]).
 1389xref_meta(notrace(G),           [G]).
 1390xref_meta('$notrace'(G),        [G]).
 1391xref_meta(\+(G),                [G]).
 1392xref_meta(ignore(G),            [G]).
 1393xref_meta(once(G),              [G]).
 1394xref_meta(initialization(G),    [G]).
 1395xref_meta(initialization(G,_),  [G]).
 1396xref_meta(retract(Rule),        [G]) :- head_of(Rule, G).
 1397xref_meta(clause(G, _),         [G]).
 1398xref_meta(clause(G, _, _),      [G]).
 1399xref_meta(phrase(G, _A),        [//(G)]).
 1400xref_meta(phrase(G, _A, _R),    [//(G)]).
 1401xref_meta(call_dcg(G, _A, _R),  [//(G)]).
 1402xref_meta(phrase_from_file(G,_),[//(G)]).
 1403xref_meta(catch(A, _, B),       [A, B]).
 1404xref_meta(catch_with_backtrace(A, _, B), [A, B]).
 1405xref_meta(thread_create(A,_,_), [A]).
 1406xref_meta(thread_create(A,_),   [A]).
 1407xref_meta(thread_signal(_,A),   [A]).
 1408xref_meta(thread_idle(A,_),     [A]).
 1409xref_meta(thread_at_exit(A),    [A]).
 1410xref_meta(thread_initialization(A), [A]).
 1411xref_meta(engine_create(_,A,_), [A]).
 1412xref_meta(engine_create(_,A,_,_), [A]).
 1413xref_meta(transaction(A),       [A]).
 1414xref_meta(transaction(A,B,_),   [A,B]).
 1415xref_meta(snapshot(A),          [A]).
 1416xref_meta(predsort(A,_,_),      [A+3]).
 1417xref_meta(call_cleanup(A, B),   [A, B]).
 1418xref_meta(call_cleanup(A, _, B),[A, B]).
 1419xref_meta(setup_call_cleanup(A, B, C),[A, B, C]).
 1420xref_meta(setup_call_catcher_cleanup(A, B, _, C),[A, B, C]).
 1421xref_meta(call_residue_vars(A,_), [A]).
 1422xref_meta(with_mutex(_,A),      [A]).
 1423xref_meta(assume(G),            [G]).   % library(debug)
 1424xref_meta(assertion(G),         [G]).   % library(debug)
 1425xref_meta(freeze(_, G),         [G]).
 1426xref_meta(when(C, A),           [C, A]).
 1427xref_meta(time(G),              [G]).   % development system
 1428xref_meta(call_time(G, _),      [G]).   % development system
 1429xref_meta(call_time(G, _, _),   [G]).   % development system
 1430xref_meta(profile(G),           [G]).
 1431xref_meta(at_halt(G),           [G]).
 1432xref_meta(call_with_time_limit(_, G), [G]).
 1433xref_meta(call_with_depth_limit(G, _, _), [G]).
 1434xref_meta(call_with_inference_limit(G, _, _), [G]).
 1435xref_meta(alarm(_, G, _),       [G]).
 1436xref_meta(alarm(_, G, _, _),    [G]).
 1437xref_meta('$add_directive_wic'(G), [G]).
 1438xref_meta(with_output_to(_, G), [G]).
 1439xref_meta(if(G),                [G]).
 1440xref_meta(elif(G),              [G]).
 1441xref_meta(meta_options(G,_,_),  [G+1]).
 1442xref_meta(on_signal(_,_,H),     [H+1]) :- H \== default.
 1443xref_meta(distinct(G),          [G]).   % library(solution_sequences)
 1444xref_meta(distinct(_, G),       [G]).
 1445xref_meta(order_by(_, G),       [G]).
 1446xref_meta(limit(_, G),          [G]).
 1447xref_meta(offset(_, G),         [G]).
 1448xref_meta(reset(G,_,_),         [G]).
 1449xref_meta(prolog_listen(Ev,G),  [G+N]) :- event_xargs(Ev, N).
 1450xref_meta(prolog_listen(Ev,G,_),[G+N]) :- event_xargs(Ev, N).
 1451xref_meta(tnot(G),		[G]).
 1452xref_meta(not_exists(G),	[G]).
 1453xref_meta(with_tty_raw(G),	[G]).
 1454xref_meta(residual_goals(G),    [G+2]).
 1455
 1456                                        % XPCE meta-predicates
 1457xref_meta(pce_global(_, new(_)), _) :- !, fail.
 1458xref_meta(pce_global(_, B),     [B+1]).
 1459xref_meta(ifmaintainer(G),      [G]).   % used in manual
 1460xref_meta(listen(_, G),         [G]).   % library(broadcast)
 1461xref_meta(listen(_, _, G),      [G]).
 1462xref_meta(in_pce_thread(G),     [G]).
 1463
 1464xref_meta(G, Meta) :-                   % call user extensions
 1465    prolog:meta_goal(G, Meta).
 1466xref_meta(G, Meta) :-                   % Generated from :- meta_predicate
 1467    meta_goal(G, Meta, _Src).
 1468
 1469setof_goal(EG, G) :-
 1470    var(EG), !, G = EG.
 1471setof_goal(_^EG, G) :-
 1472    !,
 1473    setof_goal(EG, G).
 1474setof_goal(G, G).
 1475
 1476event_xargs(abort,            0).
 1477event_xargs(erase,            1).
 1478event_xargs(break,            3).
 1479event_xargs(frame_finished,   1).
 1480event_xargs(thread_exit,      1).
 1481event_xargs(this_thread_exit, 0).
 1482event_xargs(PI,               2) :- pi_to_head(PI, _).
 head_of(+Rule, -Head)
Get the head for a retract call.
 1488head_of(Var, _) :-
 1489    var(Var), !, fail.
 1490head_of((Head :- _), Head).
 1491head_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.
 1499xref_hook(Hook) :-
 1500    prolog:hook(Hook).
 1501xref_hook(Hook) :-
 1502    hook(Hook).
 1503
 1504
 1505hook(attr_portray_hook(_,_)).
 1506hook(attr_unify_hook(_,_)).
 1507hook(attribute_goals(_,_,_)).
 1508hook(goal_expansion(_,_)).
 1509hook(term_expansion(_,_)).
 1510hook(goal_expansion(_,_,_,_)).
 1511hook(term_expansion(_,_,_,_)).
 1512hook(resource(_,_,_)).
 1513hook('$pred_option'(_,_,_,_)).
 1514hook('$nowarn_autoload'(_,_)).
 1515
 1516hook(emacs_prolog_colours:goal_classification(_,_)).
 1517hook(emacs_prolog_colours:goal_colours(_,_)).
 1518hook(emacs_prolog_colours:identify(_,_)).
 1519hook(emacs_prolog_colours:style(_,_)).
 1520hook(emacs_prolog_colours:term_colours(_,_)).
 1521hook(pce_principal:get_implementation(_,_,_,_)).
 1522hook(pce_principal:pce_class(_,_,_,_,_,_)).
 1523hook(pce_principal:pce_lazy_get_method(_,_,_)).
 1524hook(pce_principal:pce_lazy_send_method(_,_,_)).
 1525hook(pce_principal:pce_uses_template(_,_)).
 1526hook(pce_principal:send_implementation(_,_,_)).
 1527hook(predicate_options:option_decl(_,_,_)).
 1528hook(prolog:debug_control_hook(_)).
 1529hook(prolog:error_message(_,_,_)).
 1530hook(prolog:expand_answer(_,_,_)).
 1531hook(prolog:general_exception(_,_)).
 1532hook(prolog:help_hook(_)).
 1533hook(prolog:locate_clauses(_,_)).
 1534hook(prolog:message(_,_,_)).
 1535hook(prolog:message_context(_,_,_)).
 1536hook(prolog:message_line_element(_,_)).
 1537hook(prolog:message_location(_,_,_)).
 1538hook(prolog:predicate_summary(_,_)).
 1539hook(prolog:prolog_exception_hook(_,_,_,_,_)).
 1540hook(prolog:residual_goals(_,_)).
 1541hook(prolog_edit:load).
 1542hook(prolog_edit:locate(_,_,_)).
 1543hook(sandbox:safe_directive(_)).
 1544hook(sandbox:safe_global_variable(_)).
 1545hook(sandbox:safe_meta(_,_)).
 1546hook(sandbox:safe_meta_predicate(_)).
 1547hook(sandbox:safe_primitive(_)).
 1548hook(sandbox:safe_prolog_flag(_,_)).
 1549hook(shlib:unload_all_foreign_libraries).
 1550hook(system:'$foreign_registered'(_, _)).
 1551hook(user:exception(_,_,_)).
 1552hook(user:expand_answer(_,_)).
 1553hook(user:expand_query(_,_,_,_)).
 1554hook(user:file_search_path(_,_)).
 1555hook(user:library_directory(_)).
 1556hook(user:message_hook(_,_,_)).
 1557hook(prolog:message_action(_,_)).
 1558hook(user:portray(_)).
 1559hook(user:prolog_clause_name(_,_)).
 1560hook(user:prolog_list_goal(_)).
 1561hook(user:prolog_predicate_name(_,_)).
 1562hook(user:prolog_trace_interception(_,_,_,_)).
 arith_callable(+Spec, -Callable)
Translate argument of arithmetic_function/1 into a callable term
 1568arith_callable(Var, _) :-
 1569    var(Var), !, fail.
 1570arith_callable(Module:Spec, Module:Goal) :-
 1571    !,
 1572    arith_callable(Spec, Goal).
 1573arith_callable(Name/Arity, Goal) :-
 1574    PredArity is Arity + 1,
 1575    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.

 1586process_body(Body, Origin, Src) :-
 1587    forall(limit(100, process_goal(Body, Origin, Src, _Partial)),
 1588           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.
 1595process_goal(Var, _, _, _) :-
 1596    var(Var),
 1597    !.
 1598process_goal(_:Goal, _, _, _) :-
 1599    var(Goal),
 1600    !.
 1601process_goal(Goal, Origin, Src, P) :-
 1602    Goal = (_,_),                               % problems
 1603    !,
 1604    phrase(conjunction(Goal), Goals),
 1605    process_conjunction(Goals, Origin, Src, P).
 1606process_goal(Goal, Origin, Src, _) :-           % Final disjunction, no
 1607    Goal = (_;_),                               % problems
 1608    !,
 1609    phrase(disjunction(Goal), Goals),
 1610    forall(member(G, Goals),
 1611           process_body(G, Origin, Src)).
 1612process_goal(Goal, Origin, Src, P) :-
 1613    (   (   xmodule(M, Src)
 1614        ->  true
 1615        ;   M = user
 1616        ),
 1617        pi_head(PI, M:Goal),
 1618        (   current_predicate(PI),
 1619            predicate_property(M:Goal, imported_from(IM))
 1620        ->  true
 1621        ;   PI = M:Name/Arity,
 1622            '$find_library'(M, Name, Arity, IM, _Library)
 1623        ->  true
 1624        ;   IM = M
 1625        ),
 1626        prolog:called_by(Goal, IM, M, Called)
 1627    ;   prolog:called_by(Goal, Called)
 1628    ),
 1629    !,
 1630    must_be(list, Called),
 1631    current_source_line(Here),
 1632    assert_called(Src, Origin, Goal, Here),
 1633    process_called_list(Called, Origin, Src, P).
 1634process_goal(Goal, Origin, Src, _) :-
 1635    process_xpce_goal(Goal, Origin, Src),
 1636    !.
 1637process_goal(load_foreign_library(File), _Origin, Src, _) :-
 1638    process_foreign(File, Src).
 1639process_goal(load_foreign_library(File, _Init), _Origin, Src, _) :-
 1640    process_foreign(File, Src).
 1641process_goal(use_foreign_library(File), _Origin, Src, _) :-
 1642    process_foreign(File, Src).
 1643process_goal(use_foreign_library(File, _Init), _Origin, Src, _) :-
 1644    process_foreign(File, Src).
 1645process_goal(Goal, Origin, Src, P) :-
 1646    xref_meta_src(Goal, Metas, Src),
 1647    !,
 1648    current_source_line(Here),
 1649    assert_called(Src, Origin, Goal, Here),
 1650    process_called_list(Metas, Origin, Src, P).
 1651process_goal(Goal, Origin, Src, _) :-
 1652    asserting_goal(Goal, Rule),
 1653    !,
 1654    current_source_line(Here),
 1655    assert_called(Src, Origin, Goal, Here),
 1656    process_assert(Rule, Origin, Src).
 1657process_goal(Goal, Origin, Src, P) :-
 1658    partial_evaluate(Goal, P),
 1659    current_source_line(Here),
 1660    assert_called(Src, Origin, Goal, Here).
 1661
 1662disjunction(Var)   --> {var(Var), !}, [Var].
 1663disjunction((A;B)) --> !, disjunction(A), disjunction(B).
 1664disjunction(G)     --> [G].
 1665
 1666conjunction(Var)   --> {var(Var), !}, [Var].
 1667conjunction((A,B)) --> !, conjunction(A), conjunction(B).
 1668conjunction(G)     --> [G].
 1669
 1670shares_vars(RVars, T) :-
 1671    term_variables(T, TVars0),
 1672    sort(TVars0, TVars),
 1673    ord_intersect(RVars, TVars).
 1674
 1675process_conjunction([], _, _, _).
 1676process_conjunction([Disj|Rest], Origin, Src, P) :-
 1677    nonvar(Disj),
 1678    Disj = (_;_),
 1679    Rest \== [],
 1680    !,
 1681    phrase(disjunction(Disj), Goals),
 1682    term_variables(Rest, RVars0),
 1683    sort(RVars0, RVars),
 1684    partition(shares_vars(RVars), Goals, Sharing, NonSHaring),
 1685    forall(member(G, NonSHaring),
 1686           process_body(G, Origin, Src)),
 1687    (   Sharing == []
 1688    ->  true
 1689    ;   maplist(term_variables, Sharing, GVars0),
 1690        append(GVars0, GVars1),
 1691        sort(GVars1, GVars),
 1692        ord_intersection(GVars, RVars, SVars),
 1693        VT =.. [v|SVars],
 1694        findall(VT,
 1695                (   member(G, Sharing),
 1696                    process_goal(G, Origin, Src, PS),
 1697                    PS == true
 1698                ),
 1699                Alts0),
 1700        (   Alts0 == []
 1701        ->  true
 1702        ;   (   true
 1703            ;   P = true,
 1704                sort(Alts0, Alts1),
 1705                variants(Alts1, 10, Alts),
 1706                member(VT, Alts)
 1707            )
 1708        )
 1709    ),
 1710    process_conjunction(Rest, Origin, Src, P).
 1711process_conjunction([H|T], Origin, Src, P) :-
 1712    process_goal(H, Origin, Src, P),
 1713    process_conjunction(T, Origin, Src, P).
 1714
 1715
 1716process_called_list([], _, _, _).
 1717process_called_list([H|T], Origin, Src, P) :-
 1718    process_meta(H, Origin, Src, P),
 1719    process_called_list(T, Origin, Src, P).
 1720
 1721process_meta(A+N, Origin, Src, P) :-
 1722    !,
 1723    (   extend(A, N, AX)
 1724    ->  process_goal(AX, Origin, Src, P)
 1725    ;   true
 1726    ).
 1727process_meta(//(A), Origin, Src, P) :-
 1728    !,
 1729    process_dcg_goal(A, Origin, Src, P).
 1730process_meta(G, Origin, Src, P) :-
 1731    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.
 1738process_dcg_goal(Var, _, _, _) :-
 1739    var(Var),
 1740    !.
 1741process_dcg_goal((A,B), Origin, Src, P) :-
 1742    !,
 1743    process_dcg_goal(A, Origin, Src, P),
 1744    process_dcg_goal(B, Origin, Src, P).
 1745process_dcg_goal((A;B), Origin, Src, P) :-
 1746    !,
 1747    process_dcg_goal(A, Origin, Src, P),
 1748    process_dcg_goal(B, Origin, Src, P).
 1749process_dcg_goal((A|B), Origin, Src, P) :-
 1750    !,
 1751    process_dcg_goal(A, Origin, Src, P),
 1752    process_dcg_goal(B, Origin, Src, P).
 1753process_dcg_goal((A->B), Origin, Src, P) :-
 1754    !,
 1755    process_dcg_goal(A, Origin, Src, P),
 1756    process_dcg_goal(B, Origin, Src, P).
 1757process_dcg_goal((A*->B), Origin, Src, P) :-
 1758    !,
 1759    process_dcg_goal(A, Origin, Src, P),
 1760    process_dcg_goal(B, Origin, Src, P).
 1761process_dcg_goal({Goal}, Origin, Src, P) :-
 1762    !,
 1763    process_goal(Goal, Origin, Src, P).
 1764process_dcg_goal(List, _Origin, _Src, _) :-
 1765    is_list(List),
 1766    !.               % terminal
 1767process_dcg_goal(List, _Origin, _Src, _) :-
 1768    string(List),
 1769    !.                % terminal
 1770process_dcg_goal(Callable, Origin, Src, P) :-
 1771    extend(Callable, 2, Goal),
 1772    !,
 1773    process_goal(Goal, Origin, Src, P).
 1774process_dcg_goal(_, _, _, _).
 1775
 1776
 1777extend(Var, _, _) :-
 1778    var(Var), !, fail.
 1779extend(M:G, N, M:GX) :-
 1780    !,
 1781    callable(G),
 1782    extend(G, N, GX).
 1783extend(G, N, GX) :-
 1784    (   N =:= 0
 1785    ->  GX = G
 1786    ;   compound(G)
 1787    ->  compound_name_arguments(G, Name, Args),
 1788        length(Rest, N),
 1789        append(Args, Rest, NArgs),
 1790        compound_name_arguments(GX, Name, NArgs)
 1791    ;   atom(G)
 1792    ->  length(NArgs, N),
 1793        compound_name_arguments(GX, G, NArgs)
 1794    ).
 1795
 1796asserting_goal(assert(Rule), Rule).
 1797asserting_goal(asserta(Rule), Rule).
 1798asserting_goal(assertz(Rule), Rule).
 1799asserting_goal(assert(Rule,_), Rule).
 1800asserting_goal(asserta(Rule,_), Rule).
 1801asserting_goal(assertz(Rule,_), Rule).
 1802
 1803process_assert(0, _, _) :- !.           % catch variables
 1804process_assert((_:-Body), Origin, Src) :-
 1805    !,
 1806    process_body(Body, Origin, Src).
 1807process_assert(_, _, _).
 variants(+SortedList, +Max, -Variants) is det
 1811variants([], _, []).
 1812variants([H|T], Max, List) :-
 1813    variants(T, H, Max, List).
 1814
 1815variants([], H, _, [H]).
 1816variants(_, _, 0, []) :- !.
 1817variants([H|T], V, Max, List) :-
 1818    (   H =@= V
 1819    ->  variants(T, V, Max, List)
 1820    ;   List = [V|List2],
 1821        Max1 is Max-1,
 1822        variants(T, H, Max1, List2)
 1823    ).
 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?
 1837partial_evaluate(Goal, P) :-
 1838    eval(Goal),
 1839    !,
 1840    P = true.
 1841partial_evaluate(_, _).
 1842
 1843eval(X = Y) :-
 1844    unify_with_occurs_check(X, Y).
 1845
 1846		 /*******************************
 1847		 *        PLUNIT SUPPORT	*
 1848		 *******************************/
 1849
 1850enter_test_unit(Unit, _Src) :-
 1851    current_source_line(Line),
 1852    asserta(current_test_unit(Unit, Line)).
 1853
 1854leave_test_unit(Unit, _Src) :-
 1855    retractall(current_test_unit(Unit, _)).
 1856
 1857
 1858                 /*******************************
 1859                 *          XPCE STUFF          *
 1860                 *******************************/
 1861
 1862pce_goal(new(_,_), new(-, new)).
 1863pce_goal(send(_,_), send(arg, msg)).
 1864pce_goal(send_class(_,_,_), send_class(arg, arg, msg)).
 1865pce_goal(get(_,_,_), get(arg, msg, -)).
 1866pce_goal(get_class(_,_,_,_), get_class(arg, arg, msg, -)).
 1867pce_goal(get_chain(_,_,_), get_chain(arg, msg, -)).
 1868pce_goal(get_object(_,_,_), get_object(arg, msg, -)).
 1869
 1870process_xpce_goal(G, Origin, Src) :-
 1871    pce_goal(G, Process),
 1872    !,
 1873    current_source_line(Here),
 1874    assert_called(Src, Origin, G, Here),
 1875    (   arg(I, Process, How),
 1876        arg(I, G, Term),
 1877        process_xpce_arg(How, Term, Origin, Src),
 1878        fail
 1879    ;   true
 1880    ).
 1881
 1882process_xpce_arg(new, Term, Origin, Src) :-
 1883    callable(Term),
 1884    process_new(Term, Origin, Src).
 1885process_xpce_arg(arg, Term, Origin, Src) :-
 1886    compound(Term),
 1887    process_new(Term, Origin, Src).
 1888process_xpce_arg(msg, Term, Origin, Src) :-
 1889    compound(Term),
 1890    (   arg(_, Term, Arg),
 1891        process_xpce_arg(arg, Arg, Origin, Src),
 1892        fail
 1893    ;   true
 1894    ).
 1895
 1896process_new(_M:_Term, _, _) :- !.       % TBD: Calls on other modules!
 1897process_new(Term, Origin, Src) :-
 1898    assert_new(Src, Origin, Term),
 1899    (   compound(Term),
 1900        arg(_, Term, Arg),
 1901        process_xpce_arg(arg, Arg, Origin, Src),
 1902        fail
 1903    ;   true
 1904    ).
 1905
 1906assert_new(_, _, Term) :-
 1907    \+ callable(Term),
 1908    !.
 1909assert_new(Src, Origin, Control) :-
 1910    functor_name(Control, Class),
 1911    pce_control_class(Class),
 1912    !,
 1913    forall(arg(_, Control, Arg),
 1914           assert_new(Src, Origin, Arg)).
 1915assert_new(Src, Origin, Term) :-
 1916    compound(Term),
 1917    arg(1, Term, Prolog),
 1918    Prolog == @(prolog),
 1919    (   Term =.. [message, _, Selector | T],
 1920        atom(Selector)
 1921    ->  Called =.. [Selector|T],
 1922        process_body(Called, Origin, Src)
 1923    ;   Term =.. [?, _, Selector | T],
 1924        atom(Selector)
 1925    ->  append(T, [_R], T2),
 1926        Called =.. [Selector|T2],
 1927        process_body(Called, Origin, Src)
 1928    ),
 1929    fail.
 1930assert_new(_, _, @(_)) :- !.
 1931assert_new(Src, _, Term) :-
 1932    functor_name(Term, Name),
 1933    assert_used_class(Src, Name).
 1934
 1935
 1936pce_control_class(and).
 1937pce_control_class(or).
 1938pce_control_class(if).
 1939pce_control_class(not).
 1940
 1941
 1942                /********************************
 1943                *       INCLUDED MODULES        *
 1944                ********************************/
 process_use_module(+Modules, +Src, +Rexport) is det
 1948process_use_module(_Module:_Files, _, _) :- !.  % loaded in another module
 1949process_use_module([], _, _) :- !.
 1950process_use_module([H|T], Src, Reexport) :-
 1951    !,
 1952    process_use_module(H, Src, Reexport),
 1953    process_use_module(T, Src, Reexport).
 1954process_use_module(library(pce), Src, Reexport) :-     % bit special
 1955    !,
 1956    xref_public_list(library(pce), Path, Exports, Src),
 1957    forall(member(Import, Exports),
 1958           process_pce_import(Import, Src, Path, Reexport)).
 1959process_use_module(File, Src, Reexport) :-
 1960    load_module_if_needed(File),
 1961    (   xoption(Src, silent(Silent))
 1962    ->  Extra = [silent(Silent)]
 1963    ;   Extra = [silent(true)]
 1964    ),
 1965    (   xref_public_list(File, Src,
 1966                         [ path(Path),
 1967                           module(M),
 1968                           exports(Exports),
 1969                           public(Public),
 1970                           meta(Meta)
 1971                         | Extra
 1972                         ])
 1973    ->  assert(uses_file(File, Src, Path)),
 1974        assert_import(Src, Exports, _, Path, Reexport),
 1975        assert_xmodule_callable(Exports, M, Src, Path),
 1976        assert_xmodule_callable(Public, M, Src, Path),
 1977        maplist(process_meta_head(Src), Meta),
 1978        (   File = library(chr)     % hacky
 1979        ->  assert(mode(chr, Src))
 1980        ;   true
 1981        )
 1982    ;   assert(uses_file(File, Src, '<not_found>'))
 1983    ).
 1984
 1985process_pce_import(Name/Arity, Src, Path, Reexport) :-
 1986    atom(Name),
 1987    integer(Arity),
 1988    !,
 1989    functor(Term, Name, Arity),
 1990    (   \+ system_predicate(Term),
 1991        \+ Term = pce_error(_)      % hack!?
 1992    ->  assert_import(Src, [Name/Arity], _, Path, Reexport)
 1993    ;   true
 1994    ).
 1995process_pce_import(op(P,T,N), Src, _, _) :-
 1996    xref_push_op(Src, P, T, N).
 process_use_module2(+File, +Import, +Src, +Reexport) is det
Process use_module/2 and reexport/2.
 2002process_use_module2(File, Import, Src, Reexport) :-
 2003    load_module_if_needed(File),
 2004    (   catch(xref_public_list(File, Src,
 2005                               [ path(Path),
 2006                                 exports(Export),
 2007                                 meta(Meta)
 2008                               ]),
 2009              error(_,_),
 2010              fail)
 2011    ->  assertz(uses_file(File, Src, Path)),
 2012        assert_import(Src, Import, Export, Path, Reexport),
 2013        forall((  member(Head, Meta),
 2014                  imported(Head, _, Path)
 2015               ),
 2016               process_meta_head(Src, Head))
 2017    ;   assertz(uses_file(File, Src, '<not_found>'))
 2018    ).
 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.
 2027load_module_if_needed(File) :-
 2028    prolog:no_autoload_module(File),
 2029    !,
 2030    use_module(File, []).
 2031load_module_if_needed(_).
 2032
 2033prolog:no_autoload_module(library(apply_macros)).
 2034prolog:no_autoload_module(library(arithmetic)).
 2035prolog:no_autoload_module(library(record)).
 2036prolog:no_autoload_module(library(persistency)).
 2037prolog:no_autoload_module(library(pldoc)).
 2038prolog:no_autoload_module(library(settings)).
 2039prolog:no_autoload_module(library(debug)).
 2040prolog:no_autoload_module(library(plunit)).
 2041prolog:no_autoload_module(library(macros)).
 2042prolog:no_autoload_module(library(yall)).
 process_requires(+Import, +Src)
 2047process_requires(Import, Src) :-
 2048    is_list(Import),
 2049    !,
 2050    require_list(Import, Src).
 2051process_requires(Var, _Src) :-
 2052    var(Var),
 2053    !.
 2054process_requires((A,B), Src) :-
 2055    !,
 2056    process_requires(A, Src),
 2057    process_requires(B, Src).
 2058process_requires(PI, Src) :-
 2059    requires(PI, Src).
 2060
 2061require_list([], _).
 2062require_list([H|T], Src) :-
 2063    requires(H, Src),
 2064    require_list(T, Src).
 2065
 2066requires(PI, _Src) :-
 2067    '$pi_head'(PI, Head),
 2068    '$get_predicate_attribute'(system:Head, defined, 1),
 2069    !.
 2070requires(PI, Src) :-
 2071    '$pi_head'(PI, Head),
 2072    '$pi_head'(Name/Arity, Head),
 2073    '$find_library'(_Module, Name, Arity, _LoadModule, Library),
 2074    (   imported(Head, Src, Library)
 2075    ->  true
 2076    ;   assertz(imported(Head, Src, Library))
 2077    ).
 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.
 2113xref_public_list(File, Src, Options) :-
 2114    option(path(Source), Options, _),
 2115    option(module(Module), Options, _),
 2116    option(exports(Exports), Options, _),
 2117    option(public(Public), Options, _),
 2118    option(meta(Meta), Options, _),
 2119    xref_source_file(File, Path, Src, Options),
 2120    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.
 2144xref_public_list(File, Source, Export, Src) :-
 2145    xref_source_file(File, Path, Src),
 2146    public_list(Path, Source, _, _, Export, _, []).
 2147xref_public_list(File, Source, Module, Export, Meta, Src) :-
 2148    xref_source_file(File, Path, Src),
 2149    public_list(Path, Source, Module, Meta, Export, _, []).
 2150xref_public_list(File, Source, Module, Export, Public, Meta, Src) :-
 2151    xref_source_file(File, Path, Src),
 2152    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.
 2163:- dynamic  public_list_cache/7. 2164:- volatile public_list_cache/7. 2165
 2166public_list(Path, Source, Module, Meta, Export, Public, _Options) :-
 2167    \+ is_stream(Path),
 2168    public_list_cache(Path, Source, Modified,
 2169                      Module0, Meta0, Export0, Public0),
 2170    time_file(Path, ModifiedNow),
 2171    (   abs(Modified-ModifiedNow) < 0.0001
 2172    ->  !,
 2173        t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0)
 2174    ;   retractall(public_list_cache(Path, _, _, _, _, _, _)),
 2175        fail
 2176    ).
 2177public_list(Path, Source, Module, Meta, Export, Public, Options) :-
 2178    public_list_nc(Path, Source, Module0, Meta0, Export0, Public0, Options),
 2179    (   Error = error(_,_),
 2180        catch(time_file(Path, Modified), Error, fail)
 2181    ->  asserta(public_list_cache(Path, Source, Modified,
 2182                                  Module0, Meta0, Export0, Public0))
 2183    ;   true
 2184    ),
 2185    t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0).
 2186
 2187public_list_nc(Path, Source, Module, Meta, Export, Public, _Options) :-
 2188    \+ is_stream(Path),
 2189    public_list_from_index(Path, Module, Meta, Export, Public),
 2190    !,
 2191    qlf_pl_file(Path, Source).
 2192public_list_nc(Path, Source, Module, [], Export, [], _Options) :-
 2193    \+ is_stream(Path),
 2194    is_qlf_file(Path),
 2195    !,
 2196    '$qlf_module'(Path, Info),
 2197    _{module:Module, exports:Export, file:Source} :< Info.
 2198public_list_nc(Path, Path, Module, Meta, Export, Public, Options) :-
 2199    (   is_stream(Path)
 2200    ;   exists_file(Path)
 2201    ),
 2202    !,
 2203    prolog_file_directives(Path, Directives, Options),
 2204    public_list(Directives, Path, Module, Meta, [], Export, [], Public, []).
 2205public_list_nc(Path, Path, Module, [], Export, [], _Options) :-
 2206    \+ is_stream(Path),
 2207    qlf_pl_file(QlfFile, Path),
 2208    '$qlf_module'(QlfFile, Info),
 2209    _{module:Module, exports:Export} :< Info.
 2210
 2211public_list([(:- module(Module, Export0))|Decls], Path,
 2212            Module, Meta, MT, Export, Rest, Public, PT) :-
 2213    !,
 2214    (   is_list(Export0)
 2215    ->  append(Export0, Reexport, Export)
 2216    ;   Reexport = Export
 2217    ),
 2218    public_list_(Decls, Path, Meta, MT, Reexport, Rest, Public, PT).
 2219public_list([(:- encoding(_))|Decls], Path,
 2220            Module, Meta, MT, Export, Rest, Public, PT) :-
 2221    public_list(Decls, Path, Module, Meta, MT, Export, Rest, Public, PT).
 2222
 2223public_list_([], _, Meta, Meta, Export, Export, Public, Public).
 2224public_list_([(:-(Dir))|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 2225    public_list_1(Dir, Path, Meta, MT0, Export, Rest0, Public, PT0),
 2226    !,
 2227    public_list_(T, Path, MT0, MT, Rest0, Rest, PT0, PT).
 2228public_list_([_|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 2229    public_list_(T, Path, Meta, MT, Export, Rest, Public, PT).
 2230
 2231public_list_1(reexport(Spec), Path, Meta, MT, Reexport, Rest, Public, PT) :-
 2232    reexport_files(Spec, Path, Meta, MT, Reexport, Rest, Public, PT).
 2233public_list_1(reexport(Spec, Import), Path, Meta, Meta, Reexport, Rest, Public, Public) :-
 2234    public_from_import(Import, Spec, Path, Reexport, Rest).
 2235public_list_1(meta_predicate(Decl), _Path, Meta, MT, Export, Export, Public, Public) :-
 2236    phrase(meta_decls(Decl), Meta, MT).
 2237public_list_1(public(Decl), _Path, Meta, Meta, Export, Export, Public, PT) :-
 2238    phrase(public_decls(Decl), Public, PT).
 reexport_files(+Files, +Src, -Meta, ?MetaTail, -Exports, ?ExportsTail, -Public, ?PublicTail)
 2244reexport_files([], _, Meta, Meta, Export, Export, Public, Public) :- !.
 2245reexport_files([H|T], Src, Meta, MT, Export, ET, Public, PT) :-
 2246    !,
 2247    xref_source_file(H, Path, Src),
 2248    public_list(Path, _Source, _Module, Meta0, Export0, Public0, []),
 2249    append(Meta0, MT1, Meta),
 2250    append(Export0, ET1, Export),
 2251    append(Public0, PT1, Public),
 2252    reexport_files(T, Src, MT1, MT, ET1, ET, PT1, PT).
 2253reexport_files(Spec, Src, Meta, MT, Export, ET, Public, PT) :-
 2254    xref_source_file(Spec, Path, Src),
 2255    public_list(Path, _Source, _Module, Meta0, Export0, Public0, []),
 2256    append(Meta0, MT, Meta),
 2257    append(Export0, ET, Export),
 2258    append(Public0, PT, Public).
 2259
 2260public_from_import(except(Map), Path, Src, Export, Rest) :-
 2261    !,
 2262    xref_public_list(Path, _, AllExports, Src),
 2263    except(Map, AllExports, NewExports),
 2264    append(NewExports, Rest, Export).
 2265public_from_import(Import, _, _, Export, Rest) :-
 2266    import_name_map(Import, Export, Rest).
 except(+Remove, +AllExports, -Exports)
 2271except([], Exports, Exports).
 2272except([PI0 as NewName|Map], Exports0, Exports) :-
 2273    !,
 2274    canonical_pi(PI0, PI),
 2275    map_as(Exports0, PI, NewName, Exports1),
 2276    except(Map, Exports1, Exports).
 2277except([PI0|Map], Exports0, Exports) :-
 2278    canonical_pi(PI0, PI),
 2279    select(PI2, Exports0, Exports1),
 2280    same_pi(PI, PI2),
 2281    !,
 2282    except(Map, Exports1, Exports).
 2283
 2284
 2285map_as([PI|T], Repl, As, [PI2|T])  :-
 2286    same_pi(Repl, PI),
 2287    !,
 2288    pi_as(PI, As, PI2).
 2289map_as([H|T0], Repl, As, [H|T])  :-
 2290    map_as(T0, Repl, As, T).
 2291
 2292pi_as(_/Arity, Name, Name/Arity).
 2293pi_as(_//Arity, Name, Name//Arity).
 2294
 2295import_name_map([], L, L).
 2296import_name_map([_/Arity as NewName|T0], [NewName/Arity|T], Tail) :-
 2297    !,
 2298    import_name_map(T0, T, Tail).
 2299import_name_map([_//Arity as NewName|T0], [NewName//Arity|T], Tail) :-
 2300    !,
 2301    import_name_map(T0, T, Tail).
 2302import_name_map([H|T0], [H|T], Tail) :-
 2303    import_name_map(T0, T, Tail).
 2304
 2305canonical_pi(Name//Arity0, PI) :-
 2306    integer(Arity0),
 2307    !,
 2308    PI = Name/Arity,
 2309    Arity is Arity0 + 2.
 2310canonical_pi(PI, PI).
 2311
 2312same_pi(Canonical, PI2) :-
 2313    canonical_pi(PI2, Canonical).
 2314
 2315meta_decls(Var) -->
 2316    { var(Var) },
 2317    !.
 2318meta_decls((A,B)) -->
 2319    !,
 2320    meta_decls(A),
 2321    meta_decls(B).
 2322meta_decls(A) -->
 2323    [A].
 2324
 2325public_decls(Var) -->
 2326    { var(Var) },
 2327    !.
 2328public_decls((A,B)) -->
 2329    !,
 2330    public_decls(A),
 2331    public_decls(B).
 2332public_decls(A) -->
 2333    [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.
 2340public_list_from_index(Path, Module, Meta, Export, Public) :-
 2341    file_name_extension(BasePath, _Ext, Path),
 2342    file_directory_name(BasePath, Dir),
 2343    atom_concat(Dir, '/INDEX.pl', IndexFile),
 2344    exists_file(IndexFile),
 2345    file_base_name(BasePath, Base),
 2346    setup_call_cleanup(
 2347        '$push_input_context'(autoload_index),
 2348        setup_call_cleanup(
 2349            open(IndexFile, read, In),
 2350            index_public_list(In, Base, Module, Meta, Export, Public),
 2351            close(In)),
 2352        '$pop_input_context').
 2353
 2354index_public_list(In, Base, Module, Meta, Export, Public) :-
 2355    read_term(In, Term, []),
 2356    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2357
 2358index_public_list(end_of_file, _In, _Base, _Module, [], [], []).
 2359index_public_list(index(op:Op, Module, Base), In, Base, Module, Meta, [Op|Export], Public) :-
 2360    !,
 2361    read_term(In, Term, []),
 2362    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2363index_public_list(index((public):Head, Module, Base), In, Base, Module, Meta, Export, [PI|Public]) :-
 2364    !,
 2365    pi_head(PI, Head),
 2366    read_term(In, Term, []),
 2367    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2368index_public_list(index(Head, Module, Base), In, Base, Module, Meta, [PI|Export], Public) :-
 2369    !,
 2370    pi_head(PI, Head),
 2371    (   meta_mode(Head)
 2372    ->  Meta = [Head|MetaT]
 2373    ;   Meta = MetaT
 2374    ),
 2375    read_term(In, Term, []),
 2376    index_public_list(Term, In, Base, Module, MetaT, Export, Public).
 2377index_public_list(index(Name, Arity, Module, Base), In, Base, Module, Meta, [Name/Arity|Export], Public) :-
 2378    !,
 2379    read_term(In, Term, []),
 2380    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2381index_public_list(_, In, Base, Module, Meta, Export, Public) :-
 2382    read_term(In, Term, []),
 2383    index_public_list(Term, In, Base, Module, Meta, Export, Public).
 2384
 2385meta_mode(H) :-
 2386    compound(H),
 2387    arg(_, H, A),
 2388    meta_arg(A),
 2389    !.
 2390
 2391meta_arg(I) :-
 2392    integer(I),
 2393    !.
 2394meta_arg(:).
 2395meta_arg(^).
 2396meta_arg(//).
 2397
 2398                 /*******************************
 2399                 *             INCLUDE          *
 2400                 *******************************/
 2401
 2402process_include([], _) :- !.
 2403process_include([H|T], Src) :-
 2404    !,
 2405    process_include(H, Src),
 2406    process_include(T, Src).
 2407process_include(File, Src) :-
 2408    callable(File),
 2409    !,
 2410    (   once(xref_input(ParentSrc, _)),
 2411        xref_source_file(File, Path, ParentSrc)
 2412    ->  (   (   uses_file(_, Src, Path)
 2413            ;   Path == Src
 2414            )
 2415        ->  true
 2416        ;   assert(uses_file(File, Src, Path)),
 2417            (   xoption(Src, process_include(true))
 2418            ->  findall(O, xoption(Src, O), Options),
 2419                setup_call_cleanup(
 2420                    open_include_file(Path, In, Refs),
 2421                    collect(Src, Path, In, Options),
 2422                    close_include(In, Refs))
 2423            ;   true
 2424            )
 2425        )
 2426    ;   assert(uses_file(File, Src, '<not_found>'))
 2427    ).
 2428process_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.
 2436open_include_file(Path, In, [Ref]) :-
 2437    once(xref_input(_, Parent)),
 2438    stream_property(Parent, encoding(Enc)),
 2439    '$push_input_context'(xref_include),
 2440    catch((   prolog:xref_open_source(Path, In)
 2441          ->  catch(set_stream(In, encoding(Enc)),
 2442                    error(_,_), true)       % deal with non-file input
 2443          ;   include_encoding(Enc, Options),
 2444              open(Path, read, In, Options)
 2445          ), E,
 2446          ( '$pop_input_context', throw(E))),
 2447    catch((   peek_char(In, #)              % Deal with #! script
 2448          ->  skip(In, 10)
 2449          ;   true
 2450          ), E,
 2451          ( close_include(In, []), throw(E))),
 2452    asserta(xref_input(Path, In), Ref).
 2453
 2454include_encoding(wchar_t, []) :- !.
 2455include_encoding(Enc, [encoding(Enc)]).
 2456
 2457
 2458close_include(In, Refs) :-
 2459    maplist(erase, Refs),
 2460    close(In, [force(true)]),
 2461    '$pop_input_context'.
 process_foreign(+Spec, +Src)
Process a load_foreign_library/1 call.
 2467process_foreign(Spec, Src) :-
 2468    ground(Spec),
 2469    current_foreign_library(Spec, Defined),
 2470    !,
 2471    (   xmodule(Module, Src)
 2472    ->  true
 2473    ;   Module = user
 2474    ),
 2475    process_foreign_defined(Defined, Module, Src).
 2476process_foreign(_, _).
 2477
 2478process_foreign_defined([], _, _).
 2479process_foreign_defined([H|T], M, Src) :-
 2480    (   H = M:Head
 2481    ->  assert_foreign(Src, Head)
 2482    ;   assert_foreign(Src, H)
 2483    ),
 2484    process_foreign_defined(T, M, Src).
 2485
 2486
 2487                 /*******************************
 2488                 *          CHR SUPPORT         *
 2489                 *******************************/
 2490
 2491/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2492This part of the file supports CHR. Our choice is between making special
 2493hooks to make CHR expansion work and  then handle the (complex) expanded
 2494code or process the  CHR  source   directly.  The  latter looks simpler,
 2495though I don't like the idea  of   adding  support for libraries to this
 2496module.  A  file  is  supposed  to  be  a    CHR   file  if  it  uses  a
 2497use_module(library(chr) or contains a :-   constraint/1 directive. As an
 2498extra bonus we get the source-locations right :-)
 2499- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2500
 2501process_chr(@(_Name, Rule), Src) :-
 2502    mode(chr, Src),
 2503    process_chr(Rule, Src).
 2504process_chr(pragma(Rule, _Pragma), Src) :-
 2505    mode(chr, Src),
 2506    process_chr(Rule, Src).
 2507process_chr(<=>(Head, Body), Src) :-
 2508    mode(chr, Src),
 2509    chr_head(Head, Src, H),
 2510    chr_body(Body, H, Src).
 2511process_chr(==>(Head, Body), Src) :-
 2512    mode(chr, Src),
 2513    chr_head(Head, H, Src),
 2514    chr_body(Body, H, Src).
 2515process_chr((:- chr_constraint(Decls)), Src) :-
 2516    (   mode(chr, Src)
 2517    ->  true
 2518    ;   assert(mode(chr, Src))
 2519    ),
 2520    chr_decls(Decls, Src).
 2521
 2522chr_decls((A,B), Src) =>
 2523    chr_decls(A, Src),
 2524    chr_decls(B, Src).
 2525chr_decls(Head, Src) =>
 2526    generalise_term(Head, Gen),
 2527    (   declared(Gen, chr_constraint, Src, _)
 2528    ->  true
 2529    ;   current_source_line(Line),
 2530        assertz(declared(Gen, chr_constraint, Src, Line))
 2531    ).
 2532
 2533chr_head(X, _, _) :-
 2534    var(X),
 2535    !.                      % Illegal.  Warn?
 2536chr_head(\(A,B), Src, H) :-
 2537    chr_head(A, Src, H),
 2538    process_body(B, H, Src).
 2539chr_head((H0,B), Src, H) :-
 2540    chr_defined(H0, Src, H),
 2541    process_body(B, H, Src).
 2542chr_head(H0, Src, H) :-
 2543    chr_defined(H0, Src, H).
 2544
 2545chr_defined(X, _, _) :-
 2546    var(X),
 2547    !.
 2548chr_defined(#(C,_Id), Src, C) :-
 2549    !,
 2550    assert_constraint(Src, C).
 2551chr_defined(A, Src, A) :-
 2552    assert_constraint(Src, A).
 2553
 2554chr_body(X, From, Src) :-
 2555    var(X),
 2556    !,
 2557    process_body(X, From, Src).
 2558chr_body('|'(Guard, Goals), H, Src) :-
 2559    !,
 2560    chr_body(Guard, H, Src),
 2561    chr_body(Goals, H, Src).
 2562chr_body(G, From, Src) :-
 2563    process_body(G, From, Src).
 2564
 2565assert_constraint(_, Head) :-
 2566    var(Head),
 2567    !.
 2568assert_constraint(Src, Head) :-
 2569    constraint(Head, Src, _),
 2570    !.
 2571assert_constraint(Src, Head) :-
 2572    generalise_term(Head, Term),
 2573    current_source_line(Line),
 2574    assert(constraint(Term, Src, Line)).
 2575
 2576
 2577                /********************************
 2578                *       PHASE 1 ASSERTIONS      *
 2579                ********************************/
 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.
 2586assert_called(_, _, Var, _) :-
 2587    var(Var),
 2588    !.
 2589assert_called(Src, From, Goal, Line) :-
 2590    var(From),
 2591    !,
 2592    assert_called(Src, '<unknown>', Goal, Line).
 2593assert_called(_, _, Goal, _) :-
 2594    expand_hide_called(Goal),
 2595    !.
 2596assert_called(Src, Origin, M:G, Line) :-
 2597    !,
 2598    (   atom(M),
 2599        callable(G)
 2600    ->  current_condition(Cond),
 2601        (   xmodule(M, Src)         % explicit call to own module
 2602        ->  assert_called(Src, Origin, G, Line)
 2603        ;   called(M:G, Src, Origin, Cond, Line) % already registered
 2604        ->  true
 2605        ;   hide_called(M:G, Src)           % not interesting (now)
 2606        ->  true
 2607        ;   generalise(Origin, OTerm),
 2608            generalise(G, GTerm)
 2609        ->  assert(called(M:GTerm, Src, OTerm, Cond, Line))
 2610        ;   true
 2611        )
 2612    ;   true                        % call to variable module
 2613    ).
 2614assert_called(Src, _, Goal, _) :-
 2615    (   xmodule(M, Src)
 2616    ->  M \== system
 2617    ;   M = user
 2618    ),
 2619    hide_called(M:Goal, Src),
 2620    !.
 2621assert_called(Src, Origin, Goal, Line) :-
 2622    current_condition(Cond),
 2623    (   called(Goal, Src, Origin, Cond, Line)
 2624    ->  true
 2625    ;   generalise(Origin, OTerm),
 2626        generalise(Goal, Term)
 2627    ->  assert(called(Term, Src, OTerm, Cond, Line))
 2628    ;   true
 2629    ).
 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.
 2637expand_hide_called(pce_principal:send_implementation(_, _, _)).
 2638expand_hide_called(pce_principal:get_implementation(_, _, _, _)).
 2639expand_hide_called(pce_principal:pce_lazy_get_method(_,_,_)).
 2640expand_hide_called(pce_principal:pce_lazy_send_method(_,_,_)).
 2641
 2642assert_defined(Src, Goal) :-
 2643    Goal = test(_Test),
 2644    current_test_unit(Unit, Line),
 2645    assert_called(Src, '<test_unit>'(Unit), Goal, Line),
 2646    fail.
 2647assert_defined(Src, Goal) :-
 2648    Goal = test(_Test, _Options),
 2649    current_test_unit(Unit, Line),
 2650    assert_called(Src, '<test_unit>'(Unit), Goal, Line),
 2651    fail.
 2652assert_defined(Src, Goal) :-
 2653    defined(Goal, Src, _),
 2654    !.
 2655assert_defined(Src, Goal) :-
 2656    generalise(Goal, Term),
 2657    current_source_line(Line),
 2658    assert(defined(Term, Src, Line)).
 2659
 2660assert_foreign(Src, Goal) :-
 2661    foreign(Goal, Src, _),
 2662    !.
 2663assert_foreign(Src, Goal) :-
 2664    generalise(Goal, Term),
 2665    current_source_line(Line),
 2666    assert(foreign(Term, Src, Line)).
 2667
 2668assert_grammar_rule(Src, Goal) :-
 2669    grammar_rule(Goal, Src),
 2670    !.
 2671assert_grammar_rule(Src, Goal) :-
 2672    generalise(Goal, Term),
 2673    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.
 2686assert_import(_, [], _, _, _) :- !.
 2687assert_import(Src, [H|T], Export, From, Reexport) :-
 2688    !,
 2689    assert_import(Src, H, Export, From, Reexport),
 2690    assert_import(Src, T, Export, From, Reexport).
 2691assert_import(Src, except(Except), Export, From, Reexport) :-
 2692    !,
 2693    is_list(Export),
 2694    !,
 2695    except(Except, Export, Import),
 2696    assert_import(Src, Import, _All, From, Reexport).
 2697assert_import(Src, Import as Name, Export, From, Reexport) :-
 2698    !,
 2699    pi_to_head(Import, Term0),
 2700    rename_goal(Term0, Name, Term),
 2701    (   in_export_list(Term0, Export)
 2702    ->  assert(imported(Term, Src, From)),
 2703        assert_reexport(Reexport, Src, Term)
 2704    ;   current_source_line(Line),
 2705        assert_called(Src, '<directive>'(Line), Term0, Line)
 2706    ).
 2707assert_import(Src, Import, Export, From, Reexport) :-
 2708    pi_to_head(Import, Term),
 2709    !,
 2710    (   in_export_list(Term, Export)
 2711    ->  assert(imported(Term, Src, From)),
 2712        assert_reexport(Reexport, Src, Term)
 2713    ;   current_source_line(Line),
 2714        assert_called(Src, '<directive>'(Line), Term, Line)
 2715    ).
 2716assert_import(Src, op(P,T,N), _, _, _) :-
 2717    xref_push_op(Src, P,T,N).
 2718
 2719in_export_list(_Head, Export) :-
 2720    var(Export),
 2721    !.
 2722in_export_list(Head, Export) :-
 2723    member(PI, Export),
 2724    pi_to_head(PI, Head).
 2725
 2726assert_reexport(false, _, _) :- !.
 2727assert_reexport(true, Src, Term) :-
 2728    assert(exported(Term, Src)).
 process_import(:Import, +Src)
Process an import/1 directive
 2734process_import(M:PI, Src) :-
 2735    pi_to_head(PI, Head),
 2736    !,
 2737    (   atom(M),
 2738        current_module(M),
 2739        module_property(M, file(From))
 2740    ->  true
 2741    ;   From = '<unknown>'
 2742    ),
 2743    assert(imported(Head, Src, From)).
 2744process_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?
 2753assert_xmodule_callable([], _, _, _).
 2754assert_xmodule_callable([PI|T], M, Src, From) :-
 2755    (   pi_to_head(M:PI, Head)
 2756    ->  assert(imported(Head, Src, From))
 2757    ;   true
 2758    ),
 2759    assert_xmodule_callable(T, M, Src, From).
 assert_op(+Src, +Op) is det
Arguments:
Op- Ground term op(Priority, Type, Name).
 2766assert_op(Src, op(P,T,M:N)) :-
 2767    (   '$current_source_module'(M)
 2768    ->  Name = N
 2769    ;   Name = M:N
 2770    ),
 2771    (   xop(Src, op(P,T,Name))
 2772    ->  true
 2773    ;   assert(xop(Src, op(P,T,Name)))
 2774    ).
 assert_module(+Src, +Module)
Assert we are loading code into Module. This is also used to exploit local term-expansion and other rules.
 2781assert_module(Src, Module) :-
 2782    xmodule(Module, Src),
 2783    !.
 2784assert_module(Src, Module) :-
 2785    '$set_source_module'(Module),
 2786    assert(xmodule(Module, Src)),
 2787    (   module_property(Module, class(system))
 2788    ->  retractall(xoption(Src, register_called(_))),
 2789        assert(xoption(Src, register_called(all)))
 2790    ;   true
 2791    ).
 2792
 2793assert_module_export(_, []) :- !.
 2794assert_module_export(Src, [H|T]) :-
 2795    !,
 2796    assert_module_export(Src, H),
 2797    assert_module_export(Src, T).
 2798assert_module_export(Src, PI) :-
 2799    pi_to_head(PI, Term),
 2800    !,
 2801    assert(exported(Term, Src)).
 2802assert_module_export(Src, op(P, A, N)) :-
 2803    xref_push_op(Src, P, A, N).
 assert_module3(+Import, +Src)
Handle 3th argument of module/3 declaration.
 2809assert_module3([], _) :- !.
 2810assert_module3([H|T], Src) :-
 2811    !,
 2812    assert_module3(H, Src),
 2813    assert_module3(T, Src).
 2814assert_module3(Option, Src) :-
 2815    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.
 2824process_predicates(Closure, Preds, Src) :-
 2825    is_list(Preds),
 2826    !,
 2827    process_predicate_list(Preds, Closure, Src).
 2828process_predicates(Closure, as(Preds, _Options), Src) :-
 2829    !,
 2830    process_predicates(Closure, Preds, Src).
 2831process_predicates(Closure, Preds, Src) :-
 2832    process_predicate_comma(Preds, Closure, Src).
 2833
 2834process_predicate_list([], _, _).
 2835process_predicate_list([H|T], Closure, Src) :-
 2836    (   nonvar(H)
 2837    ->  call(Closure, H, Src)
 2838    ;   true
 2839    ),
 2840    process_predicate_list(T, Closure, Src).
 2841
 2842process_predicate_comma(Var, _, _) :-
 2843    var(Var),
 2844    !.
 2845process_predicate_comma(M:(A,B), Closure, Src) :-
 2846    !,
 2847    process_predicate_comma(M:A, Closure, Src),
 2848    process_predicate_comma(M:B, Closure, Src).
 2849process_predicate_comma((A,B), Closure, Src) :-
 2850    !,
 2851    process_predicate_comma(A, Closure, Src),
 2852    process_predicate_comma(B, Closure, Src).
 2853process_predicate_comma(as(Spec, _Options), Closure, Src) :-
 2854    !,
 2855    process_predicate_comma(Spec, Closure, Src).
 2856process_predicate_comma(A, Closure, Src) :-
 2857    call(Closure, A, Src).
 2858
 2859
 2860assert_dynamic(PI, Src) :-
 2861    pi_to_head(PI, Term),
 2862    (   thread_local(Term, Src, _)  % dynamic after thread_local has
 2863    ->  true                        % no effect
 2864    ;   current_source_line(Line),
 2865        assert(dynamic(Term, Src, Line))
 2866    ).
 2867
 2868assert_thread_local(PI, Src) :-
 2869    pi_to_head(PI, Term),
 2870    current_source_line(Line),
 2871    assert(thread_local(Term, Src, Line)).
 2872
 2873assert_multifile(PI, Src) :-                    % :- multifile(Spec)
 2874    pi_to_head(PI, Term),
 2875    current_source_line(Line),
 2876    assert(multifile(Term, Src, Line)).
 2877
 2878assert_public(PI, Src) :-                       % :- public(Spec)
 2879    pi_to_head(PI, Term),
 2880    current_source_line(Line),
 2881    assert_called(Src, '<public>'(Line), Term, Line),
 2882    assert(public(Term, Src, Line)).
 2883
 2884assert_export(PI, Src) :-                       % :- export(Spec)
 2885    pi_to_head(PI, Term),
 2886    !,
 2887    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.
 2894pi_to_head(Var, _) :-
 2895    var(Var), !, fail.
 2896pi_to_head(M:PI, M:Term) :-
 2897    !,
 2898    pi_to_head(PI, Term).
 2899pi_to_head(Name/Arity, Term) :-
 2900    functor(Term, Name, Arity).
 2901pi_to_head(Name//DCGArity, Term) :-
 2902    Arity is DCGArity+2,
 2903    functor(Term, Name, Arity).
 2904
 2905
 2906assert_used_class(Src, Name) :-
 2907    used_class(Name, Src),
 2908    !.
 2909assert_used_class(Src, Name) :-
 2910    assert(used_class(Name, Src)).
 2911
 2912assert_defined_class(Src, Name, _Meta, _Super, _) :-
 2913    defined_class(Name, _, _, Src, _),
 2914    !.
 2915assert_defined_class(_, _, _, -, _) :- !.               % :- pce_extend_class
 2916assert_defined_class(Src, Name, Meta, Super, Summary) :-
 2917    current_source_line(Line),
 2918    (   Summary == @(default)
 2919    ->  Atom = ''
 2920    ;   is_list(Summary)
 2921    ->  atom_codes(Atom, Summary)
 2922    ;   string(Summary)
 2923    ->  atom_concat(Summary, '', Atom)
 2924    ),
 2925    assert(defined_class(Name, Super, Atom, Src, Line)),
 2926    (   Meta = @(_)
 2927    ->  true
 2928    ;   assert_used_class(Src, Meta)
 2929    ),
 2930    assert_used_class(Src, Super).
 2931
 2932assert_defined_class(Src, Name, imported_from(_File)) :-
 2933    defined_class(Name, _, _, Src, _),
 2934    !.
 2935assert_defined_class(Src, Name, imported_from(File)) :-
 2936    assert(defined_class(Name, _, '', Src, file(File))).
 2937
 2938
 2939                /********************************
 2940                *            UTILITIES          *
 2941                ********************************/
 generalise(+Callable, -General)
Generalise a callable term.
 2947generalise(Var, Var) :-
 2948    var(Var),
 2949    !.                    % error?
 2950generalise(pce_principal:send_implementation(Id, _, _),
 2951           pce_principal:send_implementation(Id, _, _)) :-
 2952    atom(Id),
 2953    !.
 2954generalise(pce_principal:get_implementation(Id, _, _, _),
 2955           pce_principal:get_implementation(Id, _, _, _)) :-
 2956    atom(Id),
 2957    !.
 2958generalise('<directive>'(Line), '<directive>'(Line)) :- !.
 2959generalise(test(Test), test(Test)) :-
 2960    current_test_unit(_,_),
 2961    ground(Test),
 2962    !.
 2963generalise(test(Test, _), test(Test, _)) :-
 2964    current_test_unit(_,_),
 2965    ground(Test),
 2966    !.
 2967generalise('<test_unit>'(Line), '<test_unit>'(Line)) :- !.
 2968generalise(Module:Goal0, Module:Goal) :-
 2969    atom(Module),
 2970    !,
 2971    generalise(Goal0, Goal).
 2972generalise(Term0, Term) :-
 2973    callable(Term0),
 2974    generalise_term(Term0, Term).
 2975
 2976
 2977                 /*******************************
 2978                 *      SOURCE MANAGEMENT       *
 2979                 *******************************/
 2980
 2981/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2982This section of the file contains   hookable  predicates to reason about
 2983sources. The built-in code here  can  only   deal  with  files. The XPCE
 2984library(pce_prolog_xref) provides hooks to deal with XPCE objects, so we
 2985can do cross-referencing on PceEmacs edit   buffers.  Other examples for
 2986hooking can be databases, (HTTP) URIs, etc.
 2987- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2988
 2989:- multifile
 2990    prolog:xref_source_directory/2, % +Source, -Dir
 2991    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.
 2999xref_source_file(Plain, File, Source) :-
 3000    xref_source_file(Plain, File, Source, []).
 3001
 3002xref_source_file(QSpec, File, Source, Options) :-
 3003    nonvar(QSpec), QSpec = _:Spec,
 3004    !,
 3005    must_be(acyclic, Spec),
 3006    xref_source_file(Spec, File, Source, Options).
 3007xref_source_file(Spec, File, _Source, _Options) :-
 3008    is_stream(Spec), !,
 3009    File = Spec.
 3010xref_source_file(Spec, File, Source, Options) :-
 3011    nonvar(Spec),
 3012    prolog:xref_source_file(Spec, File,
 3013                            [ relative_to(Source)
 3014                            | Options
 3015                            ]),
 3016    !.
 3017xref_source_file(Plain, File, Source, Options) :-
 3018    atom(Plain),
 3019    \+ is_absolute_file_name(Plain),
 3020    (   prolog:xref_source_directory(Source, Dir)
 3021    ->  true
 3022    ;   atom(Source),
 3023        file_directory_name(Source, Dir)
 3024    ),
 3025    atomic_list_concat([Dir, /, Plain], Spec0),
 3026    absolute_file_name(Spec0, Spec),
 3027    do_xref_source_file(Spec, File, Options),
 3028    !.
 3029xref_source_file(Spec, File, Source, Options) :-
 3030    do_xref_source_file(Spec, File,
 3031                        [ relative_to(Source)
 3032                        | Options
 3033                        ]),
 3034    !.
 3035xref_source_file(_, _, _, Options) :-
 3036    option(silent(true), Options),
 3037    !,
 3038    fail.
 3039xref_source_file(Spec, _, Src, _Options) :-
 3040    verbose(Src),
 3041    print_message(warning, error(existence_error(file, Spec), _)),
 3042    fail.
 3043
 3044do_xref_source_file(Spec, File, Options) :-
 3045    nonvar(Spec),
 3046    option(file_type(Type), Options, prolog),
 3047    absolute_file_name(Spec, File0,
 3048                       [ file_type(Type),
 3049                         access(read),
 3050                         file_errors(fail)
 3051                       ]),
 3052    !,
 3053    qlf_pl_file(File0, File).
 3054do_xref_source_file(Spec, File, Options) :-
 3055    atom(Spec), % handle absolute /file/to/source.pl without sources
 3056    file_name_extension(Base, Ext, Spec),
 3057    user:prolog_file_type(Ext, source),
 3058    option(file_type(prolog), Options, prolog),
 3059    absolute_file_name(Base, File0,
 3060                       [ file_type(prolog),
 3061                         access(read),
 3062                         file_errors(fail)
 3063                       ]),
 3064    qlf_pl_file(File0, File).
 qlf_pl_file(?QlfFile, ?PlFile) is semidet
 3068qlf_pl_file(QlfFile, PlFile) :-
 3069    nonvar(QlfFile),
 3070    is_qlf_file(QlfFile),
 3071    !,
 3072    '$qlf_module'(QlfFile, Info),
 3073    #{file:PlFile} :< Info.
 3074qlf_pl_file(QlfFile, PlFile) :-
 3075    nonvar(PlFile),
 3076    !,
 3077    (   file_name_extension(Base, Ext, PlFile),
 3078        user:prolog_file_type(Ext, source)
 3079    ->  true
 3080    ),
 3081    (   user:prolog_file_type(QlfExt, qlf),
 3082        file_name_extension(Base, QlfExt, QlfFile),
 3083        exists_file(QlfFile)
 3084    ->  true
 3085    ),
 3086    '$qlf_module'(QlfFile, Info),
 3087    #{file:PlFile} :< Info,
 3088    !.
 3089qlf_pl_file(PlFile, PlFile).
 3090
 3091is_qlf_file(QlfFile) :-
 3092    file_name_extension(_, Ext, QlfFile),
 3093    user:prolog_file_type(Ext, qlf),
 3094    !.
 canonical_source(?Source, ?Src) is det
Src is the canonical version of Source if Source is given.
 3100canonical_source(Source, Src) :-
 3101    (   ground(Source)
 3102    ->  prolog_canonical_source(Source, Src)
 3103    ;   Source = Src
 3104    ).
 goal_name_arity(+Goal, -Name, -Arity)
Generalized version of functor/3 that can deal with name() goals.
 3111goal_name_arity(Goal, Name, Arity) :-
 3112    (   compound(Goal)
 3113    ->  compound_name_arity(Goal, Name, Arity)
 3114    ;   atom(Goal)
 3115    ->  Name = Goal, Arity = 0
 3116    ).
 3117
 3118generalise_term(Specific, General) :-
 3119    (   compound(Specific)
 3120    ->  compound_name_arity(Specific, Name, Arity),
 3121        compound_name_arity(General, Name, Arity)
 3122    ;   General = Specific
 3123    ).
 3124
 3125functor_name(Term, Name) :-
 3126    (   compound(Term)
 3127    ->  compound_name_arity(Term, Name, _)
 3128    ;   atom(Term)
 3129    ->  Name = Term
 3130    ).
 3131
 3132rename_goal(Goal0, Name, Goal) :-
 3133    (   compound(Goal0)
 3134    ->  compound_name_arity(Goal0, _, Arity),
 3135        compound_name_arity(Goal, Name, Arity)
 3136    ;   Goal = Name
 3137    ).
 3138
 3139
 3140                /*******************************
 3141                *           MESSAGES           *
 3142                *******************************/<
 3143
 3144:- multifile prolog:message//1.
 3145
 3146prolog:message(meta_predicate_after_call(Decl, By)) -->
 3147    { pi_head(ByPI, By) },
 3148    [ ansi(code, ':- meta_predicate(~p)', [Decl]),
 3149      ' declaration appears after call from '-[],
 3150      ansi(code, '~p', [ByPI])
 3151    ]