View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org/projects/xpce/
    6    Copyright (c)  2006-2023, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9                              SWI-Prolog Solutions b.v.
   10    All rights reserved.
   11
   12    Redistribution and use in source and binary forms, with or without
   13    modification, are permitted provided that the following conditions
   14    are met:
   15
   16    1. Redistributions of source code must retain the above copyright
   17       notice, this list of conditions and the following disclaimer.
   18
   19    2. Redistributions in binary form must reproduce the above copyright
   20       notice, this list of conditions and the following disclaimer in
   21       the documentation and/or other materials provided with the
   22       distribution.
   23
   24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   25    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   26    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   27    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   28    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   29    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   30    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   31    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   32    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   34    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35    POSSIBILITY OF SUCH DAMAGE.
   36*/
   37
   38:- module(prolog_xref,
   39          [ xref_source/1,              % +Source
   40            xref_source/2,              % +Source, +Options
   41            xref_called/3,              % ?Source, ?Callable, ?By
   42            xref_called/4,              % ?Source, ?Callable, ?By, ?Cond
   43            xref_called/5,              % ?Source, ?Callable, ?By, ?Cond, ?Line
   44            xref_defined/3,             % ?Source. ?Callable, -How
   45            xref_definition_line/2,     % +How, -Line
   46            xref_exported/2,            % ?Source, ?Callable
   47            xref_module/2,              % ?Source, ?Module
   48            xref_uses_file/3,           % ?Source, ?Spec, ?Path
   49            xref_op/2,                  % ?Source, ?Op
   50            xref_prolog_flag/4,         % ?Source, ?Flag, ?Value, ?Line
   51            xref_comment/3,             % ?Source, ?Title, ?Comment
   52            xref_comment/4,             % ?Source, ?Head, ?Summary, ?Comment
   53            xref_mode/3,                % ?Source, ?Mode, ?Det
   54            xref_option/2,              % ?Source, ?Option
   55            xref_clean/1,               % +Source
   56            xref_current_source/1,      % ?Source
   57            xref_done/2,                % +Source, -When
   58            xref_built_in/1,            % ?Callable
   59            xref_source_file/3,         % +Spec, -Path, +Source
   60            xref_source_file/4,         % +Spec, -Path, +Source, +Options
   61            xref_public_list/3,         % +File, +Src, +Options
   62            xref_public_list/4,         % +File, -Path, -Export, +Src
   63            xref_public_list/6,         % +File, -Path, -Module, -Export, -Meta, +Src
   64            xref_public_list/7,         % +File, -Path, -Module, -Export, -Public, -Meta, +Src
   65            xref_meta/3,                % +Source, +Goal, -Called
   66            xref_meta/2,                % +Goal, -Called
   67            xref_hook/1,                % ?Callable
   68                                        % XPCE class references
   69            xref_used_class/2,          % ?Source, ?ClassName
   70            xref_defined_class/3        % ?Source, ?ClassName, -How
   71          ]).   72:- autoload(library(apply),[maplist/2,partition/4,maplist/3]).   73:- use_module(library(debug),[debug/3]).   74:- autoload(library(dialect),[expects_dialect/1]).   75:- autoload(library(error),[must_be/2,instantiation_error/1]).   76:- autoload(library(lists),[member/2,append/2,append/3,select/3]).   77:- autoload(library(modules),[in_temporary_module/3]).   78:- autoload(library(operators),[push_op/3]).   79:- autoload(library(option),[option/2,option/3]).   80:- autoload(library(ordsets),[ord_intersect/2,ord_intersection/3]).   81:- autoload(library(prolog_code), [pi_head/2]).   82:- autoload(library(prolog_source),
   83	    [ prolog_canonical_source/2,
   84	      prolog_open_source/2,
   85	      prolog_close_source/1,
   86	      prolog_read_source_term/4
   87	    ]).   88
   89:- if(exists_source(library(shlib))).   90:- autoload(library(shlib),[current_foreign_library/2]).   91:- endif.   92:- autoload(library(solution_sequences),[distinct/2,limit/2]).   93
   94:- if(exists_source(library(pldoc))).   95:- use_module(library(pldoc), []).      % Must be loaded before doc_process
   96:- use_module(library(pldoc/doc_process)).   97
   98:- endif.   99
  100:- predicate_options(xref_source/2, 2,
  101                     [ silent(boolean),
  102                       module(atom),
  103                       register_called(oneof([all,non_iso,non_built_in])),
  104                       comments(oneof([store,collect,ignore])),
  105                       process_include(boolean)
  106                     ]).  107
  108
  109:- dynamic
  110    called/5,                       % Head, Src, From, Cond, Line
  111    (dynamic)/3,                    % Head, Src, Line
  112    (thread_local)/3,               % Head, Src, Line
  113    (multifile)/3,                  % Head, Src, Line
  114    (public)/3,                     % Head, Src, Line
  115    defined/3,                      % Head, Src, Line
  116    meta_goal/3,                    % Head, Called, Src
  117    foreign/3,                      % Head, Src, Line
  118    constraint/3,                   % Head, Src, Line
  119    imported/3,                     % Head, Src, From
  120    exported/2,                     % Head, Src
  121    xmodule/2,                      % Module, Src
  122    uses_file/3,                    % Spec, Src, Path
  123    xop/2,                          % Src, Op
  124    source/2,                       % Src, Time
  125    used_class/2,                   % Name, Src
  126    defined_class/5,                % Name, Super, Summary, Src, Line
  127    (mode)/2,                       % Mode, Src
  128    xoption/2,                      % Src, Option
  129    xflag/4,                        % Name, Value, Src, Line
  130    grammar_rule/2,                 % Head, Src
  131    module_comment/3,               % Src, Title, Comment
  132    pred_comment/4,                 % Head, Src, Summary, Comment
  133    pred_comment_link/3,            % Head, Src, HeadTo
  134    pred_mode/3.                    % Head, Src, Det
  135
  136:- 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.
  173:- predicate_options(xref_source_file/4, 4,
  174                     [ file_type(oneof([txt,prolog,directory])),
  175                       silent(boolean)
  176                     ]).  177:- predicate_options(xref_public_list/3, 3,
  178                     [ path(-atom),
  179                       module(-atom),
  180                       exports(-list(any)),
  181                       public(-list(any)),
  182                       meta(-list(any)),
  183                       silent(boolean)
  184                     ]).  185
  186
  187                 /*******************************
  188                 *            HOOKS             *
  189                 *******************************/
 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).
  216:- multifile
  217    prolog:called_by/4,             % +Goal, +Module, +Context, -Called
  218    prolog:called_by/2,             % +Goal, -Called
  219    prolog:meta_goal/2,             % +Goal, -Pattern
  220    prolog:hook/1,                  % +Callable
  221    prolog:generated_predicate/1,   % :PI
  222    prolog:no_autoload_module/1.    % Module is not suitable for autoloading.
  223
  224:- meta_predicate
  225    prolog:generated_predicate(:).  226
  227:- dynamic
  228    meta_goal/2.  229
  230:- meta_predicate
  231    process_predicates(2, +, +).  232
  233                 /*******************************
  234                 *           BUILT-INS          *
  235                 *******************************/
 hide_called(:Callable, +Src) is semidet
True when the cross-referencer should not include Callable as being called. This is determined by the option register_called.
  243hide_called(Callable, Src) :-
  244    xoption(Src, register_called(Which)),
  245    !,
  246    mode_hide_called(Which, Callable).
  247hide_called(Callable, _) :-
  248    mode_hide_called(non_built_in, Callable).
  249
  250mode_hide_called(all, _) :- !, fail.
  251mode_hide_called(non_iso, _:Goal) :-
  252    goal_name_arity(Goal, Name, Arity),
  253    current_predicate(system:Name/Arity),
  254    predicate_property(system:Goal, iso).
  255mode_hide_called(non_built_in, _:Goal) :-
  256    goal_name_arity(Goal, Name, Arity),
  257    current_predicate(system:Name/Arity),
  258    predicate_property(system:Goal, built_in).
  259mode_hide_called(non_built_in, M:Goal) :-
  260    goal_name_arity(Goal, Name, Arity),
  261    current_predicate(M:Name/Arity),
  262    predicate_property(M:Goal, built_in).
 built_in_predicate(+Callable)
True if Callable is a built-in
  268system_predicate(Goal) :-
  269    goal_name_arity(Goal, Name, Arity),
  270    current_predicate(system:Name/Arity),   % avoid autoloading
  271    predicate_property(system:Goal, built_in),
  272    !.
  273
  274
  275                /********************************
  276                *            TOPLEVEL           *
  277                ********************************/
  278
  279verbose(Src) :-
  280    \+ xoption(Src, silent(true)).
  281
  282:- thread_local
  283    xref_input/2.                   % File, Stream
 xref_source(+Source) is det
 xref_source(+Source, +Options) is det
Generate the cross-reference data for Source if not already done and the source is not modified. Checking for modifications is only done for files. Options processed:
silent(+Boolean)
If true (default false), emit warning messages.
module(+Module)
Define the initial context module to work in.
register_called(+Which)
Determines which calls are registerd. Which is one of all, non_iso or non_built_in.
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).
Arguments:
Source- File specification or XPCE buffer
  311xref_source(Source) :-
  312    xref_source(Source, []).
  313
  314xref_source(Source, Options) :-
  315    prolog_canonical_source(Source, Src),
  316    (   last_modified(Source, Modified)
  317    ->  (   source(Src, Modified)
  318        ->  true
  319        ;   xref_clean(Src),
  320            assert(source(Src, Modified)),
  321            do_xref(Src, Options)
  322        )
  323    ;   xref_clean(Src),
  324        get_time(Now),
  325        assert(source(Src, Now)),
  326        do_xref(Src, Options)
  327    ).
  328
  329do_xref(Src, Options) :-
  330    must_be(list, Options),
  331    setup_call_cleanup(
  332        xref_setup(Src, In, Options, State),
  333        collect(Src, Src, In, Options),
  334        xref_cleanup(State)).
  335
  336last_modified(Source, Modified) :-
  337    prolog:xref_source_time(Source, Modified),
  338    !.
  339last_modified(Source, Modified) :-
  340    atom(Source),
  341    \+ is_global_url(Source),
  342    exists_file(Source),
  343    time_file(Source, Modified).
  344
  345is_global_url(File) :-
  346    sub_atom(File, B, _, _, '://'),
  347    !,
  348    B > 1,
  349    sub_atom(File, 0, B, _, Scheme),
  350    atom_codes(Scheme, Codes),
  351    maplist(between(0'a, 0'z), Codes).
  352
  353xref_setup(Src, In, Options, state(In, Dialect, Xref, [SRef|HRefs])) :-
  354    maplist(assert_option(Src), Options),
  355    assert_default_options(Src),
  356    current_prolog_flag(emulated_dialect, Dialect),
  357    prolog_open_source(Src, In),
  358    set_initial_mode(In, Options),
  359    asserta(xref_input(Src, In), SRef),
  360    set_xref(Xref),
  361    (   verbose(Src)
  362    ->  HRefs = []
  363    ;   asserta((user:thread_message_hook(_,Level,_) :-
  364                     hide_message(Level)),
  365                Ref),
  366        HRefs = [Ref]
  367    ).
  368
  369hide_message(warning).
  370hide_message(error).
  371hide_message(informational).
  372
  373assert_option(_, Var) :-
  374    var(Var),
  375    !,
  376    instantiation_error(Var).
  377assert_option(Src, silent(Boolean)) :-
  378    !,
  379    must_be(boolean, Boolean),
  380    assert(xoption(Src, silent(Boolean))).
  381assert_option(Src, register_called(Which)) :-
  382    !,
  383    must_be(oneof([all,non_iso,non_built_in]), Which),
  384    assert(xoption(Src, register_called(Which))).
  385assert_option(Src, comments(CommentHandling)) :-
  386    !,
  387    must_be(oneof([store,collect,ignore]), CommentHandling),
  388    assert(xoption(Src, comments(CommentHandling))).
  389assert_option(Src, module(Module)) :-
  390    !,
  391    must_be(atom, Module),
  392    assert(xoption(Src, module(Module))).
  393assert_option(Src, process_include(Boolean)) :-
  394    !,
  395    must_be(boolean, Boolean),
  396    assert(xoption(Src, process_include(Boolean))).
  397
  398assert_default_options(Src) :-
  399    (   xref_option_default(Opt),
  400        generalise_term(Opt, Gen),
  401        (   xoption(Src, Gen)
  402        ->  true
  403        ;   assertz(xoption(Src, Opt))
  404        ),
  405        fail
  406    ;   true
  407    ).
  408
  409xref_option_default(silent(false)).
  410xref_option_default(register_called(non_built_in)).
  411xref_option_default(comments(collect)).
  412xref_option_default(process_include(true)).
 xref_cleanup(+State) is det
Restore processing state according to the saved State.
  418xref_cleanup(state(In, Dialect, Xref, Refs)) :-
  419    prolog_close_source(In),
  420    set_prolog_flag(emulated_dialect, Dialect),
  421    set_prolog_flag(xref, Xref),
  422    maplist(erase, Refs).
  423
  424set_xref(Xref) :-
  425    current_prolog_flag(xref, Xref),
  426    set_prolog_flag(xref, true).
  427
  428:- meta_predicate
  429    with_xref(0).  430
  431with_xref(Goal) :-
  432    current_prolog_flag(xref, Xref),
  433    (   Xref == true
  434    ->  call(Goal)
  435    ;   setup_call_cleanup(
  436            set_prolog_flag(xref, true),
  437            Goal,
  438            set_prolog_flag(xref, Xref))
  439    ).
 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.
  449set_initial_mode(_Stream, Options) :-
  450    option(module(Module), Options),
  451    !,
  452    '$set_source_module'(Module).
  453set_initial_mode(Stream, _) :-
  454    stream_property(Stream, file_name(Path)),
  455    source_file_property(Path, load_context(M, _, Opts)),
  456    !,
  457    '$set_source_module'(M),
  458    (   option(dialect(Dialect), Opts)
  459    ->  expects_dialect(Dialect)
  460    ;   true
  461    ).
  462set_initial_mode(_, _) :-
  463    '$set_source_module'(user).
 xref_input_stream(-Stream) is det
Current input stream for cross-referencer.
  469xref_input_stream(Stream) :-
  470    xref_input(_, Var),
  471    !,
  472    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.
  479xref_push_op(Src, P, T, N0) :-
  480    '$current_source_module'(M0),
  481    strip_module(M0:N0, M, N),
  482    (   is_list(N),
  483        N \== []
  484    ->  maplist(push_op(Src, P, T, M), N)
  485    ;   push_op(Src, P, T, M, N)
  486    ).
  487
  488push_op(Src, P, T, M0, N0) :-
  489    strip_module(M0:N0, M, N),
  490    Name = M:N,
  491    valid_op(op(P,T,Name)),
  492    push_op(P, T, Name),
  493    assert_op(Src, op(P,T,Name)),
  494    debug(xref(op), ':- ~w.', [op(P,T,Name)]).
  495
  496valid_op(op(P,T,M:N)) :-
  497    atom(M),
  498    valid_op_name(N),
  499    integer(P),
  500    between(0, 1200, P),
  501    atom(T),
  502    op_type(T).
  503
  504valid_op_name(N) :-
  505    atom(N),
  506    !.
  507valid_op_name(N) :-
  508    N == [].
  509
  510op_type(xf).
  511op_type(yf).
  512op_type(fx).
  513op_type(fy).
  514op_type(xfx).
  515op_type(xfy).
  516op_type(yfx).
 xref_set_prolog_flag(+Flag, +Value, +Src, +Line)
Called when a directive sets a Prolog flag.
  522xref_set_prolog_flag(Flag, Value, Src, Line) :-
  523    atom(Flag),
  524    !,
  525    assertz(xflag(Flag, Value, Src, Line)).
  526xref_set_prolog_flag(_, _, _, _).
 xref_clean(+Source) is det
Reset the database for the given source.
  532xref_clean(Source) :-
  533    prolog_canonical_source(Source, Src),
  534    retractall(called(_, Src, _Origin, _Cond, _Line)),
  535    retractall(dynamic(_, Src, Line)),
  536    retractall(multifile(_, Src, Line)),
  537    retractall(public(_, Src, Line)),
  538    retractall(defined(_, Src, Line)),
  539    retractall(meta_goal(_, _, Src)),
  540    retractall(foreign(_, Src, Line)),
  541    retractall(constraint(_, Src, Line)),
  542    retractall(imported(_, Src, _From)),
  543    retractall(exported(_, Src)),
  544    retractall(uses_file(_, Src, _)),
  545    retractall(xmodule(_, Src)),
  546    retractall(xop(Src, _)),
  547    retractall(grammar_rule(_, Src)),
  548    retractall(xoption(Src, _)),
  549    retractall(xflag(_Name, _Value, Src, Line)),
  550    retractall(source(Src, _)),
  551    retractall(used_class(_, Src)),
  552    retractall(defined_class(_, _, _, Src, _)),
  553    retractall(mode(_, Src)),
  554    retractall(module_comment(Src, _, _)),
  555    retractall(pred_comment(_, Src, _, _)),
  556    retractall(pred_comment_link(_, Src, _)),
  557    retractall(pred_mode(_, Src, _)).
  558
  559
  560                 /*******************************
  561                 *          READ RESULTS        *
  562                 *******************************/
 xref_current_source(?Source)
Check what sources have been analysed.
  568xref_current_source(Source) :-
  569    source(Source, _Time).
 xref_done(+Source, -Time) is det
Cross-reference executed at Time
  576xref_done(Source, Time) :-
  577    prolog_canonical_source(Source, Src),
  578    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.
  600xref_called(Source, Called, By) :-
  601    xref_called(Source, Called, By, _).
  602
  603xref_called(Source, Called, By, Cond) :-
  604    canonical_source(Source, Src),
  605    distinct(Called-By, called(Called, Src, By, Cond, _)).
  606
  607xref_called(Source, Called, By, Cond, Line) :-
  608    canonical_source(Source, Src),
  609    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.
  631xref_defined(Source, Called, How) :-
  632    nonvar(Source),
  633    !,
  634    canonical_source(Source, Src),
  635    xref_defined2(How, Src, Called).
  636xref_defined(Source, Called, How) :-
  637    xref_defined2(How, Src, Called),
  638    canonical_source(Source, Src).
  639
  640xref_defined2(dynamic(Line), Src, Called) :-
  641    dynamic(Called, Src, Line).
  642xref_defined2(thread_local(Line), Src, Called) :-
  643    thread_local(Called, Src, Line).
  644xref_defined2(multifile(Line), Src, Called) :-
  645    multifile(Called, Src, Line).
  646xref_defined2(public(Line), Src, Called) :-
  647    public(Called, Src, Line).
  648xref_defined2(local(Line), Src, Called) :-
  649    defined(Called, Src, Line).
  650xref_defined2(foreign(Line), Src, Called) :-
  651    foreign(Called, Src, Line).
  652xref_defined2(constraint(Line), Src, Called) :-
  653    constraint(Called, Src, Line).
  654xref_defined2(imported(From), Src, Called) :-
  655    imported(Called, Src, From).
  656xref_defined2(dcg, Src, Called) :-
  657    grammar_rule(Called, Src).
 xref_definition_line(+How, -Line)
If the 3th argument of xref_defined contains line info, return this in Line.
  665xref_definition_line(local(Line),        Line).
  666xref_definition_line(dynamic(Line),      Line).
  667xref_definition_line(thread_local(Line), Line).
  668xref_definition_line(multifile(Line),    Line).
  669xref_definition_line(public(Line),       Line).
  670xref_definition_line(constraint(Line),   Line).
  671xref_definition_line(foreign(Line),      Line).
 xref_exported(?Source, ?Head) is nondet
True when Source exports Head.
  678xref_exported(Source, Called) :-
  679    prolog_canonical_source(Source, Src),
  680    exported(Called, Src).
 xref_module(?Source, ?Module) is nondet
True if Module is defined in Source.
  686xref_module(Source, Module) :-
  687    nonvar(Source),
  688    !,
  689    prolog_canonical_source(Source, Src),
  690    xmodule(Module, Src).
  691xref_module(Source, Module) :-
  692    xmodule(Module, Src),
  693    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>.
  703xref_uses_file(Source, Spec, Path) :-
  704    prolog_canonical_source(Source, Src),
  705    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)
  715xref_op(Source, Op) :-
  716    prolog_canonical_source(Source, Src),
  717    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.
  725xref_prolog_flag(Source, Flag, Value, Line) :-
  726    prolog_canonical_source(Source, Src),
  727    xflag(Flag, Value, Src, Line).
  728
  729xref_built_in(Head) :-
  730    system_predicate(Head).
  731
  732xref_used_class(Source, Class) :-
  733    prolog_canonical_source(Source, Src),
  734    used_class(Class, Src).
  735
  736xref_defined_class(Source, Class, local(Line, Super, Summary)) :-
  737    prolog_canonical_source(Source, Src),
  738    defined_class(Class, Super, Summary, Src, Line),
  739    integer(Line),
  740    !.
  741xref_defined_class(Source, Class, file(File)) :-
  742    prolog_canonical_source(Source, Src),
  743    defined_class(Class, _, _, Src, file(File)).
  744
  745:- thread_local
  746    current_cond/1,
  747    source_line/1,
  748    current_test_unit/2.  749
  750current_source_line(Line) :-
  751    source_line(Var),
  752    !,
  753    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 shich we read the program.
  761collect(Src, File, In, Options) :-
  762    (   Src == File
  763    ->  SrcSpec = Line
  764    ;   SrcSpec = (File:Line)
  765    ),
  766    option(comments(CommentHandling), Options, collect),
  767    (   CommentHandling == ignore
  768    ->  CommentOptions = [],
  769        Comments = []
  770    ;   CommentHandling == store
  771    ->  CommentOptions = [ process_comment(true) ],
  772        Comments = [],
  773	set_prolog_flag(xref_store_comments, true)
  774    ;   CommentOptions = [ comments(Comments) ]
  775    ),
  776    repeat,
  777        catch(prolog_read_source_term(
  778                  In, Term, Expanded,
  779                  [ term_position(TermPos)
  780                  | CommentOptions
  781                  ]),
  782              E, report_syntax_error(E, Src, [])),
  783        update_condition(Term),
  784        stream_position_data(line_count, TermPos, Line),
  785        setup_call_cleanup(
  786            asserta(source_line(SrcSpec), Ref),
  787            catch(process(Expanded, Comments, Term, TermPos, Src, EOF),
  788                  E, print_message(error, E)),
  789            erase(Ref)),
  790        EOF == true,
  791    !,
  792    set_prolog_flag(xref_store_comments, false).
  793
  794report_syntax_error(E, _, _) :-
  795    fatal_error(E),
  796    throw(E).
  797report_syntax_error(_, _, Options) :-
  798    option(silent(true), Options),
  799    !,
  800    fail.
  801report_syntax_error(E, Src, _Options) :-
  802    (   verbose(Src)
  803    ->  print_message(error, E)
  804    ;   true
  805    ),
  806    fail.
  807
  808fatal_error(time_limit_exceeded).
  809fatal_error(error(resource_error(_),_)).
 update_condition(+Term) is det
Update the condition under which the current code is compiled.
  815update_condition((:-Directive)) :-
  816    !,
  817    update_cond(Directive).
  818update_condition(_).
  819
  820update_cond(if(Cond)) :-
  821    !,
  822    asserta(current_cond(Cond)).
  823update_cond(else) :-
  824    retract(current_cond(C0)),
  825    !,
  826    assert(current_cond(\+C0)).
  827update_cond(elif(Cond)) :-
  828    retract(current_cond(C0)),
  829    !,
  830    assert(current_cond((\+C0,Cond))).
  831update_cond(endif) :-
  832    retract(current_cond(_)),
  833    !.
  834update_cond(_).
 current_condition(-Condition) is det
Condition is the current compilation condition as defined by the :- if/1 directive and friends.
  841current_condition(Condition) :-
  842    \+ current_cond(_),
  843    !,
  844    Condition = true.
  845current_condition(Condition) :-
  846    findall(C, current_cond(C), List),
  847    list_to_conj(List, Condition).
  848
  849list_to_conj([], true).
  850list_to_conj([C], C) :- !.
  851list_to_conj([H|T], (H,C)) :-
  852    list_to_conj(T, C).
  853
  854
  855                 /*******************************
  856                 *           PROCESS            *
  857                 *******************************/
 process(+Expanded, +Comments, +Term, +TermPos, +Src, -EOF) is det
Process a source term that has been subject to term expansion as well as its optional leading structured comments.
Arguments:
TermPos- is the term position that describes the start of the term. We need this to find leading comments.
EOF- is unified with a boolean to indicate whether or not processing was stopped because end_of_file was processed.
  869process(Expanded, Comments, Term0, TermPos, Src, EOF) :-
  870    is_list(Expanded),                          % term_expansion into list.
  871    !,
  872    (   member(Term, Expanded),
  873        process(Term, Term0, Src),
  874        Term == end_of_file
  875    ->  EOF = true
  876    ;   EOF = false
  877    ),
  878    xref_comments(Comments, TermPos, Src).
  879process(end_of_file, _, _, _, _, true) :-
  880    !.
  881process(Term, Comments, Term0, TermPos, Src, false) :-
  882    process(Term, Term0, Src),
  883    xref_comments(Comments, TermPos, Src).
 process(+Term, +Term0, +Src) is det
  887process(_, Term0, _) :-
  888    ignore_raw_term(Term0),
  889    !.
  890process(Head :- Body, Head0 --> _, Src) :-
  891    pi_head(F/A, Head),
  892    pi_head(F/A0, Head0),
  893    A =:= A0 + 2,
  894    !,
  895    assert_grammar_rule(Src, Head),
  896    process((Head :- Body), Src).
  897process(Term, _Term0, Src) :-
  898    process(Term, Src).
  899
  900ignore_raw_term((:- predicate_options(_,_,_))).
 process(+Term, +Src) is det
  904process(Var, _) :-
  905    var(Var),
  906    !.                    % Warn?
  907process(end_of_file, _) :- !.
  908process((:- Directive), Src) :-
  909    !,
  910    process_directive(Directive, Src),
  911    !.
  912process((?- Directive), Src) :-
  913    !,
  914    process_directive(Directive, Src),
  915    !.
  916process((Head :- Body), Src) :-
  917    !,
  918    assert_defined(Src, Head),
  919    process_body(Body, Head, Src).
  920process((Left => Body), Src) :-
  921    !,
  922    (   nonvar(Left),
  923        Left = (Head, Guard)
  924    ->  assert_defined(Src, Head),
  925        process_body(Guard, Head, Src),
  926        process_body(Body, Head, Src)
  927    ;   assert_defined(Src, Left),
  928        process_body(Body, Left, Src)
  929    ).
  930process(?=>(Head, Body), Src) :-
  931    !,
  932    assert_defined(Src, Head),
  933    process_body(Body, Head, Src).
  934process('$source_location'(_File, _Line):Clause, Src) :-
  935    !,
  936    process(Clause, Src).
  937process(Term, Src) :-
  938    process_chr(Term, Src),
  939    !.
  940process(M:(Head :- Body), Src) :-
  941    !,
  942    process((M:Head :- M:Body), Src).
  943process(Head, Src) :-
  944    assert_defined(Src, Head).
  945
  946
  947                 /*******************************
  948                 *            COMMENTS          *
  949                 *******************************/
 xref_comments(+Comments, +FilePos, +Src) is det
  953xref_comments([], _Pos, _Src).
  954:- if(current_predicate(parse_comment/3)).  955xref_comments([Pos-Comment|T], TermPos, Src) :-
  956    (   Pos @> TermPos              % comments inside term
  957    ->  true
  958    ;   stream_position_data(line_count, Pos, Line),
  959        FilePos = Src:Line,
  960        (   parse_comment(Comment, FilePos, Parsed)
  961        ->  assert_comments(Parsed, Src)
  962        ;   true
  963        ),
  964        xref_comments(T, TermPos, Src)
  965    ).
  966
  967assert_comments([], _).
  968assert_comments([H|T], Src) :-
  969    assert_comment(H, Src),
  970    assert_comments(T, Src).
  971
  972assert_comment(section(_Id, Title, Comment), Src) :-
  973    assertz(module_comment(Src, Title, Comment)).
  974assert_comment(predicate(PI, Summary, Comment), Src) :-
  975    pi_to_head(PI, Src, Head),
  976    assertz(pred_comment(Head, Src, Summary, Comment)).
  977assert_comment(link(PI, PITo), Src) :-
  978    pi_to_head(PI, Src, Head),
  979    pi_to_head(PITo, Src, HeadTo),
  980    assertz(pred_comment_link(Head, Src, HeadTo)).
  981assert_comment(mode(Head, Det), Src) :-
  982    assertz(pred_mode(Head, Src, Det)).
  983
  984pi_to_head(PI, Src, Head) :-
  985    pi_to_head(PI, Head0),
  986    (   Head0 = _:_
  987    ->  strip_module(Head0, M, Plain),
  988        (   xmodule(M, Src)
  989        ->  Head = Plain
  990        ;   Head = M:Plain
  991        )
  992    ;   Head = Head0
  993    ).
  994:- endif.
 xref_comment(?Source, ?Title, ?Comment) is nondet
Is true when Source has a section comment with Title and Comment
 1000xref_comment(Source, Title, Comment) :-
 1001    canonical_source(Source, Src),
 1002    module_comment(Src, Title, Comment).
 xref_comment(?Source, ?Head, ?Summary, ?Comment) is nondet
Is true when Head in Source has the given PlDoc comment.
 1008xref_comment(Source, Head, Summary, Comment) :-
 1009    canonical_source(Source, Src),
 1010    (   pred_comment(Head, Src, Summary, Comment)
 1011    ;   pred_comment_link(Head, Src, HeadTo),
 1012        pred_comment(HeadTo, Src, Summary, Comment)
 1013    ).
 xref_mode(?Source, ?Mode, ?Det) is nondet
Is true when Source provides a predicate with Mode and determinism.
 1020xref_mode(Source, Mode, Det) :-
 1021    canonical_source(Source, Src),
 1022    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.
 1029xref_option(Source, Option) :-
 1030    canonical_source(Source, Src),
 1031    xoption(Src, Option).
 1032
 1033
 1034                 /********************************
 1035                 *           DIRECTIVES         *
 1036                 ********************************/
 1037
 1038process_directive(Var, _) :-
 1039    var(Var),
 1040    !.                    % error, but that isn't our business
 1041process_directive(Dir, _Src) :-
 1042    debug(xref(directive), 'Processing :- ~q', [Dir]),
 1043    fail.
 1044process_directive((A,B), Src) :-       % TBD: what about other control
 1045    !,
 1046    process_directive(A, Src),      % structures?
 1047    process_directive(B, Src).
 1048process_directive(List, Src) :-
 1049    is_list(List),
 1050    !,
 1051    process_directive(consult(List), Src).
 1052process_directive(use_module(File, Import), Src) :-
 1053    process_use_module2(File, Import, Src, false).
 1054process_directive(autoload(File, Import), Src) :-
 1055    process_use_module2(File, Import, Src, false).
 1056process_directive(require(Import), Src) :-
 1057    process_requires(Import, Src).
 1058process_directive(expects_dialect(Dialect), Src) :-
 1059    process_directive(use_module(library(dialect/Dialect)), Src),
 1060    expects_dialect(Dialect).
 1061process_directive(reexport(File, Import), Src) :-
 1062    process_use_module2(File, Import, Src, true).
 1063process_directive(reexport(Modules), Src) :-
 1064    process_use_module(Modules, Src, true).
 1065process_directive(autoload(Modules), Src) :-
 1066    process_use_module(Modules, Src, false).
 1067process_directive(use_module(Modules), Src) :-
 1068    process_use_module(Modules, Src, false).
 1069process_directive(consult(Modules), Src) :-
 1070    process_use_module(Modules, Src, false).
 1071process_directive(ensure_loaded(Modules), Src) :-
 1072    process_use_module(Modules, Src, false).
 1073process_directive(load_files(Files, _Options), Src) :-
 1074    process_use_module(Files, Src, false).
 1075process_directive(include(Files), Src) :-
 1076    process_include(Files, Src).
 1077process_directive(dynamic(Dynamic), Src) :-
 1078    process_predicates(assert_dynamic, Dynamic, Src).
 1079process_directive(dynamic(Dynamic, _Options), Src) :-
 1080    process_predicates(assert_dynamic, Dynamic, Src).
 1081process_directive(thread_local(Dynamic), Src) :-
 1082    process_predicates(assert_thread_local, Dynamic, Src).
 1083process_directive(multifile(Dynamic), Src) :-
 1084    process_predicates(assert_multifile, Dynamic, Src).
 1085process_directive(public(Public), Src) :-
 1086    process_predicates(assert_public, Public, Src).
 1087process_directive(export(Export), Src) :-
 1088    process_predicates(assert_export, Export, Src).
 1089process_directive(import(Import), Src) :-
 1090    process_import(Import, Src).
 1091process_directive(module(Module, Export), Src) :-
 1092    assert_module(Src, Module),
 1093    assert_module_export(Src, Export).
 1094process_directive(module(Module, Export, Import), Src) :-
 1095    assert_module(Src, Module),
 1096    assert_module_export(Src, Export),
 1097    assert_module3(Import, Src).
 1098process_directive(begin_tests(Unit, _Options), Src) :-
 1099    enter_test_unit(Unit, Src).
 1100process_directive(begin_tests(Unit), Src) :-
 1101    enter_test_unit(Unit, Src).
 1102process_directive(end_tests(Unit), Src) :-
 1103    leave_test_unit(Unit, Src).
 1104process_directive('$set_source_module'(system), Src) :-
 1105    assert_module(Src, system).     % hack for handling boot/init.pl
 1106process_directive(pce_begin_class_definition(Name, Meta, Super, Doc), Src) :-
 1107    assert_defined_class(Src, Name, Meta, Super, Doc).
 1108process_directive(pce_autoload(Name, From), Src) :-
 1109    assert_defined_class(Src, Name, imported_from(From)).
 1110
 1111process_directive(op(P, A, N), Src) :-
 1112    xref_push_op(Src, P, A, N).
 1113process_directive(set_prolog_flag(Flag, Value), Src) :-
 1114    (   Flag == character_escapes
 1115    ->  set_prolog_flag(character_escapes, Value)
 1116    ;   true
 1117    ),
 1118    current_source_line(Line),
 1119    xref_set_prolog_flag(Flag, Value, Src, Line).
 1120process_directive(style_check(X), _) :-
 1121    style_check(X).
 1122process_directive(encoding(Enc), _) :-
 1123    (   xref_input_stream(Stream)
 1124    ->  catch(set_stream(Stream, encoding(Enc)), _, true)
 1125    ;   true                        % can this happen?
 1126    ).
 1127process_directive(pce_expansion:push_compile_operators, _) :-
 1128    '$current_source_module'(SM),
 1129    call(pce_expansion:push_compile_operators(SM)). % call to avoid xref
 1130process_directive(pce_expansion:pop_compile_operators, _) :-
 1131    call(pce_expansion:pop_compile_operators).
 1132process_directive(meta_predicate(Meta), Src) :-
 1133    process_meta_predicate(Meta, Src).
 1134process_directive(arithmetic_function(FSpec), Src) :-
 1135    arith_callable(FSpec, Goal),
 1136    !,
 1137    current_source_line(Line),
 1138    assert_called(Src, '<directive>'(Line), Goal, Line).
 1139process_directive(format_predicate(_, Goal), Src) :-
 1140    !,
 1141    current_source_line(Line),
 1142    assert_called(Src, '<directive>'(Line), Goal, Line).
 1143process_directive(if(Cond), Src) :-
 1144    !,
 1145    current_source_line(Line),
 1146    assert_called(Src, '<directive>'(Line), Cond, Line).
 1147process_directive(elif(Cond), Src) :-
 1148    !,
 1149    current_source_line(Line),
 1150    assert_called(Src, '<directive>'(Line), Cond, Line).
 1151process_directive(else, _) :- !.
 1152process_directive(endif, _) :- !.
 1153process_directive(Goal, Src) :-
 1154    current_source_line(Line),
 1155    process_body(Goal, '<directive>'(Line), Src).
 process_meta_predicate(+Decl, +Src)
Create meta_goal/3 facts from the meta-goal declaration.
 1161process_meta_predicate((A,B), Src) :-
 1162    !,
 1163    process_meta_predicate(A, Src),
 1164    process_meta_predicate(B, Src).
 1165process_meta_predicate(Decl, Src) :-
 1166    process_meta_head(Src, Decl).
 1167
 1168process_meta_head(Src, Decl) :-         % swapped arguments for maplist
 1169    compound(Decl),
 1170    compound_name_arity(Decl, Name, Arity),
 1171    compound_name_arity(Head, Name, Arity),
 1172    meta_args(1, Arity, Decl, Head, Meta),
 1173    (   (   prolog:meta_goal(Head, _)
 1174        ;   prolog:called_by(Head, _, _, _)
 1175        ;   prolog:called_by(Head, _)
 1176        ;   meta_goal(Head, _)
 1177        )
 1178    ->  true
 1179    ;   assert(meta_goal(Head, Meta, Src))
 1180    ).
 1181
 1182meta_args(I, Arity, _, _, []) :-
 1183    I > Arity,
 1184    !.
 1185meta_args(I, Arity, Decl, Head, [H|T]) :-               % 0
 1186    arg(I, Decl, 0),
 1187    !,
 1188    arg(I, Head, H),
 1189    I2 is I + 1,
 1190    meta_args(I2, Arity, Decl, Head, T).
 1191meta_args(I, Arity, Decl, Head, [H|T]) :-               % ^
 1192    arg(I, Decl, ^),
 1193    !,
 1194    arg(I, Head, EH),
 1195    setof_goal(EH, H),
 1196    I2 is I + 1,
 1197    meta_args(I2, Arity, Decl, Head, T).
 1198meta_args(I, Arity, Decl, Head, [//(H)|T]) :-
 1199    arg(I, Decl, //),
 1200    !,
 1201    arg(I, Head, H),
 1202    I2 is I + 1,
 1203    meta_args(I2, Arity, Decl, Head, T).
 1204meta_args(I, Arity, Decl, Head, [H+A|T]) :-             % I --> H+I
 1205    arg(I, Decl, A),
 1206    integer(A), A > 0,
 1207    !,
 1208    arg(I, Head, H),
 1209    I2 is I + 1,
 1210    meta_args(I2, Arity, Decl, Head, T).
 1211meta_args(I, Arity, Decl, Head, Meta) :-
 1212    I2 is I + 1,
 1213    meta_args(I2, Arity, Decl, Head, Meta).
 1214
 1215
 1216              /********************************
 1217              *             BODY              *
 1218              ********************************/
 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).
 1227xref_meta(Source, Head, Called) :-
 1228    canonical_source(Source, Src),
 1229    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.
 1244xref_meta_src(Head, Called, Src) :-
 1245    meta_goal(Head, Called, Src),
 1246    !.
 1247xref_meta_src(Head, Called, _) :-
 1248    xref_meta(Head, Called),
 1249    !.
 1250xref_meta_src(Head, Called, _) :-
 1251    compound(Head),
 1252    compound_name_arity(Head, Name, Arity),
 1253    apply_pred(Name),
 1254    Arity > 5,
 1255    !,
 1256    Extra is Arity - 1,
 1257    arg(1, Head, G),
 1258    Called = [G+Extra].
 1259xref_meta_src(Head, Called, _) :-
 1260    with_xref(predicate_property('$xref_tmp':Head, meta_predicate(Meta))),
 1261    !,
 1262    Meta =.. [_|Args],
 1263    meta_args(Args, 1, Head, Called).
 1264
 1265meta_args([], _, _, []).
 1266meta_args([H0|T0], I, Head, [H|T]) :-
 1267    xargs(H0, N),
 1268    !,
 1269    arg(I, Head, A),
 1270    (   N == 0
 1271    ->  H = A
 1272    ;   H = (A+N)
 1273    ),
 1274    I2 is I+1,
 1275    meta_args(T0, I2, Head, T).
 1276meta_args([_|T0], I, Head, T) :-
 1277    I2 is I+1,
 1278    meta_args(T0, I2, Head, T).
 1279
 1280xargs(N, N) :- integer(N), !.
 1281xargs(//, 2).
 1282xargs(^, 0).
 1283
 1284apply_pred(call).                               % built-in
 1285apply_pred(maplist).                            % library(apply_macros)
 1286
 1287xref_meta((A, B),               [A, B]).
 1288xref_meta((A; B),               [A, B]).
 1289xref_meta((A| B),               [A, B]).
 1290xref_meta((A -> B),             [A, B]).
 1291xref_meta((A *-> B),            [A, B]).
 1292xref_meta(findall(_V,G,_L),     [G]).
 1293xref_meta(findall(_V,G,_L,_T),  [G]).
 1294xref_meta(findnsols(_N,_V,G,_L),    [G]).
 1295xref_meta(findnsols(_N,_V,G,_L,_T), [G]).
 1296xref_meta(setof(_V, EG, _L),    [G]) :-
 1297    setof_goal(EG, G).
 1298xref_meta(bagof(_V, EG, _L),    [G]) :-
 1299    setof_goal(EG, G).
 1300xref_meta(forall(A, B),         [A, B]).
 1301xref_meta(maplist(G,_),         [G+1]).
 1302xref_meta(maplist(G,_,_),       [G+2]).
 1303xref_meta(maplist(G,_,_,_),     [G+3]).
 1304xref_meta(maplist(G,_,_,_,_),   [G+4]).
 1305xref_meta(map_list_to_pairs(G,_,_), [G+2]).
 1306xref_meta(map_assoc(G, _),      [G+1]).
 1307xref_meta(map_assoc(G, _, _),   [G+2]).
 1308xref_meta(checklist(G, _L),     [G+1]).
 1309xref_meta(sublist(G, _, _),     [G+1]).
 1310xref_meta(include(G, _, _),     [G+1]).
 1311xref_meta(exclude(G, _, _),     [G+1]).
 1312xref_meta(partition(G, _, _, _, _),     [G+2]).
 1313xref_meta(partition(G, _, _, _),[G+1]).
 1314xref_meta(call(G),              [G]).
 1315xref_meta(call(G, _),           [G+1]).
 1316xref_meta(call(G, _, _),        [G+2]).
 1317xref_meta(call(G, _, _, _),     [G+3]).
 1318xref_meta(call(G, _, _, _, _),  [G+4]).
 1319xref_meta(not(G),               [G]).
 1320xref_meta(notrace(G),           [G]).
 1321xref_meta('$notrace'(G),        [G]).
 1322xref_meta(\+(G),                [G]).
 1323xref_meta(ignore(G),            [G]).
 1324xref_meta(once(G),              [G]).
 1325xref_meta(initialization(G),    [G]).
 1326xref_meta(initialization(G,_),  [G]).
 1327xref_meta(retract(Rule),        [G]) :- head_of(Rule, G).
 1328xref_meta(clause(G, _),         [G]).
 1329xref_meta(clause(G, _, _),      [G]).
 1330xref_meta(phrase(G, _A),        [//(G)]).
 1331xref_meta(phrase(G, _A, _R),    [//(G)]).
 1332xref_meta(call_dcg(G, _A, _R),  [//(G)]).
 1333xref_meta(phrase_from_file(G,_),[//(G)]).
 1334xref_meta(catch(A, _, B),       [A, B]).
 1335xref_meta(catch_with_backtrace(A, _, B), [A, B]).
 1336xref_meta(thread_create(A,_,_), [A]).
 1337xref_meta(thread_create(A,_),   [A]).
 1338xref_meta(thread_signal(_,A),   [A]).
 1339xref_meta(thread_idle(A,_),     [A]).
 1340xref_meta(thread_at_exit(A),    [A]).
 1341xref_meta(thread_initialization(A), [A]).
 1342xref_meta(engine_create(_,A,_), [A]).
 1343xref_meta(engine_create(_,A,_,_), [A]).
 1344xref_meta(transaction(A),       [A]).
 1345xref_meta(transaction(A,B,_),   [A,B]).
 1346xref_meta(snapshot(A),          [A]).
 1347xref_meta(predsort(A,_,_),      [A+3]).
 1348xref_meta(call_cleanup(A, B),   [A, B]).
 1349xref_meta(call_cleanup(A, _, B),[A, B]).
 1350xref_meta(setup_call_cleanup(A, B, C),[A, B, C]).
 1351xref_meta(setup_call_catcher_cleanup(A, B, _, C),[A, B, C]).
 1352xref_meta(call_residue_vars(A,_), [A]).
 1353xref_meta(with_mutex(_,A),      [A]).
 1354xref_meta(assume(G),            [G]).   % library(debug)
 1355xref_meta(assertion(G),         [G]).   % library(debug)
 1356xref_meta(freeze(_, G),         [G]).
 1357xref_meta(when(C, A),           [C, A]).
 1358xref_meta(time(G),              [G]).   % development system
 1359xref_meta(call_time(G, _),      [G]).   % development system
 1360xref_meta(call_time(G, _, _),   [G]).   % development system
 1361xref_meta(profile(G),           [G]).
 1362xref_meta(at_halt(G),           [G]).
 1363xref_meta(call_with_time_limit(_, G), [G]).
 1364xref_meta(call_with_depth_limit(G, _, _), [G]).
 1365xref_meta(call_with_inference_limit(G, _, _), [G]).
 1366xref_meta(alarm(_, G, _),       [G]).
 1367xref_meta(alarm(_, G, _, _),    [G]).
 1368xref_meta('$add_directive_wic'(G), [G]).
 1369xref_meta(with_output_to(_, G), [G]).
 1370xref_meta(if(G),                [G]).
 1371xref_meta(elif(G),              [G]).
 1372xref_meta(meta_options(G,_,_),  [G+1]).
 1373xref_meta(on_signal(_,_,H),     [H+1]) :- H \== default.
 1374xref_meta(distinct(G),          [G]).   % library(solution_sequences)
 1375xref_meta(distinct(_, G),       [G]).
 1376xref_meta(order_by(_, G),       [G]).
 1377xref_meta(limit(_, G),          [G]).
 1378xref_meta(offset(_, G),         [G]).
 1379xref_meta(reset(G,_,_),         [G]).
 1380xref_meta(prolog_listen(Ev,G),  [G+N]) :- event_xargs(Ev, N).
 1381xref_meta(prolog_listen(Ev,G,_),[G+N]) :- event_xargs(Ev, N).
 1382xref_meta(tnot(G),		[G]).
 1383xref_meta(not_exists(G),	[G]).
 1384xref_meta(with_tty_raw(G),	[G]).
 1385xref_meta(residual_goals(G),    [G+2]).
 1386
 1387                                        % XPCE meta-predicates
 1388xref_meta(pce_global(_, new(_)), _) :- !, fail.
 1389xref_meta(pce_global(_, B),     [B+1]).
 1390xref_meta(ifmaintainer(G),      [G]).   % used in manual
 1391xref_meta(listen(_, G),         [G]).   % library(broadcast)
 1392xref_meta(listen(_, _, G),      [G]).
 1393xref_meta(in_pce_thread(G),     [G]).
 1394
 1395xref_meta(G, Meta) :-                   % call user extensions
 1396    prolog:meta_goal(G, Meta).
 1397xref_meta(G, Meta) :-                   % Generated from :- meta_predicate
 1398    meta_goal(G, Meta).
 1399
 1400setof_goal(EG, G) :-
 1401    var(EG), !, G = EG.
 1402setof_goal(_^EG, G) :-
 1403    !,
 1404    setof_goal(EG, G).
 1405setof_goal(G, G).
 1406
 1407event_xargs(abort,            0).
 1408event_xargs(erase,            1).
 1409event_xargs(break,            3).
 1410event_xargs(frame_finished,   1).
 1411event_xargs(thread_exit,      1).
 1412event_xargs(this_thread_exit, 0).
 1413event_xargs(PI,               2) :- pi_to_head(PI, _).
 head_of(+Rule, -Head)
Get the head for a retract call.
 1419head_of(Var, _) :-
 1420    var(Var), !, fail.
 1421head_of((Head :- _), Head).
 1422head_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.
 1430xref_hook(Hook) :-
 1431    prolog:hook(Hook).
 1432xref_hook(Hook) :-
 1433    hook(Hook).
 1434
 1435
 1436hook(attr_portray_hook(_,_)).
 1437hook(attr_unify_hook(_,_)).
 1438hook(attribute_goals(_,_,_)).
 1439hook(goal_expansion(_,_)).
 1440hook(term_expansion(_,_)).
 1441hook(resource(_,_,_)).
 1442hook('$pred_option'(_,_,_,_)).
 1443
 1444hook(emacs_prolog_colours:goal_classification(_,_)).
 1445hook(emacs_prolog_colours:goal_colours(_,_)).
 1446hook(emacs_prolog_colours:identify(_,_)).
 1447hook(emacs_prolog_colours:style(_,_)).
 1448hook(emacs_prolog_colours:term_colours(_,_)).
 1449hook(pce_principal:get_implementation(_,_,_,_)).
 1450hook(pce_principal:pce_class(_,_,_,_,_,_)).
 1451hook(pce_principal:pce_lazy_get_method(_,_,_)).
 1452hook(pce_principal:pce_lazy_send_method(_,_,_)).
 1453hook(pce_principal:pce_uses_template(_,_)).
 1454hook(pce_principal:send_implementation(_,_,_)).
 1455hook(predicate_options:option_decl(_,_,_)).
 1456hook(prolog:debug_control_hook(_)).
 1457hook(prolog:error_message(_,_,_)).
 1458hook(prolog:expand_answer(_,_,_)).
 1459hook(prolog:general_exception(_,_)).
 1460hook(prolog:help_hook(_)).
 1461hook(prolog:locate_clauses(_,_)).
 1462hook(prolog:message(_,_,_)).
 1463hook(prolog:message_context(_,_,_)).
 1464hook(prolog:message_line_element(_,_)).
 1465hook(prolog:message_location(_,_,_)).
 1466hook(prolog:predicate_summary(_,_)).
 1467hook(prolog:prolog_exception_hook(_,_,_,_,_)).
 1468hook(prolog:residual_goals(_,_)).
 1469hook(prolog:show_profile_hook(_,_)).
 1470hook(prolog_edit:load).
 1471hook(prolog_edit:locate(_,_,_)).
 1472hook(sandbox:safe_directive(_)).
 1473hook(sandbox:safe_global_variable(_)).
 1474hook(sandbox:safe_meta(_,_)).
 1475hook(sandbox:safe_meta_predicate(_)).
 1476hook(sandbox:safe_primitive(_)).
 1477hook(sandbox:safe_prolog_flag(_,_)).
 1478hook(shlib:unload_all_foreign_libraries).
 1479hook(system:'$foreign_registered'(_, _)).
 1480hook(user:exception(_,_,_)).
 1481hook(user:expand_answer(_,_)).
 1482hook(user:expand_query(_,_,_,_)).
 1483hook(user:file_search_path(_,_)).
 1484hook(user:library_directory(_)).
 1485hook(user:message_hook(_,_,_)).
 1486hook(user:portray(_)).
 1487hook(user:prolog_clause_name(_,_)).
 1488hook(user:prolog_list_goal(_)).
 1489hook(user:prolog_predicate_name(_,_)).
 1490hook(user:prolog_trace_interception(_,_,_,_)).
 arith_callable(+Spec, -Callable)
Translate argument of arithmetic_function/1 into a callable term
 1496arith_callable(Var, _) :-
 1497    var(Var), !, fail.
 1498arith_callable(Module:Spec, Module:Goal) :-
 1499    !,
 1500    arith_callable(Spec, Goal).
 1501arith_callable(Name/Arity, Goal) :-
 1502    PredArity is Arity + 1,
 1503    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.

 1514process_body(Body, Origin, Src) :-
 1515    forall(limit(100, process_goal(Body, Origin, Src, _Partial)),
 1516           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.
 1523process_goal(Var, _, _, _) :-
 1524    var(Var),
 1525    !.
 1526process_goal(_:Goal, _, _, _) :-
 1527    var(Goal),
 1528    !.
 1529process_goal(Goal, Origin, Src, P) :-
 1530    Goal = (_,_),                               % problems
 1531    !,
 1532    phrase(conjunction(Goal), Goals),
 1533    process_conjunction(Goals, Origin, Src, P).
 1534process_goal(Goal, Origin, Src, _) :-           % Final disjunction, no
 1535    Goal = (_;_),                               % problems
 1536    !,
 1537    phrase(disjunction(Goal), Goals),
 1538    forall(member(G, Goals),
 1539           process_body(G, Origin, Src)).
 1540process_goal(Goal, Origin, Src, P) :-
 1541    (   (   xmodule(M, Src)
 1542        ->  true
 1543        ;   M = user
 1544        ),
 1545        pi_head(PI, M:Goal),
 1546        (   current_predicate(PI),
 1547            predicate_property(M:Goal, imported_from(IM))
 1548        ->  true
 1549        ;   PI = M:Name/Arity,
 1550            '$find_library'(M, Name, Arity, IM, _Library)
 1551        ->  true
 1552        ;   IM = M
 1553        ),
 1554        prolog:called_by(Goal, IM, M, Called)
 1555    ;   prolog:called_by(Goal, Called)
 1556    ),
 1557    !,
 1558    must_be(list, Called),
 1559    current_source_line(Here),
 1560    assert_called(Src, Origin, Goal, Here),
 1561    process_called_list(Called, Origin, Src, P).
 1562process_goal(Goal, Origin, Src, _) :-
 1563    process_xpce_goal(Goal, Origin, Src),
 1564    !.
 1565process_goal(load_foreign_library(File), _Origin, Src, _) :-
 1566    process_foreign(File, Src).
 1567process_goal(load_foreign_library(File, _Init), _Origin, Src, _) :-
 1568    process_foreign(File, Src).
 1569process_goal(use_foreign_library(File), _Origin, Src, _) :-
 1570    process_foreign(File, Src).
 1571process_goal(use_foreign_library(File, _Init), _Origin, Src, _) :-
 1572    process_foreign(File, Src).
 1573process_goal(Goal, Origin, Src, P) :-
 1574    xref_meta_src(Goal, Metas, Src),
 1575    !,
 1576    current_source_line(Here),
 1577    assert_called(Src, Origin, Goal, Here),
 1578    process_called_list(Metas, Origin, Src, P).
 1579process_goal(Goal, Origin, Src, _) :-
 1580    asserting_goal(Goal, Rule),
 1581    !,
 1582    current_source_line(Here),
 1583    assert_called(Src, Origin, Goal, Here),
 1584    process_assert(Rule, Origin, Src).
 1585process_goal(Goal, Origin, Src, P) :-
 1586    partial_evaluate(Goal, P),
 1587    current_source_line(Here),
 1588    assert_called(Src, Origin, Goal, Here).
 1589
 1590disjunction(Var)   --> {var(Var), !}, [Var].
 1591disjunction((A;B)) --> !, disjunction(A), disjunction(B).
 1592disjunction(G)     --> [G].
 1593
 1594conjunction(Var)   --> {var(Var), !}, [Var].
 1595conjunction((A,B)) --> !, conjunction(A), conjunction(B).
 1596conjunction(G)     --> [G].
 1597
 1598shares_vars(RVars, T) :-
 1599    term_variables(T, TVars0),
 1600    sort(TVars0, TVars),
 1601    ord_intersect(RVars, TVars).
 1602
 1603process_conjunction([], _, _, _).
 1604process_conjunction([Disj|Rest], Origin, Src, P) :-
 1605    nonvar(Disj),
 1606    Disj = (_;_),
 1607    Rest \== [],
 1608    !,
 1609    phrase(disjunction(Disj), Goals),
 1610    term_variables(Rest, RVars0),
 1611    sort(RVars0, RVars),
 1612    partition(shares_vars(RVars), Goals, Sharing, NonSHaring),
 1613    forall(member(G, NonSHaring),
 1614           process_body(G, Origin, Src)),
 1615    (   Sharing == []
 1616    ->  true
 1617    ;   maplist(term_variables, Sharing, GVars0),
 1618        append(GVars0, GVars1),
 1619        sort(GVars1, GVars),
 1620        ord_intersection(GVars, RVars, SVars),
 1621        VT =.. [v|SVars],
 1622        findall(VT,
 1623                (   member(G, Sharing),
 1624                    process_goal(G, Origin, Src, PS),
 1625                    PS == true
 1626                ),
 1627                Alts0),
 1628        (   Alts0 == []
 1629        ->  true
 1630        ;   (   true
 1631            ;   P = true,
 1632                sort(Alts0, Alts1),
 1633                variants(Alts1, 10, Alts),
 1634                member(VT, Alts)
 1635            )
 1636        )
 1637    ),
 1638    process_conjunction(Rest, Origin, Src, P).
 1639process_conjunction([H|T], Origin, Src, P) :-
 1640    process_goal(H, Origin, Src, P),
 1641    process_conjunction(T, Origin, Src, P).
 1642
 1643
 1644process_called_list([], _, _, _).
 1645process_called_list([H|T], Origin, Src, P) :-
 1646    process_meta(H, Origin, Src, P),
 1647    process_called_list(T, Origin, Src, P).
 1648
 1649process_meta(A+N, Origin, Src, P) :-
 1650    !,
 1651    (   extend(A, N, AX)
 1652    ->  process_goal(AX, Origin, Src, P)
 1653    ;   true
 1654    ).
 1655process_meta(//(A), Origin, Src, P) :-
 1656    !,
 1657    process_dcg_goal(A, Origin, Src, P).
 1658process_meta(G, Origin, Src, P) :-
 1659    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.
 1666process_dcg_goal(Var, _, _, _) :-
 1667    var(Var),
 1668    !.
 1669process_dcg_goal((A,B), Origin, Src, P) :-
 1670    !,
 1671    process_dcg_goal(A, Origin, Src, P),
 1672    process_dcg_goal(B, Origin, Src, P).
 1673process_dcg_goal((A;B), Origin, Src, P) :-
 1674    !,
 1675    process_dcg_goal(A, Origin, Src, P),
 1676    process_dcg_goal(B, Origin, Src, P).
 1677process_dcg_goal((A|B), Origin, Src, P) :-
 1678    !,
 1679    process_dcg_goal(A, Origin, Src, P),
 1680    process_dcg_goal(B, Origin, Src, P).
 1681process_dcg_goal((A->B), Origin, Src, P) :-
 1682    !,
 1683    process_dcg_goal(A, Origin, Src, P),
 1684    process_dcg_goal(B, Origin, Src, P).
 1685process_dcg_goal((A*->B), Origin, Src, P) :-
 1686    !,
 1687    process_dcg_goal(A, Origin, Src, P),
 1688    process_dcg_goal(B, Origin, Src, P).
 1689process_dcg_goal({Goal}, Origin, Src, P) :-
 1690    !,
 1691    process_goal(Goal, Origin, Src, P).
 1692process_dcg_goal(List, _Origin, _Src, _) :-
 1693    is_list(List),
 1694    !.               % terminal
 1695process_dcg_goal(List, _Origin, _Src, _) :-
 1696    string(List),
 1697    !.                % terminal
 1698process_dcg_goal(Callable, Origin, Src, P) :-
 1699    extend(Callable, 2, Goal),
 1700    !,
 1701    process_goal(Goal, Origin, Src, P).
 1702process_dcg_goal(_, _, _, _).
 1703
 1704
 1705extend(Var, _, _) :-
 1706    var(Var), !, fail.
 1707extend(M:G, N, M:GX) :-
 1708    !,
 1709    callable(G),
 1710    extend(G, N, GX).
 1711extend(G, N, GX) :-
 1712    (   compound(G)
 1713    ->  compound_name_arguments(G, Name, Args),
 1714        length(Rest, N),
 1715        append(Args, Rest, NArgs),
 1716        compound_name_arguments(GX, Name, NArgs)
 1717    ;   atom(G)
 1718    ->  length(NArgs, N),
 1719        compound_name_arguments(GX, G, NArgs)
 1720    ).
 1721
 1722asserting_goal(assert(Rule), Rule).
 1723asserting_goal(asserta(Rule), Rule).
 1724asserting_goal(assertz(Rule), Rule).
 1725asserting_goal(assert(Rule,_), Rule).
 1726asserting_goal(asserta(Rule,_), Rule).
 1727asserting_goal(assertz(Rule,_), Rule).
 1728
 1729process_assert(0, _, _) :- !.           % catch variables
 1730process_assert((_:-Body), Origin, Src) :-
 1731    !,
 1732    process_body(Body, Origin, Src).
 1733process_assert(_, _, _).
 variants(+SortedList, +Max, -Variants) is det
 1737variants([], _, []).
 1738variants([H|T], Max, List) :-
 1739    variants(T, H, Max, List).
 1740
 1741variants([], H, _, [H]).
 1742variants(_, _, 0, []) :- !.
 1743variants([H|T], V, Max, List) :-
 1744    (   H =@= V
 1745    ->  variants(T, V, Max, List)
 1746    ;   List = [V|List2],
 1747        Max1 is Max-1,
 1748        variants(T, H, Max1, List2)
 1749    ).
 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?
 1763partial_evaluate(Goal, P) :-
 1764    eval(Goal),
 1765    !,
 1766    P = true.
 1767partial_evaluate(_, _).
 1768
 1769eval(X = Y) :-
 1770    unify_with_occurs_check(X, Y).
 1771
 1772		 /*******************************
 1773		 *        PLUNIT SUPPORT	*
 1774		 *******************************/
 1775
 1776enter_test_unit(Unit, _Src) :-
 1777    current_source_line(Line),
 1778    asserta(current_test_unit(Unit, Line)).
 1779
 1780leave_test_unit(Unit, _Src) :-
 1781    retractall(current_test_unit(Unit, _)).
 1782
 1783
 1784                 /*******************************
 1785                 *          XPCE STUFF          *
 1786                 *******************************/
 1787
 1788pce_goal(new(_,_), new(-, new)).
 1789pce_goal(send(_,_), send(arg, msg)).
 1790pce_goal(send_class(_,_,_), send_class(arg, arg, msg)).
 1791pce_goal(get(_,_,_), get(arg, msg, -)).
 1792pce_goal(get_class(_,_,_,_), get_class(arg, arg, msg, -)).
 1793pce_goal(get_chain(_,_,_), get_chain(arg, msg, -)).
 1794pce_goal(get_object(_,_,_), get_object(arg, msg, -)).
 1795
 1796process_xpce_goal(G, Origin, Src) :-
 1797    pce_goal(G, Process),
 1798    !,
 1799    current_source_line(Here),
 1800    assert_called(Src, Origin, G, Here),
 1801    (   arg(I, Process, How),
 1802        arg(I, G, Term),
 1803        process_xpce_arg(How, Term, Origin, Src),
 1804        fail
 1805    ;   true
 1806    ).
 1807
 1808process_xpce_arg(new, Term, Origin, Src) :-
 1809    callable(Term),
 1810    process_new(Term, Origin, Src).
 1811process_xpce_arg(arg, Term, Origin, Src) :-
 1812    compound(Term),
 1813    process_new(Term, Origin, Src).
 1814process_xpce_arg(msg, Term, Origin, Src) :-
 1815    compound(Term),
 1816    (   arg(_, Term, Arg),
 1817        process_xpce_arg(arg, Arg, Origin, Src),
 1818        fail
 1819    ;   true
 1820    ).
 1821
 1822process_new(_M:_Term, _, _) :- !.       % TBD: Calls on other modules!
 1823process_new(Term, Origin, Src) :-
 1824    assert_new(Src, Origin, Term),
 1825    (   compound(Term),
 1826        arg(_, Term, Arg),
 1827        process_xpce_arg(arg, Arg, Origin, Src),
 1828        fail
 1829    ;   true
 1830    ).
 1831
 1832assert_new(_, _, Term) :-
 1833    \+ callable(Term),
 1834    !.
 1835assert_new(Src, Origin, Control) :-
 1836    functor_name(Control, Class),
 1837    pce_control_class(Class),
 1838    !,
 1839    forall(arg(_, Control, Arg),
 1840           assert_new(Src, Origin, Arg)).
 1841assert_new(Src, Origin, Term) :-
 1842    compound(Term),
 1843    arg(1, Term, Prolog),
 1844    Prolog == @(prolog),
 1845    (   Term =.. [message, _, Selector | T],
 1846        atom(Selector)
 1847    ->  Called =.. [Selector|T],
 1848        process_body(Called, Origin, Src)
 1849    ;   Term =.. [?, _, Selector | T],
 1850        atom(Selector)
 1851    ->  append(T, [_R], T2),
 1852        Called =.. [Selector|T2],
 1853        process_body(Called, Origin, Src)
 1854    ),
 1855    fail.
 1856assert_new(_, _, @(_)) :- !.
 1857assert_new(Src, _, Term) :-
 1858    functor_name(Term, Name),
 1859    assert_used_class(Src, Name).
 1860
 1861
 1862pce_control_class(and).
 1863pce_control_class(or).
 1864pce_control_class(if).
 1865pce_control_class(not).
 1866
 1867
 1868                /********************************
 1869                *       INCLUDED MODULES        *
 1870                ********************************/
 process_use_module(+Modules, +Src, +Rexport) is det
 1874process_use_module(_Module:_Files, _, _) :- !.  % loaded in another module
 1875process_use_module([], _, _) :- !.
 1876process_use_module([H|T], Src, Reexport) :-
 1877    !,
 1878    process_use_module(H, Src, Reexport),
 1879    process_use_module(T, Src, Reexport).
 1880process_use_module(library(pce), Src, Reexport) :-     % bit special
 1881    !,
 1882    xref_public_list(library(pce), Path, Exports, Src),
 1883    forall(member(Import, Exports),
 1884           process_pce_import(Import, Src, Path, Reexport)).
 1885process_use_module(File, Src, Reexport) :-
 1886    load_module_if_needed(File),
 1887    (   xoption(Src, silent(Silent))
 1888    ->  Extra = [silent(Silent)]
 1889    ;   Extra = [silent(true)]
 1890    ),
 1891    (   xref_public_list(File, Src,
 1892                         [ path(Path),
 1893                           module(M),
 1894                           exports(Exports),
 1895                           public(Public),
 1896                           meta(Meta)
 1897                         | Extra
 1898                         ])
 1899    ->  assert(uses_file(File, Src, Path)),
 1900        assert_import(Src, Exports, _, Path, Reexport),
 1901        assert_xmodule_callable(Exports, M, Src, Path),
 1902        assert_xmodule_callable(Public, M, Src, Path),
 1903        maplist(process_meta_head(Src), Meta),
 1904        (   File = library(chr)     % hacky
 1905        ->  assert(mode(chr, Src))
 1906        ;   true
 1907        )
 1908    ;   assert(uses_file(File, Src, '<not_found>'))
 1909    ).
 1910
 1911process_pce_import(Name/Arity, Src, Path, Reexport) :-
 1912    atom(Name),
 1913    integer(Arity),
 1914    !,
 1915    functor(Term, Name, Arity),
 1916    (   \+ system_predicate(Term),
 1917        \+ Term = pce_error(_)      % hack!?
 1918    ->  assert_import(Src, [Name/Arity], _, Path, Reexport)
 1919    ;   true
 1920    ).
 1921process_pce_import(op(P,T,N), Src, _, _) :-
 1922    xref_push_op(Src, P, T, N).
 process_use_module2(+File, +Import, +Src, +Reexport) is det
Process use_module/2 and reexport/2.
 1928process_use_module2(File, Import, Src, Reexport) :-
 1929    load_module_if_needed(File),
 1930    (   xref_source_file(File, Path, Src)
 1931    ->  assert(uses_file(File, Src, Path)),
 1932        (   catch(public_list(Path, _, Meta, Export, _Public, []), _, fail)
 1933        ->  assert_import(Src, Import, Export, Path, Reexport),
 1934            forall((  member(Head, Meta),
 1935                      imported(Head, _, Path)
 1936                   ),
 1937                   process_meta_head(Src, Head))
 1938        ;   true
 1939        )
 1940    ;   assert(uses_file(File, Src, '<not_found>'))
 1941    ).
 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.
 1950load_module_if_needed(File) :-
 1951    prolog:no_autoload_module(File),
 1952    !,
 1953    use_module(File, []).
 1954load_module_if_needed(_).
 1955
 1956prolog:no_autoload_module(library(apply_macros)).
 1957prolog:no_autoload_module(library(arithmetic)).
 1958prolog:no_autoload_module(library(record)).
 1959prolog:no_autoload_module(library(persistency)).
 1960prolog:no_autoload_module(library(pldoc)).
 1961prolog:no_autoload_module(library(settings)).
 1962prolog:no_autoload_module(library(debug)).
 1963prolog:no_autoload_module(library(plunit)).
 1964prolog:no_autoload_module(library(macros)).
 1965prolog:no_autoload_module(library(yall)).
 process_requires(+Import, +Src)
 1970process_requires(Import, Src) :-
 1971    is_list(Import),
 1972    !,
 1973    require_list(Import, Src).
 1974process_requires(Var, _Src) :-
 1975    var(Var),
 1976    !.
 1977process_requires((A,B), Src) :-
 1978    !,
 1979    process_requires(A, Src),
 1980    process_requires(B, Src).
 1981process_requires(PI, Src) :-
 1982    requires(PI, Src).
 1983
 1984require_list([], _).
 1985require_list([H|T], Src) :-
 1986    requires(H, Src),
 1987    require_list(T, Src).
 1988
 1989requires(PI, _Src) :-
 1990    '$pi_head'(PI, Head),
 1991    '$get_predicate_attribute'(system:Head, defined, 1),
 1992    !.
 1993requires(PI, Src) :-
 1994    '$pi_head'(PI, Head),
 1995    '$pi_head'(Name/Arity, Head),
 1996    '$find_library'(_Module, Name, Arity, _LoadModule, Library),
 1997    (   imported(Head, Src, Library)
 1998    ->  true
 1999    ;   assertz(imported(Head, Src, Library))
 2000    ).
 xref_public_list(+Spec, +Source, +Options) 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 in Options. Options processed:
path(-Path)
Path is the full path name of the referenced 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.
meta(-Meta)
Meta is a list of heads as they appear in meta_predicate/1 declarations.
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.
 2031xref_public_list(File, Src, Options) :-
 2032    option(path(Path), Options, _),
 2033    option(module(Module), Options, _),
 2034    option(exports(Exports), Options, _),
 2035    option(public(Public), Options, _),
 2036    option(meta(Meta), Options, _),
 2037    xref_source_file(File, Path, Src, Options),
 2038    public_list(Path, 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:
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.
 2060xref_public_list(File, Path, Export, Src) :-
 2061    xref_source_file(File, Path, Src),
 2062    public_list(Path, _, _, Export, _, []).
 2063xref_public_list(File, Path, Module, Export, Meta, Src) :-
 2064    xref_source_file(File, Path, Src),
 2065    public_list(Path, Module, Meta, Export, _, []).
 2066xref_public_list(File, Path, Module, Export, Public, Meta, Src) :-
 2067    xref_source_file(File, Path, Src),
 2068    public_list(Path, Module, Meta, Export, Public, []).
 public_list(+Path, -Module, -Meta, -Export, -Public, +Options)
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.
 2078:- dynamic  public_list_cache/6. 2079:- volatile public_list_cache/6. 2080
 2081public_list(Path, Module, Meta, Export, Public, _Options) :-
 2082    public_list_cache(Path, Modified,
 2083                      Module0, Meta0, Export0, Public0),
 2084    time_file(Path, ModifiedNow),
 2085    (   abs(Modified-ModifiedNow) < 0.0001
 2086    ->  !,
 2087        t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0)
 2088    ;   retractall(public_list_cache(Path, _, _, _, _, _)),
 2089        fail
 2090    ).
 2091public_list(Path, Module, Meta, Export, Public, Options) :-
 2092    public_list_nc(Path, Module0, Meta0, Export0, Public0, Options),
 2093    (   Error = error(_,_),
 2094        catch(time_file(Path, Modified), Error, fail)
 2095    ->  asserta(public_list_cache(Path, Modified,
 2096                                  Module0, Meta0, Export0, Public0))
 2097    ;   true
 2098    ),
 2099    t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0).
 2100
 2101public_list_nc(Path, Module, Meta, Export, Public, Options) :-
 2102    in_temporary_module(
 2103        TempModule,
 2104        true,
 2105        public_list_diff(TempModule, Path, Module,
 2106                         Meta, [], Export, [], Public, [], Options)).
 2107
 2108
 2109public_list_diff(TempModule,
 2110                 Path, Module, Meta, MT, Export, Rest, Public, PT, Options) :-
 2111    setup_call_cleanup(
 2112        public_list_setup(TempModule, Path, In, State),
 2113        phrase(read_directives(In, Options, [true]), Directives),
 2114        public_list_cleanup(In, State)),
 2115    public_list(Directives, Path, Module, Meta, MT, Export, Rest, Public, PT).
 2116
 2117public_list_setup(TempModule, Path, In, state(OldM, OldXref)) :-
 2118    prolog_open_source(Path, In),
 2119    '$set_source_module'(OldM, TempModule),
 2120    set_xref(OldXref).
 2121
 2122public_list_cleanup(In, state(OldM, OldXref)) :-
 2123    '$set_source_module'(OldM),
 2124    set_prolog_flag(xref, OldXref),
 2125    prolog_close_source(In).
 2126
 2127
 2128read_directives(In, Options, State) -->
 2129    {  repeat,
 2130       catch(prolog_read_source_term(In, Term, Expanded,
 2131                                     [ process_comment(true),
 2132                                       syntax_errors(error)
 2133                                     ]),
 2134             E, report_syntax_error(E, -, Options))
 2135    -> nonvar(Term),
 2136       Term = (:-_)
 2137    },
 2138    !,
 2139    terms(Expanded, State, State1),
 2140    read_directives(In, Options, State1).
 2141read_directives(_, _, _) --> [].
 2142
 2143terms(Var, State, State) --> { var(Var) }, !.
 2144terms([H|T], State0, State) -->
 2145    !,
 2146    terms(H, State0, State1),
 2147    terms(T, State1, State).
 2148terms((:-if(Cond)), State0, [True|State0]) -->
 2149    !,
 2150    { eval_cond(Cond, True) }.
 2151terms((:-elif(Cond)), [True0|State], [True|State]) -->
 2152    !,
 2153    { eval_cond(Cond, True1),
 2154      elif(True0, True1, True)
 2155    }.
 2156terms((:-else), [True0|State], [True|State]) -->
 2157    !,
 2158    { negate(True0, True) }.
 2159terms((:-endif), [_|State], State) -->  !.
 2160terms(H, State, State) -->
 2161    (   {State = [true|_]}
 2162    ->  [H]
 2163    ;   []
 2164    ).
 2165
 2166eval_cond(Cond, true) :-
 2167    catch(Cond, _, fail),
 2168    !.
 2169eval_cond(_, false).
 2170
 2171elif(true,  _,    else_false) :- !.
 2172elif(false, true, true) :- !.
 2173elif(True,  _,    True).
 2174
 2175negate(true,       false).
 2176negate(false,      true).
 2177negate(else_false, else_false).
 2178
 2179public_list([(:- module(Module, Export0))|Decls], Path,
 2180            Module, Meta, MT, Export, Rest, Public, PT) :-
 2181    !,
 2182    (   is_list(Export0)
 2183    ->  append(Export0, Reexport, Export)
 2184    ;   Reexport = Export
 2185    ),
 2186    public_list_(Decls, Path, Meta, MT, Reexport, Rest, Public, PT).
 2187public_list([(:- encoding(_))|Decls], Path,
 2188            Module, Meta, MT, Export, Rest, Public, PT) :-
 2189    public_list(Decls, Path, Module, Meta, MT, Export, Rest, Public, PT).
 2190
 2191public_list_([], _, Meta, Meta, Export, Export, Public, Public).
 2192public_list_([(:-(Dir))|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 2193    public_list_1(Dir, Path, Meta, MT0, Export, Rest0, Public, PT0),
 2194    !,
 2195    public_list_(T, Path, MT0, MT, Rest0, Rest, PT0, PT).
 2196public_list_([_|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 2197    public_list_(T, Path, Meta, MT, Export, Rest, Public, PT).
 2198
 2199public_list_1(reexport(Spec), Path, Meta, MT, Reexport, Rest, Public, PT) :-
 2200    reexport_files(Spec, Path, Meta, MT, Reexport, Rest, Public, PT).
 2201public_list_1(reexport(Spec, Import), Path, Meta, Meta, Reexport, Rest, Public, Public) :-
 2202    public_from_import(Import, Spec, Path, Reexport, Rest).
 2203public_list_1(meta_predicate(Decl), _Path, Meta, MT, Export, Export, Public, Public) :-
 2204    phrase(meta_decls(Decl), Meta, MT).
 2205public_list_1(public(Decl), _Path, Meta, Meta, Export, Export, Public, PT) :-
 2206    phrase(public_decls(Decl), Public, PT).
 reexport_files(+Files, +Src, -Meta, ?MetaTail, -Exports, ?ExportsTail, -Public, ?PublicTail)
 2212reexport_files([], _, Meta, Meta, Export, Export, Public, Public) :- !.
 2213reexport_files([H|T], Src, Meta, MT, Export, ET, Public, PT) :-
 2214    !,
 2215    xref_source_file(H, Path, Src),
 2216    public_list(Path, _Module, Meta0, Export0, Public0, []),
 2217    append(Meta0, MT1, Meta),
 2218    append(Export0, ET1, Export),
 2219    append(Public0, PT1, Public),
 2220    reexport_files(T, Src, MT1, MT, ET1, ET, PT1, PT).
 2221reexport_files(Spec, Src, Meta, MT, Export, ET, Public, PT) :-
 2222    xref_source_file(Spec, Path, Src),
 2223    public_list(Path, _Module, Meta0, Export0, Public0, []),
 2224    append(Meta0, MT, Meta),
 2225    append(Export0, ET, Export),
 2226    append(Public0, PT, Public).
 2227
 2228public_from_import(except(Map), Path, Src, Export, Rest) :-
 2229    !,
 2230    xref_public_list(Path, _, AllExports, Src),
 2231    except(Map, AllExports, NewExports),
 2232    append(NewExports, Rest, Export).
 2233public_from_import(Import, _, _, Export, Rest) :-
 2234    import_name_map(Import, Export, Rest).
 except(+Remove, +AllExports, -Exports)
 2239except([], Exports, Exports).
 2240except([PI0 as NewName|Map], Exports0, Exports) :-
 2241    !,
 2242    canonical_pi(PI0, PI),
 2243    map_as(Exports0, PI, NewName, Exports1),
 2244    except(Map, Exports1, Exports).
 2245except([PI0|Map], Exports0, Exports) :-
 2246    canonical_pi(PI0, PI),
 2247    select(PI2, Exports0, Exports1),
 2248    same_pi(PI, PI2),
 2249    !,
 2250    except(Map, Exports1, Exports).
 2251
 2252
 2253map_as([PI|T], Repl, As, [PI2|T])  :-
 2254    same_pi(Repl, PI),
 2255    !,
 2256    pi_as(PI, As, PI2).
 2257map_as([H|T0], Repl, As, [H|T])  :-
 2258    map_as(T0, Repl, As, T).
 2259
 2260pi_as(_/Arity, Name, Name/Arity).
 2261pi_as(_//Arity, Name, Name//Arity).
 2262
 2263import_name_map([], L, L).
 2264import_name_map([_/Arity as NewName|T0], [NewName/Arity|T], Tail) :-
 2265    !,
 2266    import_name_map(T0, T, Tail).
 2267import_name_map([_//Arity as NewName|T0], [NewName//Arity|T], Tail) :-
 2268    !,
 2269    import_name_map(T0, T, Tail).
 2270import_name_map([H|T0], [H|T], Tail) :-
 2271    import_name_map(T0, T, Tail).
 2272
 2273canonical_pi(Name//Arity0, PI) :-
 2274    integer(Arity0),
 2275    !,
 2276    PI = Name/Arity,
 2277    Arity is Arity0 + 2.
 2278canonical_pi(PI, PI).
 2279
 2280same_pi(Canonical, PI2) :-
 2281    canonical_pi(PI2, Canonical).
 2282
 2283meta_decls(Var) -->
 2284    { var(Var) },
 2285    !.
 2286meta_decls((A,B)) -->
 2287    !,
 2288    meta_decls(A),
 2289    meta_decls(B).
 2290meta_decls(A) -->
 2291    [A].
 2292
 2293public_decls(Var) -->
 2294    { var(Var) },
 2295    !.
 2296public_decls((A,B)) -->
 2297    !,
 2298    public_decls(A),
 2299    public_decls(B).
 2300public_decls(A) -->
 2301    [A].
 2302
 2303                 /*******************************
 2304                 *             INCLUDE          *
 2305                 *******************************/
 2306
 2307process_include([], _) :- !.
 2308process_include([H|T], Src) :-
 2309    !,
 2310    process_include(H, Src),
 2311    process_include(T, Src).
 2312process_include(File, Src) :-
 2313    callable(File),
 2314    !,
 2315    (   once(xref_input(ParentSrc, _)),
 2316        xref_source_file(File, Path, ParentSrc)
 2317    ->  (   (   uses_file(_, Src, Path)
 2318            ;   Path == Src
 2319            )
 2320        ->  true
 2321        ;   assert(uses_file(File, Src, Path)),
 2322            (   xoption(Src, process_include(true))
 2323            ->  findall(O, xoption(Src, O), Options),
 2324                setup_call_cleanup(
 2325                    open_include_file(Path, In, Refs),
 2326                    collect(Src, Path, In, Options),
 2327                    close_include(In, Refs))
 2328            ;   true
 2329            )
 2330        )
 2331    ;   assert(uses_file(File, Src, '<not_found>'))
 2332    ).
 2333process_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.
 2341open_include_file(Path, In, [Ref]) :-
 2342    once(xref_input(_, Parent)),
 2343    stream_property(Parent, encoding(Enc)),
 2344    '$push_input_context'(xref_include),
 2345    catch((   prolog:xref_open_source(Path, In)
 2346          ->  catch(set_stream(In, encoding(Enc)),
 2347                    error(_,_), true)       % deal with non-file input
 2348          ;   include_encoding(Enc, Options),
 2349              open(Path, read, In, Options)
 2350          ), E,
 2351          ( '$pop_input_context', throw(E))),
 2352    catch((   peek_char(In, #)              % Deal with #! script
 2353          ->  skip(In, 10)
 2354          ;   true
 2355          ), E,
 2356          ( close_include(In, []), throw(E))),
 2357    asserta(xref_input(Path, In), Ref).
 2358
 2359include_encoding(wchar_t, []) :- !.
 2360include_encoding(Enc, [encoding(Enc)]).
 2361
 2362
 2363close_include(In, Refs) :-
 2364    maplist(erase, Refs),
 2365    close(In, [force(true)]),
 2366    '$pop_input_context'.
 process_foreign(+Spec, +Src)
Process a load_foreign_library/1 call.
 2372process_foreign(Spec, Src) :-
 2373    ground(Spec),
 2374    current_foreign_library(Spec, Defined),
 2375    !,
 2376    (   xmodule(Module, Src)
 2377    ->  true
 2378    ;   Module = user
 2379    ),
 2380    process_foreign_defined(Defined, Module, Src).
 2381process_foreign(_, _).
 2382
 2383process_foreign_defined([], _, _).
 2384process_foreign_defined([H|T], M, Src) :-
 2385    (   H = M:Head
 2386    ->  assert_foreign(Src, Head)
 2387    ;   assert_foreign(Src, H)
 2388    ),
 2389    process_foreign_defined(T, M, Src).
 2390
 2391
 2392                 /*******************************
 2393                 *          CHR SUPPORT         *
 2394                 *******************************/
 2395
 2396/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2397This part of the file supports CHR. Our choice is between making special
 2398hooks to make CHR expansion work and  then handle the (complex) expanded
 2399code or process the  CHR  source   directly.  The  latter looks simpler,
 2400though I don't like the idea  of   adding  support for libraries to this
 2401module.  A  file  is  supposed  to  be  a    CHR   file  if  it  uses  a
 2402use_module(library(chr) or contains a :-   constraint/1 directive. As an
 2403extra bonus we get the source-locations right :-)
 2404- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2405
 2406process_chr(@(_Name, Rule), Src) :-
 2407    mode(chr, Src),
 2408    process_chr(Rule, Src).
 2409process_chr(pragma(Rule, _Pragma), Src) :-
 2410    mode(chr, Src),
 2411    process_chr(Rule, Src).
 2412process_chr(<=>(Head, Body), Src) :-
 2413    mode(chr, Src),
 2414    chr_head(Head, Src, H),
 2415    chr_body(Body, H, Src).
 2416process_chr(==>(Head, Body), Src) :-
 2417    mode(chr, Src),
 2418    chr_head(Head, H, Src),
 2419    chr_body(Body, H, Src).
 2420process_chr((:- chr_constraint(_)), Src) :-
 2421    (   mode(chr, Src)
 2422    ->  true
 2423    ;   assert(mode(chr, Src))
 2424    ).
 2425
 2426chr_head(X, _, _) :-
 2427    var(X),
 2428    !.                      % Illegal.  Warn?
 2429chr_head(\(A,B), Src, H) :-
 2430    chr_head(A, Src, H),
 2431    process_body(B, H, Src).
 2432chr_head((H0,B), Src, H) :-
 2433    chr_defined(H0, Src, H),
 2434    process_body(B, H, Src).
 2435chr_head(H0, Src, H) :-
 2436    chr_defined(H0, Src, H).
 2437
 2438chr_defined(X, _, _) :-
 2439    var(X),
 2440    !.
 2441chr_defined(#(C,_Id), Src, C) :-
 2442    !,
 2443    assert_constraint(Src, C).
 2444chr_defined(A, Src, A) :-
 2445    assert_constraint(Src, A).
 2446
 2447chr_body(X, From, Src) :-
 2448    var(X),
 2449    !,
 2450    process_body(X, From, Src).
 2451chr_body('|'(Guard, Goals), H, Src) :-
 2452    !,
 2453    chr_body(Guard, H, Src),
 2454    chr_body(Goals, H, Src).
 2455chr_body(G, From, Src) :-
 2456    process_body(G, From, Src).
 2457
 2458assert_constraint(_, Head) :-
 2459    var(Head),
 2460    !.
 2461assert_constraint(Src, Head) :-
 2462    constraint(Head, Src, _),
 2463    !.
 2464assert_constraint(Src, Head) :-
 2465    generalise_term(Head, Term),
 2466    current_source_line(Line),
 2467    assert(constraint(Term, Src, Line)).
 2468
 2469
 2470                /********************************
 2471                *       PHASE 1 ASSERTIONS      *
 2472                ********************************/
 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.
 2479assert_called(_, _, Var, _) :-
 2480    var(Var),
 2481    !.
 2482assert_called(Src, From, Goal, Line) :-
 2483    var(From),
 2484    !,
 2485    assert_called(Src, '<unknown>', Goal, Line).
 2486assert_called(_, _, Goal, _) :-
 2487    expand_hide_called(Goal),
 2488    !.
 2489assert_called(Src, Origin, M:G, Line) :-
 2490    !,
 2491    (   atom(M),
 2492        callable(G)
 2493    ->  current_condition(Cond),
 2494        (   xmodule(M, Src)         % explicit call to own module
 2495        ->  assert_called(Src, Origin, G, Line)
 2496        ;   called(M:G, Src, Origin, Cond, Line) % already registered
 2497        ->  true
 2498        ;   hide_called(M:G, Src)           % not interesting (now)
 2499        ->  true
 2500        ;   generalise(Origin, OTerm),
 2501            generalise(G, GTerm)
 2502        ->  assert(called(M:GTerm, Src, OTerm, Cond, Line))
 2503        ;   true
 2504        )
 2505    ;   true                        % call to variable module
 2506    ).
 2507assert_called(Src, _, Goal, _) :-
 2508    (   xmodule(M, Src)
 2509    ->  M \== system
 2510    ;   M = user
 2511    ),
 2512    hide_called(M:Goal, Src),
 2513    !.
 2514assert_called(Src, Origin, Goal, Line) :-
 2515    current_condition(Cond),
 2516    (   called(Goal, Src, Origin, Cond, Line)
 2517    ->  true
 2518    ;   generalise(Origin, OTerm),
 2519        generalise(Goal, Term)
 2520    ->  assert(called(Term, Src, OTerm, Cond, Line))
 2521    ;   true
 2522    ).
 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.
 2530expand_hide_called(pce_principal:send_implementation(_, _, _)).
 2531expand_hide_called(pce_principal:get_implementation(_, _, _, _)).
 2532expand_hide_called(pce_principal:pce_lazy_get_method(_,_,_)).
 2533expand_hide_called(pce_principal:pce_lazy_send_method(_,_,_)).
 2534
 2535assert_defined(Src, Goal) :-
 2536    Goal = test(_Test),
 2537    current_test_unit(Unit, Line),
 2538    assert_called(Src, '<test_unit>'(Unit), Goal, Line),
 2539    fail.
 2540assert_defined(Src, Goal) :-
 2541    Goal = test(_Test, _Options),
 2542    current_test_unit(Unit, Line),
 2543    assert_called(Src, '<test_unit>'(Unit), Goal, Line),
 2544    fail.
 2545assert_defined(Src, Goal) :-
 2546    defined(Goal, Src, _),
 2547    !.
 2548assert_defined(Src, Goal) :-
 2549    generalise(Goal, Term),
 2550    current_source_line(Line),
 2551    assert(defined(Term, Src, Line)).
 2552
 2553assert_foreign(Src, Goal) :-
 2554    foreign(Goal, Src, _),
 2555    !.
 2556assert_foreign(Src, Goal) :-
 2557    generalise(Goal, Term),
 2558    current_source_line(Line),
 2559    assert(foreign(Term, Src, Line)).
 2560
 2561assert_grammar_rule(Src, Goal) :-
 2562    grammar_rule(Goal, Src),
 2563    !.
 2564assert_grammar_rule(Src, Goal) :-
 2565    generalise(Goal, Term),
 2566    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.
 2579assert_import(_, [], _, _, _) :- !.
 2580assert_import(Src, [H|T], Export, From, Reexport) :-
 2581    !,
 2582    assert_import(Src, H, Export, From, Reexport),
 2583    assert_import(Src, T, Export, From, Reexport).
 2584assert_import(Src, except(Except), Export, From, Reexport) :-
 2585    !,
 2586    is_list(Export),
 2587    !,
 2588    except(Except, Export, Import),
 2589    assert_import(Src, Import, _All, From, Reexport).
 2590assert_import(Src, Import as Name, Export, From, Reexport) :-
 2591    !,
 2592    pi_to_head(Import, Term0),
 2593    rename_goal(Term0, Name, Term),
 2594    (   in_export_list(Term0, Export)
 2595    ->  assert(imported(Term, Src, From)),
 2596        assert_reexport(Reexport, Src, Term)
 2597    ;   current_source_line(Line),
 2598        assert_called(Src, '<directive>'(Line), Term0, Line)
 2599    ).
 2600assert_import(Src, Import, Export, From, Reexport) :-
 2601    pi_to_head(Import, Term),
 2602    !,
 2603    (   in_export_list(Term, Export)
 2604    ->  assert(imported(Term, Src, From)),
 2605        assert_reexport(Reexport, Src, Term)
 2606    ;   current_source_line(Line),
 2607        assert_called(Src, '<directive>'(Line), Term, Line)
 2608    ).
 2609assert_import(Src, op(P,T,N), _, _, _) :-
 2610    xref_push_op(Src, P,T,N).
 2611
 2612in_export_list(_Head, Export) :-
 2613    var(Export),
 2614    !.
 2615in_export_list(Head, Export) :-
 2616    member(PI, Export),
 2617    pi_to_head(PI, Head).
 2618
 2619assert_reexport(false, _, _) :- !.
 2620assert_reexport(true, Src, Term) :-
 2621    assert(exported(Term, Src)).
 process_import(:Import, +Src)
Process an import/1 directive
 2627process_import(M:PI, Src) :-
 2628    pi_to_head(PI, Head),
 2629    !,
 2630    (   atom(M),
 2631        current_module(M),
 2632        module_property(M, file(From))
 2633    ->  true
 2634    ;   From = '<unknown>'
 2635    ),
 2636    assert(imported(Head, Src, From)).
 2637process_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?
 2646assert_xmodule_callable([], _, _, _).
 2647assert_xmodule_callable([PI|T], M, Src, From) :-
 2648    (   pi_to_head(M:PI, Head)
 2649    ->  assert(imported(Head, Src, From))
 2650    ;   true
 2651    ),
 2652    assert_xmodule_callable(T, M, Src, From).
 assert_op(+Src, +Op) is det
Arguments:
Op- Ground term op(Priority, Type, Name).
 2659assert_op(Src, op(P,T,M:N)) :-
 2660    (   '$current_source_module'(M)
 2661    ->  Name = N
 2662    ;   Name = M:N
 2663    ),
 2664    (   xop(Src, op(P,T,Name))
 2665    ->  true
 2666    ;   assert(xop(Src, op(P,T,Name)))
 2667    ).
 assert_module(+Src, +Module)
Assert we are loading code into Module. This is also used to exploit local term-expansion and other rules.
 2674assert_module(Src, Module) :-
 2675    xmodule(Module, Src),
 2676    !.
 2677assert_module(Src, Module) :-
 2678    '$set_source_module'(Module),
 2679    assert(xmodule(Module, Src)),
 2680    (   module_property(Module, class(system))
 2681    ->  retractall(xoption(Src, register_called(_))),
 2682        assert(xoption(Src, register_called(all)))
 2683    ;   true
 2684    ).
 2685
 2686assert_module_export(_, []) :- !.
 2687assert_module_export(Src, [H|T]) :-
 2688    !,
 2689    assert_module_export(Src, H),
 2690    assert_module_export(Src, T).
 2691assert_module_export(Src, PI) :-
 2692    pi_to_head(PI, Term),
 2693    !,
 2694    assert(exported(Term, Src)).
 2695assert_module_export(Src, op(P, A, N)) :-
 2696    xref_push_op(Src, P, A, N).
 assert_module3(+Import, +Src)
Handle 3th argument of module/3 declaration.
 2702assert_module3([], _) :- !.
 2703assert_module3([H|T], Src) :-
 2704    !,
 2705    assert_module3(H, Src),
 2706    assert_module3(T, Src).
 2707assert_module3(Option, Src) :-
 2708    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.
 2717process_predicates(Closure, Preds, Src) :-
 2718    is_list(Preds),
 2719    !,
 2720    process_predicate_list(Preds, Closure, Src).
 2721process_predicates(Closure, as(Preds, _Options), Src) :-
 2722    !,
 2723    process_predicates(Closure, Preds, Src).
 2724process_predicates(Closure, Preds, Src) :-
 2725    process_predicate_comma(Preds, Closure, Src).
 2726
 2727process_predicate_list([], _, _).
 2728process_predicate_list([H|T], Closure, Src) :-
 2729    (   nonvar(H)
 2730    ->  call(Closure, H, Src)
 2731    ;   true
 2732    ),
 2733    process_predicate_list(T, Closure, Src).
 2734
 2735process_predicate_comma(Var, _, _) :-
 2736    var(Var),
 2737    !.
 2738process_predicate_comma(M:(A,B), Closure, Src) :-
 2739    !,
 2740    process_predicate_comma(M:A, Closure, Src),
 2741    process_predicate_comma(M:B, Closure, Src).
 2742process_predicate_comma((A,B), Closure, Src) :-
 2743    !,
 2744    process_predicate_comma(A, Closure, Src),
 2745    process_predicate_comma(B, Closure, Src).
 2746process_predicate_comma(as(Spec, _Options), Closure, Src) :-
 2747    !,
 2748    process_predicate_comma(Spec, Closure, Src).
 2749process_predicate_comma(A, Closure, Src) :-
 2750    call(Closure, A, Src).
 2751
 2752
 2753assert_dynamic(PI, Src) :-
 2754    pi_to_head(PI, Term),
 2755    (   thread_local(Term, Src, _)  % dynamic after thread_local has
 2756    ->  true                        % no effect
 2757    ;   current_source_line(Line),
 2758        assert(dynamic(Term, Src, Line))
 2759    ).
 2760
 2761assert_thread_local(PI, Src) :-
 2762    pi_to_head(PI, Term),
 2763    current_source_line(Line),
 2764    assert(thread_local(Term, Src, Line)).
 2765
 2766assert_multifile(PI, Src) :-                    % :- multifile(Spec)
 2767    pi_to_head(PI, Term),
 2768    current_source_line(Line),
 2769    assert(multifile(Term, Src, Line)).
 2770
 2771assert_public(PI, Src) :-                       % :- public(Spec)
 2772    pi_to_head(PI, Term),
 2773    current_source_line(Line),
 2774    assert_called(Src, '<public>'(Line), Term, Line),
 2775    assert(public(Term, Src, Line)).
 2776
 2777assert_export(PI, Src) :-                       % :- export(Spec)
 2778    pi_to_head(PI, Term),
 2779    !,
 2780    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.
 2787pi_to_head(Var, _) :-
 2788    var(Var), !, fail.
 2789pi_to_head(M:PI, M:Term) :-
 2790    !,
 2791    pi_to_head(PI, Term).
 2792pi_to_head(Name/Arity, Term) :-
 2793    functor(Term, Name, Arity).
 2794pi_to_head(Name//DCGArity, Term) :-
 2795    Arity is DCGArity+2,
 2796    functor(Term, Name, Arity).
 2797
 2798
 2799assert_used_class(Src, Name) :-
 2800    used_class(Name, Src),
 2801    !.
 2802assert_used_class(Src, Name) :-
 2803    assert(used_class(Name, Src)).
 2804
 2805assert_defined_class(Src, Name, _Meta, _Super, _) :-
 2806    defined_class(Name, _, _, Src, _),
 2807    !.
 2808assert_defined_class(_, _, _, -, _) :- !.               % :- pce_extend_class
 2809assert_defined_class(Src, Name, Meta, Super, Summary) :-
 2810    current_source_line(Line),
 2811    (   Summary == @(default)
 2812    ->  Atom = ''
 2813    ;   is_list(Summary)
 2814    ->  atom_codes(Atom, Summary)
 2815    ;   string(Summary)
 2816    ->  atom_concat(Summary, '', Atom)
 2817    ),
 2818    assert(defined_class(Name, Super, Atom, Src, Line)),
 2819    (   Meta = @(_)
 2820    ->  true
 2821    ;   assert_used_class(Src, Meta)
 2822    ),
 2823    assert_used_class(Src, Super).
 2824
 2825assert_defined_class(Src, Name, imported_from(_File)) :-
 2826    defined_class(Name, _, _, Src, _),
 2827    !.
 2828assert_defined_class(Src, Name, imported_from(File)) :-
 2829    assert(defined_class(Name, _, '', Src, file(File))).
 2830
 2831
 2832                /********************************
 2833                *            UTILITIES          *
 2834                ********************************/
 generalise(+Callable, -General)
Generalise a callable term.
 2840generalise(Var, Var) :-
 2841    var(Var),
 2842    !.                    % error?
 2843generalise(pce_principal:send_implementation(Id, _, _),
 2844           pce_principal:send_implementation(Id, _, _)) :-
 2845    atom(Id),
 2846    !.
 2847generalise(pce_principal:get_implementation(Id, _, _, _),
 2848           pce_principal:get_implementation(Id, _, _, _)) :-
 2849    atom(Id),
 2850    !.
 2851generalise('<directive>'(Line), '<directive>'(Line)) :- !.
 2852generalise(test(Test), test(Test)) :-
 2853    current_test_unit(_,_),
 2854    ground(Test),
 2855    !.
 2856generalise(test(Test, _), test(Test, _)) :-
 2857    current_test_unit(_,_),
 2858    ground(Test),
 2859    !.
 2860generalise('<test_unit>'(Line), '<test_unit>'(Line)) :- !.
 2861generalise(Module:Goal0, Module:Goal) :-
 2862    atom(Module),
 2863    !,
 2864    generalise(Goal0, Goal).
 2865generalise(Term0, Term) :-
 2866    callable(Term0),
 2867    generalise_term(Term0, Term).
 2868
 2869
 2870                 /*******************************
 2871                 *      SOURCE MANAGEMENT       *
 2872                 *******************************/
 2873
 2874/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2875This section of the file contains   hookable  predicates to reason about
 2876sources. The built-in code here  can  only   deal  with  files. The XPCE
 2877library(pce_prolog_xref) provides hooks to deal with XPCE objects, so we
 2878can do cross-referencing on PceEmacs edit   buffers.  Other examples for
 2879hooking can be databases, (HTTP) URIs, etc.
 2880- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2881
 2882:- multifile
 2883    prolog:xref_source_directory/2, % +Source, -Dir
 2884    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.
 2892xref_source_file(Plain, File, Source) :-
 2893    xref_source_file(Plain, File, Source, []).
 2894
 2895xref_source_file(QSpec, File, Source, Options) :-
 2896    nonvar(QSpec), QSpec = _:Spec,
 2897    !,
 2898    must_be(acyclic, Spec),
 2899    xref_source_file(Spec, File, Source, Options).
 2900xref_source_file(Spec, File, Source, Options) :-
 2901    nonvar(Spec),
 2902    prolog:xref_source_file(Spec, File,
 2903                            [ relative_to(Source)
 2904                            | Options
 2905                            ]),
 2906    !.
 2907xref_source_file(Plain, File, Source, Options) :-
 2908    atom(Plain),
 2909    \+ is_absolute_file_name(Plain),
 2910    (   prolog:xref_source_directory(Source, Dir)
 2911    ->  true
 2912    ;   atom(Source),
 2913        file_directory_name(Source, Dir)
 2914    ),
 2915    atomic_list_concat([Dir, /, Plain], Spec0),
 2916    absolute_file_name(Spec0, Spec),
 2917    do_xref_source_file(Spec, File, Options),
 2918    !.
 2919xref_source_file(Spec, File, Source, Options) :-
 2920    do_xref_source_file(Spec, File,
 2921                        [ relative_to(Source)
 2922                        | Options
 2923                        ]),
 2924    !.
 2925xref_source_file(_, _, _, Options) :-
 2926    option(silent(true), Options),
 2927    !,
 2928    fail.
 2929xref_source_file(Spec, _, Src, _Options) :-
 2930    verbose(Src),
 2931    print_message(warning, error(existence_error(file, Spec), _)),
 2932    fail.
 2933
 2934do_xref_source_file(Spec, File, Options) :-
 2935    nonvar(Spec),
 2936    option(file_type(Type), Options, prolog),
 2937    absolute_file_name(Spec, File,
 2938                       [ file_type(Type),
 2939                         access(read),
 2940                         file_errors(fail)
 2941                       ]),
 2942    !.
 canonical_source(?Source, ?Src) is det
Src is the canonical version of Source if Source is given.
 2948canonical_source(Source, Src) :-
 2949    (   ground(Source)
 2950    ->  prolog_canonical_source(Source, Src)
 2951    ;   Source = Src
 2952    ).
 goal_name_arity(+Goal, -Name, -Arity)
Generalized version of functor/3 that can deal with name() goals.
 2959goal_name_arity(Goal, Name, Arity) :-
 2960    (   compound(Goal)
 2961    ->  compound_name_arity(Goal, Name, Arity)
 2962    ;   atom(Goal)
 2963    ->  Name = Goal, Arity = 0
 2964    ).
 2965
 2966generalise_term(Specific, General) :-
 2967    (   compound(Specific)
 2968    ->  compound_name_arity(Specific, Name, Arity),
 2969        compound_name_arity(General, Name, Arity)
 2970    ;   General = Specific
 2971    ).
 2972
 2973functor_name(Term, Name) :-
 2974    (   compound(Term)
 2975    ->  compound_name_arity(Term, Name, _)
 2976    ;   atom(Term)
 2977    ->  Name = Term
 2978    ).
 2979
 2980rename_goal(Goal0, Name, Goal) :-
 2981    (   compound(Goal0)
 2982    ->  compound_name_arity(Goal0, _, Arity),
 2983        compound_name_arity(Goal, Name, Arity)
 2984    ;   Goal = Name
 2985    )