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-2019, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9    All rights reserved.
   10
   11    Redistribution and use in source and binary forms, with or without
   12    modification, are permitted provided that the following conditions
   13    are met:
   14
   15    1. Redistributions of source code must retain the above copyright
   16       notice, this list of conditions and the following disclaimer.
   17
   18    2. Redistributions in binary form must reproduce the above copyright
   19       notice, this list of conditions and the following disclaimer in
   20       the documentation and/or other materials provided with the
   21       distribution.
   22
   23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34    POSSIBILITY OF SUCH DAMAGE.
   35*/
   36
   37:- module('$syspreds',
   38          [ leash/1,
   39            visible/1,
   40            style_check/1,
   41            (spy)/1,
   42            (nospy)/1,
   43            trace/1,
   44            trace/2,
   45            nospyall/0,
   46            debugging/0,
   47            rational/3,
   48            flag/3,
   49            atom_prefix/2,
   50            dwim_match/2,
   51            source_file_property/2,
   52            source_file/1,
   53            source_file/2,
   54            unload_file/1,
   55            prolog_load_context/2,
   56            stream_position_data/3,
   57            current_predicate/2,
   58            '$defined_predicate'/1,
   59            predicate_property/2,
   60            '$predicate_property'/2,
   61            clause_property/2,
   62            current_module/1,                   % ?Module
   63            module_property/2,                  % ?Module, ?Property
   64            module/1,                           % +Module
   65            current_trie/1,                     % ?Trie
   66            trie_property/2,                    % ?Trie, ?Property
   67            working_directory/2,                % -OldDir, +NewDir
   68            shell/1,                            % +Command
   69            on_signal/3,
   70            current_signal/3,
   71            open_shared_object/2,
   72            open_shared_object/3,
   73            format/1,
   74            garbage_collect/0,
   75            set_prolog_stack/2,
   76            prolog_stack_property/2,
   77            absolute_file_name/2,
   78            tmp_file_stream/3,                  % +Enc, -File, -Stream
   79            require/1,
   80            call_with_depth_limit/3,            % :Goal, +Limit, -Result
   81            call_with_inference_limit/3,        % :Goal, +Limit, -Result
   82            numbervars/3,                       % +Term, +Start, -End
   83            term_string/3,                      % ?Term, ?String, +Options
   84            nb_setval/2,                        % +Var, +Value
   85            thread_create/2,                    % :Goal, -Id
   86            thread_join/1,                      % +Id
   87            set_prolog_gc_thread/1,		% +Status
   88
   89            '$wrap_predicate'/4                 % :Head, +Name, -Wrapped, +Body
   90          ]).   91
   92                /********************************
   93                *           DEBUGGER            *
   94                *********************************/
 map_bits(:Pred, +Modify, +OldBits, -NewBits)
   98:- meta_predicate
   99    map_bits(2, +, +, -).  100
  101map_bits(_, Var, _, _) :-
  102    var(Var),
  103    !,
  104    '$instantiation_error'(Var).
  105map_bits(_, [], Bits, Bits) :- !.
  106map_bits(Pred, [H|T], Old, New) :-
  107    map_bits(Pred, H, Old, New0),
  108    map_bits(Pred, T, New0, New).
  109map_bits(Pred, +Name, Old, New) :-     % set a bit
  110    !,
  111    bit(Pred, Name, Bits),
  112    !,
  113    New is Old \/ Bits.
  114map_bits(Pred, -Name, Old, New) :-     % clear a bit
  115    !,
  116    bit(Pred, Name, Bits),
  117    !,
  118    New is Old /\ (\Bits).
  119map_bits(Pred, ?(Name), Old, Old) :-   % ask a bit
  120    !,
  121    bit(Pred, Name, Bits),
  122    Old /\ Bits > 0.
  123map_bits(_, Term, _, _) :-
  124    '$type_error'('+|-|?(Flag)', Term).
  125
  126bit(Pred, Name, Bits) :-
  127    call(Pred, Name, Bits),
  128    !.
  129bit(_:Pred, Name, _) :-
  130    '$domain_error'(Pred, Name).
  131
  132:- public port_name/2.                  % used by library(test_cover)
  133
  134port_name(      call, 2'000000001).
  135port_name(      exit, 2'000000010).
  136port_name(      fail, 2'000000100).
  137port_name(      redo, 2'000001000).
  138port_name(     unify, 2'000010000).
  139port_name(     break, 2'000100000).
  140port_name(  cut_call, 2'001000000).
  141port_name(  cut_exit, 2'010000000).
  142port_name( exception, 2'100000000).
  143port_name(       cut, 2'011000000).
  144port_name(       all, 2'000111111).
  145port_name(      full, 2'000101111).
  146port_name(      half, 2'000101101).     % '
  147
  148leash(Ports) :-
  149    '$leash'(Old, Old),
  150    map_bits(port_name, Ports, Old, New),
  151    '$leash'(_, New).
  152
  153visible(Ports) :-
  154    '$visible'(Old, Old),
  155    map_bits(port_name, Ports, Old, New),
  156    '$visible'(_, New).
  157
  158style_name(atom,            0x0001) :-
  159    print_message(warning, decl_no_effect(style_check(atom))).
  160style_name(singleton,       0x0042).            % semantic and syntactic
  161style_name(discontiguous,   0x0008).
  162style_name(charset,         0x0020).
  163style_name(no_effect,       0x0080).
  164style_name(var_branches,    0x0100).
 style_check(+Spec) is nondet
  168style_check(Var) :-
  169    var(Var),
  170    !,
  171    '$instantiation_error'(Var).
  172style_check(?(Style)) :-
  173    !,
  174    (   var(Style)
  175    ->  enum_style_check(Style)
  176    ;   enum_style_check(Style)
  177    ->  true
  178    ).
  179style_check(Spec) :-
  180    '$style_check'(Old, Old),
  181    map_bits(style_name, Spec, Old, New),
  182    '$style_check'(_, New).
  183
  184enum_style_check(Style) :-
  185    '$style_check'(Bits, Bits),
  186    style_name(Style, Bit),
  187    Bit /\ Bits =\= 0.
 prolog:debug_control_hook(+Action)
Allow user-hooks in the Prolog debugger interaction. See the calls below for the provided hooks. We use a single predicate with action argument to avoid an uncontrolled poliferation of hooks.

TBD: What hooks to provide for trace/[1,2]

  198:- multifile
  199    prolog:debug_control_hook/1.    % +Action
 trace(:Preds) is det
 trace(:Preds, +PortSpec) is det
Start printing messages if control passes specified ports of the given predicates.
  207:- meta_predicate
  208    trace(:),
  209    trace(:, +).  210
  211trace(Preds) :-
  212    trace(Preds, +all).
  213
  214trace(_:X, _) :-
  215    var(X),
  216    !,
  217    throw(error(instantiation_error, _)).
  218trace(_:[], _) :- !.
  219trace(M:[H|T], Ps) :-
  220    !,
  221    trace(M:H, Ps),
  222    trace(M:T, Ps).
  223trace(Pred, Ports) :-
  224    '$find_predicate'(Pred, Preds),
  225    Preds \== [],
  226    set_prolog_flag(debug, true),
  227    (   '$member'(PI, Preds),
  228            pi_to_head(PI, Head),
  229            (   Head = _:_
  230            ->  QHead0 = Head
  231            ;   QHead0 = user:Head
  232            ),
  233            '$define_predicate'(QHead0),
  234            (   predicate_property(QHead0, imported_from(M))
  235            ->  QHead0 = _:Plain,
  236                QHead = M:Plain
  237            ;   QHead = QHead0
  238            ),
  239            '$trace'(Ports, QHead),
  240            trace_ports(QHead, Tracing),
  241            print_message(informational, trace(QHead, Tracing)),
  242        fail
  243    ;   true
  244    ).
  245
  246trace_alias(all,  [trace_call, trace_redo, trace_exit, trace_fail]).
  247trace_alias(call, [trace_call]).
  248trace_alias(redo, [trace_redo]).
  249trace_alias(exit, [trace_exit]).
  250trace_alias(fail, [trace_fail]).
  251
  252'$trace'([], _) :- !.
  253'$trace'([H|T], Head) :-
  254    !,
  255    '$trace'(H, Head),
  256    '$trace'(T, Head).
  257'$trace'(+H, Head) :-
  258    trace_alias(H, A0),
  259    !,
  260    tag_list(A0, +, A1),
  261    '$trace'(A1, Head).
  262'$trace'(+H, Head) :-
  263    !,
  264    trace_alias(_, [H]),
  265    '$set_predicate_attribute'(Head, H, true).
  266'$trace'(-H, Head) :-
  267    trace_alias(H, A0),
  268    !,
  269    tag_list(A0, -, A1),
  270    '$trace'(A1, Head).
  271'$trace'(-H, Head) :-
  272    !,
  273    trace_alias(_, [H]),
  274    '$set_predicate_attribute'(Head, H, false).
  275'$trace'(H, Head) :-
  276    atom(H),
  277    '$trace'(+H, Head).
  278
  279tag_list([], _, []).
  280tag_list([H0|T0], F, [H1|T1]) :-
  281    H1 =.. [F, H0],
  282    tag_list(T0, F, T1).
  283
  284:- meta_predicate
  285    spy(:),
  286    nospy(:).
 spy(:Spec) is det
 nospy(:Spec) is det
 nospyall is det
Set/clear spy-points. A successfully set or cleared spy-point is reported using print_message/2, level informational, with one of the following terms, where Spec is of the form M:Head.
See also
- spy/1 and nospy/1 call the hook debug_control_hook/1 to allow for alternative specifications of the thing to debug.
  303spy(_:X) :-
  304    var(X),
  305    throw(error(instantiation_error, _)).
  306spy(_:[]) :- !.
  307spy(M:[H|T]) :-
  308    !,
  309    spy(M:H),
  310    spy(M:T).
  311spy(Spec) :-
  312    notrace(prolog:debug_control_hook(spy(Spec))),
  313    !.
  314spy(Spec) :-
  315    '$find_predicate'(Spec, Preds),
  316    '$member'(PI, Preds),
  317        pi_to_head(PI, Head),
  318        '$define_predicate'(Head),
  319        '$spy'(Head),
  320    fail.
  321spy(_).
  322
  323nospy(_:X) :-
  324    var(X),
  325    throw(error(instantiation_error, _)).
  326nospy(_:[]) :- !.
  327nospy(M:[H|T]) :-
  328    !,
  329    nospy(M:H),
  330    nospy(M:T).
  331nospy(Spec) :-
  332    notrace(prolog:debug_control_hook(nospy(Spec))),
  333    !.
  334nospy(Spec) :-
  335    '$find_predicate'(Spec, Preds),
  336    '$member'(PI, Preds),
  337         pi_to_head(PI, Head),
  338        '$nospy'(Head),
  339    fail.
  340nospy(_).
  341
  342nospyall :-
  343    notrace(prolog:debug_control_hook(nospyall)),
  344    fail.
  345nospyall :-
  346    spy_point(Head),
  347        '$nospy'(Head),
  348    fail.
  349nospyall.
  350
  351pi_to_head(M:PI, M:Head) :-
  352    !,
  353    pi_to_head(PI, Head).
  354pi_to_head(Name/Arity, Head) :-
  355    functor(Head, Name, Arity).
 debugging is det
Report current status of the debugger.
  361debugging :-
  362    notrace(prolog:debug_control_hook(debugging)),
  363    !.
  364debugging :-
  365    current_prolog_flag(debug, true),
  366    !,
  367    print_message(informational, debugging(on)),
  368    findall(H, spy_point(H), SpyPoints),
  369    print_message(informational, spying(SpyPoints)),
  370    findall(trace(H,P), trace_point(H,P), TracePoints),
  371    print_message(informational, tracing(TracePoints)).
  372debugging :-
  373    print_message(informational, debugging(off)).
  374
  375spy_point(Module:Head) :-
  376    current_predicate(_, Module:Head),
  377    '$get_predicate_attribute'(Module:Head, spy, 1),
  378    \+ predicate_property(Module:Head, imported_from(_)).
  379
  380trace_point(Module:Head, Ports) :-
  381    current_predicate(_, Module:Head),
  382        '$get_predicate_attribute'(Module:Head, trace_any, 1),
  383        \+ predicate_property(Module:Head, imported_from(_)),
  384        trace_ports(Module:Head, Ports).
  385
  386trace_ports(Head, Ports) :-
  387    findall(Port,
  388            (trace_alias(Port, [AttName]),
  389             '$get_predicate_attribute'(Head, AttName, 1)),
  390            Ports).
 flag(+Name, -Old, +New) is det
True when Old is the current value associated with the flag Name and New has become the new value.
  398flag(Name, Old, New) :-
  399    Old == New,
  400    !,
  401    get_flag(Name, Old).
  402flag(Name, Old, New) :-
  403    with_mutex('$flag', update_flag(Name, Old, New)).
  404
  405update_flag(Name, Old, New) :-
  406    get_flag(Name, Old),
  407    (   atom(New)
  408    ->  set_flag(Name, New)
  409    ;   Value is New,
  410        set_flag(Name, Value)
  411    ).
  412
  413
  414                 /*******************************
  415                 *            RATIONAL          *
  416                 *******************************/
 rational(+Rat, -Numerator, -Denominator) is semidet
True when Rat is a rational number with given Numerator and Denominator.
  423rational(Rat, M, N) :-
  424    rational(Rat),
  425    (   Rat = rdiv(M, N)
  426    ->  true
  427    ;   integer(Rat)
  428    ->  M = Rat,
  429        N = 1
  430    ).
  431
  432
  433                /********************************
  434                *             ATOMS             *
  435                *********************************/
  436
  437dwim_match(A1, A2) :-
  438    dwim_match(A1, A2, _).
  439
  440atom_prefix(Atom, Prefix) :-
  441    sub_atom(Atom, 0, _, _, Prefix).
  442
  443
  444                /********************************
  445                *             SOURCE            *
  446                *********************************/
 source_file(-File) is nondet
source_file(+File) is semidet
True if File is loaded into Prolog. If File is unbound it is bound to the canonical name for it. If File is bound it succeeds if the canonical name as defined by absolute_file_name/2 is known as a loaded filename.

Note that Time = 0.0 is used by PlDoc and other code that needs to create a file record without being interested in the time.

  459source_file(File) :-
  460    (   current_prolog_flag(access_level, user)
  461    ->  Level = user
  462    ;   true
  463    ),
  464    (   ground(File)
  465    ->  (   '$time_source_file'(File, Time, Level)
  466        ;   absolute_file_name(File, Abs),
  467            '$time_source_file'(Abs, Time, Level)
  468        ), !
  469    ;   '$time_source_file'(File, Time, Level)
  470    ),
  471    Time > 0.0.
 source_file(+Head, -File) is semidet
source_file(?Head, ?File) is nondet
True when Head is a predicate owned by File.
  478:- meta_predicate source_file(:, ?).  479
  480source_file(M:Head, File) :-
  481    nonvar(M), nonvar(Head),
  482    !,
  483    (   '$c_current_predicate'(_, M:Head),
  484        predicate_property(M:Head, multifile)
  485    ->  multi_source_files(M:Head, Files),
  486        '$member'(File, Files)
  487    ;   '$source_file'(M:Head, File)
  488    ).
  489source_file(M:Head, File) :-
  490    (   nonvar(File)
  491    ->  true
  492    ;   source_file(File)
  493    ),
  494    '$source_file_predicates'(File, Predicates),
  495    '$member'(M:Head, Predicates).
  496
  497:- thread_local found_src_file/1.  498
  499multi_source_files(Head, Files) :-
  500    call_cleanup(
  501        findall(File, multi_source_file(Head, File), Files),
  502        retractall(found_src_file(_))).
  503
  504multi_source_file(Head, File) :-
  505    nth_clause(Head, _, Clause),
  506    clause_property(Clause, source(File)),
  507    \+ found_src_file(File),
  508    asserta(found_src_file(File)).
 source_file_property(?File, ?Property) is nondet
True if Property is a property of the loaded source-file File.
  515source_file_property(File, P) :-
  516    nonvar(File),
  517    !,
  518    canonical_source_file(File, Path),
  519    property_source_file(P, Path).
  520source_file_property(File, P) :-
  521    property_source_file(P, File).
  522
  523property_source_file(modified(Time), File) :-
  524    '$time_source_file'(File, Time, user).
  525property_source_file(source(Source), File) :-
  526    (   '$source_file_property'(File, from_state, true)
  527    ->  Source = state
  528    ;   '$source_file_property'(File, resource, true)
  529    ->  Source = resource
  530    ;   Source = file
  531    ).
  532property_source_file(module(M), File) :-
  533    (   nonvar(M)
  534    ->  '$current_module'(M, File)
  535    ;   nonvar(File)
  536    ->  '$current_module'(ML, File),
  537        (   atom(ML)
  538        ->  M = ML
  539        ;   '$member'(M, ML)
  540        )
  541    ;   '$current_module'(M, File)
  542    ).
  543property_source_file(load_context(Module, Location, Options), File) :-
  544    '$time_source_file'(File, _, user),
  545    clause(system:'$load_context_module'(File, Module, Options), true, Ref),
  546    (   clause_property(Ref, file(FromFile)),
  547        clause_property(Ref, line_count(FromLine))
  548    ->  Location = FromFile:FromLine
  549    ;   Location = user
  550    ).
  551property_source_file(includes(Master, Stamp), File) :-
  552    system:'$included'(File, _Line, Master, Stamp).
  553property_source_file(included_in(Master, Line), File) :-
  554    system:'$included'(Master, Line, File, _).
  555property_source_file(derived_from(DerivedFrom, Stamp), File) :-
  556    system:'$derived_source'(File, DerivedFrom, Stamp).
  557property_source_file(reloading, File) :-
  558    source_file(File),
  559    '$source_file_property'(File, reloading, true).
  560property_source_file(load_count(Count), File) :-
  561    source_file(File),
  562    '$source_file_property'(File, load_count, Count).
  563property_source_file(number_of_clauses(Count), File) :-
  564    source_file(File),
  565    '$source_file_property'(File, number_of_clauses, Count).
 canonical_source_file(+Spec, -File) is semidet
File is the canonical representation of the source-file Spec.
  572canonical_source_file(Spec, File) :-
  573    atom(Spec),
  574    '$time_source_file'(Spec, _, _),
  575    !,
  576    File = Spec.
  577canonical_source_file(Spec, File) :-
  578    system:'$included'(_Master, _Line, Spec, _),
  579    !,
  580    File = Spec.
  581canonical_source_file(Spec, File) :-
  582    absolute_file_name(Spec,
  583                           [ file_type(prolog),
  584                             access(read),
  585                             file_errors(fail)
  586                           ],
  587                           File),
  588    source_file(File).
 prolog_load_context(+Key, -Value)
Provides context information for term_expansion and directives. Note that only the line-number info is valid for the '$stream_position'. Largely Quintus compatible.
  597prolog_load_context(module, Module) :-
  598    '$current_source_module'(Module).
  599prolog_load_context(file, File) :-
  600    input_file(File).
  601prolog_load_context(source, F) :-       % SICStus compatibility
  602    input_file(F0),
  603    '$input_context'(Context),
  604    '$top_file'(Context, F0, F).
  605prolog_load_context(stream, S) :-
  606    (   system:'$load_input'(_, S0)
  607    ->  S = S0
  608    ).
  609prolog_load_context(directory, D) :-
  610    input_file(F),
  611    file_directory_name(F, D).
  612prolog_load_context(dialect, D) :-
  613    current_prolog_flag(emulated_dialect, D).
  614prolog_load_context(term_position, TermPos) :-
  615    source_location(_, L),
  616    (   nb_current('$term_position', Pos),
  617        compound(Pos),              % actually set
  618        stream_position_data(line_count, Pos, L)
  619    ->  TermPos = Pos
  620    ;   TermPos = '$stream_position'(0,L,0,0)
  621    ).
  622prolog_load_context(script, Bool) :-
  623    (   '$toplevel':loaded_init_file(script, Path),
  624        input_file(File),
  625        same_file(File, Path)
  626    ->  Bool = true
  627    ;   Bool = false
  628    ).
  629prolog_load_context(variable_names, Bindings) :-
  630    nb_current('$variable_names', Bindings).
  631prolog_load_context(term, Term) :-
  632    nb_current('$term', Term).
  633prolog_load_context(reloading, true) :-
  634    prolog_load_context(source, F),
  635    '$source_file_property'(F, reloading, true).
  636
  637input_file(File) :-
  638    (   system:'$load_input'(_, Stream)
  639    ->  stream_property(Stream, file_name(File))
  640    ),
  641    !.
  642input_file(File) :-
  643    source_location(File, _).
 unload_file(+File) is det
Remove all traces of loading file.
  650:- dynamic system:'$resolved_source_path'/2.  651
  652unload_file(File) :-
  653    (   canonical_source_file(File, Path)
  654    ->  '$unload_file'(Path),
  655        retractall(system:'$resolved_source_path'(_, Path))
  656    ;   true
  657    ).
  658
  659
  660                 /*******************************
  661                 *            STREAMS           *
  662                 *******************************/
 stream_position_data(?Field, +Pos, ?Date)
Extract values from stream position objects. '$stream_position' is of the format '$stream_position'(Byte, Char, Line, LinePos)
  669stream_position_data(Prop, Term, Value) :-
  670    nonvar(Prop),
  671    !,
  672    (   stream_position_field(Prop, Pos)
  673    ->  arg(Pos, Term, Value)
  674    ;   throw(error(domain_error(stream_position_data, Prop)))
  675    ).
  676stream_position_data(Prop, Term, Value) :-
  677    stream_position_field(Prop, Pos),
  678    arg(Pos, Term, Value).
  679
  680stream_position_field(char_count,    1).
  681stream_position_field(line_count,    2).
  682stream_position_field(line_position, 3).
  683stream_position_field(byte_count,    4).
  684
  685
  686                 /*******************************
  687                 *            CONTROL           *
  688                 *******************************/
 call_with_depth_limit(:Goal, +DepthLimit, -Result)
Try to proof Goal, but fail on any branch exceeding the indicated depth-limit. Unify Result with the maximum-reached limit on success, depth_limit_exceeded if the limit was exceeded and fails otherwise.
  696:- meta_predicate
  697    call_with_depth_limit(0, +, -).  698
  699call_with_depth_limit(G, Limit, Result) :-
  700    '$depth_limit'(Limit, OLimit, OReached),
  701    (   catch(G, E, '$depth_limit_except'(OLimit, OReached, E)),
  702        '$depth_limit_true'(Limit, OLimit, OReached, Result, Det),
  703        ( Det == ! -> ! ; true )
  704    ;   '$depth_limit_false'(OLimit, OReached, Result)
  705    ).
 call_with_inference_limit(:Goal, +InferenceLimit, -Result)
Equivalent to call(Goal), but poses a limit on the number of inferences. If this limit is reached, Result is unified with inference_limit_exceeded, otherwise Result is unified with ! if Goal succeeded without a choicepoint and true otherwise.

Note that we perform calls in system to avoid auto-importing, which makes raiseInferenceLimitException() fail to recognise that the exception happens in the overhead.

  719:- meta_predicate
  720    call_with_inference_limit(0, +, -).  721
  722call_with_inference_limit(G, Limit, Result) :-
  723    '$inference_limit'(Limit, OLimit),
  724    (   catch(G, Except,
  725              system:'$inference_limit_except'(OLimit, Except, Result0)),
  726        system:'$inference_limit_true'(Limit, OLimit, Result0),
  727        ( Result0 == ! -> ! ; true ),
  728        Result = Result0
  729    ;   system:'$inference_limit_false'(OLimit)
  730    ).
  731
  732
  733                /********************************
  734                *           DATA BASE           *
  735                *********************************/
  736
  737/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  738The predicate current_predicate/2 is   a  difficult subject since  the
  739introduction  of defaulting     modules   and   dynamic     libraries.
  740current_predicate/2 is normally  called with instantiated arguments to
  741verify some  predicate can   be called without trapping   an undefined
  742predicate.  In this case we must  perform the search algorithm used by
  743the prolog system itself.
  744
  745If the pattern is not fully specified, we only generate the predicates
  746actually available in this  module.   This seems the best for listing,
  747etc.
  748- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  749
  750
  751:- meta_predicate
  752    current_predicate(?, :),
  753    '$defined_predicate'(:).  754
  755current_predicate(Name, Module:Head) :-
  756    (var(Module) ; var(Head)),
  757    !,
  758    generate_current_predicate(Name, Module, Head).
  759current_predicate(Name, Term) :-
  760    '$c_current_predicate'(Name, Term),
  761    '$defined_predicate'(Term),
  762    !.
  763current_predicate(Name, Module:Head) :-
  764    default_module(Module, DefModule),
  765    '$c_current_predicate'(Name, DefModule:Head),
  766    '$defined_predicate'(DefModule:Head),
  767    !.
  768current_predicate(Name, Module:Head) :-
  769    current_prolog_flag(autoload, true),
  770    \+ current_prolog_flag(Module:unknown, fail),
  771    (   compound(Head)
  772    ->  compound_name_arity(Head, Name, Arity)
  773    ;   Name = Head, Arity = 0
  774    ),
  775    '$find_library'(Module, Name, Arity, _LoadModule, _Library),
  776    !.
  777
  778generate_current_predicate(Name, Module, Head) :-
  779    current_module(Module),
  780    QHead = Module:Head,
  781    '$c_current_predicate'(Name, QHead),
  782    '$get_predicate_attribute'(QHead, defined, 1).
  783
  784'$defined_predicate'(Head) :-
  785    '$get_predicate_attribute'(Head, defined, 1),
  786    !.
 predicate_property(?Predicate, ?Property) is nondet
True when Property is a property of Predicate.
  792:- meta_predicate
  793    predicate_property(:, ?).  794
  795:- multifile
  796    '$predicate_property'/2.  797
  798:- '$iso'(predicate_property/2).  799
  800predicate_property(Pred, Property) :-           % Mode ?,+
  801    nonvar(Property),
  802    !,
  803    property_predicate(Property, Pred).
  804predicate_property(Pred, Property) :-           % Mode +,-
  805    define_or_generate(Pred),
  806    '$predicate_property'(Property, Pred).
 property_predicate(+Property, ?Pred)
First handle the special cases that are not about querying normally defined predicates: undefined, visible and autoload, followed by the generic case.
  814property_predicate(undefined, Pred) :-
  815    !,
  816    Pred = Module:Head,
  817    current_module(Module),
  818    '$c_current_predicate'(_, Pred),
  819    \+ '$defined_predicate'(Pred),          % Speed up a bit
  820    \+ current_predicate(_, Pred),
  821    goal_name_arity(Head, Name, Arity),
  822    \+ system_undefined(Module:Name/Arity).
  823property_predicate(visible, Pred) :-
  824    !,
  825    visible_predicate(Pred).
  826property_predicate(autoload(File), _:Head) :-
  827    !,
  828    current_prolog_flag(autoload, true),
  829    (   callable(Head)
  830    ->  goal_name_arity(Head, Name, Arity),
  831        (   '$find_library'(_, Name, Arity, _, File)
  832        ->  true
  833        )
  834    ;   '$in_library'(Name, Arity, File),
  835        functor(Head, Name, Arity)
  836    ).
  837property_predicate(implementation_module(IM), M:Head) :-
  838    !,
  839    atom(M),
  840    (   default_module(M, DM),
  841        '$get_predicate_attribute'(DM:Head, defined, 1)
  842    ->  (   '$get_predicate_attribute'(DM:Head, imported, ImportM)
  843        ->  IM = ImportM
  844        ;   IM = M
  845        )
  846    ;   \+ current_prolog_flag(M:unknown, fail),
  847        goal_name_arity(Head, Name, Arity),
  848        '$find_library'(_, Name, Arity, LoadModule, _File)
  849    ->  IM = LoadModule
  850    ;   M = IM
  851    ).
  852property_predicate(iso, _:Head) :-
  853    callable(Head),
  854    !,
  855    goal_name_arity(Head, Name, Arity),
  856    current_predicate(system:Name/Arity),
  857    '$predicate_property'(iso, system:Head).
  858property_predicate(Property, Pred) :-
  859    define_or_generate(Pred),
  860    '$predicate_property'(Property, Pred).
  861
  862goal_name_arity(Head, Name, Arity) :-
  863    compound(Head),
  864    !,
  865    compound_name_arity(Head, Name, Arity).
  866goal_name_arity(Head, Head, 0).
 define_or_generate(+Head) is semidet
define_or_generate(-Head) is nondet
If the predicate is known, try to resolve it. Otherwise generate the known predicate, but do not try to (auto)load the predicate.
  875define_or_generate(M:Head) :-
  876    callable(Head),
  877    atom(M),
  878    '$get_predicate_attribute'(M:Head, defined, 1),
  879    !.
  880define_or_generate(M:Head) :-
  881    callable(Head),
  882    nonvar(M), M \== system,
  883    !,
  884    '$define_predicate'(M:Head).
  885define_or_generate(Pred) :-
  886    current_predicate(_, Pred),
  887    '$define_predicate'(Pred).
  888
  889
  890'$predicate_property'(interpreted, Pred) :-
  891    '$get_predicate_attribute'(Pred, foreign, 0).
  892'$predicate_property'(visible, Pred) :-
  893    '$get_predicate_attribute'(Pred, defined, 1).
  894'$predicate_property'(built_in, Pred) :-
  895    '$get_predicate_attribute'(Pred, system, 1).
  896'$predicate_property'(exported, Pred) :-
  897    '$get_predicate_attribute'(Pred, exported, 1).
  898'$predicate_property'(public, Pred) :-
  899    '$get_predicate_attribute'(Pred, public, 1).
  900'$predicate_property'(non_terminal, Pred) :-
  901    '$get_predicate_attribute'(Pred, non_terminal, 1).
  902'$predicate_property'(foreign, Pred) :-
  903    '$get_predicate_attribute'(Pred, foreign, 1).
  904'$predicate_property'((dynamic), Pred) :-
  905    '$get_predicate_attribute'(Pred, (dynamic), 1).
  906'$predicate_property'((static), Pred) :-
  907    '$get_predicate_attribute'(Pred, (dynamic), 0).
  908'$predicate_property'((volatile), Pred) :-
  909    '$get_predicate_attribute'(Pred, (volatile), 1).
  910'$predicate_property'((thread_local), Pred) :-
  911    '$get_predicate_attribute'(Pred, (thread_local), 1).
  912'$predicate_property'((multifile), Pred) :-
  913    '$get_predicate_attribute'(Pred, (multifile), 1).
  914'$predicate_property'(imported_from(Module), Pred) :-
  915    '$get_predicate_attribute'(Pred, imported, Module).
  916'$predicate_property'(transparent, Pred) :-
  917    '$get_predicate_attribute'(Pred, transparent, 1).
  918'$predicate_property'(meta_predicate(Pattern), Pred) :-
  919    '$get_predicate_attribute'(Pred, meta_predicate, Pattern).
  920'$predicate_property'(file(File), Pred) :-
  921    '$get_predicate_attribute'(Pred, file, File).
  922'$predicate_property'(line_count(LineNumber), Pred) :-
  923    '$get_predicate_attribute'(Pred, line_count, LineNumber).
  924'$predicate_property'(notrace, Pred) :-
  925    '$get_predicate_attribute'(Pred, trace, 0).
  926'$predicate_property'(nodebug, Pred) :-
  927    '$get_predicate_attribute'(Pred, hide_childs, 1).
  928'$predicate_property'(spying, Pred) :-
  929    '$get_predicate_attribute'(Pred, spy, 1).
  930'$predicate_property'(number_of_clauses(N), Pred) :-
  931    '$get_predicate_attribute'(Pred, number_of_clauses, N).
  932'$predicate_property'(number_of_rules(N), Pred) :-
  933    '$get_predicate_attribute'(Pred, number_of_rules, N).
  934'$predicate_property'(last_modified_generation(Gen), Pred) :-
  935    '$get_predicate_attribute'(Pred, last_modified_generation, Gen).
  936'$predicate_property'(indexed(Indices), Pred) :-
  937    '$get_predicate_attribute'(Pred, indexed, Indices).
  938'$predicate_property'(noprofile, Pred) :-
  939    '$get_predicate_attribute'(Pred, noprofile, 1).
  940'$predicate_property'(iso, Pred) :-
  941    '$get_predicate_attribute'(Pred, iso, 1).
  942'$predicate_property'(quasi_quotation_syntax, Pred) :-
  943    '$get_predicate_attribute'(Pred, quasi_quotation_syntax, 1).
  944'$predicate_property'(defined, Pred) :-
  945    '$get_predicate_attribute'(Pred, defined, 1).
  946'$predicate_property'(tabled(Mode), Pred) :-
  947    '$get_predicate_attribute'(Pred, tabled, 1),
  948    '$tbl_implementation'(Pred, M:Head),
  949    M:'$tabled'(Head, Mode).
  950
  951system_undefined(user:prolog_trace_interception/4).
  952system_undefined(user:prolog_exception_hook/4).
  953system_undefined(system:'$c_call_prolog'/0).
  954system_undefined(system:window_title/2).
 visible_predicate(:Head) is nondet
True when Head can be called without raising an existence error. This implies it is defined, can be inherited from a default module or can be autoloaded.
  962visible_predicate(Pred) :-
  963    Pred = M:Head,
  964    current_module(M),
  965    (   callable(Head)
  966    ->  (   '$get_predicate_attribute'(Pred, defined, 1)
  967        ->  true
  968        ;   \+ current_prolog_flag(M:unknown, fail),
  969            functor(Head, Name, Arity),
  970            '$find_library'(M, Name, Arity, _LoadModule, _Library)
  971        )
  972    ;   setof(PI, visible_in_module(M, PI), PIs),
  973        '$member'(Name/Arity, PIs),
  974        functor(Head, Name, Arity)
  975    ).
  976
  977visible_in_module(M, Name/Arity) :-
  978    default_module(M, DefM),
  979    DefHead = DefM:Head,
  980    '$c_current_predicate'(_, DefHead),
  981    '$get_predicate_attribute'(DefHead, defined, 1),
  982    \+ hidden_system_predicate(Head),
  983    functor(Head, Name, Arity).
  984visible_in_module(_, Name/Arity) :-
  985    '$in_library'(Name, Arity, _).
  986
  987hidden_system_predicate(Head) :-
  988    functor(Head, Name, _),
  989    atom(Name),                     % Avoid [].
  990    sub_atom(Name, 0, _, _, $),
  991    \+ current_prolog_flag(access_level, system).
 clause_property(+ClauseRef, ?Property) is nondet
Provide information on individual clauses. Defined properties are:
line_count(-Line)
Line from which the clause is loaded.
file(-File)
File from which the clause is loaded.
source(-File)
File that `owns' the clause: reloading this file wipes the clause.
fact
Clause has body true.
erased
Clause was erased.
predicate(:PI)
Predicate indicator of the predicate this clause belongs to. Can be used to find the predicate of erased clauses.
module(-M)
Module context in which the clause was compiled.
 1016clause_property(Clause, Property) :-
 1017    '$clause_property'(Property, Clause).
 1018
 1019'$clause_property'(line_count(LineNumber), Clause) :-
 1020    '$get_clause_attribute'(Clause, line_count, LineNumber).
 1021'$clause_property'(file(File), Clause) :-
 1022    '$get_clause_attribute'(Clause, file, File).
 1023'$clause_property'(source(File), Clause) :-
 1024    '$get_clause_attribute'(Clause, owner, File).
 1025'$clause_property'(size(Bytes), Clause) :-
 1026    '$get_clause_attribute'(Clause, size, Bytes).
 1027'$clause_property'(fact, Clause) :-
 1028    '$get_clause_attribute'(Clause, fact, true).
 1029'$clause_property'(erased, Clause) :-
 1030    '$get_clause_attribute'(Clause, erased, true).
 1031'$clause_property'(predicate(PI), Clause) :-
 1032    '$get_clause_attribute'(Clause, predicate_indicator, PI).
 1033'$clause_property'(module(M), Clause) :-
 1034    '$get_clause_attribute'(Clause, module, M).
 1035
 1036
 1037                 /*******************************
 1038                 *             REQUIRE          *
 1039                 *******************************/
 1040
 1041:- meta_predicate
 1042    require(:).
 require(:ListOfPredIndicators) is det
Tag given predicates as undefined, so they will be included into a saved state through the autoloader.
See also
- autoload/0.
 1051require(M:List) :-
 1052    (   is_list(List)
 1053    ->  require(List, M)
 1054    ;   throw(error(type_error(list, List), _))
 1055    ).
 1056
 1057require([], _).
 1058require([N/A|T], M) :-
 1059    !,
 1060    functor(Head, N, A),
 1061    '$require'(M:Head),
 1062    require(T, M).
 1063require([H|_T], _) :-
 1064    throw(error(type_error(predicate_indicator, H), _)).
 1065
 1066
 1067                /********************************
 1068                *            MODULES            *
 1069                *********************************/
 current_module(?Module) is nondet
True if Module is a currently defined module.
 1075current_module(Module) :-
 1076    '$current_module'(Module, _).
 module_property(?Module, ?Property) is nondet
True if Property is a property of Module. Defined properties are:
file(File)
Module is loaded from File.
line_count(Count)
The module declaration is on line Count of File.
exports(ListOfPredicateIndicators)
The module exports ListOfPredicateIndicators
exported_operators(ListOfOp3)
The module exports the operators ListOfOp3.
 1092module_property(Module, Property) :-
 1093    nonvar(Module), nonvar(Property),
 1094    !,
 1095    property_module(Property, Module).
 1096module_property(Module, Property) :-    % -, file(File)
 1097    nonvar(Property), Property = file(File),
 1098    !,
 1099    (   nonvar(File)
 1100    ->  '$current_module'(Modules, File),
 1101        (   atom(Modules)
 1102        ->  Module = Modules
 1103        ;   '$member'(Module, Modules)
 1104        )
 1105    ;   '$current_module'(Module, File),
 1106        File \== []
 1107    ).
 1108module_property(Module, Property) :-
 1109    current_module(Module),
 1110    property_module(Property, Module).
 1111
 1112property_module(Property, Module) :-
 1113    module_property(Property),
 1114    (   Property = exported_operators(List)
 1115    ->  '$exported_ops'(Module, List, []),
 1116        List \== []
 1117    ;   '$module_property'(Module, Property)
 1118    ).
 1119
 1120module_property(class(_)).
 1121module_property(file(_)).
 1122module_property(line_count(_)).
 1123module_property(exports(_)).
 1124module_property(exported_operators(_)).
 1125module_property(program_size(_)).
 1126module_property(program_space(_)).
 1127module_property(last_modified_generation(_)).
 module(+Module) is det
Set the module that is associated to the toplevel to Module.
 1133module(Module) :-
 1134    atom(Module),
 1135    current_module(Module),
 1136    !,
 1137    '$set_typein_module'(Module).
 1138module(Module) :-
 1139    '$set_typein_module'(Module),
 1140    print_message(warning, no_current_module(Module)).
 working_directory(-Old, +New)
True when Old is the current working directory and the working directory has been updated to New.
 1147working_directory(Old, New) :-
 1148    '$cwd'(Old),
 1149    (   Old == New
 1150    ->  true
 1151    ;   '$chdir'(New)
 1152    ).
 1153
 1154
 1155                 /*******************************
 1156                 *            TRIES             *
 1157                 *******************************/
 current_trie(?Trie) is nondet
True if Trie is the handle of an existing trie.
 1163current_trie(Trie) :-
 1164    current_blob(Trie, trie),
 1165    is_trie(Trie).
 trie_property(?Trie, ?Property)
True when Property is a property of Trie. Defined properties are:
value_count(Count)
Number of terms in the trie.
node_count(Count)
Number of nodes in the trie.
size(Bytes)
Number of bytes needed to store the trie.
hashed(Count)
Number of hashed nodes.
 1181trie_property(Trie, Property) :-
 1182    current_trie(Trie),
 1183    trie_property(Property),
 1184    '$trie_property'(Trie, Property).
 1185
 1186trie_property(node_count(_)).
 1187trie_property(value_count(_)).
 1188trie_property(size(_)).
 1189trie_property(hashed(_)).
 1190                                                % below only when -DO_TRIE_STATS
 1191trie_property(lookup_count(_)).                 % is enabled in pl-trie.h
 1192trie_property(gen_call_count(_)).
 1193trie_property(gen_exit_count(_)).
 1194trie_property(gen_fail_count(_)).
 1195
 1196
 1197                /********************************
 1198                *      SYSTEM INTERACTION       *
 1199                *********************************/
 1200
 1201shell(Command) :-
 1202    shell(Command, 0).
 1203
 1204
 1205                 /*******************************
 1206                 *            SIGNALS           *
 1207                 *******************************/
 1208
 1209:- meta_predicate
 1210    on_signal(+, :, :),
 1211    current_signal(?, ?, :).
 on_signal(+Signal, -OldHandler, :NewHandler) is det
 1215on_signal(Signal, Old, New) :-
 1216    atom(Signal),
 1217    !,
 1218    '$on_signal'(_Num, Signal, Old, New).
 1219on_signal(Signal, Old, New) :-
 1220    integer(Signal),
 1221    !,
 1222    '$on_signal'(Signal, _Name, Old, New).
 1223on_signal(Signal, _Old, _New) :-
 1224    '$type_error'(signal_name, Signal).
 current_signal(?Name, ?SignalNumber, :Handler) is nondet
 1228current_signal(Name, Id, Handler) :-
 1229    between(1, 32, Id),
 1230    '$on_signal'(Id, Name, Handler, Handler).
 1231
 1232:- multifile
 1233    prolog:called_by/2. 1234
 1235prolog:called_by(on_signal(_,_,New), [New+1]) :-
 1236    (   new == throw
 1237    ;   new == default
 1238    ), !, fail.
 1239
 1240
 1241                 /*******************************
 1242                 *            DLOPEN            *
 1243                 *******************************/
 open_shared_object(+File, -Handle) is det
 open_shared_object(+File, -Handle, +Flags) is det
Open a shared object or DLL file. Flags is a list of flags. The following flags are recognised. Note however that these flags may have no affect on the target platform.
 1257open_shared_object(File, Handle) :-
 1258    open_shared_object(File, Handle, []). % use pl-load.c defaults
 1259
 1260open_shared_object(File, Handle, Flags) :-
 1261    (   is_list(Flags)
 1262    ->  true
 1263    ;   throw(error(type_error(list, Flags), _))
 1264    ),
 1265    map_dlflags(Flags, Mask),
 1266    '$open_shared_object'(File, Handle, Mask).
 1267
 1268dlopen_flag(now,        2'01).          % see pl-load.c for these constants
 1269dlopen_flag(global,     2'10).          % Solaris only
 1270
 1271map_dlflags([], 0).
 1272map_dlflags([F|T], M) :-
 1273    map_dlflags(T, M0),
 1274    (   dlopen_flag(F, I)
 1275    ->  true
 1276    ;   throw(error(domain_error(dlopen_flag, F), _))
 1277    ),
 1278    M is M0 \/ I.
 1279
 1280
 1281                 /*******************************
 1282                 *             I/O              *
 1283                 *******************************/
 1284
 1285format(Fmt) :-
 1286    format(Fmt, []).
 1287
 1288                 /*******************************
 1289                 *            FILES             *
 1290                 *******************************/
 absolute_file_name(+Term, -AbsoluteFile)
 1294absolute_file_name(Name, Abs) :-
 1295    atomic(Name),
 1296    !,
 1297    '$absolute_file_name'(Name, Abs).
 1298absolute_file_name(Term, Abs) :-
 1299    '$chk_file'(Term, [''], [access(read)], true, File),
 1300    !,
 1301    '$absolute_file_name'(File, Abs).
 1302absolute_file_name(Term, Abs) :-
 1303    '$chk_file'(Term, [''], [], true, File),
 1304    !,
 1305    '$absolute_file_name'(File, Abs).
 tmp_file_stream(-File, -Stream, +Options) is det
tmp_file_stream(+Encoding, -File, -Stream) is det
Create a temporary file and open it atomically. The second mode is for compatibility reasons.
 1313tmp_file_stream(Enc, File, Stream) :-
 1314    atom(Enc), var(File), var(Stream),
 1315    !,
 1316    '$tmp_file_stream'('', Enc, File, Stream).
 1317tmp_file_stream(File, Stream, Options) :-
 1318    current_prolog_flag(encoding, DefEnc),
 1319    '$option'(encoding(Enc), Options, DefEnc),
 1320    '$option'(extension(Ext), Options, ''),
 1321    '$tmp_file_stream'(Ext, Enc, File, Stream),
 1322    set_stream(Stream, file_name(File)).
 1323
 1324
 1325                /********************************
 1326                *        MEMORY MANAGEMENT      *
 1327                *********************************/
 garbage_collect is det
Invoke the garbage collector. The argument of the underlying '$garbage_collect'/1 is the debugging level to use during garbage collection. This only works if the system is compiled with the -DODEBUG cpp flag. Only to simplify maintenance.
 1336garbage_collect :-
 1337    '$garbage_collect'(0).
 set_prolog_stack(+Name, +Option) is det
Set a parameter for one of the Prolog stacks.
 1343set_prolog_stack(Stack, Option) :-
 1344    Option =.. [Name,Value0],
 1345    Value is Value0,
 1346    '$set_prolog_stack'(Stack, Name, _Old, Value).
 prolog_stack_property(?Stack, ?Property) is nondet
Examine stack properties.
 1352prolog_stack_property(Stack, Property) :-
 1353    stack_property(P),
 1354    stack_name(Stack),
 1355    Property =.. [P,Value],
 1356    '$set_prolog_stack'(Stack, P, Value, Value).
 1357
 1358stack_name(local).
 1359stack_name(global).
 1360stack_name(trail).
 1361
 1362stack_property(limit).
 1363stack_property(spare).
 1364stack_property(min_free).
 1365stack_property(low).
 1366stack_property(factor).
 1367
 1368
 1369                 /*******************************
 1370                 *             TERM             *
 1371                 *******************************/
 1372
 1373:- '$iso'((numbervars/3)).
 numbervars(+Term, +StartIndex, -EndIndex) is det
Number all unbound variables in Term using '$VAR'(N), where the first N is StartIndex and EndIndex is unified to the index that will be given to the next variable.
 1381numbervars(Term, From, To) :-
 1382    numbervars(Term, From, To, []).
 1383
 1384
 1385                 /*******************************
 1386                 *            STRING            *
 1387                 *******************************/
 term_string(?Term, ?String, +Options)
Parse/write a term from/to a string using Options.
 1393term_string(Term, String, Options) :-
 1394    nonvar(String),
 1395    !,
 1396    read_term_from_atom(String, Term, Options).
 1397term_string(Term, String, Options) :-
 1398    (   '$option'(quoted(_), Options)
 1399    ->  Options1 = Options
 1400    ;   '$merge_options'(_{quoted:true}, Options, Options1)
 1401    ),
 1402    format(string(String), '~W', [Term, Options1]).
 1403
 1404
 1405                 /*******************************
 1406                 *             GVAR             *
 1407                 *******************************/
 nb_setval(+Name, +Value) is det
Bind the non-backtrackable variable Name with a copy of Value
 1413nb_setval(Name, Value) :-
 1414    duplicate_term(Value, Copy),
 1415    nb_linkval(Name, Copy).
 1416
 1417
 1418		 /*******************************
 1419		 *            THREADS		*
 1420		 *******************************/
 1421
 1422:- meta_predicate
 1423    thread_create(0, -).
 thread_create(:Goal, -Id)
Shorthand for thread_create(Goal, Id, []).
 1429thread_create(Goal, Id) :-
 1430    thread_create(Goal, Id, []).
 thread_join(+Id)
Join a thread and raise an error of the thread did not succeed.
Errors
- thread_error(Status), where Status is the result of thread_join/2.
 1439thread_join(Id) :-
 1440    thread_join(Id, Status),
 1441    (   Status == true
 1442    ->  true
 1443    ;   throw(error(thread_error(Status), _))
 1444    ).
 set_prolog_gc_thread(+Status)
Control the GC thread. Status is one of
false
Disable the separate GC thread, running atom and clause garbage collection in the triggering thread.
true
Enable the separate GC thread. All implicit atom and clause garbage collection is executed by the thread gc.
stop
Stop the gc thread if it is running. The thread is recreated on the next implicit atom or clause garbage collection. Used by fork/1 to avoid forking a multi-threaded application.
 1461set_prolog_gc_thread(Status) :-
 1462    var(Status),
 1463    !,
 1464    '$instantiation_error'(Status).
 1465set_prolog_gc_thread(false) :-
 1466    !,
 1467    set_prolog_flag(gc_thread, false),
 1468    (   current_prolog_flag(threads, true)
 1469    ->  (   '$gc_stop'
 1470        ->  thread_join(gc)
 1471        ;   true
 1472        )
 1473    ;   true
 1474    ).
 1475set_prolog_gc_thread(true) :-
 1476    !,
 1477    set_prolog_flag(gc_thread, true).
 1478set_prolog_gc_thread(stop) :-
 1479    !,
 1480    (   current_prolog_flag(threads, true)
 1481    ->  (   '$gc_stop'
 1482        ->  thread_join(gc)
 1483        ;   true
 1484        )
 1485    ;   true
 1486    ).
 1487set_prolog_gc_thread(Status) :-
 1488    '$domain_error'(gc_thread, Status).
 $wrap_predicate(:Head, +Name, -Wrapped, +Body) is det
Would be nicer to have this from library(prolog_wrap), but we need it for tabling, so it must be a system predicate.
 1495:- meta_predicate
 1496    '$wrap_predicate'(:, +, -, +). 1497
 1498'$wrap_predicate'(M:Head, WName, call(Wrapped), Body) :-
 1499    callable_name_arguments(Head, PName, Args),
 1500    distinct_vars(Args, Head, Arity),
 1501    atomic_list_concat(['__wrap$', PName], WrapName),
 1502    volatile(M:WrapName/Arity),
 1503    WHead =.. [WrapName|Args],
 1504    '$c_wrap_predicate'(M:Head, WName, Wrapped, M:(WHead :- Body)).
 1505
 1506distinct_vars(Vars, _, Arity) :-
 1507    all_vars(Vars),
 1508    sort(Vars, Sorted),
 1509    length(Vars, Arity),
 1510    length(Sorted, Arity),
 1511    !.
 1512distinct_vars(_, Head, _) :-
 1513    '$domain_error'('most_general_term', Head).
 1514
 1515all_vars([]).
 1516all_vars([H|T]) :-
 1517    (   var(H)
 1518    ->  all_vars(T)
 1519    ;   '$uninstantiation_error'(H)
 1520    ).
 1521
 1522callable_name_arguments(Head, PName, Args) :-
 1523    atom(Head),
 1524    !,
 1525    PName = Head,
 1526    Args = [].
 1527callable_name_arguments(Head, PName, Args) :-
 1528    compound_name_arguments(Head, PName, Args)