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-2019, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9    All rights reserved.
   10
   11    Redistribution and use in source and binary forms, with or without
   12    modification, are permitted provided that the following conditions
   13    are met:
   14
   15    1. Redistributions of source code must retain the above copyright
   16       notice, this list of conditions and the following disclaimer.
   17
   18    2. Redistributions in binary form must reproduce the above copyright
   19       notice, this list of conditions and the following disclaimer in
   20       the documentation and/or other materials provided with the
   21       distribution.
   22
   23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34    POSSIBILITY OF SUCH DAMAGE.
   35*/
   36
   37:- module(prolog_xref,
   38          [ xref_source/1,              % +Source
   39            xref_source/2,              % +Source, +Options
   40            xref_called/3,              % ?Source, ?Callable, ?By
   41            xref_called/4,              % ?Source, ?Callable, ?By, ?Cond
   42            xref_called/5,              % ?Source, ?Callable, ?By, ?Cond, ?Line
   43            xref_defined/3,             % ?Source. ?Callable, -How
   44            xref_definition_line/2,     % +How, -Line
   45            xref_exported/2,            % ?Source, ?Callable
   46            xref_module/2,              % ?Source, ?Module
   47            xref_uses_file/3,           % ?Source, ?Spec, ?Path
   48            xref_op/2,                  % ?Source, ?Op
   49            xref_prolog_flag/4,         % ?Source, ?Flag, ?Value, ?Line
   50            xref_comment/3,             % ?Source, ?Title, ?Comment
   51            xref_comment/4,             % ?Source, ?Head, ?Summary, ?Comment
   52            xref_mode/3,                % ?Source, ?Mode, ?Det
   53            xref_option/2,              % ?Source, ?Option
   54            xref_clean/1,               % +Source
   55            xref_current_source/1,      % ?Source
   56            xref_done/2,                % +Source, -When
   57            xref_built_in/1,            % ?Callable
   58            xref_source_file/3,         % +Spec, -Path, +Source
   59            xref_source_file/4,         % +Spec, -Path, +Source, +Options
   60            xref_public_list/3,         % +File, +Src, +Options
   61            xref_public_list/4,         % +File, -Path, -Export, +Src
   62            xref_public_list/6,         % +File, -Path, -Module, -Export, -Meta, +Src
   63            xref_public_list/7,         % +File, -Path, -Module, -Export, -Public, -Meta, +Src
   64            xref_meta/3,                % +Source, +Goal, -Called
   65            xref_meta/2,                % +Goal, -Called
   66            xref_hook/1,                % ?Callable
   67                                        % XPCE class references
   68            xref_used_class/2,          % ?Source, ?ClassName
   69            xref_defined_class/3        % ?Source, ?ClassName, -How
   70          ]).   71:- use_module(library(debug), [debug/3]).   72:- use_module(library(lists), [append/3, append/2, member/2, select/3]).   73:- use_module(library(operators), [push_op/3]).   74:- use_module(library(shlib), [current_foreign_library/2]).   75:- use_module(library(ordsets)).   76:- use_module(library(prolog_source)).   77:- use_module(library(option)).   78:- use_module(library(error)).   79:- use_module(library(apply)).   80:- use_module(library(debug)).   81:- if(exists_source(library(pldoc))).   82:- use_module(library(pldoc), []).      % Must be loaded before doc_process
   83:- use_module(library(pldoc/doc_process)).   84:- endif.   85:- use_module(library(solution_sequences)).   86:- use_module(library(modules)).   87
   88:- predicate_options(xref_source/2, 2,
   89                     [ silent(boolean),
   90                       module(atom),
   91                       register_called(oneof([all,non_iso,non_built_in])),
   92                       comments(oneof([store,collect,ignore])),
   93                       process_include(boolean)
   94                     ]).   95
   96
   97:- dynamic
   98    called/5,                       % Head, Src, From, Cond, Line
   99    (dynamic)/3,                    % Head, Src, Line
  100    (thread_local)/3,               % Head, Src, Line
  101    (multifile)/3,                  % Head, Src, Line
  102    (public)/3,                     % Head, Src, Line
  103    defined/3,                      % Head, Src, Line
  104    meta_goal/3,                    % Head, Called, Src
  105    foreign/3,                      % Head, Src, Line
  106    constraint/3,                   % Head, Src, Line
  107    imported/3,                     % Head, Src, From
  108    exported/2,                     % Head, Src
  109    xmodule/2,                      % Module, Src
  110    uses_file/3,                    % Spec, Src, Path
  111    xop/2,                          % Src, Op
  112    source/2,                       % Src, Time
  113    used_class/2,                   % Name, Src
  114    defined_class/5,                % Name, Super, Summary, Src, Line
  115    (mode)/2,                       % Mode, Src
  116    xoption/2,                      % Src, Option
  117    xflag/4,                        % Name, Value, Src, Line
  118
  119    module_comment/3,               % Src, Title, Comment
  120    pred_comment/4,                 % Head, Src, Summary, Comment
  121    pred_comment_link/3,            % Head, Src, HeadTo
  122    pred_mode/3.                    % Head, Src, Det
  123
  124:- 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.
  161:- predicate_options(xref_source_file/4, 4,
  162                     [ file_type(oneof([txt,prolog,directory])),
  163                       silent(boolean)
  164                     ]).  165:- predicate_options(xref_public_list/3, 3,
  166                     [ path(-atom),
  167                       module(-atom),
  168                       exports(-list(any)),
  169                       public(-list(any)),
  170                       meta(-list(any)),
  171                       silent(boolean)
  172                     ]).  173
  174
  175                 /*******************************
  176                 *            HOOKS             *
  177                 *******************************/
 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).
  204:- multifile
  205    prolog:called_by/4,             % +Goal, +Module, +Context, -Called
  206    prolog:called_by/2,             % +Goal, -Called
  207    prolog:meta_goal/2,             % +Goal, -Pattern
  208    prolog:hook/1,                  % +Callable
  209    prolog:generated_predicate/1.   % :PI
  210
  211:- meta_predicate
  212    prolog:generated_predicate(:).  213
  214:- dynamic
  215    meta_goal/2.  216
  217:- meta_predicate
  218    process_predicates(2, +, +).  219
  220                 /*******************************
  221                 *           BUILT-INS          *
  222                 *******************************/
 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.
  230hide_called(Callable, Src) :-
  231    xoption(Src, register_called(Which)),
  232    !,
  233    mode_hide_called(Which, Callable).
  234hide_called(Callable, _) :-
  235    mode_hide_called(non_built_in, Callable).
  236
  237mode_hide_called(all, _) :- !, fail.
  238mode_hide_called(non_iso, _:Goal) :-
  239    goal_name_arity(Goal, Name, Arity),
  240    current_predicate(system:Name/Arity),
  241    predicate_property(system:Goal, iso).
  242mode_hide_called(non_built_in, _:Goal) :-
  243    goal_name_arity(Goal, Name, Arity),
  244    current_predicate(system:Name/Arity),
  245    predicate_property(system:Goal, built_in).
  246mode_hide_called(non_built_in, M:Goal) :-
  247    goal_name_arity(Goal, Name, Arity),
  248    current_predicate(M:Name/Arity),
  249    predicate_property(M:Goal, built_in).
 built_in_predicate(+Callable)
True if Callable is a built-in
  255system_predicate(Goal) :-
  256    goal_name_arity(Goal, Name, Arity),
  257    current_predicate(system:Name/Arity),   % avoid autoloading
  258    predicate_property(system:Goal, built_in),
  259    !.
  260
  261
  262                /********************************
  263                *            TOPLEVEL           *
  264                ********************************/
  265
  266verbose(Src) :-
  267    \+ xoption(Src, silent(true)).
  268
  269:- thread_local
  270    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
  298xref_source(Source) :-
  299    xref_source(Source, []).
  300
  301xref_source(Source, Options) :-
  302    prolog_canonical_source(Source, Src),
  303    (   last_modified(Source, Modified)
  304    ->  (   source(Src, Modified)
  305        ->  true
  306        ;   xref_clean(Src),
  307            assert(source(Src, Modified)),
  308            do_xref(Src, Options)
  309        )
  310    ;   xref_clean(Src),
  311        get_time(Now),
  312        assert(source(Src, Now)),
  313        do_xref(Src, Options)
  314    ).
  315
  316do_xref(Src, Options) :-
  317    must_be(list, Options),
  318    setup_call_cleanup(
  319        xref_setup(Src, In, Options, State),
  320        collect(Src, Src, In, Options),
  321        xref_cleanup(State)).
  322
  323last_modified(Source, Modified) :-
  324    prolog:xref_source_time(Source, Modified),
  325    !.
  326last_modified(Source, Modified) :-
  327    atom(Source),
  328    \+ is_global_url(Source),
  329    exists_file(Source),
  330    time_file(Source, Modified).
  331
  332is_global_url(File) :-
  333    sub_atom(File, B, _, _, '://'),
  334    !,
  335    B > 1,
  336    sub_atom(File, 0, B, _, Scheme),
  337    atom_codes(Scheme, Codes),
  338    maplist(between(0'a, 0'z), Codes).
  339
  340xref_setup(Src, In, Options, state(In, Dialect, Xref, [SRef|HRefs])) :-
  341    maplist(assert_option(Src), Options),
  342    assert_default_options(Src),
  343    current_prolog_flag(emulated_dialect, Dialect),
  344    prolog_open_source(Src, In),
  345    set_initial_mode(In, Options),
  346    asserta(xref_input(Src, In), SRef),
  347    set_xref(Xref),
  348    (   verbose(Src)
  349    ->  HRefs = []
  350    ;   asserta(user:thread_message_hook(_,_,_), Ref),
  351        HRefs = [Ref]
  352    ).
  353
  354assert_option(_, Var) :-
  355    var(Var),
  356    !,
  357    instantiation_error(Var).
  358assert_option(Src, silent(Boolean)) :-
  359    !,
  360    must_be(boolean, Boolean),
  361    assert(xoption(Src, silent(Boolean))).
  362assert_option(Src, register_called(Which)) :-
  363    !,
  364    must_be(oneof([all,non_iso,non_built_in]), Which),
  365    assert(xoption(Src, register_called(Which))).
  366assert_option(Src, comments(CommentHandling)) :-
  367    !,
  368    must_be(oneof([store,collect,ignore]), CommentHandling),
  369    assert(xoption(Src, comments(CommentHandling))).
  370assert_option(Src, module(Module)) :-
  371    !,
  372    must_be(atom, Module),
  373    assert(xoption(Src, module(Module))).
  374assert_option(Src, process_include(Boolean)) :-
  375    !,
  376    must_be(boolean, Boolean),
  377    assert(xoption(Src, process_include(Boolean))).
  378
  379assert_default_options(Src) :-
  380    (   xref_option_default(Opt),
  381        generalise_term(Opt, Gen),
  382        (   xoption(Src, Gen)
  383        ->  true
  384        ;   assertz(xoption(Src, Opt))
  385        ),
  386        fail
  387    ;   true
  388    ).
  389
  390xref_option_default(silent(false)).
  391xref_option_default(register_called(non_built_in)).
  392xref_option_default(comments(collect)).
  393xref_option_default(process_include(true)).
 xref_cleanup(+State) is det
Restore processing state according to the saved State.
  399xref_cleanup(state(In, Dialect, Xref, Refs)) :-
  400    prolog_close_source(In),
  401    set_prolog_flag(emulated_dialect, Dialect),
  402    set_prolog_flag(xref, Xref),
  403    maplist(erase, Refs).
  404
  405set_xref(Xref) :-
  406    current_prolog_flag(xref, Xref),
  407    set_prolog_flag(xref, true).
 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.
  416set_initial_mode(_Stream, Options) :-
  417    option(module(Module), Options),
  418    !,
  419    '$set_source_module'(Module).
  420set_initial_mode(Stream, _) :-
  421    stream_property(Stream, file_name(Path)),
  422    source_file_property(Path, load_context(M, _, Opts)),
  423    !,
  424    '$set_source_module'(M),
  425    (   option(dialect(Dialect), Opts)
  426    ->  expects_dialect(Dialect)
  427    ;   true
  428    ).
  429set_initial_mode(_, _) :-
  430    '$set_source_module'(user).
 xref_input_stream(-Stream) is det
Current input stream for cross-referencer.
  436xref_input_stream(Stream) :-
  437    xref_input(_, Var),
  438    !,
  439    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.
  446xref_push_op(Src, P, T, N0) :-
  447    '$current_source_module'(M0),
  448    strip_module(M0:N0, M, N),
  449    (   is_list(N),
  450        N \== []
  451    ->  maplist(push_op(Src, P, T, M), N)
  452    ;   push_op(Src, P, T, M, N)
  453    ).
  454
  455push_op(Src, P, T, M0, N0) :-
  456    strip_module(M0:N0, M, N),
  457    Name = M:N,
  458    valid_op(op(P,T,Name)),
  459    push_op(P, T, Name),
  460    assert_op(Src, op(P,T,Name)),
  461    debug(xref(op), ':- ~w.', [op(P,T,Name)]).
  462
  463valid_op(op(P,T,M:N)) :-
  464    atom(M),
  465    valid_op_name(N),
  466    integer(P),
  467    between(0, 1200, P),
  468    atom(T),
  469    op_type(T).
  470
  471valid_op_name(N) :-
  472    atom(N),
  473    !.
  474valid_op_name(N) :-
  475    N == [].
  476
  477op_type(xf).
  478op_type(yf).
  479op_type(fx).
  480op_type(fy).
  481op_type(xfx).
  482op_type(xfy).
  483op_type(yfx).
 xref_set_prolog_flag(+Flag, +Value, +Src, +Line)
Called when a directive sets a Prolog flag.
  489xref_set_prolog_flag(Flag, Value, Src, Line) :-
  490    atom(Flag),
  491    !,
  492    assertz(xflag(Flag, Value, Src, Line)).
  493xref_set_prolog_flag(_, _, _, _).
 xref_clean(+Source) is det
Reset the database for the given source.
  499xref_clean(Source) :-
  500    prolog_canonical_source(Source, Src),
  501    retractall(called(_, Src, _Origin, _Cond, _Line)),
  502    retractall(dynamic(_, Src, Line)),
  503    retractall(multifile(_, Src, Line)),
  504    retractall(public(_, Src, Line)),
  505    retractall(defined(_, Src, Line)),
  506    retractall(meta_goal(_, _, Src)),
  507    retractall(foreign(_, Src, Line)),
  508    retractall(constraint(_, Src, Line)),
  509    retractall(imported(_, Src, _From)),
  510    retractall(exported(_, Src)),
  511    retractall(uses_file(_, Src, _)),
  512    retractall(xmodule(_, Src)),
  513    retractall(xop(Src, _)),
  514    retractall(xoption(Src, _)),
  515    retractall(xflag(_Name, _Value, Src, Line)),
  516    retractall(source(Src, _)),
  517    retractall(used_class(_, Src)),
  518    retractall(defined_class(_, _, _, Src, _)),
  519    retractall(mode(_, Src)),
  520    retractall(module_comment(Src, _, _)),
  521    retractall(pred_comment(_, Src, _, _)),
  522    retractall(pred_comment_link(_, Src, _)),
  523    retractall(pred_mode(_, Src, _)).
  524
  525
  526                 /*******************************
  527                 *          READ RESULTS        *
  528                 *******************************/
 xref_current_source(?Source)
Check what sources have been analysed.
  534xref_current_source(Source) :-
  535    source(Source, _Time).
 xref_done(+Source, -Time) is det
Cross-reference executed at Time
  542xref_done(Source, Time) :-
  543    prolog_canonical_source(Source, Src),
  544    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.
  566xref_called(Source, Called, By) :-
  567    xref_called(Source, Called, By, _).
  568
  569xref_called(Source, Called, By, Cond) :-
  570    canonical_source(Source, Src),
  571    distinct(Called-By, called(Called, Src, By, Cond, _)).
  572
  573xref_called(Source, Called, By, Cond, Line) :-
  574    canonical_source(Source, Src),
  575    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.
  596xref_defined(Source, Called, How) :-
  597    nonvar(Source),
  598    !,
  599    canonical_source(Source, Src),
  600    xref_defined2(How, Src, Called).
  601xref_defined(Source, Called, How) :-
  602    xref_defined2(How, Src, Called),
  603    canonical_source(Source, Src).
  604
  605xref_defined2(dynamic(Line), Src, Called) :-
  606    dynamic(Called, Src, Line).
  607xref_defined2(thread_local(Line), Src, Called) :-
  608    thread_local(Called, Src, Line).
  609xref_defined2(multifile(Line), Src, Called) :-
  610    multifile(Called, Src, Line).
  611xref_defined2(public(Line), Src, Called) :-
  612    public(Called, Src, Line).
  613xref_defined2(local(Line), Src, Called) :-
  614    defined(Called, Src, Line).
  615xref_defined2(foreign(Line), Src, Called) :-
  616    foreign(Called, Src, Line).
  617xref_defined2(constraint(Line), Src, Called) :-
  618    constraint(Called, Src, Line).
  619xref_defined2(imported(From), Src, Called) :-
  620    imported(Called, Src, From).
 xref_definition_line(+How, -Line)
If the 3th argument of xref_defined contains line info, return this in Line.
  628xref_definition_line(local(Line),        Line).
  629xref_definition_line(dynamic(Line),      Line).
  630xref_definition_line(thread_local(Line), Line).
  631xref_definition_line(multifile(Line),    Line).
  632xref_definition_line(public(Line),       Line).
  633xref_definition_line(constraint(Line),   Line).
  634xref_definition_line(foreign(Line),      Line).
 xref_exported(?Source, ?Head) is nondet
True when Source exports Head.
  641xref_exported(Source, Called) :-
  642    prolog_canonical_source(Source, Src),
  643    exported(Called, Src).
 xref_module(?Source, ?Module) is nondet
True if Module is defined in Source.
  649xref_module(Source, Module) :-
  650    nonvar(Source),
  651    !,
  652    prolog_canonical_source(Source, Src),
  653    xmodule(Module, Src).
  654xref_module(Source, Module) :-
  655    xmodule(Module, Src),
  656    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>.
  666xref_uses_file(Source, Spec, Path) :-
  667    prolog_canonical_source(Source, Src),
  668    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)
  678xref_op(Source, Op) :-
  679    prolog_canonical_source(Source, Src),
  680    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.
  688xref_prolog_flag(Source, Flag, Value, Line) :-
  689    prolog_canonical_source(Source, Src),
  690    xflag(Flag, Value, Src, Line).
  691
  692xref_built_in(Head) :-
  693    system_predicate(Head).
  694
  695xref_used_class(Source, Class) :-
  696    prolog_canonical_source(Source, Src),
  697    used_class(Class, Src).
  698
  699xref_defined_class(Source, Class, local(Line, Super, Summary)) :-
  700    prolog_canonical_source(Source, Src),
  701    defined_class(Class, Super, Summary, Src, Line),
  702    integer(Line),
  703    !.
  704xref_defined_class(Source, Class, file(File)) :-
  705    prolog_canonical_source(Source, Src),
  706    defined_class(Class, _, _, Src, file(File)).
  707
  708:- thread_local
  709    current_cond/1,
  710    source_line/1.  711
  712current_source_line(Line) :-
  713    source_line(Var),
  714    !,
  715    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.
  723collect(Src, File, In, Options) :-
  724    (   Src == File
  725    ->  SrcSpec = Line
  726    ;   SrcSpec = (File:Line)
  727    ),
  728    option(comments(CommentHandling), Options, collect),
  729    (   CommentHandling == ignore
  730    ->  CommentOptions = [],
  731        Comments = []
  732    ;   CommentHandling == store
  733    ->  CommentOptions = [ process_comment(true) ],
  734        Comments = []
  735    ;   CommentOptions = [ comments(Comments) ]
  736    ),
  737    repeat,
  738        catch(prolog_read_source_term(
  739                  In, Term, Expanded,
  740                  [ term_position(TermPos)
  741                  | CommentOptions
  742                  ]),
  743              E, report_syntax_error(E, Src, [])),
  744        update_condition(Term),
  745        stream_position_data(line_count, TermPos, Line),
  746        setup_call_cleanup(
  747            asserta(source_line(SrcSpec), Ref),
  748            catch(process(Expanded, Comments, TermPos, Src, EOF),
  749                  E, print_message(error, E)),
  750            erase(Ref)),
  751        EOF == true,
  752    !.
  753
  754report_syntax_error(E, _, _) :-
  755    fatal_error(E),
  756    throw(E).
  757report_syntax_error(_, _, Options) :-
  758    option(silent(true), Options),
  759    !,
  760    fail.
  761report_syntax_error(E, Src, _Options) :-
  762    (   verbose(Src)
  763    ->  print_message(error, E)
  764    ;   true
  765    ),
  766    fail.
  767
  768fatal_error(time_limit_exceeded).
  769fatal_error(error(resource_error(_),_)).
 update_condition(+Term) is det
Update the condition under which the current code is compiled.
  775update_condition((:-Directive)) :-
  776    !,
  777    update_cond(Directive).
  778update_condition(_).
  779
  780update_cond(if(Cond)) :-
  781    !,
  782    asserta(current_cond(Cond)).
  783update_cond(else) :-
  784    retract(current_cond(C0)),
  785    !,
  786    assert(current_cond(\+C0)).
  787update_cond(elif(Cond)) :-
  788    retract(current_cond(C0)),
  789    !,
  790    assert(current_cond((\+C0,Cond))).
  791update_cond(endif) :-
  792    retract(current_cond(_)),
  793    !.
  794update_cond(_).
 current_condition(-Condition) is det
Condition is the current compilation condition as defined by the :- if/1 directive and friends.
  801current_condition(Condition) :-
  802    \+ current_cond(_),
  803    !,
  804    Condition = true.
  805current_condition(Condition) :-
  806    findall(C, current_cond(C), List),
  807    list_to_conj(List, Condition).
  808
  809list_to_conj([], true).
  810list_to_conj([C], C) :- !.
  811list_to_conj([H|T], (H,C)) :-
  812    list_to_conj(T, C).
  813
  814
  815                 /*******************************
  816                 *           PROCESS            *
  817                 *******************************/
 process(+Expanded, +Comments, +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.
  829process(Expanded, Comments, TermPos, Src, EOF) :-
  830    is_list(Expanded),                          % term_expansion into list.
  831    !,
  832    (   member(Term, Expanded),
  833        process(Term, Src),
  834        Term == end_of_file
  835    ->  EOF = true
  836    ;   EOF = false
  837    ),
  838    xref_comments(Comments, TermPos, Src).
  839process(end_of_file, _, _, _, true) :-
  840    !.
  841process(Term, Comments, TermPos, Src, false) :-
  842    process(Term, Src),
  843    xref_comments(Comments, TermPos, Src).
 process(+Term, +Src) is det
  847process(Var, _) :-
  848    var(Var),
  849    !.                    % Warn?
  850process(end_of_file, _) :- !.
  851process((:- Directive), Src) :-
  852    !,
  853    process_directive(Directive, Src),
  854    !.
  855process((?- Directive), Src) :-
  856    !,
  857    process_directive(Directive, Src),
  858    !.
  859process((Head :- Body), Src) :-
  860    !,
  861    assert_defined(Src, Head),
  862    process_body(Body, Head, Src).
  863process('$source_location'(_File, _Line):Clause, Src) :-
  864    !,
  865    process(Clause, Src).
  866process(Term, Src) :-
  867    process_chr(Term, Src),
  868    !.
  869process(M:(Head :- Body), Src) :-
  870    !,
  871    process((M:Head :- M:Body), Src).
  872process(Head, Src) :-
  873    assert_defined(Src, Head).
  874
  875
  876                 /*******************************
  877                 *            COMMENTS          *
  878                 *******************************/
 xref_comments(+Comments, +FilePos, +Src) is det
  882xref_comments([], _Pos, _Src).
  883:- if(current_predicate(parse_comment/3)).  884xref_comments([Pos-Comment|T], TermPos, Src) :-
  885    (   Pos @> TermPos              % comments inside term
  886    ->  true
  887    ;   stream_position_data(line_count, Pos, Line),
  888        FilePos = Src:Line,
  889        (   parse_comment(Comment, FilePos, Parsed)
  890        ->  assert_comments(Parsed, Src)
  891        ;   true
  892        ),
  893        xref_comments(T, TermPos, Src)
  894    ).
  895
  896assert_comments([], _).
  897assert_comments([H|T], Src) :-
  898    assert_comment(H, Src),
  899    assert_comments(T, Src).
  900
  901assert_comment(section(_Id, Title, Comment), Src) :-
  902    assertz(module_comment(Src, Title, Comment)).
  903assert_comment(predicate(PI, Summary, Comment), Src) :-
  904    pi_to_head(PI, Src, Head),
  905    assertz(pred_comment(Head, Src, Summary, Comment)).
  906assert_comment(link(PI, PITo), Src) :-
  907    pi_to_head(PI, Src, Head),
  908    pi_to_head(PITo, Src, HeadTo),
  909    assertz(pred_comment_link(Head, Src, HeadTo)).
  910assert_comment(mode(Head, Det), Src) :-
  911    assertz(pred_mode(Head, Src, Det)).
  912
  913pi_to_head(PI, Src, Head) :-
  914    pi_to_head(PI, Head0),
  915    (   Head0 = _:_
  916    ->  strip_module(Head0, M, Plain),
  917        (   xmodule(M, Src)
  918        ->  Head = Plain
  919        ;   Head = M:Plain
  920        )
  921    ;   Head = Head0
  922    ).
  923:- endif.
 xref_comment(?Source, ?Title, ?Comment) is nondet
Is true when Source has a section comment with Title and Comment
  929xref_comment(Source, Title, Comment) :-
  930    canonical_source(Source, Src),
  931    module_comment(Src, Title, Comment).
 xref_comment(?Source, ?Head, ?Summary, ?Comment) is nondet
Is true when Head in Source has the given PlDoc comment.
  937xref_comment(Source, Head, Summary, Comment) :-
  938    canonical_source(Source, Src),
  939    (   pred_comment(Head, Src, Summary, Comment)
  940    ;   pred_comment_link(Head, Src, HeadTo),
  941        pred_comment(HeadTo, Src, Summary, Comment)
  942    ).
 xref_mode(?Source, ?Mode, ?Det) is nondet
Is true when Source provides a predicate with Mode and determinism.
  949xref_mode(Source, Mode, Det) :-
  950    canonical_source(Source, Src),
  951    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.
  958xref_option(Source, Option) :-
  959    canonical_source(Source, Src),
  960    xoption(Src, Option).
  961
  962
  963                 /********************************
  964                 *           DIRECTIVES         *
  965                 ********************************/
  966
  967process_directive(Var, _) :-
  968    var(Var),
  969    !.                    % error, but that isn't our business
  970process_directive(Dir, _Src) :-
  971    debug(xref(directive), 'Processing :- ~q', [Dir]),
  972    fail.
  973process_directive((A,B), Src) :-       % TBD: what about other control
  974    !,
  975    process_directive(A, Src),      % structures?
  976    process_directive(B, Src).
  977process_directive(List, Src) :-
  978    is_list(List),
  979    !,
  980    process_directive(consult(List), Src).
  981process_directive(use_module(File, Import), Src) :-
  982    process_use_module2(File, Import, Src, false).
  983process_directive(expects_dialect(Dialect), Src) :-
  984    process_directive(use_module(library(dialect/Dialect)), Src),
  985    expects_dialect(Dialect).
  986process_directive(reexport(File, Import), Src) :-
  987    process_use_module2(File, Import, Src, true).
  988process_directive(reexport(Modules), Src) :-
  989    process_use_module(Modules, Src, true).
  990process_directive(use_module(Modules), Src) :-
  991    process_use_module(Modules, Src, false).
  992process_directive(consult(Modules), Src) :-
  993    process_use_module(Modules, Src, false).
  994process_directive(ensure_loaded(Modules), Src) :-
  995    process_use_module(Modules, Src, false).
  996process_directive(load_files(Files, _Options), Src) :-
  997    process_use_module(Files, Src, false).
  998process_directive(include(Files), Src) :-
  999    process_include(Files, Src).
 1000process_directive(dynamic(Dynamic), Src) :-
 1001    process_predicates(assert_dynamic, Dynamic, Src).
 1002process_directive(dynamic(Dynamic, _Options), Src) :-
 1003    process_predicates(assert_dynamic, Dynamic, Src).
 1004process_directive(thread_local(Dynamic), Src) :-
 1005    process_predicates(assert_thread_local, Dynamic, Src).
 1006process_directive(multifile(Dynamic), Src) :-
 1007    process_predicates(assert_multifile, Dynamic, Src).
 1008process_directive(public(Public), Src) :-
 1009    process_predicates(assert_public, Public, Src).
 1010process_directive(export(Export), Src) :-
 1011    process_predicates(assert_export, Export, Src).
 1012process_directive(import(Import), Src) :-
 1013    process_import(Import, Src).
 1014process_directive(module(Module, Export), Src) :-
 1015    assert_module(Src, Module),
 1016    assert_module_export(Src, Export).
 1017process_directive(module(Module, Export, Import), Src) :-
 1018    assert_module(Src, Module),
 1019    assert_module_export(Src, Export),
 1020    assert_module3(Import, Src).
 1021process_directive('$set_source_module'(system), Src) :-
 1022    assert_module(Src, system).     % hack for handling boot/init.pl
 1023process_directive(pce_begin_class_definition(Name, Meta, Super, Doc), Src) :-
 1024    assert_defined_class(Src, Name, Meta, Super, Doc).
 1025process_directive(pce_autoload(Name, From), Src) :-
 1026    assert_defined_class(Src, Name, imported_from(From)).
 1027
 1028process_directive(op(P, A, N), Src) :-
 1029    xref_push_op(Src, P, A, N).
 1030process_directive(set_prolog_flag(Flag, Value), Src) :-
 1031    (   Flag == character_escapes
 1032    ->  set_prolog_flag(character_escapes, Value)
 1033    ;   true
 1034    ),
 1035    current_source_line(Line),
 1036    xref_set_prolog_flag(Flag, Value, Src, Line).
 1037process_directive(style_check(X), _) :-
 1038    style_check(X).
 1039process_directive(encoding(Enc), _) :-
 1040    (   xref_input_stream(Stream)
 1041    ->  catch(set_stream(Stream, encoding(Enc)), _, true)
 1042    ;   true                        % can this happen?
 1043    ).
 1044process_directive(pce_expansion:push_compile_operators, _) :-
 1045    '$current_source_module'(SM),
 1046    call(pce_expansion:push_compile_operators(SM)). % call to avoid xref
 1047process_directive(pce_expansion:pop_compile_operators, _) :-
 1048    call(pce_expansion:pop_compile_operators).
 1049process_directive(meta_predicate(Meta), Src) :-
 1050    process_meta_predicate(Meta, Src).
 1051process_directive(arithmetic_function(FSpec), Src) :-
 1052    arith_callable(FSpec, Goal),
 1053    !,
 1054    current_source_line(Line),
 1055    assert_called(Src, '<directive>'(Line), Goal, Line).
 1056process_directive(format_predicate(_, Goal), Src) :-
 1057    !,
 1058    current_source_line(Line),
 1059    assert_called(Src, '<directive>'(Line), Goal, Line).
 1060process_directive(if(Cond), Src) :-
 1061    !,
 1062    current_source_line(Line),
 1063    assert_called(Src, '<directive>'(Line), Cond, Line).
 1064process_directive(elif(Cond), Src) :-
 1065    !,
 1066    current_source_line(Line),
 1067    assert_called(Src, '<directive>'(Line), Cond, Line).
 1068process_directive(else, _) :- !.
 1069process_directive(endif, _) :- !.
 1070process_directive(Goal, Src) :-
 1071    current_source_line(Line),
 1072    process_body(Goal, '<directive>'(Line), Src).
 process_meta_predicate(+Decl, +Src)
Create meta_goal/3 facts from the meta-goal declaration.
 1078process_meta_predicate((A,B), Src) :-
 1079    !,
 1080    process_meta_predicate(A, Src),
 1081    process_meta_predicate(B, Src).
 1082process_meta_predicate(Decl, Src) :-
 1083    process_meta_head(Src, Decl).
 1084
 1085process_meta_head(Src, Decl) :-         % swapped arguments for maplist
 1086    compound(Decl),
 1087    compound_name_arity(Decl, Name, Arity),
 1088    compound_name_arity(Head, Name, Arity),
 1089    meta_args(1, Arity, Decl, Head, Meta),
 1090    (   (   prolog:meta_goal(Head, _)
 1091        ;   prolog:called_by(Head, _, _, _)
 1092        ;   prolog:called_by(Head, _)
 1093        ;   meta_goal(Head, _)
 1094        )
 1095    ->  true
 1096    ;   assert(meta_goal(Head, Meta, Src))
 1097    ).
 1098
 1099meta_args(I, Arity, _, _, []) :-
 1100    I > Arity,
 1101    !.
 1102meta_args(I, Arity, Decl, Head, [H|T]) :-               % 0
 1103    arg(I, Decl, 0),
 1104    !,
 1105    arg(I, Head, H),
 1106    I2 is I + 1,
 1107    meta_args(I2, Arity, Decl, Head, T).
 1108meta_args(I, Arity, Decl, Head, [H|T]) :-               % ^
 1109    arg(I, Decl, ^),
 1110    !,
 1111    arg(I, Head, EH),
 1112    setof_goal(EH, H),
 1113    I2 is I + 1,
 1114    meta_args(I2, Arity, Decl, Head, T).
 1115meta_args(I, Arity, Decl, Head, [//(H)|T]) :-
 1116    arg(I, Decl, //),
 1117    !,
 1118    arg(I, Head, H),
 1119    I2 is I + 1,
 1120    meta_args(I2, Arity, Decl, Head, T).
 1121meta_args(I, Arity, Decl, Head, [H+A|T]) :-             % I --> H+I
 1122    arg(I, Decl, A),
 1123    integer(A), A > 0,
 1124    !,
 1125    arg(I, Head, H),
 1126    I2 is I + 1,
 1127    meta_args(I2, Arity, Decl, Head, T).
 1128meta_args(I, Arity, Decl, Head, Meta) :-
 1129    I2 is I + 1,
 1130    meta_args(I2, Arity, Decl, Head, Meta).
 1131
 1132
 1133              /********************************
 1134              *             BODY              *
 1135              ********************************/
 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).
 1144xref_meta(Source, Head, Called) :-
 1145    canonical_source(Source, Src),
 1146    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.
 1161xref_meta_src(Head, Called, Src) :-
 1162    meta_goal(Head, Called, Src),
 1163    !.
 1164xref_meta_src(Head, Called, _) :-
 1165    xref_meta(Head, Called),
 1166    !.
 1167xref_meta_src(Head, Called, _) :-
 1168    compound(Head),
 1169    compound_name_arity(Head, Name, Arity),
 1170    apply_pred(Name),
 1171    Arity > 5,
 1172    !,
 1173    Extra is Arity - 1,
 1174    arg(1, Head, G),
 1175    Called = [G+Extra].
 1176
 1177apply_pred(call).                               % built-in
 1178apply_pred(maplist).                            % library(apply_macros)
 1179
 1180xref_meta((A, B),               [A, B]).
 1181xref_meta((A; B),               [A, B]).
 1182xref_meta((A| B),               [A, B]).
 1183xref_meta((A -> B),             [A, B]).
 1184xref_meta((A *-> B),            [A, B]).
 1185xref_meta(findall(_V,G,_L),     [G]).
 1186xref_meta(findall(_V,G,_L,_T),  [G]).
 1187xref_meta(findnsols(_N,_V,G,_L),    [G]).
 1188xref_meta(findnsols(_N,_V,G,_L,_T), [G]).
 1189xref_meta(setof(_V, EG, _L),    [G]) :-
 1190    setof_goal(EG, G).
 1191xref_meta(bagof(_V, EG, _L),    [G]) :-
 1192    setof_goal(EG, G).
 1193xref_meta(forall(A, B),         [A, B]).
 1194xref_meta(maplist(G,_),         [G+1]).
 1195xref_meta(maplist(G,_,_),       [G+2]).
 1196xref_meta(maplist(G,_,_,_),     [G+3]).
 1197xref_meta(maplist(G,_,_,_,_),   [G+4]).
 1198xref_meta(map_list_to_pairs(G,_,_), [G+2]).
 1199xref_meta(map_assoc(G, _),      [G+1]).
 1200xref_meta(map_assoc(G, _, _),   [G+2]).
 1201xref_meta(checklist(G, _L),     [G+1]).
 1202xref_meta(sublist(G, _, _),     [G+1]).
 1203xref_meta(include(G, _, _),     [G+1]).
 1204xref_meta(exclude(G, _, _),     [G+1]).
 1205xref_meta(partition(G, _, _, _, _),     [G+2]).
 1206xref_meta(partition(G, _, _, _),[G+1]).
 1207xref_meta(call(G),              [G]).
 1208xref_meta(call(G, _),           [G+1]).
 1209xref_meta(call(G, _, _),        [G+2]).
 1210xref_meta(call(G, _, _, _),     [G+3]).
 1211xref_meta(call(G, _, _, _, _),  [G+4]).
 1212xref_meta(not(G),               [G]).
 1213xref_meta(notrace(G),           [G]).
 1214xref_meta(\+(G),                [G]).
 1215xref_meta(ignore(G),            [G]).
 1216xref_meta(once(G),              [G]).
 1217xref_meta(initialization(G),    [G]).
 1218xref_meta(initialization(G,_),  [G]).
 1219xref_meta(retract(Rule),        [G]) :- head_of(Rule, G).
 1220xref_meta(clause(G, _),         [G]).
 1221xref_meta(clause(G, _, _),      [G]).
 1222xref_meta(phrase(G, _A),        [//(G)]).
 1223xref_meta(phrase(G, _A, _R),    [//(G)]).
 1224xref_meta(call_dcg(G, _A, _R),  [//(G)]).
 1225xref_meta(phrase_from_file(G,_),[//(G)]).
 1226xref_meta(catch(A, _, B),       [A, B]).
 1227xref_meta(catch_with_backtrace(A, _, B), [A, B]).
 1228xref_meta(thread_create(A,_,_), [A]).
 1229xref_meta(thread_create(A,_),   [A]).
 1230xref_meta(thread_signal(_,A),   [A]).
 1231xref_meta(thread_at_exit(A),    [A]).
 1232xref_meta(thread_initialization(A), [A]).
 1233xref_meta(engine_create(_,A,_), [A]).
 1234xref_meta(engine_create(_,A,_,_), [A]).
 1235xref_meta(predsort(A,_,_),      [A+3]).
 1236xref_meta(call_cleanup(A, B),   [A, B]).
 1237xref_meta(call_cleanup(A, _, B),[A, B]).
 1238xref_meta(setup_call_cleanup(A, B, C),[A, B, C]).
 1239xref_meta(setup_call_catcher_cleanup(A, B, _, C),[A, B, C]).
 1240xref_meta(call_residue_vars(A,_), [A]).
 1241xref_meta(with_mutex(_,A),      [A]).
 1242xref_meta(assume(G),            [G]).   % library(debug)
 1243xref_meta(assertion(G),         [G]).   % library(debug)
 1244xref_meta(freeze(_, G),         [G]).
 1245xref_meta(when(C, A),           [C, A]).
 1246xref_meta(time(G),              [G]).   % development system
 1247xref_meta(profile(G),           [G]).
 1248xref_meta(at_halt(G),           [G]).
 1249xref_meta(call_with_time_limit(_, G), [G]).
 1250xref_meta(call_with_depth_limit(G, _, _), [G]).
 1251xref_meta(call_with_inference_limit(G, _, _), [G]).
 1252xref_meta(alarm(_, G, _),       [G]).
 1253xref_meta(alarm(_, G, _, _),    [G]).
 1254xref_meta('$add_directive_wic'(G), [G]).
 1255xref_meta(with_output_to(_, G), [G]).
 1256xref_meta(if(G),                [G]).
 1257xref_meta(elif(G),              [G]).
 1258xref_meta(meta_options(G,_,_),  [G+1]).
 1259xref_meta(on_signal(_,_,H),     [H+1]) :- H \== default.
 1260xref_meta(distinct(G),          [G]).   % library(solution_sequences)
 1261xref_meta(distinct(_, G),       [G]).
 1262xref_meta(order_by(_, G),       [G]).
 1263xref_meta(limit(_, G),          [G]).
 1264xref_meta(offset(_, G),         [G]).
 1265xref_meta(reset(G,_,_),         [G]).
 1266xref_meta(prolog_listen(Ev,G),  [G+N]) :- event_xargs(Ev, N).
 1267xref_meta(prolog_listen(Ev,G,_),[G+N]) :- event_xargs(Ev, N).
 1268
 1269                                        % XPCE meta-predicates
 1270xref_meta(pce_global(_, new(_)), _) :- !, fail.
 1271xref_meta(pce_global(_, B),     [B+1]).
 1272xref_meta(ifmaintainer(G),      [G]).   % used in manual
 1273xref_meta(listen(_, G),         [G]).   % library(broadcast)
 1274xref_meta(listen(_, _, G),      [G]).
 1275xref_meta(in_pce_thread(G),     [G]).
 1276
 1277xref_meta(G, Meta) :-                   % call user extensions
 1278    prolog:meta_goal(G, Meta).
 1279xref_meta(G, Meta) :-                   % Generated from :- meta_predicate
 1280    meta_goal(G, Meta).
 1281
 1282setof_goal(EG, G) :-
 1283    var(EG), !, G = EG.
 1284setof_goal(_^EG, G) :-
 1285    !,
 1286    setof_goal(EG, G).
 1287setof_goal(G, G).
 1288
 1289event_xargs(abort,            0).
 1290event_xargs(erase,            1).
 1291event_xargs(break,            3).
 1292event_xargs(frame_finished,   1).
 1293event_xargs(thread_exit,      1).
 1294event_xargs(this_thread_exit, 0).
 1295event_xargs(PI,               2) :- pi_to_head(PI, _).
 head_of(+Rule, -Head)
Get the head for a retract call.
 1301head_of(Var, _) :-
 1302    var(Var), !, fail.
 1303head_of((Head :- _), Head).
 1304head_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.
 1312xref_hook(Hook) :-
 1313    prolog:hook(Hook).
 1314xref_hook(Hook) :-
 1315    hook(Hook).
 1316
 1317
 1318hook(attr_portray_hook(_,_)).
 1319hook(attr_unify_hook(_,_)).
 1320hook(attribute_goals(_,_,_)).
 1321hook(goal_expansion(_,_)).
 1322hook(term_expansion(_,_)).
 1323hook(resource(_,_,_)).
 1324hook('$pred_option'(_,_,_,_)).
 1325
 1326hook(emacs_prolog_colours:goal_classification(_,_)).
 1327hook(emacs_prolog_colours:term_colours(_,_)).
 1328hook(emacs_prolog_colours:goal_colours(_,_)).
 1329hook(emacs_prolog_colours:style(_,_)).
 1330hook(emacs_prolog_colours:identify(_,_)).
 1331hook(pce_principal:pce_class(_,_,_,_,_,_)).
 1332hook(pce_principal:send_implementation(_,_,_)).
 1333hook(pce_principal:get_implementation(_,_,_,_)).
 1334hook(pce_principal:pce_lazy_get_method(_,_,_)).
 1335hook(pce_principal:pce_lazy_send_method(_,_,_)).
 1336hook(pce_principal:pce_uses_template(_,_)).
 1337hook(prolog:locate_clauses(_,_)).
 1338hook(prolog:message(_,_,_)).
 1339hook(prolog:error_message(_,_,_)).
 1340hook(prolog:message_location(_,_,_)).
 1341hook(prolog:message_context(_,_,_)).
 1342hook(prolog:message_line_element(_,_)).
 1343hook(prolog:debug_control_hook(_)).
 1344hook(prolog:help_hook(_)).
 1345hook(prolog:show_profile_hook(_,_)).
 1346hook(prolog:general_exception(_,_)).
 1347hook(prolog:predicate_summary(_,_)).
 1348hook(prolog:residual_goals(_,_)).
 1349hook(prolog_edit:load).
 1350hook(prolog_edit:locate(_,_,_)).
 1351hook(shlib:unload_all_foreign_libraries).
 1352hook(system:'$foreign_registered'(_, _)).
 1353hook(predicate_options:option_decl(_,_,_)).
 1354hook(user:exception(_,_,_)).
 1355hook(user:file_search_path(_,_)).
 1356hook(user:library_directory(_)).
 1357hook(user:message_hook(_,_,_)).
 1358hook(user:portray(_)).
 1359hook(user:prolog_clause_name(_,_)).
 1360hook(user:prolog_list_goal(_)).
 1361hook(user:prolog_predicate_name(_,_)).
 1362hook(user:prolog_trace_interception(_,_,_,_)).
 1363hook(user:prolog_exception_hook(_,_,_,_)).
 1364hook(sandbox:safe_primitive(_)).
 1365hook(sandbox:safe_meta_predicate(_)).
 1366hook(sandbox:safe_meta(_,_)).
 1367hook(sandbox:safe_global_variable(_)).
 1368hook(sandbox:safe_directive(_)).
 arith_callable(+Spec, -Callable)
Translate argument of arithmetic_function/1 into a callable term
 1375arith_callable(Var, _) :-
 1376    var(Var), !, fail.
 1377arith_callable(Module:Spec, Module:Goal) :-
 1378    !,
 1379    arith_callable(Spec, Goal).
 1380arith_callable(Name/Arity, Goal) :-
 1381    PredArity is Arity + 1,
 1382    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.

 1393process_body(Body, Origin, Src) :-
 1394    forall(limit(100, process_goal(Body, Origin, Src, _Partial)),
 1395           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.
 1402process_goal(Var, _, _, _) :-
 1403    var(Var),
 1404    !.
 1405process_goal(Goal, Origin, Src, P) :-
 1406    Goal = (_,_),                               % problems
 1407    !,
 1408    phrase(conjunction(Goal), Goals),
 1409    process_conjunction(Goals, Origin, Src, P).
 1410process_goal(Goal, Origin, Src, _) :-           % Final disjunction, no
 1411    Goal = (_;_),                               % problems
 1412    !,
 1413    phrase(disjunction(Goal), Goals),
 1414    forall(member(G, Goals),
 1415           process_body(G, Origin, Src)).
 1416process_goal(Goal, Origin, Src, P) :-
 1417    (   (   xmodule(M, Src)
 1418        ->  true
 1419        ;   M = user
 1420        ),
 1421        (   predicate_property(M:Goal, imported_from(IM))
 1422        ->  true
 1423        ;   IM = M
 1424        ),
 1425        prolog:called_by(Goal, IM, M, Called)
 1426    ;   prolog:called_by(Goal, Called)
 1427    ),
 1428    !,
 1429    must_be(list, Called),
 1430    current_source_line(Here),
 1431    assert_called(Src, Origin, Goal, Here),
 1432    process_called_list(Called, Origin, Src, P).
 1433process_goal(Goal, Origin, Src, _) :-
 1434    process_xpce_goal(Goal, Origin, Src),
 1435    !.
 1436process_goal(load_foreign_library(File), _Origin, Src, _) :-
 1437    process_foreign(File, Src).
 1438process_goal(load_foreign_library(File, _Init), _Origin, Src, _) :-
 1439    process_foreign(File, Src).
 1440process_goal(use_foreign_library(File), _Origin, Src, _) :-
 1441    process_foreign(File, Src).
 1442process_goal(use_foreign_library(File, _Init), _Origin, Src, _) :-
 1443    process_foreign(File, Src).
 1444process_goal(Goal, Origin, Src, P) :-
 1445    xref_meta_src(Goal, Metas, Src),
 1446    !,
 1447    current_source_line(Here),
 1448    assert_called(Src, Origin, Goal, Here),
 1449    process_called_list(Metas, Origin, Src, P).
 1450process_goal(Goal, Origin, Src, _) :-
 1451    asserting_goal(Goal, Rule),
 1452    !,
 1453    current_source_line(Here),
 1454    assert_called(Src, Origin, Goal, Here),
 1455    process_assert(Rule, Origin, Src).
 1456process_goal(Goal, Origin, Src, P) :-
 1457    partial_evaluate(Goal, P),
 1458    current_source_line(Here),
 1459    assert_called(Src, Origin, Goal, Here).
 1460
 1461disjunction(Var)   --> {var(Var), !}, [Var].
 1462disjunction((A;B)) --> !, disjunction(A), disjunction(B).
 1463disjunction(G)     --> [G].
 1464
 1465conjunction(Var)   --> {var(Var), !}, [Var].
 1466conjunction((A,B)) --> !, conjunction(A), conjunction(B).
 1467conjunction(G)     --> [G].
 1468
 1469shares_vars(RVars, T) :-
 1470    term_variables(T, TVars0),
 1471    sort(TVars0, TVars),
 1472    ord_intersect(RVars, TVars).
 1473
 1474process_conjunction([], _, _, _).
 1475process_conjunction([Disj|Rest], Origin, Src, P) :-
 1476    nonvar(Disj),
 1477    Disj = (_;_),
 1478    Rest \== [],
 1479    !,
 1480    phrase(disjunction(Disj), Goals),
 1481    term_variables(Rest, RVars0),
 1482    sort(RVars0, RVars),
 1483    partition(shares_vars(RVars), Goals, Sharing, NonSHaring),
 1484    forall(member(G, NonSHaring),
 1485           process_body(G, Origin, Src)),
 1486    (   Sharing == []
 1487    ->  true
 1488    ;   maplist(term_variables, Sharing, GVars0),
 1489        append(GVars0, GVars1),
 1490        sort(GVars1, GVars),
 1491        ord_intersection(GVars, RVars, SVars),
 1492        VT =.. [v|SVars],
 1493        findall(VT,
 1494                (   member(G, Sharing),
 1495                    process_goal(G, Origin, Src, PS),
 1496                    PS == true
 1497                ),
 1498                Alts0),
 1499        (   Alts0 == []
 1500        ->  true
 1501        ;   (   true
 1502            ;   P = true,
 1503                sort(Alts0, Alts1),
 1504                variants(Alts1, 10, Alts),
 1505                member(VT, Alts)
 1506            )
 1507        )
 1508    ),
 1509    process_conjunction(Rest, Origin, Src, P).
 1510process_conjunction([H|T], Origin, Src, P) :-
 1511    process_goal(H, Origin, Src, P),
 1512    process_conjunction(T, Origin, Src, P).
 1513
 1514
 1515process_called_list([], _, _, _).
 1516process_called_list([H|T], Origin, Src, P) :-
 1517    process_meta(H, Origin, Src, P),
 1518    process_called_list(T, Origin, Src, P).
 1519
 1520process_meta(A+N, Origin, Src, P) :-
 1521    !,
 1522    (   extend(A, N, AX)
 1523    ->  process_goal(AX, Origin, Src, P)
 1524    ;   true
 1525    ).
 1526process_meta(//(A), Origin, Src, P) :-
 1527    !,
 1528    process_dcg_goal(A, Origin, Src, P).
 1529process_meta(G, Origin, Src, P) :-
 1530    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.
 1537process_dcg_goal(Var, _, _, _) :-
 1538    var(Var),
 1539    !.
 1540process_dcg_goal((A,B), Origin, Src, P) :-
 1541    !,
 1542    process_dcg_goal(A, Origin, Src, P),
 1543    process_dcg_goal(B, Origin, Src, P).
 1544process_dcg_goal((A;B), Origin, Src, P) :-
 1545    !,
 1546    process_dcg_goal(A, Origin, Src, P),
 1547    process_dcg_goal(B, Origin, Src, P).
 1548process_dcg_goal((A|B), Origin, Src, P) :-
 1549    !,
 1550    process_dcg_goal(A, Origin, Src, P),
 1551    process_dcg_goal(B, Origin, Src, P).
 1552process_dcg_goal((A->B), Origin, Src, P) :-
 1553    !,
 1554    process_dcg_goal(A, Origin, Src, P),
 1555    process_dcg_goal(B, Origin, Src, P).
 1556process_dcg_goal((A*->B), Origin, Src, P) :-
 1557    !,
 1558    process_dcg_goal(A, Origin, Src, P),
 1559    process_dcg_goal(B, Origin, Src, P).
 1560process_dcg_goal({Goal}, Origin, Src, P) :-
 1561    !,
 1562    process_goal(Goal, Origin, Src, P).
 1563process_dcg_goal(List, _Origin, _Src, _) :-
 1564    is_list(List),
 1565    !.               % terminal
 1566process_dcg_goal(List, _Origin, _Src, _) :-
 1567    string(List),
 1568    !.                % terminal
 1569process_dcg_goal(Callable, Origin, Src, P) :-
 1570    extend(Callable, 2, Goal),
 1571    !,
 1572    process_goal(Goal, Origin, Src, P).
 1573process_dcg_goal(_, _, _, _).
 1574
 1575
 1576extend(Var, _, _) :-
 1577    var(Var), !, fail.
 1578extend(M:G, N, M:GX) :-
 1579    !,
 1580    callable(G),
 1581    extend(G, N, GX).
 1582extend(G, N, GX) :-
 1583    (   compound(G)
 1584    ->  compound_name_arguments(G, Name, Args),
 1585        length(Rest, N),
 1586        append(Args, Rest, NArgs),
 1587        compound_name_arguments(GX, Name, NArgs)
 1588    ;   atom(G)
 1589    ->  length(NArgs, N),
 1590        compound_name_arguments(GX, G, NArgs)
 1591    ).
 1592
 1593asserting_goal(assert(Rule), Rule).
 1594asserting_goal(asserta(Rule), Rule).
 1595asserting_goal(assertz(Rule), Rule).
 1596asserting_goal(assert(Rule,_), Rule).
 1597asserting_goal(asserta(Rule,_), Rule).
 1598asserting_goal(assertz(Rule,_), Rule).
 1599
 1600process_assert(0, _, _) :- !.           % catch variables
 1601process_assert((_:-Body), Origin, Src) :-
 1602    !,
 1603    process_body(Body, Origin, Src).
 1604process_assert(_, _, _).
 variants(+SortedList, +Max, -Variants) is det
 1608variants([], _, []).
 1609variants([H|T], Max, List) :-
 1610    variants(T, H, Max, List).
 1611
 1612variants([], H, _, [H]).
 1613variants(_, _, 0, []) :- !.
 1614variants([H|T], V, Max, List) :-
 1615    (   H =@= V
 1616    ->  variants(T, V, Max, List)
 1617    ;   List = [V|List2],
 1618        Max1 is Max-1,
 1619        variants(T, H, Max1, List2)
 1620    ).
 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?
 1634partial_evaluate(Goal, P) :-
 1635    eval(Goal),
 1636    !,
 1637    P = true.
 1638partial_evaluate(_, _).
 1639
 1640eval(X = Y) :-
 1641    unify_with_occurs_check(X, Y).
 1642
 1643
 1644                 /*******************************
 1645                 *          XPCE STUFF          *
 1646                 *******************************/
 1647
 1648pce_goal(new(_,_), new(-, new)).
 1649pce_goal(send(_,_), send(arg, msg)).
 1650pce_goal(send_class(_,_,_), send_class(arg, arg, msg)).
 1651pce_goal(get(_,_,_), get(arg, msg, -)).
 1652pce_goal(get_class(_,_,_,_), get_class(arg, arg, msg, -)).
 1653pce_goal(get_chain(_,_,_), get_chain(arg, msg, -)).
 1654pce_goal(get_object(_,_,_), get_object(arg, msg, -)).
 1655
 1656process_xpce_goal(G, Origin, Src) :-
 1657    pce_goal(G, Process),
 1658    !,
 1659    current_source_line(Here),
 1660    assert_called(Src, Origin, G, Here),
 1661    (   arg(I, Process, How),
 1662        arg(I, G, Term),
 1663        process_xpce_arg(How, Term, Origin, Src),
 1664        fail
 1665    ;   true
 1666    ).
 1667
 1668process_xpce_arg(new, Term, Origin, Src) :-
 1669    callable(Term),
 1670    process_new(Term, Origin, Src).
 1671process_xpce_arg(arg, Term, Origin, Src) :-
 1672    compound(Term),
 1673    process_new(Term, Origin, Src).
 1674process_xpce_arg(msg, Term, Origin, Src) :-
 1675    compound(Term),
 1676    (   arg(_, Term, Arg),
 1677        process_xpce_arg(arg, Arg, Origin, Src),
 1678        fail
 1679    ;   true
 1680    ).
 1681
 1682process_new(_M:_Term, _, _) :- !.       % TBD: Calls on other modules!
 1683process_new(Term, Origin, Src) :-
 1684    assert_new(Src, Origin, Term),
 1685    (   compound(Term),
 1686        arg(_, Term, Arg),
 1687        process_xpce_arg(arg, Arg, Origin, Src),
 1688        fail
 1689    ;   true
 1690    ).
 1691
 1692assert_new(_, _, Term) :-
 1693    \+ callable(Term),
 1694    !.
 1695assert_new(Src, Origin, Control) :-
 1696    functor_name(Control, Class),
 1697    pce_control_class(Class),
 1698    !,
 1699    forall(arg(_, Control, Arg),
 1700           assert_new(Src, Origin, Arg)).
 1701assert_new(Src, Origin, Term) :-
 1702    compound(Term),
 1703    arg(1, Term, Prolog),
 1704    Prolog == @(prolog),
 1705    (   Term =.. [message, _, Selector | T],
 1706        atom(Selector)
 1707    ->  Called =.. [Selector|T],
 1708        process_body(Called, Origin, Src)
 1709    ;   Term =.. [?, _, Selector | T],
 1710        atom(Selector)
 1711    ->  append(T, [_R], T2),
 1712        Called =.. [Selector|T2],
 1713        process_body(Called, Origin, Src)
 1714    ),
 1715    fail.
 1716assert_new(_, _, @(_)) :- !.
 1717assert_new(Src, _, Term) :-
 1718    functor_name(Term, Name),
 1719    assert_used_class(Src, Name).
 1720
 1721
 1722pce_control_class(and).
 1723pce_control_class(or).
 1724pce_control_class(if).
 1725pce_control_class(not).
 1726
 1727
 1728                /********************************
 1729                *       INCLUDED MODULES        *
 1730                ********************************/
 process_use_module(+Modules, +Src, +Rexport) is det
 1734process_use_module(_Module:_Files, _, _) :- !.  % loaded in another module
 1735process_use_module([], _, _) :- !.
 1736process_use_module([H|T], Src, Reexport) :-
 1737    !,
 1738    process_use_module(H, Src, Reexport),
 1739    process_use_module(T, Src, Reexport).
 1740process_use_module(library(pce), Src, Reexport) :-     % bit special
 1741    !,
 1742    xref_public_list(library(pce), Path, Exports, Src),
 1743    forall(member(Import, Exports),
 1744           process_pce_import(Import, Src, Path, Reexport)).
 1745process_use_module(File, Src, Reexport) :-
 1746    (   xoption(Src, silent(Silent))
 1747    ->  Extra = [silent(Silent)]
 1748    ;   Extra = [silent(true)]
 1749    ),
 1750    (   xref_public_list(File, Src,
 1751                         [ path(Path),
 1752                           module(M),
 1753                           exports(Exports),
 1754                           public(Public),
 1755                           meta(Meta)
 1756                         | Extra
 1757                         ])
 1758    ->  assert(uses_file(File, Src, Path)),
 1759        assert_import(Src, Exports, _, Path, Reexport),
 1760        assert_xmodule_callable(Exports, M, Src, Path),
 1761        assert_xmodule_callable(Public, M, Src, Path),
 1762        maplist(process_meta_head(Src), Meta),
 1763        (   File = library(chr)     % hacky
 1764        ->  assert(mode(chr, Src))
 1765        ;   true
 1766        )
 1767    ;   assert(uses_file(File, Src, '<not_found>'))
 1768    ).
 1769
 1770process_pce_import(Name/Arity, Src, Path, Reexport) :-
 1771    atom(Name),
 1772    integer(Arity),
 1773    !,
 1774    functor(Term, Name, Arity),
 1775    (   \+ system_predicate(Term),
 1776        \+ Term = pce_error(_)      % hack!?
 1777    ->  assert_import(Src, [Name/Arity], _, Path, Reexport)
 1778    ;   true
 1779    ).
 1780process_pce_import(op(P,T,N), Src, _, _) :-
 1781    xref_push_op(Src, P, T, N).
 process_use_module2(+File, +Import, +Src, +Reexport) is det
Process use_module/2 and reexport/2.
 1787process_use_module2(File, Import, Src, Reexport) :-
 1788    (   xref_source_file(File, Path, Src)
 1789    ->  assert(uses_file(File, Src, Path)),
 1790        (   catch(public_list(Path, _, Meta, Export, _Public, []), _, fail)
 1791        ->  assert_import(Src, Import, Export, Path, Reexport),
 1792            forall((  member(Head, Meta),
 1793                      imported(Head, _, Path)
 1794                   ),
 1795                   process_meta_head(Src, Head))
 1796        ;   true
 1797        )
 1798    ;   assert(uses_file(File, Src, '<not_found>'))
 1799    ).
 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.
 1830xref_public_list(File, Src, Options) :-
 1831    option(path(Path), Options, _),
 1832    option(module(Module), Options, _),
 1833    option(exports(Exports), Options, _),
 1834    option(public(Public), Options, _),
 1835    option(meta(Meta), Options, _),
 1836    xref_source_file(File, Path, Src, Options),
 1837    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.
 1859xref_public_list(File, Path, Export, Src) :-
 1860    xref_source_file(File, Path, Src),
 1861    public_list(Path, _, _, Export, _, []).
 1862xref_public_list(File, Path, Module, Export, Meta, Src) :-
 1863    xref_source_file(File, Path, Src),
 1864    public_list(Path, Module, Meta, Export, _, []).
 1865xref_public_list(File, Path, Module, Export, Public, Meta, Src) :-
 1866    xref_source_file(File, Path, Src),
 1867    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.
 1877:- dynamic  public_list_cache/6. 1878:- volatile public_list_cache/6. 1879
 1880public_list(Path, Module, Meta, Export, Public, _Options) :-
 1881    public_list_cache(Path, Modified,
 1882                      Module0, Meta0, Export0, Public0),
 1883    time_file(Path, ModifiedNow),
 1884    (   abs(Modified-ModifiedNow) < 0.0001
 1885    ->  !,
 1886        t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0)
 1887    ;   retractall(public_list_cache(Path, _, _, _, _, _)),
 1888        fail
 1889    ).
 1890public_list(Path, Module, Meta, Export, Public, Options) :-
 1891    public_list_nc(Path, Module0, Meta0, Export0, Public0, Options),
 1892    (   Error = error(_,_),
 1893        catch(time_file(Path, Modified), Error, fail)
 1894    ->  asserta(public_list_cache(Path, Modified,
 1895                                  Module0, Meta0, Export0, Public0))
 1896    ;   true
 1897    ),
 1898    t(Module,Meta,Export,Public) = t(Module0,Meta0,Export0,Public0).
 1899
 1900public_list_nc(Path, Module, Meta, Export, Public, Options) :-
 1901    in_temporary_module(
 1902        TempModule,
 1903        true,
 1904        public_list_diff(TempModule, Path, Module,
 1905                         Meta, [], Export, [], Public, [], Options)).
 1906
 1907
 1908public_list_diff(TempModule,
 1909                 Path, Module, Meta, MT, Export, Rest, Public, PT, Options) :-
 1910    setup_call_cleanup(
 1911        public_list_setup(TempModule, Path, In, State),
 1912        phrase(read_directives(In, Options, [true]), Directives),
 1913        public_list_cleanup(In, State)),
 1914    public_list(Directives, Path, Module, Meta, MT, Export, Rest, Public, PT).
 1915
 1916public_list_setup(TempModule, Path, In, state(OldM, OldXref)) :-
 1917    prolog_open_source(Path, In),
 1918    '$set_source_module'(OldM, TempModule),
 1919    set_xref(OldXref).
 1920
 1921public_list_cleanup(In, state(OldM, OldXref)) :-
 1922    '$set_source_module'(OldM),
 1923    set_prolog_flag(xref, OldXref),
 1924    prolog_close_source(In).
 1925
 1926
 1927read_directives(In, Options, State) -->
 1928    {  repeat,
 1929       catch(prolog_read_source_term(In, Term, Expanded,
 1930                                     [ process_comment(true),
 1931                                       syntax_errors(error)
 1932                                     ]),
 1933             E, report_syntax_error(E, -, Options))
 1934    -> nonvar(Term),
 1935       Term = (:-_)
 1936    },
 1937    !,
 1938    terms(Expanded, State, State1),
 1939    read_directives(In, Options, State1).
 1940read_directives(_, _, _) --> [].
 1941
 1942terms(Var, State, State) --> { var(Var) }, !.
 1943terms([H|T], State0, State) -->
 1944    !,
 1945    terms(H, State0, State1),
 1946    terms(T, State1, State).
 1947terms((:-if(Cond)), State0, [True|State0]) -->
 1948    !,
 1949    { eval_cond(Cond, True) }.
 1950terms((:-elif(Cond)), [True0|State], [True|State]) -->
 1951    !,
 1952    { eval_cond(Cond, True1),
 1953      elif(True0, True1, True)
 1954    }.
 1955terms((:-else), [True0|State], [True|State]) -->
 1956    !,
 1957    { negate(True0, True) }.
 1958terms((:-endif), [_|State], State) -->  !.
 1959terms(H, State, State) -->
 1960    (   {State = [true|_]}
 1961    ->  [H]
 1962    ;   []
 1963    ).
 1964
 1965eval_cond(Cond, true) :-
 1966    catch(Cond, _, fail),
 1967    !.
 1968eval_cond(_, false).
 1969
 1970elif(true,  _,    else_false) :- !.
 1971elif(false, true, true) :- !.
 1972elif(True,  _,    True).
 1973
 1974negate(true,       false).
 1975negate(false,      true).
 1976negate(else_false, else_false).
 1977
 1978public_list([(:- module(Module, Export0))|Decls], Path,
 1979            Module, Meta, MT, Export, Rest, Public, PT) :-
 1980    !,
 1981    append(Export0, Reexport, Export),
 1982    public_list_(Decls, Path, Meta, MT, Reexport, Rest, Public, PT).
 1983public_list([(:- encoding(_))|Decls], Path,
 1984            Module, Meta, MT, Export, Rest, Public, PT) :-
 1985    public_list(Decls, Path, Module, Meta, MT, Export, Rest, Public, PT).
 1986
 1987public_list_([], _, Meta, Meta, Export, Export, Public, Public).
 1988public_list_([(:-(Dir))|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 1989    public_list_1(Dir, Path, Meta, MT0, Export, Rest0, Public, PT0),
 1990    !,
 1991    public_list_(T, Path, MT0, MT, Rest0, Rest, PT0, PT).
 1992public_list_([_|T], Path, Meta, MT, Export, Rest, Public, PT) :-
 1993    public_list_(T, Path, Meta, MT, Export, Rest, Public, PT).
 1994
 1995public_list_1(reexport(Spec), Path, Meta, MT, Reexport, Rest, Public, PT) :-
 1996    reexport_files(Spec, Path, Meta, MT, Reexport, Rest, Public, PT).
 1997public_list_1(reexport(Spec, Import), Path, Meta, Meta, Reexport, Rest, Public, Public) :-
 1998    public_from_import(Import, Spec, Path, Reexport, Rest).
 1999public_list_1(meta_predicate(Decl), _Path, Meta, MT, Export, Export, Public, Public) :-
 2000    phrase(meta_decls(Decl), Meta, MT).
 2001public_list_1(public(Decl), _Path, Meta, Meta, Export, Export, Public, PT) :-
 2002    phrase(public_decls(Decl), Public, PT).
 reexport_files(+Files, +Src, -Meta, ?MetaTail, -Exports, ?ExportsTail, -Public, ?PublicTail)
 2008reexport_files([], _, Meta, Meta, Export, Export, Public, Public) :- !.
 2009reexport_files([H|T], Src, Meta, MT, Export, ET, Public, PT) :-
 2010    !,
 2011    xref_source_file(H, Path, Src),
 2012    public_list(Path, _Module, Meta0, Export0, Public0, []),
 2013    append(Meta0, MT1, Meta),
 2014    append(Export0, ET1, Export),
 2015    append(Public0, PT1, Public),
 2016    reexport_files(T, Src, MT1, MT, ET1, ET, PT1, PT).
 2017reexport_files(Spec, Src, Meta, MT, Export, ET, Public, PT) :-
 2018    xref_source_file(Spec, Path, Src),
 2019    public_list(Path, _Module, Meta0, Export0, Public0, []),
 2020    append(Meta0, MT, Meta),
 2021    append(Export0, ET, Export),
 2022    append(Public0, PT, Public).
 2023
 2024public_from_import(except(Map), Path, Src, Export, Rest) :-
 2025    !,
 2026    xref_public_list(Path, _, AllExports, Src),
 2027    except(Map, AllExports, NewExports),
 2028    append(NewExports, Rest, Export).
 2029public_from_import(Import, _, _, Export, Rest) :-
 2030    import_name_map(Import, Export, Rest).
 except(+Remove, +AllExports, -Exports)
 2035except([], Exports, Exports).
 2036except([PI0 as NewName|Map], Exports0, Exports) :-
 2037    !,
 2038    canonical_pi(PI0, PI),
 2039    map_as(Exports0, PI, NewName, Exports1),
 2040    except(Map, Exports1, Exports).
 2041except([PI0|Map], Exports0, Exports) :-
 2042    canonical_pi(PI0, PI),
 2043    select(PI2, Exports0, Exports1),
 2044    same_pi(PI, PI2),
 2045    !,
 2046    except(Map, Exports1, Exports).
 2047
 2048
 2049map_as([PI|T], Repl, As, [PI2|T])  :-
 2050    same_pi(Repl, PI),
 2051    !,
 2052    pi_as(PI, As, PI2).
 2053map_as([H|T0], Repl, As, [H|T])  :-
 2054    map_as(T0, Repl, As, T).
 2055
 2056pi_as(_/Arity, Name, Name/Arity).
 2057pi_as(_//Arity, Name, Name//Arity).
 2058
 2059import_name_map([], L, L).
 2060import_name_map([_/Arity as NewName|T0], [NewName/Arity|T], Tail) :-
 2061    !,
 2062    import_name_map(T0, T, Tail).
 2063import_name_map([_//Arity as NewName|T0], [NewName//Arity|T], Tail) :-
 2064    !,
 2065    import_name_map(T0, T, Tail).
 2066import_name_map([H|T0], [H|T], Tail) :-
 2067    import_name_map(T0, T, Tail).
 2068
 2069canonical_pi(Name//Arity0, PI) :-
 2070    integer(Arity0),
 2071    !,
 2072    PI = Name/Arity,
 2073    Arity is Arity0 + 2.
 2074canonical_pi(PI, PI).
 2075
 2076same_pi(Canonical, PI2) :-
 2077    canonical_pi(PI2, Canonical).
 2078
 2079meta_decls(Var) -->
 2080    { var(Var) },
 2081    !.
 2082meta_decls((A,B)) -->
 2083    !,
 2084    meta_decls(A),
 2085    meta_decls(B).
 2086meta_decls(A) -->
 2087    [A].
 2088
 2089public_decls(Var) -->
 2090    { var(Var) },
 2091    !.
 2092public_decls((A,B)) -->
 2093    !,
 2094    public_decls(A),
 2095    public_decls(B).
 2096public_decls(A) -->
 2097    [A].
 2098
 2099                 /*******************************
 2100                 *             INCLUDE          *
 2101                 *******************************/
 2102
 2103process_include([], _) :- !.
 2104process_include([H|T], Src) :-
 2105    !,
 2106    process_include(H, Src),
 2107    process_include(T, Src).
 2108process_include(File, Src) :-
 2109    callable(File),
 2110    !,
 2111    (   once(xref_input(ParentSrc, _)),
 2112        xref_source_file(File, Path, ParentSrc)
 2113    ->  (   (   uses_file(_, Src, Path)
 2114            ;   Path == Src
 2115            )
 2116        ->  true
 2117        ;   assert(uses_file(File, Src, Path)),
 2118            (   xoption(Src, process_include(true))
 2119            ->  findall(O, xoption(Src, O), Options),
 2120                setup_call_cleanup(
 2121                    open_include_file(Path, In, Refs),
 2122                    collect(Src, Path, In, Options),
 2123                    close_include(In, Refs))
 2124            ;   true
 2125            )
 2126        )
 2127    ;   assert(uses_file(File, Src, '<not_found>'))
 2128    ).
 2129process_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.
 2137open_include_file(Path, In, [Ref]) :-
 2138    once(xref_input(_, Parent)),
 2139    stream_property(Parent, encoding(Enc)),
 2140    '$push_input_context'(xref_include),
 2141    catch((   prolog:xref_open_source(Path, In)
 2142          ->  set_stream(In, encoding(Enc))
 2143          ;   include_encoding(Enc, Options),
 2144              open(Path, read, In, Options)
 2145          ), E,
 2146          ( '$pop_input_context', throw(E))),
 2147    catch((   peek_char(In, #)              % Deal with #! script
 2148          ->  skip(In, 10)
 2149          ;   true
 2150          ), E,
 2151          ( close_include(In, []), throw(E))),
 2152    asserta(xref_input(Path, In), Ref).
 2153
 2154include_encoding(wchar_t, []) :- !.
 2155include_encoding(Enc, [encoding(Enc)]).
 2156
 2157
 2158close_include(In, Refs) :-
 2159    maplist(erase, Refs),
 2160    close(In, [force(true)]),
 2161    '$pop_input_context'.
 process_foreign(+Spec, +Src)
Process a load_foreign_library/1 call.
 2167process_foreign(Spec, Src) :-
 2168    ground(Spec),
 2169    current_foreign_library(Spec, Defined),
 2170    !,
 2171    (   xmodule(Module, Src)
 2172    ->  true
 2173    ;   Module = user
 2174    ),
 2175    process_foreign_defined(Defined, Module, Src).
 2176process_foreign(_, _).
 2177
 2178process_foreign_defined([], _, _).
 2179process_foreign_defined([H|T], M, Src) :-
 2180    (   H = M:Head
 2181    ->  assert_foreign(Src, Head)
 2182    ;   assert_foreign(Src, H)
 2183    ),
 2184    process_foreign_defined(T, M, Src).
 2185
 2186
 2187                 /*******************************
 2188                 *          CHR SUPPORT         *
 2189                 *******************************/
 2190
 2191/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2192This part of the file supports CHR. Our choice is between making special
 2193hooks to make CHR expansion work and  then handle the (complex) expanded
 2194code or process the  CHR  source   directly.  The  latter looks simpler,
 2195though I don't like the idea  of   adding  support for libraries to this
 2196module.  A  file  is  supposed  to  be  a    CHR   file  if  it  uses  a
 2197use_module(library(chr) or contains a :-   constraint/1 directive. As an
 2198extra bonus we get the source-locations right :-)
 2199- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2200
 2201process_chr(@(_Name, Rule), Src) :-
 2202    mode(chr, Src),
 2203    process_chr(Rule, Src).
 2204process_chr(pragma(Rule, _Pragma), Src) :-
 2205    mode(chr, Src),
 2206    process_chr(Rule, Src).
 2207process_chr(<=>(Head, Body), Src) :-
 2208    mode(chr, Src),
 2209    chr_head(Head, Src, H),
 2210    chr_body(Body, H, Src).
 2211process_chr(==>(Head, Body), Src) :-
 2212    mode(chr, Src),
 2213    chr_head(Head, H, Src),
 2214    chr_body(Body, H, Src).
 2215process_chr((:- chr_constraint(_)), Src) :-
 2216    (   mode(chr, Src)
 2217    ->  true
 2218    ;   assert(mode(chr, Src))
 2219    ).
 2220
 2221chr_head(X, _, _) :-
 2222    var(X),
 2223    !.                      % Illegal.  Warn?
 2224chr_head(\(A,B), Src, H) :-
 2225    chr_head(A, Src, H),
 2226    process_body(B, H, Src).
 2227chr_head((H0,B), Src, H) :-
 2228    chr_defined(H0, Src, H),
 2229    process_body(B, H, Src).
 2230chr_head(H0, Src, H) :-
 2231    chr_defined(H0, Src, H).
 2232
 2233chr_defined(X, _, _) :-
 2234    var(X),
 2235    !.
 2236chr_defined(#(C,_Id), Src, C) :-
 2237    !,
 2238    assert_constraint(Src, C).
 2239chr_defined(A, Src, A) :-
 2240    assert_constraint(Src, A).
 2241
 2242chr_body(X, From, Src) :-
 2243    var(X),
 2244    !,
 2245    process_body(X, From, Src).
 2246chr_body('|'(Guard, Goals), H, Src) :-
 2247    !,
 2248    chr_body(Guard, H, Src),
 2249    chr_body(Goals, H, Src).
 2250chr_body(G, From, Src) :-
 2251    process_body(G, From, Src).
 2252
 2253assert_constraint(_, Head) :-
 2254    var(Head),
 2255    !.
 2256assert_constraint(Src, Head) :-
 2257    constraint(Head, Src, _),
 2258    !.
 2259assert_constraint(Src, Head) :-
 2260    generalise_term(Head, Term),
 2261    current_source_line(Line),
 2262    assert(constraint(Term, Src, Line)).
 2263
 2264
 2265                /********************************
 2266                *       PHASE 1 ASSERTIONS      *
 2267                ********************************/
 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.
 2274assert_called(_, _, Var, _) :-
 2275    var(Var),
 2276    !.
 2277assert_called(Src, From, Goal, Line) :-
 2278    var(From),
 2279    !,
 2280    assert_called(Src, '<unknown>', Goal, Line).
 2281assert_called(_, _, Goal, _) :-
 2282    expand_hide_called(Goal),
 2283    !.
 2284assert_called(Src, Origin, M:G, Line) :-
 2285    !,
 2286    (   atom(M),
 2287        callable(G)
 2288    ->  current_condition(Cond),
 2289        (   xmodule(M, Src)         % explicit call to own module
 2290        ->  assert_called(Src, Origin, G, Line)
 2291        ;   called(M:G, Src, Origin, Cond, Line) % already registered
 2292        ->  true
 2293        ;   hide_called(M:G, Src)           % not interesting (now)
 2294        ->  true
 2295        ;   generalise(Origin, OTerm),
 2296            generalise(G, GTerm)
 2297        ->  assert(called(M:GTerm, Src, OTerm, Cond, Line))
 2298        ;   true
 2299        )
 2300    ;   true                        % call to variable module
 2301    ).
 2302assert_called(Src, _, Goal, _) :-
 2303    (   xmodule(M, Src)
 2304    ->  M \== system
 2305    ;   M = user
 2306    ),
 2307    hide_called(M:Goal, Src),
 2308    !.
 2309assert_called(Src, Origin, Goal, Line) :-
 2310    current_condition(Cond),
 2311    (   called(Goal, Src, Origin, Cond, Line)
 2312    ->  true
 2313    ;   generalise(Origin, OTerm),
 2314        generalise(Goal, Term)
 2315    ->  assert(called(Term, Src, OTerm, Cond, Line))
 2316    ;   true
 2317    ).
 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.
 2325expand_hide_called(pce_principal:send_implementation(_, _, _)).
 2326expand_hide_called(pce_principal:get_implementation(_, _, _, _)).
 2327expand_hide_called(pce_principal:pce_lazy_get_method(_,_,_)).
 2328expand_hide_called(pce_principal:pce_lazy_send_method(_,_,_)).
 2329
 2330assert_defined(Src, Goal) :-
 2331    defined(Goal, Src, _),
 2332    !.
 2333assert_defined(Src, Goal) :-
 2334    generalise(Goal, Term),
 2335    current_source_line(Line),
 2336    assert(defined(Term, Src, Line)).
 2337
 2338assert_foreign(Src, Goal) :-
 2339    foreign(Goal, Src, _),
 2340    !.
 2341assert_foreign(Src, Goal) :-
 2342    generalise(Goal, Term),
 2343    current_source_line(Line),
 2344    assert(foreign(Term, Src, Line)).
 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.
 2356assert_import(_, [], _, _, _) :- !.
 2357assert_import(Src, [H|T], Export, From, Reexport) :-
 2358    !,
 2359    assert_import(Src, H, Export, From, Reexport),
 2360    assert_import(Src, T, Export, From, Reexport).
 2361assert_import(Src, except(Except), Export, From, Reexport) :-
 2362    !,
 2363    is_list(Export),
 2364    !,
 2365    except(Except, Export, Import),
 2366    assert_import(Src, Import, _All, From, Reexport).
 2367assert_import(Src, Import as Name, Export, From, Reexport) :-
 2368    !,
 2369    pi_to_head(Import, Term0),
 2370    rename_goal(Term0, Name, Term),
 2371    (   in_export_list(Term0, Export)
 2372    ->  assert(imported(Term, Src, From)),
 2373        assert_reexport(Reexport, Src, Term)
 2374    ;   current_source_line(Line),
 2375        assert_called(Src, '<directive>'(Line), Term0, Line)
 2376    ).
 2377assert_import(Src, Import, Export, From, Reexport) :-
 2378    pi_to_head(Import, Term),
 2379    !,
 2380    (   in_export_list(Term, Export)
 2381    ->  assert(imported(Term, Src, From)),
 2382        assert_reexport(Reexport, Src, Term)
 2383    ;   current_source_line(Line),
 2384        assert_called(Src, '<directive>'(Line), Term, Line)
 2385    ).
 2386assert_import(Src, op(P,T,N), _, _, _) :-
 2387    xref_push_op(Src, P,T,N).
 2388
 2389in_export_list(_Head, Export) :-
 2390    var(Export),
 2391    !.
 2392in_export_list(Head, Export) :-
 2393    member(PI, Export),
 2394    pi_to_head(PI, Head).
 2395
 2396assert_reexport(false, _, _) :- !.
 2397assert_reexport(true, Src, Term) :-
 2398    assert(exported(Term, Src)).
 process_import(:Import, +Src)
Process an import/1 directive
 2404process_import(M:PI, Src) :-
 2405    pi_to_head(PI, Head),
 2406    !,
 2407    (   atom(M),
 2408        current_module(M),
 2409        module_property(M, file(From))
 2410    ->  true
 2411    ;   From = '<unknown>'
 2412    ),
 2413    assert(imported(Head, Src, From)).
 2414process_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?
 2423assert_xmodule_callable([], _, _, _).
 2424assert_xmodule_callable([PI|T], M, Src, From) :-
 2425    (   pi_to_head(M:PI, Head)
 2426    ->  assert(imported(Head, Src, From))
 2427    ;   true
 2428    ),
 2429    assert_xmodule_callable(T, M, Src, From).
 assert_op(+Src, +Op) is det
Arguments:
Op- Ground term op(Priority, Type, Name).
 2436assert_op(Src, op(P,T,M:N)) :-
 2437    (   '$current_source_module'(M)
 2438    ->  Name = N
 2439    ;   Name = M:N
 2440    ),
 2441    (   xop(Src, op(P,T,Name))
 2442    ->  true
 2443    ;   assert(xop(Src, op(P,T,Name)))
 2444    ).
 assert_module(+Src, +Module)
Assert we are loading code into Module. This is also used to exploit local term-expansion and other rules.
 2451assert_module(Src, Module) :-
 2452    xmodule(Module, Src),
 2453    !.
 2454assert_module(Src, Module) :-
 2455    '$set_source_module'(Module),
 2456    assert(xmodule(Module, Src)),
 2457    (   module_property(Module, class(system))
 2458    ->  retractall(xoption(Src, register_called(_))),
 2459        assert(xoption(Src, register_called(all)))
 2460    ;   true
 2461    ).
 2462
 2463assert_module_export(_, []) :- !.
 2464assert_module_export(Src, [H|T]) :-
 2465    !,
 2466    assert_module_export(Src, H),
 2467    assert_module_export(Src, T).
 2468assert_module_export(Src, PI) :-
 2469    pi_to_head(PI, Term),
 2470    !,
 2471    assert(exported(Term, Src)).
 2472assert_module_export(Src, op(P, A, N)) :-
 2473    xref_push_op(Src, P, A, N).
 assert_module3(+Import, +Src)
Handle 3th argument of module/3 declaration.
 2479assert_module3([], _) :- !.
 2480assert_module3([H|T], Src) :-
 2481    !,
 2482    assert_module3(H, Src),
 2483    assert_module3(T, Src).
 2484assert_module3(Option, Src) :-
 2485    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.
 2494process_predicates(Closure, Preds, Src) :-
 2495    is_list(Preds),
 2496    !,
 2497    process_predicate_list(Preds, Closure, Src).
 2498process_predicates(Closure, Preds, Src) :-
 2499    process_predicate_comma(Preds, Closure, Src).
 2500
 2501process_predicate_list([], _, _).
 2502process_predicate_list([H|T], Closure, Src) :-
 2503    (   nonvar(H)
 2504    ->  call(Closure, H, Src)
 2505    ;   true
 2506    ),
 2507    process_predicate_list(T, Closure, Src).
 2508
 2509process_predicate_comma(Var, _, _) :-
 2510    var(Var),
 2511    !.
 2512process_predicate_comma(M:(A,B), Closure, Src) :-
 2513    !,
 2514    process_predicate_comma(M:A, Closure, Src),
 2515    process_predicate_comma(M:B, Closure, Src).
 2516process_predicate_comma((A,B), Closure, Src) :-
 2517    !,
 2518    process_predicate_comma(A, Closure, Src),
 2519    process_predicate_comma(B, Closure, Src).
 2520process_predicate_comma(A, Closure, Src) :-
 2521    call(Closure, A, Src).
 2522
 2523
 2524assert_dynamic(PI, Src) :-
 2525    pi_to_head(PI, Term),
 2526    (   thread_local(Term, Src, _)  % dynamic after thread_local has
 2527    ->  true                        % no effect
 2528    ;   current_source_line(Line),
 2529        assert(dynamic(Term, Src, Line))
 2530    ).
 2531
 2532assert_thread_local(PI, Src) :-
 2533    pi_to_head(PI, Term),
 2534    current_source_line(Line),
 2535    assert(thread_local(Term, Src, Line)).
 2536
 2537assert_multifile(PI, Src) :-                    % :- multifile(Spec)
 2538    pi_to_head(PI, Term),
 2539    current_source_line(Line),
 2540    assert(multifile(Term, Src, Line)).
 2541
 2542assert_public(PI, Src) :-                       % :- public(Spec)
 2543    pi_to_head(PI, Term),
 2544    current_source_line(Line),
 2545    assert_called(Src, '<public>'(Line), Term, Line),
 2546    assert(public(Term, Src, Line)).
 2547
 2548assert_export(PI, Src) :-                       % :- export(Spec)
 2549    pi_to_head(PI, Term),
 2550    !,
 2551    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.
 2558pi_to_head(Var, _) :-
 2559    var(Var), !, fail.
 2560pi_to_head(M:PI, M:Term) :-
 2561    !,
 2562    pi_to_head(PI, Term).
 2563pi_to_head(Name/Arity, Term) :-
 2564    functor(Term, Name, Arity).
 2565pi_to_head(Name//DCGArity, Term) :-
 2566    Arity is DCGArity+2,
 2567    functor(Term, Name, Arity).
 2568
 2569
 2570assert_used_class(Src, Name) :-
 2571    used_class(Name, Src),
 2572    !.
 2573assert_used_class(Src, Name) :-
 2574    assert(used_class(Name, Src)).
 2575
 2576assert_defined_class(Src, Name, _Meta, _Super, _) :-
 2577    defined_class(Name, _, _, Src, _),
 2578    !.
 2579assert_defined_class(_, _, _, -, _) :- !.               % :- pce_extend_class
 2580assert_defined_class(Src, Name, Meta, Super, Summary) :-
 2581    current_source_line(Line),
 2582    (   Summary == @(default)
 2583    ->  Atom = ''
 2584    ;   is_list(Summary)
 2585    ->  atom_codes(Atom, Summary)
 2586    ;   string(Summary)
 2587    ->  atom_concat(Summary, '', Atom)
 2588    ),
 2589    assert(defined_class(Name, Super, Atom, Src, Line)),
 2590    (   Meta = @(_)
 2591    ->  true
 2592    ;   assert_used_class(Src, Meta)
 2593    ),
 2594    assert_used_class(Src, Super).
 2595
 2596assert_defined_class(Src, Name, imported_from(_File)) :-
 2597    defined_class(Name, _, _, Src, _),
 2598    !.
 2599assert_defined_class(Src, Name, imported_from(File)) :-
 2600    assert(defined_class(Name, _, '', Src, file(File))).
 2601
 2602
 2603                /********************************
 2604                *            UTILITIES          *
 2605                ********************************/
 generalise(+Callable, -General)
Generalise a callable term.
 2611generalise(Var, Var) :-
 2612    var(Var),
 2613    !.                    % error?
 2614generalise(pce_principal:send_implementation(Id, _, _),
 2615           pce_principal:send_implementation(Id, _, _)) :-
 2616    atom(Id),
 2617    !.
 2618generalise(pce_principal:get_implementation(Id, _, _, _),
 2619           pce_principal:get_implementation(Id, _, _, _)) :-
 2620    atom(Id),
 2621    !.
 2622generalise('<directive>'(Line), '<directive>'(Line)) :- !.
 2623generalise(Module:Goal0, Module:Goal) :-
 2624    atom(Module),
 2625    !,
 2626    generalise(Goal0, Goal).
 2627generalise(Term0, Term) :-
 2628    callable(Term0),
 2629    generalise_term(Term0, Term).
 2630
 2631
 2632                 /*******************************
 2633                 *      SOURCE MANAGEMENT       *
 2634                 *******************************/
 2635
 2636/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 2637This section of the file contains   hookable  predicates to reason about
 2638sources. The built-in code here  can  only   deal  with  files. The XPCE
 2639library(pce_prolog_xref) provides hooks to deal with XPCE objects, so we
 2640can do cross-referencing on PceEmacs edit   buffers.  Other examples for
 2641hooking can be databases, (HTTP) URIs, etc.
 2642- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 2643
 2644:- multifile
 2645    prolog:xref_source_directory/2, % +Source, -Dir
 2646    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.
 2654xref_source_file(Plain, File, Source) :-
 2655    xref_source_file(Plain, File, Source, []).
 2656
 2657xref_source_file(QSpec, File, Source, Options) :-
 2658    nonvar(QSpec), QSpec = _:Spec,
 2659    !,
 2660    must_be(acyclic, Spec),
 2661    xref_source_file(Spec, File, Source, Options).
 2662xref_source_file(Spec, File, Source, Options) :-
 2663    nonvar(Spec),
 2664    prolog:xref_source_file(Spec, File,
 2665                            [ relative_to(Source)
 2666                            | Options
 2667                            ]),
 2668    !.
 2669xref_source_file(Plain, File, Source, Options) :-
 2670    atom(Plain),
 2671    \+ is_absolute_file_name(Plain),
 2672    (   prolog:xref_source_directory(Source, Dir)
 2673    ->  true
 2674    ;   atom(Source),
 2675        file_directory_name(Source, Dir)
 2676    ),
 2677    atomic_list_concat([Dir, /, Plain], Spec0),
 2678    absolute_file_name(Spec0, Spec),
 2679    do_xref_source_file(Spec, File, Options),
 2680    !.
 2681xref_source_file(Spec, File, Source, Options) :-
 2682    do_xref_source_file(Spec, File,
 2683                        [ relative_to(Source)
 2684                        | Options
 2685                        ]),
 2686    !.
 2687xref_source_file(_, _, _, Options) :-
 2688    option(silent(true), Options),
 2689    !,
 2690    fail.
 2691xref_source_file(Spec, _, Src, _Options) :-
 2692    verbose(Src),
 2693    print_message(warning, error(existence_error(file, Spec), _)),
 2694    fail.
 2695
 2696do_xref_source_file(Spec, File, Options) :-
 2697    nonvar(Spec),
 2698    option(file_type(Type), Options, prolog),
 2699    absolute_file_name(Spec, File,
 2700                       [ file_type(Type),
 2701                         access(read),
 2702                         file_errors(fail)
 2703                       ]),
 2704    !.
 canonical_source(?Source, ?Src) is det
Src is the canonical version of Source if Source is given.
 2710canonical_source(Source, Src) :-
 2711    (   ground(Source)
 2712    ->  prolog_canonical_source(Source, Src)
 2713    ;   Source = Src
 2714    ).
 goal_name_arity(+Goal, -Name, -Arity)
Generalized version of functor/3 that can deal with name() goals.
 2721goal_name_arity(Goal, Name, Arity) :-
 2722    (   compound(Goal)
 2723    ->  compound_name_arity(Goal, Name, Arity)
 2724    ;   atom(Goal)
 2725    ->  Name = Goal, Arity = 0
 2726    ).
 2727
 2728generalise_term(Specific, General) :-
 2729    (   compound(Specific)
 2730    ->  compound_name_arity(Specific, Name, Arity),
 2731        compound_name_arity(General, Name, Arity)
 2732    ;   General = Specific
 2733    ).
 2734
 2735functor_name(Term, Name) :-
 2736    (   compound(Term)
 2737    ->  compound_name_arity(Term, Name, _)
 2738    ;   atom(Term)
 2739    ->  Name = Term
 2740    ).
 2741
 2742rename_goal(Goal0, Name, Goal) :-
 2743    (   compound(Goal0)
 2744    ->  compound_name_arity(Goal0, _, Arity),
 2745        compound_name_arity(Goal, Name, Arity)
 2746    ;   Goal = Name
 2747    )