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

  195:- multifile
  196    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.
  204:- meta_predicate
  205    trace(:),
  206    trace(:, +).  207
  208trace(Preds) :-
  209    trace(Preds, +all).
  210
  211trace(_:X, _) :-
  212    var(X),
  213    !,
  214    throw(error(instantiation_error, _)).
  215trace(_:[], _) :- !.
  216trace(M:[H|T], Ps) :-
  217    !,
  218    trace(M:H, Ps),
  219    trace(M:T, Ps).
  220trace(Pred, Ports) :-
  221    '$find_predicate'(Pred, Preds),
  222    Preds \== [],
  223    set_prolog_flag(debug, true),
  224    (   '$member'(PI, Preds),
  225            pi_to_head(PI, Head),
  226            (   Head = _:_
  227            ->  QHead0 = Head
  228            ;   QHead0 = user:Head
  229            ),
  230            '$define_predicate'(QHead0),
  231            (   predicate_property(QHead0, imported_from(M))
  232            ->  QHead0 = _:Plain,
  233                QHead = M:Plain
  234            ;   QHead = QHead0
  235            ),
  236            '$trace'(Ports, QHead),
  237            trace_ports(QHead, Tracing),
  238            print_message(informational, trace(QHead, Tracing)),
  239        fail
  240    ;   true
  241    ).
  242
  243trace_alias(all,  [trace_call, trace_redo, trace_exit, trace_fail]).
  244trace_alias(call, [trace_call]).
  245trace_alias(redo, [trace_redo]).
  246trace_alias(exit, [trace_exit]).
  247trace_alias(fail, [trace_fail]).
  248
  249'$trace'([], _) :- !.
  250'$trace'([H|T], Head) :-
  251    !,
  252    '$trace'(H, Head),
  253    '$trace'(T, Head).
  254'$trace'(+H, Head) :-
  255    trace_alias(H, A0),
  256    !,
  257    tag_list(A0, +, A1),
  258    '$trace'(A1, Head).
  259'$trace'(+H, Head) :-
  260    !,
  261    trace_alias(_, [H]),
  262    '$set_predicate_attribute'(Head, H, true).
  263'$trace'(-H, Head) :-
  264    trace_alias(H, A0),
  265    !,
  266    tag_list(A0, -, A1),
  267    '$trace'(A1, Head).
  268'$trace'(-H, Head) :-
  269    !,
  270    trace_alias(_, [H]),
  271    '$set_predicate_attribute'(Head, H, false).
  272'$trace'(H, Head) :-
  273    atom(H),
  274    '$trace'(+H, Head).
  275
  276tag_list([], _, []).
  277tag_list([H0|T0], F, [H1|T1]) :-
  278    H1 =.. [F, H0],
  279    tag_list(T0, F, T1).
  280
  281:- meta_predicate
  282    spy(:),
  283    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.
  300spy(_:X) :-
  301    var(X),
  302    throw(error(instantiation_error, _)).
  303spy(_:[]) :- !.
  304spy(M:[H|T]) :-
  305    !,
  306    spy(M:H),
  307    spy(M:T).
  308spy(Spec) :-
  309    notrace(prolog:debug_control_hook(spy(Spec))),
  310    !.
  311spy(Spec) :-
  312    '$find_predicate'(Spec, Preds),
  313    '$member'(PI, Preds),
  314        pi_to_head(PI, Head),
  315        '$define_predicate'(Head),
  316        '$spy'(Head),
  317    fail.
  318spy(_).
  319
  320nospy(_:X) :-
  321    var(X),
  322    throw(error(instantiation_error, _)).
  323nospy(_:[]) :- !.
  324nospy(M:[H|T]) :-
  325    !,
  326    nospy(M:H),
  327    nospy(M:T).
  328nospy(Spec) :-
  329    notrace(prolog:debug_control_hook(nospy(Spec))),
  330    !.
  331nospy(Spec) :-
  332    '$find_predicate'(Spec, Preds),
  333    '$member'(PI, Preds),
  334         pi_to_head(PI, Head),
  335        '$nospy'(Head),
  336    fail.
  337nospy(_).
  338
  339nospyall :-
  340    notrace(prolog:debug_control_hook(nospyall)),
  341    fail.
  342nospyall :-
  343    spy_point(Head),
  344        '$nospy'(Head),
  345    fail.
  346nospyall.
  347
  348pi_to_head(M:PI, M:Head) :-
  349    !,
  350    pi_to_head(PI, Head).
  351pi_to_head(Name/Arity, Head) :-
  352    functor(Head, Name, Arity).
 debugging is det
Report current status of the debugger.
  358debugging :-
  359    notrace(prolog:debug_control_hook(debugging)),
  360    !.
  361debugging :-
  362    current_prolog_flag(debug, true),
  363    !,
  364    print_message(informational, debugging(on)),
  365    findall(H, spy_point(H), SpyPoints),
  366    print_message(informational, spying(SpyPoints)),
  367    findall(trace(H,P), trace_point(H,P), TracePoints),
  368    print_message(informational, tracing(TracePoints)).
  369debugging :-
  370    print_message(informational, debugging(off)).
  371
  372spy_point(Module:Head) :-
  373    current_predicate(_, Module:Head),
  374    '$get_predicate_attribute'(Module:Head, spy, 1),
  375    \+ predicate_property(Module:Head, imported_from(_)).
  376
  377trace_point(Module:Head, Ports) :-
  378    current_predicate(_, Module:Head),
  379        '$get_predicate_attribute'(Module:Head, trace_any, 1),
  380        \+ predicate_property(Module:Head, imported_from(_)),
  381        trace_ports(Module:Head, Ports).
  382
  383trace_ports(Head, Ports) :-
  384    findall(Port,
  385            (trace_alias(Port, [AttName]),
  386             '$get_predicate_attribute'(Head, AttName, 1)),
  387            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.
  395flag(Name, Old, New) :-
  396    Old == New,
  397    !,
  398    get_flag(Name, Old).
  399flag(Name, Old, New) :-
  400    with_mutex('$flag', update_flag(Name, Old, New)).
  401
  402update_flag(Name, Old, New) :-
  403    get_flag(Name, Old),
  404    (   atom(New)
  405    ->  set_flag(Name, New)
  406    ;   Value is New,
  407        set_flag(Name, Value)
  408    ).
  409
  410
  411                 /*******************************
  412                 *            RATIONAL          *
  413                 *******************************/
 rational(+Rat, -Numerator, -Denominator) is semidet
True when Rat is a rational number with given Numerator and Denominator.
  420rational(Rat, M, N) :-
  421    rational(Rat),
  422    (   Rat = rdiv(M, N)
  423    ->  true
  424    ;   integer(Rat)
  425    ->  M = Rat,
  426        N = 1
  427    ).
  428
  429
  430                /********************************
  431                *             ATOMS             *
  432                *********************************/
  433
  434dwim_match(A1, A2) :-
  435    dwim_match(A1, A2, _).
  436
  437atom_prefix(Atom, Prefix) :-
  438    sub_atom(Atom, 0, _, _, Prefix).
  439
  440
  441                /********************************
  442                *             SOURCE            *
  443                *********************************/
 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.

  456source_file(File) :-
  457    (   current_prolog_flag(access_level, user)
  458    ->  Level = user
  459    ;   true
  460    ),
  461    (   ground(File)
  462    ->  (   '$time_source_file'(File, Time, Level)
  463        ;   absolute_file_name(File, Abs),
  464            '$time_source_file'(Abs, Time, Level)
  465        ), !
  466    ;   '$time_source_file'(File, Time, Level)
  467    ),
  468    Time > 0.0.
 source_file(+Head, -File) is semidet
source_file(?Head, ?File) is nondet
True when Head is a predicate owned by File.
  475:- meta_predicate source_file(:, ?).  476
  477source_file(M:Head, File) :-
  478    nonvar(M), nonvar(Head),
  479    !,
  480    (   '$c_current_predicate'(_, M:Head),
  481        predicate_property(M:Head, multifile)
  482    ->  multi_source_files(M:Head, Files),
  483        '$member'(File, Files)
  484    ;   '$source_file'(M:Head, File)
  485    ).
  486source_file(M:Head, File) :-
  487    (   nonvar(File)
  488    ->  true
  489    ;   source_file(File)
  490    ),
  491    '$source_file_predicates'(File, Predicates),
  492    '$member'(M:Head, Predicates).
  493
  494:- thread_local found_src_file/1.  495
  496multi_source_files(Head, Files) :-
  497    call_cleanup(
  498        findall(File, multi_source_file(Head, File), Files),
  499        retractall(found_src_file(_))).
  500
  501multi_source_file(Head, File) :-
  502    nth_clause(Head, _, Clause),
  503    clause_property(Clause, source(File)),
  504    \+ found_src_file(File),
  505    asserta(found_src_file(File)).
 source_file_property(?File, ?Property) is nondet
True if Property is a property of the loaded source-file File.
  512source_file_property(File, P) :-
  513    nonvar(File),
  514    !,
  515    canonical_source_file(File, Path),
  516    property_source_file(P, Path).
  517source_file_property(File, P) :-
  518    property_source_file(P, File).
  519
  520property_source_file(modified(Time), File) :-
  521    '$time_source_file'(File, Time, user).
  522property_source_file(source(Source), File) :-
  523    (   '$source_file_property'(File, from_state, true)
  524    ->  Source = state
  525    ;   '$source_file_property'(File, resource, true)
  526    ->  Source = resource
  527    ;   Source = file
  528    ).
  529property_source_file(module(M), File) :-
  530    (   nonvar(M)
  531    ->  '$current_module'(M, File)
  532    ;   nonvar(File)
  533    ->  '$current_module'(ML, File),
  534        (   atom(ML)
  535        ->  M = ML
  536        ;   '$member'(M, ML)
  537        )
  538    ;   '$current_module'(M, File)
  539    ).
  540property_source_file(load_context(Module, Location, Options), File) :-
  541    '$time_source_file'(File, _, user),
  542    clause(system:'$load_context_module'(File, Module, Options), true, Ref),
  543    (   clause_property(Ref, file(FromFile)),
  544        clause_property(Ref, line_count(FromLine))
  545    ->  Location = FromFile:FromLine
  546    ;   Location = user
  547    ).
  548property_source_file(includes(Master, Stamp), File) :-
  549    system:'$included'(File, _Line, Master, Stamp).
  550property_source_file(included_in(Master, Line), File) :-
  551    system:'$included'(Master, Line, File, _).
  552property_source_file(derived_from(DerivedFrom, Stamp), File) :-
  553    system:'$derived_source'(File, DerivedFrom, Stamp).
  554property_source_file(reloading, File) :-
  555    source_file(File),
  556    '$source_file_property'(File, reloading, true).
  557property_source_file(load_count(Count), File) :-
  558    source_file(File),
  559    '$source_file_property'(File, load_count, Count).
  560property_source_file(number_of_clauses(Count), File) :-
  561    source_file(File),
  562    '$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.
  569canonical_source_file(Spec, File) :-
  570    atom(Spec),
  571    '$time_source_file'(Spec, _, _),
  572    !,
  573    File = Spec.
  574canonical_source_file(Spec, File) :-
  575    system:'$included'(_Master, _Line, Spec, _),
  576    !,
  577    File = Spec.
  578canonical_source_file(Spec, File) :-
  579    absolute_file_name(Spec,
  580                           [ file_type(prolog),
  581                             access(read),
  582                             file_errors(fail)
  583                           ],
  584                           File),
  585    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.
  594prolog_load_context(module, Module) :-
  595    '$current_source_module'(Module).
  596prolog_load_context(file, File) :-
  597    input_file(File).
  598prolog_load_context(source, F) :-       % SICStus compatibility
  599    input_file(F0),
  600    '$input_context'(Context),
  601    '$top_file'(Context, F0, F).
  602prolog_load_context(stream, S) :-
  603    (   system:'$load_input'(_, S0)
  604    ->  S = S0
  605    ).
  606prolog_load_context(directory, D) :-
  607    input_file(F),
  608    file_directory_name(F, D).
  609prolog_load_context(dialect, D) :-
  610    current_prolog_flag(emulated_dialect, D).
  611prolog_load_context(term_position, TermPos) :-
  612    source_location(_, L),
  613    (   nb_current('$term_position', Pos),
  614        compound(Pos),              % actually set
  615        stream_position_data(line_count, Pos, L)
  616    ->  TermPos = Pos
  617    ;   TermPos = '$stream_position'(0,L,0,0)
  618    ).
  619prolog_load_context(script, Bool) :-
  620    (   '$toplevel':loaded_init_file(script, Path),
  621        input_file(File),
  622        same_file(File, Path)
  623    ->  Bool = true
  624    ;   Bool = false
  625    ).
  626prolog_load_context(variable_names, Bindings) :-
  627    nb_current('$variable_names', Bindings).
  628prolog_load_context(term, Term) :-
  629    nb_current('$term', Term).
  630prolog_load_context(reloading, true) :-
  631    prolog_load_context(source, F),
  632    '$source_file_property'(F, reloading, true).
  633
  634input_file(File) :-
  635    (   system:'$load_input'(_, Stream)
  636    ->  stream_property(Stream, file_name(File))
  637    ),
  638    !.
  639input_file(File) :-
  640    source_location(File, _).
 unload_file(+File) is det
Remove all traces of loading file.
  647:- dynamic system:'$resolved_source_path'/2.  648
  649unload_file(File) :-
  650    (   canonical_source_file(File, Path)
  651    ->  '$unload_file'(Path),
  652        retractall(system:'$resolved_source_path'(_, Path))
  653    ;   true
  654    ).
  655
  656
  657                 /*******************************
  658                 *            STREAMS           *
  659                 *******************************/
 stream_position_data(?Field, +Pos, ?Date)
Extract values from stream position objects. '$stream_position' is of the format '$stream_position'(Byte, Char, Line, LinePos)
  666stream_position_data(Prop, Term, Value) :-
  667    nonvar(Prop),
  668    !,
  669    (   stream_position_field(Prop, Pos)
  670    ->  arg(Pos, Term, Value)
  671    ;   throw(error(domain_error(stream_position_data, Prop)))
  672    ).
  673stream_position_data(Prop, Term, Value) :-
  674    stream_position_field(Prop, Pos),
  675    arg(Pos, Term, Value).
  676
  677stream_position_field(char_count,    1).
  678stream_position_field(line_count,    2).
  679stream_position_field(line_position, 3).
  680stream_position_field(byte_count,    4).
  681
  682
  683                 /*******************************
  684                 *            CONTROL           *
  685                 *******************************/
 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.
  693:- meta_predicate
  694    call_with_depth_limit(0, +, -).  695
  696call_with_depth_limit(G, Limit, Result) :-
  697    '$depth_limit'(Limit, OLimit, OReached),
  698    (   catch(G, E, '$depth_limit_except'(OLimit, OReached, E)),
  699        '$depth_limit_true'(Limit, OLimit, OReached, Result, Det),
  700        ( Det == ! -> ! ; true )
  701    ;   '$depth_limit_false'(OLimit, OReached, Result)
  702    ).
 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.

  716:- meta_predicate
  717    call_with_inference_limit(0, +, -).  718
  719call_with_inference_limit(G, Limit, Result) :-
  720    '$inference_limit'(Limit, OLimit),
  721    (   catch(G, Except,
  722              system:'$inference_limit_except'(OLimit, Except, Result0)),
  723        system:'$inference_limit_true'(Limit, OLimit, Result0),
  724        ( Result0 == ! -> ! ; true ),
  725        Result = Result0
  726    ;   system:'$inference_limit_false'(OLimit)
  727    ).
  728
  729
  730                /********************************
  731                *           DATA BASE           *
  732                *********************************/
  733
  734/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  735The predicate current_predicate/2 is   a  difficult subject since  the
  736introduction  of defaulting     modules   and   dynamic     libraries.
  737current_predicate/2 is normally  called with instantiated arguments to
  738verify some  predicate can   be called without trapping   an undefined
  739predicate.  In this case we must  perform the search algorithm used by
  740the prolog system itself.
  741
  742If the pattern is not fully specified, we only generate the predicates
  743actually available in this  module.   This seems the best for listing,
  744etc.
  745- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  746
  747
  748:- meta_predicate
  749    current_predicate(?, :),
  750    '$defined_predicate'(:).  751
  752current_predicate(Name, Module:Head) :-
  753    (var(Module) ; var(Head)),
  754    !,
  755    generate_current_predicate(Name, Module, Head).
  756current_predicate(Name, Term) :-
  757    '$c_current_predicate'(Name, Term),
  758    '$defined_predicate'(Term),
  759    !.
  760current_predicate(Name, Module:Head) :-
  761    default_module(Module, DefModule),
  762    '$c_current_predicate'(Name, DefModule:Head),
  763    '$defined_predicate'(DefModule:Head),
  764    !.
  765current_predicate(Name, Module:Head) :-
  766    current_prolog_flag(autoload, true),
  767    \+ current_prolog_flag(Module:unknown, fail),
  768    (   compound(Head)
  769    ->  compound_name_arity(Head, Name, Arity)
  770    ;   Name = Head, Arity = 0
  771    ),
  772    '$find_library'(Module, Name, Arity, _LoadModule, _Library),
  773    !.
  774
  775generate_current_predicate(Name, Module, Head) :-
  776    current_module(Module),
  777    QHead = Module:Head,
  778    '$c_current_predicate'(Name, QHead),
  779    '$get_predicate_attribute'(QHead, defined, 1).
  780
  781'$defined_predicate'(Head) :-
  782    '$get_predicate_attribute'(Head, defined, 1),
  783    !.
 predicate_property(?Predicate, ?Property) is nondet
True when Property is a property of Predicate.
  789:- meta_predicate
  790    predicate_property(:, ?).  791
  792:- '$iso'(predicate_property/2).  793
  794predicate_property(Pred, Property) :-           % Mode ?,+
  795    nonvar(Property),
  796    !,
  797    property_predicate(Property, Pred).
  798predicate_property(Pred, Property) :-           % Mode +,-
  799    define_or_generate(Pred),
  800    '$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.
  808property_predicate(undefined, Pred) :-
  809    !,
  810    Pred = Module:Head,
  811    current_module(Module),
  812    '$c_current_predicate'(_, Pred),
  813    \+ '$defined_predicate'(Pred),          % Speed up a bit
  814    \+ current_predicate(_, Pred),
  815    goal_name_arity(Head, Name, Arity),
  816    \+ system_undefined(Module:Name/Arity).
  817property_predicate(visible, Pred) :-
  818    !,
  819    visible_predicate(Pred).
  820property_predicate(autoload(File), _:Head) :-
  821    !,
  822    current_prolog_flag(autoload, true),
  823    (   callable(Head)
  824    ->  goal_name_arity(Head, Name, Arity),
  825        (   '$find_library'(_, Name, Arity, _, File)
  826        ->  true
  827        )
  828    ;   '$in_library'(Name, Arity, File),
  829        functor(Head, Name, Arity)
  830    ).
  831property_predicate(implementation_module(IM), M:Head) :-
  832    !,
  833    atom(M),
  834    (   default_module(M, DM),
  835        '$get_predicate_attribute'(DM:Head, defined, 1)
  836    ->  (   '$get_predicate_attribute'(DM:Head, imported, ImportM)
  837        ->  IM = ImportM
  838        ;   IM = M
  839        )
  840    ;   \+ current_prolog_flag(M:unknown, fail),
  841        goal_name_arity(Head, Name, Arity),
  842        '$find_library'(_, Name, Arity, LoadModule, _File)
  843    ->  IM = LoadModule
  844    ;   M = IM
  845    ).
  846property_predicate(iso, _:Head) :-
  847    callable(Head),
  848    !,
  849    goal_name_arity(Head, Name, Arity),
  850    current_predicate(system:Name/Arity),
  851    '$predicate_property'(iso, system:Head).
  852property_predicate(Property, Pred) :-
  853    define_or_generate(Pred),
  854    '$predicate_property'(Property, Pred).
  855
  856goal_name_arity(Head, Name, Arity) :-
  857    compound(Head),
  858    !,
  859    compound_name_arity(Head, Name, Arity).
  860goal_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.
  869define_or_generate(M:Head) :-
  870    callable(Head),
  871    atom(M),
  872    '$get_predicate_attribute'(M:Head, defined, 1),
  873    !.
  874define_or_generate(M:Head) :-
  875    callable(Head),
  876    nonvar(M), M \== system,
  877    !,
  878    '$define_predicate'(M:Head).
  879define_or_generate(Pred) :-
  880    current_predicate(_, Pred),
  881    '$define_predicate'(Pred).
  882
  883
  884'$predicate_property'(interpreted, Pred) :-
  885    '$get_predicate_attribute'(Pred, foreign, 0).
  886'$predicate_property'(visible, Pred) :-
  887    '$get_predicate_attribute'(Pred, defined, 1).
  888'$predicate_property'(built_in, Pred) :-
  889    '$get_predicate_attribute'(Pred, system, 1).
  890'$predicate_property'(exported, Pred) :-
  891    '$get_predicate_attribute'(Pred, exported, 1).
  892'$predicate_property'(public, Pred) :-
  893    '$get_predicate_attribute'(Pred, public, 1).
  894'$predicate_property'(non_terminal, Pred) :-
  895    '$get_predicate_attribute'(Pred, non_terminal, 1).
  896'$predicate_property'(foreign, Pred) :-
  897    '$get_predicate_attribute'(Pred, foreign, 1).
  898'$predicate_property'((dynamic), Pred) :-
  899    '$get_predicate_attribute'(Pred, (dynamic), 1).
  900'$predicate_property'((static), Pred) :-
  901    '$get_predicate_attribute'(Pred, (dynamic), 0).
  902'$predicate_property'((volatile), Pred) :-
  903    '$get_predicate_attribute'(Pred, (volatile), 1).
  904'$predicate_property'((thread_local), Pred) :-
  905    '$get_predicate_attribute'(Pred, (thread_local), 1).
  906'$predicate_property'((multifile), Pred) :-
  907    '$get_predicate_attribute'(Pred, (multifile), 1).
  908'$predicate_property'(imported_from(Module), Pred) :-
  909    '$get_predicate_attribute'(Pred, imported, Module).
  910'$predicate_property'(transparent, Pred) :-
  911    '$get_predicate_attribute'(Pred, transparent, 1).
  912'$predicate_property'(meta_predicate(Pattern), Pred) :-
  913    '$get_predicate_attribute'(Pred, meta_predicate, Pattern).
  914'$predicate_property'(file(File), Pred) :-
  915    '$get_predicate_attribute'(Pred, file, File).
  916'$predicate_property'(line_count(LineNumber), Pred) :-
  917    '$get_predicate_attribute'(Pred, line_count, LineNumber).
  918'$predicate_property'(notrace, Pred) :-
  919    '$get_predicate_attribute'(Pred, trace, 0).
  920'$predicate_property'(nodebug, Pred) :-
  921    '$get_predicate_attribute'(Pred, hide_childs, 1).
  922'$predicate_property'(spying, Pred) :-
  923    '$get_predicate_attribute'(Pred, spy, 1).
  924'$predicate_property'(number_of_clauses(N), Pred) :-
  925    '$get_predicate_attribute'(Pred, number_of_clauses, N).
  926'$predicate_property'(number_of_rules(N), Pred) :-
  927    '$get_predicate_attribute'(Pred, number_of_rules, N).
  928'$predicate_property'(last_modified_generation(Gen), Pred) :-
  929    '$get_predicate_attribute'(Pred, last_modified_generation, Gen).
  930'$predicate_property'(indexed(Indices), Pred) :-
  931    '$get_predicate_attribute'(Pred, indexed, Indices).
  932'$predicate_property'(noprofile, Pred) :-
  933    '$get_predicate_attribute'(Pred, noprofile, 1).
  934'$predicate_property'(iso, Pred) :-
  935    '$get_predicate_attribute'(Pred, iso, 1).
  936'$predicate_property'(quasi_quotation_syntax, Pred) :-
  937    '$get_predicate_attribute'(Pred, quasi_quotation_syntax, 1).
  938'$predicate_property'(defined, Pred) :-
  939    '$get_predicate_attribute'(Pred, defined, 1).
  940'$predicate_property'(tabled(default), M:Pred) :-
  941    '$c_current_predicate'(_, M:'$tabled'(_)),
  942    M:'$tabled'(Pred).
  943
  944system_undefined(user:prolog_trace_interception/4).
  945system_undefined(user:prolog_exception_hook/4).
  946system_undefined(system:'$c_call_prolog'/0).
  947system_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.
  955visible_predicate(Pred) :-
  956    Pred = M:Head,
  957    current_module(M),
  958    (   callable(Head)
  959    ->  (   '$get_predicate_attribute'(Pred, defined, 1)
  960        ->  true
  961        ;   \+ current_prolog_flag(M:unknown, fail),
  962            functor(Head, Name, Arity),
  963            '$find_library'(M, Name, Arity, _LoadModule, _Library)
  964        )
  965    ;   setof(PI, visible_in_module(M, PI), PIs),
  966        '$member'(Name/Arity, PIs),
  967        functor(Head, Name, Arity)
  968    ).
  969
  970visible_in_module(M, Name/Arity) :-
  971    default_module(M, DefM),
  972    DefHead = DefM:Head,
  973    '$c_current_predicate'(_, DefHead),
  974    '$get_predicate_attribute'(DefHead, defined, 1),
  975    \+ hidden_system_predicate(Head),
  976    functor(Head, Name, Arity).
  977visible_in_module(_, Name/Arity) :-
  978    '$in_library'(Name, Arity, _).
  979
  980hidden_system_predicate(Head) :-
  981    functor(Head, Name, _),
  982    atom(Name),                     % Avoid [].
  983    sub_atom(Name, 0, _, _, $),
  984    \+ 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.
 1009clause_property(Clause, Property) :-
 1010    '$clause_property'(Property, Clause).
 1011
 1012'$clause_property'(line_count(LineNumber), Clause) :-
 1013    '$get_clause_attribute'(Clause, line_count, LineNumber).
 1014'$clause_property'(file(File), Clause) :-
 1015    '$get_clause_attribute'(Clause, file, File).
 1016'$clause_property'(source(File), Clause) :-
 1017    '$get_clause_attribute'(Clause, owner, File).
 1018'$clause_property'(size(Bytes), Clause) :-
 1019    '$get_clause_attribute'(Clause, size, Bytes).
 1020'$clause_property'(fact, Clause) :-
 1021    '$get_clause_attribute'(Clause, fact, true).
 1022'$clause_property'(erased, Clause) :-
 1023    '$get_clause_attribute'(Clause, erased, true).
 1024'$clause_property'(predicate(PI), Clause) :-
 1025    '$get_clause_attribute'(Clause, predicate_indicator, PI).
 1026'$clause_property'(module(M), Clause) :-
 1027    '$get_clause_attribute'(Clause, module, M).
 1028
 1029
 1030                 /*******************************
 1031                 *             REQUIRE          *
 1032                 *******************************/
 1033
 1034:- meta_predicate
 1035    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.
 1044require(M:List) :-
 1045    (   is_list(List)
 1046    ->  require(List, M)
 1047    ;   throw(error(type_error(list, List), _))
 1048    ).
 1049
 1050require([], _).
 1051require([N/A|T], M) :-
 1052    !,
 1053    functor(Head, N, A),
 1054    '$require'(M:Head),
 1055    require(T, M).
 1056require([H|_T], _) :-
 1057    throw(error(type_error(predicate_indicator, H), _)).
 1058
 1059
 1060                /********************************
 1061                *            MODULES            *
 1062                *********************************/
 current_module(?Module) is nondet
True if Module is a currently defined module.
 1068current_module(Module) :-
 1069    '$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.
 1085module_property(Module, Property) :-
 1086    nonvar(Module), nonvar(Property),
 1087    !,
 1088    property_module(Property, Module).
 1089module_property(Module, Property) :-    % -, file(File)
 1090    nonvar(Property), Property = file(File),
 1091    !,
 1092    (   nonvar(File)
 1093    ->  '$current_module'(Modules, File),
 1094        (   atom(Modules)
 1095        ->  Module = Modules
 1096        ;   '$member'(Module, Modules)
 1097        )
 1098    ;   '$current_module'(Module, File),
 1099        File \== []
 1100    ).
 1101module_property(Module, Property) :-
 1102    current_module(Module),
 1103    property_module(Property, Module).
 1104
 1105property_module(Property, Module) :-
 1106    module_property(Property),
 1107    (   Property = exported_operators(List)
 1108    ->  '$exported_ops'(Module, List, []),
 1109        List \== []
 1110    ;   '$module_property'(Module, Property)
 1111    ).
 1112
 1113module_property(class(_)).
 1114module_property(file(_)).
 1115module_property(line_count(_)).
 1116module_property(exports(_)).
 1117module_property(exported_operators(_)).
 1118module_property(program_size(_)).
 1119module_property(program_space(_)).
 1120module_property(last_modified_generation(_)).
 module(+Module) is det
Set the module that is associated to the toplevel to Module.
 1126module(Module) :-
 1127    atom(Module),
 1128    current_module(Module),
 1129    !,
 1130    '$set_typein_module'(Module).
 1131module(Module) :-
 1132    '$set_typein_module'(Module),
 1133    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.
 1140working_directory(Old, New) :-
 1141    '$cwd'(Old),
 1142    (   Old == New
 1143    ->  true
 1144    ;   '$chdir'(New)
 1145    ).
 1146
 1147
 1148                 /*******************************
 1149                 *            TRIES             *
 1150                 *******************************/
 current_trie(?Trie) is nondet
True if Trie is the handle of an existing trie.
 1156current_trie(Trie) :-
 1157    current_blob(Trie, trie),
 1158    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.
 1174trie_property(Trie, Property) :-
 1175    current_trie(Trie),
 1176    trie_property(Property),
 1177    '$trie_property'(Trie, Property).
 1178
 1179trie_property(node_count(_)).
 1180trie_property(value_count(_)).
 1181trie_property(size(_)).
 1182trie_property(hashed(_)).
 1183
 1184
 1185
 1186                /********************************
 1187                *      SYSTEM INTERACTION       *
 1188                *********************************/
 1189
 1190shell(Command) :-
 1191    shell(Command, 0).
 1192
 1193
 1194                 /*******************************
 1195                 *            SIGNALS           *
 1196                 *******************************/
 1197
 1198:- meta_predicate
 1199    on_signal(+, :, :),
 1200    current_signal(?, ?, :).
 on_signal(+Signal, -OldHandler, :NewHandler) is det
 1204on_signal(Signal, Old, New) :-
 1205    atom(Signal),
 1206    !,
 1207    '$on_signal'(_Num, Signal, Old, New).
 1208on_signal(Signal, Old, New) :-
 1209    integer(Signal),
 1210    !,
 1211    '$on_signal'(Signal, _Name, Old, New).
 1212on_signal(Signal, _Old, _New) :-
 1213    '$type_error'(signal_name, Signal).
 current_signal(?Name, ?SignalNumber, :Handler) is nondet
 1217current_signal(Name, Id, Handler) :-
 1218    between(1, 32, Id),
 1219    '$on_signal'(Id, Name, Handler, Handler).
 1220
 1221:- multifile
 1222    prolog:called_by/2. 1223
 1224prolog:called_by(on_signal(_,_,New), [New+1]) :-
 1225    (   new == throw
 1226    ;   new == default
 1227    ), !, fail.
 1228
 1229
 1230                 /*******************************
 1231                 *            DLOPEN            *
 1232                 *******************************/
 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.
 1246open_shared_object(File, Handle) :-
 1247    open_shared_object(File, Handle, []). % use pl-load.c defaults
 1248
 1249open_shared_object(File, Handle, Flags) :-
 1250    (   is_list(Flags)
 1251    ->  true
 1252    ;   throw(error(type_error(list, Flags), _))
 1253    ),
 1254    map_dlflags(Flags, Mask),
 1255    '$open_shared_object'(File, Handle, Mask).
 1256
 1257dlopen_flag(now,        2'01).          % see pl-load.c for these constants
 1258dlopen_flag(global,     2'10).          % Solaris only
 1259
 1260map_dlflags([], 0).
 1261map_dlflags([F|T], M) :-
 1262    map_dlflags(T, M0),
 1263    (   dlopen_flag(F, I)
 1264    ->  true
 1265    ;   throw(error(domain_error(dlopen_flag, F), _))
 1266    ),
 1267    M is M0 \/ I.
 1268
 1269
 1270                 /*******************************
 1271                 *             I/O              *
 1272                 *******************************/
 1273
 1274format(Fmt) :-
 1275    format(Fmt, []).
 1276
 1277                 /*******************************
 1278                 *            FILES             *
 1279                 *******************************/
 absolute_file_name(+Term, -AbsoluteFile)
 1283absolute_file_name(Name, Abs) :-
 1284    atomic(Name),
 1285    !,
 1286    '$absolute_file_name'(Name, Abs).
 1287absolute_file_name(Term, Abs) :-
 1288    '$chk_file'(Term, [''], [access(read)], true, File),
 1289    !,
 1290    '$absolute_file_name'(File, Abs).
 1291absolute_file_name(Term, Abs) :-
 1292    '$chk_file'(Term, [''], [], true, File),
 1293    !,
 1294    '$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.
 1302tmp_file_stream(Enc, File, Stream) :-
 1303    atom(Enc), var(File), var(Stream),
 1304    !,
 1305    '$tmp_file_stream'('', Enc, File, Stream).
 1306tmp_file_stream(File, Stream, Options) :-
 1307    current_prolog_flag(encoding, DefEnc),
 1308    '$option'(encoding(Enc), Options, DefEnc),
 1309    '$option'(extension(Ext), Options, ''),
 1310    '$tmp_file_stream'(Ext, Enc, File, Stream),
 1311    set_stream(Stream, file_name(File)).
 1312
 1313
 1314                /********************************
 1315                *        MEMORY MANAGEMENT      *
 1316                *********************************/
 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.
 1325garbage_collect :-
 1326    '$garbage_collect'(0).
 set_prolog_stack(+Name, +Option) is det
Set a parameter for one of the Prolog stacks.
 1332set_prolog_stack(Stack, Option) :-
 1333    Option =.. [Name,Value0],
 1334    Value is Value0,
 1335    '$set_prolog_stack'(Stack, Name, _Old, Value).
 prolog_stack_property(?Stack, ?Property) is nondet
Examine stack properties.
 1341prolog_stack_property(Stack, Property) :-
 1342    stack_property(P),
 1343    stack_name(Stack),
 1344    Property =.. [P,Value],
 1345    '$set_prolog_stack'(Stack, P, Value, Value).
 1346
 1347stack_name(local).
 1348stack_name(global).
 1349stack_name(trail).
 1350
 1351stack_property(limit).
 1352stack_property(spare).
 1353stack_property(min_free).
 1354stack_property(low).
 1355stack_property(factor).
 1356
 1357
 1358                 /*******************************
 1359                 *             TERM             *
 1360                 *******************************/
 1361
 1362:- '$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.
 1370numbervars(Term, From, To) :-
 1371    numbervars(Term, From, To, []).
 1372
 1373
 1374                 /*******************************
 1375                 *            STRING            *
 1376                 *******************************/
 term_string(?Term, ?String, +Options)
Parse/write a term from/to a string using Options.
 1382term_string(Term, String, Options) :-
 1383    nonvar(String),
 1384    !,
 1385    read_term_from_atom(String, Term, Options).
 1386term_string(Term, String, Options) :-
 1387    (   '$option'(quoted(_), Options)
 1388    ->  Options1 = Options
 1389    ;   '$merge_options'(_{quoted:true}, Options, Options1)
 1390    ),
 1391    format(string(String), '~W', [Term, Options1]).
 1392
 1393
 1394                 /*******************************
 1395                 *             GVAR             *
 1396                 *******************************/
 nb_setval(+Name, +Value) is det
Bind the non-backtrackable variable Name with a copy of Value
 1402nb_setval(Name, Value) :-
 1403    duplicate_term(Value, Copy),
 1404    nb_linkval(Name, Copy).
 1405
 1406
 1407		 /*******************************
 1408		 *            THREADS		*
 1409		 *******************************/
 1410
 1411:- meta_predicate
 1412    thread_create(0, -).
 thread_create(:Goal, -Id)
Shorthand for thread_create(Goal, Id, []).
 1418thread_create(Goal, Id) :-
 1419    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.
 1428thread_join(Id) :-
 1429    thread_join(Id, Status),
 1430    (   Status == true
 1431    ->  true
 1432    ;   throw(error(thread_error(Status), _))
 1433    ).
 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.
 1450set_prolog_gc_thread(Status) :-
 1451    var(Status),
 1452    !,
 1453    '$instantiation_error'(Status).
 1454set_prolog_gc_thread(false) :-
 1455    !,
 1456    set_prolog_flag(gc_thread, false),
 1457    (   current_prolog_flag(threads, true)
 1458    ->  (   '$gc_stop'
 1459        ->  thread_join(gc)
 1460        ;   true
 1461        )
 1462    ;   true
 1463    ).
 1464set_prolog_gc_thread(true) :-
 1465    !,
 1466    set_prolog_flag(gc_thread, true).
 1467set_prolog_gc_thread(stop) :-
 1468    !,
 1469    (   current_prolog_flag(threads, true)
 1470    ->  (   '$gc_stop'
 1471        ->  thread_join(gc)
 1472        ;   true
 1473        )
 1474    ;   true
 1475    ).
 1476set_prolog_gc_thread(Status) :-
 1477    '$domain_error'(gc_thread, Status)