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
    6    Copyright (c)  1985-2025, University of Amsterdam
    7			      VU University Amsterdam
    8			      CWI, Amsterdam
    9			      SWI-Prolog Solutions b.v.
   10    All rights reserved.
   11
   12    Redistribution and use in source and binary forms, with or without
   13    modification, are permitted provided that the following conditions
   14    are met:
   15
   16    1. Redistributions of source code must retain the above copyright
   17       notice, this list of conditions and the following disclaimer.
   18
   19    2. Redistributions in binary form must reproduce the above copyright
   20       notice, this list of conditions and the following disclaimer in
   21       the documentation and/or other materials provided with the
   22       distribution.
   23
   24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   25    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   26    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   27    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   28    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   29    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   30    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   31    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   32    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   34    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35    POSSIBILITY OF SUCH DAMAGE.
   36*/
   37
   38/*
   39Consult, derivates and basic things.   This  module  is  loaded  by  the
   40C-written  bootstrap  compiler.
   41
   42The $:- directive  is  executed  by  the  bootstrap  compiler,  but  not
   43inserted  in  the  intermediate  code  file.   Used  to print diagnostic
   44messages and start the Prolog defined compiler for  the  remaining  boot
   45modules.
   46
   47If you want  to  debug  this  module,  put  a  '$:-'(trace).   directive
   48somewhere.   The  tracer will work properly under boot compilation as it
   49will use the C defined write predicate  to  print  goals  and  does  not
   50attempt to call the Prolog defined trace interceptor.
   51*/
   52
   53		/********************************
   54		*    LOAD INTO MODULE SYSTEM    *
   55		********************************/
   56
   57:- '$set_source_module'(system).   58
   59'$boot_message'(_Format, _Args) :-
   60    current_prolog_flag(verbose, silent),
   61    !.
   62'$boot_message'(Format, Args) :-
   63    format(Format, Args),
   64    !.
   65
   66'$:-'('$boot_message'('Loading boot file ...~n', [])).
 memberchk(?E, ?List) is semidet
Semantically equivalent to once(member(E,List)). Implemented in C. If List is partial though we need to do the work in Prolog to get the proper constraint behavior. Needs to be defined early as the boot code uses it.
   76memberchk(E, List) :-
   77    '$memberchk'(E, List, Tail),
   78    (   nonvar(Tail)
   79    ->  true
   80    ;   Tail = [_|_],
   81	memberchk(E, Tail)
   82    ).
   83
   84		/********************************
   85		*          DIRECTIVES           *
   86		*********************************/
   87
   88:- meta_predicate
   89    dynamic(:),
   90    multifile(:),
   91    public(:),
   92    module_transparent(:),
   93    discontiguous(:),
   94    volatile(:),
   95    thread_local(:),
   96    noprofile(:),
   97    non_terminal(:),
   98    det(:),
   99    '$clausable'(:),
  100    '$iso'(:),
  101    '$hide'(:),
  102    '$notransact'(:).
 dynamic +Spec is det
 multifile +Spec is det
 module_transparent +Spec is det
 discontiguous +Spec is det
 volatile +Spec is det
 thread_local +Spec is det
 noprofile(+Spec) is det
 public +Spec is det
 non_terminal(+Spec) is det
Predicate versions of standard directives that set predicate attributes. These predicates bail out with an error on the first failure (typically permission errors).
 $iso(+Spec) is det
Set the ISO flag. This defines that the predicate cannot be redefined inside a module.
 $clausable(+Spec) is det
Specify that we can run clause/2 on a predicate, even if it is static. ISO specifies that public also plays this role. in SWI, public means that the predicate can be called, even if we cannot find a reference to it.
 $hide(+Spec) is det
Specify that the predicate cannot be seen in the debugger.
  134dynamic(Spec)            :- '$set_pattr'(Spec, pred, dynamic(true)).
  135multifile(Spec)          :- '$set_pattr'(Spec, pred, multifile(true)).
  136module_transparent(Spec) :- '$set_pattr'(Spec, pred, transparent(true)).
  137discontiguous(Spec)      :- '$set_pattr'(Spec, pred, discontiguous(true)).
  138volatile(Spec)           :- '$set_pattr'(Spec, pred, volatile(true)).
  139thread_local(Spec)       :- '$set_pattr'(Spec, pred, thread_local(true)).
  140noprofile(Spec)          :- '$set_pattr'(Spec, pred, noprofile(true)).
  141public(Spec)             :- '$set_pattr'(Spec, pred, public(true)).
  142non_terminal(Spec)       :- '$set_pattr'(Spec, pred, non_terminal(true)).
  143det(Spec)                :- '$set_pattr'(Spec, pred, det(true)).
  144'$iso'(Spec)             :- '$set_pattr'(Spec, pred, iso(true)).
  145'$clausable'(Spec)       :- '$set_pattr'(Spec, pred, clausable(true)).
  146'$hide'(Spec)            :- '$set_pattr'(Spec, pred, trace(false)).
  147'$notransact'(Spec)      :- '$set_pattr'(Spec, pred, transact(false)).
  148
  149'$set_pattr'(M:Pred, How, Attr) :-
  150    '$set_pattr'(Pred, M, How, Attr).
 $set_pattr(+Spec, +Module, +From, +Attr)
Set predicate attributes. From is one of pred or directive.
  156'$set_pattr'(X, _, _, _) :-
  157    var(X),
  158    '$uninstantiation_error'(X).
  159'$set_pattr'(as(Spec,Options), M, How, Attr0) :-
  160    !,
  161    '$attr_options'(Options, Attr0, Attr),
  162    '$set_pattr'(Spec, M, How, Attr).
  163'$set_pattr'([], _, _, _) :- !.
  164'$set_pattr'([H|T], M, How, Attr) :-           % ISO
  165    !,
  166    '$set_pattr'(H, M, How, Attr),
  167    '$set_pattr'(T, M, How, Attr).
  168'$set_pattr'((A,B), M, How, Attr) :-           % ISO and traditional
  169    !,
  170    '$set_pattr'(A, M, How, Attr),
  171    '$set_pattr'(B, M, How, Attr).
  172'$set_pattr'(M:T, _, How, Attr) :-
  173    !,
  174    '$set_pattr'(T, M, How, Attr).
  175'$set_pattr'(PI, M, _, []) :-
  176    !,
  177    '$pi_head'(M:PI, Pred),
  178    '$set_table_wrappers'(Pred).
  179'$set_pattr'(A, M, How, [O|OT]) :-
  180    !,
  181    '$set_pattr'(A, M, How, O),
  182    '$set_pattr'(A, M, How, OT).
  183'$set_pattr'(A, M, pred, Attr) :-
  184    !,
  185    Attr =.. [Name,Val],
  186    '$set_pi_attr'(M:A, Name, Val).
  187'$set_pattr'(A, M, directive, Attr) :-
  188    !,
  189    Attr =.. [Name,Val],
  190    catch('$set_pi_attr'(M:A, Name, Val),
  191	  error(E, _),
  192	  print_message(error, error(E, context((Name)/1,_)))).
  193
  194'$set_pi_attr'(PI, Name, Val) :-
  195    '$pi_head'(PI, Head),
  196    '$set_predicate_attribute'(Head, Name, Val).
  197
  198'$attr_options'(Var, _, _) :-
  199    var(Var),
  200    !,
  201    '$uninstantiation_error'(Var).
  202'$attr_options'((A,B), Attr0, Attr) :-
  203    !,
  204    '$attr_options'(A, Attr0, Attr1),
  205    '$attr_options'(B, Attr1, Attr).
  206'$attr_options'(Opt, Attr0, Attrs) :-
  207    '$must_be'(ground, Opt),
  208    (   '$attr_option'(Opt, AttrX)
  209    ->  (   is_list(Attr0)
  210	->  '$join_attrs'(AttrX, Attr0, Attrs)
  211	;   '$join_attrs'(AttrX, [Attr0], Attrs)
  212	)
  213    ;   '$domain_error'(predicate_option, Opt)
  214    ).
  215
  216'$join_attrs'([], Attrs, Attrs) :-
  217    !.
  218'$join_attrs'([H|T], Attrs0, Attrs) :-
  219    !,
  220    '$join_attrs'(H, Attrs0, Attrs1),
  221    '$join_attrs'(T, Attrs1, Attrs).
  222'$join_attrs'(Attr, Attrs, Attrs) :-
  223    memberchk(Attr, Attrs),
  224    !.
  225'$join_attrs'(Attr, Attrs, Attrs) :-
  226    Attr =.. [Name,Value],
  227    Gen =.. [Name,Existing],
  228    memberchk(Gen, Attrs),
  229    !,
  230    throw(error(conflict_error(Name, Value, Existing), _)).
  231'$join_attrs'(Attr, Attrs0, Attrs) :-
  232    '$append'(Attrs0, [Attr], Attrs).
  233
  234'$attr_option'(incremental, [incremental(true),opaque(false)]).
  235'$attr_option'(monotonic, monotonic(true)).
  236'$attr_option'(lazy, lazy(true)).
  237'$attr_option'(opaque, [incremental(false),opaque(true)]).
  238'$attr_option'(abstract(Level0), abstract(Level)) :-
  239    '$table_option'(Level0, Level).
  240'$attr_option'(subgoal_abstract(Level0), subgoal_abstract(Level)) :-
  241    '$table_option'(Level0, Level).
  242'$attr_option'(answer_abstract(Level0), answer_abstract(Level)) :-
  243    '$table_option'(Level0, Level).
  244'$attr_option'(max_answers(Level0), max_answers(Level)) :-
  245    '$table_option'(Level0, Level).
  246'$attr_option'(volatile, volatile(true)).
  247'$attr_option'(multifile, multifile(true)).
  248'$attr_option'(discontiguous, discontiguous(true)).
  249'$attr_option'(shared, thread_local(false)).
  250'$attr_option'(local, thread_local(true)).
  251'$attr_option'(private, thread_local(true)).
  252
  253'$table_option'(Value0, _Value) :-
  254    var(Value0),
  255    !,
  256    '$instantiation_error'(Value0).
  257'$table_option'(Value0, Value) :-
  258    integer(Value0),
  259    Value0 >= 0,
  260    !,
  261    Value = Value0.
  262'$table_option'(off, -1) :-
  263    !.
  264'$table_option'(false, -1) :-
  265    !.
  266'$table_option'(infinite, -1) :-
  267    !.
  268'$table_option'(Value, _) :-
  269    '$domain_error'(nonneg_or_false, Value).
 $pattr_directive(+Spec, +Module) is det
This implements the directive version of dynamic/1, multifile/1, etc. This version catches and prints errors. If the directive specifies multiple predicates, processing after an error continues with the remaining predicates.
  279'$pattr_directive'(dynamic(Spec), M) :-
  280    '$set_pattr'(Spec, M, directive, dynamic(true)).
  281'$pattr_directive'(multifile(Spec), M) :-
  282    '$set_pattr'(Spec, M, directive, multifile(true)).
  283'$pattr_directive'(module_transparent(Spec), M) :-
  284    '$set_pattr'(Spec, M, directive, transparent(true)).
  285'$pattr_directive'(discontiguous(Spec), M) :-
  286    '$set_pattr'(Spec, M, directive, discontiguous(true)).
  287'$pattr_directive'(volatile(Spec), M) :-
  288    '$set_pattr'(Spec, M, directive, volatile(true)).
  289'$pattr_directive'(thread_local(Spec), M) :-
  290    '$set_pattr'(Spec, M, directive, thread_local(true)).
  291'$pattr_directive'(noprofile(Spec), M) :-
  292    '$set_pattr'(Spec, M, directive, noprofile(true)).
  293'$pattr_directive'(public(Spec), M) :-
  294    '$set_pattr'(Spec, M, directive, public(true)).
  295'$pattr_directive'(det(Spec), M) :-
  296    '$set_pattr'(Spec, M, directive, det(true)).
 $pi_head(?PI, ?Head)
  300'$pi_head'(PI, Head) :-
  301    var(PI),
  302    var(Head),
  303    '$instantiation_error'([PI,Head]).
  304'$pi_head'(M:PI, M:Head) :-
  305    !,
  306    '$pi_head'(PI, Head).
  307'$pi_head'(Name/Arity, Head) :-
  308    !,
  309    '$head_name_arity'(Head, Name, Arity).
  310'$pi_head'(Name//DCGArity, Head) :-
  311    !,
  312    (   nonvar(DCGArity)
  313    ->  Arity is DCGArity+2,
  314	'$head_name_arity'(Head, Name, Arity)
  315    ;   '$head_name_arity'(Head, Name, Arity),
  316	DCGArity is Arity - 2
  317    ).
  318'$pi_head'(PI, _) :-
  319    '$type_error'(predicate_indicator, PI).
 $head_name_arity(+Goal, -Name, -Arity)
$head_name_arity(-Goal, +Name, +Arity)
  324'$head_name_arity'(Goal, Name, Arity) :-
  325    (   atom(Goal)
  326    ->  Name = Goal, Arity = 0
  327    ;   compound(Goal)
  328    ->  compound_name_arity(Goal, Name, Arity)
  329    ;   var(Goal)
  330    ->  (   Arity == 0
  331	->  (   atom(Name)
  332	    ->  Goal = Name
  333	    ;   Name == []
  334	    ->  Goal = Name
  335	    ;   blob(Name, closure)
  336	    ->  Goal = Name
  337	    ;   '$type_error'(atom, Name)
  338	    )
  339	;   compound_name_arity(Goal, Name, Arity)
  340	)
  341    ;   '$type_error'(callable, Goal)
  342    ).
  343
  344:- '$iso'(((dynamic)/1, (multifile)/1, (discontiguous)/1)).  345
  346
  347		/********************************
  348		*       CALLING, CONTROL        *
  349		*********************************/
  350
  351:- noprofile((call/1,
  352	      catch/3,
  353	      once/1,
  354	      ignore/1,
  355	      call_cleanup/2,
  356	      setup_call_cleanup/3,
  357	      setup_call_catcher_cleanup/4,
  358	      notrace/1)).  359
  360:- meta_predicate
  361    ';'(0,0),
  362    ','(0,0),
  363    @(0,+),
  364    call(0),
  365    call(1,?),
  366    call(2,?,?),
  367    call(3,?,?,?),
  368    call(4,?,?,?,?),
  369    call(5,?,?,?,?,?),
  370    call(6,?,?,?,?,?,?),
  371    call(7,?,?,?,?,?,?,?),
  372    not(0),
  373    \+(0),
  374    $(0),
  375    '->'(0,0),
  376    '*->'(0,0),
  377    once(0),
  378    ignore(0),
  379    catch(0,?,0),
  380    reset(0,?,-),
  381    setup_call_cleanup(0,0,0),
  382    setup_call_catcher_cleanup(0,0,?,0),
  383    call_cleanup(0,0),
  384    catch_with_backtrace(0,?,0),
  385    notrace(0),
  386    '$meta_call'(0).  387
  388:- '$iso'((call/1, (\+)/1, once/1, (;)/2, (',')/2, (->)/2, catch/3)).  389
  390% The control structures are always compiled, both   if they appear in a
  391% clause body and if they are handed  to   call/1.  The only way to call
  392% these predicates is by means of  call/2..   In  that case, we call the
  393% hole control structure again to get it compiled by call/1 and properly
  394% deal  with  !,  etc.  Another  reason  for  having  these  things   as
  395% predicates is to be able to define   properties for them, helping code
  396% analyzers.
  397
  398(M0:If ; M0:Then) :- !, call(M0:(If ; Then)).
  399(M1:If ; M2:Then) :-    call(M1:(If ; M2:Then)).
  400(G1   , G2)       :-    call((G1   , G2)).
  401(If  -> Then)     :-    call((If  -> Then)).
  402(If *-> Then)     :-    call((If *-> Then)).
  403@(Goal,Module)    :-    @(Goal,Module).
 $meta_call(:Goal)
Interpreted meta-call implementation. By default, call/1 compiles its argument into a temporary clause. This realises better performance if the (complex) goal does a lot of backtracking because this interpreted version needs to re-interpret the remainder of the goal after backtracking.

This implementation is used by reset/3 because the continuation cannot be captured if it contains a such a compiled temporary clause.

  417'$meta_call'(M:G) :-
  418    prolog_current_choice(Ch),
  419    '$meta_call'(G, M, Ch).
  420
  421'$meta_call'(Var, _, _) :-
  422    var(Var),
  423    !,
  424    '$instantiation_error'(Var).
  425'$meta_call'((A,B), M, Ch) :-
  426    !,
  427    '$meta_call'(A, M, Ch),
  428    '$meta_call'(B, M, Ch).
  429'$meta_call'((I->T;E), M, Ch) :-
  430    !,
  431    (   prolog_current_choice(Ch2),
  432	'$meta_call'(I, M, Ch2)
  433    ->  '$meta_call'(T, M, Ch)
  434    ;   '$meta_call'(E, M, Ch)
  435    ).
  436'$meta_call'((I*->T;E), M, Ch) :-
  437    !,
  438    (   prolog_current_choice(Ch2),
  439	'$meta_call'(I, M, Ch2)
  440    *-> '$meta_call'(T, M, Ch)
  441    ;   '$meta_call'(E, M, Ch)
  442    ).
  443'$meta_call'((I->T), M, Ch) :-
  444    !,
  445    (   prolog_current_choice(Ch2),
  446	'$meta_call'(I, M, Ch2)
  447    ->  '$meta_call'(T, M, Ch)
  448    ).
  449'$meta_call'((I*->T), M, Ch) :-
  450    !,
  451    prolog_current_choice(Ch2),
  452    '$meta_call'(I, M, Ch2),
  453    '$meta_call'(T, M, Ch).
  454'$meta_call'((A;B), M, Ch) :-
  455    !,
  456    (   '$meta_call'(A, M, Ch)
  457    ;   '$meta_call'(B, M, Ch)
  458    ).
  459'$meta_call'(\+(G), M, _) :-
  460    !,
  461    prolog_current_choice(Ch),
  462    \+ '$meta_call'(G, M, Ch).
  463'$meta_call'($(G), M, _) :-
  464    !,
  465    prolog_current_choice(Ch),
  466    $('$meta_call'(G, M, Ch)).
  467'$meta_call'(call(G), M, _) :-
  468    !,
  469    prolog_current_choice(Ch),
  470    '$meta_call'(G, M, Ch).
  471'$meta_call'(M:G, _, Ch) :-
  472    !,
  473    '$meta_call'(G, M, Ch).
  474'$meta_call'(!, _, Ch) :-
  475    prolog_cut_to(Ch).
  476'$meta_call'(G, M, _Ch) :-
  477    call(M:G).
 call(:Closure, ?A)
 call(:Closure, ?A1, ?A2)
 call(:Closure, ?A1, ?A2, ?A3)
 call(:Closure, ?A1, ?A2, ?A3, ?A4)
 call(:Closure, ?A1, ?A2, ?A3, ?A4, ?A5)
 call(:Closure, ?A1, ?A2, ?A3, ?A4, ?A5, ?A6)
 call(:Closure, ?A1, ?A2, ?A3, ?A4, ?A5, ?A6, ?A7)
Arity 2..8 is demanded by the ISO standard. Higher arities are supported, but handled by the compiler. This implies they are not backed up by predicates and analyzers thus cannot ask for their properties. Analyzers should hard-code handling of call/2..
  493:- '$iso'((call/2,
  494	   call/3,
  495	   call/4,
  496	   call/5,
  497	   call/6,
  498	   call/7,
  499	   call/8)).  500
  501call(Goal) :-                           % make these available as predicates
  502    Goal.
  503call(Goal, A) :-
  504    call(Goal, A).
  505call(Goal, A, B) :-
  506    call(Goal, A, B).
  507call(Goal, A, B, C) :-
  508    call(Goal, A, B, C).
  509call(Goal, A, B, C, D) :-
  510    call(Goal, A, B, C, D).
  511call(Goal, A, B, C, D, E) :-
  512    call(Goal, A, B, C, D, E).
  513call(Goal, A, B, C, D, E, F) :-
  514    call(Goal, A, B, C, D, E, F).
  515call(Goal, A, B, C, D, E, F, G) :-
  516    call(Goal, A, B, C, D, E, F, G).
 not(:Goal) is semidet
Pre-ISO version of \+/1. Note that some systems define not/1 as a logically more sound version of \+/1.
  523not(Goal) :-
  524    \+ Goal.
 \+ :Goal is semidet
Predicate version that allows for meta-calling.
  530\+ Goal :-
  531    \+ Goal.
 once(:Goal) is semidet
ISO predicate, acting as call((Goal, !)).
  537once(Goal) :-
  538    Goal,
  539    !.
 ignore(:Goal) is det
Call Goal, cut choice-points on success and succeed on failure. intended for calling side-effects and proceed on failure.
  546ignore(Goal) :-
  547    Goal,
  548    !.
  549ignore(_Goal).
  550
  551:- '$iso'((false/0)).
 false
Synonym for fail/0, providing a declarative reading.
  557false :-
  558    fail.
 catch(:Goal, +Catcher, :Recover)
ISO compliant exception handling.
  564catch(_Goal, _Catcher, _Recover) :-
  565    '$catch'.                       % Maps to I_CATCH, I_EXITCATCH
 prolog_cut_to(+Choice)
Cut all choice points after Choice
  571prolog_cut_to(_Choice) :-
  572    '$cut'.                         % Maps to I_CUTCHP
 $ is det
Declare that from now on this predicate succeeds deterministically.
  578'$' :- '$'.
 $ :Goal is det
Declare that Goal must succeed deterministically.
  584$(Goal) :- $(Goal).
 notrace(:Goal) is semidet
Suspend the tracer while running Goal.
  590:- '$hide'(notrace/1).  591
  592notrace(Goal) :-
  593    setup_call_cleanup(
  594	'$notrace'(Flags, SkipLevel),
  595	once(Goal),
  596	'$restore_trace'(Flags, SkipLevel)).
 reset(:Goal, ?Ball, -Continue)
Delimited continuation support.
  603reset(_Goal, _Ball, _Cont) :-
  604    '$reset'.
 $tbl_reset(+Goal, ?Ball, -Continue, +WorkList, +Skeleton, +Delays)
As reset/3, but if Goal succeeds, add Skeleton as an answer to WorkList with Delays and fail. If the answer completes the table, first prune the choice points of Goal. Thus, this only succeeds if Goal suspends. Used by delim/4 of the tabling library. Goal is either a module-qualified goal or a continuation. This is not a meta-predicate to avoid qualifying the continuation on every resumption.
  616'$tbl_reset'(_Goal, _Ball, _Cont, _WorkList, _Skeleton, _Delays) :-
  617    '$reset'.
 shift(+Ball)
 shift_for_copy(+Ball)
Shift control back to the enclosing reset/3. The second version assumes the continuation will be saved to be reused in a different context.
  626shift(Ball) :-
  627    '$shift'(Ball).
  628
  629shift_for_copy(Ball) :-
  630    '$shift_for_copy'(Ball).
 call_continuation(+Continuation:list)
Call a continuation as created by shift/1. The continuation is a list of '$cont$'(Clause, PC, EnvironmentArg, ...) structures. The predicate '$call_one_tail_body'/1 creates a frame from the continuation and calls this.

Note that we can technically also push the entire continuation onto the environment and call it. Doing it incrementally as below exploits last-call optimization and therefore possible quadratic expansion of the continuation.

  644call_continuation([]).
  645call_continuation([TB|Rest]) :-
  646    (   Rest == []
  647    ->  '$call_continuation'(TB)
  648    ;   '$call_continuation'(TB),
  649	call_continuation(Rest)
  650    ).
 catch_with_backtrace(:Goal, ?Ball, :Recover)
As catch/3, but tell library(prolog_stack) to record a backtrace in case of an exception.
  657catch_with_backtrace(Goal, Ball, Recover) :-
  658    catch(Goal, Ball, Recover),
  659    '$no_lco'.
  660
  661'$no_lco'.
 $recover_and_rethrow(:Goal, +Term)
This goal is used to wrap the catch/3 recover handler if the exception is not supposed to be `catchable'. This applies to exceptions of the shape unwind(Term). Note that we cut to ensure that the exception is not delayed forever because the recover handler leaves a choicepoint.
  671:- public '$recover_and_rethrow'/2.  672
  673'$recover_and_rethrow'(Goal, Exception) :-
  674    call_cleanup(Goal, throw(Exception)),
  675    !.
 call_cleanup(:Goal, :Cleanup)
 setup_call_cleanup(:Setup, :Goal, :Cleanup)
 setup_call_catcher_cleanup(:Setup, :Goal, +Catcher, :Cleanup)
Call Cleanup once after Goal is finished (deterministic success, failure, exception or cut). The call to '$call_cleanup' is translated to I_CALLCLEANUP, I_EXITCLEANUP. These instructions rely on the exact stack layout left by these predicates, where the variant is determined by the arity. See also callCleanupHandler() in pl-wam.c.
  689setup_call_catcher_cleanup(Setup, _Goal, _Catcher, _Cleanup) :-
  690    sig_atomic(Setup),
  691    '$call_cleanup'.
  692
  693setup_call_cleanup(Setup, _Goal, _Cleanup) :-
  694    sig_atomic(Setup),
  695    '$call_cleanup'.
  696
  697call_cleanup(_Goal, _Cleanup) :-
  698    '$call_cleanup'.
  699
  700
  701		 /*******************************
  702		 *       INITIALIZATION         *
  703		 *******************************/
  704
  705:- meta_predicate
  706    initialization(0, +).  707
  708:- multifile '$init_goal'/3.  709:- dynamic   '$init_goal'/3.  710:- '$notransact'('$init_goal'/3).
 initialization(:Goal, +When)
Register Goal to be executed if a saved state is restored. In addition, the goal is executed depending on When:
now
Execute immediately
after_load
Execute after loading the file in which it appears. This is initialization/1.
restore_state
Do not execute immediately, but only when restoring the state. Not allowed in a sandboxed environment.
prepare_state
Called before saving a state. Can be used to clean the environment (see also volatile/1) or eagerly execute goals that are normally executed lazily.
program
Works as -g goal goals.
main
Starts the application. Only last declaration is used.

Note that all goals are executed when a program is restored.

  736initialization(Goal, When) :-
  737    '$must_be'(oneof(atom, initialization_type,
  738		     [ now,
  739		       after_load,
  740		       restore,
  741		       restore_state,
  742		       prepare_state,
  743		       program,
  744		       main
  745		     ]), When),
  746    '$initialization_context'(Source, Ctx),
  747    '$initialization'(When, Goal, Source, Ctx).
  748
  749'$initialization'(now, Goal, _Source, Ctx) :-
  750    '$run_init_goal'(Goal, Ctx),
  751    '$compile_init_goal'(-, Goal, Ctx).
  752'$initialization'(after_load, Goal, Source, Ctx) :-
  753    (   Source \== (-)
  754    ->  '$compile_init_goal'(Source, Goal, Ctx)
  755    ;   throw(error(context_error(nodirective,
  756				  initialization(Goal, after_load)),
  757		    _))
  758    ).
  759'$initialization'(restore, Goal, Source, Ctx) :- % deprecated
  760    '$initialization'(restore_state, Goal, Source, Ctx).
  761'$initialization'(restore_state, Goal, _Source, Ctx) :-
  762    (   \+ current_prolog_flag(sandboxed_load, true)
  763    ->  '$compile_init_goal'(-, Goal, Ctx)
  764    ;   '$permission_error'(register, initialization(restore), Goal)
  765    ).
  766'$initialization'(prepare_state, Goal, _Source, Ctx) :-
  767    (   \+ current_prolog_flag(sandboxed_load, true)
  768    ->  '$compile_init_goal'(when(prepare_state), Goal, Ctx)
  769    ;   '$permission_error'(register, initialization(restore), Goal)
  770    ).
  771'$initialization'(program, Goal, _Source, Ctx) :-
  772    (   \+ current_prolog_flag(sandboxed_load, true)
  773    ->  '$compile_init_goal'(when(program), Goal, Ctx)
  774    ;   '$permission_error'(register, initialization(restore), Goal)
  775    ).
  776'$initialization'(main, Goal, _Source, Ctx) :-
  777    (   \+ current_prolog_flag(sandboxed_load, true)
  778    ->  '$compile_init_goal'(when(main), Goal, Ctx)
  779    ;   '$permission_error'(register, initialization(restore), Goal)
  780    ).
  781
  782
  783'$compile_init_goal'(Source, Goal, Ctx) :-
  784    atom(Source),
  785    Source \== (-),
  786    !,
  787    '$store_admin_clause'(system:'$init_goal'(Source, Goal, Ctx),
  788			  _Layout, Source, Ctx).
  789'$compile_init_goal'(Source, Goal, Ctx) :-
  790    assertz('$init_goal'(Source, Goal, Ctx)).
 $run_initialization(?File, +Options) is det
 $run_initialization(?File, +Action, +Options) is det
Run initialization directives for all files if File is unbound, or for a specified file. Note that '$run_initialization'/2 is called from runInitialization() in pl-wic.c for .qlf files. The '$run_initialization'/3 is called with Action set to loaded when called for a QLF file.
  802'$run_initialization'(_, loaded, _) :- !.
  803'$run_initialization'(File, _Action, Options) :-
  804    '$run_initialization'(File, Options).
  805
  806'$run_initialization'(File, Options) :-
  807    setup_call_cleanup(
  808	'$start_run_initialization'(Options, Restore),
  809	'$run_initialization_2'(File),
  810	'$end_run_initialization'(Restore)).
  811
  812'$start_run_initialization'(Options, OldSandBoxed) :-
  813    '$push_input_context'(initialization),
  814    '$set_sandboxed_load'(Options, OldSandBoxed).
  815'$end_run_initialization'(OldSandBoxed) :-
  816    set_prolog_flag(sandboxed_load, OldSandBoxed),
  817    '$pop_input_context'.
  818
  819'$run_initialization_2'(File) :-
  820    (   '$init_goal'(File, Goal, Ctx),
  821	File \= when(_),
  822	'$run_init_goal'(Goal, Ctx),
  823	fail
  824    ;   true
  825    ).
  826
  827'$run_init_goal'(Goal, Ctx) :-
  828    (   catch_with_backtrace('$run_init_goal'(Goal), E,
  829			     '$initialization_error'(E, Goal, Ctx))
  830    ->  true
  831    ;   '$initialization_failure'(Goal, Ctx)
  832    ).
  833
  834:- multifile prolog:sandbox_allowed_goal/1.  835
  836'$run_init_goal'(Goal) :-
  837    current_prolog_flag(sandboxed_load, false),
  838    !,
  839    call(Goal).
  840'$run_init_goal'(Goal) :-
  841    prolog:sandbox_allowed_goal(Goal),
  842    call(Goal).
  843
  844'$initialization_context'(Source, Ctx) :-
  845    (   source_location(File, Line)
  846    ->  Ctx = File:Line,
  847	'$input_context'(Context),
  848	'$top_file'(Context, File, Source)
  849    ;   Ctx = (-),
  850	File = (-)
  851    ).
  852
  853'$top_file'([input(include, F1, _, _)|T], _, F) :-
  854    !,
  855    '$top_file'(T, F1, F).
  856'$top_file'(_, F, F).
  857
  858
  859'$initialization_error'(unwind(halt(Status)), Goal, Ctx) :-
  860    !,
  861    print_message(warning, initialization(halt(Status), Goal, Ctx)).
  862'$initialization_error'(E, Goal, Ctx) :-
  863    print_message(error, initialization_error(Goal, E, Ctx)).
  864
  865'$initialization_failure'(Goal, Ctx) :-
  866    print_message(warning, initialization_failure(Goal, Ctx)).
 $clear_source_admin(+File) is det
Removes source adminstration related to File
See also
- Called from destroySourceFile() in pl-proc.c
  874:- public '$clear_source_admin'/1.  875
  876'$clear_source_admin'(File) :-
  877    retractall('$init_goal'(_, _, File:_)),
  878    retractall('$load_context_module'(File, _, _)),
  879    retractall('$resolved_source_path_db'(_, _, File)).
  880
  881
  882		 /*******************************
  883		 *            STREAM            *
  884		 *******************************/
  885
  886:- '$iso'(stream_property/2).  887stream_property(Stream, Property) :-
  888    nonvar(Stream),
  889    nonvar(Property),
  890    !,
  891    '$stream_property'(Stream, Property).
  892stream_property(Stream, Property) :-
  893    nonvar(Stream),
  894    !,
  895    '$stream_properties'(Stream, Properties),
  896    '$member'(Property, Properties).
  897stream_property(Stream, Property) :-
  898    nonvar(Property),
  899    !,
  900    (   Property = alias(Alias),
  901	atom(Alias)
  902    ->  '$alias_stream'(Alias, Stream)
  903    ;   '$streams_properties'(Property, Pairs),
  904	'$member'(Stream-Property, Pairs)
  905    ).
  906stream_property(Stream, Property) :-
  907    '$streams_properties'(Property, Pairs),
  908    '$member'(Stream-Properties, Pairs),
  909    '$member'(Property, Properties).
  910
  911
  912		/********************************
  913		*            MODULES            *
  914		*********************************/
  915
  916%       '$prefix_module'(+Module, +Context, +Term, -Prefixed)
  917%       Tags `Term' with `Module:' if `Module' is not the context module.
  918
  919'$prefix_module'(Module, Module, Head, Head) :- !.
  920'$prefix_module'(Module, _, Head, Module:Head).
 default_module(+Me, -Super) is multi
Is true if `Super' is `Me' or a super (auto import) module of `Me'.
  926default_module(Me, Super) :-
  927    (   atom(Me)
  928    ->  (   var(Super)
  929	->  '$default_module'(Me, Super)
  930	;   '$default_module'(Me, Super), !
  931	)
  932    ;   '$type_error'(module, Me)
  933    ).
  934
  935'$default_module'(Me, Me).
  936'$default_module'(Me, Super) :-
  937    import_module(Me, S),
  938    '$default_module'(S, Super).
  939
  940
  941		/********************************
  942		*      TRACE AND EXCEPTIONS     *
  943		*********************************/
  944
  945:- dynamic   user:exception/3.  946:- multifile user:exception/3.  947:- '$hide'(user:exception/3).
 $undefined_procedure(+Module, +Name, +Arity, -Action) is det
This predicate is called from C on undefined predicates. First allows the user to take care of it using exception/3. Else try to give a DWIM warning. Otherwise fail. C will print an error message.
  956:- public
  957    '$undefined_procedure'/4.  958
  959'$undefined_procedure'(Module, Name, Arity, Action) :-
  960    '$prefix_module'(Module, user, Name/Arity, Pred),
  961    user:exception(undefined_predicate, Pred, Action0),
  962    !,
  963    Action = Action0.
  964'$undefined_procedure'(Module, Name, Arity, Action) :-
  965    \+ current_prolog_flag(autoload, false),
  966    '$autoload'(Module:Name/Arity),
  967    !,
  968    Action = retry.
  969'$undefined_procedure'(_, _, _, error).
 $loading(+Library)
True if the library is being loaded. Just testing that the predicate is defined is not good enough as the file may be partly loaded. Calling use_module/2 at any time has two drawbacks: it queries the filesystem, causing slowdown and it stops libraries being autoloaded from a saved state where the library is already loaded, but the source may not be accessible.
  981'$loading'(Library) :-
  982    current_prolog_flag(threads, true),
  983    (   '$loading_file'(Library, _Queue, _LoadThread)
  984    ->  true
  985    ;   '$loading_file'(FullFile, _Queue, _LoadThread),
  986	file_name_extension(Library, _, FullFile)
  987    ->  true
  988    ).
  989
  990%        handle debugger 'w', 'p' and <N> depth options.
  991
  992'$set_debugger_write_options'(write) :-
  993    !,
  994    create_prolog_flag(debugger_write_options,
  995		       [ quoted(true),
  996			 attributes(dots),
  997			 spacing(next_argument)
  998		       ], []).
  999'$set_debugger_write_options'(print) :-
 1000    !,
 1001    create_prolog_flag(debugger_write_options,
 1002		       [ quoted(true),
 1003			 portray(true),
 1004			 max_depth(10),
 1005			 attributes(portray),
 1006			 spacing(next_argument)
 1007		       ], []).
 1008'$set_debugger_write_options'(Depth) :-
 1009    current_prolog_flag(debugger_write_options, Options0),
 1010    (   '$select'(max_depth(_), Options0, Options)
 1011    ->  true
 1012    ;   Options = Options0
 1013    ),
 1014    create_prolog_flag(debugger_write_options,
 1015		       [max_depth(Depth)|Options], []).
 1016
 1017
 1018		/********************************
 1019		*        SYSTEM MESSAGES        *
 1020		*********************************/
 $confirm(Spec) is semidet
Ask the user to confirm a question. Spec is a term as used for print_message/2. It is printed the the query channel. This predicate may be hooked using confirm/2, which must return a boolean.
 1029:- multifile
 1030    prolog:confirm/2. 1031
 1032'$confirm'(Spec) :-
 1033    prolog:confirm(Spec, Result),
 1034    !,
 1035    Result == true.
 1036'$confirm'(Spec) :-
 1037    print_message(query, Spec),
 1038    between(0, 5, _),
 1039	get_single_char(Answer),
 1040	(   '$in_reply'(Answer, 'yYjJ \n')
 1041	->  !,
 1042	    print_message(query, if_tty([yes-[]]))
 1043	;   '$in_reply'(Answer, 'nN')
 1044	->  !,
 1045	    print_message(query, if_tty([no-[]])),
 1046	    fail
 1047	;   print_message(help, query(confirm)),
 1048	    fail
 1049	).
 1050
 1051'$in_reply'(Code, Atom) :-
 1052    char_code(Char, Code),
 1053    sub_atom(Atom, _, _, _, Char),
 1054    !.
 1055
 1056:- dynamic
 1057    user:portray/1. 1058:- multifile
 1059    user:portray/1. 1060:- '$notransact'(user:portray/1). 1061
 1062
 1063		 /*******************************
 1064		 *       FILE_SEARCH_PATH       *
 1065		 *******************************/
 1066
 1067:- dynamic
 1068    user:file_search_path/2,
 1069    user:library_directory/1. 1070:- multifile
 1071    user:file_search_path/2,
 1072    user:library_directory/1. 1073:- '$notransact'((user:file_search_path/2,
 1074                  user:library_directory/1)). 1075
 1076user:(file_search_path(library, Dir) :-
 1077	library_directory(Dir)).
 1078user:file_search_path(swi, Home) :-
 1079    current_prolog_flag(home, Home).
 1080user:file_search_path(swi, Home) :-
 1081    current_prolog_flag(shared_home, Home).
 1082user:file_search_path(library, app_config(lib)).
 1083user:file_search_path(library, swi(library)).
 1084user:file_search_path(library, swi(library/clp)).
 1085user:file_search_path(library, Dir) :-
 1086    '$ext_library_directory'(Dir).
 1087user:file_search_path(path, Dir) :-
 1088    getenv('PATH', Path),
 1089    current_prolog_flag(path_sep, Sep),
 1090    atomic_list_concat(Dirs, Sep, Path),
 1091    '$member'(Dir, Dirs).
 1092user:file_search_path(user_app_data, Dir) :-
 1093    '$xdg_prolog_directory'(data, Dir).
 1094user:file_search_path(common_app_data, Dir) :-
 1095    '$xdg_prolog_directory'(common_data, Dir).
 1096user:file_search_path(user_app_config, Dir) :-
 1097    '$xdg_prolog_directory'(config, Dir).
 1098user:file_search_path(common_app_config, Dir) :-
 1099    '$xdg_prolog_directory'(common_config, Dir).
 1100user:file_search_path(app_data, user_app_data('.')).
 1101user:file_search_path(app_data, common_app_data('.')).
 1102user:file_search_path(app_config, user_app_config('.')).
 1103user:file_search_path(app_config, common_app_config('.')).
 1104% backward compatibility
 1105user:file_search_path(app_preferences, user_app_config('.')).
 1106user:file_search_path(user_profile, app_preferences('.')).
 1107user:file_search_path(app, swi(app)).
 1108user:file_search_path(app, app_data(app)).
 1109user:file_search_path(demo, swi(demo)).
 1110user:file_search_path(working_directory, CWD) :-
 1111    working_directory(CWD, CWD).
 1112
 1113'$xdg_prolog_directory'(Which, Dir) :-
 1114    '$xdg_directory'(Which, XDGDir),
 1115    '$make_config_dir'(XDGDir),
 1116    '$ensure_slash'(XDGDir, XDGDirS),
 1117    atom_concat(XDGDirS, 'swi-prolog', Dir),
 1118    '$make_config_dir'(Dir).
 1119
 1120'$xdg_directory'(Which, Dir) :-
 1121    '$xdg_directory_search'(Where),
 1122    '$xdg_directory'(Which, Where, Dir).
 1123
 1124'$xdg_directory_search'(xdg) :-
 1125    current_prolog_flag(xdg, true),
 1126    !.
 1127'$xdg_directory_search'(Where) :-
 1128    current_prolog_flag(windows, true),
 1129    (   current_prolog_flag(xdg, false)
 1130    ->  Where = windows
 1131    ;   '$member'(Where, [windows, xdg])
 1132    ).
 1133
 1134% config
 1135'$xdg_directory'(config, windows, Home) :-
 1136    catch(win_folder(appdata, Home), _, fail).
 1137'$xdg_directory'(config, xdg, Home) :-
 1138    getenv('XDG_CONFIG_HOME', Home).
 1139'$xdg_directory'(config, xdg, Home) :-
 1140    expand_file_name('~/.config', [Home]).
 1141% data
 1142'$xdg_directory'(data, windows, Home) :-
 1143    catch(win_folder(local_appdata, Home), _, fail).
 1144'$xdg_directory'(data, xdg, Home) :-
 1145    getenv('XDG_DATA_HOME', Home).
 1146'$xdg_directory'(data, xdg, Home) :-
 1147    expand_file_name('~/.local', [Local]),
 1148    '$make_config_dir'(Local),
 1149    atom_concat(Local, '/share', Home),
 1150    '$make_config_dir'(Home).
 1151% common data
 1152'$xdg_directory'(common_data, windows, Dir) :-
 1153    catch(win_folder(common_appdata, Dir), _, fail).
 1154'$xdg_directory'(common_data, xdg, Dir) :-
 1155    '$existing_dir_from_env_path'('XDG_DATA_DIRS',
 1156				  [ '/usr/local/share',
 1157				    '/usr/share'
 1158				  ],
 1159				  Dir).
 1160% common config
 1161'$xdg_directory'(common_config, windows, Dir) :-
 1162    catch(win_folder(common_appdata, Dir), _, fail).
 1163'$xdg_directory'(common_config, xdg, Dir) :-
 1164    '$existing_dir_from_env_path'('XDG_CONFIG_DIRS', ['/etc/xdg'], Dir).
 1165
 1166'$existing_dir_from_env_path'(Env, Defaults, Dir) :-
 1167    (   getenv(Env, Path)
 1168    ->  current_prolog_flag(path_sep, Sep),
 1169	atomic_list_concat(Dirs, Sep, Path)
 1170    ;   Dirs = Defaults
 1171    ),
 1172    '$member'(Dir, Dirs),
 1173    Dir \== '',
 1174    exists_directory(Dir).
 1175
 1176'$make_config_dir'(Dir) :-
 1177    exists_directory(Dir),
 1178    !.
 1179'$make_config_dir'(Dir) :-
 1180    nb_current('$create_search_directories', true),
 1181    file_directory_name(Dir, Parent),
 1182    '$my_file'(Parent),
 1183    catch(make_directory(Dir), _, fail).
 1184
 1185'$ensure_slash'(Dir, DirS) :-
 1186    (   sub_atom(Dir, _, _, 0, /)
 1187    ->  DirS = Dir
 1188    ;   atom_concat(Dir, /, DirS)
 1189    ).
 1190
 1191:- dynamic '$ext_lib_dirs'/1. 1192:- volatile '$ext_lib_dirs'/1. 1193
 1194'$ext_library_directory'(Dir) :-
 1195    '$ext_lib_dirs'(Dirs),
 1196    !,
 1197    '$member'(Dir, Dirs).
 1198'$ext_library_directory'(Dir) :-
 1199    current_prolog_flag(home, Home),
 1200    atom_concat(Home, '/library/ext/*', Pattern),
 1201    expand_file_name(Pattern, Dirs0),
 1202    '$include'(exists_directory, Dirs0, Dirs),
 1203    asserta('$ext_lib_dirs'(Dirs)),
 1204    '$member'(Dir, Dirs).
 $expand_file_search_path(+Spec, -Expanded, +Cond) is nondet
 1209'$expand_file_search_path'(Spec, Expanded, Cond) :-
 1210    '$option'(access(Access), Cond),
 1211    memberchk(Access, [write,append]),
 1212    !,
 1213    setup_call_cleanup(
 1214	nb_setval('$create_search_directories', true),
 1215	expand_file_search_path(Spec, Expanded),
 1216	nb_delete('$create_search_directories')).
 1217'$expand_file_search_path'(Spec, Expanded, _Cond) :-
 1218    expand_file_search_path(Spec, Expanded).
 expand_file_search_path(+Spec, -Expanded) is nondet
Expand a search path. The system uses depth-first search upto a specified depth. If this depth is exceeded an exception is raised. TBD: bread-first search?
 1226expand_file_search_path(Spec, Expanded) :-
 1227    catch('$expand_file_search_path'(Spec, Expanded, 0, []),
 1228	  loop(Used),
 1229	  throw(error(loop_error(Spec), file_search(Used)))).
 1230
 1231'$expand_file_search_path'(Spec, Expanded, N, Used) :-
 1232    functor(Spec, Alias, 1),
 1233    !,
 1234    user:file_search_path(Alias, Exp0),
 1235    NN is N + 1,
 1236    (   NN > 16
 1237    ->  throw(loop(Used))
 1238    ;   true
 1239    ),
 1240    '$expand_file_search_path'(Exp0, Exp1, NN, [Alias=Exp0|Used]),
 1241    arg(1, Spec, Segments),
 1242    '$segments_to_atom'(Segments, File),
 1243    '$make_path'(Exp1, File, Expanded).
 1244'$expand_file_search_path'(Spec, Path, _, _) :-
 1245    '$segments_to_atom'(Spec, Path).
 1246
 1247'$make_path'(Dir, '.', Path) :-
 1248    !,
 1249    Path = Dir.
 1250'$make_path'(Dir, File, Path) :-
 1251    sub_atom(Dir, _, _, 0, /),
 1252    !,
 1253    atom_concat(Dir, File, Path).
 1254'$make_path'(Dir, File, Path) :-
 1255    atomic_list_concat([Dir, /, File], Path).
 1256
 1257
 1258		/********************************
 1259		*         FILE CHECKING         *
 1260		*********************************/
 absolute_file_name(+Term, -AbsoluteFile, +Options) is nondet
Translate path-specifier into a full path-name. This predicate originates from Quintus was introduced in SWI-Prolog very early and has re-appeared in SICStus 3.9.0, where they changed argument order and added some options. We addopted the SICStus argument order, but still accept the original argument order for compatibility reasons.
 1271absolute_file_name(Spec, Options, Path) :-
 1272    '$is_options'(Options),
 1273    \+ '$is_options'(Path),
 1274    !,
 1275    '$absolute_file_name'(Spec, Path, Options).
 1276absolute_file_name(Spec, Path, Options) :-
 1277    '$absolute_file_name'(Spec, Path, Options).
 1278
 1279'$absolute_file_name'(Spec, Path, Options0) :-
 1280    '$options_dict'(Options0, Options),
 1281		    % get the valid extensions
 1282    (   '$select_option'(extensions(Exts), Options, Options1)
 1283    ->  '$must_be'(list, Exts)
 1284    ;   '$option'(file_type(Type), Options)
 1285    ->  '$must_be'(atom, Type),
 1286	'$file_type_extensions'(Type, Exts),
 1287	Options1 = Options
 1288    ;   Options1 = Options,
 1289	Exts = ['']
 1290    ),
 1291    '$canonicalise_extensions'(Exts, Extensions),
 1292		    % unless specified otherwise, ask regular file
 1293    (   (   nonvar(Type)
 1294	;   '$option'(access(none), Options, none)
 1295	)
 1296    ->  Options2 = Options1
 1297    ;   '$merge_options'(_{file_type:regular}, Options1, Options2)
 1298    ),
 1299		    % Det or nondet?
 1300    (   '$select_option'(solutions(Sols), Options2, Options3)
 1301    ->  '$must_be'(oneof(atom, solutions, [first,all]), Sols)
 1302    ;   Sols = first,
 1303	Options3 = Options2
 1304    ),
 1305		    % Errors or not?
 1306    (   '$select_option'(file_errors(FileErrors), Options3, Options4)
 1307    ->  '$must_be'(oneof(atom, file_errors, [error,fail]), FileErrors)
 1308    ;   FileErrors = error,
 1309	Options4 = Options3
 1310    ),
 1311		    % Expand shell patterns?
 1312    (   atomic(Spec),
 1313	'$select_option'(expand(Expand), Options4, Options5),
 1314	'$must_be'(boolean, Expand)
 1315    ->  expand_file_name(Spec, List),
 1316	'$member'(Spec1, List)
 1317    ;   Spec1 = Spec,
 1318	Options5 = Options4
 1319    ),
 1320		    % Search for files
 1321    (   Sols == first
 1322    ->  (   '$chk_file'(Spec1, Extensions, Options5, true, Path)
 1323	->  !       % also kill choice point of expand_file_name/2
 1324	;   (   FileErrors == fail
 1325	    ->  fail
 1326	    ;   '$current_module'('$bags', _File),
 1327		findall(P,
 1328			'$chk_file'(Spec1, Extensions, [access(exist)],
 1329				    false, P),
 1330			Candidates),
 1331		'$abs_file_error'(Spec, Candidates, Options5)
 1332	    )
 1333	)
 1334    ;   '$chk_file'(Spec1, Extensions, Options5, false, Path)
 1335    ).
 1336
 1337'$abs_file_error'(Spec, Candidates, Conditions) :-
 1338    '$member'(F, Candidates),
 1339    '$member'(C, Conditions),
 1340    '$file_condition'(C),
 1341    '$file_error'(C, Spec, F, E, Comment),
 1342    !,
 1343    throw(error(E, context(_, Comment))).
 1344'$abs_file_error'(Spec, _, _) :-
 1345    '$existence_error'(source_sink, Spec).
 1346
 1347'$file_error'(file_type(directory), Spec, File, Error, Comment) :-
 1348    \+ exists_directory(File),
 1349    !,
 1350    Error = existence_error(directory, Spec),
 1351    Comment = not_a_directory(File).
 1352'$file_error'(file_type(_), Spec, File, Error, Comment) :-
 1353    exists_directory(File),
 1354    !,
 1355    Error = existence_error(file, Spec),
 1356    Comment = directory(File).
 1357'$file_error'(access(OneOrList), Spec, File, Error, _) :-
 1358    '$one_or_member'(Access, OneOrList),
 1359    \+ access_file(File, Access),
 1360    Error = permission_error(Access, source_sink, Spec).
 1361
 1362'$one_or_member'(Elem, List) :-
 1363    is_list(List),
 1364    !,
 1365    '$member'(Elem, List).
 1366'$one_or_member'(Elem, Elem).
 1367
 1368'$file_type_extensions'(Type, Exts) :-
 1369    '$current_module'('$bags', _File),
 1370    !,
 1371    findall(Ext, user:prolog_file_type(Ext, Type), Exts0),
 1372    (   Exts0 == [],
 1373	\+ '$ft_no_ext'(Type)
 1374    ->  '$domain_error'(file_type, Type)
 1375    ;   true
 1376    ),
 1377    '$append'(Exts0, [''], Exts).
 1378'$file_type_extensions'(prolog, [pl, '']). % findall is not yet defined ...
 1379
 1380'$ft_no_ext'(txt).
 1381'$ft_no_ext'(executable).
 1382'$ft_no_ext'(directory).
 1383'$ft_no_ext'(regular).
 user:prolog_file_type(?Extension, ?Type)
Define type of file based on the extension. This is used by absolute_file_name/3 and may be used to extend the list of extensions used for some type.

Note that qlf must be last when searching for Prolog files. Otherwise use_module/1 will consider the file as not-loaded because the .qlf file is not the loaded file. Must be fixed elsewhere.

 1396:- multifile(user:prolog_file_type/2). 1397:- dynamic(user:prolog_file_type/2). 1398
 1399user:prolog_file_type(pl,       prolog).
 1400user:prolog_file_type(prolog,   prolog).
 1401user:prolog_file_type(qlf,      prolog).
 1402user:prolog_file_type(pl,       source).
 1403user:prolog_file_type(prolog,   source).
 1404user:prolog_file_type(qlf,      qlf).
 1405user:prolog_file_type(Ext,      executable) :-
 1406    current_prolog_flag(shared_object_extension, Ext).
 1407user:prolog_file_type(dylib,    executable) :-
 1408    current_prolog_flag(apple,  true).
 $chk_file(+Spec, +Extensions, +Cond, +UseCache, -FullName)
File is a specification of a Prolog source file. Return the full path of the file.
 1415'$chk_file'(Spec, _Extensions, _Cond, _Cache, _FullName) :-
 1416    \+ ground(Spec),
 1417    !,
 1418    '$instantiation_error'(Spec).
 1419'$chk_file'(Spec, Extensions, Cond, Cache, FullName) :-
 1420    compound(Spec),
 1421    functor(Spec, _, 1),
 1422    !,
 1423    '$relative_to'(Cond, cwd, CWD),
 1424    '$chk_alias_file'(Spec, Extensions, Cond, Cache, CWD, FullName).
 1425'$chk_file'(Segments, Ext, Cond, Cache, FullName) :-    % allow a/b/...
 1426    \+ atomic(Segments),
 1427    !,
 1428    '$segments_to_atom'(Segments, Atom),
 1429    '$chk_file'(Atom, Ext, Cond, Cache, FullName).
 1430'$chk_file'(File, Exts, Cond, _, FullName) :-           % Absolute files
 1431    is_absolute_file_name(File),
 1432    !,
 1433    '$extend_file'(File, Exts, Extended),
 1434    '$file_conditions'(Cond, Extended),
 1435    '$absolute_file_name'(Extended, FullName).
 1436'$chk_file'(File, Exts, Cond, _, FullName) :-           % Explicit relative_to
 1437    '$option'(relative_to(_), Cond),
 1438    !,
 1439    '$relative_to'(Cond, none, Dir),
 1440    '$chk_file_relative_to'(File, Exts, Cond, Dir, FullName).
 1441'$chk_file'(File, Exts, Cond, _Cache, FullName) :-      % From source
 1442    source_location(ContextFile, _Line),
 1443    !,
 1444    (   file_directory_name(ContextFile, Dir),
 1445        '$chk_file_relative_to'(File, Exts, Cond, Dir, FullName)
 1446    *-> true
 1447    ;   current_prolog_flag(source_search_working_directory, true),
 1448	'$extend_file'(File, Exts, Extended),
 1449	'$file_conditions'(Cond, Extended),
 1450	'$absolute_file_name'(Extended, FullName),
 1451        '$print_message'(warning,
 1452                         deprecated(source_search_working_directory(
 1453                                        File, FullName)))
 1454    ).
 1455'$chk_file'(File, Exts, Cond, _Cache, FullName) :-      % Not loading source
 1456    '$extend_file'(File, Exts, Extended),
 1457    '$file_conditions'(Cond, Extended),
 1458    '$absolute_file_name'(Extended, FullName).
 1459
 1460'$chk_file_relative_to'(File, Exts, Cond, Dir, FullName) :-
 1461    atomic_list_concat([Dir, /, File], AbsFile),
 1462    '$extend_file'(AbsFile, Exts, Extended),
 1463    '$file_conditions'(Cond, Extended),
 1464    '$absolute_file_name'(Extended, FullName).
 1465
 1466
 1467'$segments_to_atom'(Atom, Atom) :-
 1468    atomic(Atom),
 1469    !.
 1470'$segments_to_atom'(Segments, Atom) :-
 1471    '$segments_to_list'(Segments, List, []),
 1472    !,
 1473    atomic_list_concat(List, /, Atom).
 1474
 1475'$segments_to_list'(A/B, H, T) :-
 1476    '$segments_to_list'(A, H, T0),
 1477    '$segments_to_list'(B, T0, T).
 1478'$segments_to_list'(A, [A|T], T) :-
 1479    atomic(A).
 $relative_to(+Condition, +Default, -Dir)
Determine the directory to work from. This can be specified explicitely using one or more relative_to(FileOrDir) options or implicitely relative to the working directory or current source-file.
 1489'$relative_to'(Conditions, Default, Dir) :-
 1490    (   '$option'(relative_to(FileOrDir), Conditions)
 1491    *-> (   exists_directory(FileOrDir)
 1492	->  Dir = FileOrDir
 1493	;   atom_concat(Dir, /, FileOrDir)
 1494	->  true
 1495	;   file_directory_name(FileOrDir, Dir)
 1496	)
 1497    ;   Default == cwd
 1498    ->  working_directory(Dir, Dir)
 1499    ;   Default == source
 1500    ->  source_location(ContextFile, _Line),
 1501	file_directory_name(ContextFile, Dir)
 1502    ).
 $chk_alias_file(+Spec, +Exts, +Cond, +Cache, +CWD, -FullFile) is nondet
 1507:- dynamic
 1508    '$search_path_file_cache'/3,    % SHA1, Time, Path
 1509    '$search_path_gc_time'/1.       % Time
 1510:- volatile
 1511    '$search_path_file_cache'/3,
 1512    '$search_path_gc_time'/1. 1513:- '$notransact'(('$search_path_file_cache'/3,
 1514                  '$search_path_gc_time'/1)). 1515
 1516:- create_prolog_flag(file_search_cache_time, 10, []). 1517
 1518'$chk_alias_file'(Spec, Exts, Cond, true, CWD, FullFile) :-
 1519    !,
 1520    findall(Exp, '$expand_file_search_path'(Spec, Exp, Cond), Expansions),
 1521    current_prolog_flag(emulated_dialect, Dialect),
 1522    Cache = cache(Exts, Cond, CWD, Expansions, Dialect),
 1523    variant_sha1(Spec+Cache, SHA1),
 1524    get_time(Now),
 1525    current_prolog_flag(file_search_cache_time, TimeOut),
 1526    (   '$search_path_file_cache'(SHA1, CachedTime, FullFile),
 1527	CachedTime > Now - TimeOut,
 1528	'$file_conditions'(Cond, FullFile)
 1529    ->  '$search_message'(file_search(cache(Spec, Cond), FullFile))
 1530    ;   '$member'(Expanded, Expansions),
 1531	'$extend_file'(Expanded, Exts, LibFile),
 1532	(   '$file_conditions'(Cond, LibFile),
 1533	    '$absolute_file_name'(LibFile, FullFile),
 1534	    '$cache_file_found'(SHA1, Now, TimeOut, FullFile)
 1535	->  '$search_message'(file_search(found(Spec, Cond), FullFile))
 1536	;   '$search_message'(file_search(tried(Spec, Cond), LibFile)),
 1537	    fail
 1538	)
 1539    ).
 1540'$chk_alias_file'(Spec, Exts, Cond, false, _CWD, FullFile) :-
 1541    '$expand_file_search_path'(Spec, Expanded, Cond),
 1542    '$extend_file'(Expanded, Exts, LibFile),
 1543    '$file_conditions'(Cond, LibFile),
 1544    '$absolute_file_name'(LibFile, FullFile).
 1545
 1546'$cache_file_found'(_, _, TimeOut, _) :-
 1547    TimeOut =:= 0,
 1548    !.
 1549'$cache_file_found'(SHA1, Now, TimeOut, FullFile) :-
 1550    '$search_path_file_cache'(SHA1, Saved, FullFile),
 1551    !,
 1552    (   Now - Saved < TimeOut/2
 1553    ->  true
 1554    ;   retractall('$search_path_file_cache'(SHA1, _, _)),
 1555	asserta('$search_path_file_cache'(SHA1, Now, FullFile))
 1556    ).
 1557'$cache_file_found'(SHA1, Now, TimeOut, FullFile) :-
 1558    'gc_file_search_cache'(TimeOut),
 1559    asserta('$search_path_file_cache'(SHA1, Now, FullFile)).
 1560
 1561'gc_file_search_cache'(TimeOut) :-
 1562    get_time(Now),
 1563    '$search_path_gc_time'(Last),
 1564    Now-Last < TimeOut/2,
 1565    !.
 1566'gc_file_search_cache'(TimeOut) :-
 1567    get_time(Now),
 1568    retractall('$search_path_gc_time'(_)),
 1569    assertz('$search_path_gc_time'(Now)),
 1570    Before is Now - TimeOut,
 1571    (   '$search_path_file_cache'(SHA1, Cached, FullFile),
 1572	Cached < Before,
 1573	retractall('$search_path_file_cache'(SHA1, Cached, FullFile)),
 1574	fail
 1575    ;   true
 1576    ).
 1577
 1578
 1579'$search_message'(Term) :-
 1580    current_prolog_flag(verbose_file_search, true),
 1581    !,
 1582    print_message(informational, Term).
 1583'$search_message'(_).
 $file_conditions(+Condition, +Path)
Verify Path satisfies Condition.
 1590'$file_conditions'(List, File) :-
 1591    is_list(List),
 1592    !,
 1593    \+ ( '$member'(C, List),
 1594	 '$file_condition'(C),
 1595	 \+ '$file_condition'(C, File)
 1596       ).
 1597'$file_conditions'(Map, File) :-
 1598    \+ (  get_dict(Key, Map, Value),
 1599	  C =.. [Key,Value],
 1600	  '$file_condition'(C),
 1601	 \+ '$file_condition'(C, File)
 1602       ).
 1603
 1604'$file_condition'(file_type(directory), File) :-
 1605    !,
 1606    exists_directory(File).
 1607'$file_condition'(file_type(_), File) :-
 1608    !,
 1609    \+ exists_directory(File).
 1610'$file_condition'(access(Accesses), File) :-
 1611    !,
 1612    \+ (  '$one_or_member'(Access, Accesses),
 1613	  \+ access_file(File, Access)
 1614       ).
 1615
 1616'$file_condition'(exists).
 1617'$file_condition'(file_type(_)).
 1618'$file_condition'(access(_)).
 1619
 1620'$extend_file'(File, Exts, FileEx) :-
 1621    '$ensure_extensions'(Exts, File, Fs),
 1622    '$list_to_set'(Fs, FsSet),
 1623    '$member'(FileEx, FsSet).
 1624
 1625'$ensure_extensions'([], _, []).
 1626'$ensure_extensions'([E|E0], F, [FE|E1]) :-
 1627    file_name_extension(F, E, FE),
 1628    '$ensure_extensions'(E0, F, E1).
 $list_to_set(+List, -Set) is det
Turn list into a set, keeping the left-most copy of duplicate elements. Copied from library(lists).
 1635'$list_to_set'(List, Set) :-
 1636    '$number_list'(List, 1, Numbered),
 1637    sort(1, @=<, Numbered, ONum),
 1638    '$remove_dup_keys'(ONum, NumSet),
 1639    sort(2, @=<, NumSet, ONumSet),
 1640    '$pairs_keys'(ONumSet, Set).
 1641
 1642'$number_list'([], _, []).
 1643'$number_list'([H|T0], N, [H-N|T]) :-
 1644    N1 is N+1,
 1645    '$number_list'(T0, N1, T).
 1646
 1647'$remove_dup_keys'([], []).
 1648'$remove_dup_keys'([H|T0], [H|T]) :-
 1649    H = V-_,
 1650    '$remove_same_key'(T0, V, T1),
 1651    '$remove_dup_keys'(T1, T).
 1652
 1653'$remove_same_key'([V1-_|T0], V, T) :-
 1654    V1 == V,
 1655    !,
 1656    '$remove_same_key'(T0, V, T).
 1657'$remove_same_key'(L, _, L).
 1658
 1659'$pairs_keys'([], []).
 1660'$pairs_keys'([K-_|T0], [K|T]) :-
 1661    '$pairs_keys'(T0, T).
 1662
 1663'$pairs_values'([], []).
 1664'$pairs_values'([_-V|T0], [V|T]) :-
 1665    '$pairs_values'(T0, T).
 1666
 1667/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 1668Canonicalise the extension list. Old SWI-Prolog   require  `.pl', etc, which
 1669the Quintus compatibility  requests  `pl'.   This  layer  canonicalises  all
 1670extensions to .ext
 1671- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 1672
 1673'$canonicalise_extensions'([], []) :- !.
 1674'$canonicalise_extensions'([H|T], [CH|CT]) :-
 1675    !,
 1676    '$must_be'(atom, H),
 1677    '$canonicalise_extension'(H, CH),
 1678    '$canonicalise_extensions'(T, CT).
 1679'$canonicalise_extensions'(E, [CE]) :-
 1680    '$canonicalise_extension'(E, CE).
 1681
 1682'$canonicalise_extension'('', '') :- !.
 1683'$canonicalise_extension'(DotAtom, DotAtom) :-
 1684    sub_atom(DotAtom, 0, _, _, '.'),
 1685    !.
 1686'$canonicalise_extension'(Atom, DotAtom) :-
 1687    atom_concat('.', Atom, DotAtom).
 1688
 1689
 1690		/********************************
 1691		*            CONSULT            *
 1692		*********************************/
 1693
 1694:- dynamic
 1695    user:library_directory/1,
 1696    user:prolog_load_file/2. 1697:- multifile
 1698    user:library_directory/1,
 1699    user:prolog_load_file/2. 1700
 1701:- prompt(_, '|: '). 1702
 1703:- thread_local
 1704    '$compilation_mode_store'/1,    % database, wic, qlf
 1705    '$directive_mode_store'/1.      % database, wic, qlf
 1706:- volatile
 1707    '$compilation_mode_store'/1,
 1708    '$directive_mode_store'/1. 1709:- '$notransact'(('$compilation_mode_store'/1,
 1710                  '$directive_mode_store'/1)). 1711
 1712'$compilation_mode'(Mode) :-
 1713    (   '$compilation_mode_store'(Val)
 1714    ->  Mode = Val
 1715    ;   Mode = database
 1716    ).
 1717
 1718'$set_compilation_mode'(Mode) :-
 1719    retractall('$compilation_mode_store'(_)),
 1720    assertz('$compilation_mode_store'(Mode)).
 1721
 1722'$compilation_mode'(Old, New) :-
 1723    '$compilation_mode'(Old),
 1724    (   New == Old
 1725    ->  true
 1726    ;   '$set_compilation_mode'(New)
 1727    ).
 1728
 1729'$directive_mode'(Mode) :-
 1730    (   '$directive_mode_store'(Val)
 1731    ->  Mode = Val
 1732    ;   Mode = database
 1733    ).
 1734
 1735'$directive_mode'(Old, New) :-
 1736    '$directive_mode'(Old),
 1737    (   New == Old
 1738    ->  true
 1739    ;   '$set_directive_mode'(New)
 1740    ).
 1741
 1742'$set_directive_mode'(Mode) :-
 1743    retractall('$directive_mode_store'(_)),
 1744    assertz('$directive_mode_store'(Mode)).
 $compilation_level(-Level) is det
True when Level reflects the nesting in files compiling other files. 0 if no files are being loaded.
 1752'$compilation_level'(Level) :-
 1753    '$input_context'(Stack),
 1754    '$compilation_level'(Stack, Level).
 1755
 1756'$compilation_level'([], 0).
 1757'$compilation_level'([Input|T], Level) :-
 1758    (   arg(1, Input, see)
 1759    ->  '$compilation_level'(T, Level)
 1760    ;   '$compilation_level'(T, Level0),
 1761	Level is Level0+1
 1762    ).
 compiling
Is true if SWI-Prolog is generating a state or qlf file or executes a `call' directive while doing this.
 1770compiling :-
 1771    \+ (   '$compilation_mode'(database),
 1772	   '$directive_mode'(database)
 1773       ).
 1774
 1775:- meta_predicate
 1776    '$ifcompiling'(0). 1777
 1778'$ifcompiling'(G) :-
 1779    (   '$compilation_mode'(database)
 1780    ->  true
 1781    ;   call(G)
 1782    ).
 1783
 1784		/********************************
 1785		*         READ SOURCE           *
 1786		*********************************/
 $load_msg_level(+Action, +NestingLevel, -StartVerbose, -EndVerbose)
 1790'$load_msg_level'(Action, Nesting, Start, Done) :-
 1791    '$update_autoload_level'([], 0),
 1792    !,
 1793    current_prolog_flag(verbose_load, Type0),
 1794    '$load_msg_compat'(Type0, Type),
 1795    (   '$load_msg_level'(Action, Nesting, Type, Start, Done)
 1796    ->  true
 1797    ).
 1798'$load_msg_level'(_, _, silent, silent).
 1799
 1800'$load_msg_compat'(true, normal) :- !.
 1801'$load_msg_compat'(false, silent) :- !.
 1802'$load_msg_compat'(X, X).
 1803
 1804'$load_msg_level'(load_file,    _, full,   informational, informational).
 1805'$load_msg_level'(include_file, _, full,   informational, informational).
 1806'$load_msg_level'(load_file,    _, normal, silent,        informational).
 1807'$load_msg_level'(include_file, _, normal, silent,        silent).
 1808'$load_msg_level'(load_file,    0, brief,  silent,        informational).
 1809'$load_msg_level'(load_file,    _, brief,  silent,        silent).
 1810'$load_msg_level'(include_file, _, brief,  silent,        silent).
 1811'$load_msg_level'(load_file,    _, silent, silent,        silent).
 1812'$load_msg_level'(include_file, _, silent, silent,        silent).
 $source_term(+From, -Read, -RLayout, -Term, -TLayout, -Stream, +Options) is nondet
Read Prolog terms from the input From. Terms are returned on backtracking. Associated resources (i.e., streams) are closed due to setup_call_cleanup/3.
Arguments:
From- is either a term stream(Id, Stream) or a file specification.
Read- is the raw term as read from the input.
Term- is the term after term-expansion. If a term is expanded into the empty list, this is returned too. This is required to be able to return the raw term in Read
Stream- is the stream from which Read is read
Options- provides additional options:
encoding(Enc)
Encoding used to open From
syntax_errors(+ErrorMode)
process_comments(+Boolean)
term_position(-Pos)
 1835'$source_term'(From, Read, RLayout, Term, TLayout, Stream, Options) :-
 1836    '$source_term'(From, Read, RLayout, Term, TLayout, Stream, [], Options),
 1837    (   Term == end_of_file
 1838    ->  !, fail
 1839    ;   Term \== begin_of_file
 1840    ).
 1841
 1842'$source_term'(Input, _,_,_,_,_,_,_) :-
 1843    \+ ground(Input),
 1844    !,
 1845    '$instantiation_error'(Input).
 1846'$source_term'(stream(Id, In, Opts),
 1847	       Read, RLayout, Term, TLayout, Stream, Parents, Options) :-
 1848    !,
 1849    '$record_included'(Parents, Id, Id, 0.0, Message),
 1850    setup_call_cleanup(
 1851	'$open_source'(stream(Id, In, Opts), In, State, Parents, Options),
 1852	'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream,
 1853			[Id|Parents], Options),
 1854	'$close_source'(State, Message)).
 1855'$source_term'(File,
 1856	       Read, RLayout, Term, TLayout, Stream, Parents, Options) :-
 1857    absolute_file_name(File, Path,
 1858		       [ file_type(prolog),
 1859			 access(read)
 1860		       ]),
 1861    time_file(Path, Time),
 1862    '$record_included'(Parents, File, Path, Time, Message),
 1863    setup_call_cleanup(
 1864	'$open_source'(Path, In, State, Parents, Options),
 1865	'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream,
 1866			[Path|Parents], Options),
 1867	'$close_source'(State, Message)).
 1868
 1869:- thread_local
 1870    '$load_input'/2. 1871:- volatile
 1872    '$load_input'/2. 1873:- '$notransact'('$load_input'/2). 1874
 1875'$open_source'(stream(Id, In, Opts), In,
 1876	       restore(In, StreamState, Id, Ref, Opts), Parents, _Options) :-
 1877    !,
 1878    '$context_type'(Parents, ContextType),
 1879    '$push_input_context'(ContextType),
 1880    '$prepare_load_stream'(In, Id, StreamState),
 1881    asserta('$load_input'(stream(Id), In), Ref).
 1882'$open_source'(Path, In, close(In, Path, Ref), Parents, Options) :-
 1883    '$context_type'(Parents, ContextType),
 1884    '$push_input_context'(ContextType),
 1885    '$open_source'(Path, In, Options),
 1886    '$set_encoding'(In, Options),
 1887    asserta('$load_input'(Path, In), Ref).
 1888
 1889'$context_type'([], load_file) :- !.
 1890'$context_type'(_, include).
 1891
 1892:- multifile prolog:open_source_hook/3. 1893
 1894'$open_source'(Path, In, Options) :-
 1895    prolog:open_source_hook(Path, In, Options),
 1896    !.
 1897'$open_source'(Path, In, _Options) :-
 1898    open(Path, read, In).
 1899
 1900'$close_source'(close(In, _Id, Ref), Message) :-
 1901    erase(Ref),
 1902    call_cleanup(
 1903	close(In),
 1904	'$pop_input_context'),
 1905    '$close_message'(Message).
 1906'$close_source'(restore(In, StreamState, _Id, Ref, Opts), Message) :-
 1907    erase(Ref),
 1908    call_cleanup(
 1909	'$restore_load_stream'(In, StreamState, Opts),
 1910	'$pop_input_context'),
 1911    '$close_message'(Message).
 1912
 1913'$close_message'(message(Level, Msg)) :-
 1914    !,
 1915    '$print_message'(Level, Msg).
 1916'$close_message'(_).
 $term_in_file(+In, -Read, -RLayout, -Term, -TLayout, -Stream, +Parents, +Options) is multi
True when Term is an expanded term from In. Read is a raw term (before term-expansion). Stream is the actual stream, which starts at In, but may change due to processing included files.
See also
- '$source_term'/8 for details.
 1928'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, Parents, Options) :-
 1929    Parents \= [_,_|_],
 1930    (   '$load_input'(_, Input)
 1931    ->  stream_property(Input, file_name(File))
 1932    ),
 1933    '$set_source_location'(File, 0),
 1934    '$expanded_term'(In,
 1935		     begin_of_file, 0-0, Read, RLayout, Term, TLayout,
 1936		     Stream, Parents, Options).
 1937'$term_in_file'(In, Read, RLayout, Term, TLayout, Stream, Parents, Options) :-
 1938    '$skip_script_line'(In, Options),
 1939    '$read_clause_options'(Options, ReadOptions),
 1940    '$repeat_and_read_error_mode'(ErrorMode),
 1941      read_clause(In, Raw,
 1942		  [ syntax_errors(ErrorMode),
 1943		    variable_names(Bindings),
 1944		    term_position(Pos),
 1945		    subterm_positions(RawLayout)
 1946		  | ReadOptions
 1947		  ]),
 1948      b_setval('$term_position', Pos),
 1949      b_setval('$variable_names', Bindings),
 1950      (   Raw == end_of_file
 1951      ->  !,
 1952	  (   Parents = [_,_|_]     % Included file
 1953	  ->  fail
 1954	  ;   '$expanded_term'(In,
 1955			       Raw, RawLayout, Read, RLayout, Term, TLayout,
 1956			       Stream, Parents, Options)
 1957	  )
 1958      ;   '$expanded_term'(In, Raw, RawLayout, Read, RLayout, Term, TLayout,
 1959			   Stream, Parents, Options)
 1960      ).
 1961
 1962'$read_clause_options'([], []).
 1963'$read_clause_options'([H|T0], List) :-
 1964    (   '$read_clause_option'(H)
 1965    ->  List = [H|T]
 1966    ;   List = T
 1967    ),
 1968    '$read_clause_options'(T0, T).
 1969
 1970'$read_clause_option'(syntax_errors(_)).
 1971'$read_clause_option'(term_position(_)).
 1972'$read_clause_option'(process_comment(_)).
 $repeat_and_read_error_mode(-Mode) is multi
Calls repeat/1 and return the error mode. The implemenation is like this because during part of the boot cycle expand.pl is not yet loaded.
 1980'$repeat_and_read_error_mode'(Mode) :-
 1981    (   current_predicate('$including'/0)
 1982    ->  repeat,
 1983	(   '$including'
 1984	->  Mode = dec10
 1985	;   Mode = quiet
 1986	)
 1987    ;   Mode = dec10,
 1988	repeat
 1989    ).
 1990
 1991
 1992'$expanded_term'(In, Raw, RawLayout, Read, RLayout, Term, TLayout,
 1993		 Stream, Parents, Options) :-
 1994    E = error(_,_),
 1995    catch('$expand_term'(Raw, RawLayout, Expanded, ExpandedLayout), E,
 1996	  '$print_message_fail'(E)),
 1997    (   Expanded \== []
 1998    ->  '$expansion_member'(Expanded, ExpandedLayout, Term1, Layout1)
 1999    ;   Term1 = Expanded,
 2000	Layout1 = ExpandedLayout
 2001    ),
 2002    (   nonvar(Term1), Term1 = (:-Directive), nonvar(Directive)
 2003    ->  (   Directive = include(File),
 2004	    '$current_source_module'(Module),
 2005	    '$valid_directive'(Module:include(File))
 2006	->  stream_property(In, encoding(Enc)),
 2007	    '$add_encoding'(Enc, Options, Options1),
 2008	    '$source_term'(File, Read, RLayout, Term, TLayout,
 2009			   Stream, Parents, Options1)
 2010	;   Directive = encoding(Enc)
 2011	->  set_stream(In, encoding(Enc)),
 2012	    fail
 2013	;   Term = Term1,
 2014	    Stream = In,
 2015	    Read = Raw
 2016	)
 2017    ;   Term = Term1,
 2018	TLayout = Layout1,
 2019	Stream = In,
 2020	Read = Raw,
 2021	RLayout = RawLayout
 2022    ).
 2023
 2024'$expansion_member'(Var, Layout, Var, Layout) :-
 2025    var(Var),
 2026    !.
 2027'$expansion_member'([], _, _, _) :- !, fail.
 2028'$expansion_member'(List, ListLayout, Term, Layout) :-
 2029    is_list(List),
 2030    !,
 2031    (   var(ListLayout)
 2032    ->  '$member'(Term, List)
 2033    ;   is_list(ListLayout)
 2034    ->  '$member_rep2'(Term, Layout, List, ListLayout)
 2035    ;   Layout = ListLayout,
 2036	'$member'(Term, List)
 2037    ).
 2038'$expansion_member'(X, Layout, X, Layout).
 2039
 2040% pairwise member, repeating last element of the second
 2041% list.
 2042
 2043'$member_rep2'(H1, H2, [H1|_], [H2|_]).
 2044'$member_rep2'(H1, H2, [_|T1], [T2]) :-
 2045    !,
 2046    '$member_rep2'(H1, H2, T1, [T2]).
 2047'$member_rep2'(H1, H2, [_|T1], [_|T2]) :-
 2048    '$member_rep2'(H1, H2, T1, T2).
 $add_encoding(+Enc, +Options0, -Options)
 2052'$add_encoding'(Enc, Options0, Options) :-
 2053    (   Options0 = [encoding(Enc)|_]
 2054    ->  Options = Options0
 2055    ;   Options = [encoding(Enc)|Options0]
 2056    ).
 2057
 2058
 2059:- multifile
 2060    '$included'/4.                  % Into, Line, File, LastModified
 2061:- dynamic
 2062    '$included'/4.
 $record_included(+Parents, +File, +Path, +Time, -Message) is det
Record that we included File into the head of Parents. This is troublesome when creating a QLF file because this may happen before we opened the QLF file (and we do not yet know how to open the file because we do not yet know whether this is a module file or not).

I think that the only sensible solution is to have a special statement for this, that may appear both inside and outside QLF `parts'.

 2076'$record_included'([Parent|Parents], File, Path, Time,
 2077		   message(DoneMsgLevel,
 2078			   include_file(done(Level, file(File, Path))))) :-
 2079    source_location(SrcFile, Line),
 2080    !,
 2081    '$compilation_level'(Level),
 2082    '$load_msg_level'(include_file, Level, StartMsgLevel, DoneMsgLevel),
 2083    '$print_message'(StartMsgLevel,
 2084		     include_file(start(Level,
 2085					file(File, Path)))),
 2086    '$last'([Parent|Parents], Owner),
 2087    '$store_admin_clause'(
 2088        system:'$included'(Parent, Line, Path, Time),
 2089        _, Owner, SrcFile:Line, database),
 2090    '$ifcompiling'('$qlf_include'(Owner, Parent, Line, Path, Time)).
 2091'$record_included'(_, _, _, _, true).
 $master_file(+File, -MasterFile)
Find the primary load file from included files.
 2097'$master_file'(File, MasterFile) :-
 2098    '$included'(MasterFile0, _Line, File, _Time),
 2099    !,
 2100    '$master_file'(MasterFile0, MasterFile).
 2101'$master_file'(File, File).
 2102
 2103
 2104'$skip_script_line'(_In, Options) :-
 2105    '$option'(check_script(false), Options),
 2106    !.
 2107'$skip_script_line'(In, _Options) :-
 2108    (   peek_char(In, #)
 2109    ->  skip(In, 10)
 2110    ;   true
 2111    ).
 2112
 2113'$set_encoding'(Stream, Options) :-
 2114    '$option'(encoding(Enc), Options),
 2115    !,
 2116    Enc \== default,
 2117    set_stream(Stream, encoding(Enc)).
 2118'$set_encoding'(_, _).
 2119
 2120
 2121'$prepare_load_stream'(In, Id, state(HasName,HasPos)) :-
 2122    (   stream_property(In, file_name(_))
 2123    ->  HasName = true,
 2124	(   stream_property(In, position(_))
 2125	->  HasPos = true
 2126	;   HasPos = false,
 2127	    set_stream(In, record_position(true))
 2128	)
 2129    ;   HasName = false,
 2130	set_stream(In, file_name(Id)),
 2131	(   stream_property(In, position(_))
 2132	->  HasPos = true
 2133	;   HasPos = false,
 2134	    set_stream(In, record_position(true))
 2135	)
 2136    ).
 2137
 2138'$restore_load_stream'(In, _State, Options) :-
 2139    '$option'(close(true), Options),
 2140    !,
 2141    close(In).
 2142'$restore_load_stream'(In, state(HasName, HasPos), _Options) :-
 2143    (   HasName == false
 2144    ->  set_stream(In, file_name(''))
 2145    ;   true
 2146    ),
 2147    (   HasPos == false
 2148    ->  set_stream(In, record_position(false))
 2149    ;   true
 2150    ).
 2151
 2152
 2153		 /*******************************
 2154		 *          DERIVED FILES       *
 2155		 *******************************/
 2156
 2157:- dynamic
 2158    '$derived_source_db'/3.         % Loaded, DerivedFrom, Time
 2159
 2160'$register_derived_source'(_, '-') :- !.
 2161'$register_derived_source'(Loaded, DerivedFrom) :-
 2162    retractall('$derived_source_db'(Loaded, _, _)),
 2163    time_file(DerivedFrom, Time),
 2164    assert('$derived_source_db'(Loaded, DerivedFrom, Time)).
 2165
 2166%       Auto-importing dynamic predicates is not very elegant and
 2167%       leads to problems with qsave_program/[1,2]
 2168
 2169'$derived_source'(Loaded, DerivedFrom, Time) :-
 2170    '$derived_source_db'(Loaded, DerivedFrom, Time).
 2171
 2172
 2173		/********************************
 2174		*       LOAD PREDICATES         *
 2175		*********************************/
 2176
 2177:- meta_predicate
 2178    ensure_loaded(:),
 2179    [:|+],
 2180    consult(:),
 2181    use_module(:),
 2182    use_module(:, +),
 2183    reexport(:),
 2184    reexport(:, +),
 2185    load_files(:),
 2186    load_files(:, +).
 ensure_loaded(+FileOrListOfFiles)
Load specified files, provided they where not loaded before. If the file is a module file import the public predicates into the context module.
 2194ensure_loaded(Files) :-
 2195    load_files(Files, [if(not_loaded)]).
 use_module(+FileOrListOfFiles)
Very similar to ensure_loaded/1, but insists on the loaded file to be a module file. If the file is already imported, but the public predicates are not yet imported into the context module, then do so.
 2204use_module(Files) :-
 2205    load_files(Files, [ if(not_loaded),
 2206			must_be_module(true)
 2207		      ]).
 use_module(+File, +ImportList)
As use_module/1, but takes only one file argument and imports only the specified predicates rather than all public predicates.
 2214use_module(File, Import) :-
 2215    load_files(File, [ if(not_loaded),
 2216		       must_be_module(true),
 2217		       imports(Import)
 2218		     ]).
 reexport(+Files)
As use_module/1, exporting all imported predicates.
 2224reexport(Files) :-
 2225    load_files(Files, [ if(not_loaded),
 2226			must_be_module(true),
 2227			reexport(true)
 2228		      ]).
 reexport(+File, +ImportList)
As use_module/1, re-exporting all imported predicates.
 2234reexport(File, Import) :-
 2235    load_files(File, [ if(not_loaded),
 2236		       must_be_module(true),
 2237		       imports(Import),
 2238		       reexport(true)
 2239		     ]).
 2240
 2241
 2242[X] :-
 2243    !,
 2244    consult(X).
 2245[M:F|R] :-
 2246    consult(M:[F|R]).
 2247
 2248consult(M:X) :-
 2249    X == user,
 2250    !,
 2251    flag('$user_consult', N, N+1),
 2252    NN is N + 1,
 2253    atom_concat('user://', NN, Id),
 2254    '$consult_user'(M:Id).
 2255consult(List) :-
 2256    load_files(List, [expand(true)]).
 $consult_user(:Id) is det
Handle ?- [user].. This is a separate predicate, such that we can easily wrap this for the browser version.
 2263'$consult_user'(Id) :-
 2264    load_files(Id, [stream(user_input), check_script(false), silent(false)]).
 load_files(:File, +Options)
Common entry for all the consult derivates. File is the raw user specified file specification, possibly tagged with the module.
 2271load_files(Files) :-
 2272    load_files(Files, []).
 2273load_files(Module:Files, Options) :-
 2274    '$must_be'(list, Options),
 2275    '$load_files'(Files, Module, Options).
 2276
 2277'$load_files'(X, _, _) :-
 2278    var(X),
 2279    !,
 2280    '$instantiation_error'(X).
 2281'$load_files'([], _, _) :- !.
 2282'$load_files'(Id, Module, Options) :-   % load_files(foo, [stream(In)])
 2283    '$option'(stream(_), Options),
 2284    !,
 2285    (   atom(Id)
 2286    ->  '$load_file'(Id, Module, Options)
 2287    ;   throw(error(type_error(atom, Id), _))
 2288    ).
 2289'$load_files'(List, Module, Options) :-
 2290    List = [_|_],
 2291    !,
 2292    '$must_be'(list, List),
 2293    '$load_file_list'(List, Module, Options).
 2294'$load_files'(File, Module, Options) :-
 2295    '$load_one_file'(File, Module, Options).
 2296
 2297'$load_file_list'([], _, _).
 2298'$load_file_list'([File|Rest], Module, Options) :-
 2299    E = error(_,_),
 2300    catch('$load_one_file'(File, Module, Options), E,
 2301	  '$print_message'(error, E)),
 2302    '$load_file_list'(Rest, Module, Options).
 2303
 2304
 2305'$load_one_file'(Spec, Module, Options) :-
 2306    atomic(Spec),
 2307    '$option'(expand(true), Options, false),
 2308    !,
 2309    expand_file_name(Spec, Expanded),
 2310    (   Expanded = [Load]
 2311    ->  true
 2312    ;   Load = Expanded
 2313    ),
 2314    '$load_files'(Load, Module, [expand(false)|Options]).
 2315'$load_one_file'(File, Module, Options) :-
 2316    strip_module(Module:File, Into, PlainFile),
 2317    '$load_file'(PlainFile, Into, Options).
 $noload(+Condition, +FullFile, +Options) is semidet
True of FullFile should not be loaded.
 2324'$noload'(true, _, _) :-
 2325    !,
 2326    fail.
 2327'$noload'(_, FullFile, _Options) :-
 2328    '$time_source_file'(FullFile, Time, system),
 2329    float(Time),
 2330    !.
 2331'$noload'(not_loaded, FullFile, _) :-
 2332    source_file(FullFile),
 2333    !.
 2334'$noload'(changed, Derived, _) :-
 2335    '$derived_source'(_FullFile, Derived, LoadTime),
 2336    time_file(Derived, Modified),
 2337    Modified @=< LoadTime,
 2338    !.
 2339'$noload'(changed, FullFile, Options) :-
 2340    '$time_source_file'(FullFile, LoadTime, user),
 2341    '$modified_id'(FullFile, Modified, Options),
 2342    Modified @=< LoadTime,
 2343    !.
 2344'$noload'(exists, File, Options) :-
 2345    '$noload'(changed, File, Options).
 $qlf_file(+Spec, +PlFile, -LoadFile, -Mode, +Options) is det
Determine how to load the source. LoadFile is the file to be loaded, Mode is how to load it. Mode is one of
compile
Normal source compilation
qcompile
Compile from source, creating a QLF file in the process
qload
Load from QLF file.
stream
Load from a stream. Content can be a source or QLF file.
Arguments:
Spec- is the original search specification
PlFile- is the resolved absolute path to the Prolog file.
 2364'$qlf_file'(Spec, _, Spec, stream, Options) :-
 2365    '$option'(stream(_), Options),      % stream: no choice
 2366    !.
 2367'$qlf_file'(Spec, FullFile, LoadFile, compile, _) :-
 2368    '$spec_extension'(Spec, Ext),       % user explicitly specified
 2369    (   user:prolog_file_type(Ext, qlf)
 2370    ->  absolute_file_name(Spec, LoadFile,
 2371                           [ file_type(qlf),
 2372                             access(read)
 2373                           ])
 2374    ;   user:prolog_file_type(Ext, prolog)
 2375    ->  LoadFile = FullFile
 2376    ),
 2377    !.
 2378'$qlf_file'(_, FullFile, FullFile, compile, _) :-
 2379    current_prolog_flag(source, true),
 2380    access_file(FullFile, read),
 2381    !.
 2382'$qlf_file'(Spec, FullFile, LoadFile, Mode, Options) :-
 2383    '$compilation_mode'(database),
 2384    file_name_extension(Base, PlExt, FullFile),
 2385    user:prolog_file_type(PlExt, prolog),
 2386    user:prolog_file_type(QlfExt, qlf),
 2387    file_name_extension(Base, QlfExt, QlfFile),
 2388    (   access_file(QlfFile, read),
 2389        (   '$qlf_out_of_date'(FullFile, QlfFile, Why)
 2390	->  (   access_file(QlfFile, write)
 2391	    ->  print_message(informational,
 2392			      qlf(recompile(Spec, FullFile, QlfFile, Why))),
 2393		Mode = qcompile,
 2394		LoadFile = FullFile
 2395	    ;   Why == old,
 2396		(   current_prolog_flag(home, PlHome),
 2397		    sub_atom(FullFile, 0, _, _, PlHome)
 2398		;   sub_atom(QlfFile, 0, _, _, 'res://')
 2399		)
 2400	    ->  print_message(silent,
 2401			      qlf(system_lib_out_of_date(Spec, QlfFile))),
 2402		Mode = qload,
 2403		LoadFile = QlfFile
 2404	    ;   print_message(warning,
 2405			      qlf(can_not_recompile(Spec, QlfFile, Why))),
 2406		Mode = compile,
 2407		LoadFile = FullFile
 2408	    )
 2409	;   Mode = qload,
 2410	    LoadFile = QlfFile
 2411	)
 2412    ->  !
 2413    ;   '$qlf_auto'(FullFile, QlfFile, Options)
 2414    ->  !, Mode = qcompile,
 2415	LoadFile = FullFile
 2416    ).
 2417'$qlf_file'(_, FullFile, FullFile, compile, _).
 $qlf_out_of_date(+PlFile, +QlfFile, -Why) is semidet
True if the QlfFile file is out-of-date because of Why. This predicate is the negation such that we can return the reason.

QlfFile is out of date if it is incompatible with this version or if one of the files it was compiled from changed. That is PlFile, but also the files PlFile consults or includes, which are compiled into QlfFile, and the files that qlf_dependency/2 declares. '$qlf_sources'/2 raises an exception if QlfFile is incompatible and otherwise lists these files, opening QlfFile only once. If QlfFile is incompatible, that is reported, also if a source changed, as it is the more serious problem.

 2433'$qlf_out_of_date'(PlFile, QlfFile, Why) :-
 2434    (   access_file(PlFile, read)
 2435    ->  Error = error(Formal,_),
 2436	catch('$qlf_sources'(QlfFile, Sources), Error, true),
 2437	(   nonvar(Formal)              % QlfFile is incompatible
 2438	->  Why = Error
 2439	;   time_file(QlfFile, QlfTime),
 2440	    '$qlf_sources_changed'(PlFile, Sources, QlfTime)
 2441	->  Why = old                   % a source changed
 2442	;   fail                        % QlfFile is up-to-date and ok
 2443	)
 2444    ;   fail                            % can not read .pl; try .qlf
 2445    ).
 $qlf_sources_changed(+PlFile, +Sources, +QlfTime) is semidet
True when PlFile or one of the other Sources of a .qlf file written at QlfTime changed. PlFile is asked explicitly as it may appear under another name in Sources. Sources that no longer exist are ignored.
 2454'$qlf_sources_changed'(PlFile, Sources, QlfTime) :-
 2455    '$qlf_source_changed'(PlFile, Sources, QlfTime),
 2456    !.
 2457'$qlf_sources_changed'(PlFile, Sources, QlfTime) :-
 2458    '$member'(Source, Sources),
 2459    arg(1, Source, File),
 2460    File \== PlFile,
 2461    '$qlf_source_changed'(File, Sources, QlfTime),
 2462    !.
 $qlf_source_changed(+File, +Sources, +QlfTime) is semidet
True when the content of File differs from the copy that was compiled into the .qlf file. The modification time is cheap to ask, but proves nothing: a tree that arrives by checkout, copy, unpack or install carries times of its own, in either direction and at the resolution of the file system it landed on. So, if the time says File may be newer, the hash the .qlf file records for File in Sources settles it.

If Sources records no hash for File -- the .qlf file was written by an older version, or File could not be read when it was compiled -- the times have the last word, as they had before.

Note that a file edited in the second its .qlf file was written has the time of that file, so the times do not say "may be newer" and the content is never asked. Loading every .pl file to find out would cost more than it is worth here; qlf_needs_rebuild/1 of library(prolog_qlfmake), which is what a build asks, does compare the content of every source.

 2485'$qlf_source_changed'(File, Sources, QlfTime) :-
 2486    catch(time_file(File, Time), error(_,_), fail),
 2487    Time > QlfTime,
 2488    (   '$member'(Source, Sources),
 2489	arg(1, Source, File),
 2490	arg(2, Source, Hash),
 2491	Hash =\= 0
 2492    ->  \+ '$file_hash'(File, Hash)
 2493    ;   true
 2494    ).
 $qlf_auto(+PlFile, +QlfFile, +Options) is semidet
True if we create QlfFile using qcompile/2. This is determined by the option qcompile(QlfMode) or, if this is not present, by the prolog_flag qcompile.
 2502:- create_prolog_flag(qcompile, false, [type(atom)]). 2503
 2504'$qlf_auto'(PlFile, QlfFile, Options) :-
 2505    (   '$option'(qcompile(QlfMode), Options)
 2506    ->  true
 2507    ;   current_prolog_flag(qcompile, QlfMode),
 2508	\+ '$in_system_dir'(PlFile)
 2509    ),
 2510    (   QlfMode == auto
 2511    ->  true
 2512    ;   QlfMode == large,
 2513	size_file(PlFile, Size),
 2514	Size > 100000
 2515    ),
 2516    access_file(QlfFile, write).
 2517
 2518'$in_system_dir'(PlFile) :-
 2519    current_prolog_flag(home, Home),
 2520    sub_atom(PlFile, 0, _, _, Home).
 2521
 2522'$spec_extension'(File, Ext) :-
 2523    atom(File),
 2524    !,
 2525    file_name_extension(_, Ext, File).
 2526'$spec_extension'(Spec, Ext) :-
 2527    compound(Spec),
 2528    arg(1, Spec, Arg),
 2529    '$segments_to_atom'(Arg, File),
 2530    file_name_extension(_, Ext, File).
 $load_file(+Spec, +ContextModule, +Options) is det
Load the file Spec into ContextModule controlled by Options. This wrapper deals with two cases before proceeding to the real loader:
 2542:- dynamic
 2543    '$resolved_source_path_db'/3.                % ?Spec, ?Dialect, ?Path
 2544:- '$notransact'('$resolved_source_path_db'/3). 2545
 2546'$load_file'(File, Module, Options) :-
 2547    '$error_count'(E0, W0),
 2548    '$load_file_e'(File, Module, Options),
 2549    '$error_count'(E1, W1),
 2550    Errors is E1-E0,
 2551    Warnings is W1-W0,
 2552    (   Errors+Warnings =:= 0
 2553    ->  true
 2554    ;   '$print_message'(silent, load_file_errors(File, Errors, Warnings))
 2555    ).
 2556
 2557:- if(current_prolog_flag(threads, true)). 2558'$error_count'(Errors, Warnings) :-
 2559    current_prolog_flag(threads, true),
 2560    !,
 2561    thread_self(Me),
 2562    thread_statistics(Me, errors, Errors),
 2563    thread_statistics(Me, warnings, Warnings).
 2564:- endif. 2565'$error_count'(Errors, Warnings) :-
 2566    statistics(errors, Errors),
 2567    statistics(warnings, Warnings).
 2568
 2569'$load_file_e'(File, Module, Options) :-
 2570    \+ '$option'(stream(_), Options),
 2571    user:prolog_load_file(Module:File, Options),
 2572    !.
 2573'$load_file_e'(File, Module, Options) :-
 2574    '$option'(stream(_), Options),
 2575    !,
 2576    '$assert_load_context_module'(File, Module, Options),
 2577    '$qdo_load_file'(File, File, Module, Options).
 2578'$load_file_e'(File, Module, Options) :-
 2579    (   '$resolved_source_path'(File, FullFile, Options)
 2580    ->  true
 2581    ;   '$resolve_source_path'(File, FullFile, Options)
 2582    ),
 2583    !,
 2584    '$mt_load_file'(File, FullFile, Module, Options).
 2585'$load_file_e'(_, _, _).
 $resolved_source_path(+File, -FullFile, +Options) is semidet
True when File has already been resolved to an absolute path.
 2591'$resolved_source_path'(File, FullFile, Options) :-
 2592    current_prolog_flag(emulated_dialect, Dialect),
 2593    '$resolved_source_path_db'(File, Dialect, FullFile),
 2594    (   '$source_file_property'(FullFile, from_state, true)
 2595    ;   '$source_file_property'(FullFile, resource, true)
 2596    ;   '$option'(if(If), Options, true),
 2597	'$noload'(If, FullFile, Options)
 2598    ),
 2599    !.
 $resolve_source_path(+File, -FullFile, +Options) is semidet
Resolve a source file specification to an absolute path. May throw existence and other errors. Attempts:
  1. Do a regular file search
  2. Find a known source file. This is used if the actual file was loaded from a .qlf file.
  3. Fail silently if if(exists) is in Options
  4. Raise a existence_error(source_sink, File)
 2612'$resolve_source_path'(File, FullFile, _Options) :-
 2613    absolute_file_name(File, AbsFile,
 2614		       [ file_type(prolog),
 2615			 access(read),
 2616                         file_errors(fail)
 2617		       ]),
 2618    !,
 2619    '$admin_file'(AbsFile, FullFile),
 2620    '$register_resolved_source_path'(File, FullFile).
 2621'$resolve_source_path'(File, FullFile, _Options) :-
 2622    absolute_file_name(File, FullFile,
 2623		       [ file_type(prolog),
 2624                         solutions(all),
 2625                         file_errors(fail)
 2626		       ]),
 2627    source_file(FullFile),
 2628    !.
 2629'$resolve_source_path'(_File, _FullFile, Options) :-
 2630    '$option'(if(exists), Options),
 2631    !,
 2632    fail.
 2633'$resolve_source_path'(File, _FullFile, _Options) :-
 2634    '$existence_error'(source_sink, File).
 $register_resolved_source_path(+Spec, -FullFile) is det
If Spec is Path(File), cache where we found the file. This both avoids many lookups on the file system and avoids that Spec is resolved to different locations.
 2642'$register_resolved_source_path'(File, FullFile) :-
 2643    (   compound(File)
 2644    ->  current_prolog_flag(emulated_dialect, Dialect),
 2645	(   '$resolved_source_path_db'(File, Dialect, FullFile)
 2646	->  true
 2647	;   asserta('$resolved_source_path_db'(File, Dialect, FullFile))
 2648	)
 2649    ;   true
 2650    ).
 $translated_source(+Old, +New) is det
Called from loading a QLF state when source files are being renamed.
 2656:- public '$translated_source'/2. 2657'$translated_source'(Old, New) :-
 2658    forall(retract('$resolved_source_path_db'(File, Dialect, Old)),
 2659	   assertz('$resolved_source_path_db'(File, Dialect, New))).
 $register_resource_file(+FullFile) is det
If we load a file from a resource we lock it, so we never have to check the modification again.
 2666'$register_resource_file'(FullFile) :-
 2667    (   sub_atom(FullFile, 0, _, _, 'res://'),
 2668	\+ file_name_extension(_, qlf, FullFile)
 2669    ->  '$set_source_file'(FullFile, resource, true)
 2670    ;   true
 2671    ).
 $already_loaded(+File, +FullFile, +Module, +Options) is det
Called if File is already loaded. If this is a module-file, the module must be imported into the context Module. If it is not a module file, it must be reloaded.
bug
- A file may be associated with multiple modules. How do we find the `main export module'? Currently there is no good way to find out which module is associated to the file as a result of the first :- module/2 term.
 2684'$already_loaded'(_File, FullFile, Module, Options) :-
 2685    '$assert_load_context_module'(FullFile, Module, Options),
 2686    '$current_module'(LoadModules, FullFile),
 2687    !,
 2688    (   atom(LoadModules)
 2689    ->  LoadModule = LoadModules
 2690    ;   LoadModules = [LoadModule|_]
 2691    ),
 2692    '$import_from_loaded_module'(LoadModule, Module, Options).
 2693'$already_loaded'(_, _, user, _) :- !.
 2694'$already_loaded'(File, FullFile, Module, Options) :-
 2695    (   '$load_context_module'(FullFile, Module, CtxOptions),
 2696	'$load_ctx_options'(Options, CtxOptions)
 2697    ->  true
 2698    ;   '$load_file'(File, Module, [if(true)|Options])
 2699    ).
 $mt_load_file(+File, +FullFile, +Module, +Options) is det
Deal with multi-threaded loading of files. The thread that wishes to load the thread first will do so, while other threads will wait until the leader finished and than act as if the file is already loaded.

Synchronisation is handled using a message queue that exists while the file is being loaded. This synchronisation relies on the fact that thread_get_message/1 throws an existence_error if the message queue is destroyed. This is hacky. Events or condition variables would have made a cleaner design.

 2714:- dynamic
 2715    '$loading_file'/3.              % File, Queue, Thread
 2716:- volatile
 2717    '$loading_file'/3. 2718:- '$notransact'('$loading_file'/3). 2719
 2720:- if(current_prolog_flag(threads, true)). 2721'$mt_load_file'(File, FullFile, Module, Options) :-
 2722    current_prolog_flag(threads, true),
 2723    !,
 2724    sig_atomic(setup_call_cleanup(
 2725		   with_mutex('$load_file',
 2726			      '$mt_start_load'(FullFile, Loading, Options)),
 2727		   '$mt_do_load'(Loading, File, FullFile, Module, Options),
 2728		   '$mt_end_load'(Loading))).
 2729:- endif. 2730'$mt_load_file'(File, FullFile, Module, Options) :-
 2731    '$option'(if(If), Options, true),
 2732    '$noload'(If, FullFile, Options),
 2733    !,
 2734    '$already_loaded'(File, FullFile, Module, Options).
 2735:- if(current_prolog_flag(threads, true)). 2736'$mt_load_file'(File, FullFile, Module, Options) :-
 2737    sig_atomic('$ctx_load_file'(File, FullFile, Module, Options)).
 2738:- else. 2739'$mt_load_file'(File, FullFile, Module, Options) :-
 2740    '$ctx_load_file'(File, FullFile, Module, Options).
 2741:- endif.
 $ctx_load_file(+Spec, +FullFile, +ContextModule, +Options) is det
Record the module FullFile is loaded from and load it. The record is what source_file_property(FullFile, load_context(Module, ...)) reports, which make/0 and the .qlf dependencies of qlf_dependency/2 rely on.
 2750'$ctx_load_file'(File, FullFile, Module, Options) :-
 2751    '$assert_load_context_module'(FullFile, Module, Options),
 2752    '$qdo_load_file'(File, FullFile, Module, Options).
 2753
 2754:- if(current_prolog_flag(threads, true)). 2755'$mt_start_load'(FullFile, queue(Queue), _) :-
 2756    '$loading_file'(FullFile, Queue, LoadThread),
 2757    \+ thread_self(LoadThread),
 2758    !.
 2759'$mt_start_load'(FullFile, already_loaded, Options) :-
 2760    '$option'(if(If), Options, true),
 2761    '$noload'(If, FullFile, Options),
 2762    !.
 2763'$mt_start_load'(FullFile, Ref, _) :-
 2764    thread_self(Me),
 2765    message_queue_create(Queue),
 2766    assertz('$loading_file'(FullFile, Queue, Me), Ref).
 2767
 2768'$mt_do_load'(queue(Queue), File, FullFile, Module, Options) :-
 2769    !,
 2770    catch(thread_get_message(Queue, _), error(_,_), true),
 2771    '$already_loaded'(File, FullFile, Module, Options).
 2772'$mt_do_load'(already_loaded, File, FullFile, Module, Options) :-
 2773    !,
 2774    '$already_loaded'(File, FullFile, Module, Options).
 2775'$mt_do_load'(_Ref, File, FullFile, Module, Options) :-
 2776    '$ctx_load_file'(File, FullFile, Module, Options).
 2777
 2778'$mt_end_load'(queue(_)) :- !.
 2779'$mt_end_load'(already_loaded) :- !.
 2780'$mt_end_load'(Ref) :-
 2781    clause('$loading_file'(_, Queue, _), _, Ref),
 2782    erase(Ref),
 2783    thread_send_message(Queue, done),
 2784    message_queue_destroy(Queue).
 2785:- endif.
 $qdo_load_file(+Spec, +FullFile, +ContextModule, +Options) is det
Switch to qcompile mode if requested by the option '$qlf'(+Out)
 2791'$qdo_load_file'(File, FullFile, Module, Options) :-
 2792    '$qdo_load_file2'(File, FullFile, Module, Action, Options),
 2793    '$register_resource_file'(FullFile),
 2794    '$run_initialization'(FullFile, Action, Options).
 2795
 2796'$qdo_load_file2'(File, FullFile, Module, Action, Options) :-
 2797    '$option'('$qlf'(QlfOut), Options),
 2798    '$stage_file'(QlfOut, StageQlf),
 2799    !,
 2800    setup_call_catcher_cleanup(
 2801	'$qstart'(StageQlf, Module, State),
 2802	( '$do_load_file'(File, FullFile, Module, Action, Options),
 2803          '$qlf_add_dependencies'(FullFile)
 2804        ),
 2805	Catcher,
 2806	'$qend'(State, Catcher, StageQlf, QlfOut)).
 2807'$qdo_load_file2'(File, FullFile, Module, Action, Options) :-
 2808    '$do_load_file'(File, FullFile, Module, Action, Options).
 2809
 2810'$qstart'(Qlf, Module, state(OldMode, OldModule)) :-
 2811    '$qlf_open'(Qlf),
 2812    '$compilation_mode'(OldMode, qlf),
 2813    '$set_source_module'(OldModule, Module).
 2814
 2815'$qend'(state(OldMode, OldModule), Catcher, StageQlf, QlfOut) :-
 2816    '$set_source_module'(_, OldModule),
 2817    '$set_compilation_mode'(OldMode),
 2818    '$qlf_close',
 2819    '$install_staged_file'(Catcher, StageQlf, QlfOut, warn).
 2820
 2821'$set_source_module'(OldModule, Module) :-
 2822    '$current_source_module'(OldModule),
 2823    '$set_source_module'(Module).
 $qlf_add_dependencies(+File) is det
Add compilation dependencies. These are files that are loaded into Module that define term or goal expansion rules.

This must be called with the .qlf file open and the part written, as it is here: '$qlf_dependency'/1 writes into the stream and the record belongs after the part, in the trailer.

 2834'$qlf_add_dependencies'(File) :-
 2835    findall(DepFile, '$dependency'(File, DepFile), DepFiles0),
 2836    sort(DepFiles0, DepFiles),          % a file need only be named once
 2837    forall('$member'(DepFile, DepFiles),
 2838           '$qlf_dependency'(DepFile)).
 prolog:qlf_dependency(+File, -DependsOn) is nondet
Hook. True when compiling File to a .qlf file takes a copy of something in DependsOn, so that the .qlf file must be rebuilt if DependsOn changes. Expansion rules are found without this hook; the hook is for a library that copies code of its own, as XPCE does with a class template: the methods of the template are put in each class that uses one, when that class is compiled.
 2849:- multifile
 2850    prolog:qlf_dependency/2.        % +File, -DependsOn
 2851
 2852'$dependency'(File, DepFile) :-
 2853    '$current_module'(Module, File),
 2854    '$load_context_module'(DepFile, Module, _Options),
 2855    '$source_defines_expansion'(DepFile).
 2856'$dependency'(File, DepFile) :-
 2857    prolog:qlf_dependency(File, DepFile).
 2858
 2859% Also used by autoload.pl
 2860'$source_defines_expansion'(File) :-
 2861    '$expansion_hook'(P),
 2862    source_file(P, File),
 2863    !.
 2864
 2865'$expansion_hook'(user:goal_expansion(_,_)).
 2866'$expansion_hook'(user:goal_expansion(_,_,_,_)).
 2867'$expansion_hook'(system:goal_expansion(_,_)).
 2868'$expansion_hook'(system:goal_expansion(_,_,_,_)).
 2869'$expansion_hook'(user:term_expansion(_,_)).
 2870'$expansion_hook'(user:term_expansion(_,_,_,_)).
 2871'$expansion_hook'(system:term_expansion(_,_)).
 2872'$expansion_hook'(system:term_expansion(_,_,_,_)).
 $do_load_file(+Spec, +FullFile, +ContextModule, -Action, +Options) is det
Perform the actual loading.
 2879'$do_load_file'(File, FullFile, Module, Action, Options) :-
 2880    '$option'(derived_from(DerivedFrom), Options, -),
 2881    '$register_derived_source'(FullFile, DerivedFrom),
 2882    '$qlf_file'(File, FullFile, Absolute, Mode, Options),
 2883    (   Mode == qcompile
 2884    ->  qcompile(Module:File, Options)
 2885    ;   '$do_load_file_2'(File, FullFile, Absolute, Module, Action, Options)
 2886    ).
 2887
 2888'$do_load_file_2'(File, FullFile, Absolute, Module, Action, Options) :-
 2889    '$source_file_property'(FullFile, number_of_clauses, OldClauses),
 2890    statistics(cputime, OldTime),
 2891
 2892    '$setup_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef,
 2893		  Options),
 2894
 2895    '$compilation_level'(Level),
 2896    '$load_msg_level'(load_file, Level, StartMsgLevel, DoneMsgLevel),
 2897    '$print_message'(StartMsgLevel,
 2898		     load_file(start(Level,
 2899				     file(File, Absolute)))),
 2900
 2901    (   '$option'(stream(FromStream), Options)
 2902    ->  Input = stream
 2903    ;   Input = source
 2904    ),
 2905
 2906    (   Input == stream,
 2907	(   '$option'(format(qlf), Options, source)
 2908	->  set_stream(FromStream, file_name(Absolute)),
 2909	    '$qload_stream'(FromStream, Module, Action, LM, Options)
 2910	;   '$consult_file'(stream(Absolute, FromStream, []),
 2911			    Module, Action, LM, Options)
 2912	)
 2913    ->  true
 2914    ;   Input == source,
 2915	file_name_extension(_, Ext, Absolute),
 2916	(   user:prolog_file_type(Ext, qlf),
 2917	    E = error(_,_),
 2918	    catch('$qload_file'(Absolute, Module, Action, LM, Options),
 2919		  E,
 2920		  print_message(warning, E))
 2921	->  true
 2922	;   '$consult_file'(Absolute, Module, Action, LM, Options)
 2923	)
 2924    ->  true
 2925    ;   '$print_message'(error, load_file(failed(File))),
 2926	fail
 2927    ),
 2928
 2929    '$import_from_loaded_module'(LM, Module, Options),
 2930
 2931    '$source_file_property'(FullFile, number_of_clauses, NewClauses),
 2932    statistics(cputime, Time),
 2933    ClausesCreated is NewClauses - OldClauses,
 2934    TimeUsed is Time - OldTime,
 2935
 2936    '$print_message'(DoneMsgLevel,
 2937		     load_file(done(Level,
 2938				    file(File, Absolute),
 2939				    Action,
 2940				    LM,
 2941				    TimeUsed,
 2942				    ClausesCreated))),
 2943
 2944    '$restore_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef).
 2945
 2946'$setup_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef,
 2947	      Options) :-
 2948    '$save_file_scoped_flags'(ScopedFlags),
 2949    '$set_sandboxed_load'(Options, OldSandBoxed),
 2950    '$set_verbose_load'(Options, OldVerbose),
 2951    '$set_optimise_load'(Options),
 2952    '$update_autoload_level'(Options, OldAutoLevel),
 2953    '$set_no_xref'(OldXRef).
 2954
 2955'$restore_load'(ScopedFlags, OldSandBoxed, OldVerbose, OldAutoLevel, OldXRef) :-
 2956    '$set_autoload_level'(OldAutoLevel),
 2957    set_prolog_flag(xref, OldXRef),
 2958    set_prolog_flag(verbose_load, OldVerbose),
 2959    set_prolog_flag(sandboxed_load, OldSandBoxed),
 2960    '$restore_file_scoped_flags'(ScopedFlags).
 $save_file_scoped_flags(-State) is det
 $restore_file_scoped_flags(-State) is det
Save/restore flags that are scoped to a compilation unit.
 2968'$save_file_scoped_flags'(State) :-
 2969    current_predicate(findall/3),          % Not when doing boot compile
 2970    !,
 2971    findall(SavedFlag, '$save_file_scoped_flag'(SavedFlag), State).
 2972'$save_file_scoped_flags'([]).
 2973
 2974'$save_file_scoped_flag'(Flag-Value) :-
 2975    '$file_scoped_flag'(Flag, Default),
 2976    (   current_prolog_flag(Flag, Value)
 2977    ->  true
 2978    ;   Value = Default
 2979    ).
 2980
 2981'$file_scoped_flag'(generate_debug_info, true).
 2982'$file_scoped_flag'(optimise,            false).
 2983'$file_scoped_flag'(xref,                false).
 2984
 2985'$restore_file_scoped_flags'([]).
 2986'$restore_file_scoped_flags'([Flag-Value|T]) :-
 2987    set_prolog_flag(Flag, Value),
 2988    '$restore_file_scoped_flags'(T).
 $import_from_loaded_module(+LoadedModule, +Module, +Options) is det
Import public predicates from LoadedModule into Module
 2995'$import_from_loaded_module'(LoadedModule, Module, Options) :-
 2996    LoadedModule \== Module,
 2997    atom(LoadedModule),
 2998    !,
 2999    '$option'(imports(Import), Options, all),
 3000    '$option'(reexport(Reexport), Options, false),
 3001    '$import_list'(Module, LoadedModule, Import, Reexport).
 3002'$import_from_loaded_module'(_, _, _).
 $set_verbose_load(+Options, -Old) is det
Set the verbose_load flag according to Options and unify Old with the old value.
 3010'$set_verbose_load'(Options, Old) :-
 3011    current_prolog_flag(verbose_load, Old),
 3012    (   '$option'(silent(Silent), Options)
 3013    ->  (   '$negate'(Silent, Level0)
 3014	->  '$load_msg_compat'(Level0, Level)
 3015	;   Level = Silent
 3016	),
 3017	set_prolog_flag(verbose_load, Level)
 3018    ;   true
 3019    ).
 3020
 3021'$negate'(true, false).
 3022'$negate'(false, true).
 $set_sandboxed_load(+Options, -Old) is det
Update the Prolog flag sandboxed_load from Options. Old is unified with the old flag.
Errors
- permission_error(leave, sandbox, -)
 3031'$set_sandboxed_load'(Options, Old) :-
 3032    current_prolog_flag(sandboxed_load, Old),
 3033    (   '$option'(sandboxed(SandBoxed), Options),
 3034	'$enter_sandboxed'(Old, SandBoxed, New),
 3035	New \== Old
 3036    ->  set_prolog_flag(sandboxed_load, New)
 3037    ;   true
 3038    ).
 3039
 3040'$enter_sandboxed'(Old, New, SandBoxed) :-
 3041    (   Old == false, New == true
 3042    ->  SandBoxed = true,
 3043	'$ensure_loaded_library_sandbox'
 3044    ;   Old == true, New == false
 3045    ->  throw(error(permission_error(leave, sandbox, -), _))
 3046    ;   SandBoxed = Old
 3047    ).
 3048'$enter_sandboxed'(false, true, true).
 3049
 3050'$ensure_loaded_library_sandbox' :-
 3051    source_file_property(library(sandbox), module(sandbox)),
 3052    !.
 3053'$ensure_loaded_library_sandbox' :-
 3054    load_files(library(sandbox), [if(not_loaded), silent(true)]).
 3055
 3056'$set_optimise_load'(Options) :-
 3057    (   '$option'(optimise(Optimise), Options)
 3058    ->  set_prolog_flag(optimise, Optimise)
 3059    ;   true
 3060    ).
 3061
 3062'$set_no_xref'(OldXRef) :-
 3063    (   current_prolog_flag(xref, OldXRef)
 3064    ->  true
 3065    ;   OldXRef = false
 3066    ),
 3067    set_prolog_flag(xref, false).
 $update_autoload_level(+Options, -OldLevel)
Update the '$autoload_nesting' and return the old value.
 3074:- thread_local
 3075    '$autoload_nesting'/1. 3076:- '$notransact'('$autoload_nesting'/1). 3077
 3078'$update_autoload_level'(Options, AutoLevel) :-
 3079    '$option'(autoload(Autoload), Options, false),
 3080    (   '$autoload_nesting'(CurrentLevel)
 3081    ->  AutoLevel = CurrentLevel
 3082    ;   AutoLevel = 0
 3083    ),
 3084    (   Autoload == false
 3085    ->  true
 3086    ;   NewLevel is AutoLevel + 1,
 3087	'$set_autoload_level'(NewLevel)
 3088    ).
 3089
 3090'$set_autoload_level'(New) :-
 3091    retractall('$autoload_nesting'(_)),
 3092    asserta('$autoload_nesting'(New)).
 $print_message(+Level, +Term) is det
As print_message/2, but deal with the fact that the message system might not yet be loaded.
 3100'$print_message'(Level, Term) :-
 3101    current_predicate(system:print_message/2),
 3102    !,
 3103    print_message(Level, Term).
 3104'$print_message'(warning, Term) :-
 3105    source_location(File, Line),
 3106    !,
 3107    format(user_error, 'WARNING: ~w:~w: ~p~n', [File, Line, Term]).
 3108'$print_message'(error, Term) :-
 3109    !,
 3110    source_location(File, Line),
 3111    !,
 3112    format(user_error, 'ERROR: ~w:~w: ~p~n', [File, Line, Term]).
 3113'$print_message'(_Level, _Term).
 3114
 3115'$print_message_fail'(E) :-
 3116    '$print_message'(error, E),
 3117    fail.
 $consult_file(+Path, +Module, -Action, -LoadedIn, +Options)
Called from '$do_load_file'/4 using the goal returned by '$consult_goal'/2. This means that the calling conventions must be kept synchronous with '$qload_file'/6.
 3125'$consult_file'(Absolute, Module, What, LM, Options) :-
 3126    '$current_source_module'(Module),   % same module
 3127    !,
 3128    '$consult_file_2'(Absolute, Module, What, LM, Options).
 3129'$consult_file'(Absolute, Module, What, LM, Options) :-
 3130    '$set_source_module'(OldModule, Module),
 3131    '$ifcompiling'('$qlf_start_sub_module'(Module)),
 3132    '$consult_file_2'(Absolute, Module, What, LM, Options),
 3133    '$ifcompiling'('$qlf_end_part'),
 3134    '$set_source_module'(OldModule).
 3135
 3136'$consult_file_2'(Absolute, Module, What, LM, Options) :-
 3137    '$set_source_module'(OldModule, Module),
 3138    '$load_id'(Absolute, Id, Modified, Options),
 3139    '$compile_type'(What),
 3140    '$save_lex_state'(LexState, Options),
 3141    '$set_dialect'(Options),
 3142    setup_call_cleanup(
 3143	'$start_consult'(Id, Modified),
 3144	'$load_file'(Absolute, Id, LM, Options),
 3145	'$end_consult'(Id, LexState, OldModule)).
 3146
 3147'$end_consult'(Id, LexState, OldModule) :-
 3148    '$end_consult'(Id),
 3149    '$restore_lex_state'(LexState),
 3150    '$set_source_module'(OldModule).
 3151
 3152
 3153:- create_prolog_flag(emulated_dialect, swi, [type(atom)]).
 $save_lex_state(-LexState, +Options) is det
 3157'$save_lex_state'(State, Options) :-
 3158    '$option'(scope_settings(false), Options),
 3159    !,
 3160    State = (-).
 3161'$save_lex_state'(lexstate(Style, Dialect), _) :-
 3162    '$style_check'(Style, Style),
 3163    current_prolog_flag(emulated_dialect, Dialect).
 3164
 3165'$restore_lex_state'(-) :- !.
 3166'$restore_lex_state'(lexstate(Style, Dialect)) :-
 3167    '$style_check'(_, Style),
 3168    set_prolog_flag(emulated_dialect, Dialect).
 3169
 3170'$set_dialect'(Options) :-
 3171    '$option'(dialect(Dialect), Options),
 3172    !,
 3173    '$expects_dialect'(Dialect).
 3174'$set_dialect'(_).
 3175
 3176'$load_id'(stream(Id, _, _), Id, Modified, Options) :-
 3177    !,
 3178    '$modified_id'(Id, Modified, Options).
 3179'$load_id'(Id, Id, Modified, Options) :-
 3180    '$modified_id'(Id, Modified, Options).
 3181
 3182'$modified_id'(_, Modified, Options) :-
 3183    '$option'(modified(Stamp), Options, Def),
 3184    Stamp \== Def,
 3185    !,
 3186    Modified = Stamp.
 3187'$modified_id'(Id, Modified, _) :-
 3188    catch(time_file(Id, Modified),
 3189	  error(_, _),
 3190	  fail),
 3191    !.
 3192'$modified_id'(_, 0, _).
 3193
 3194
 3195'$compile_type'(What) :-
 3196    '$compilation_mode'(How),
 3197    (   How == database
 3198    ->  What = compiled
 3199    ;   How == qlf
 3200    ->  What = '*qcompiled*'
 3201    ;   What = 'boot compiled'
 3202    ).
 $assert_load_context_module(+File, -Module, -Options)
Record the module a file was loaded from (see make/0). The first clause deals with loading from another file. On reload, this clause will be discarded by $start_consult/1. The second clause deals with reload from the toplevel. Here we avoid creating a duplicate dynamic (i.e., not related to a source) clause.
 3212:- dynamic
 3213    '$load_context_module'/3. 3214:- multifile
 3215    '$load_context_module'/3. 3216:- '$notransact'('$load_context_module'/3). 3217
 3218'$assert_load_context_module'(_, _, Options) :-
 3219    '$option'(register(false), Options),
 3220    !.
 3221'$assert_load_context_module'(File, Module, Options) :-
 3222    source_location(FromFile, Line),
 3223    !,
 3224    '$master_file'(FromFile, MasterFile),
 3225    '$admin_file'(File, PlFile),
 3226    '$check_load_non_module'(PlFile, Module),
 3227    '$add_dialect'(Options, Options1),
 3228    '$load_ctx_options'(Options1, Options2),
 3229    '$store_admin_clause'(
 3230	system:'$load_context_module'(PlFile, Module, Options2),
 3231	_Layout, MasterFile, FromFile:Line).
 3232'$assert_load_context_module'(File, Module, Options) :-
 3233    '$admin_file'(File, PlFile),
 3234    '$check_load_non_module'(PlFile, Module),
 3235    '$add_dialect'(Options, Options1),
 3236    '$load_ctx_options'(Options1, Options2),
 3237    (   clause('$load_context_module'(PlFile, Module, _), true, Ref),
 3238	\+ clause_property(Ref, file(_)),
 3239	erase(Ref)
 3240    ->  true
 3241    ;   true
 3242    ),
 3243    assertz('$load_context_module'(PlFile, Module, Options2)).
 $admin_file(+File, -PlFile) is det
Get the canonical Prolog file name in case File is a .qlf file. Note that all source admin uses the Prolog file names rather than the qlf file names.
 3251'$admin_file'(QlfFile, PlFile) :-
 3252    file_name_extension(_, qlf, QlfFile),
 3253    '$qlf_module'(QlfFile, Info),
 3254    get_dict(file, Info, PlFile),
 3255    !.
 3256'$admin_file'(File, File).
 $add_dialect(+Options0, -Options) is det
If we are in a dialect environment, add this to the load options such that the load context reflects the correct options for reloading this file.
 3264'$add_dialect'(Options0, Options) :-
 3265    current_prolog_flag(emulated_dialect, Dialect), Dialect \== swi,
 3266    !,
 3267    Options = [dialect(Dialect)|Options0].
 3268'$add_dialect'(Options, Options).
 $load_ctx_options(+Options, -CtxOptions) is det
Select the load options that determine the load semantics to perform a proper reload. Delete the others.
 3275'$load_ctx_options'(Options, CtxOptions) :-
 3276    '$load_ctx_options2'(Options, CtxOptions0),
 3277    sort(CtxOptions0, CtxOptions).
 3278
 3279'$load_ctx_options2'([], []).
 3280'$load_ctx_options2'([H|T0], [H|T]) :-
 3281    '$load_ctx_option'(H),
 3282    !,
 3283    '$load_ctx_options2'(T0, T).
 3284'$load_ctx_options2'([_|T0], T) :-
 3285    '$load_ctx_options2'(T0, T).
 3286
 3287'$load_ctx_option'(derived_from(_)).
 3288'$load_ctx_option'(dialect(_)).
 3289'$load_ctx_option'(encoding(_)).
 3290'$load_ctx_option'(imports(_)).
 3291'$load_ctx_option'(reexport(_)).
 $check_load_non_module(+File) is det
Test that a non-module file is not loaded into multiple contexts.
 3299'$check_load_non_module'(File, _) :-
 3300    '$current_module'(_, File),
 3301    !.          % File is a module file
 3302'$check_load_non_module'(File, Module) :-
 3303    '$load_context_module'(File, OldModule, _),
 3304    Module \== OldModule,
 3305    !,
 3306    format(atom(Msg),
 3307	   'Non-module file already loaded into module ~w; \c
 3308	       trying to load into ~w',
 3309	   [OldModule, Module]),
 3310    throw(error(permission_error(load, source, File),
 3311		context(load_files/2, Msg))).
 3312'$check_load_non_module'(_, _).
 $load_file(+Path, +Id, -Module, +Options)
'$load_file'/4 does the actual loading.

state(FirstTerm:boolean, Module:atom, AtEnd:atom, Stop:boolean, Id:atom, Dialect:atom)

 3325'$load_file'(Path, Id, Module, Options) :-
 3326    State = state(true, _, true, false, Id, -),
 3327    (   '$source_term'(Path, _Read, _Layout, Term, Layout,
 3328		       _Stream, Options),
 3329	'$valid_term'(Term),
 3330	(   arg(1, State, true)
 3331	->  '$first_term'(Term, Layout, Id, State, Options),
 3332	    nb_setarg(1, State, false)
 3333	;   '$compile_term'(Term, Layout, Id, Options)
 3334	),
 3335	arg(4, State, true)
 3336    ;   '$fixup_reconsult'(Id),
 3337	'$end_load_file'(State)
 3338    ),
 3339    !,
 3340    arg(2, State, Module).
 3341
 3342'$valid_term'(Var) :-
 3343    var(Var),
 3344    !,
 3345    print_message(error, error(instantiation_error, _)).
 3346'$valid_term'(Term) :-
 3347    Term \== [].
 3348
 3349'$end_load_file'(State) :-
 3350    arg(1, State, true),           % empty file
 3351    !,
 3352    nb_setarg(2, State, Module),
 3353    arg(5, State, Id),
 3354    '$current_source_module'(Module),
 3355    '$ifcompiling'('$qlf_start_file'(Id)),
 3356    '$ifcompiling'('$qlf_end_part').
 3357'$end_load_file'(State) :-
 3358    arg(3, State, End),
 3359    '$end_load_file'(End, State).
 3360
 3361'$end_load_file'(true, _).
 3362'$end_load_file'(end_module, State) :-
 3363    arg(2, State, Module),
 3364    '$check_export'(Module),
 3365    '$ifcompiling'('$qlf_end_part').
 3366'$end_load_file'(end_non_module, _State) :-
 3367    '$ifcompiling'('$qlf_end_part').
 3368
 3369
 3370'$first_term'(?-(Directive), Layout, Id, State, Options) :-
 3371    !,
 3372    '$first_term'(:-(Directive), Layout, Id, State, Options).
 3373'$first_term'(:-(Directive), _Layout, Id, State, Options) :-
 3374    nonvar(Directive),
 3375    (   (   Directive = module(Name, Public)
 3376	->  Imports = []
 3377	;   Directive = module(Name, Public, Imports)
 3378	)
 3379    ->  !,
 3380	'$module_name'(Name, Id, Module, Options),
 3381	'$start_module'(Module, Public, State, Options),
 3382	'$module3'(Imports)
 3383    ;   Directive = expects_dialect(Dialect)
 3384    ->  !,
 3385	'$set_dialect'(Dialect, State),
 3386	fail                        % Still consider next term as first
 3387    ).
 3388'$first_term'(Term, Layout, Id, State, Options) :-
 3389    '$start_non_module'(Id, Term, State, Options),
 3390    '$compile_term'(Term, Layout, Id, Options).
 $compile_term(+Term, +Layout, +SrcId, +Options) is det
 $compile_term(+Term, +Layout, +SrcId, +SrcLoc, +Options) is det
Distinguish between directives and normal clauses.
 3397'$compile_term'(Term, Layout, SrcId, Options) :-
 3398    '$compile_term'(Term, Layout, SrcId, -, Options).
 3399
 3400'$compile_term'(Var, _Layout, _Id, _SrcLoc, _Options) :-
 3401    var(Var),
 3402    !,
 3403    '$instantiation_error'(Var).
 3404'$compile_term'((?-Directive), _Layout, Id, _SrcLoc, Options) :-
 3405    !,
 3406    '$execute_directive'(Directive, Id, Options).
 3407'$compile_term'((:-Directive), _Layout, Id, _SrcLoc, Options) :-
 3408    !,
 3409    '$execute_directive'(Directive, Id, Options).
 3410'$compile_term'('$source_location'(File, Line):Term,
 3411		Layout, Id, _SrcLoc, Options) :-
 3412    !,
 3413    '$compile_term'(Term, Layout, Id, File:Line, Options).
 3414'$compile_term'(Clause, Layout, Id, SrcLoc, _Options) :-
 3415    E = error(_,_),
 3416    catch('$store_clause'(Clause, Layout, Id, SrcLoc), E,
 3417	  '$print_message'(error, E)).
 3418
 3419'$start_non_module'(_Id, Term, _State, Options) :-
 3420    '$option'(must_be_module(true), Options, false),
 3421    !,
 3422    '$domain_error'(module_header, Term).
 3423'$start_non_module'(Id, _Term, State, _Options) :-
 3424    '$current_source_module'(Module),
 3425    '$ifcompiling'('$qlf_start_file'(Id)),
 3426    '$qset_dialect'(State),
 3427    nb_setarg(2, State, Module),
 3428    nb_setarg(3, State, end_non_module).
 $set_dialect(+Dialect, +State)
Sets the expected dialect. This is difficult if we are compiling a .qlf file using qcompile/1 because the file is already open, while we are looking for the first term to decide wether this is a module or not. We save the dialect and set it after opening the file or module.

Note that expects_dialect/1 itself may be autoloaded from the library.

 3441'$set_dialect'(Dialect, State) :-
 3442    '$compilation_mode'(qlf, database),
 3443    !,
 3444    '$expects_dialect'(Dialect),
 3445    '$compilation_mode'(_, qlf),
 3446    nb_setarg(6, State, Dialect).
 3447'$set_dialect'(Dialect, _) :-
 3448    '$expects_dialect'(Dialect).
 3449
 3450'$qset_dialect'(State) :-
 3451    '$compilation_mode'(qlf),
 3452    arg(6, State, Dialect), Dialect \== (-),
 3453    !,
 3454    '$add_directive_wic'('$expects_dialect'(Dialect)).
 3455'$qset_dialect'(_).
 3456
 3457'$expects_dialect'(Dialect) :-
 3458    Dialect == swi,
 3459    !,
 3460    set_prolog_flag(emulated_dialect, Dialect).
 3461'$expects_dialect'(Dialect) :-
 3462    current_predicate(expects_dialect/1),
 3463    !,
 3464    expects_dialect(Dialect).
 3465'$expects_dialect'(Dialect) :-
 3466    use_module(library(dialect), [expects_dialect/1]),
 3467    expects_dialect(Dialect).
 3468
 3469
 3470		 /*******************************
 3471		 *           MODULES            *
 3472		 *******************************/
 3473
 3474'$start_module'(Module, _Public, State, _Options) :-
 3475    '$current_module'(Module, OldFile),
 3476    source_location(File, _Line),
 3477    OldFile \== File, OldFile \== [],
 3478    same_file(OldFile, File),
 3479    !,
 3480    nb_setarg(2, State, Module),
 3481    nb_setarg(4, State, true).      % Stop processing
 3482'$start_module'(Module, Public, State, Options) :-
 3483    arg(5, State, File),
 3484    nb_setarg(2, State, Module),
 3485    source_location(_File, Line),
 3486    '$option'(redefine_module(Action), Options, false),
 3487    '$module_class'(File, Class, Super),
 3488    '$reset_dialect'(File, Class),
 3489    '$redefine_module'(Module, File, Action),
 3490    '$declare_module'(Module, Class, Super, File, Line, false),
 3491    '$export_list'(Public, Module, Ops),
 3492    '$ifcompiling'('$qlf_start_module'(Module)),
 3493    '$export_ops'(Ops, Module, File),
 3494    '$qset_dialect'(State),
 3495    nb_setarg(3, State, end_module).
 $reset_dialect(+File, +Class) is det
Load .pl files from the SWI-Prolog distribution always in swi dialect.
 3502'$reset_dialect'(File, library) :-
 3503    file_name_extension(_, pl, File),
 3504    !,
 3505    set_prolog_flag(emulated_dialect, swi).
 3506'$reset_dialect'(_, _).
 $module3(+Spec) is det
Handle the 3th argument of a module declartion.
 3513'$module3'(Var) :-
 3514    var(Var),
 3515    !,
 3516    '$instantiation_error'(Var).
 3517'$module3'([]) :- !.
 3518'$module3'([H|T]) :-
 3519    !,
 3520    '$module3'(H),
 3521    '$module3'(T).
 3522'$module3'(Id) :-
 3523    use_module(library(dialect/Id)).
 $module_name(?Name, +Id, -Module, +Options) is semidet
Determine the module name. There are some cases:
 3537'$module_name'(_, _, Module, Options) :-
 3538    '$option'(module(Module), Options),
 3539    !,
 3540    '$current_source_module'(Context),
 3541    Context \== Module.                     % cause '$first_term'/5 to fail.
 3542'$module_name'(Var, Id, Module, Options) :-
 3543    var(Var),
 3544    !,
 3545    file_base_name(Id, File),
 3546    file_name_extension(Var, _, File),
 3547    '$module_name'(Var, Id, Module, Options).
 3548'$module_name'(Reserved, _, _, _) :-
 3549    '$reserved_module'(Reserved),
 3550    !,
 3551    throw(error(permission_error(load, module, Reserved), _)).
 3552'$module_name'(Module, _Id, Module, _).
 3553
 3554
 3555'$reserved_module'(system).
 3556'$reserved_module'(user).
 $redefine_module(+Module, +File, -Redefine)
 3561'$redefine_module'(_Module, _, false) :- !.
 3562'$redefine_module'(Module, File, true) :-
 3563    !,
 3564    (   module_property(Module, file(OldFile)),
 3565	File \== OldFile
 3566    ->  unload_file(OldFile)
 3567    ;   true
 3568    ).
 3569'$redefine_module'(Module, File, ask) :-
 3570    (   stream_property(user_input, tty(true)),
 3571	module_property(Module, file(OldFile)),
 3572	File \== OldFile,
 3573	'$rdef_response'(Module, OldFile, File, true)
 3574    ->  '$redefine_module'(Module, File, true)
 3575    ;   true
 3576    ).
 3577
 3578'$rdef_response'(Module, OldFile, File, Ok) :-
 3579    repeat,
 3580    print_message(query, redefine_module(Module, OldFile, File)),
 3581    get_single_char(Char),
 3582    '$rdef_response'(Char, Ok0),
 3583    !,
 3584    Ok = Ok0.
 3585
 3586'$rdef_response'(Char, true) :-
 3587    memberchk(Char, `yY`),
 3588    format(user_error, 'yes~n', []).
 3589'$rdef_response'(Char, false) :-
 3590    memberchk(Char, `nN`),
 3591    format(user_error, 'no~n', []).
 3592'$rdef_response'(Char, _) :-
 3593    memberchk(Char, `a`),
 3594    format(user_error, 'abort~n', []),
 3595    abort.
 3596'$rdef_response'(_, _) :-
 3597    print_message(help, redefine_module_reply),
 3598    fail.
 $module_class(+File, -Class, -Super) is det
Determine the file class and initial module from which File inherits. All boot and library modules as well as the -F script files inherit from system, while all normal user modules inherit from user.
 3608'$module_class'(File, Class, system) :-
 3609    current_prolog_flag(home, Home),
 3610    sub_atom(File, 0, Len, _, Home),
 3611    (   sub_atom(File, Len, _, _, '/boot/')
 3612    ->  !, Class = system
 3613    ;   '$lib_prefix'(Prefix),
 3614	sub_atom(File, Len, _, _, Prefix)
 3615    ->  !, Class = library
 3616    ;   file_directory_name(File, Home),
 3617	file_name_extension(_, rc, File)
 3618    ->  !, Class = library
 3619    ).
 3620'$module_class'(_, user, user).
 3621
 3622'$lib_prefix'('/library').
 3623'$lib_prefix'('/xpce/prolog/').
 3624
 3625'$check_export'(Module) :-
 3626    '$undefined_export'(Module, UndefList),
 3627    (   '$member'(Undef, UndefList),
 3628	strip_module(Undef, _, Local),
 3629	print_message(error,
 3630		      undefined_export(Module, Local)),
 3631	fail
 3632    ;   true
 3633    ).
 $import_list(+TargetModule, +FromModule, +Import, +Reexport) is det
Import from FromModule to TargetModule. Import is one of all, a list of optionally mapped predicate indicators or a term except(Import).
Arguments:
Reexport- is a bool asking to re-export our imports or not.
 3644'$import_list'(_, _, Var, _) :-
 3645    var(Var),
 3646    !,
 3647    throw(error(instantitation_error, _)).
 3648'$import_list'(Target, Source, all, Reexport) :-
 3649    !,
 3650    '$exported_ops'(Source, Import, Predicates),
 3651    '$module_property'(Source, exports(Predicates)),
 3652    '$import_all'(Import, Target, Source, Reexport, weak).
 3653'$import_list'(Target, Source, except(Spec), Reexport) :-
 3654    !,
 3655    '$exported_ops'(Source, Export, Predicates),
 3656    '$module_property'(Source, exports(Predicates)),
 3657    (   is_list(Spec)
 3658    ->  true
 3659    ;   throw(error(type_error(list, Spec), _))
 3660    ),
 3661    '$import_except'(Spec, Source, Export, Import),
 3662    '$import_all'(Import, Target, Source, Reexport, weak).
 3663'$import_list'(Target, Source, Import, Reexport) :-
 3664    is_list(Import),
 3665    !,
 3666    '$exported_ops'(Source, Ops, []),
 3667    '$expand_ops'(Import, Ops, Import1),
 3668    '$import_all'(Import1, Target, Source, Reexport, strong).
 3669'$import_list'(_, _, Import, _) :-
 3670    '$type_error'(import_specifier, Import).
 3671
 3672'$expand_ops'([], _, []).
 3673'$expand_ops'([H|T0], Ops, Imports) :-
 3674    nonvar(H), H = op(_,_,_),
 3675    !,
 3676    '$include'('$can_unify'(H), Ops, Ops1),
 3677    '$append'(Ops1, T1, Imports),
 3678    '$expand_ops'(T0, Ops, T1).
 3679'$expand_ops'([H|T0], Ops, [H|T1]) :-
 3680    '$expand_ops'(T0, Ops, T1).
 3681
 3682
 3683'$import_except'([], _, List, List).
 3684'$import_except'([H|T], Source, List0, List) :-
 3685    '$import_except_1'(H, Source, List0, List1),
 3686    '$import_except'(T, Source, List1, List).
 3687
 3688'$import_except_1'(Var, _, _, _) :-
 3689    var(Var),
 3690    !,
 3691    '$instantiation_error'(Var).
 3692'$import_except_1'(PI as N, _, List0, List) :-
 3693    '$pi'(PI), atom(N),
 3694    !,
 3695    '$canonical_pi'(PI, CPI),
 3696    '$import_as'(CPI, N, List0, List).
 3697'$import_except_1'(op(P,A,N), _, List0, List) :-
 3698    !,
 3699    '$remove_ops'(List0, op(P,A,N), List).
 3700'$import_except_1'(PI, Source, List0, List) :-
 3701    '$pi'(PI),
 3702    !,
 3703    '$canonical_pi'(PI, CPI),
 3704    (   '$select'(P, List0, List),
 3705        '$canonical_pi'(CPI, P)
 3706    ->  true
 3707    ;   print_message(warning,
 3708                      error(existence_error(export, PI, module(Source)), _)),
 3709        List = List0
 3710    ).
 3711'$import_except_1'(Except, _, _, _) :-
 3712    '$type_error'(import_specifier, Except).
 3713
 3714'$import_as'(CPI, N, [PI2|T], [CPI as N|T]) :-
 3715    '$canonical_pi'(PI2, CPI),
 3716    !.
 3717'$import_as'(PI, N, [H|T0], [H|T]) :-
 3718    !,
 3719    '$import_as'(PI, N, T0, T).
 3720'$import_as'(PI, _, _, _) :-
 3721    '$existence_error'(export, PI).
 3722
 3723'$pi'(N/A) :- atom(N), integer(A), !.
 3724'$pi'(N//A) :- atom(N), integer(A).
 3725
 3726'$canonical_pi'(N//A0, N/A) :-
 3727    A is A0 + 2.
 3728'$canonical_pi'(PI, PI).
 3729
 3730'$remove_ops'([], _, []).
 3731'$remove_ops'([Op|T0], Pattern, T) :-
 3732    subsumes_term(Pattern, Op),
 3733    !,
 3734    '$remove_ops'(T0, Pattern, T).
 3735'$remove_ops'([H|T0], Pattern, [H|T]) :-
 3736    '$remove_ops'(T0, Pattern, T).
 $import_all(+Import, +Context, +Source, +Reexport, +Strength)
Import Import from Source into Context. If Reexport is true, add the imported material to the exports of Context. If Strength is weak, definitions in Context overrule the import. If strong, a local definition is considered an error.
 3746'$import_all'(Import, Context, Source, Reexport, Strength) :-
 3747    '$import_all2'(Import, Context, Source, Imported, ImpOps, Strength),
 3748    (   Reexport == true,
 3749	(   '$list_to_conj'(Imported, Conj)
 3750	->  export(Context:Conj),
 3751	    '$ifcompiling'('$add_directive_wic'(export(Context:Conj)))
 3752	;   true
 3753	),
 3754	source_location(File, _Line),
 3755	'$export_ops'(ImpOps, Context, File)
 3756    ;   true
 3757    ).
 $import_all2(+Imports, +Context, +Source, -Imported, -ImpOps, +Strength)
 3761'$import_all2'([], _, _, [], [], _).
 3762'$import_all2'([PI as NewName|Rest], Context, Source,
 3763	       [NewName/Arity|Imported], ImpOps, Strength) :-
 3764    !,
 3765    '$canonical_pi'(PI, Name/Arity),
 3766    length(Args, Arity),
 3767    Head =.. [Name|Args],
 3768    NewHead =.. [NewName|Args],
 3769    (   '$get_predicate_attribute'(Source:Head, meta_predicate, Meta)
 3770    ->  Meta =.. [Name|MetaArgs],
 3771        NewMeta =.. [NewName|MetaArgs],
 3772        meta_predicate(Context:NewMeta)
 3773    ;   '$get_predicate_attribute'(Source:Head, transparent, 1)
 3774    ->  '$set_predicate_attribute'(Context:NewHead, transparent, true)
 3775    ;   true
 3776    ),
 3777    (   source_location(File, Line)
 3778    ->  E = error(_,_),
 3779	catch('$store_admin_clause'((NewHead :- Source:Head),
 3780				    _Layout, File, File:Line),
 3781	      E, '$print_message'(error, E))
 3782    ;   assertz((NewHead :- !, Source:Head)) % ! avoids problems with
 3783    ),                                       % duplicate load
 3784    '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength).
 3785'$import_all2'([op(P,A,N)|Rest], Context, Source, Imported,
 3786	       [op(P,A,N)|ImpOps], Strength) :-
 3787    !,
 3788    '$import_ops'(Context, Source, op(P,A,N)),
 3789    '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength).
 3790'$import_all2'([Pred|Rest], Context, Source, [Pred|Imported], ImpOps, Strength) :-
 3791    Error = error(_,_),
 3792    catch(Context:'$import'(Source:Pred, Strength), Error,
 3793	  print_message(error, Error)),
 3794    '$ifcompiling'('$import_wic'(Source, Pred, Strength)),
 3795    '$import_all2'(Rest, Context, Source, Imported, ImpOps, Strength).
 3796
 3797
 3798'$list_to_conj'([One], One) :- !.
 3799'$list_to_conj'([H|T], (H,Rest)) :-
 3800    '$list_to_conj'(T, Rest).
 $exported_ops(+Module, -Ops, ?Tail) is det
Ops is a list of op(P,A,N) terms representing the operators exported from Module.
 3807'$exported_ops'(Module, Ops, Tail) :-
 3808    '$c_current_predicate'(_, Module:'$exported_op'(_,_,_)),
 3809    !,
 3810    findall(op(P,A,N), Module:'$exported_op'(P,A,N), Ops, Tail).
 3811'$exported_ops'(_, Ops, Ops).
 3812
 3813'$exported_op'(Module, P, A, N) :-
 3814    '$c_current_predicate'(_, Module:'$exported_op'(_,_,_)),
 3815    Module:'$exported_op'(P, A, N).
 $import_ops(+Target, +Source, +Pattern)
Import the operators export from Source into the module table of Target. We only import operators that unify with Pattern.
 3822'$import_ops'(To, From, Pattern) :-
 3823    ground(Pattern),
 3824    !,
 3825    Pattern = op(P,A,N),
 3826    op(P,A,To:N),
 3827    (   '$exported_op'(From, P, A, N)
 3828    ->  true
 3829    ;   print_message(warning, no_exported_op(From, Pattern))
 3830    ).
 3831'$import_ops'(To, From, Pattern) :-
 3832    (   '$exported_op'(From, Pri, Assoc, Name),
 3833	Pattern = op(Pri, Assoc, Name),
 3834	op(Pri, Assoc, To:Name),
 3835	fail
 3836    ;   true
 3837    ).
 $export_list(+Declarations, +Module, -Ops)
Handle the export list of the module declaration for Module associated to File.
 3845'$export_list'(Decls, Module, Ops) :-
 3846    is_list(Decls),
 3847    !,
 3848    '$do_export_list'(Decls, Module, Ops).
 3849'$export_list'(Decls, _, _) :-
 3850    var(Decls),
 3851    throw(error(instantiation_error, _)).
 3852'$export_list'(Decls, _, _) :-
 3853    throw(error(type_error(list, Decls), _)).
 3854
 3855'$do_export_list'([], _, []) :- !.
 3856'$do_export_list'([H|T], Module, Ops) :-
 3857    !,
 3858    E = error(_,_),
 3859    catch('$export1'(H, Module, Ops, Ops1),
 3860	  E, ('$print_message'(error, E), Ops = Ops1)),
 3861    '$do_export_list'(T, Module, Ops1).
 3862
 3863'$export1'(Var, _, _, _) :-
 3864    var(Var),
 3865    !,
 3866    throw(error(instantiation_error, _)).
 3867'$export1'(Op, _, [Op|T], T) :-
 3868    Op = op(_,_,_),
 3869    !.
 3870'$export1'(PI0, Module, Ops, Ops) :-
 3871    strip_module(Module:PI0, M, PI),
 3872    (   PI = (_//_)
 3873    ->  non_terminal(M:PI)
 3874    ;   true
 3875    ),
 3876    export(M:PI).
 3877
 3878'$export_ops'([op(Pri, Assoc, Name)|T], Module, File) :-
 3879    E = error(_,_),
 3880    catch(( '$execute_directive'(op(Pri, Assoc, Module:Name), File, []),
 3881	    '$export_op'(Pri, Assoc, Name, Module, File)
 3882	  ),
 3883	  E, '$print_message'(error, E)),
 3884    '$export_ops'(T, Module, File).
 3885'$export_ops'([], _, _).
 3886
 3887'$export_op'(Pri, Assoc, Name, Module, File) :-
 3888    (   '$get_predicate_attribute'(Module:'$exported_op'(_,_,_), defined, 1)
 3889    ->  true
 3890    ;   '$execute_directive'(discontiguous(Module:'$exported_op'/3), File, [])
 3891    ),
 3892    '$store_admin_clause'('$exported_op'(Pri, Assoc, Name), _Layout, File, -).
 $execute_directive(:Goal, +File, +Options) is det
Execute the argument of :- or ?- while loading a file.
 3898'$execute_directive'(Var, _F, _Options) :-
 3899    var(Var),
 3900    '$instantiation_error'(Var).
 3901'$execute_directive'(encoding(Encoding), _F, _Options) :-
 3902    !,
 3903    (   '$load_input'(_F, S)
 3904    ->  set_stream(S, encoding(Encoding))
 3905    ).
 3906'$execute_directive'(Goal, _, Options) :-
 3907    \+ '$compilation_mode'(database),
 3908    !,
 3909    '$add_directive_wic2'(Goal, Type, Options),
 3910    (   Type == call                % suspend compiling into .qlf file
 3911    ->  '$compilation_mode'(Old, database),
 3912	setup_call_cleanup(
 3913	    '$directive_mode'(OldDir, Old),
 3914	    '$execute_directive_3'(Goal),
 3915	    ( '$set_compilation_mode'(Old),
 3916	      '$set_directive_mode'(OldDir)
 3917	    ))
 3918    ;   '$execute_directive_3'(Goal)
 3919    ).
 3920'$execute_directive'(Goal, _, _Options) :-
 3921    '$execute_directive_3'(Goal).
 3922
 3923'$execute_directive_3'(Goal) :-
 3924    '$current_source_module'(Module),
 3925    '$valid_directive'(Module:Goal),
 3926    !,
 3927    (   '$pattr_directive'(Goal, Module)
 3928    ->  true
 3929    ;   Term = error(_,_),
 3930	catch(Module:Goal, Term, '$exception_in_directive'(Term))
 3931    ->  true
 3932    ;   '$print_message'(warning, goal_failed(directive, Module:Goal)),
 3933	fail
 3934    ).
 3935'$execute_directive_3'(_).
 $valid_directive(:Directive) is det
If the flag sandboxed_load is true, this calls sandbox_allowed_directive/1. This call can deny execution of the directive by throwing an exception.
 3944:- multifile prolog:sandbox_allowed_directive/1. 3945:- multifile prolog:sandbox_allowed_clause/1. 3946:- meta_predicate '$valid_directive'(:). 3947
 3948'$valid_directive'(_) :-
 3949    current_prolog_flag(sandboxed_load, false),
 3950    !.
 3951'$valid_directive'(Goal) :-
 3952    Error = error(Formal, _),
 3953    catch(prolog:sandbox_allowed_directive(Goal), Error, true),
 3954    !,
 3955    (   var(Formal)
 3956    ->  true
 3957    ;   print_message(error, Error),
 3958	fail
 3959    ).
 3960'$valid_directive'(Goal) :-
 3961    print_message(error,
 3962		  error(permission_error(execute,
 3963					 sandboxed_directive,
 3964					 Goal), _)),
 3965    fail.
 3966
 3967'$exception_in_directive'(Term) :-
 3968    '$print_message'(error, Term),
 3969    fail.
 $add_directive_wic2(+Directive, -Type, +Options) is det
Classify Directive as one of load or call. Add a call directive to the QLF file. load directives continue the compilation into the QLF file.
 3977'$add_directive_wic2'(Goal, Type, Options) :-
 3978    '$common_goal_type'(Goal, Type, Options),
 3979    !,
 3980    (   Type == load
 3981    ->  true
 3982    ;   '$current_source_module'(Module),
 3983	'$add_directive_wic'(Module:Goal)
 3984    ).
 3985'$add_directive_wic2'(Goal, _, _) :-
 3986    (   '$compilation_mode'(qlf)    % no problem for qlf files
 3987    ->  true
 3988    ;   print_message(error, mixed_directive(Goal))
 3989    ).
 $common_goal_type(+Directive, -Type, +Options) is semidet
True when all subgoals of Directive must be handled using load or call.
 3996'$common_goal_type'((A,B), Type, Options) :-
 3997    !,
 3998    '$common_goal_type'(A, Type, Options),
 3999    '$common_goal_type'(B, Type, Options).
 4000'$common_goal_type'((A;B), Type, Options) :-
 4001    !,
 4002    '$common_goal_type'(A, Type, Options),
 4003    '$common_goal_type'(B, Type, Options).
 4004'$common_goal_type'((A->B), Type, Options) :-
 4005    !,
 4006    '$common_goal_type'(A, Type, Options),
 4007    '$common_goal_type'(B, Type, Options).
 4008'$common_goal_type'(Goal, Type, Options) :-
 4009    '$goal_type'(Goal, Type, Options).
 4010
 4011'$goal_type'(Goal, Type, Options) :-
 4012    (   '$load_goal'(Goal, Options)
 4013    ->  Type = load
 4014    ;   Type = call
 4015    ).
 4016
 4017:- thread_local
 4018    '$qlf':qinclude/1. 4019
 4020'$load_goal'([_|_], _).
 4021'$load_goal'(consult(_), _).
 4022'$load_goal'(load_files(_), _).
 4023'$load_goal'(load_files(_,Options), _) :-
 4024    '$option'(qcompile(QlfMode), Options),
 4025    '$qlf_part_mode'(QlfMode).
 4026'$load_goal'(ensure_loaded(_), _) :- '$compilation_mode'(wic).
 4027'$load_goal'(use_module(_), _)    :- '$compilation_mode'(wic).
 4028'$load_goal'(use_module(_, _), _) :- '$compilation_mode'(wic).
 4029'$load_goal'(reexport(_), _)      :- '$compilation_mode'(wic).
 4030'$load_goal'(reexport(_, _), _)   :- '$compilation_mode'(wic).
 4031'$load_goal'(Goal, _Options) :-
 4032    '$qlf':qinclude(user),
 4033    '$load_goal_file'(Goal, File),
 4034    '$all_user_files'(File).
 4035
 4036
 4037'$load_goal_file'(load_files(F), F).
 4038'$load_goal_file'(load_files(F, _), F).
 4039'$load_goal_file'(ensure_loaded(F), F).
 4040'$load_goal_file'(use_module(F), F).
 4041'$load_goal_file'(use_module(F, _), F).
 4042'$load_goal_file'(reexport(F), F).
 4043'$load_goal_file'(reexport(F, _), F).
 4044
 4045'$all_user_files'([]) :-
 4046    !.
 4047'$all_user_files'([H|T]) :-
 4048    !,
 4049    '$is_user_file'(H),
 4050    '$all_user_files'(T).
 4051'$all_user_files'(F) :-
 4052    ground(F),
 4053    '$is_user_file'(F).
 4054
 4055'$is_user_file'(File) :-
 4056    absolute_file_name(File, Path,
 4057		       [ file_type(prolog),
 4058			 access(read)
 4059		       ]),
 4060    '$module_class'(Path, user, _).
 4061
 4062'$qlf_part_mode'(part).
 4063'$qlf_part_mode'(true).                 % compatibility
 4064
 4065
 4066		/********************************
 4067		*        COMPILE A CLAUSE       *
 4068		*********************************/
 $store_admin_clause(+Clause, ?Layout, +Owner, +SrcLoc) is det
 $store_admin_clause(+Clause, ?Layout, +Owner, +SrcLoc, +Mode) is det
Store a clause into the database for administrative purposes. This bypasses sanity checking.
 4076'$store_admin_clause'(Clause, Layout, Owner, SrcLoc) :-
 4077    '$compilation_mode'(Mode),
 4078    '$store_admin_clause'(Clause, Layout, Owner, SrcLoc, Mode).
 4079
 4080'$store_admin_clause'(Clause, Layout, Owner, SrcLoc, Mode) :-
 4081    Owner \== (-),
 4082    !,
 4083    setup_call_cleanup(
 4084	'$start_aux'(Owner, Context),
 4085	'$store_admin_clause2'(Clause, Layout, Owner, SrcLoc, Mode),
 4086	'$end_aux'(Owner, Context)).
 4087'$store_admin_clause'(Clause, Layout, File, SrcLoc, Mode) :-
 4088    '$store_admin_clause2'(Clause, Layout, File, SrcLoc, Mode).
 4089
 4090:- public '$store_admin_clause2'/4.     % Used by autoload.pl
 4091'$store_admin_clause2'(Clause, _Layout, File, SrcLoc) :-
 4092    '$compilation_mode'(Mode),
 4093    '$store_admin_clause2'(Clause, _Layout, File, SrcLoc, Mode).
 4094
 4095'$store_admin_clause2'(Clause, _Layout, File, SrcLoc, Mode) :-
 4096    (   Mode == database
 4097    ->  '$record_clause'(Clause, File, SrcLoc)
 4098    ;   '$record_clause'(Clause, File, SrcLoc, Ref),
 4099	'$qlf_assert_clause'(Ref, development)
 4100    ).
 $store_clause(+Clause, ?Layout, +Owner, +SrcLoc) is det
Store a clause into the database.
Arguments:
Owner- is the file-id that owns the clause
SrcLoc- is the file:line term where the clause originates from.
 4110'$store_clause'((_, _), _, _, _) :-
 4111    !,
 4112    print_message(error, cannot_redefine_comma),
 4113    fail.
 4114'$store_clause'((Pre => Body), _Layout, File, SrcLoc) :-
 4115    nonvar(Pre),
 4116    Pre = (Head,Cond),
 4117    !,
 4118    (   '$is_true'(Cond), current_prolog_flag(optimise, true)
 4119    ->  '$store_clause'((Head=>Body), _Layout, File, SrcLoc)
 4120    ;   '$store_clause'(?=>(Head,(Cond,!,Body)), _Layout, File, SrcLoc)
 4121    ).
 4122'$store_clause'(Clause, _Layout, File, SrcLoc) :-
 4123    '$valid_clause'(Clause),
 4124    !,
 4125    (   '$compilation_mode'(database)
 4126    ->  '$record_clause'(Clause, File, SrcLoc)
 4127    ;   '$record_clause'(Clause, File, SrcLoc, Ref),
 4128	'$qlf_assert_clause'(Ref, development)
 4129    ).
 4130
 4131'$is_true'(true)  => true.
 4132'$is_true'((A,B)) => '$is_true'(A), '$is_true'(B).
 4133'$is_true'(_)     => fail.
 4134
 4135'$valid_clause'(_) :-
 4136    current_prolog_flag(sandboxed_load, false),
 4137    !.
 4138'$valid_clause'(Clause) :-
 4139    \+ '$cross_module_clause'(Clause),
 4140    !.
 4141'$valid_clause'(Clause) :-
 4142    Error = error(Formal, _),
 4143    catch(prolog:sandbox_allowed_clause(Clause), Error, true),
 4144    !,
 4145    (   var(Formal)
 4146    ->  true
 4147    ;   print_message(error, Error),
 4148	fail
 4149    ).
 4150'$valid_clause'(Clause) :-
 4151    print_message(error,
 4152		  error(permission_error(assert,
 4153					 sandboxed_clause,
 4154					 Clause), _)),
 4155    fail.
 4156
 4157'$cross_module_clause'(Clause) :-
 4158    '$head_module'(Clause, Module),
 4159    \+ '$current_source_module'(Module).
 4160
 4161'$head_module'(Var, _) :-
 4162    var(Var), !, fail.
 4163'$head_module'((Head :- _), Module) :-
 4164    '$head_module'(Head, Module).
 4165'$head_module'(Module:_, Module).
 4166
 4167'$clause_source'('$source_location'(File,Line):Clause, Clause, File:Line) :- !.
 4168'$clause_source'(Clause, Clause, -).
 $store_clause(+Term, +Id) is det
This interface is used by PlDoc (and who knows). Kept for to avoid compatibility issues.
 4175:- public
 4176    '$store_clause'/2. 4177
 4178'$store_clause'(Term, Id) :-
 4179    '$clause_source'(Term, Clause, SrcLoc),
 4180    '$store_clause'(Clause, _, Id, SrcLoc).
 compile_aux_clauses(+Clauses) is det
Compile clauses given the current source location but do not change the notion of the current procedure such that discontiguous warnings are not issued. The clauses are associated with the current file and therefore wiped out if the file is reloaded.

If the cross-referencer is active, we should not (re-)assert the clauses. Actually, we should make them known to the cross-referencer. How do we do that? Maybe we need a different API, such as in:

expand_term_aux(Goal, NewGoal, Clauses)

The clauses are owned by the file being loaded and their source location is the current source location. These differ if the clauses are compiled from an included file.

To be done
- Deal with source code layout?
 4205compile_aux_clauses(_Clauses) :-
 4206    current_prolog_flag(xref, true),
 4207    !.
 4208compile_aux_clauses(Clauses) :-
 4209    source_location(File, Line),
 4210    prolog_load_context(source, Owner),
 4211    '$compile_aux_clauses'(Clauses, Owner, File:Line).
 4212
 4213'$compile_aux_clauses'(Clauses, Owner, SrcLoc) :-
 4214    setup_call_cleanup(
 4215	'$start_aux'(Owner, Context),
 4216	'$store_aux_clauses'(Clauses, Owner, SrcLoc),
 4217	'$end_aux'(Owner, Context)).
 4218
 4219'$store_aux_clauses'(Clauses, Owner, SrcLoc) :-
 4220    is_list(Clauses),
 4221    !,
 4222    forall('$member'(C,Clauses),
 4223	   '$compile_term'(C, _Layout, Owner, SrcLoc, [])).
 4224'$store_aux_clauses'(Clause, Owner, SrcLoc) :-
 4225    '$compile_term'(Clause, _Layout, Owner, SrcLoc, []).
 4226
 4227
 4228		 /*******************************
 4229		 *            STAGING		*
 4230		 *******************************/
 $stage_file(+Target, -Stage) is det
 $install_staged_file(+Catcher, +Staged, +Target, +OnError)
Create files using staging, where we first write a temporary file and move it to Target if the file was created successfully. This provides an atomic transition, preventing customers from reading an incomplete file.
 4240'$stage_file'(Target, Stage) :-
 4241    file_directory_name(Target, Dir),
 4242    file_base_name(Target, File),
 4243    current_prolog_flag(pid, Pid),
 4244    format(atom(Stage), '~w/.~w.~d', [Dir,File,Pid]).
 4245
 4246'$install_staged_file'(exit, Staged, Target, error) :-
 4247    !,
 4248    win_rename_file(Staged, Target).
 4249'$install_staged_file'(exit, Staged, Target, OnError) :-
 4250    !,
 4251    InstallError = error(_,_),
 4252    catch(win_rename_file(Staged, Target),
 4253	  InstallError,
 4254	  '$install_staged_error'(OnError, InstallError, Staged, Target)).
 4255'$install_staged_file'(_, Staged, _, _OnError) :-
 4256    E = error(_,_),
 4257    catch(delete_file(Staged), E, true).
 4258
 4259'$install_staged_error'(OnError, Error, Staged, _Target) :-
 4260    E = error(_,_),
 4261    catch(delete_file(Staged), E, true),
 4262    (   OnError = silent
 4263    ->  true
 4264    ;   OnError = fail
 4265    ->  fail
 4266    ;   print_message(warning, Error)
 4267    ).
 win_rename_file(+From, +To) is det
Retry installing to deal with possible permission errors due to Windows sharing violations.
 4274:- if(current_prolog_flag(windows, true)). 4275win_rename_file(From, To) :-
 4276    between(1, 10, _),
 4277    catch(rename_file(From, To), error(permission_error(rename, file, _),_), (sleep(0.1),fail)),
 4278    !.
 4279:- endif. 4280win_rename_file(From, To) :-
 4281    rename_file(From, To).
 4282
 4283
 4284		 /*******************************
 4285		 *             READING          *
 4286		 *******************************/
 4287
 4288:- multifile
 4289    prolog:comment_hook/4.                  % hook for read_clause/3
 4290
 4291
 4292		 /*******************************
 4293		 *       FOREIGN INTERFACE      *
 4294		 *******************************/
 4295
 4296%       call-back from PL_register_foreign().  First argument is the module
 4297%       into which the foreign predicate is loaded and second is a term
 4298%       describing the arguments.
 4299
 4300:- dynamic
 4301    '$foreign_registered'/2. 4302
 4303		 /*******************************
 4304		 *   TEMPORARY TERM EXPANSION   *
 4305		 *******************************/
 4306
 4307% Provide temporary definitions for the boot-loader.  These are replaced
 4308% by the real thing in load.pl
 4309
 4310:- dynamic
 4311    '$expand_goal'/2,
 4312    '$expand_term'/4. 4313
 4314'$expand_goal'(In, In).
 4315'$expand_term'(In, Layout, In, Layout).
 4316
 4317
 4318		 /*******************************
 4319		 *         TYPE SUPPORT         *
 4320		 *******************************/
 4321
 4322'$type_error'(Type, Value) :-
 4323    (   var(Value)
 4324    ->  throw(error(instantiation_error, _))
 4325    ;   throw(error(type_error(Type, Value), _))
 4326    ).
 4327
 4328'$domain_error'(Type, Value) :-
 4329    throw(error(domain_error(Type, Value), _)).
 4330
 4331'$existence_error'(Type, Object) :-
 4332    throw(error(existence_error(Type, Object), _)).
 4333
 4334'$existence_error'(Type, Object, In) :-
 4335    throw(error(existence_error(Type, Object, In), _)).
 4336
 4337'$permission_error'(Action, Type, Term) :-
 4338    throw(error(permission_error(Action, Type, Term), _)).
 4339
 4340'$instantiation_error'(_Var) :-
 4341    throw(error(instantiation_error, _)).
 4342
 4343'$uninstantiation_error'(NonVar) :-
 4344    throw(error(uninstantiation_error(NonVar), _)).
 4345
 4346'$must_be'(list, X) :- !,
 4347    '$skip_list'(_, X, Tail),
 4348    (   Tail == []
 4349    ->  true
 4350    ;   '$type_error'(list, Tail)
 4351    ).
 4352'$must_be'(options, X) :- !,
 4353    (   '$is_options'(X)
 4354    ->  true
 4355    ;   '$type_error'(options, X)
 4356    ).
 4357'$must_be'(atom, X) :- !,
 4358    (   atom(X)
 4359    ->  true
 4360    ;   '$type_error'(atom, X)
 4361    ).
 4362'$must_be'(integer, X) :- !,
 4363    (   integer(X)
 4364    ->  true
 4365    ;   '$type_error'(integer, X)
 4366    ).
 4367'$must_be'(between(Low,High), X) :- !,
 4368    (   integer(X)
 4369    ->  (   between(Low, High, X)
 4370	->  true
 4371	;   '$domain_error'(between(Low,High), X)
 4372	)
 4373    ;   '$type_error'(integer, X)
 4374    ).
 4375'$must_be'(callable, X) :- !,
 4376    (   callable(X)
 4377    ->  true
 4378    ;   '$type_error'(callable, X)
 4379    ).
 4380'$must_be'(acyclic, X) :- !,
 4381    (   acyclic_term(X)
 4382    ->  true
 4383    ;   '$domain_error'(acyclic_term, X)
 4384    ).
 4385'$must_be'(oneof(Type, Domain, List), X) :- !,
 4386    '$must_be'(Type, X),
 4387    (   memberchk(X, List)
 4388    ->  true
 4389    ;   '$domain_error'(Domain, X)
 4390    ).
 4391'$must_be'(boolean, X) :- !,
 4392    (   (X == true ; X == false)
 4393    ->  true
 4394    ;   '$type_error'(boolean, X)
 4395    ).
 4396'$must_be'(ground, X) :- !,
 4397    (   ground(X)
 4398    ->  true
 4399    ;   '$instantiation_error'(X)
 4400    ).
 4401'$must_be'(filespec, X) :- !,
 4402    (   (   atom(X)
 4403	;   string(X)
 4404	;   compound(X),
 4405	    compound_name_arity(X, _, 1)
 4406	)
 4407    ->  true
 4408    ;   '$type_error'(filespec, X)
 4409    ).
 4410
 4411% Use for debugging
 4412%'$must_be'(Type, _X) :- format('Unknown $must_be type: ~q~n', [Type]).
 4413
 4414
 4415		/********************************
 4416		*       LIST PROCESSING         *
 4417		*********************************/
 4418
 4419'$member'(El, [H|T]) :-
 4420    '$member_'(T, El, H).
 4421
 4422'$member_'(_, El, El).
 4423'$member_'([H|T], El, _) :-
 4424    '$member_'(T, El, H).
 4425
 4426'$append'([], L, L).
 4427'$append'([H|T], L, [H|R]) :-
 4428    '$append'(T, L, R).
 4429
 4430'$append'(ListOfLists, List) :-
 4431    '$must_be'(list, ListOfLists),
 4432    '$append_'(ListOfLists, List).
 4433
 4434'$append_'([], []).
 4435'$append_'([L|Ls], As) :-
 4436    '$append'(L, Ws, As),
 4437    '$append_'(Ls, Ws).
 4438
 4439'$select'(X, [X|Tail], Tail).
 4440'$select'(Elem, [Head|Tail], [Head|Rest]) :-
 4441    '$select'(Elem, Tail, Rest).
 4442
 4443'$reverse'(L1, L2) :-
 4444    '$reverse'(L1, [], L2).
 4445
 4446'$reverse'([], List, List).
 4447'$reverse'([Head|List1], List2, List3) :-
 4448    '$reverse'(List1, [Head|List2], List3).
 4449
 4450'$delete'([], _, []) :- !.
 4451'$delete'([Elem|Tail], Elem, Result) :-
 4452    !,
 4453    '$delete'(Tail, Elem, Result).
 4454'$delete'([Head|Tail], Elem, [Head|Rest]) :-
 4455    '$delete'(Tail, Elem, Rest).
 4456
 4457'$last'([H|T], Last) :-
 4458    '$last'(T, H, Last).
 4459
 4460'$last'([], Last, Last).
 4461'$last'([H|T], _, Last) :-
 4462    '$last'(T, H, Last).
 4463
 4464:- meta_predicate '$include'(1,+,-). 4465'$include'(_, [], []).
 4466'$include'(G, [H|T0], L) :-
 4467    (   call(G,H)
 4468    ->  L = [H|T]
 4469    ;   T = L
 4470    ),
 4471    '$include'(G, T0, T).
 4472
 4473'$can_unify'(A, B) :-
 4474    \+ A \= B.
 length(?List, ?N)
Is true when N is the length of List.
 4480:- '$iso'((length/2)). 4481
 4482length(List, Length) :-
 4483    var(Length),
 4484    !,
 4485    '$skip_list'(Length0, List, Tail),
 4486    (   Tail == []
 4487    ->  Length = Length0                    % +,-
 4488    ;   var(Tail)
 4489    ->  Tail \== Length,                    % avoid length(L,L)
 4490	'$length3'(Tail, Length, Length0)   % -,-
 4491    ;   throw(error(type_error(list, List),
 4492		    context(length/2, _)))
 4493    ).
 4494length(List, Length) :-
 4495    integer(Length),
 4496    Length >= 0,
 4497    !,
 4498    '$skip_list'(Length0, List, Tail),
 4499    (   Tail == []                          % proper list
 4500    ->  Length = Length0
 4501    ;   var(Tail)
 4502    ->  Extra is Length-Length0,
 4503	'$length'(Tail, Extra)
 4504    ;   throw(error(type_error(list, List),
 4505		    context(length/2, _)))
 4506    ).
 4507length(_, Length) :-
 4508    integer(Length),
 4509    !,
 4510    throw(error(domain_error(not_less_than_zero, Length),
 4511		context(length/2, _))).
 4512length(_, Length) :-
 4513    throw(error(type_error(integer, Length),
 4514		context(length/2, _))).
 4515
 4516'$length3'([], N, N).
 4517'$length3'([_|List], N, N0) :-
 4518    N1 is N0+1,
 4519    '$length3'(List, N, N1).
 4520
 4521
 4522		 /*******************************
 4523		 *       OPTION PROCESSING      *
 4524		 *******************************/
 $is_options(@Term) is semidet
True if Term looks like it provides options.
 4530'$is_options'(Map) :-
 4531    is_dict(Map, _),
 4532    !.
 4533'$is_options'(List) :-
 4534    is_list(List),
 4535    (   List == []
 4536    ->  true
 4537    ;   List = [H|_],
 4538	'$is_option'(H, _, _)
 4539    ).
 4540
 4541'$is_option'(Var, _, _) :-
 4542    var(Var), !, fail.
 4543'$is_option'(F, Name, Value) :-
 4544    functor(F, _, 1),
 4545    !,
 4546    F =.. [Name,Value].
 4547'$is_option'(Name=Value, Name, Value).
 $option(?Opt, +Options) is semidet
 4551'$option'(Opt, Options) :-
 4552    is_dict(Options),
 4553    !,
 4554    [Opt] :< Options.
 4555'$option'(Opt, Options) :-
 4556    memberchk(Opt, Options).
 $option(?Opt, +Options, +Default) is det
 4560'$option'(Term, Options, Default) :-
 4561    arg(1, Term, Value),
 4562    functor(Term, Name, 1),
 4563    (   is_dict(Options)
 4564    ->  (   get_dict(Name, Options, GVal)
 4565	->  Value = GVal
 4566	;   Value = Default
 4567	)
 4568    ;   functor(Gen, Name, 1),
 4569	arg(1, Gen, GVal),
 4570	(   memberchk(Gen, Options)
 4571	->  Value = GVal
 4572	;   Value = Default
 4573	)
 4574    ).
 $select_option(?Opt, +Options, -Rest) is semidet
Select an option from Options.
Arguments:
Rest- is always a map.
 4582'$select_option'(Opt, Options, Rest) :-
 4583    '$options_dict'(Options, Dict),
 4584    select_dict([Opt], Dict, Rest).
 $merge_options(+New, +Default, -Merged) is det
Add/replace options specified in New.
Arguments:
Merged- is always a map.
 4592'$merge_options'(New, Old, Merged) :-
 4593    '$options_dict'(New, NewDict),
 4594    '$options_dict'(Old, OldDict),
 4595    put_dict(NewDict, OldDict, Merged).
 $options_dict(+Options, --Dict) is det
Translate to an options dict. For possible duplicate keys we keep the first.
 4602'$options_dict'(Options, Dict) :-
 4603    is_list(Options),
 4604    !,
 4605    '$keyed_options'(Options, Keyed),
 4606    sort(1, @<, Keyed, UniqueKeyed),
 4607    '$pairs_values'(UniqueKeyed, Unique),
 4608    dict_create(Dict, _, Unique).
 4609'$options_dict'(Dict, Dict) :-
 4610    is_dict(Dict),
 4611    !.
 4612'$options_dict'(Options, _) :-
 4613    '$domain_error'(options, Options).
 4614
 4615'$keyed_options'([], []).
 4616'$keyed_options'([H0|T0], [H|T]) :-
 4617    '$keyed_option'(H0, H),
 4618    '$keyed_options'(T0, T).
 4619
 4620'$keyed_option'(Var, _) :-
 4621    var(Var),
 4622    !,
 4623    '$instantiation_error'(Var).
 4624'$keyed_option'(Name=Value, Name-(Name-Value)).
 4625'$keyed_option'(NameValue, Name-(Name-Value)) :-
 4626    compound_name_arguments(NameValue, Name, [Value]),
 4627    !.
 4628'$keyed_option'(Opt, _) :-
 4629    '$domain_error'(option, Opt).
 4630
 4631
 4632		 /*******************************
 4633		 *   HANDLE TRACER 'L'-COMMAND  *
 4634		 *******************************/
 4635
 4636:- public '$prolog_list_goal'/1. 4637
 4638:- multifile
 4639    user:prolog_list_goal/1. 4640
 4641'$prolog_list_goal'(Goal) :-
 4642    user:prolog_list_goal(Goal),
 4643    !.
 4644'$prolog_list_goal'(Goal) :-
 4645    use_module(library(listing), [listing/1]),
 4646    @(listing(Goal), user).
 4647
 4648
 4649		 /*******************************
 4650		 *             HALT             *
 4651		 *******************************/
 4652
 4653:- '$iso'((halt/0)). 4654
 4655halt :-
 4656    '$exit_code'(Code),
 4657    (   Code == 0
 4658    ->  true
 4659    ;   print_message(warning, on_error(halt(1)))
 4660    ),
 4661    halt(Code).
 $exit_code(Code)
Determine the exit code baed on the on_error and on_warning flags. Also used by qsave_toplevel/0.
 4668'$exit_code'(Code) :-
 4669    (   (   current_prolog_flag(on_error, status),
 4670	    statistics(errors, Count),
 4671	    Count > 0
 4672	;   current_prolog_flag(on_warning, status),
 4673	    statistics(warnings, Count),
 4674	    Count > 0
 4675	)
 4676    ->  Code = 1
 4677    ;   Code = 0
 4678    ).
 at_halt(:Goal)
Register Goal to be called if the system halts.
To be done
- : get location into the error message
 4687:- meta_predicate at_halt(0). 4688:- dynamic        system:term_expansion/2, '$at_halt'/2. 4689:- multifile      system:term_expansion/2, '$at_halt'/2. 4690
 4691system:term_expansion((:- at_halt(Goal)),
 4692		      system:'$at_halt'(Module:Goal, File:Line)) :-
 4693    \+ current_prolog_flag(xref, true),
 4694    source_location(File, Line),
 4695    '$current_source_module'(Module).
 4696
 4697at_halt(Goal) :-
 4698    asserta('$at_halt'(Goal, (-):0)).
 4699
 4700:- public '$run_at_halt'/0. 4701
 4702'$run_at_halt' :-
 4703    forall(clause('$at_halt'(Goal, Src), true, Ref),
 4704	   ( '$call_at_halt'(Goal, Src),
 4705	     erase(Ref)
 4706	   )).
 4707
 4708'$call_at_halt'(Goal, _Src) :-
 4709    catch(Goal, E, true),
 4710    !,
 4711    (   var(E)
 4712    ->  true
 4713    ;   subsumes_term(cancel_halt(_), E)
 4714    ->  '$print_message'(informational, E),
 4715	fail
 4716    ;   '$print_message'(error, E)
 4717    ).
 4718'$call_at_halt'(Goal, _Src) :-
 4719    '$print_message'(warning, goal_failed(at_halt, Goal)).
 cancel_halt(+Reason)
This predicate may be called from at_halt/1 handlers to cancel halting the program. If causes halt/0 to fail rather than terminating the process.
 4727cancel_halt(Reason) :-
 4728    throw(cancel_halt(Reason)).
 prolog:heartbeat
Called every N inferences of the Prolog flag heartbeat is non-zero.
 4735:- multifile prolog:heartbeat/0. 4736
 4737
 4738                /*******************************
 4739                *        UNICODE ATOMS         *
 4740                *******************************/
 $install_unicode_normalize_hook is det
Called from setPrologFlag() in pl-prologflag.c when the user sets the unicode_normalize flag and no kernel normalisation hook is registered. Loading library(unicode) calls PL_atom_normalize_hook from its install_t entry point. The call propagates an error if the library is unavailable.
 4750:- public '$install_unicode_normalize_hook'/0. 4751
 4752'$install_unicode_normalize_hook' :-
 4753    use_module(library(unicode), []).
 4754
 4755
 4756		/********************************
 4757		*      LOAD OTHER MODULES       *
 4758		*********************************/
 4759
 4760:- meta_predicate
 4761    '$load_wic_files'(:). 4762
 4763'$load_wic_files'(Files) :-
 4764    Files = Module:_,
 4765    '$execute_directive'('$set_source_module'(OldM, Module), [], []),
 4766    '$save_lex_state'(LexState, []),
 4767    '$style_check'(_, 0xC7),                % see style_name/2 in syspred.pl
 4768    '$compilation_mode'(OldC, wic),
 4769    consult(Files),
 4770    '$execute_directive'('$set_source_module'(OldM), [], []),
 4771    '$execute_directive'('$restore_lex_state'(LexState), [], []),
 4772    '$set_compilation_mode'(OldC).
 $load_additional_boot_files is det
Called from compileFileList() in pl-wic.c. Gets the files from "-c file ..." and loads them into the module user.
 4780:- public '$load_additional_boot_files'/0. 4781
 4782'$load_additional_boot_files' :-
 4783    current_prolog_flag(argv, Argv),
 4784    '$get_files_argv'(Argv, Files),
 4785    (   Files \== []
 4786    ->  format('Loading additional boot files~n'),
 4787	'$load_wic_files'(user:Files),
 4788	format('additional boot files loaded~n')
 4789    ;   true
 4790    ).
 4791
 4792'$get_files_argv'([], []) :- !.
 4793'$get_files_argv'(['-c'|Files], Files) :- !.
 4794'$get_files_argv'([_|Rest], Files) :-
 4795    '$get_files_argv'(Rest, Files).
 4796
 4797'$:-'(('$boot_message'('Loading Prolog startup files~n', []),
 4798       source_location(File, _Line),
 4799       file_directory_name(File, Dir),
 4800       atom_concat(Dir, '/load.pl', LoadFile),
 4801       '$load_wic_files'(system:[LoadFile]),
 4802       '$boot_message'('SWI-Prolog boot files loaded~n', []),
 4803       '$compilation_mode'(OldC, wic),
 4804       '$execute_directive'('$set_source_module'(user), [], []),
 4805       '$set_compilation_mode'(OldC)
 4806      ))