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-2026, 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 '$answer_class'/1, % -Class 49 residual_goals/1, % +Callable 50 (initialization)/1, % initialization goal (directive) 51 '$thread_init'/0, % initialise thread 52 (thread_initialization)/1 % thread initialization goal 53 ]). 54 55 56 /******************************* 57 * VERSION BANNER * 58 *******************************/ 59 60:- dynamic prolog:version_msg/1. 61:- multifile prolog:version_msg/1.
68version :-
69 print_message(banner, welcome).75:- multifile 76 system:term_expansion/2. 77 78systemterm_expansion((:- version(Message)), 79 prolog:version_msg(Message)). 80 81version(Message) :- 82 ( prolog:version_msg(Message) 83 -> true 84 ; assertz(prolog:version_msg(Message)) 85 ). 86 87 88 /******************************** 89 * INITIALISATION * 90 *********************************/
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.99load_init_file(_) :- 100 '$cmd_option_val'(init_file, OsFile), 101 !, 102 prolog_to_os_filename(File, OsFile), 103 load_init_file(File, explicit). 104load_init_file(prolog) :- 105 !, 106 load_init_file('init.pl', implicit). 107load_init_file(none) :- 108 !, 109 load_init_file('init.pl', implicit). 110load_init_file(_).
116:- dynamic 117 loaded_init_file/2. % already loaded init files 118 119load_init_file(none, _) :- !. 120load_init_file(Base, _) :- 121 loaded_init_file(Base, _), 122 !. 123load_init_file(InitFile, explicit) :- 124 exists_file(InitFile), 125 !, 126 ensure_loaded(user:InitFile). 127load_init_file(Base, _) :- 128 absolute_file_name(user_app_config(Base), InitFile, 129 [ access(read), 130 file_errors(fail) 131 ]), 132 !, 133 asserta(loaded_init_file(Base, InitFile)), 134 load_files(user:InitFile, 135 [ scope_settings(false) 136 ]). 137load_init_file('init.pl', implicit) :- 138 ( current_prolog_flag(windows, true), 139 absolute_file_name(user_profile('swipl.ini'), InitFile, 140 [ access(read), 141 file_errors(fail) 142 ]) 143 ; expand_file_name('~/.swiplrc', [InitFile]), 144 exists_file(InitFile) 145 ), 146 !, 147 print_message(warning, backcomp(init_file_moved(InitFile))). 148load_init_file(_, _). 149 150'$load_system_init_file' :- 151 loaded_init_file(system, _), 152 !. 153'$load_system_init_file' :- 154 '$cmd_option_val'(system_init_file, Base), 155 Base \== none, 156 current_prolog_flag(home, Home), 157 file_name_extension(Base, rc, Name), 158 atomic_list_concat([Home, '/', Name], File), 159 absolute_file_name(File, Path, 160 [ file_type(prolog), 161 access(read), 162 file_errors(fail) 163 ]), 164 asserta(loaded_init_file(system, Path)), 165 load_files(user:Path, 166 [ silent(true), 167 scope_settings(false) 168 ]), 169 !. 170'$load_system_init_file'. 171 172'$load_script_file' :- 173 loaded_init_file(script, _), 174 !. 175'$load_script_file' :- 176 '$cmd_option_val'(script_file, OsFiles), 177 load_script_files(OsFiles). 178 179load_script_files([]). 180load_script_files([OsFile|More]) :- 181 prolog_to_os_filename(File, OsFile), 182 ( absolute_file_name(File, Path, 183 [ file_type(prolog), 184 access(read), 185 file_errors(fail) 186 ]) 187 -> asserta(loaded_init_file(script, Path)), 188 load_files(user:Path), 189 load_files(user:More) 190 ; throw(error(existence_error(script_file, File), _)) 191 ). 192 193 194 /******************************* 195 * AT_INITIALISATION * 196 *******************************/ 197 198:- meta_predicate 199 initialization(). 200 201:- '$iso'((initialization)/1).
210initialization(Goal) :- 211 Goal = _:G, 212 prolog:initialize_now(G, Use), 213 !, 214 print_message(warning, initialize_now(G, Use)), 215 initialization(Goal, now). 216initialization(Goal) :- 217 initialization(Goal, after_load). 218 219:- multifile 220 prolog:initialize_now/2, 221 prolog:message//1, 222 prolog:line_editor_attributes/2. % +Off, +On 223 224prologinitialize_now(load_foreign_library(_), 225 'use :- use_foreign_library/1 instead'). 226prologinitialize_now(load_foreign_library(_,_), 227 'use :- use_foreign_library/2 instead'). 228 229prologmessage(initialize_now(Goal, Use)) --> 230 [ 'Initialization goal ~p will be executed'-[Goal],nl, 231 'immediately for backward compatibility reasons', nl, 232 '~w'-[Use] 233 ]. 234 235'$run_initialization' :- 236 '$set_prolog_file_extension', 237 '$run_initialization'(_, []), 238 '$thread_init'.
:- initialization(Goal, program).. Stop
with an exception if a goal fails or raises an exception.245initialize :- 246 forall('$init_goal'(when(program), Goal, Ctx), 247 run_initialize(Goal, Ctx)). 248 249run_initialize(Goal, Ctx) :- 250 ( catch(Goal, E, true), 251 ( var(E) 252 -> true 253 ; throw(error(initialization_error(E, Goal, Ctx), _)) 254 ) 255 ; throw(error(initialization_error(failed, Goal, Ctx), _)) 256 ). 257 258 259 /******************************* 260 * THREAD INITIALIZATION * 261 *******************************/ 262 263:- meta_predicate 264 thread_initialization(). 265:- dynamic 266 '$at_thread_initialization'/1.
272thread_initialization(Goal) :-
273 assert('$at_thread_initialization'(Goal)),
274 call(Goal),
275 !.start_thread() from pl-thread.c before the thread's goal.281'$thread_init' :- 282 set_prolog_flag(toplevel_thread, false), 283 ( '$at_thread_initialization'(Goal), 284 ( call(Goal) 285 -> fail 286 ; fail 287 ) 288 ; true 289 ). 290 291 292 /******************************* 293 * FILE SEARCH PATH (-p) * 294 *******************************/
300'$set_file_search_paths' :- 301 '$cmd_option_val'(search_paths, Paths), 302 ( '$member'(Path, Paths), 303 atom_chars(Path, Chars), 304 ( phrase('$search_path'(Name, Aliases), Chars) 305 -> '$reverse'(Aliases, Aliases1), 306 forall('$member'(Alias, Aliases1), 307 asserta(user:file_search_path(Name, Alias))) 308 ; print_message(error, commandline_arg_type(p, Path)) 309 ), 310 fail ; true 311 ). 312 313'$search_path'(Name, Aliases) --> 314 '$string'(NameChars), 315 [=], 316 !, 317 {atom_chars(Name, NameChars)}, 318 '$search_aliases'(Aliases). 319 320'$search_aliases'([Alias|More]) --> 321 '$string'(AliasChars), 322 path_sep, 323 !, 324 { '$make_alias'(AliasChars, Alias) }, 325 '$search_aliases'(More). 326'$search_aliases'([Alias]) --> 327 '$string'(AliasChars), 328 '$eos', 329 !, 330 { '$make_alias'(AliasChars, Alias) }. 331 332path_sep --> 333 { current_prolog_flag(path_sep, Sep) }, 334 [Sep]. 335 336'$string'([]) --> []. 337'$string'([H|T]) --> [H], '$string'(T). 338 339'$eos'([], []). 340 341'$make_alias'(Chars, Alias) :- 342 catch(term_to_atom(Alias, Chars), _, fail), 343 ( atom(Alias) 344 ; functor(Alias, F, 1), 345 F \== / 346 ), 347 !. 348'$make_alias'(Chars, Alias) :- 349 atom_chars(Alias, Chars). 350 351 352 /******************************* 353 * LOADING ASSIOCIATED FILES * 354 *******************************/
argv, extracting the leading script files.
This is called after the C based parser removed Prolog options such
as -q, -f none, etc. These options are available through
'$cmd_option_val'/2.
Our task is to update the Prolog flag argv and return a list of
the files to be loaded. The rules are:
-- all remaining options must go to argvsearch(name) as Prolog file,
make this the content of Files and pass the remainder as
options to argv.388argv_prolog_files([], exe) :- 389 current_prolog_flag(saved_program_class, runtime), 390 !, 391 clean_argv. 392argv_prolog_files(Files, ScriptMode) :- 393 current_prolog_flag(argv, Argv), 394 no_option_files(Argv, Argv1, Files, ScriptMode), 395 ( ( nonvar(ScriptMode) 396 ; Argv1 == [] 397 ) 398 -> ( Argv1 \== Argv 399 -> set_prolog_flag(argv, Argv1) 400 ; true 401 ) 402 ; '$usage', 403 halt(1) 404 ). 405 406no_option_files([--|Argv], Argv, [], ScriptMode) :- 407 !, 408 ( ScriptMode = none 409 -> true 410 ; true 411 ). 412no_option_files([Opt|_], _, _, ScriptMode) :- 413 var(ScriptMode), 414 sub_atom(Opt, 0, _, _, '-'), 415 !, 416 '$usage', 417 halt(1). 418no_option_files([OsFile|Argv0], Argv, [File|T], ScriptMode) :- 419 file_name_extension(_, Ext, OsFile), 420 user:prolog_file_type(Ext, prolog), 421 !, 422 ScriptMode = prolog, 423 prolog_to_os_filename(File, OsFile), 424 no_option_files(Argv0, Argv, T, ScriptMode). 425no_option_files([OsScript|Argv], Argv, [Script], ScriptMode) :- 426 var(ScriptMode), 427 !, 428 prolog_to_os_filename(PlScript, OsScript), 429 ( exists_file(PlScript) 430 -> Script = PlScript, 431 ScriptMode = script 432 ; cli_script(OsScript, Script) 433 -> ScriptMode = app, 434 set_prolog_flag(app_name, OsScript) 435 ; '$existence_error'(file, PlScript) 436 ). 437no_option_files(Argv, Argv, [], ScriptMode) :- 438 ( ScriptMode = none 439 -> true 440 ; true 441 ). 442 443cli_script(CLI, Script) :- 444 ( sub_atom(CLI, Pre, _, Post, ':') 445 -> sub_atom(CLI, 0, Pre, _, SearchPath), 446 sub_atom(CLI, _, Post, 0, Base), 447 Spec =.. [SearchPath, Base] 448 ; Spec = app(CLI) 449 ), 450 absolute_file_name(Spec, Script, 451 [ file_type(prolog), 452 access(exist), 453 file_errors(fail) 454 ]). 455 456clean_argv :- 457 ( current_prolog_flag(argv, [--|Argv]) 458 -> set_prolog_flag(argv, Argv) 459 ; true 460 ).
469win_associated_files(Files) :- 470 ( Files = [File|_] 471 -> absolute_file_name(File, AbsFile), 472 set_prolog_flag(associated_file, AbsFile), 473 forall(prolog:set_app_file_config(Files), true) 474 ; true 475 ). 476 477:- multifile 478 prolog:set_app_file_config/1. % +Files
--pldoc[=port] is given, load the PlDoc system.484start_pldoc :- 485 '$cmd_option_val'(pldoc_server, Server), 486 ( Server == '' 487 -> call((doc_server(_), doc_browser)) 488 ; catch(atom_number(Server, Port), _, fail) 489 -> call(doc_server(Port)) 490 ; print_message(error, option_usage(pldoc)), 491 halt(1) 492 ). 493start_pldoc.
500load_associated_files(Files) :- 501 load_files(user:Files). 502 503hkey('HKEY_CURRENT_USER/Software/SWI/Prolog'). 504hkey('HKEY_LOCAL_MACHINE/Software/SWI/Prolog'). 505 506'$set_prolog_file_extension' :- 507 current_prolog_flag(windows, true), 508 hkey(Key), 509 catch(win_registry_get_value(Key, fileExtension, Ext0), 510 _, fail), 511 !, 512 ( atom_concat('.', Ext, Ext0) 513 -> true 514 ; Ext = Ext0 515 ), 516 ( user:prolog_file_type(Ext, prolog) 517 -> true 518 ; asserta(user:prolog_file_type(Ext, prolog)) 519 ). 520'$set_prolog_file_extension'. 521 522 523 /******************************** 524 * TOPLEVEL GOALS * 525 *********************************/
533'$initialise' :- 534 catch(initialise_prolog, E, initialise_error(E)). 535 536initialise_error(unwind(abort)) :- !. 537initialise_error(unwind(halt(_))) :- !. 538initialise_error(E) :- 539 print_message(error, initialization_exception(E)), 540 fail. 541 542initialise_prolog :- 543 apply_defines, 544 init_optimise, 545 '$run_initialization', 546 '$load_system_init_file', % -F file 547 set_toplevel, % set `toplevel_goal` flag from -t 548 '$set_file_search_paths', % handle -p alias=dir[:dir]* 549 init_debug_flags, 550 setup_app, 551 start_pldoc, % handle --pldoc[=port] 552 main_thread_init.
epilog is set and
xpce is around, create an epilog window and complete the user part
of the initialization in the epilog thread.560:- if(current_prolog_flag(threads, true)). 561main_thread_init :- 562 current_prolog_flag(epilog, true), 563 thread_self(main), 564 current_prolog_flag(xpce, true), 565 exists_source(library(epilog)), 566 !, 567 setup_theme, 568 catch(setup_backtrace, E, print_message(warning, E)), 569 use_module(library(epilog)), 570 set_thread(main, class(system)), 571 call(epilog([ init(user_thread_init), 572 main(true) 573 ])). 574main_thread_init :- 575 set_thread(main, class(console)), 576 setup_theme, 577 user_thread_init. 578:- else. 579main_thread_init :- 580 setup_theme, 581 user_thread_init. 582:- endif.
589user_thread_init :-
590 opt_attach_packs,
591 argv_prolog_files(Files, ScriptMode),
592 load_init_file(ScriptMode), % -f file
593 catch(setup_colors, E, print_message(warning, E)),
594 win_associated_files(Files), % swipl-win: cd and update title
595 '$load_script_file', % -s file (may be repeated)
596 load_associated_files(Files),
597 '$cmd_option_val'(goals, Goals), % -g goal (may be repeated)
598 ( ScriptMode == app
599 -> run_program_init, % initialization(Goal, program)
600 run_main_init(true)
601 ; Goals == [],
602 \+ '$init_goal'(when(_), _, _) % no -g or -t or initialization(program)
603 -> version % default interactive run
604 ; run_init_goals(Goals), % run -g goals
605 ( load_only % used -l to load
606 -> version
607 ; run_program_init, % initialization(Goal, program)
608 run_main_init(false) % initialization(Goal, main)
609 )
610 ).614:- multifile 615 prolog:theme/1. 616 617setup_theme :- 618 current_prolog_flag(theme, Theme), 619 exists_source(library(theme/Theme)), 620 !, 621 use_module(library(theme/Theme)). 622setup_theme.
628apply_defines :- 629 '$cmd_option_val'(defines, Defs), 630 apply_defines(Defs). 631 632apply_defines([]). 633apply_defines([H|T]) :- 634 apply_define(H), 635 apply_defines(T). 636 637apply_define(Def) :- 638 sub_atom(Def, B, _, A, '='), 639 !, 640 sub_atom(Def, 0, B, _, Flag), 641 sub_atom(Def, _, A, 0, Value0), 642 ( '$current_prolog_flag'(Flag, Value0, _Scope, Access, Type) 643 -> ( Access \== write 644 -> '$permission_error'(set, prolog_flag, Flag) 645 ; text_flag_value(Type, Value0, Value) 646 ), 647 set_prolog_flag(Flag, Value) 648 ; ( atom_number(Value0, Value) 649 -> true 650 ; Value = Value0 651 ), 652 set_defined(Flag, Value) 653 ). 654apply_define(Def) :- 655 atom_concat('no-', Flag, Def), 656 !, 657 set_user_boolean_flag(Flag, false). 658apply_define(Def) :- 659 set_user_boolean_flag(Def, true). 660 661set_user_boolean_flag(Flag, Value) :- 662 current_prolog_flag(Flag, Old), 663 !, 664 ( Old == Value 665 -> true 666 ; set_prolog_flag(Flag, Value) 667 ). 668set_user_boolean_flag(Flag, Value) :- 669 set_defined(Flag, Value). 670 671text_flag_value(integer, Text, Int) :- 672 atom_number(Text, Int), 673 !. 674text_flag_value(float, Text, Float) :- 675 atom_number(Text, Float), 676 !. 677text_flag_value(term, Text, Term) :- 678 term_string(Term, Text, []), 679 !. 680text_flag_value(_, Value, Value). 681 682set_defined(Flag, Value) :- 683 define_options(Flag, Options), !, 684 create_prolog_flag(Flag, Value, Options).
691define_options('SDL_VIDEODRIVER', []). 692define_options(_, [warn_not_accessed(true)]).
-O is effective.698init_optimise :- 699 current_prolog_flag(optimise, true), 700 !, 701 use_module(user:library(apply_macros)). 702init_optimise. 703 704opt_attach_packs :- 705 current_prolog_flag(packs, true), 706 !, 707 attach_packs. 708opt_attach_packs. 709 710set_toplevel :- 711 '$cmd_option_val'(toplevel, TopLevelAtom), 712 catch(term_to_atom(TopLevel, TopLevelAtom), E, 713 (print_message(error, E), 714 halt(1))), 715 create_prolog_flag(toplevel_goal, TopLevel, [type(term)]). 716 717load_only :- 718 current_prolog_flag(os_argv, OSArgv), 719 memberchk('-l', OSArgv), 720 current_prolog_flag(argv, Argv), 721 \+ memberchk('-l', Argv).
728run_init_goals([]). 729run_init_goals([H|T]) :- 730 run_init_goal(H), 731 run_init_goals(T). 732 733run_init_goal(Text) :- 734 catch(term_to_atom(Goal, Text), E, 735 ( print_message(error, init_goal_syntax(E, Text)), 736 halt(2) 737 )), 738 run_init_goal(Goal, Text).
744run_program_init :- 745 forall('$init_goal'(when(program), Goal, Ctx), 746 run_init_goal(Goal, @(Goal,Ctx))). 747 748run_main_init(_) :- 749 findall(Goal-Ctx, '$init_goal'(when(main), Goal, Ctx), Pairs), 750 '$last'(Pairs, Goal-Ctx), 751 !, 752 ( current_prolog_flag(toplevel_goal, default) 753 -> set_prolog_flag(toplevel_goal, halt) 754 ; true 755 ), 756 run_init_goal(Goal, @(Goal,Ctx)). 757run_main_init(true) :- 758 '$existence_error'(initialization, main). 759run_main_init(_). 760 761run_init_goal(Goal, Ctx) :- 762 ( catch_with_backtrace(user:Goal, E, true) 763 -> ( var(E) 764 -> true 765 ; init_goal_failed(E, Ctx) 766 ) 767 ; ( current_prolog_flag(verbose, silent) 768 -> Level = silent 769 ; Level = error 770 ), 771 print_message(Level, init_goal_failed(failed, Ctx)), 772 halt(1) 773 ). 774 775init_goal_failed(E, Ctx) :- 776 print_message(error, init_goal_failed(E, Ctx)), 777 init_goal_failed(E). 778 779init_goal_failed(_) :- 780 thread_self(main), 781 !, 782 halt(2). 783init_goal_failed(_).
790init_debug_flags :-
791 Keep = [keep(true)],
792 create_prolog_flag(answer_write_options,
793 [ quoted(true), portray(true), max_depth(10),
794 spacing(next_argument)], Keep),
795 create_prolog_flag(prompt_alternatives_on, determinism, Keep),
796 create_prolog_flag(toplevel_extra_white_line, true, Keep),
797 create_prolog_flag(toplevel_print_factorized, false, Keep),
798 create_prolog_flag(print_write_options,
799 [ portray(true), quoted(true), numbervars(true) ],
800 Keep),
801 create_prolog_flag(toplevel_residue_vars, false, Keep),
802 create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
803 '$set_debugger_write_options'(print).
809setup_backtrace :-
810 ( \+ current_prolog_flag(backtrace, false),
811 load_setup_file(library(prolog_stack))
812 -> true
813 ; true
814 ).
820setup_colors :-
821 ( \+ current_prolog_flag(color_term, false),
822 stream_property(user_input, tty(true)),
823 stream_property(user_error, tty(true)),
824 stream_property(user_output, tty(true)),
825 \+ getenv('TERM', dumb),
826 load_setup_file(user:library(ansi_term))
827 -> true
828 ; true
829 ).
835setup_history :-
836 ( \+ current_prolog_flag(save_history, false),
837 stream_property(user_input, tty(true)),
838 \+ current_prolog_flag(readline, false),
839 load_setup_file(library(prolog_history))
840 -> prolog_history(enable)
841 ; true
842 ).848setup_readline :- 849 ( stream_property(user_input, tty(true)), 850 current_prolog_flag(tty_control, true), 851 \+ getenv('TERM', dumb), 852 ( current_prolog_flag(readline, ReadLine) 853 -> true 854 ; ReadLine = true 855 ), 856 readline_library(ReadLine, Library), 857 ( load_setup_file(library(Library)) 858 -> true 859 ; current_prolog_flag(epilog, true), 860 print_message(warning, 861 error(existence_error(library, library(Library)), 862 _)), 863 fail 864 ) 865 -> set_prolog_flag(readline, Library) 866 ; set_prolog_flag(readline, false) 867 ). 868 869readline_library(true, Library) :- 870 !, 871 preferred_readline(Library). 872readline_library(false, _) :- 873 !, 874 fail. 875readline_library(Library, Library). 876 877preferred_readline(editline).
883load_setup_file(File) :-
884 catch(load_files(File,
885 [ silent(true),
886 if(not_loaded)
887 ]), error(_,_), fail).899:- if(current_prolog_flag(windows,true)). 900 901setup_app :- 902 current_prolog_flag(associated_file, _), 903 !. 904setup_app :- 905 '$cmd_option_val'(win_app, true), 906 !, 907 catch(my_prolog, E, print_message(warning, E)). 908setup_app. 909 910my_prolog :- 911 win_folder(personal, MyDocs), 912 atom_concat(MyDocs, '/Prolog', PrologDir), 913 ( ensure_dir(PrologDir) 914 -> working_directory(_, PrologDir) 915 ; working_directory(_, MyDocs) 916 ). 917 918ensure_dir(Dir) :- 919 exists_directory(Dir), 920 !. 921ensure_dir(Dir) :- 922 catch(make_directory(Dir), E, (print_message(warning, E), fail)). 923 924:- elif(current_prolog_flag(apple, true)). 925use_app_settings(true). % Indicate we need app settings 926 927setup_app :- 928 apple_set_locale, 929 current_prolog_flag(associated_file, _), 930 !. 931setup_app :- 932 current_prolog_flag(bundle, true), 933 current_prolog_flag(epilog, true), 934 getenv('__CFBundleIdentifier', _), 935 !, 936 setup_macos_app. 937setup_app. 938 939apple_set_locale :- 940 ( getenv('LC_CTYPE', 'UTF-8'), 941 apple_current_locale_identifier(LocaleID), 942 atom_concat(LocaleID, '.UTF-8', Locale), 943 catch(setlocale(ctype, _Old, Locale), _, fail) 944 -> setenv('LANG', Locale), 945 unsetenv('LC_CTYPE') 946 ; true 947 ). 948 949setup_macos_app :- 950 restore_working_directory, 951 !. 952setup_macos_app :- 953 expand_file_name('~/Prolog', [PrologDir]), 954 ( exists_directory(PrologDir) 955 -> true 956 ; catch(make_directory(PrologDir), MkDirError, 957 print_message(warning, MkDirError)) 958 ), 959 catch(working_directory(_, PrologDir), CdError, 960 print_message(warning, CdError)), 961 !. 962setup_macos_app. 963 964:- elif(current_prolog_flag(emscripten, true)). 965setup_app. 966:- else. 967use_app_settings(true). % Indicate we need app settings 968 969% Other (Unix-like) platforms. 970setup_app :- 971 running_as_app, 972 restore_working_directory, 973 !. 974setup_app.
980running_as_app :- 981% getenv('FLATPAK_SANDBOX_DIR', _), 982 current_prolog_flag(epilog, true), 983 stream_property(In, file_no(0)), 984 \+ stream_property(In, tty(true)), 985 !. 986 987:- endif. 988 989 990:- if((current_predicate(use_app_settings/1), 991 use_app_settings(true))). 992 993 994 /******************************* 995 * APP WORKING DIRECTORY * 996 *******************************/ 997 998save_working_directory :- 999 working_directory(WD, WD), 1000 app_settings(Settings), 1001 ( Settings.get(working_directory) == WD 1002 -> true 1003 ; app_save_settings(Settings.put(working_directory, WD)) 1004 ). 1005 1006restore_working_directory :- 1007 at_halt(save_working_directory), 1008 app_settings(Settings), 1009 WD = Settings.get(working_directory), 1010 catch(working_directory(_, WD), _, fail), 1011 !. 1012 1013 /******************************* 1014 * SETTINGS * 1015 *******************************/
1021app_settings(Settings) :- 1022 app_settings_file(File), 1023 access_file(File, read), 1024 catch(setup_call_cleanup( 1025 open(File, read, In, [encoding(utf8)]), 1026 read_term(In, Settings, []), 1027 close(In)), 1028 Error, 1029 (print_message(warning, Error), fail)), 1030 !. 1031app_settings(#{}).
1037app_save_settings(Settings) :- 1038 app_settings_file(File), 1039 catch(setup_call_cleanup( 1040 open(File, write, Out, [encoding(utf8)]), 1041 write_term(Out, Settings, 1042 [ quoted(true), 1043 module(system), % default operators 1044 fullstop(true), 1045 nl(true) 1046 ]), 1047 close(Out)), 1048 Error, 1049 (print_message(warning, Error), fail)). 1050 1051 1052app_settings_file(File) :- 1053 absolute_file_name(user_app_config('app_settings.pl'), File, 1054 [ access(write), 1055 file_errors(fail) 1056 ]). 1057:- endif.% app_settings 1058 1059 /******************************* 1060 * TOPLEVEL * 1061 *******************************/ 1062 1063:- '$hide'('$toplevel'/0). % avoid in the GUI stacktrace
1069'$toplevel' :-
1070 '$runtoplevel',
1071 print_message(informational, halt).default and prolog both
start the interactive toplevel, where prolog implies the user gave
-t prolog.
1081'$runtoplevel' :- 1082 current_prolog_flag(toplevel_goal, TopLevel0), 1083 toplevel_goal(TopLevel0, TopLevel), 1084 user:TopLevel. 1085 1086:- dynamic setup_done/0. 1087:- volatile setup_done/0. 1088 1089toplevel_goal(default, '$query_loop') :- 1090 !, 1091 setup_interactive. 1092toplevel_goal(prolog, '$query_loop') :- 1093 !, 1094 setup_interactive. 1095toplevel_goal(Goal, Goal). 1096 1097setup_interactive :- 1098 setup_done, 1099 !. 1100setup_interactive :- 1101 asserta(setup_done), 1102 catch(setup_backtrace, E, print_message(warning, E)), 1103 catch(setup_readline, E, print_message(warning, E)), 1104 catch(setup_history, E, print_message(warning, E)).
1110'$compile' :- 1111 ( catch('$compile_', E, (print_message(error, E), halt(1))) 1112 -> true 1113 ; print_message(error, error(goal_failed('$compile'), _)), 1114 halt(1) 1115 ), 1116 halt. % set exit code 1117 1118'$compile_' :- 1119 '$load_system_init_file', 1120 catch(setup_colors, _, true), 1121 '$set_file_search_paths', 1122 init_debug_flags, 1123 '$run_initialization', 1124 opt_attach_packs, 1125 use_module(library(qsave)), 1126 qsave:qsave_toplevel.
1132'$config' :- 1133 '$load_system_init_file', 1134 '$set_file_search_paths', 1135 init_debug_flags, 1136 '$run_initialization', 1137 load_files(library(prolog_config)), 1138 ( catch(prolog_dump_runtime_variables, E, 1139 (print_message(error, E), halt(1))) 1140 -> true 1141 ; print_message(error, error(goal_failed(prolog_dump_runtime_variables),_)) 1142 ). 1143 1144 1145 /******************************** 1146 * USER INTERACTIVE LOOP * 1147 *********************************/
forall(prolog:repl_loop_hook(BeginEnd, BreakLevel), true)
1160:- multifile
1161 prolog:repl_loop_hook/2.1169prolog :- 1170 break. 1171 1172:- create_prolog_flag(toplevel_mode, backtracking, []).
query_loop(). This ensures that unhandled
exceptions are really unhandled (in Prolog).1181'$query_loop' :- 1182 break_level(BreakLev), 1183 setup_call_cleanup( 1184 notrace(call_repl_loop_hook(begin, BreakLev, IsToplevel)), 1185 '$query_loop'(BreakLev), 1186 notrace(call_repl_loop_hook(end, BreakLev, IsToplevel))). 1187 1188call_repl_loop_hook(begin, BreakLev, IsToplevel) => 1189 ( current_prolog_flag(toplevel_thread, IsToplevel) 1190 -> true 1191 ; IsToplevel = false 1192 ), 1193 set_prolog_flag(toplevel_thread, true), 1194 call_repl_loop_hook_(begin, BreakLev). 1195call_repl_loop_hook(end, BreakLev, IsToplevel) => 1196 set_prolog_flag(toplevel_thread, IsToplevel), 1197 call_repl_loop_hook_(end, BreakLev). 1198 1199call_repl_loop_hook_(BeginEnd, BreakLev) :- 1200 forall(prolog:repl_loop_hook(BeginEnd, BreakLev), true). 1201 1202 1203'$query_loop'(BreakLev) :- 1204 current_prolog_flag(toplevel_mode, recursive), 1205 !, 1206 read_expanded_query(BreakLev, Query, Bindings), 1207 ( Query == end_of_file 1208 -> print_message(query, query(eof)) 1209 ; '$call_no_catch'('$execute_query'(Query, Bindings, _)), 1210 ( current_prolog_flag(toplevel_mode, recursive) 1211 -> '$query_loop'(BreakLev) 1212 ; '$switch_toplevel_mode'(backtracking), 1213 '$query_loop'(BreakLev) % Maybe throw('$switch_toplevel_mode')? 1214 ) 1215 ). 1216'$query_loop'(BreakLev) :- 1217 repeat, 1218 read_expanded_query(BreakLev, Query, Bindings), 1219 ( Query == end_of_file 1220 -> !, print_message(query, query(eof)) 1221 ; '$execute_query'(Query, Bindings, _), 1222 ( current_prolog_flag(toplevel_mode, recursive) 1223 -> !, 1224 '$switch_toplevel_mode'(recursive), 1225 '$query_loop'(BreakLev) 1226 ; fail 1227 ) 1228 ). 1229 1230break_level(BreakLev) :- 1231 ( current_prolog_flag(break_level, BreakLev) 1232 -> true 1233 ; BreakLev = -1 1234 ). 1235 1236read_expanded_query(BreakLev, ExpandedQuery, ExpandedBindings) :- 1237 '$current_typein_module'(TypeIn), 1238 ( stream_property(user_input, tty(true)) 1239 -> '$system_prompt'(TypeIn, BreakLev, Prompt), 1240 decorate_prompt('| ', Continue), 1241 prompt(Old, Continue) 1242 ; Prompt = '', 1243 prompt(Old, '') 1244 ), 1245 reset_answer_count, 1246 trim_stacks, 1247 trim_heap, 1248 repeat, 1249 ( catch(call_cleanup(read_query(Prompt, Query, Bindings), 1250 end_input_style), 1251 error(io_error(_,_),_), fail) 1252 -> prompt(_, Old), 1253 catch(call_expand_query(Query, ExpandedQuery, 1254 Bindings, ExpandedBindings), 1255 Error, 1256 (print_message(error, Error), fail)) 1257 ; set_prolog_flag(debug_on_error, false), 1258 thread_exit(io_error) 1259 ), 1260 !.
1269:- multifile 1270 prolog:history/2. 1271 1272:- if(current_prolog_flag(emscripten, true)). 1273read_query(_Prompt, Goal, Bindings) :- 1274 '$can_yield', 1275 !, 1276 await(query, GoalString), 1277 term_string(Goal, GoalString, [variable_names(Bindings)]). 1278:- endif. 1279read_query(Prompt, Goal, Bindings) :- 1280 prolog:history(current_input, enabled), 1281 !, 1282 decorate_prompt(Prompt, DPrompt), 1283 read_term_with_history( 1284 Goal, 1285 [ show(h), 1286 help('!h'), 1287 no_save([trace]), 1288 prompt(DPrompt), 1289 variable_names(Bindings) 1290 ]). 1291read_query(Prompt, Goal, Bindings) :- 1292 remove_history_prompt(Prompt, Prompt0), 1293 decorate_prompt(Prompt0, Prompt1), 1294 repeat, % over syntax errors 1295 prompt1(Prompt1), 1296 read_query_line(user_input, Line), 1297 '$current_typein_module'(TypeIn), 1298 catch(read_term_from_atom(Line, Goal, 1299 [ variable_names(Bindings), 1300 module(TypeIn), 1301 blob(resolve) 1302 ]), E, 1303 ( print_message(error, E), 1304 fail 1305 )), 1306 !.
user and read the next query. This supports injecting
goals in some GNU-Emacs modes.1314read_query_line(Input, Line) :- 1315 stream_property(Input, error(true)), 1316 !, 1317 Line = end_of_file. 1318read_query_line(Input, Line) :- 1319 catch(read_term_as_atom(Input, Line0), Error, true), 1320 end_input_style, % before a possible syntax error 1321 save_debug_after_read, 1322 ( var(Error) 1323 -> ( catch(term_string(Goal, Line0), error(_,_), fail), 1324 Goal = '$silent'(SilentGoal) 1325 -> Error = error(_,_), 1326 catch_with_backtrace(ignore(SilentGoal), Error, 1327 print_message(error, Error)), 1328 read_query_line(Input, Line) 1329 ; Line = Line0 1330 ) 1331 ; catch(print_message(error, Error), _, true), 1332 ( Error = error(syntax_error(_),_) 1333 -> fail 1334 ; throw(Error) 1335 ) 1336 ).
1343read_term_as_atom(In, Line) :-
1344 '$raw_read'(In, Line),
1345 ( Line == end_of_file
1346 -> true
1347 ; skip_to_nl(In)
1348 ).1355skip_to_nl(In) :- 1356 repeat, 1357 peek_char(In, C), 1358 ( C == '%' 1359 -> skip(In, '\n') 1360 ; char_type(C, space) 1361 -> get_char(In, _), 1362 C == '\n' 1363 ; true 1364 ), 1365 !. 1366 1367remove_history_prompt('', '') :- !. 1368remove_history_prompt(Prompt0, Prompt) :- 1369 atom_chars(Prompt0, Chars0), 1370 clean_history_prompt_chars(Chars0, Chars1), 1371 delete_leading_blanks(Chars1, Chars), 1372 atom_chars(Prompt, Chars). 1373 1374clean_history_prompt_chars([], []). 1375clean_history_prompt_chars(['~', !|T], T) :- !. 1376clean_history_prompt_chars([H|T0], [H|T]) :- 1377 clean_history_prompt_chars(T0, T). 1378 1379delete_leading_blanks([' '|T0], T) :- 1380 !, 1381 delete_leading_blanks(T0, T). 1382delete_leading_blanks(L, L). 1383 1384 1385 /******************************* 1386 * TOPLEVEL DEBUG * 1387 *******************************/
thread_signal(main, gdebug)
1402save_debug_after_read :- 1403 current_prolog_flag(debug, true), 1404 !, 1405 save_debug. 1406save_debug_after_read. 1407 1408save_debug :- 1409 ( tracing, 1410 notrace 1411 -> Tracing = true 1412 ; Tracing = false 1413 ), 1414 current_prolog_flag(debug, Debugging), 1415 set_prolog_flag(debug, false), 1416 create_prolog_flag(query_debug_settings, 1417 debug(Debugging, Tracing), []). 1418 1419restore_debug :- 1420 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)), 1421 set_prolog_flag(debug, Debugging), 1422 ( Tracing == true 1423 -> trace 1424 ; true 1425 ). 1426 1427:- initialization 1428 create_prolog_flag(query_debug_settings, debug(false, false), []). 1429 1430 1431 /******************************** 1432 * PROMPTING * 1433 ********************************/
answer(odd) or answer(even),
alternating over the answers of a single query. Using a different
background colour for both stripes the answers, which separates
the answers of a non-deterministic query.
Only an answer that shows bindings, residual goals or delays is
decorated: true. and false. are not answers to stripe.
Exported (and thus $-prefixed) because it is used by
boot/messages.pl. It is not intended for use by applications.
1449'$answer_class'(Class) :- 1450 nb_current('$answer_class', Class), 1451 Class \== none. 1452 1453answer_count(Count) :- 1454 ( nb_current('$answer_count', C) 1455 -> Count = C 1456 ; Count = 0 1457 ). 1458 1459reset_answer_count :- 1460 nb_setval('$answer_count', 0), 1461 no_answer.
true., false. and the empty line that
ends the interaction.
1469no_answer :-
1470 nb_setval('$answer_class', none).1476next_answer([], true, []-[]) :- 1477 !, 1478 no_answer. 1479next_answer(_Bindings, _Delays, _Residuals) :- 1480 answer_count(C0), 1481 C is C0+1, 1482 nb_setval('$answer_count', C), 1483 ( C mod 2 =:= 0 1484 -> Class = answer(even) 1485 ; Class = answer(odd) 1486 ), 1487 nb_setval('$answer_class', Class).
input followed by `\e[K`.
As the prompt is written at the start of a line this paints
the entire line, which makes a background colour extend to the
right margin.prompt, the prompt itself
and a reset.input again. These remain in effect while
the user is typing, which is how the typed text is coloured
differently from the output. end_input_style/0 cancels this
once the query has been read.Note that the line editor (see library(editline)) does not count escape sequences towards the prompt width and neither does line_position/2.
1509decorate_prompt('', Prompt) :- 1510 !, 1511 Prompt = ''. % not connected to a terminal 1512decorate_prompt(Plain, Decorated) :- 1513 prompt_sgr(input, Input), 1514 prompt_sgr(prompt, Prompt), 1515 line_editor_attributes(Input), 1516 ( Input == '', 1517 Prompt == '' 1518 -> Decorated = Plain 1519 ; Input == '' % nothing to paint the line with 1520 -> atomic_list_concat([Prompt, Plain, '\e[0m'], Decorated) 1521 ; atomic_list_concat([Input, '\e[K', Prompt, Plain, '\e[0m', Input], 1522 Decorated) 1523 ).
This is called each time we build a prompt rather than once, so that a theme loaded at run time is picked up.
1540line_editor_attributes(Input) :- 1541 ( Input == '' 1542 -> Off = '', On = '' 1543 ; Off = '\e[0m', On = Input 1544 ), 1545 ignore(prolog:line_editor_attributes(Off, On)). 1546 1547prompt_sgr(Class, Sequence) :- 1548 colour_console, 1549 current_predicate(ansi_term:ansi_sgr/2), 1550 catch(ansi_term:ansi_sgr(Class, String), _, fail), 1551 String \== "", 1552 !, 1553 atom_string(Sequence, String). 1554prompt_sgr(_, ''). 1555 1556colour_console :- 1557 current_prolog_flag(color_term, true), 1558 stream_property(user_output, tty(true)).
input.1566end_input_style :- 1567 ( colour_console 1568 -> write(user_output, '\e[0m'), 1569 flush_output(user_output) 1570 ; true 1571 ). 1572 1573'$system_prompt'(Module, BrekLev, Prompt) :- 1574 current_prolog_flag(toplevel_prompt, PAtom), 1575 atom_codes(PAtom, P0), 1576 ( Module \== user 1577 -> '$substitute'('~m', [Module, ': '], P0, P1) 1578 ; '$substitute'('~m', [], P0, P1) 1579 ), 1580 ( BrekLev > 0 1581 -> '$substitute'('~l', ['[', BrekLev, '] '], P1, P2) 1582 ; '$substitute'('~l', [], P1, P2) 1583 ), 1584 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)), 1585 ( Tracing == true 1586 -> '$substitute'('~d', ['[trace] '], P2, P3) 1587 ; Debugging == true 1588 -> '$substitute'('~d', ['[debug] '], P2, P3) 1589 ; '$substitute'('~d', [], P2, P3) 1590 ), 1591 atom_chars(Prompt, P3). 1592 1593'$substitute'(From, T, Old, New) :- 1594 atom_codes(From, FromCodes), 1595 phrase(subst_chars(T), T0), 1596 '$append'(Pre, S0, Old), 1597 '$append'(FromCodes, Post, S0) -> 1598 '$append'(Pre, T0, S1), 1599 '$append'(S1, Post, New), 1600 !. 1601'$substitute'(_, _, Old, Old). 1602 1603subst_chars([]) --> 1604 []. 1605subst_chars([H|T]) --> 1606 { atomic(H), 1607 !, 1608 atom_codes(H, Codes) 1609 }, 1610 , 1611 subst_chars(T). 1612subst_chars([H|T]) --> 1613 , 1614 subst_chars(T). 1615 1616 1617 /******************************** 1618 * EXECUTION * 1619 ********************************/
1625'$execute_query'(Var, _, true) :- 1626 var(Var), 1627 !, 1628 print_message(informational, var_query(Var)). 1629'$execute_query'(Goal, Bindings, Truth) :- 1630 '$current_typein_module'(TypeIn), 1631 '$dwim_correct_goal'(TypeIn:Goal, Bindings, Corrected), 1632 !, 1633 setup_call_cleanup( 1634 '$set_source_module'(M0, TypeIn), 1635 expand_goal(Corrected, Expanded), 1636 '$set_source_module'(M0)), 1637 print_message(silent, toplevel_goal(Expanded, Bindings)), 1638 '$execute_goal2'(Expanded, Bindings, Truth). 1639'$execute_query'(_, _, false) :- 1640 notrace, 1641 no_answer, 1642 print_message(query, query(no)). 1643 1644'$execute_goal2'(Goal, Bindings, true) :- 1645 restore_debug, 1646 '$current_typein_module'(TypeIn), 1647 residue_vars(TypeIn:Goal, Vars, TypeIn:Delays, Chp), 1648 deterministic(Det), 1649 ( save_debug 1650 ; restore_debug, fail 1651 ), 1652 flush_output(user_output), 1653 ( Det == true 1654 -> DetOrChp = true 1655 ; DetOrChp = Chp 1656 ), 1657 call_expand_answer(Goal, Bindings, NewBindings), 1658 ( \+ \+ write_bindings(NewBindings, Vars, Delays, DetOrChp) 1659 -> ! 1660 ). 1661'$execute_goal2'(_, _, false) :- 1662 save_debug, 1663 no_answer, 1664 print_message(query, query(no)). 1665 1666residue_vars(Goal, Vars, Delays, Chp) :- 1667 current_prolog_flag(toplevel_residue_vars, true), 1668 !, 1669 '$wfs_call'(call_residue_vars(stop_backtrace(Goal, Chp), Vars), Delays). 1670residue_vars(Goal, [], Delays, Chp) :- 1671 '$wfs_call'(stop_backtrace(Goal, Chp), Delays). 1672 1673stop_backtrace(Goal, Chp) :- 1674 toplevel_call(Goal), 1675 prolog_current_choice(Chp). 1676 1677toplevel_call(Goal) :- 1678 call(Goal), 1679 no_lco. 1680 1681no_lco.
groundness gives the classical behaviour,
determinism is considered more adequate and informative.
Succeeds if the user accepts the answer and fails otherwise.
1697write_bindings(Bindings, ResidueVars, Delays, DetOrChp) :- 1698 '$current_typein_module'(TypeIn), 1699 translate_bindings(Bindings, Bindings1, ResidueVars, TypeIn:Residuals), 1700 omit_qualifier(Delays, TypeIn, Delays1), 1701 next_answer(Bindings1, Delays1, Residuals), 1702 write_bindings2(Bindings, Bindings1, Residuals, Delays1, DetOrChp). 1703 1704write_bindings2(OrgBindings, [], Residuals, Delays, _) :- 1705 current_prolog_flag(prompt_alternatives_on, groundness), 1706 !, 1707 name_vars(OrgBindings, [], t(Residuals, Delays)), 1708 print_message(query, query(yes(Delays, Residuals))). 1709write_bindings2(OrgBindings, Bindings, Residuals, Delays, true) :- 1710 current_prolog_flag(prompt_alternatives_on, determinism), 1711 !, 1712 name_vars(OrgBindings, Bindings, t(Residuals, Delays)), 1713 print_message(query, query(yes(Bindings, Delays, Residuals))). 1714write_bindings2(OrgBindings, Bindings, Residuals, Delays, Chp) :- 1715 repeat, 1716 name_vars(OrgBindings, Bindings, t(Residuals, Delays)), 1717 print_message(query, query(more(Bindings, Delays, Residuals))), 1718 get_respons(Action, Chp), 1719 ( Action == redo 1720 -> !, fail 1721 ; Action == show_again 1722 -> fail 1723 ; !, 1724 no_answer, 1725 print_message(query, query(done)) 1726 ).
_[A-Z][0-9]* to all variables in Term, that do not
have a name due to Bindings. Singleton variables in Term are named
_. The behavior depends on these Prolog flags:
true, else name_vars/3 is a no-op.
Variables are named by unifying them to '$VAR'(Name)
1742name_vars(OrgBindings, Bindings, Term) :- 1743 current_prolog_flag(toplevel_name_variables, true), 1744 answer_flags_imply_numbervars, 1745 !, 1746 '$term_multitons'(t(Bindings,Term), Vars), 1747 bindings_var_names(OrgBindings, Bindings, VarNames), 1748 name_vars_(Vars, VarNames, 0), 1749 term_variables(t(Bindings,Term), SVars), 1750 anon_vars(SVars). 1751name_vars(_OrgBindings, _Bindings, _Term). 1752 1753name_vars_([], _, _). 1754name_vars_([H|T], Bindings, N) :- 1755 name_var(Bindings, Name, N, N1), 1756 H = '$VAR'(Name), 1757 name_vars_(T, Bindings, N1). 1758 1759anon_vars([]). 1760anon_vars(['$VAR'('_')|T]) :- 1761 anon_vars(T).
1768name_var(Reserved, Name, N0, N) :-
1769 between(N0, infinite, N1),
1770 I is N1//26,
1771 J is 0'A + N1 mod 26,
1772 ( I == 0
1773 -> format(atom(Name), '_~c', [J])
1774 ; format(atom(Name), '_~c~d', [J, I])
1775 ),
1776 \+ memberchk(Name, Reserved),
1777 !,
1778 N is N1+1.
1787bindings_var_names(OrgBindings, TransBindings, VarNames) :-
1788 phrase(bindings_var_names_(OrgBindings), VarNames0, Tail),
1789 phrase(bindings_var_names_(TransBindings), Tail, []),
1790 sort(VarNames0, VarNames).1797bindings_var_names_([]) --> []. 1798bindings_var_names_([H|T]) --> 1799 binding_var_names(H), 1800 bindings_var_names_(T). 1801 1802binding_var_names(binding(Vars,_Value,_Subst)) ==> 1803 var_names(Vars). 1804binding_var_names(Name=_Value) ==> 1805 [Name]. 1806 1807var_names([]) --> []. 1808var_names([H|T]) --> [H], var_names(T).
1816answer_flags_imply_numbervars :- 1817 current_prolog_flag(answer_write_options, Options), 1818 numbervars_option(Opt), 1819 '$option'(Opt, Options), 1820 !. 1821 1822numbervars_option(portray(true)). 1823numbervars_option(portrayed(true)). 1824numbervars_option(numbervars(true)).
1831:- multifile 1832 residual_goal_collector/1. 1833 1834:- meta_predicate 1835 residual_goals(). 1836 1837residual_goals(NonTerminal) :- 1838 throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)). 1839 1840systemterm_expansion((:- residual_goals(NonTerminal)), 1841 '$toplevel':residual_goal_collector(M2:Head)) :- 1842 \+ current_prolog_flag(xref, true), 1843 prolog_load_context(module, M), 1844 strip_module(M:NonTerminal, M2, Head), 1845 '$must_be'(callable, Head).
1852:- public prolog:residual_goals//0. 1853 1854prolog:residual_goals --> 1855 { findall(NT, residual_goal_collector(NT), NTL) }, 1856 collect_residual_goals(NTL). 1857 1858collect_residual_goals([]) --> []. 1859collect_residual_goals([H|T]) --> 1860 ( call(H) -> [] ; [] ), 1861 collect_residual_goals(T).
1886:- public 1887 prolog:translate_bindings/5. 1888:- meta_predicate 1889 prolog:translate_bindings(, , , , ). 1890 1891prologtranslate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals) :- 1892 translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals), 1893 name_vars(Bindings0, Bindings, t(ResVars, ResGoals, Residuals)). 1894 1895% should not be required. 1896prologname_vars(Bindings, Term) :- name_vars([], Bindings, Term). 1897prologname_vars(Bindings0, Bindings, Term) :- name_vars(Bindings0, Bindings, Term). 1898 1899translate_bindings(Bindings0, Bindings, ResidueVars, Residuals) :- 1900 prolog:residual_goals(ResidueGoals, []), 1901 translate_bindings(Bindings0, Bindings, ResidueVars, ResidueGoals, 1902 Residuals). 1903 1904translate_bindings(Bindings0, Bindings, [], [], _:[]-[]) :- 1905 term_attvars(Bindings0, []), 1906 !, 1907 join_same_bindings(Bindings0, Bindings1), 1908 factorize_bindings(Bindings1, Bindings2), 1909 bind_vars(Bindings2, Bindings3), 1910 filter_bindings(Bindings3, Bindings). 1911translate_bindings(Bindings0, Bindings, ResidueVars, ResGoals0, 1912 TypeIn:Residuals-HiddenResiduals) :- 1913 project_constraints(Bindings0, ResidueVars), 1914 hidden_residuals(ResidueVars, Bindings0, HiddenResiduals0), 1915 omit_qualifiers(HiddenResiduals0, TypeIn, HiddenResiduals), 1916 copy_term(Bindings0+ResGoals0, Bindings1+ResGoals1, Residuals0), 1917 '$append'(ResGoals1, Residuals0, Residuals1), 1918 omit_qualifiers(Residuals1, TypeIn, Residuals), 1919 join_same_bindings(Bindings1, Bindings2), 1920 factorize_bindings(Bindings2, Bindings3), 1921 bind_vars(Bindings3, Bindings4), 1922 filter_bindings(Bindings4, Bindings). 1923 (ResidueVars, Bindings, Goal) :- 1925 term_attvars(ResidueVars, Remaining), 1926 term_attvars(Bindings, QueryVars), 1927 subtract_vars(Remaining, QueryVars, HiddenVars), 1928 copy_term(HiddenVars, _, Goal). 1929 1930subtract_vars(All, Subtract, Remaining) :- 1931 sort(All, AllSorted), 1932 sort(Subtract, SubtractSorted), 1933 ord_subtract(AllSorted, SubtractSorted, Remaining). 1934 1935ord_subtract([], _Not, []). 1936ord_subtract([H1|T1], L2, Diff) :- 1937 diff21(L2, H1, T1, Diff). 1938 1939diff21([], H1, T1, [H1|T1]). 1940diff21([H2|T2], H1, T1, Diff) :- 1941 compare(Order, H1, H2), 1942 diff3(Order, H1, T1, H2, T2, Diff). 1943 1944diff12([], _H2, _T2, []). 1945diff12([H1|T1], H2, T2, Diff) :- 1946 compare(Order, H1, H2), 1947 diff3(Order, H1, T1, H2, T2, Diff). 1948 1949diff3(<, H1, T1, H2, T2, [H1|Diff]) :- 1950 diff12(T1, H2, T2, Diff). 1951diff3(=, _H1, T1, _H2, T2, Diff) :- 1952 ord_subtract(T1, T2, Diff). 1953diff3(>, H1, T1, _H2, T2, Diff) :- 1954 diff21(T2, H1, T1, Diff).
toplevel_residue_vars is set to project.1962project_constraints(Bindings, ResidueVars) :- 1963 !, 1964 term_attvars(Bindings, AttVars), 1965 phrase(attribute_modules(AttVars), Modules0), 1966 sort(Modules0, Modules), 1967 term_variables(Bindings, QueryVars), 1968 project_attributes(Modules, QueryVars, ResidueVars). 1969project_constraints(_, _). 1970 1971project_attributes([], _, _). 1972project_attributes([M|T], QueryVars, ResidueVars) :- 1973 ( current_predicate(M:project_attributes/2), 1974 catch(M:project_attributes(QueryVars, ResidueVars), E, 1975 print_message(error, E)) 1976 -> true 1977 ; true 1978 ), 1979 project_attributes(T, QueryVars, ResidueVars). 1980 1981attribute_modules([]) --> []. 1982attribute_modules([H|T]) --> 1983 { get_attrs(H, Attrs) }, 1984 attrs_modules(Attrs), 1985 attribute_modules(T). 1986 1987attrs_modules([]) --> []. 1988attrs_modules(att(Module, _, More)) --> 1989 [Module], 1990 attrs_modules(More).
2001join_same_bindings([], []). 2002join_same_bindings([Name=V0|T0], [[Name|Names]=V|T]) :- 2003 take_same_bindings(T0, V0, V, Names, T1), 2004 join_same_bindings(T1, T). 2005 2006take_same_bindings([], Val, Val, [], []). 2007take_same_bindings([Name=V1|T0], V0, V, [Name|Names], T) :- 2008 V0 == V1, 2009 !, 2010 take_same_bindings(T0, V1, V, Names, T). 2011take_same_bindings([Pair|T0], V0, V, Names, [Pair|T]) :- 2012 take_same_bindings(T0, V0, V, Names, T).
2021omit_qualifiers([], _, []). 2022omit_qualifiers([Goal0|Goals0], TypeIn, [Goal|Goals]) :- 2023 omit_qualifier(Goal0, TypeIn, Goal), 2024 omit_qualifiers(Goals0, TypeIn, Goals). 2025 2026omit_qualifier(M:G0, TypeIn, G) :- 2027 M == TypeIn, 2028 !, 2029 omit_meta_qualifiers(G0, TypeIn, G). 2030omit_qualifier(M:G0, TypeIn, G) :- 2031 predicate_property(TypeIn:G0, imported_from(M)), 2032 \+ predicate_property(G0, transparent), 2033 !, 2034 G0 = G. 2035omit_qualifier(_:G0, _, G) :- 2036 predicate_property(G0, built_in), 2037 \+ predicate_property(G0, transparent), 2038 !, 2039 G0 = G. 2040omit_qualifier(M:G0, _, M:G) :- 2041 atom(M), 2042 !, 2043 omit_meta_qualifiers(G0, M, G). 2044omit_qualifier(G0, TypeIn, G) :- 2045 omit_meta_qualifiers(G0, TypeIn, G). 2046 2047omit_meta_qualifiers(V, _, V) :- 2048 var(V), 2049 !. 2050omit_meta_qualifiers((QA,QB), TypeIn, (A,B)) :- 2051 !, 2052 omit_qualifier(QA, TypeIn, A), 2053 omit_qualifier(QB, TypeIn, B). 2054omit_meta_qualifiers(tnot(QA), TypeIn, tnot(A)) :- 2055 !, 2056 omit_qualifier(QA, TypeIn, A). 2057omit_meta_qualifiers(freeze(V, QGoal), TypeIn, freeze(V, Goal)) :- 2058 callable(QGoal), 2059 !, 2060 omit_qualifier(QGoal, TypeIn, Goal). 2061omit_meta_qualifiers(when(Cond, QGoal), TypeIn, when(Cond, Goal)) :- 2062 callable(QGoal), 2063 !, 2064 omit_qualifier(QGoal, TypeIn, Goal). 2065omit_meta_qualifiers(G, _, G).
2074bind_vars(Bindings0, Bindings) :- 2075 bind_query_vars(Bindings0, Bindings, SNames), 2076 bind_skel_vars(Bindings, Bindings, SNames, 1, _). 2077 2078bind_query_vars([], [], []). 2079bind_query_vars([binding(Names,Var,[Var2=Cycle])|T0], 2080 [binding(Names,Cycle,[])|T], [Name|SNames]) :- 2081 Var == Var2, % also implies var(Var) 2082 !, 2083 '$last'(Names, Name), 2084 Var = '$VAR'(Name), 2085 bind_query_vars(T0, T, SNames). 2086bind_query_vars([B|T0], [B|T], AllNames) :- 2087 B = binding(Names,Var,Skel), 2088 bind_query_vars(T0, T, SNames), 2089 ( var(Var), \+ attvar(Var), Skel == [] 2090 -> AllNames = [Name|SNames], 2091 '$last'(Names, Name), 2092 Var = '$VAR'(Name) 2093 ; AllNames = SNames 2094 ). 2095 2096 2097 2098bind_skel_vars([], _, _, N, N). 2099bind_skel_vars([binding(_,_,Skel)|T], Bindings, SNames, N0, N) :- 2100 bind_one_skel_vars(Skel, Bindings, SNames, N0, N1), 2101 bind_skel_vars(T, Bindings, SNames, N1, N).
2120bind_one_skel_vars([], _, _, N, N). 2121bind_one_skel_vars([Var=Value|T], Bindings, Names, N0, N) :- 2122 ( var(Var) 2123 -> ( '$member'(binding(Names, VVal, []), Bindings), 2124 same_term(Value, VVal) 2125 -> '$last'(Names, VName), 2126 Var = '$VAR'(VName), 2127 N2 = N0 2128 ; between(N0, infinite, N1), 2129 atom_concat('_S', N1, Name), 2130 \+ memberchk(Name, Names), 2131 !, 2132 Var = '$VAR'(Name), 2133 N2 is N1 + 1 2134 ) 2135 ; N2 = N0 2136 ), 2137 bind_one_skel_vars(T, Bindings, Names, N2, N).
2144factorize_bindings([], []). 2145factorize_bindings([Name=Value|T0], [binding(Name, Skel, Subst)|T]) :- 2146 '$factorize_term'(Value, Skel, Subst0), 2147 ( current_prolog_flag(toplevel_print_factorized, true) 2148 -> Subst = Subst0 2149 ; only_cycles(Subst0, Subst) 2150 ), 2151 factorize_bindings(T0, T). 2152 2153 2154only_cycles([], []). 2155only_cycles([B|T0], List) :- 2156 ( B = (Var=Value), 2157 Var = Value, 2158 acyclic_term(Var) 2159 -> only_cycles(T0, List) 2160 ; List = [B|T], 2161 only_cycles(T0, T) 2162 ).
2171filter_bindings([], []). 2172filter_bindings([H0|T0], T) :- 2173 hide_vars(H0, H), 2174 ( ( arg(1, H, []) 2175 ; self_bounded(H) 2176 ) 2177 -> filter_bindings(T0, T) 2178 ; T = [H|T1], 2179 filter_bindings(T0, T1) 2180 ). 2181 2182hide_vars(binding(Names0, Skel, Subst), binding(Names, Skel, Subst)) :- 2183 hide_names(Names0, Skel, Subst, Names). 2184 2185hide_names([], _, _, []). 2186hide_names([Name|T0], Skel, Subst, T) :- 2187 ( anon_var_name(Name), 2188 current_prolog_flag(toplevel_print_anon, false) 2189 -> true 2190 ; Subst == [], 2191 Skel == '$VAR'(Name) 2192 ), 2193 !, 2194 hide_names(T0, Skel, Subst, T). 2195hide_names([Name|T0], Skel, Subst, [Name|T]) :- 2196 hide_names(T0, Skel, Subst, T). 2197 2198% anon_var_name(+Name) is semidet. 2199% 2200% True if Name is `_X`, or `?_X` if the flag `var_prefix` is `?`. 2201 2202anon_var_name(Name) :- 2203 ( sub_atom(Name, 0, 1, _, '_') 2204 -> S = 1 2205 ; sub_atom(Name, 0, 1, _, P), 2206 char_type(P, prolog_symbol), 2207 sub_atom(Name, 1, 1, _, '_') 2208 -> S = 2 2209 ), 2210 sub_atom(Name, S, 1, _, Next), 2211 char_type(Next, prolog_var_start). 2212 2213self_bounded(binding([Name], Value, [])) :- 2214 Value == '$VAR'(Name).
2220:- if(current_prolog_flag(emscripten, true)). 2221get_respons(Action, Chp) :- 2222 '$can_yield', 2223 !, 2224 repeat, 2225 await(more, CommandS), 2226 atom_string(Command, CommandS), 2227 more_action(Command, Chp, Action), 2228 ( Action == again 2229 -> print_message(query, query(action)), 2230 fail 2231 ; ! 2232 ). 2233:- endif. 2234get_respons(Action, Chp) :- 2235 repeat, 2236 flush_output(user_output), 2237 get_single_char(Code), 2238 find_more_command(Code, Command, Feedback, Style), 2239 ( Style \== '-' 2240 -> print_message(query, if_tty([ansi(Style, '~w', [Feedback])])) 2241 ; true 2242 ), 2243 more_action(Command, Chp, Action), 2244 ( Action == again 2245 -> print_message(query, query(action)), 2246 fail 2247 ; ! 2248 ). 2249 2250find_more_command(-1, end_of_file, 'EOF', warning) :- 2251 !. 2252find_more_command(Code, Command, Feedback, Style) :- 2253 more_command(Command, Atom, Feedback, Style), 2254 '$in_reply'(Code, Atom), 2255 !. 2256find_more_command(Code, again, '', -) :- 2257 print_message(query, no_action(Code)). 2258 2259more_command(help, '?h', '', -). 2260more_command(redo, ';nrNR \t', ';', bold). 2261more_command(trace, 'tT', '; [trace]', comment). 2262more_command(continue, 'ca\n\ryY.', '.', bold). 2263more_command(break, 'b', '', -). 2264more_command(choicepoint, '*', '', -). 2265more_command(write, 'w', '[write]', comment). 2266more_command(print, 'p', '[print]', comment). 2267more_command(depth_inc, '+', Change, comment) :- 2268 ( print_depth(Depth0) 2269 -> depth_step(Step), 2270 NewDepth is Depth0*Step, 2271 format(atom(Change), '[max_depth(~D)]', [NewDepth]) 2272 ; Change = 'no max_depth' 2273 ). 2274more_command(depth_dec, '-', Change, comment) :- 2275 ( print_depth(Depth0) 2276 -> depth_step(Step), 2277 NewDepth is max(1, Depth0//Step), 2278 format(atom(Change), '[max_depth(~D)]', [NewDepth]) 2279 ; Change = '[max_depth(10)]' 2280 ). 2281 2282more_action(help, _, Action) => 2283 Action = again, 2284 print_message(help, query(help)). 2285more_action(redo, _, Action) => % Next 2286 Action = redo. 2287more_action(trace, _, Action) => 2288 Action = redo, 2289 trace, 2290 save_debug. 2291more_action(continue, _, Action) => % Stop 2292 Action = continue. 2293more_action(break, _, Action) => 2294 Action = show_again, 2295 break. 2296more_action(choicepoint, Chp, Action) => 2297 Action = show_again, 2298 print_last_chpoint(Chp). 2299more_action(end_of_file, _, Action) => 2300 Action = show_again, 2301 halt(0). 2302more_action(again, _, Action) => 2303 Action = again. 2304more_action(Command, _, Action), 2305 current_prolog_flag(answer_write_options, Options0), 2306 print_predicate(Command, Options0, Options) => 2307 Action = show_again, 2308 set_prolog_flag(answer_write_options, Options). 2309 2310print_depth(Depth) :- 2311 current_prolog_flag(answer_write_options, Options), 2312 '$option'(max_depth(Depth), Options), 2313 !.
answer_write_options value according to the user
command.2320print_predicate(write, Options0, Options) :- 2321 edit_options([-portrayed(true),-portray(true)], 2322 Options0, Options). 2323print_predicate(print, Options0, Options) :- 2324 edit_options([+portrayed(true)], 2325 Options0, Options). 2326print_predicate(depth_inc, Options0, Options) :- 2327 ( '$select'(max_depth(D0), Options0, Options1) 2328 -> depth_step(Step), 2329 D is D0*Step, 2330 Options = [max_depth(D)|Options1] 2331 ; Options = Options0 2332 ). 2333print_predicate(depth_dec, Options0, Options) :- 2334 ( '$select'(max_depth(D0), Options0, Options1) 2335 -> depth_step(Step), 2336 D is max(1, D0//Step), 2337 Options = [max_depth(D)|Options1] 2338 ; D = 10, 2339 Options = [max_depth(D)|Options0] 2340 ). 2341 2342depth_step(5). 2343 2344edit_options([], Options, Options). 2345edit_options([H|T], Options0, Options) :- 2346 edit_option(H, Options0, Options1), 2347 edit_options(T, Options1, Options). 2348 2349edit_option(-Term, Options0, Options) => 2350 ( '$select'(Term, Options0, Options) 2351 -> true 2352 ; Options = Options0 2353 ). 2354edit_option(+Term, Options0, Options) => 2355 functor(Term, Name, 1), 2356 functor(Var, Name, 1), 2357 ( '$select'(Var, Options0, Options1) 2358 -> Options = [Term|Options1] 2359 ; Options = [Term|Options0] 2360 ).
2366print_last_chpoint(Chp) :- 2367 current_predicate(print_last_choice_point/0), 2368 !, 2369 print_last_chpoint_(Chp). 2370print_last_chpoint(Chp) :- 2371 use_module(library(prolog_stack), [print_last_choicepoint/2]), 2372 print_last_chpoint_(Chp). 2373 2374print_last_chpoint_(Chp) :- 2375 print_last_choicepoint(Chp, [message_level(information)]). 2376 2377 2378 /******************************* 2379 * EXPANSION * 2380 *******************************/ 2381 2382:- user:dynamic(expand_query/4). 2383:- user:multifile(expand_query/4). 2384 2385call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :- 2386 ( '$replace_toplevel_vars'(Goal, Expanded0, Bindings, ExpandedBindings0) 2387 -> true 2388 ; Expanded0 = Goal, ExpandedBindings0 = Bindings 2389 ), 2390 ( user:expand_query(Expanded0, Expanded, ExpandedBindings0, ExpandedBindings) 2391 -> true 2392 ; Expanded = Expanded0, ExpandedBindings = ExpandedBindings0 2393 ). 2394 2395 2396:- dynamic 2397 user:expand_answer/2, 2398 prolog:expand_answer/3. 2399:- multifile 2400 user:expand_answer/2, 2401 prolog:expand_answer/3. 2402 2403call_expand_answer(Goal, BindingsIn, BindingsOut) :- 2404 ( prolog:expand_answer(Goal, BindingsIn, BindingsOut) 2405 -> true 2406 ; user:expand_answer(BindingsIn, BindingsOut) 2407 -> true 2408 ; BindingsOut = BindingsIn 2409 ), 2410 '$save_toplevel_vars'(BindingsOut), 2411 !. 2412call_expand_answer(_, Bindings, Bindings)