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-2024, 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.
67version :-
68 print_message(banner, welcome).
74:- multifile 75 system:term_expansion/2. 76 77systemterm_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 *********************************/
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(prolog) :- 104 !, 105 load_init_file('init.pl', implicit). 106load_init_file(none) :- 107 !, 108 load_init_file('init.pl', implicit). 109load_init_file(_).
115:- dynamic 116 loaded_init_file/2. % already loaded init files 117 118load_init_file(none, _) :- !. 119load_init_file(Base, _) :- 120 loaded_init_file(Base, _), 121 !. 122load_init_file(InitFile, explicit) :- 123 exists_file(InitFile), 124 !, 125 ensure_loaded(user:InitFile). 126load_init_file(Base, _) :- 127 absolute_file_name(user_app_config(Base), InitFile, 128 [ access(read), 129 file_errors(fail) 130 ]), 131 !, 132 asserta(loaded_init_file(Base, InitFile)), 133 load_files(user:InitFile, 134 [ scope_settings(false) 135 ]). 136load_init_file('init.pl', implicit) :- 137 ( current_prolog_flag(windows, true), 138 absolute_file_name(user_profile('swipl.ini'), InitFile, 139 [ access(read), 140 file_errors(fail) 141 ]) 142 ; expand_file_name('~/.swiplrc', [InitFile]), 143 exists_file(InitFile) 144 ), 145 !, 146 print_message(warning, backcomp(init_file_moved(InitFile))). 147load_init_file(_, _). 148 149'$load_system_init_file' :- 150 loaded_init_file(system, _), 151 !. 152'$load_system_init_file' :- 153 '$cmd_option_val'(system_init_file, Base), 154 Base \== none, 155 current_prolog_flag(home, Home), 156 file_name_extension(Base, rc, Name), 157 atomic_list_concat([Home, '/', Name], File), 158 absolute_file_name(File, Path, 159 [ file_type(prolog), 160 access(read), 161 file_errors(fail) 162 ]), 163 asserta(loaded_init_file(system, Path)), 164 load_files(user:Path, 165 [ silent(true), 166 scope_settings(false) 167 ]), 168 !. 169'$load_system_init_file'. 170 171'$load_script_file' :- 172 loaded_init_file(script, _), 173 !. 174'$load_script_file' :- 175 '$cmd_option_val'(script_file, OsFiles), 176 load_script_files(OsFiles). 177 178load_script_files([]). 179load_script_files([OsFile|More]) :- 180 prolog_to_os_filename(File, OsFile), 181 ( absolute_file_name(File, Path, 182 [ file_type(prolog), 183 access(read), 184 file_errors(fail) 185 ]) 186 -> asserta(loaded_init_file(script, Path)), 187 load_files(user:Path), 188 load_files(user:More) 189 ; throw(error(existence_error(script_file, File), _)) 190 ). 191 192 193 /******************************* 194 * AT_INITIALISATION * 195 *******************************/ 196 197:- meta_predicate 198 initialization( ). 199 200:- '$iso'((initialization)/1).
209initialization(Goal) :- 210 Goal = _:G, 211 prolog:initialize_now(G, Use), 212 !, 213 print_message(warning, initialize_now(G, Use)), 214 initialization(Goal, now). 215initialization(Goal) :- 216 initialization(Goal, after_load). 217 218:- multifile 219 prolog:initialize_now/2, 220 prolog:message//1. 221 222prologinitialize_now(load_foreign_library(_), 223 'use :- use_foreign_library/1 instead'). 224prologinitialize_now(load_foreign_library(_,_), 225 'use :- use_foreign_library/2 instead'). 226 227prologmessage(initialize_now(Goal, Use)) --> 228 [ 'Initialization goal ~p will be executed'-[Goal],nl, 229 'immediately for backward compatibility reasons', nl, 230 '~w'-[Use] 231 ]. 232 233'$run_initialization' :- 234 '$set_prolog_file_extension', 235 '$run_initialization'(_, []), 236 '$thread_init'.
:- initialization(Goal, program).
. Stop
with an exception if a goal fails or raises an exception.243initialize :- 244 forall('$init_goal'(when(program), Goal, Ctx), 245 run_initialize(Goal, Ctx)). 246 247run_initialize(Goal, Ctx) :- 248 ( catch(Goal, E, true), 249 ( var(E) 250 -> true 251 ; throw(error(initialization_error(E, Goal, Ctx), _)) 252 ) 253 ; throw(error(initialization_error(failed, Goal, Ctx), _)) 254 ). 255 256 257 /******************************* 258 * THREAD INITIALIZATION * 259 *******************************/ 260 261:- meta_predicate 262 thread_initialization( ). 263:- dynamic 264 '$at_thread_initialization'/1.
270thread_initialization(Goal) :- 271 assert('$at_thread_initialization'(Goal)), 272 call(Goal), 273 !. 274 275'$thread_init' :- 276 ( '$at_thread_initialization'(Goal), 277 ( call(Goal) 278 -> fail 279 ; fail 280 ) 281 ; true 282 ). 283 284 285 /******************************* 286 * FILE SEARCH PATH (-p) * 287 *******************************/
293'$set_file_search_paths' :- 294 '$cmd_option_val'(search_paths, Paths), 295 ( '$member'(Path, Paths), 296 atom_chars(Path, Chars), 297 ( phrase('$search_path'(Name, Aliases), Chars) 298 -> '$reverse'(Aliases, Aliases1), 299 forall('$member'(Alias, Aliases1), 300 asserta(user:file_search_path(Name, Alias))) 301 ; print_message(error, commandline_arg_type(p, Path)) 302 ), 303 fail ; true 304 ). 305 306'$search_path'(Name, Aliases) --> 307 '$string'(NameChars), 308 [=], 309 !, 310 {atom_chars(Name, NameChars)}, 311 '$search_aliases'(Aliases). 312 313'$search_aliases'([Alias|More]) --> 314 '$string'(AliasChars), 315 path_sep, 316 !, 317 { '$make_alias'(AliasChars, Alias) }, 318 '$search_aliases'(More). 319'$search_aliases'([Alias]) --> 320 '$string'(AliasChars), 321 '$eos', 322 !, 323 { '$make_alias'(AliasChars, Alias) }. 324 325path_sep --> 326 { current_prolog_flag(path_sep, Sep) }, 327 [Sep]. 328 329'$string'([]) --> []. 330'$string'([H|T]) --> [H], '$string'(T). 331 332'$eos'([], []). 333 334'$make_alias'(Chars, Alias) :- 335 catch(term_to_atom(Alias, Chars), _, fail), 336 ( atom(Alias) 337 ; functor(Alias, F, 1), 338 F \== / 339 ), 340 !. 341'$make_alias'(Chars, Alias) :- 342 atom_chars(Alias, Chars). 343 344 345 /******************************* 346 * LOADING ASSIOCIATED FILES * 347 *******************************/
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 availabkle 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 argv
search(name)
as Prolog file,
make this the content of Files and pass the remainder as
options to argv
.381argv_prolog_files([], exe) :- 382 current_prolog_flag(saved_program_class, runtime), 383 !, 384 clean_argv. 385argv_prolog_files(Files, ScriptMode) :- 386 current_prolog_flag(argv, Argv), 387 no_option_files(Argv, Argv1, Files, ScriptMode), 388 ( ( nonvar(ScriptMode) 389 ; Argv1 == [] 390 ) 391 -> ( Argv1 \== Argv 392 -> set_prolog_flag(argv, Argv1) 393 ; true 394 ) 395 ; '$usage', 396 halt(1) 397 ). 398 399no_option_files([--|Argv], Argv, [], ScriptMode) :- 400 !, 401 ( ScriptMode = none 402 -> true 403 ; true 404 ). 405no_option_files([Opt|_], _, _, ScriptMode) :- 406 var(ScriptMode), 407 sub_atom(Opt, 0, _, _, '-'), 408 !, 409 '$usage', 410 halt(1). 411no_option_files([OsFile|Argv0], Argv, [File|T], ScriptMode) :- 412 file_name_extension(_, Ext, OsFile), 413 user:prolog_file_type(Ext, prolog), 414 !, 415 ScriptMode = prolog, 416 prolog_to_os_filename(File, OsFile), 417 no_option_files(Argv0, Argv, T, ScriptMode). 418no_option_files([OsScript|Argv], Argv, [Script], ScriptMode) :- 419 var(ScriptMode), 420 !, 421 prolog_to_os_filename(PlScript, OsScript), 422 ( exists_file(PlScript) 423 -> Script = PlScript, 424 ScriptMode = script 425 ; cli_script(OsScript, Script) 426 -> ScriptMode = app, 427 set_prolog_flag(app_name, OsScript) 428 ; '$existence_error'(file, PlScript) 429 ). 430no_option_files(Argv, Argv, [], ScriptMode) :- 431 ( ScriptMode = none 432 -> true 433 ; true 434 ). 435 436cli_script(CLI, Script) :- 437 ( sub_atom(CLI, Pre, _, Post, ':') 438 -> sub_atom(CLI, 0, Pre, _, SearchPath), 439 sub_atom(CLI, _, Post, 0, Base), 440 Spec =.. [SearchPath, Base] 441 ; Spec = app(CLI) 442 ), 443 absolute_file_name(Spec, Script, 444 [ file_type(prolog), 445 access(exist), 446 file_errors(fail) 447 ]). 448 449clean_argv :- 450 ( current_prolog_flag(argv, [--|Argv]) 451 -> set_prolog_flag(argv, Argv) 452 ; true 453 ).
462win_associated_files(Files) :-
463 ( Files = [File|_]
464 -> absolute_file_name(File, AbsFile),
465 set_prolog_flag(associated_file, AbsFile),
466 set_working_directory(File),
467 set_window_title(Files)
468 ; true
469 ).
console_menu
,
which is set by swipl-win[.exe].479set_working_directory(File) :- 480 current_prolog_flag(console_menu, true), 481 access_file(File, read), 482 !, 483 file_directory_name(File, Dir), 484 working_directory(_, Dir). 485set_working_directory(_). 486 487set_window_title([File|More]) :- 488 current_predicate(system:window_title/2), 489 !, 490 ( More == [] 491 -> Extra = [] 492 ; Extra = ['...'] 493 ), 494 atomic_list_concat(['SWI-Prolog --', File | Extra], ' ', Title), 495 system:window_title(_, Title). 496set_window_title(_).
--pldoc[=port]
is given, load the PlDoc system.503start_pldoc :- 504 '$cmd_option_val'(pldoc_server, Server), 505 ( Server == '' 506 -> call((doc_server(_), doc_browser)) 507 ; catch(atom_number(Server, Port), _, fail) 508 -> call(doc_server(Port)) 509 ; print_message(error, option_usage(pldoc)), 510 halt(1) 511 ). 512start_pldoc.
519load_associated_files(Files) :- 520 ( '$member'(File, Files), 521 load_files(user:File, [expand(false)]), 522 fail 523 ; true 524 ). 525 526hkey('HKEY_CURRENT_USER/Software/SWI/Prolog'). 527hkey('HKEY_LOCAL_MACHINE/Software/SWI/Prolog'). 528 529'$set_prolog_file_extension' :- 530 current_prolog_flag(windows, true), 531 hkey(Key), 532 catch(win_registry_get_value(Key, fileExtension, Ext0), 533 _, fail), 534 !, 535 ( atom_concat('.', Ext, Ext0) 536 -> true 537 ; Ext = Ext0 538 ), 539 ( user:prolog_file_type(Ext, prolog) 540 -> true 541 ; asserta(user:prolog_file_type(Ext, prolog)) 542 ). 543'$set_prolog_file_extension'. 544 545 546 /******************************** 547 * TOPLEVEL GOALS * 548 *********************************/
556'$initialise' :- 557 catch(initialise_prolog, E, initialise_error(E)). 558 559initialise_error('$aborted') :- !. 560initialise_error(E) :- 561 print_message(error, initialization_exception(E)), 562 fail. 563 564initialise_prolog :- 565 '$clean_history', 566 apply_defines, 567 apple_setup_app, % MacOS cwd/locale setup for swipl-win 568 init_optimise, 569 '$run_initialization', 570 argv_prolog_files(Files, ScriptMode), 571 '$load_system_init_file', % -F file 572 set_toplevel, % set `toplevel_goal` flag from -t 573 '$set_file_search_paths', % handle -p alias=dir[:dir]* 574 init_debug_flags, 575 start_pldoc, % handle --pldoc[=port] 576 opt_attach_packs, 577 load_init_file(ScriptMode), % -f file 578 catch(setup_colors, E, print_message(warning, E)), 579 win_associated_files(Files), % swipl-win: cd and update title 580 '$load_script_file', % -s file (may be repeated) 581 load_associated_files(Files), 582 '$cmd_option_val'(goals, Goals), % -g goal (may be repeated) 583 ( ScriptMode == app 584 -> run_program_init, % initialization(Goal, program) 585 run_main_init(true) 586 ; Goals == [], 587 \+ '$init_goal'(when(_), _, _) % no -g or -t or initialization(program) 588 -> version % default interactive run 589 ; run_init_goals(Goals), % run -g goals 590 ( load_only % used -l to load 591 -> version 592 ; run_program_init, % initialization(Goal, program) 593 run_main_init(false) % initialization(Goal, main) 594 ) 595 ). 596 597apply_defines :- 598 '$cmd_option_val'(defines, Defs), 599 apply_defines(Defs). 600 601apply_defines([]). 602apply_defines([H|T]) :- 603 apply_define(H), 604 apply_defines(T). 605 606apply_define(Def) :- 607 sub_atom(Def, B, _, A, '='), 608 !, 609 sub_atom(Def, 0, B, _, Flag), 610 sub_atom(Def, _, A, 0, Value0), 611 ( '$current_prolog_flag'(Flag, Value0, _Scope, Access, Type) 612 -> ( Access \== write 613 -> '$permission_error'(set, prolog_flag, Flag) 614 ; text_flag_value(Type, Value0, Value) 615 ), 616 set_prolog_flag(Flag, Value) 617 ; ( atom_number(Value0, Value) 618 -> true 619 ; Value = Value0 620 ), 621 create_prolog_flag(Flag, Value, [warn_not_accessed]) 622 ). 623apply_define(Def) :- 624 atom_concat('no-', Flag, Def), 625 !, 626 set_user_boolean_flag(Flag, false). 627apply_define(Def) :- 628 set_user_boolean_flag(Def, true). 629 630set_user_boolean_flag(Flag, Value) :- 631 current_prolog_flag(Flag, Old), 632 !, 633 ( Old == Value 634 -> true 635 ; set_prolog_flag(Flag, Value) 636 ). 637set_user_boolean_flag(Flag, Value) :- 638 create_prolog_flag(Flag, Value, [warn_not_accessed]). 639 640text_flag_value(integer, Text, Int) :- 641 atom_number(Text, Int), 642 !. 643text_flag_value(float, Text, Float) :- 644 atom_number(Text, Float), 645 !. 646text_flag_value(term, Text, Term) :- 647 term_string(Term, Text, []), 648 !. 649text_flag_value(_, Value, Value). 650 651:- if(current_prolog_flag(apple,true)). 652apple_set_working_directory :- 653 ( expand_file_name('~', [Dir]), 654 exists_directory(Dir) 655 -> working_directory(_, Dir) 656 ; true 657 ). 658 659apple_set_locale :- 660 ( getenv('LC_CTYPE', 'UTF-8'), 661 apple_current_locale_identifier(LocaleID), 662 atom_concat(LocaleID, '.UTF-8', Locale), 663 catch(setlocale(ctype, _Old, Locale), _, fail) 664 -> setenv('LANG', Locale), 665 unsetenv('LC_CTYPE') 666 ; true 667 ). 668 669apple_setup_app :- 670 current_prolog_flag(apple, true), 671 current_prolog_flag(console_menu, true), % SWI-Prolog.app on MacOS 672 apple_set_working_directory, 673 apple_set_locale. 674:- endif. 675apple_setup_app. 676 677init_optimise :- 678 current_prolog_flag(optimise, true), 679 !, 680 use_module(user:library(apply_macros)). 681init_optimise. 682 683opt_attach_packs :- 684 current_prolog_flag(packs, true), 685 !, 686 attach_packs. 687opt_attach_packs. 688 689set_toplevel :- 690 '$cmd_option_val'(toplevel, TopLevelAtom), 691 catch(term_to_atom(TopLevel, TopLevelAtom), E, 692 (print_message(error, E), 693 halt(1))), 694 create_prolog_flag(toplevel_goal, TopLevel, [type(term)]). 695 696load_only :- 697 current_prolog_flag(os_argv, OSArgv), 698 memberchk('-l', OSArgv), 699 current_prolog_flag(argv, Argv), 700 \+ memberchk('-l', Argv).
707run_init_goals([]). 708run_init_goals([H|T]) :- 709 run_init_goal(H), 710 run_init_goals(T). 711 712run_init_goal(Text) :- 713 catch(term_to_atom(Goal, Text), E, 714 ( print_message(error, init_goal_syntax(E, Text)), 715 halt(2) 716 )), 717 run_init_goal(Goal, Text).
723run_program_init :- 724 forall('$init_goal'(when(program), Goal, Ctx), 725 run_init_goal(Goal, @(Goal,Ctx))). 726 727run_main_init(_) :- 728 findall(Goal-Ctx, '$init_goal'(when(main), Goal, Ctx), Pairs), 729 '$last'(Pairs, Goal-Ctx), 730 !, 731 ( current_prolog_flag(toplevel_goal, default) 732 -> set_prolog_flag(toplevel_goal, halt) 733 ; true 734 ), 735 run_init_goal(Goal, @(Goal,Ctx)). 736run_main_init(true) :- 737 '$existence_error'(initialization, main). 738run_main_init(_). 739 740run_init_goal(Goal, Ctx) :- 741 ( catch_with_backtrace(user:Goal, E, true) 742 -> ( var(E) 743 -> true 744 ; print_message(error, init_goal_failed(E, Ctx)), 745 halt(2) 746 ) 747 ; ( current_prolog_flag(verbose, silent) 748 -> Level = silent 749 ; Level = error 750 ), 751 print_message(Level, init_goal_failed(failed, Ctx)), 752 halt(1) 753 ).
760init_debug_flags :-
761 once(print_predicate(_, [print], PrintOptions)),
762 Keep = [keep(true)],
763 create_prolog_flag(answer_write_options, PrintOptions, Keep),
764 create_prolog_flag(prompt_alternatives_on, determinism, Keep),
765 create_prolog_flag(toplevel_extra_white_line, true, Keep),
766 create_prolog_flag(toplevel_print_factorized, false, Keep),
767 create_prolog_flag(print_write_options,
768 [ portray(true), quoted(true), numbervars(true) ],
769 Keep),
770 create_prolog_flag(toplevel_residue_vars, false, Keep),
771 create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
772 '$set_debugger_write_options'(print).
778setup_backtrace :-
779 ( \+ current_prolog_flag(backtrace, false),
780 load_setup_file(library(prolog_stack))
781 -> true
782 ; true
783 ).
789setup_colors :-
790 ( \+ current_prolog_flag(color_term, false),
791 stream_property(user_input, tty(true)),
792 stream_property(user_error, tty(true)),
793 stream_property(user_output, tty(true)),
794 \+ getenv('TERM', dumb),
795 load_setup_file(user:library(ansi_term))
796 -> true
797 ; true
798 ).
804setup_history :-
805 ( \+ current_prolog_flag(save_history, false),
806 stream_property(user_input, tty(true)),
807 \+ current_prolog_flag(readline, false),
808 load_setup_file(library(prolog_history))
809 -> prolog_history(enable)
810 ; true
811 ),
812 set_default_history,
813 '$load_history'.
819setup_readline :- 820 ( current_prolog_flag(readline, swipl_win) 821 -> true 822 ; stream_property(user_input, tty(true)), 823 current_prolog_flag(tty_control, true), 824 \+ getenv('TERM', dumb), 825 ( current_prolog_flag(readline, ReadLine) 826 -> true 827 ; ReadLine = true 828 ), 829 readline_library(ReadLine, Library), 830 load_setup_file(library(Library)) 831 -> set_prolog_flag(readline, Library) 832 ; set_prolog_flag(readline, false) 833 ). 834 835readline_library(true, Library) :- 836 !, 837 preferred_readline(Library). 838readline_library(false, _) :- 839 !, 840 fail. 841readline_library(Library, Library). 842 843preferred_readline(editline). 844preferred_readline(readline).
850load_setup_file(File) :- 851 catch(load_files(File, 852 [ silent(true), 853 if(not_loaded) 854 ]), _, fail). 855 856 857:- '$hide'('$toplevel'/0). % avoid in the GUI stacktrace
863'$toplevel' :-
864 '$runtoplevel',
865 print_message(informational, halt).
default
and prolog
both
start the interactive toplevel, where prolog
implies the user gave
-t prolog
.
875'$runtoplevel' :- 876 current_prolog_flag(toplevel_goal, TopLevel0), 877 toplevel_goal(TopLevel0, TopLevel), 878 user:TopLevel. 879 880:- dynamic setup_done/0. 881:- volatile setup_done/0. 882 883toplevel_goal(default, '$query_loop') :- 884 !, 885 setup_interactive. 886toplevel_goal(prolog, '$query_loop') :- 887 !, 888 setup_interactive. 889toplevel_goal(Goal, Goal). 890 891setup_interactive :- 892 setup_done, 893 !. 894setup_interactive :- 895 asserta(setup_done), 896 catch(setup_backtrace, E, print_message(warning, E)), 897 catch(setup_readline, E, print_message(warning, E)), 898 catch(setup_history, E, print_message(warning, E)).
904'$compile' :- 905 ( catch('$compile_', E, (print_message(error, E), halt(1))) 906 -> true 907 ; print_message(error, error(goal_failed('$compile'), _)), 908 halt(1) 909 ), 910 halt. % set exit code 911 912'$compile_' :- 913 '$load_system_init_file', 914 catch(setup_colors, _, true), 915 '$set_file_search_paths', 916 init_debug_flags, 917 '$run_initialization', 918 opt_attach_packs, 919 use_module(library(qsave)), 920 qsave:qsave_toplevel.
926'$config' :- 927 '$load_system_init_file', 928 '$set_file_search_paths', 929 init_debug_flags, 930 '$run_initialization', 931 load_files(library(prolog_config)), 932 ( catch(prolog_dump_runtime_variables, E, 933 (print_message(error, E), halt(1))) 934 -> true 935 ; print_message(error, error(goal_failed(prolog_dump_runtime_variables),_)) 936 ). 937 938 939 /******************************** 940 * USER INTERACTIVE LOOP * 941 *********************************/
forall(prolog:repl_loop_hook(BeginEnd, BreakLevel), true)
954:- multifile
955 prolog:repl_loop_hook/2.
963prolog :- 964 break. 965 966:- create_prolog_flag(toplevel_mode, backtracking, []).
query_loop()
. This ensures that unhandled
exceptions are really unhandled (in Prolog).975'$query_loop' :- 976 break_level(BreakLev), 977 setup_call_cleanup( 978 notrace(call_repl_loop_hook(begin, BreakLev)), 979 '$query_loop'(BreakLev), 980 notrace(call_repl_loop_hook(end, BreakLev))). 981 982call_repl_loop_hook(BeginEnd, BreakLev) :- 983 forall(prolog:repl_loop_hook(BeginEnd, BreakLev), true). 984 985 986'$query_loop'(BreakLev) :- 987 current_prolog_flag(toplevel_mode, recursive), 988 !, 989 read_expanded_query(BreakLev, Query, Bindings), 990 ( Query == end_of_file 991 -> print_message(query, query(eof)) 992 ; '$call_no_catch'('$execute_query'(Query, Bindings, _)), 993 ( current_prolog_flag(toplevel_mode, recursive) 994 -> '$query_loop'(BreakLev) 995 ; '$switch_toplevel_mode'(backtracking), 996 '$query_loop'(BreakLev) % Maybe throw('$switch_toplevel_mode')? 997 ) 998 ). 999'$query_loop'(BreakLev) :- 1000 repeat, 1001 read_expanded_query(BreakLev, Query, Bindings), 1002 ( Query == end_of_file 1003 -> !, print_message(query, query(eof)) 1004 ; '$execute_query'(Query, Bindings, _), 1005 ( current_prolog_flag(toplevel_mode, recursive) 1006 -> !, 1007 '$switch_toplevel_mode'(recursive), 1008 '$query_loop'(BreakLev) 1009 ; fail 1010 ) 1011 ). 1012 1013break_level(BreakLev) :- 1014 ( current_prolog_flag(break_level, BreakLev) 1015 -> true 1016 ; BreakLev = -1 1017 ). 1018 1019read_expanded_query(BreakLev, ExpandedQuery, ExpandedBindings) :- 1020 '$current_typein_module'(TypeIn), 1021 ( stream_property(user_input, tty(true)) 1022 -> '$system_prompt'(TypeIn, BreakLev, Prompt), 1023 prompt(Old, '| ') 1024 ; Prompt = '', 1025 prompt(Old, '') 1026 ), 1027 trim_stacks, 1028 trim_heap, 1029 repeat, 1030 read_query(Prompt, Query, Bindings), 1031 prompt(_, Old), 1032 catch(call_expand_query(Query, ExpandedQuery, 1033 Bindings, ExpandedBindings), 1034 Error, 1035 (print_message(error, Error), fail)), 1036 !.
1045:- if(current_prolog_flag(emscripten, true)). 1046read_query(_Prompt, Goal, Bindings) :- 1047 '$can_yield', 1048 !, 1049 await(goal, GoalString), 1050 term_string(Goal, GoalString, [variable_names(Bindings)]). 1051:- endif. 1052read_query(Prompt, Goal, Bindings) :- 1053 current_prolog_flag(history, N), 1054 integer(N), N > 0, 1055 !, 1056 read_term_with_history( 1057 Goal, 1058 [ show(h), 1059 help('!h'), 1060 no_save([trace, end_of_file]), 1061 prompt(Prompt), 1062 variable_names(Bindings) 1063 ]). 1064read_query(Prompt, Goal, Bindings) :- 1065 remove_history_prompt(Prompt, Prompt1), 1066 repeat, % over syntax errors 1067 prompt1(Prompt1), 1068 read_query_line(user_input, Line), 1069 '$save_history_line'(Line), % save raw line (edit syntax errors) 1070 '$current_typein_module'(TypeIn), 1071 catch(read_term_from_atom(Line, Goal, 1072 [ variable_names(Bindings), 1073 module(TypeIn) 1074 ]), E, 1075 ( print_message(error, E), 1076 fail 1077 )), 1078 !, 1079 '$save_history_event'(Line). % save event (no syntax errors)
1083read_query_line(Input, Line) :- 1084 stream_property(Input, error(true)), 1085 !, 1086 Line = end_of_file. 1087read_query_line(Input, Line) :- 1088 catch(read_term_as_atom(Input, Line), Error, true), 1089 save_debug_after_read, 1090 ( var(Error) 1091 -> true 1092 ; catch(print_message(error, Error), _, true), 1093 ( Error = error(syntax_error(_),_) 1094 -> fail 1095 ; throw(Error) 1096 ) 1097 ).
1104read_term_as_atom(In, Line) :-
1105 '$raw_read'(In, Line),
1106 ( Line == end_of_file
1107 -> true
1108 ; skip_to_nl(In)
1109 ).
1116skip_to_nl(In) :- 1117 repeat, 1118 peek_char(In, C), 1119 ( C == '%' 1120 -> skip(In, '\n') 1121 ; char_type(C, space) 1122 -> get_char(In, _), 1123 C == '\n' 1124 ; true 1125 ), 1126 !. 1127 1128remove_history_prompt('', '') :- !. 1129remove_history_prompt(Prompt0, Prompt) :- 1130 atom_chars(Prompt0, Chars0), 1131 clean_history_prompt_chars(Chars0, Chars1), 1132 delete_leading_blanks(Chars1, Chars), 1133 atom_chars(Prompt, Chars). 1134 1135clean_history_prompt_chars([], []). 1136clean_history_prompt_chars(['~', !|T], T) :- !. 1137clean_history_prompt_chars([H|T0], [H|T]) :- 1138 clean_history_prompt_chars(T0, T). 1139 1140delete_leading_blanks([' '|T0], T) :- 1141 !, 1142 delete_leading_blanks(T0, T). 1143delete_leading_blanks(L, L).
1152set_default_history :- 1153 current_prolog_flag(history, _), 1154 !. 1155set_default_history :- 1156 ( ( \+ current_prolog_flag(readline, false) 1157 ; current_prolog_flag(emacs_inferior_process, true) 1158 ) 1159 -> create_prolog_flag(history, 0, []) 1160 ; create_prolog_flag(history, 25, []) 1161 ). 1162 1163 1164 /******************************* 1165 * TOPLEVEL DEBUG * 1166 *******************************/
thread_signal(main, gdebug)
1181save_debug_after_read :- 1182 current_prolog_flag(debug, true), 1183 !, 1184 save_debug. 1185save_debug_after_read. 1186 1187save_debug :- 1188 ( tracing, 1189 notrace 1190 -> Tracing = true 1191 ; Tracing = false 1192 ), 1193 current_prolog_flag(debug, Debugging), 1194 set_prolog_flag(debug, false), 1195 create_prolog_flag(query_debug_settings, 1196 debug(Debugging, Tracing), []). 1197 1198restore_debug :- 1199 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)), 1200 set_prolog_flag(debug, Debugging), 1201 ( Tracing == true 1202 -> trace 1203 ; true 1204 ). 1205 1206:- initialization 1207 create_prolog_flag(query_debug_settings, debug(false, false), []). 1208 1209 1210 /******************************** 1211 * PROMPTING * 1212 ********************************/ 1213 1214'$system_prompt'(Module, BrekLev, Prompt) :- 1215 current_prolog_flag(toplevel_prompt, PAtom), 1216 atom_codes(PAtom, P0), 1217 ( Module \== user 1218 -> '$substitute'('~m', [Module, ': '], P0, P1) 1219 ; '$substitute'('~m', [], P0, P1) 1220 ), 1221 ( BrekLev > 0 1222 -> '$substitute'('~l', ['[', BrekLev, '] '], P1, P2) 1223 ; '$substitute'('~l', [], P1, P2) 1224 ), 1225 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)), 1226 ( Tracing == true 1227 -> '$substitute'('~d', ['[trace] '], P2, P3) 1228 ; Debugging == true 1229 -> '$substitute'('~d', ['[debug] '], P2, P3) 1230 ; '$substitute'('~d', [], P2, P3) 1231 ), 1232 atom_chars(Prompt, P3). 1233 1234'$substitute'(From, T, Old, New) :- 1235 atom_codes(From, FromCodes), 1236 phrase(subst_chars(T), T0), 1237 '$append'(Pre, S0, Old), 1238 '$append'(FromCodes, Post, S0) -> 1239 '$append'(Pre, T0, S1), 1240 '$append'(S1, Post, New), 1241 !. 1242'$substitute'(_, _, Old, Old). 1243 1244subst_chars([]) --> 1245 []. 1246subst_chars([H|T]) --> 1247 { atomic(H), 1248 !, 1249 atom_codes(H, Codes) 1250 }, 1251 , 1252 subst_chars(T). 1253subst_chars([H|T]) --> 1254 , 1255 subst_chars(T). 1256 1257 1258 /******************************** 1259 * EXECUTION * 1260 ********************************/
1266'$execute_query'(Var, _, true) :- 1267 var(Var), 1268 !, 1269 print_message(informational, var_query(Var)). 1270'$execute_query'(Goal, Bindings, Truth) :- 1271 '$current_typein_module'(TypeIn), 1272 '$dwim_correct_goal'(TypeIn:Goal, Bindings, Corrected), 1273 !, 1274 setup_call_cleanup( 1275 '$set_source_module'(M0, TypeIn), 1276 expand_goal(Corrected, Expanded), 1277 '$set_source_module'(M0)), 1278 print_message(silent, toplevel_goal(Expanded, Bindings)), 1279 '$execute_goal2'(Expanded, Bindings, Truth). 1280'$execute_query'(_, _, false) :- 1281 notrace, 1282 print_message(query, query(no)). 1283 1284'$execute_goal2'(Goal, Bindings, true) :- 1285 restore_debug, 1286 '$current_typein_module'(TypeIn), 1287 residue_vars(TypeIn:Goal, Vars, TypeIn:Delays, Chp), 1288 deterministic(Det), 1289 ( save_debug 1290 ; restore_debug, fail 1291 ), 1292 flush_output(user_output), 1293 ( Det == true 1294 -> DetOrChp = true 1295 ; DetOrChp = Chp 1296 ), 1297 call_expand_answer(Goal, Bindings, NewBindings), 1298 ( \+ \+ write_bindings(NewBindings, Vars, Delays, DetOrChp) 1299 -> ! 1300 ). 1301'$execute_goal2'(_, _, false) :- 1302 save_debug, 1303 print_message(query, query(no)). 1304 1305residue_vars(Goal, Vars, Delays, Chp) :- 1306 current_prolog_flag(toplevel_residue_vars, true), 1307 !, 1308 '$wfs_call'(call_residue_vars(stop_backtrace(Goal, Chp), Vars), Delays). 1309residue_vars(Goal, [], Delays, Chp) :- 1310 '$wfs_call'(stop_backtrace(Goal, Chp), Delays). 1311 1312stop_backtrace(Goal, Chp) :- 1313 toplevel_call(Goal), 1314 prolog_current_choice(Chp). 1315 1316toplevel_call(Goal) :- 1317 call(Goal), 1318 no_lco. 1319 1320no_lco.
groundness
gives the classical behaviour,
determinism
is considered more adequate and informative.
Succeeds if the user accepts the answer and fails otherwise.
1336write_bindings(Bindings, ResidueVars, Delays, DetOrChp) :- 1337 '$current_typein_module'(TypeIn), 1338 translate_bindings(Bindings, Bindings1, ResidueVars, TypeIn:Residuals), 1339 omit_qualifier(Delays, TypeIn, Delays1), 1340 name_vars(Bindings1, t(Residuals, Delays1)), 1341 write_bindings2(Bindings1, Residuals, Delays1, DetOrChp). 1342 1343write_bindings2([], Residuals, Delays, _) :- 1344 current_prolog_flag(prompt_alternatives_on, groundness), 1345 !, 1346 print_message(query, query(yes(Delays, Residuals))). 1347write_bindings2(Bindings, Residuals, Delays, true) :- 1348 current_prolog_flag(prompt_alternatives_on, determinism), 1349 !, 1350 print_message(query, query(yes(Bindings, Delays, Residuals))). 1351write_bindings2(Bindings, Residuals, Delays, Chp) :- 1352 repeat, 1353 print_message(query, query(more(Bindings, Delays, Residuals))), 1354 get_respons(Action, Chp), 1355 ( Action == redo 1356 -> !, fail 1357 ; Action == show_again 1358 -> fail 1359 ; !, 1360 print_message(query, query(done)) 1361 ).
_[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/2 is a no-op.
Variables are named by unifying them to '$VAR'(Name)
1377name_vars(Bindings, Term) :- 1378 current_prolog_flag(toplevel_name_variables, true), 1379 !, 1380 '$term_multitons'(t(Bindings,Term), Vars), 1381 name_vars_(Vars, Bindings, 0), 1382 term_variables(t(Bindings,Term), SVars), 1383 anon_vars(SVars). 1384name_vars(_Bindings, _Term). 1385 1386name_vars_([], _, _). 1387name_vars_([H|T], Bindings, N) :- 1388 name_var(Bindings, Name, N, N1), 1389 H = '$VAR'(Name), 1390 name_vars_(T, Bindings, N1). 1391 1392anon_vars([]). 1393anon_vars(['$VAR'('_')|T]) :- 1394 anon_vars(T). 1395 1396name_var(Bindings, Name, N0, N) :- 1397 between(N0, infinite, N1), 1398 I is N1//26, 1399 J is 0'A + N1 mod 26, 1400 ( I == 0 1401 -> format(atom(Name), '_~c', [J]) 1402 ; format(atom(Name), '_~c~d', [J, I]) 1403 ), 1404 ( current_prolog_flag(toplevel_print_anon, false) 1405 -> true 1406 ; \+ is_bound(Bindings, Name) 1407 ), 1408 !, 1409 N is N1+1. 1410 1411is_bound([Vars=_|T], Name) :- 1412 ( in_vars(Vars, Name) 1413 -> true 1414 ; is_bound(T, Name) 1415 ). 1416 1417in_vars(Name, Name) :- !. 1418in_vars(Names, Name) :- 1419 '$member'(Name, Names).
1426:- multifile 1427 residual_goal_collector/1. 1428 1429:- meta_predicate 1430 residual_goals( ). 1431 1432residual_goals(NonTerminal) :- 1433 throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)). 1434 1435systemterm_expansion((:- residual_goals(NonTerminal)), 1436 '$toplevel':residual_goal_collector(M2:Head)) :- 1437 \+ current_prolog_flag(xref, true), 1438 prolog_load_context(module, M), 1439 strip_module(M:NonTerminal, M2, Head), 1440 '$must_be'(callable, Head).
1447:- public prolog:residual_goals//0. 1448 1449prolog:residual_goals --> 1450 { findall(NT, residual_goal_collector(NT), NTL) }, 1451 collect_residual_goals(NTL). 1452 1453collect_residual_goals([]) --> []. 1454collect_residual_goals([H|T]) --> 1455 ( call(H) -> [] ; [] ), 1456 collect_residual_goals(T).
1481:- public 1482 prolog:translate_bindings/5. 1483:- meta_predicate 1484 prolog:translate_bindings( , , , , ). 1485 1486prologtranslate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals) :- 1487 translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals), 1488 name_vars(Bindings, t(ResVars, ResGoals, Residuals)). 1489 1490% should not be required. 1491prologname_vars(Bindings, Term) :- name_vars(Bindings, Term). 1492 1493translate_bindings(Bindings0, Bindings, ResidueVars, Residuals) :- 1494 prolog:residual_goals(ResidueGoals, []), 1495 translate_bindings(Bindings0, Bindings, ResidueVars, ResidueGoals, 1496 Residuals). 1497 1498translate_bindings(Bindings0, Bindings, [], [], _:[]-[]) :- 1499 term_attvars(Bindings0, []), 1500 !, 1501 join_same_bindings(Bindings0, Bindings1), 1502 factorize_bindings(Bindings1, Bindings2), 1503 bind_vars(Bindings2, Bindings3), 1504 filter_bindings(Bindings3, Bindings). 1505translate_bindings(Bindings0, Bindings, ResidueVars, ResGoals0, 1506 TypeIn:Residuals-HiddenResiduals) :- 1507 project_constraints(Bindings0, ResidueVars), 1508 hidden_residuals(ResidueVars, Bindings0, HiddenResiduals0), 1509 omit_qualifiers(HiddenResiduals0, TypeIn, HiddenResiduals), 1510 copy_term(Bindings0+ResGoals0, Bindings1+ResGoals1, Residuals0), 1511 '$append'(ResGoals1, Residuals0, Residuals1), 1512 omit_qualifiers(Residuals1, TypeIn, Residuals), 1513 join_same_bindings(Bindings1, Bindings2), 1514 factorize_bindings(Bindings2, Bindings3), 1515 bind_vars(Bindings3, Bindings4), 1516 filter_bindings(Bindings4, Bindings). 1517 ResidueVars, Bindings, Goal) (:- 1519 term_attvars(ResidueVars, Remaining), 1520 term_attvars(Bindings, QueryVars), 1521 subtract_vars(Remaining, QueryVars, HiddenVars), 1522 copy_term(HiddenVars, _, Goal). 1523 1524subtract_vars(All, Subtract, Remaining) :- 1525 sort(All, AllSorted), 1526 sort(Subtract, SubtractSorted), 1527 ord_subtract(AllSorted, SubtractSorted, Remaining). 1528 1529ord_subtract([], _Not, []). 1530ord_subtract([H1|T1], L2, Diff) :- 1531 diff21(L2, H1, T1, Diff). 1532 1533diff21([], H1, T1, [H1|T1]). 1534diff21([H2|T2], H1, T1, Diff) :- 1535 compare(Order, H1, H2), 1536 diff3(Order, H1, T1, H2, T2, Diff). 1537 1538diff12([], _H2, _T2, []). 1539diff12([H1|T1], H2, T2, Diff) :- 1540 compare(Order, H1, H2), 1541 diff3(Order, H1, T1, H2, T2, Diff). 1542 1543diff3(<, H1, T1, H2, T2, [H1|Diff]) :- 1544 diff12(T1, H2, T2, Diff). 1545diff3(=, _H1, T1, _H2, T2, Diff) :- 1546 ord_subtract(T1, T2, Diff). 1547diff3(>, H1, T1, _H2, T2, Diff) :- 1548 diff21(T2, H1, T1, Diff).
toplevel_residue_vars
is set to project
.1556project_constraints(Bindings, ResidueVars) :- 1557 !, 1558 term_attvars(Bindings, AttVars), 1559 phrase(attribute_modules(AttVars), Modules0), 1560 sort(Modules0, Modules), 1561 term_variables(Bindings, QueryVars), 1562 project_attributes(Modules, QueryVars, ResidueVars). 1563project_constraints(_, _). 1564 1565project_attributes([], _, _). 1566project_attributes([M|T], QueryVars, ResidueVars) :- 1567 ( current_predicate(M:project_attributes/2), 1568 catch(M:project_attributes(QueryVars, ResidueVars), E, 1569 print_message(error, E)) 1570 -> true 1571 ; true 1572 ), 1573 project_attributes(T, QueryVars, ResidueVars). 1574 1575attribute_modules([]) --> []. 1576attribute_modules([H|T]) --> 1577 { get_attrs(H, Attrs) }, 1578 attrs_modules(Attrs), 1579 attribute_modules(T). 1580 1581attrs_modules([]) --> []. 1582attrs_modules(att(Module, _, More)) --> 1583 [Module], 1584 attrs_modules(More).
1595join_same_bindings([], []). 1596join_same_bindings([Name=V0|T0], [[Name|Names]=V|T]) :- 1597 take_same_bindings(T0, V0, V, Names, T1), 1598 join_same_bindings(T1, T). 1599 1600take_same_bindings([], Val, Val, [], []). 1601take_same_bindings([Name=V1|T0], V0, V, [Name|Names], T) :- 1602 V0 == V1, 1603 !, 1604 take_same_bindings(T0, V1, V, Names, T). 1605take_same_bindings([Pair|T0], V0, V, Names, [Pair|T]) :- 1606 take_same_bindings(T0, V0, V, Names, T).
1615omit_qualifiers([], _, []). 1616omit_qualifiers([Goal0|Goals0], TypeIn, [Goal|Goals]) :- 1617 omit_qualifier(Goal0, TypeIn, Goal), 1618 omit_qualifiers(Goals0, TypeIn, Goals). 1619 1620omit_qualifier(M:G0, TypeIn, G) :- 1621 M == TypeIn, 1622 !, 1623 omit_meta_qualifiers(G0, TypeIn, G). 1624omit_qualifier(M:G0, TypeIn, G) :- 1625 predicate_property(TypeIn:G0, imported_from(M)), 1626 \+ predicate_property(G0, transparent), 1627 !, 1628 G0 = G. 1629omit_qualifier(_:G0, _, G) :- 1630 predicate_property(G0, built_in), 1631 \+ predicate_property(G0, transparent), 1632 !, 1633 G0 = G. 1634omit_qualifier(M:G0, _, M:G) :- 1635 atom(M), 1636 !, 1637 omit_meta_qualifiers(G0, M, G). 1638omit_qualifier(G0, TypeIn, G) :- 1639 omit_meta_qualifiers(G0, TypeIn, G). 1640 1641omit_meta_qualifiers(V, _, V) :- 1642 var(V), 1643 !. 1644omit_meta_qualifiers((QA,QB), TypeIn, (A,B)) :- 1645 !, 1646 omit_qualifier(QA, TypeIn, A), 1647 omit_qualifier(QB, TypeIn, B). 1648omit_meta_qualifiers(tnot(QA), TypeIn, tnot(A)) :- 1649 !, 1650 omit_qualifier(QA, TypeIn, A). 1651omit_meta_qualifiers(freeze(V, QGoal), TypeIn, freeze(V, Goal)) :- 1652 callable(QGoal), 1653 !, 1654 omit_qualifier(QGoal, TypeIn, Goal). 1655omit_meta_qualifiers(when(Cond, QGoal), TypeIn, when(Cond, Goal)) :- 1656 callable(QGoal), 1657 !, 1658 omit_qualifier(QGoal, TypeIn, Goal). 1659omit_meta_qualifiers(G, _, G).
1668bind_vars(Bindings0, Bindings) :- 1669 bind_query_vars(Bindings0, Bindings, SNames), 1670 bind_skel_vars(Bindings, Bindings, SNames, 1, _). 1671 1672bind_query_vars([], [], []). 1673bind_query_vars([binding(Names,Var,[Var2=Cycle])|T0], 1674 [binding(Names,Cycle,[])|T], [Name|SNames]) :- 1675 Var == Var2, % also implies var(Var) 1676 !, 1677 '$last'(Names, Name), 1678 Var = '$VAR'(Name), 1679 bind_query_vars(T0, T, SNames). 1680bind_query_vars([B|T0], [B|T], AllNames) :- 1681 B = binding(Names,Var,Skel), 1682 bind_query_vars(T0, T, SNames), 1683 ( var(Var), \+ attvar(Var), Skel == [] 1684 -> AllNames = [Name|SNames], 1685 '$last'(Names, Name), 1686 Var = '$VAR'(Name) 1687 ; AllNames = SNames 1688 ). 1689 1690 1691 1692bind_skel_vars([], _, _, N, N). 1693bind_skel_vars([binding(_,_,Skel)|T], Bindings, SNames, N0, N) :- 1694 bind_one_skel_vars(Skel, Bindings, SNames, N0, N1), 1695 bind_skel_vars(T, Bindings, SNames, N1, N).
1714bind_one_skel_vars([], _, _, N, N). 1715bind_one_skel_vars([Var=Value|T], Bindings, Names, N0, N) :- 1716 ( var(Var) 1717 -> ( '$member'(binding(Names, VVal, []), Bindings), 1718 same_term(Value, VVal) 1719 -> '$last'(Names, VName), 1720 Var = '$VAR'(VName), 1721 N2 = N0 1722 ; between(N0, infinite, N1), 1723 atom_concat('_S', N1, Name), 1724 \+ memberchk(Name, Names), 1725 !, 1726 Var = '$VAR'(Name), 1727 N2 is N1 + 1 1728 ) 1729 ; N2 = N0 1730 ), 1731 bind_one_skel_vars(T, Bindings, Names, N2, N).
1738factorize_bindings([], []). 1739factorize_bindings([Name=Value|T0], [binding(Name, Skel, Subst)|T]) :- 1740 '$factorize_term'(Value, Skel, Subst0), 1741 ( current_prolog_flag(toplevel_print_factorized, true) 1742 -> Subst = Subst0 1743 ; only_cycles(Subst0, Subst) 1744 ), 1745 factorize_bindings(T0, T). 1746 1747 1748only_cycles([], []). 1749only_cycles([B|T0], List) :- 1750 ( B = (Var=Value), 1751 Var = Value, 1752 acyclic_term(Var) 1753 -> only_cycles(T0, List) 1754 ; List = [B|T], 1755 only_cycles(T0, T) 1756 ).
1765filter_bindings([], []). 1766filter_bindings([H0|T0], T) :- 1767 hide_vars(H0, H), 1768 ( ( arg(1, H, []) 1769 ; self_bounded(H) 1770 ) 1771 -> filter_bindings(T0, T) 1772 ; T = [H|T1], 1773 filter_bindings(T0, T1) 1774 ). 1775 1776hide_vars(binding(Names0, Skel, Subst), binding(Names, Skel, Subst)) :- 1777 hide_names(Names0, Skel, Subst, Names). 1778 1779hide_names([], _, _, []). 1780hide_names([Name|T0], Skel, Subst, T) :- 1781 ( sub_atom(Name, 0, _, _, '_'), 1782 current_prolog_flag(toplevel_print_anon, false), 1783 sub_atom(Name, 1, 1, _, Next), 1784 char_type(Next, prolog_var_start) 1785 -> true 1786 ; Subst == [], 1787 Skel == '$VAR'(Name) 1788 ), 1789 !, 1790 hide_names(T0, Skel, Subst, T). 1791hide_names([Name|T0], Skel, Subst, [Name|T]) :- 1792 hide_names(T0, Skel, Subst, T). 1793 1794self_bounded(binding([Name], Value, [])) :- 1795 Value == '$VAR'(Name).
1801:- if(current_prolog_flag(emscripten, true)). 1802get_respons(Action, _Chp) :- 1803 '$can_yield', 1804 !, 1805 await(more, ActionS), 1806 atom_string(Action, ActionS). 1807:- endif. 1808get_respons(Action, Chp) :- 1809 repeat, 1810 flush_output(user_output), 1811 get_single_char(Char), 1812 answer_respons(Char, Chp, Action), 1813 ( Action == again 1814 -> print_message(query, query(action)), 1815 fail 1816 ; ! 1817 ). 1818 1819answer_respons(Char, _, again) :- 1820 '$in_reply'(Char, '?h'), 1821 !, 1822 print_message(help, query(help)). 1823answer_respons(Char, _, redo) :- 1824 '$in_reply'(Char, ';nrNR \t'), 1825 !, 1826 print_message(query, if_tty([ansi(bold, ';', [])])). 1827answer_respons(Char, _, redo) :- 1828 '$in_reply'(Char, 'tT'), 1829 !, 1830 trace, 1831 save_debug, 1832 print_message(query, if_tty([ansi(bold, '; [trace]', [])])). 1833answer_respons(Char, _, continue) :- 1834 '$in_reply'(Char, 'ca\n\ryY.'), 1835 !, 1836 print_message(query, if_tty([ansi(bold, '.', [])])). 1837answer_respons(0'b, _, show_again) :- 1838 !, 1839 break. 1840answer_respons(0'*, Chp, show_again) :- 1841 !, 1842 print_last_chpoint(Chp). 1843answer_respons(Char, _, show_again) :- 1844 print_predicate(Char, Pred, Options), 1845 !, 1846 print_message(query, if_tty(['~w'-[Pred]])), 1847 set_prolog_flag(answer_write_options, Options). 1848answer_respons(-1, _, show_again) :- 1849 !, 1850 print_message(query, halt('EOF')), 1851 halt(0). 1852answer_respons(Char, _, again) :- 1853 print_message(query, no_action(Char)). 1854 1855print_predicate(0'w, [write], [ quoted(true), 1856 spacing(next_argument) 1857 ]). 1858print_predicate(0'p, [print], [ quoted(true), 1859 portray(true), 1860 max_depth(10), 1861 spacing(next_argument) 1862 ]). 1863 1864 1865print_last_chpoint(Chp) :- 1866 current_predicate(print_last_choice_point/0), 1867 !, 1868 print_last_chpoint_(Chp). 1869print_last_chpoint(Chp) :- 1870 use_module(library(prolog_stack), [print_last_choicepoint/2]), 1871 print_last_chpoint_(Chp). 1872 1873print_last_chpoint_(Chp) :- 1874 print_last_choicepoint(Chp, [message_level(information)]). 1875 1876 1877 /******************************* 1878 * EXPANSION * 1879 *******************************/ 1880 1881:- user:dynamic(expand_query/4). 1882:- user:multifile(expand_query/4). 1883 1884call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :- 1885 ( '$replace_toplevel_vars'(Goal, Expanded0, Bindings, ExpandedBindings0) 1886 -> true 1887 ; Expanded0 = Goal, ExpandedBindings0 = Bindings 1888 ), 1889 ( user:expand_query(Expanded0, Expanded, ExpandedBindings0, ExpandedBindings) 1890 -> true 1891 ; Expanded = Expanded0, ExpandedBindings = ExpandedBindings0 1892 ). 1893 1894 1895:- dynamic 1896 user:expand_answer/2, 1897 prolog:expand_answer/3. 1898:- multifile 1899 user:expand_answer/2, 1900 prolog:expand_answer/3. 1901 1902call_expand_answer(Goal, BindingsIn, BindingsOut) :- 1903 ( prolog:expand_answer(Goal, BindingsIn, BindingsOut) 1904 -> true 1905 ; user:expand_answer(BindingsIn, BindingsOut) 1906 -> true 1907 ; BindingsOut = BindingsIn 1908 ), 1909 '$save_toplevel_vars'(BindingsOut), 1910 !. 1911call_expand_answer(_, Bindings, Bindings)