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-2021, University of Amsterdam
    7                              VU University Amsterdam
    8                              SWI-Prolog Solutions b.v.
    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('$toplevel',
   38          [ '$initialise'/0,            % start Prolog
   39            '$toplevel'/0,              % Prolog top-level (re-entrant)
   40            '$compile'/0,               % `-c' toplevel
   41            '$config'/0,                % --dump-runtime-variables toplevel
   42            initialize/0,               % Run program initialization
   43            version/0,                  % Write initial banner
   44            version/1,                  % Add message to the banner
   45            prolog/0,                   % user toplevel predicate
   46            '$query_loop'/0,            % toplevel predicate
   47            '$execute_query'/3,         % +Query, +Bindings, -Truth
   48            residual_goals/1,           % +Callable
   49            (initialization)/1,         % initialization goal (directive)
   50            '$thread_init'/0,           % initialise thread
   51            (thread_initialization)/1   % thread initialization goal
   52            ]).   53
   54
   55                 /*******************************
   56                 *         VERSION BANNER       *
   57                 *******************************/
   58
   59:- dynamic
   60    prolog:version_msg/1.
 version is det
Print the Prolog banner message and messages registered using version/1.
   67version :-
   68    print_message(banner, welcome).
 version(+Message) is det
Add message to version/0
   74:- multifile
   75    system:term_expansion/2.   76
   77system:term_expansion((:- version(Message)),
   78                      prolog:version_msg(Message)).
   79
   80version(Message) :-
   81    (   prolog:version_msg(Message)
   82    ->  true
   83    ;   assertz(prolog:version_msg(Message))
   84    ).
   85
   86
   87                /********************************
   88                *         INITIALISATION        *
   89                *********************************/
 load_init_file is det
Load the user customization file. This can be done using swipl -f file or simply using swipl. In the first case we search the file both directly and over the alias user_app_config. In the latter case we only use the alias.
   98load_init_file :-
   99    '$cmd_option_val'(init_file, OsFile),
  100    !,
  101    prolog_to_os_filename(File, OsFile),
  102    load_init_file(File, explicit).
  103load_init_file :-
  104    load_init_file('init.pl', implicit).
 loaded_init_file(?Base, ?AbsFile)
Used by prolog_load_context/2 to confirm we are loading a script.
  110:- dynamic
  111    loaded_init_file/2.             % already loaded init files
  112
  113load_init_file(none, _) :- !.
  114load_init_file(Base, _) :-
  115    loaded_init_file(Base, _),
  116    !.
  117load_init_file(InitFile, explicit) :-
  118    exists_file(InitFile),
  119    !,
  120    ensure_loaded(user:InitFile).
  121load_init_file(Base, _) :-
  122    absolute_file_name(user_app_config(Base), InitFile,
  123                       [ access(read),
  124                         file_errors(fail)
  125                       ]),
  126    asserta(loaded_init_file(Base, InitFile)),
  127    load_files(user:InitFile,
  128               [ scope_settings(false)
  129               ]).
  130load_init_file('init.pl', implicit) :-
  131    (   current_prolog_flag(windows, true),
  132        absolute_file_name(user_profile('swipl.ini'), InitFile,
  133                           [ access(read),
  134                             file_errors(fail)
  135                           ])
  136    ;   expand_file_name('~/.swiplrc', [InitFile]),
  137        exists_file(InitFile)
  138    ),
  139    !,
  140    print_message(warning, backcomp(init_file_moved(InitFile))).
  141load_init_file(_, _).
  142
  143'$load_system_init_file' :-
  144    loaded_init_file(system, _),
  145    !.
  146'$load_system_init_file' :-
  147    '$cmd_option_val'(system_init_file, Base),
  148    Base \== none,
  149    current_prolog_flag(home, Home),
  150    file_name_extension(Base, rc, Name),
  151    atomic_list_concat([Home, '/', Name], File),
  152    absolute_file_name(File, Path,
  153                       [ file_type(prolog),
  154                         access(read),
  155                         file_errors(fail)
  156                       ]),
  157    asserta(loaded_init_file(system, Path)),
  158    load_files(user:Path,
  159               [ silent(true),
  160                 scope_settings(false)
  161               ]),
  162    !.
  163'$load_system_init_file'.
  164
  165'$load_script_file' :-
  166    loaded_init_file(script, _),
  167    !.
  168'$load_script_file' :-
  169    '$cmd_option_val'(script_file, OsFiles),
  170    load_script_files(OsFiles).
  171
  172load_script_files([]).
  173load_script_files([OsFile|More]) :-
  174    prolog_to_os_filename(File, OsFile),
  175    (   absolute_file_name(File, Path,
  176                           [ file_type(prolog),
  177                             access(read),
  178                             file_errors(fail)
  179                           ])
  180    ->  asserta(loaded_init_file(script, Path)),
  181        load_files(user:Path, []),
  182        load_files(More)
  183    ;   throw(error(existence_error(script_file, File), _))
  184    ).
  185
  186
  187                 /*******************************
  188                 *       AT_INITIALISATION      *
  189                 *******************************/
  190
  191:- meta_predicate
  192    initialization(0).  193
  194:- '$iso'((initialization)/1).
 initialization :Goal
Runs Goal after loading the file in which this directive appears as well as after restoring a saved state.
See also
- initialization/2
  203initialization(Goal) :-
  204    Goal = _:G,
  205    prolog:initialize_now(G, Use),
  206    !,
  207    print_message(warning, initialize_now(G, Use)),
  208    initialization(Goal, now).
  209initialization(Goal) :-
  210    initialization(Goal, after_load).
  211
  212:- multifile
  213    prolog:initialize_now/2,
  214    prolog:message//1.  215
  216prolog:initialize_now(load_foreign_library(_),
  217                      'use :- use_foreign_library/1 instead').
  218prolog:initialize_now(load_foreign_library(_,_),
  219                      'use :- use_foreign_library/2 instead').
  220
  221prolog:message(initialize_now(Goal, Use)) -->
  222    [ 'Initialization goal ~p will be executed'-[Goal],nl,
  223      'immediately for backward compatibility reasons', nl,
  224      '~w'-[Use]
  225    ].
  226
  227'$run_initialization' :-
  228    '$run_initialization'(_, []),
  229    '$thread_init'.
 initialize
Run goals registered with :- initialization(Goal, program).. Stop with an exception if a goal fails or raises an exception.
  236initialize :-
  237    forall('$init_goal'(when(program), Goal, Ctx),
  238           run_initialize(Goal, Ctx)).
  239
  240run_initialize(Goal, Ctx) :-
  241    (   catch(Goal, E, true),
  242        (   var(E)
  243        ->  true
  244        ;   throw(error(initialization_error(E, Goal, Ctx), _))
  245        )
  246    ;   throw(error(initialization_error(failed, Goal, Ctx), _))
  247    ).
  248
  249
  250                 /*******************************
  251                 *     THREAD INITIALIZATION    *
  252                 *******************************/
  253
  254:- meta_predicate
  255    thread_initialization(0).  256:- dynamic
  257    '$at_thread_initialization'/1.
 thread_initialization :Goal
Run Goal now and everytime a new thread is created.
  263thread_initialization(Goal) :-
  264    assert('$at_thread_initialization'(Goal)),
  265    call(Goal),
  266    !.
  267
  268'$thread_init' :-
  269    (   '$at_thread_initialization'(Goal),
  270        (   call(Goal)
  271        ->  fail
  272        ;   fail
  273        )
  274    ;   true
  275    ).
  276
  277
  278                 /*******************************
  279                 *     FILE SEARCH PATH (-p)    *
  280                 *******************************/
 $set_file_search_paths is det
Process -p PathSpec options.
  286'$set_file_search_paths' :-
  287    '$cmd_option_val'(search_paths, Paths),
  288    (   '$member'(Path, Paths),
  289        atom_chars(Path, Chars),
  290        (   phrase('$search_path'(Name, Aliases), Chars)
  291        ->  '$reverse'(Aliases, Aliases1),
  292            forall('$member'(Alias, Aliases1),
  293                   asserta(user:file_search_path(Name, Alias)))
  294        ;   print_message(error, commandline_arg_type(p, Path))
  295        ),
  296        fail ; true
  297    ).
  298
  299'$search_path'(Name, Aliases) -->
  300    '$string'(NameChars),
  301    [=],
  302    !,
  303    {atom_chars(Name, NameChars)},
  304    '$search_aliases'(Aliases).
  305
  306'$search_aliases'([Alias|More]) -->
  307    '$string'(AliasChars),
  308    path_sep,
  309    !,
  310    { '$make_alias'(AliasChars, Alias) },
  311    '$search_aliases'(More).
  312'$search_aliases'([Alias]) -->
  313    '$string'(AliasChars),
  314    '$eos',
  315    !,
  316    { '$make_alias'(AliasChars, Alias) }.
  317
  318path_sep -->
  319    { current_prolog_flag(windows, true)
  320    },
  321    !,
  322    [;].
  323path_sep -->
  324    [:].
  325
  326'$string'([]) --> [].
  327'$string'([H|T]) --> [H], '$string'(T).
  328
  329'$eos'([], []).
  330
  331'$make_alias'(Chars, Alias) :-
  332    catch(term_to_atom(Alias, Chars), _, fail),
  333    (   atom(Alias)
  334    ;   functor(Alias, F, 1),
  335        F \== /
  336    ),
  337    !.
  338'$make_alias'(Chars, Alias) :-
  339    atom_chars(Alias, Chars).
  340
  341
  342                 /*******************************
  343                 *   LOADING ASSIOCIATED FILES  *
  344                 *******************************/
 argv_files(-Files) is det
Update the Prolog flag argv, extracting the leading script files.
  350argv_files(Files) :-
  351    current_prolog_flag(argv, Argv),
  352    no_option_files(Argv, Argv1, Files, ScriptArgs),
  353    (   (   ScriptArgs == true
  354        ;   Argv1 == []
  355        )
  356    ->  (   Argv1 \== Argv
  357        ->  set_prolog_flag(argv, Argv1)
  358        ;   true
  359        )
  360    ;   '$usage',
  361        halt(1)
  362    ).
  363
  364no_option_files([--|Argv], Argv, [], true) :- !.
  365no_option_files([Opt|_], _, _, ScriptArgs) :-
  366    ScriptArgs \== true,
  367    sub_atom(Opt, 0, _, _, '-'),
  368    !,
  369    '$usage',
  370    halt(1).
  371no_option_files([OsFile|Argv0], Argv, [File|T], ScriptArgs) :-
  372    file_name_extension(_, Ext, OsFile),
  373    user:prolog_file_type(Ext, prolog),
  374    !,
  375    ScriptArgs = true,
  376    prolog_to_os_filename(File, OsFile),
  377    no_option_files(Argv0, Argv, T, ScriptArgs).
  378no_option_files([OsScript|Argv], Argv, [Script], ScriptArgs) :-
  379    ScriptArgs \== true,
  380    !,
  381    prolog_to_os_filename(Script, OsScript),
  382    (   exists_file(Script)
  383    ->  true
  384    ;   '$existence_error'(file, Script)
  385    ),
  386    ScriptArgs = true.
  387no_option_files(Argv, Argv, [], _).
  388
  389clean_argv :-
  390    (   current_prolog_flag(argv, [--|Argv])
  391    ->  set_prolog_flag(argv, Argv)
  392    ;   true
  393    ).
 associated_files(-Files)
If SWI-Prolog is started as <exe> <file>.<ext>, where <ext> is the extension registered for associated files, set the Prolog flag associated_file, switch to the directory holding the file and -if possible- adjust the window title.
  402associated_files([]) :-
  403    current_prolog_flag(saved_program_class, runtime),
  404    !,
  405    clean_argv.
  406associated_files(Files) :-
  407    '$set_prolog_file_extension',
  408    argv_files(Files),
  409    (   Files = [File|_]
  410    ->  absolute_file_name(File, AbsFile),
  411        set_prolog_flag(associated_file, AbsFile),
  412        set_working_directory(File),
  413        set_window_title(Files)
  414    ;   true
  415    ).
 set_working_directory(+File)
When opening as a GUI application, e.g., by opening a file from the Finder/Explorer/..., we typically want to change working directory to the location of the primary file. We currently detect that we are a GUI app by the Prolog flag console_menu, which is set by swipl-win[.exe].
  425set_working_directory(File) :-
  426    current_prolog_flag(console_menu, true),
  427    access_file(File, read),
  428    !,
  429    file_directory_name(File, Dir),
  430    working_directory(_, Dir).
  431set_working_directory(_).
  432
  433set_window_title([File|More]) :-
  434    current_predicate(system:window_title/2),
  435    !,
  436    (   More == []
  437    ->  Extra = []
  438    ;   Extra = ['...']
  439    ),
  440    atomic_list_concat(['SWI-Prolog --', File | Extra], ' ', Title),
  441    system:window_title(_, Title).
  442set_window_title(_).
 start_pldoc
If the option --pldoc[=port] is given, load the PlDoc system.
  450start_pldoc :-
  451    '$cmd_option_val'(pldoc_server, Server),
  452    (   Server == ''
  453    ->  call((doc_server(_), doc_browser))
  454    ;   catch(atom_number(Server, Port), _, fail)
  455    ->  call(doc_server(Port))
  456    ;   print_message(error, option_usage(pldoc)),
  457        halt(1)
  458    ).
  459start_pldoc.
 load_associated_files(+Files)
Load Prolog files specified from the commandline.
  466load_associated_files(Files) :-
  467    (   '$member'(File, Files),
  468        load_files(user:File, [expand(false)]),
  469        fail
  470    ;   true
  471    ).
  472
  473hkey('HKEY_CURRENT_USER/Software/SWI/Prolog').
  474hkey('HKEY_LOCAL_MACHINE/Software/SWI/Prolog').
  475
  476'$set_prolog_file_extension' :-
  477    current_prolog_flag(windows, true),
  478    hkey(Key),
  479    catch(win_registry_get_value(Key, fileExtension, Ext0),
  480          _, fail),
  481    !,
  482    (   atom_concat('.', Ext, Ext0)
  483    ->  true
  484    ;   Ext = Ext0
  485    ),
  486    (   user:prolog_file_type(Ext, prolog)
  487    ->  true
  488    ;   asserta(user:prolog_file_type(Ext, prolog))
  489    ).
  490'$set_prolog_file_extension'.
  491
  492
  493                /********************************
  494                *        TOPLEVEL GOALS         *
  495                *********************************/
 $initialise is semidet
Called from PL_initialise() to do the Prolog part of the initialization. If an exception occurs, this is printed and '$initialise' fails.
  503'$initialise' :-
  504    catch(initialise_prolog, E, initialise_error(E)).
  505
  506initialise_error('$aborted') :- !.
  507initialise_error(E) :-
  508    print_message(error, initialization_exception(E)),
  509    fail.
  510
  511initialise_prolog :-
  512    '$clean_history',
  513    '$run_initialization',
  514    '$load_system_init_file',
  515    set_toplevel,
  516    '$set_file_search_paths',
  517    init_debug_flags,
  518    start_pldoc,
  519    opt_attach_packs,
  520    load_init_file,
  521    catch(setup_colors, E, print_message(warning, E)),
  522    '$load_script_file',
  523    associated_files(Files),
  524    load_associated_files(Files),
  525    '$cmd_option_val'(goals, Goals),
  526    (   Goals == [],
  527        \+ '$init_goal'(when(_), _, _)
  528    ->  version                                 % default interactive run
  529    ;   run_init_goals(Goals),
  530        (   load_only
  531        ->  version
  532        ;   run_program_init,
  533            run_main_init
  534        )
  535    ).
  536
  537opt_attach_packs :-
  538    current_prolog_flag(packs, true),
  539    !,
  540    attach_packs.
  541opt_attach_packs.
  542
  543set_toplevel :-
  544    '$cmd_option_val'(toplevel, TopLevelAtom),
  545    catch(term_to_atom(TopLevel, TopLevelAtom), E,
  546          (print_message(error, E),
  547           halt(1))),
  548    create_prolog_flag(toplevel_goal, TopLevel, [type(term)]).
  549
  550load_only :-
  551    current_prolog_flag(os_argv, OSArgv),
  552    memberchk('-l', OSArgv),
  553    current_prolog_flag(argv, Argv),
  554    \+ memberchk('-l', Argv).
 run_init_goals(+Goals) is det
Run registered initialization goals on order. If a goal fails, execution is halted.
  561run_init_goals([]).
  562run_init_goals([H|T]) :-
  563    run_init_goal(H),
  564    run_init_goals(T).
  565
  566run_init_goal(Text) :-
  567    catch(term_to_atom(Goal, Text), E,
  568          (   print_message(error, init_goal_syntax(E, Text)),
  569              halt(2)
  570          )),
  571    run_init_goal(Goal, Text).
 run_program_init is det
Run goals registered using
  577run_program_init :-
  578    forall('$init_goal'(when(program), Goal, Ctx),
  579           run_init_goal(Goal, @(Goal,Ctx))).
  580
  581run_main_init :-
  582    findall(Goal-Ctx, '$init_goal'(when(main), Goal, Ctx), Pairs),
  583    '$last'(Pairs, Goal-Ctx),
  584    !,
  585    (   current_prolog_flag(toplevel_goal, default)
  586    ->  set_prolog_flag(toplevel_goal, halt)
  587    ;   true
  588    ),
  589    run_init_goal(Goal, @(Goal,Ctx)).
  590run_main_init.
  591
  592run_init_goal(Goal, Ctx) :-
  593    (   catch_with_backtrace(user:Goal, E, true)
  594    ->  (   var(E)
  595        ->  true
  596        ;   print_message(error, init_goal_failed(E, Ctx)),
  597            halt(2)
  598        )
  599    ;   (   current_prolog_flag(verbose, silent)
  600        ->  Level = silent
  601        ;   Level = error
  602        ),
  603        print_message(Level, init_goal_failed(failed, Ctx)),
  604        halt(1)
  605    ).
 init_debug_flags is det
Initialize the various Prolog flags that control the debugger and toplevel.
  612init_debug_flags :-
  613    once(print_predicate(_, [print], PrintOptions)),
  614    Keep = [keep(true)],
  615    create_prolog_flag(answer_write_options, PrintOptions, Keep),
  616    create_prolog_flag(prompt_alternatives_on, determinism, Keep),
  617    create_prolog_flag(toplevel_extra_white_line, true, Keep),
  618    create_prolog_flag(toplevel_print_factorized, false, Keep),
  619    create_prolog_flag(print_write_options,
  620                       [ portray(true), quoted(true), numbervars(true) ],
  621                       Keep),
  622    create_prolog_flag(toplevel_residue_vars, false, Keep),
  623    create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
  624    '$set_debugger_write_options'(print).
 setup_backtrace
Initialise printing a backtrace.
  630setup_backtrace :-
  631    (   \+ current_prolog_flag(backtrace, false),
  632        load_setup_file(library(prolog_stack))
  633    ->  true
  634    ;   true
  635    ).
 setup_colors is det
Setup interactive usage by enabling colored output.
  641setup_colors :-
  642    (   \+ current_prolog_flag(color_term, false),
  643        stream_property(user_input, tty(true)),
  644        stream_property(user_error, tty(true)),
  645        stream_property(user_output, tty(true)),
  646        \+ getenv('TERM', dumb),
  647        load_setup_file(user:library(ansi_term))
  648    ->  true
  649    ;   true
  650    ).
 setup_history
Enable per-directory persistent history.
  656setup_history :-
  657    (   \+ current_prolog_flag(save_history, false),
  658        stream_property(user_input, tty(true)),
  659        \+ current_prolog_flag(readline, false),
  660        load_setup_file(library(prolog_history))
  661    ->  prolog_history(enable)
  662    ;   true
  663    ),
  664    set_default_history,
  665    '$load_history'.
 setup_readline
Setup line editing.
  671setup_readline :-
  672    (   current_prolog_flag(readline, swipl_win)
  673    ->  true
  674    ;   stream_property(user_input, tty(true)),
  675        current_prolog_flag(tty_control, true),
  676        \+ getenv('TERM', dumb),
  677        (   current_prolog_flag(readline, ReadLine)
  678        ->  true
  679        ;   ReadLine = true
  680        ),
  681        readline_library(ReadLine, Library),
  682        load_setup_file(library(Library))
  683    ->  set_prolog_flag(readline, Library)
  684    ;   set_prolog_flag(readline, false)
  685    ).
  686
  687readline_library(true, Library) :-
  688    !,
  689    preferred_readline(Library).
  690readline_library(false, _) :-
  691    !,
  692    fail.
  693readline_library(Library, Library).
  694
  695preferred_readline(editline).
  696preferred_readline(readline).
 load_setup_file(+File) is semidet
Load a file and fail silently if the file does not exist.
  702load_setup_file(File) :-
  703    catch(load_files(File,
  704                     [ silent(true),
  705                       if(not_loaded)
  706                     ]), _, fail).
  707
  708
  709:- '$hide'('$toplevel'/0).              % avoid in the GUI stacktrace
 $toplevel
Called from PL_toplevel()
  715'$toplevel' :-
  716    '$runtoplevel',
  717    print_message(informational, halt).
 $runtoplevel
Actually run the toplevel. The values default and prolog both start the interactive toplevel, where prolog implies the user gave -t prolog.
See also
- prolog/0 is the default interactive toplevel
  727'$runtoplevel' :-
  728    current_prolog_flag(toplevel_goal, TopLevel0),
  729    toplevel_goal(TopLevel0, TopLevel),
  730    user:TopLevel.
  731
  732:- dynamic  setup_done/0.  733:- volatile setup_done/0.  734
  735toplevel_goal(default, '$query_loop') :-
  736    !,
  737    setup_interactive.
  738toplevel_goal(prolog, '$query_loop') :-
  739    !,
  740    setup_interactive.
  741toplevel_goal(Goal, Goal).
  742
  743setup_interactive :-
  744    setup_done,
  745    !.
  746setup_interactive :-
  747    asserta(setup_done),
  748    catch(setup_backtrace, E, print_message(warning, E)),
  749    catch(setup_readline,  E, print_message(warning, E)),
  750    catch(setup_history,   E, print_message(warning, E)).
 $compile
Toplevel called when invoked with -c option.
  756'$compile' :-
  757    (   catch('$compile_', E, (print_message(error, E), halt(1)))
  758    ->  true
  759    ;   print_message(error, error(goal_failed('$compile'), _)),
  760        halt(1)
  761    ),
  762    halt.                               % set exit code
  763
  764'$compile_' :-
  765    '$load_system_init_file',
  766    catch(setup_colors, _, true),
  767    '$set_file_search_paths',
  768    init_debug_flags,
  769    '$run_initialization',
  770    opt_attach_packs,
  771    use_module(library(qsave)),
  772    qsave:qsave_toplevel.
 $config
Toplevel when invoked with --dump-runtime-variables
  778'$config' :-
  779    '$load_system_init_file',
  780    '$set_file_search_paths',
  781    init_debug_flags,
  782    '$run_initialization',
  783    load_files(library(prolog_config)),
  784    (   catch(prolog_dump_runtime_variables, E,
  785              (print_message(error, E), halt(1)))
  786    ->  true
  787    ;   print_message(error, error(goal_failed(prolog_dump_runtime_variables),_))
  788    ).
  789
  790
  791                /********************************
  792                *    USER INTERACTIVE LOOP      *
  793                *********************************/
 prolog
Run the Prolog toplevel. This is now the same as break/0, which pretends to be in a break-level if there is a parent environment.
  801prolog :-
  802    break.
  803
  804:- create_prolog_flag(toplevel_mode, backtracking, []).
 $query_loop
Run the normal Prolog query loop. Note that the query is not protected by catch/3. Dealing with unhandled exceptions is done by the C-function query_loop(). This ensures that unhandled exceptions are really unhandled (in Prolog).
  813'$query_loop' :-
  814    current_prolog_flag(toplevel_mode, recursive),
  815    !,
  816    break_level(Level),
  817    read_expanded_query(Level, Query, Bindings),
  818    (   Query == end_of_file
  819    ->  print_message(query, query(eof))
  820    ;   '$call_no_catch'('$execute_query'(Query, Bindings, _)),
  821        (   current_prolog_flag(toplevel_mode, recursive)
  822        ->  '$query_loop'
  823        ;   '$switch_toplevel_mode'(backtracking),
  824            '$query_loop'           % Maybe throw('$switch_toplevel_mode')?
  825        )
  826    ).
  827'$query_loop' :-
  828    break_level(BreakLev),
  829    repeat,
  830        read_expanded_query(BreakLev, Query, Bindings),
  831        (   Query == end_of_file
  832        ->  !, print_message(query, query(eof))
  833        ;   '$execute_query'(Query, Bindings, _),
  834            (   current_prolog_flag(toplevel_mode, recursive)
  835            ->  !,
  836                '$switch_toplevel_mode'(recursive),
  837                '$query_loop'
  838            ;   fail
  839            )
  840        ).
  841
  842break_level(BreakLev) :-
  843    (   current_prolog_flag(break_level, BreakLev)
  844    ->  true
  845    ;   BreakLev = -1
  846    ).
  847
  848read_expanded_query(BreakLev, ExpandedQuery, ExpandedBindings) :-
  849    '$current_typein_module'(TypeIn),
  850    (   stream_property(user_input, tty(true))
  851    ->  '$system_prompt'(TypeIn, BreakLev, Prompt),
  852        prompt(Old, '|    ')
  853    ;   Prompt = '',
  854        prompt(Old, '')
  855    ),
  856    trim_stacks,
  857    trim_heap,
  858    repeat,
  859      read_query(Prompt, Query, Bindings),
  860      prompt(_, Old),
  861      catch(call_expand_query(Query, ExpandedQuery,
  862                              Bindings, ExpandedBindings),
  863            Error,
  864            (print_message(error, Error), fail)),
  865    !.
 read_query(+Prompt, -Goal, -Bindings) is det
Read the next query. The first clause deals with the case where !-based history is enabled. The second is used if we have command line editing.
  874read_query(Prompt, Goal, Bindings) :-
  875    current_prolog_flag(history, N),
  876    integer(N), N > 0,
  877    !,
  878    read_term_with_history(
  879        Goal,
  880        [ show(h),
  881          help('!h'),
  882          no_save([trace, end_of_file]),
  883          prompt(Prompt),
  884          variable_names(Bindings)
  885        ]).
  886read_query(Prompt, Goal, Bindings) :-
  887    remove_history_prompt(Prompt, Prompt1),
  888    repeat,                                 % over syntax errors
  889    prompt1(Prompt1),
  890    read_query_line(user_input, Line),
  891    '$save_history_line'(Line),             % save raw line (edit syntax errors)
  892    '$current_typein_module'(TypeIn),
  893    catch(read_term_from_atom(Line, Goal,
  894                              [ variable_names(Bindings),
  895                                module(TypeIn)
  896                              ]), E,
  897          (   print_message(error, E),
  898              fail
  899          )),
  900    !,
  901    '$save_history_event'(Line).            % save event (no syntax errors)
 read_query_line(+Input, -Line) is det
  905read_query_line(Input, Line) :-
  906    catch(read_term_as_atom(Input, Line), Error, true),
  907    save_debug_after_read,
  908    (   var(Error)
  909    ->  true
  910    ;   Error = error(syntax_error(_),_)
  911    ->  print_message(error, Error),
  912        fail
  913    ;   print_message(error, Error),
  914        throw(Error)
  915    ).
 read_term_as_atom(+Input, -Line)
Read the next term as an atom and skip to the newline or a non-space character.
  922read_term_as_atom(In, Line) :-
  923    '$raw_read'(In, Line),
  924    (   Line == end_of_file
  925    ->  true
  926    ;   skip_to_nl(In)
  927    ).
 skip_to_nl(+Input) is det
Read input after the term. Skips white space and %... comment until the end of the line or a non-blank character.
  934skip_to_nl(In) :-
  935    repeat,
  936    peek_char(In, C),
  937    (   C == '%'
  938    ->  skip(In, '\n')
  939    ;   char_type(C, space)
  940    ->  get_char(In, _),
  941        C == '\n'
  942    ;   true
  943    ),
  944    !.
  945
  946remove_history_prompt('', '') :- !.
  947remove_history_prompt(Prompt0, Prompt) :-
  948    atom_chars(Prompt0, Chars0),
  949    clean_history_prompt_chars(Chars0, Chars1),
  950    delete_leading_blanks(Chars1, Chars),
  951    atom_chars(Prompt, Chars).
  952
  953clean_history_prompt_chars([], []).
  954clean_history_prompt_chars(['~', !|T], T) :- !.
  955clean_history_prompt_chars([H|T0], [H|T]) :-
  956    clean_history_prompt_chars(T0, T).
  957
  958delete_leading_blanks([' '|T0], T) :-
  959    !,
  960    delete_leading_blanks(T0, T).
  961delete_leading_blanks(L, L).
 set_default_history
Enable !-based numbered command history. This is enabled by default if we are not running under GNU-emacs and we do not have our own line editing.
  970set_default_history :-
  971    current_prolog_flag(history, _),
  972    !.
  973set_default_history :-
  974    (   (   \+ current_prolog_flag(readline, false)
  975        ;   current_prolog_flag(emacs_inferior_process, true)
  976        )
  977    ->  create_prolog_flag(history, 0, [])
  978    ;   create_prolog_flag(history, 25, [])
  979    ).
  980
  981
  982                 /*******************************
  983                 *        TOPLEVEL DEBUG        *
  984                 *******************************/
 save_debug_after_read
Called right after the toplevel read to save the debug status if it was modified from the GUI thread using e.g.
thread_signal(main, gdebug)
bug
- Ideally, the prompt would change if debug mode is enabled. That is hard to realise with all the different console interfaces supported by SWI-Prolog.
  999save_debug_after_read :-
 1000    current_prolog_flag(debug, true),
 1001    !,
 1002    save_debug.
 1003save_debug_after_read.
 1004
 1005save_debug :-
 1006    (   tracing,
 1007        notrace
 1008    ->  Tracing = true
 1009    ;   Tracing = false
 1010    ),
 1011    current_prolog_flag(debug, Debugging),
 1012    set_prolog_flag(debug, false),
 1013    create_prolog_flag(query_debug_settings,
 1014                       debug(Debugging, Tracing), []).
 1015
 1016restore_debug :-
 1017    current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)),
 1018    set_prolog_flag(debug, Debugging),
 1019    (   Tracing == true
 1020    ->  trace
 1021    ;   true
 1022    ).
 1023
 1024:- initialization
 1025    create_prolog_flag(query_debug_settings, debug(false, false), []). 1026
 1027
 1028                /********************************
 1029                *            PROMPTING          *
 1030                ********************************/
 1031
 1032'$system_prompt'(Module, BrekLev, Prompt) :-
 1033    current_prolog_flag(toplevel_prompt, PAtom),
 1034    atom_codes(PAtom, P0),
 1035    (    Module \== user
 1036    ->   '$substitute'('~m', [Module, ': '], P0, P1)
 1037    ;    '$substitute'('~m', [], P0, P1)
 1038    ),
 1039    (    BrekLev > 0
 1040    ->   '$substitute'('~l', ['[', BrekLev, '] '], P1, P2)
 1041    ;    '$substitute'('~l', [], P1, P2)
 1042    ),
 1043    current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)),
 1044    (    Tracing == true
 1045    ->   '$substitute'('~d', ['[trace] '], P2, P3)
 1046    ;    Debugging == true
 1047    ->   '$substitute'('~d', ['[debug] '], P2, P3)
 1048    ;    '$substitute'('~d', [], P2, P3)
 1049    ),
 1050    atom_chars(Prompt, P3).
 1051
 1052'$substitute'(From, T, Old, New) :-
 1053    atom_codes(From, FromCodes),
 1054    phrase(subst_chars(T), T0),
 1055    '$append'(Pre, S0, Old),
 1056    '$append'(FromCodes, Post, S0) ->
 1057    '$append'(Pre, T0, S1),
 1058    '$append'(S1, Post, New),
 1059    !.
 1060'$substitute'(_, _, Old, Old).
 1061
 1062subst_chars([]) -->
 1063    [].
 1064subst_chars([H|T]) -->
 1065    { atomic(H),
 1066      !,
 1067      atom_codes(H, Codes)
 1068    },
 1069    Codes,
 1070    subst_chars(T).
 1071subst_chars([H|T]) -->
 1072    H,
 1073    subst_chars(T).
 1074
 1075
 1076                /********************************
 1077                *           EXECUTION           *
 1078                ********************************/
 $execute_query(Goal, Bindings, -Truth) is det
Execute Goal using Bindings.
 1084'$execute_query'(Var, _, true) :-
 1085    var(Var),
 1086    !,
 1087    print_message(informational, var_query(Var)).
 1088'$execute_query'(Goal, Bindings, Truth) :-
 1089    '$current_typein_module'(TypeIn),
 1090    '$dwim_correct_goal'(TypeIn:Goal, Bindings, Corrected),
 1091    !,
 1092    setup_call_cleanup(
 1093        '$set_source_module'(M0, TypeIn),
 1094        expand_goal(Corrected, Expanded),
 1095        '$set_source_module'(M0)),
 1096    print_message(silent, toplevel_goal(Expanded, Bindings)),
 1097    '$execute_goal2'(Expanded, Bindings, Truth).
 1098'$execute_query'(_, _, false) :-
 1099    notrace,
 1100    print_message(query, query(no)).
 1101
 1102'$execute_goal2'(Goal, Bindings, true) :-
 1103    restore_debug,
 1104    '$current_typein_module'(TypeIn),
 1105    residue_vars(TypeIn:Goal, Vars, TypeIn:Delays, Chp),
 1106    deterministic(Det),
 1107    (   save_debug
 1108    ;   restore_debug, fail
 1109    ),
 1110    flush_output(user_output),
 1111    (   Det == true
 1112    ->  DetOrChp = true
 1113    ;   DetOrChp = Chp
 1114    ),
 1115    call_expand_answer(Bindings, NewBindings),
 1116    (    \+ \+ write_bindings(NewBindings, Vars, Delays, DetOrChp)
 1117    ->   !
 1118    ).
 1119'$execute_goal2'(_, _, false) :-
 1120    save_debug,
 1121    print_message(query, query(no)).
 1122
 1123residue_vars(Goal, Vars, Delays, Chp) :-
 1124    current_prolog_flag(toplevel_residue_vars, true),
 1125    !,
 1126    '$wfs_call'(call_residue_vars(stop_backtrace(Goal, Chp), Vars), Delays).
 1127residue_vars(Goal, [], Delays, Chp) :-
 1128    '$wfs_call'(stop_backtrace(Goal, Chp), Delays).
 1129
 1130stop_backtrace(Goal, Chp) :-
 1131    toplevel_call(Goal),
 1132    prolog_current_choice(Chp).
 1133
 1134toplevel_call(Goal) :-
 1135    call(Goal),
 1136    no_lco.
 1137
 1138no_lco.
 write_bindings(+Bindings, +ResidueVars, +Delays, +DetOrChp) is semidet
Write bindings resulting from a query. The flag prompt_alternatives_on determines whether the user is prompted for alternatives. groundness gives the classical behaviour, determinism is considered more adequate and informative.

Succeeds if the user accepts the answer and fails otherwise.

Arguments:
ResidueVars- are the residual constraints and provided if the prolog flag toplevel_residue_vars is set to project.
 1154write_bindings(Bindings, ResidueVars, Delays, DetOrChp) :-
 1155    '$current_typein_module'(TypeIn),
 1156    translate_bindings(Bindings, Bindings1, ResidueVars, TypeIn:Residuals),
 1157    omit_qualifier(Delays, TypeIn, Delays1),
 1158    name_vars(Bindings1, Residuals, Delays1),
 1159    write_bindings2(Bindings1, Residuals, Delays1, DetOrChp).
 1160
 1161write_bindings2([], Residuals, Delays, _) :-
 1162    current_prolog_flag(prompt_alternatives_on, groundness),
 1163    !,
 1164    print_message(query, query(yes(Delays, Residuals))).
 1165write_bindings2(Bindings, Residuals, Delays, true) :-
 1166    current_prolog_flag(prompt_alternatives_on, determinism),
 1167    !,
 1168    print_message(query, query(yes(Bindings, Delays, Residuals))).
 1169write_bindings2(Bindings, Residuals, Delays, Chp) :-
 1170    repeat,
 1171        print_message(query, query(more(Bindings, Delays, Residuals))),
 1172        get_respons(Action, Chp),
 1173    (   Action == redo
 1174    ->  !, fail
 1175    ;   Action == show_again
 1176    ->  fail
 1177    ;   !,
 1178        print_message(query, query(done))
 1179    ).
 1180
 1181name_vars(Bindings, Residuals, Delays) :-
 1182    current_prolog_flag(toplevel_name_variables, true),
 1183    !,
 1184    '$term_multitons'(t(Bindings,Residuals,Delays), Vars),
 1185    name_vars_(Vars, Bindings, 0),
 1186    term_variables(t(Bindings,Residuals,Delays), SVars),
 1187    anon_vars(SVars).
 1188name_vars(_Bindings, _Residuals, _Delays).
 1189
 1190name_vars_([], _, _).
 1191name_vars_([H|T], Bindings, N) :-
 1192    name_var(Bindings, Name, N, N1),
 1193    H = '$VAR'(Name),
 1194    name_vars_(T, Bindings, N1).
 1195
 1196anon_vars([]).
 1197anon_vars(['$VAR'('_')|T]) :-
 1198    anon_vars(T).
 1199
 1200name_var(Bindings, Name, N0, N) :-
 1201    between(N0, infinite, N1),
 1202    I is N1//26,
 1203    J is 0'A + N1 mod 26,
 1204    (   I == 0
 1205    ->  format(atom(Name), '_~c', [J])
 1206    ;   format(atom(Name), '_~c~d', [J, I])
 1207    ),
 1208    (   current_prolog_flag(toplevel_print_anon, false)
 1209    ->  true
 1210    ;   \+ is_bound(Bindings, Name)
 1211    ),
 1212    !,
 1213    N is N1+1.
 1214
 1215is_bound([Vars=_|T], Name) :-
 1216    (   in_vars(Vars, Name)
 1217    ->  true
 1218    ;   is_bound(T, Name)
 1219    ).
 1220
 1221in_vars(Name, Name) :- !.
 1222in_vars(Names, Name) :-
 1223    '$member'(Name, Names).
 residual_goals(:NonTerminal)
Directive that registers NonTerminal as a collector for residual goals.
 1230:- multifile
 1231    residual_goal_collector/1. 1232
 1233:- meta_predicate
 1234    residual_goals(2). 1235
 1236residual_goals(NonTerminal) :-
 1237    throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)).
 1238
 1239system:term_expansion((:- residual_goals(NonTerminal)),
 1240                      '$toplevel':residual_goal_collector(M2:Head)) :-
 1241    \+ current_prolog_flag(xref, true),
 1242    prolog_load_context(module, M),
 1243    strip_module(M:NonTerminal, M2, Head),
 1244    '$must_be'(callable, Head).
 prolog:residual_goals// is det
DCG that collects residual goals that are not associated with the answer through attributed variables.
 1251:- public prolog:residual_goals//0. 1252
 1253prolog:residual_goals -->
 1254    { findall(NT, residual_goal_collector(NT), NTL) },
 1255    collect_residual_goals(NTL).
 1256
 1257collect_residual_goals([]) --> [].
 1258collect_residual_goals([H|T]) -->
 1259    ( call(H) -> [] ; [] ),
 1260    collect_residual_goals(T).
 prolog:translate_bindings(+Bindings0, -Bindings, +ResidueVars, +ResidualGoals, -Residuals) is det
Translate the raw variable bindings resulting from successfully completing a query into a binding list and list of residual goals suitable for human consumption.
Arguments:
Bindings- is a list of binding(Vars,Value,Substitutions), where Vars is a list of variable names. E.g. binding(['A','B'],42,[])` means that both the variable A and B have the value 42. Values may contain terms '$VAR'(Name) to indicate sharing with a given variable. Value is always an acyclic term. If cycles appear in the answer, Substitutions contains a list of substitutions that restore the original term.
Residuals- is a pair of two lists representing residual goals. The first element of the pair are residuals related to the query variables and the second are related that are disconnected from the query.
 1285:- public
 1286    prolog:translate_bindings/5. 1287:- meta_predicate
 1288    prolog:translate_bindings(+, -, +, +, :). 1289
 1290prolog:translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals) :-
 1291    translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals).
 1292
 1293translate_bindings(Bindings0, Bindings, ResidueVars, Residuals) :-
 1294    prolog:residual_goals(ResidueGoals, []),
 1295    translate_bindings(Bindings0, Bindings, ResidueVars, ResidueGoals,
 1296                       Residuals).
 1297
 1298translate_bindings(Bindings0, Bindings, [], [], _:[]-[]) :-
 1299    term_attvars(Bindings0, []),
 1300    !,
 1301    join_same_bindings(Bindings0, Bindings1),
 1302    factorize_bindings(Bindings1, Bindings2),
 1303    bind_vars(Bindings2, Bindings3),
 1304    filter_bindings(Bindings3, Bindings).
 1305translate_bindings(Bindings0, Bindings, ResidueVars, ResGoals0,
 1306                   TypeIn:Residuals-HiddenResiduals) :-
 1307    project_constraints(Bindings0, ResidueVars),
 1308    hidden_residuals(ResidueVars, Bindings0, HiddenResiduals0),
 1309    omit_qualifiers(HiddenResiduals0, TypeIn, HiddenResiduals),
 1310    copy_term(Bindings0+ResGoals0, Bindings1+ResGoals1, Residuals0),
 1311    '$append'(ResGoals1, Residuals0, Residuals1),
 1312    omit_qualifiers(Residuals1, TypeIn, Residuals),
 1313    join_same_bindings(Bindings1, Bindings2),
 1314    factorize_bindings(Bindings2, Bindings3),
 1315    bind_vars(Bindings3, Bindings4),
 1316    filter_bindings(Bindings4, Bindings).
 1317
 1318hidden_residuals(ResidueVars, Bindings, Goal) :-
 1319    term_attvars(ResidueVars, Remaining),
 1320    term_attvars(Bindings, QueryVars),
 1321    subtract_vars(Remaining, QueryVars, HiddenVars),
 1322    copy_term(HiddenVars, _, Goal).
 1323
 1324subtract_vars(All, Subtract, Remaining) :-
 1325    sort(All, AllSorted),
 1326    sort(Subtract, SubtractSorted),
 1327    ord_subtract(AllSorted, SubtractSorted, Remaining).
 1328
 1329ord_subtract([], _Not, []).
 1330ord_subtract([H1|T1], L2, Diff) :-
 1331    diff21(L2, H1, T1, Diff).
 1332
 1333diff21([], H1, T1, [H1|T1]).
 1334diff21([H2|T2], H1, T1, Diff) :-
 1335    compare(Order, H1, H2),
 1336    diff3(Order, H1, T1, H2, T2, Diff).
 1337
 1338diff12([], _H2, _T2, []).
 1339diff12([H1|T1], H2, T2, Diff) :-
 1340    compare(Order, H1, H2),
 1341    diff3(Order, H1, T1, H2, T2, Diff).
 1342
 1343diff3(<,  H1, T1,  H2, T2, [H1|Diff]) :-
 1344    diff12(T1, H2, T2, Diff).
 1345diff3(=, _H1, T1, _H2, T2, Diff) :-
 1346    ord_subtract(T1, T2, Diff).
 1347diff3(>,  H1, T1, _H2, T2, Diff) :-
 1348    diff21(T2, H1, T1, Diff).
 project_constraints(+Bindings, +ResidueVars) is det
Call <module>:project_attributes/2 if the Prolog flag toplevel_residue_vars is set to project.
 1356project_constraints(Bindings, ResidueVars) :-
 1357    !,
 1358    term_attvars(Bindings, AttVars),
 1359    phrase(attribute_modules(AttVars), Modules0),
 1360    sort(Modules0, Modules),
 1361    term_variables(Bindings, QueryVars),
 1362    project_attributes(Modules, QueryVars, ResidueVars).
 1363project_constraints(_, _).
 1364
 1365project_attributes([], _, _).
 1366project_attributes([M|T], QueryVars, ResidueVars) :-
 1367    (   current_predicate(M:project_attributes/2),
 1368        catch(M:project_attributes(QueryVars, ResidueVars), E,
 1369              print_message(error, E))
 1370    ->  true
 1371    ;   true
 1372    ),
 1373    project_attributes(T, QueryVars, ResidueVars).
 1374
 1375attribute_modules([]) --> [].
 1376attribute_modules([H|T]) -->
 1377    { get_attrs(H, Attrs) },
 1378    attrs_modules(Attrs),
 1379    attribute_modules(T).
 1380
 1381attrs_modules([]) --> [].
 1382attrs_modules(att(Module, _, More)) -->
 1383    [Module],
 1384    attrs_modules(More).
 join_same_bindings(Bindings0, Bindings)
Join variables that are bound to the same value. Note that we return the last value. This is because the factorization may be different and ultimately the names will be printed as V1 = V2, ... VN = Value. Using the last, Value has the factorization of VN.
 1395join_same_bindings([], []).
 1396join_same_bindings([Name=V0|T0], [[Name|Names]=V|T]) :-
 1397    take_same_bindings(T0, V0, V, Names, T1),
 1398    join_same_bindings(T1, T).
 1399
 1400take_same_bindings([], Val, Val, [], []).
 1401take_same_bindings([Name=V1|T0], V0, V, [Name|Names], T) :-
 1402    V0 == V1,
 1403    !,
 1404    take_same_bindings(T0, V1, V, Names, T).
 1405take_same_bindings([Pair|T0], V0, V, Names, [Pair|T]) :-
 1406    take_same_bindings(T0, V0, V, Names, T).
 omit_qualifiers(+QGoals, +TypeIn, -Goals) is det
Omit unneeded module qualifiers from QGoals relative to the given module TypeIn.
 1415omit_qualifiers([], _, []).
 1416omit_qualifiers([Goal0|Goals0], TypeIn, [Goal|Goals]) :-
 1417    omit_qualifier(Goal0, TypeIn, Goal),
 1418    omit_qualifiers(Goals0, TypeIn, Goals).
 1419
 1420omit_qualifier(M:G0, TypeIn, G) :-
 1421    M == TypeIn,
 1422    !,
 1423    omit_meta_qualifiers(G0, TypeIn, G).
 1424omit_qualifier(M:G0, TypeIn, G) :-
 1425    predicate_property(TypeIn:G0, imported_from(M)),
 1426    \+ predicate_property(G0, transparent),
 1427    !,
 1428    G0 = G.
 1429omit_qualifier(_:G0, _, G) :-
 1430    predicate_property(G0, built_in),
 1431    \+ predicate_property(G0, transparent),
 1432    !,
 1433    G0 = G.
 1434omit_qualifier(M:G0, _, M:G) :-
 1435    atom(M),
 1436    !,
 1437    omit_meta_qualifiers(G0, M, G).
 1438omit_qualifier(G0, TypeIn, G) :-
 1439    omit_meta_qualifiers(G0, TypeIn, G).
 1440
 1441omit_meta_qualifiers(V, _, V) :-
 1442    var(V),
 1443    !.
 1444omit_meta_qualifiers((QA,QB), TypeIn, (A,B)) :-
 1445    !,
 1446    omit_qualifier(QA, TypeIn, A),
 1447    omit_qualifier(QB, TypeIn, B).
 1448omit_meta_qualifiers(tnot(QA), TypeIn, tnot(A)) :-
 1449    !,
 1450    omit_qualifier(QA, TypeIn, A).
 1451omit_meta_qualifiers(freeze(V, QGoal), TypeIn, freeze(V, Goal)) :-
 1452    callable(QGoal),
 1453    !,
 1454    omit_qualifier(QGoal, TypeIn, Goal).
 1455omit_meta_qualifiers(when(Cond, QGoal), TypeIn, when(Cond, Goal)) :-
 1456    callable(QGoal),
 1457    !,
 1458    omit_qualifier(QGoal, TypeIn, Goal).
 1459omit_meta_qualifiers(G, _, G).
 bind_vars(+BindingsIn, -Bindings)
Bind variables to '$VAR'(Name), so they are printed by the names used in the query. Note that by binding in the reverse order, variables bound to one another come out in the natural order.
 1468bind_vars(Bindings0, Bindings) :-
 1469    bind_query_vars(Bindings0, Bindings, SNames),
 1470    bind_skel_vars(Bindings, Bindings, SNames, 1, _).
 1471
 1472bind_query_vars([], [], []).
 1473bind_query_vars([binding(Names,Var,[Var2=Cycle])|T0],
 1474                [binding(Names,Cycle,[])|T], [Name|SNames]) :-
 1475    Var == Var2,                   % also implies var(Var)
 1476    !,
 1477    '$last'(Names, Name),
 1478    Var = '$VAR'(Name),
 1479    bind_query_vars(T0, T, SNames).
 1480bind_query_vars([B|T0], [B|T], AllNames) :-
 1481    B = binding(Names,Var,Skel),
 1482    bind_query_vars(T0, T, SNames),
 1483    (   var(Var), \+ attvar(Var), Skel == []
 1484    ->  AllNames = [Name|SNames],
 1485        '$last'(Names, Name),
 1486        Var = '$VAR'(Name)
 1487    ;   AllNames = SNames
 1488    ).
 1489
 1490
 1491
 1492bind_skel_vars([], _, _, N, N).
 1493bind_skel_vars([binding(_,_,Skel)|T], Bindings, SNames, N0, N) :-
 1494    bind_one_skel_vars(Skel, Bindings, SNames, N0, N1),
 1495    bind_skel_vars(T, Bindings, SNames, N1, N).
 bind_one_skel_vars(+Subst, +Bindings, +VarName, +N0, -N)
Give names to the factorized variables that do not have a name yet. This introduces names _S<N>, avoiding duplicates. If a factorized variable shares with another binding, use the name of that variable.
To be done
- Consider the call below. We could remove either of the A = x(1). Which is best?
?- A = x(1), B = a(A,A).
A = x(1),
B = a(A, A), % where
    A = x(1).
 1514bind_one_skel_vars([], _, _, N, N).
 1515bind_one_skel_vars([Var=Value|T], Bindings, Names, N0, N) :-
 1516    (   var(Var)
 1517    ->  (   '$member'(binding(Names, VVal, []), Bindings),
 1518            same_term(Value, VVal)
 1519        ->  '$last'(Names, VName),
 1520            Var = '$VAR'(VName),
 1521            N2 = N0
 1522        ;   between(N0, infinite, N1),
 1523            atom_concat('_S', N1, Name),
 1524            \+ memberchk(Name, Names),
 1525            !,
 1526            Var = '$VAR'(Name),
 1527            N2 is N1 + 1
 1528        )
 1529    ;   N2 = N0
 1530    ),
 1531    bind_one_skel_vars(T, Bindings, Names, N2, N).
 factorize_bindings(+Bindings0, -Factorized)
Factorize cycles and sharing in the bindings.
 1538factorize_bindings([], []).
 1539factorize_bindings([Name=Value|T0], [binding(Name, Skel, Subst)|T]) :-
 1540    '$factorize_term'(Value, Skel, Subst0),
 1541    (   current_prolog_flag(toplevel_print_factorized, true)
 1542    ->  Subst = Subst0
 1543    ;   only_cycles(Subst0, Subst)
 1544    ),
 1545    factorize_bindings(T0, T).
 1546
 1547
 1548only_cycles([], []).
 1549only_cycles([B|T0], List) :-
 1550    (   B = (Var=Value),
 1551        Var = Value,
 1552        acyclic_term(Var)
 1553    ->  only_cycles(T0, List)
 1554    ;   List = [B|T],
 1555        only_cycles(T0, T)
 1556    ).
 filter_bindings(+Bindings0, -Bindings)
Remove bindings that must not be printed. There are two of them: Variables whose name start with '_' and variables that are only bound to themselves (or, unbound).
 1565filter_bindings([], []).
 1566filter_bindings([H0|T0], T) :-
 1567    hide_vars(H0, H),
 1568    (   (   arg(1, H, [])
 1569        ;   self_bounded(H)
 1570        )
 1571    ->  filter_bindings(T0, T)
 1572    ;   T = [H|T1],
 1573        filter_bindings(T0, T1)
 1574    ).
 1575
 1576hide_vars(binding(Names0, Skel, Subst), binding(Names, Skel, Subst)) :-
 1577    hide_names(Names0, Skel, Subst, Names).
 1578
 1579hide_names([], _, _, []).
 1580hide_names([Name|T0], Skel, Subst, T) :-
 1581    (   sub_atom(Name, 0, _, _, '_'),
 1582        current_prolog_flag(toplevel_print_anon, false),
 1583        sub_atom(Name, 1, 1, _, Next),
 1584        char_type(Next, prolog_var_start)
 1585    ->  true
 1586    ;   Subst == [],
 1587        Skel == '$VAR'(Name)
 1588    ),
 1589    !,
 1590    hide_names(T0, Skel, Subst, T).
 1591hide_names([Name|T0], Skel, Subst, [Name|T]) :-
 1592    hide_names(T0, Skel, Subst, T).
 1593
 1594self_bounded(binding([Name], Value, [])) :-
 1595    Value == '$VAR'(Name).
 get_respons(-Action, +Chp)
Read the continuation entered by the user.
 1601get_respons(Action, Chp) :-
 1602    repeat,
 1603        flush_output(user_output),
 1604        get_single_char(Char),
 1605        answer_respons(Char, Chp, Action),
 1606        (   Action == again
 1607        ->  print_message(query, query(action)),
 1608            fail
 1609        ;   !
 1610        ).
 1611
 1612answer_respons(Char, _, again) :-
 1613    '$in_reply'(Char, '?h'),
 1614    !,
 1615    print_message(help, query(help)).
 1616answer_respons(Char, _, redo) :-
 1617    '$in_reply'(Char, ';nrNR \t'),
 1618    !,
 1619    print_message(query, if_tty([ansi(bold, ';', [])])).
 1620answer_respons(Char, _, redo) :-
 1621    '$in_reply'(Char, 'tT'),
 1622    !,
 1623    trace,
 1624    save_debug,
 1625    print_message(query, if_tty([ansi(bold, '; [trace]', [])])).
 1626answer_respons(Char, _, continue) :-
 1627    '$in_reply'(Char, 'ca\n\ryY.'),
 1628    !,
 1629    print_message(query, if_tty([ansi(bold, '.', [])])).
 1630answer_respons(0'b, _, show_again) :-
 1631    !,
 1632    break.
 1633answer_respons(0'*, Chp, show_again) :-
 1634    !,
 1635    print_last_chpoint(Chp).
 1636answer_respons(Char, _, show_again) :-
 1637    print_predicate(Char, Pred, Options),
 1638    !,
 1639    print_message(query, if_tty(['~w'-[Pred]])),
 1640    set_prolog_flag(answer_write_options, Options).
 1641answer_respons(-1, _, show_again) :-
 1642    !,
 1643    print_message(query, halt('EOF')),
 1644    halt(0).
 1645answer_respons(Char, _, again) :-
 1646    print_message(query, no_action(Char)).
 1647
 1648print_predicate(0'w, [write], [ quoted(true),
 1649                                spacing(next_argument)
 1650                              ]).
 1651print_predicate(0'p, [print], [ quoted(true),
 1652                                portray(true),
 1653                                max_depth(10),
 1654                                spacing(next_argument)
 1655                              ]).
 1656
 1657
 1658print_last_chpoint(Chp) :-
 1659    current_predicate(print_last_choice_point/0),
 1660    !,
 1661    print_last_chpoint_(Chp).
 1662print_last_chpoint(Chp) :-
 1663    use_module(library(prolog_stack), [print_last_choicepoint/2]),
 1664    print_last_chpoint_(Chp).
 1665
 1666print_last_chpoint_(Chp) :-
 1667    print_last_choicepoint(Chp, [message_level(information)]).
 1668
 1669
 1670                 /*******************************
 1671                 *          EXPANSION           *
 1672                 *******************************/
 1673
 1674:- user:dynamic(expand_query/4). 1675:- user:multifile(expand_query/4). 1676
 1677call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :-
 1678    user:expand_query(Goal, Expanded, Bindings, ExpandedBindings),
 1679    !.
 1680call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :-
 1681    toplevel_variables:expand_query(Goal, Expanded, Bindings, ExpandedBindings),
 1682    !.
 1683call_expand_query(Goal, Goal, Bindings, Bindings).
 1684
 1685
 1686:- user:dynamic(expand_answer/2). 1687:- user:multifile(expand_answer/2). 1688
 1689call_expand_answer(Goal, Expanded) :-
 1690    user:expand_answer(Goal, Expanded),
 1691    !.
 1692call_expand_answer(Goal, Expanded) :-
 1693    toplevel_variables:expand_answer(Goal, Expanded),
 1694    !.
 1695call_expand_answer(Goal, Goal)