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-2020, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module('$toplevel', 37 [ '$initialise'/0, % start Prolog 38 '$toplevel'/0, % Prolog top-level (re-entrant) 39 '$compile'/0, % `-c' toplevel 40 '$config'/0, % --dump-runtime-variables toplevel 41 initialize/0, % Run program initialization 42 version/0, % Write initial banner 43 version/1, % Add message to the banner 44 prolog/0, % user toplevel predicate 45 '$query_loop'/0, % toplevel predicate 46 '$execute_query'/3, % +Query, +Bindings, -Truth 47 residual_goals/1, % +Callable 48 (initialization)/1, % initialization goal (directive) 49 '$thread_init'/0, % initialise thread 50 (thread_initialization)/1 % thread initialization goal 51 ]). 52 53 54 /******************************* 55 * VERSION BANNER * 56 *******************************/ 57 58:- dynamic 59 prolog:version_msg/1.
66version :-
67 print_message(banner, welcome).
73:- multifile 74 system:term_expansion/2. 75 76systemterm_expansion((:- version(Message)), 77 prolog:version_msg(Message)). 78 79version(Message) :- 80 ( prolog:version_msg(Message) 81 -> true 82 ; assertz(prolog:version_msg(Message)) 83 ). 84 85 86 /******************************** 87 * INITIALISATION * 88 *********************************/ 89 90% note: loaded_init_file/2 is used by prolog_load_context/2 to 91% confirm we are loading a script. 92 93:- dynamic 94 loaded_init_file/2. % already loaded init files 95 96'$load_init_file'(none) :- !. 97'$load_init_file'(Base) :- 98 loaded_init_file(Base, _), 99 !. 100'$load_init_file'(InitFile) :- 101 exists_file(InitFile), 102 !, 103 ensure_loaded(user:InitFile). 104'$load_init_file'(Base) :- 105 absolute_file_name(user_app_config(Base), InitFile, 106 [ access(read), 107 file_errors(fail) 108 ]), 109 asserta(loaded_init_file(Base, InitFile)), 110 load_files(user:InitFile, 111 [ scope_settings(false) 112 ]). 113'$load_init_file'('init.pl') :- 114 ( current_prolog_flag(windows, true), 115 absolute_file_name(user_profile('swipl.ini'), InitFile, 116 [ access(read), 117 file_errors(fail) 118 ]) 119 ; expand_file_name('~/.swiplrc', [InitFile]), 120 exists_file(InitFile) 121 ), 122 !, 123 print_message(warning, backcomp(init_file_moved(InitFile))). 124'$load_init_file'(_). 125 126'$load_system_init_file' :- 127 loaded_init_file(system, _), 128 !. 129'$load_system_init_file' :- 130 '$cmd_option_val'(system_init_file, Base), 131 Base \== none, 132 current_prolog_flag(home, Home), 133 file_name_extension(Base, rc, Name), 134 atomic_list_concat([Home, '/', Name], File), 135 absolute_file_name(File, Path, 136 [ file_type(prolog), 137 access(read), 138 file_errors(fail) 139 ]), 140 asserta(loaded_init_file(system, Path)), 141 load_files(user:Path, 142 [ silent(true), 143 scope_settings(false) 144 ]), 145 !. 146'$load_system_init_file'. 147 148'$load_script_file' :- 149 loaded_init_file(script, _), 150 !. 151'$load_script_file' :- 152 '$cmd_option_val'(script_file, OsFiles), 153 load_script_files(OsFiles). 154 155load_script_files([]). 156load_script_files([OsFile|More]) :- 157 prolog_to_os_filename(File, OsFile), 158 ( absolute_file_name(File, Path, 159 [ file_type(prolog), 160 access(read), 161 file_errors(fail) 162 ]) 163 -> asserta(loaded_init_file(script, Path)), 164 load_files(user:Path, []), 165 load_files(More) 166 ; throw(error(existence_error(script_file, File), _)) 167 ). 168 169 170 /******************************* 171 * AT_INITIALISATION * 172 *******************************/ 173 174:- meta_predicate 175 initialization( ). 176 177:- '$iso'((initialization)/1).
186initialization(Goal) :- 187 Goal = _:G, 188 prolog:initialize_now(G, Use), 189 !, 190 print_message(warning, initialize_now(G, Use)), 191 initialization(Goal, now). 192initialization(Goal) :- 193 initialization(Goal, after_load). 194 195:- multifile 196 prolog:initialize_now/2, 197 prolog:message//1. 198 199prologinitialize_now(load_foreign_library(_), 200 'use :- use_foreign_library/1 instead'). 201prologinitialize_now(load_foreign_library(_,_), 202 'use :- use_foreign_library/2 instead'). 203 204prologmessage(initialize_now(Goal, Use)) --> 205 [ 'Initialization goal ~p will be executed'-[Goal],nl, 206 'immediately for backward compatibility reasons', nl, 207 '~w'-[Use] 208 ]. 209 210'$run_initialization' :- 211 '$run_initialization'(_, []), 212 '$thread_init'.
:- initialization(Goal, program).
. Stop
with an exception if a goal fails or raises an exception.219initialize :- 220 forall('$init_goal'(when(program), Goal, Ctx), 221 run_initialize(Goal, Ctx)). 222 223run_initialize(Goal, Ctx) :- 224 ( catch(Goal, E, true), 225 ( var(E) 226 -> true 227 ; throw(error(initialization_error(E, Goal, Ctx), _)) 228 ) 229 ; throw(error(initialization_error(failed, Goal, Ctx), _)) 230 ). 231 232 233 /******************************* 234 * THREAD INITIALIZATION * 235 *******************************/ 236 237:- meta_predicate 238 thread_initialization( ). 239:- dynamic 240 '$at_thread_initialization'/1.
246thread_initialization(Goal) :- 247 assert('$at_thread_initialization'(Goal)), 248 call(Goal), 249 !. 250 251'$thread_init' :- 252 ( '$at_thread_initialization'(Goal), 253 ( call(Goal) 254 -> fail 255 ; fail 256 ) 257 ; true 258 ). 259 260 261 /******************************* 262 * FILE SEARCH PATH (-p) * 263 *******************************/
269'$set_file_search_paths' :- 270 '$cmd_option_val'(search_paths, Paths), 271 ( '$member'(Path, Paths), 272 atom_chars(Path, Chars), 273 ( phrase('$search_path'(Name, Aliases), Chars) 274 -> '$reverse'(Aliases, Aliases1), 275 forall('$member'(Alias, Aliases1), 276 asserta(user:file_search_path(Name, Alias))) 277 ; print_message(error, commandline_arg_type(p, Path)) 278 ), 279 fail ; true 280 ). 281 282'$search_path'(Name, Aliases) --> 283 '$string'(NameChars), 284 [=], 285 !, 286 {atom_chars(Name, NameChars)}, 287 '$search_aliases'(Aliases). 288 289'$search_aliases'([Alias|More]) --> 290 '$string'(AliasChars), 291 path_sep, 292 !, 293 { '$make_alias'(AliasChars, Alias) }, 294 '$search_aliases'(More). 295'$search_aliases'([Alias]) --> 296 '$string'(AliasChars), 297 '$eos', 298 !, 299 { '$make_alias'(AliasChars, Alias) }. 300 301path_sep --> 302 { current_prolog_flag(windows, true) 303 }, 304 !, 305 [;]. 306path_sep --> 307 [:]. 308 309'$string'([]) --> []. 310'$string'([H|T]) --> [H], '$string'(T). 311 312'$eos'([], []). 313 314'$make_alias'(Chars, Alias) :- 315 catch(term_to_atom(Alias, Chars), _, fail), 316 ( atom(Alias) 317 ; functor(Alias, F, 1), 318 F \== / 319 ), 320 !. 321'$make_alias'(Chars, Alias) :- 322 atom_chars(Alias, Chars). 323 324 325 /******************************* 326 * LOADING ASSIOCIATED FILES * 327 *******************************/
argv
, extracting the leading script files.333argv_files(Files) :- 334 current_prolog_flag(argv, Argv), 335 no_option_files(Argv, Argv1, Files, ScriptArgs), 336 ( ( ScriptArgs == true 337 ; Argv1 == [] 338 ) 339 -> ( Argv1 \== Argv 340 -> set_prolog_flag(argv, Argv1) 341 ; true 342 ) 343 ; '$usage', 344 halt(1) 345 ). 346 347no_option_files([--|Argv], Argv, [], true) :- !. 348no_option_files([Opt|_], _, _, ScriptArgs) :- 349 ScriptArgs \== true, 350 sub_atom(Opt, 0, _, _, '-'), 351 !, 352 '$usage', 353 halt(1). 354no_option_files([OsFile|Argv0], Argv, [File|T], ScriptArgs) :- 355 file_name_extension(_, Ext, OsFile), 356 user:prolog_file_type(Ext, prolog), 357 !, 358 ScriptArgs = true, 359 prolog_to_os_filename(File, OsFile), 360 no_option_files(Argv0, Argv, T, ScriptArgs). 361no_option_files([OsScript|Argv], Argv, [Script], ScriptArgs) :- 362 ScriptArgs \== true, 363 !, 364 prolog_to_os_filename(Script, OsScript), 365 ( exists_file(Script) 366 -> true 367 ; '$existence_error'(file, Script) 368 ), 369 ScriptArgs = true. 370no_option_files(Argv, Argv, [], _). 371 372clean_argv :- 373 ( current_prolog_flag(argv, [--|Argv]) 374 -> set_prolog_flag(argv, Argv) 375 ; true 376 ).
385associated_files([]) :- 386 current_prolog_flag(saved_program_class, runtime), 387 !, 388 clean_argv. 389associated_files(Files) :- 390 '$set_prolog_file_extension', 391 argv_files(Files), 392 ( Files = [File|_] 393 -> absolute_file_name(File, AbsFile), 394 set_prolog_flag(associated_file, AbsFile), 395 set_working_directory(File), 396 set_window_title(Files) 397 ; true 398 ).
console_menu
,
which is set by swipl-win[.exe].408set_working_directory(File) :- 409 current_prolog_flag(console_menu, true), 410 access_file(File, read), 411 !, 412 file_directory_name(File, Dir), 413 working_directory(_, Dir). 414set_working_directory(_). 415 416set_window_title([File|More]) :- 417 current_predicate(system:window_title/2), 418 !, 419 ( More == [] 420 -> Extra = [] 421 ; Extra = ['...'] 422 ), 423 atomic_list_concat(['SWI-Prolog --', File | Extra], ' ', Title), 424 system:window_title(_, Title). 425set_window_title(_).
--pldoc[=port]
is given, load the PlDoc
system.433start_pldoc :- 434 '$cmd_option_val'(pldoc_server, Server), 435 ( Server == '' 436 -> call((doc_server(_), doc_browser)) 437 ; catch(atom_number(Server, Port), _, fail) 438 -> call(doc_server(Port)) 439 ; print_message(error, option_usage(pldoc)), 440 halt(1) 441 ). 442start_pldoc.
449load_associated_files(Files) :- 450 ( '$member'(File, Files), 451 load_files(user:File, [expand(false)]), 452 fail 453 ; true 454 ). 455 456hkey('HKEY_CURRENT_USER/Software/SWI/Prolog'). 457hkey('HKEY_LOCAL_MACHINE/Software/SWI/Prolog'). 458 459'$set_prolog_file_extension' :- 460 current_prolog_flag(windows, true), 461 hkey(Key), 462 catch(win_registry_get_value(Key, fileExtension, Ext0), 463 _, fail), 464 !, 465 ( atom_concat('.', Ext, Ext0) 466 -> true 467 ; Ext = Ext0 468 ), 469 ( user:prolog_file_type(Ext, prolog) 470 -> true 471 ; asserta(user:prolog_file_type(Ext, prolog)) 472 ). 473'$set_prolog_file_extension'. 474 475 476 /******************************** 477 * TOPLEVEL GOALS * 478 *********************************/
486'$initialise' :- 487 catch(initialise_prolog, E, initialise_error(E)). 488 489initialise_error('$aborted') :- !. 490initialise_error(E) :- 491 print_message(error, initialization_exception(E)), 492 fail. 493 494initialise_prolog :- 495 '$clean_history', 496 '$run_initialization', 497 '$load_system_init_file', 498 set_toplevel, 499 '$set_file_search_paths', 500 init_debug_flags, 501 start_pldoc, 502 opt_attach_packs, 503 '$cmd_option_val'(init_file, OsFile), 504 prolog_to_os_filename(File, OsFile), 505 '$load_init_file'(File), 506 catch(setup_colors, E, print_message(warning, E)), 507 '$load_script_file', 508 associated_files(Files), 509 load_associated_files(Files), 510 '$cmd_option_val'(goals, Goals), 511 ( Goals == [], 512 \+ '$init_goal'(when(_), _, _) 513 -> version % default interactive run 514 ; run_init_goals(Goals), 515 ( load_only 516 -> version 517 ; run_program_init, 518 run_main_init 519 ) 520 ). 521 522opt_attach_packs :- 523 current_prolog_flag(packs, true), 524 !, 525 attach_packs. 526opt_attach_packs. 527 528set_toplevel :- 529 '$cmd_option_val'(toplevel, TopLevelAtom), 530 catch(term_to_atom(TopLevel, TopLevelAtom), E, 531 (print_message(error, E), 532 halt(1))), 533 create_prolog_flag(toplevel_goal, TopLevel, [type(term)]). 534 535load_only :- 536 current_prolog_flag(os_argv, OSArgv), 537 memberchk('-l', OSArgv), 538 current_prolog_flag(argv, Argv), 539 \+ memberchk('-l', Argv).
546run_init_goals([]). 547run_init_goals([H|T]) :- 548 run_init_goal(H), 549 run_init_goals(T). 550 551run_init_goal(Text) :- 552 catch(term_to_atom(Goal, Text), E, 553 ( print_message(error, init_goal_syntax(E, Text)), 554 halt(2) 555 )), 556 run_init_goal(Goal, Text).
562run_program_init :- 563 forall('$init_goal'(when(program), Goal, Ctx), 564 run_init_goal(Goal, @(Goal,Ctx))). 565 566run_main_init :- 567 findall(Goal-Ctx, '$init_goal'(when(main), Goal, Ctx), Pairs), 568 '$last'(Pairs, Goal-Ctx), 569 !, 570 ( current_prolog_flag(toplevel_goal, default) 571 -> set_prolog_flag(toplevel_goal, halt) 572 ; true 573 ), 574 run_init_goal(Goal, @(Goal,Ctx)). 575run_main_init. 576 577run_init_goal(Goal, Ctx) :- 578 ( catch_with_backtrace(user:Goal, E, true) 579 -> ( var(E) 580 -> true 581 ; print_message(error, init_goal_failed(E, Ctx)), 582 halt(2) 583 ) 584 ; ( current_prolog_flag(verbose, silent) 585 -> Level = silent 586 ; Level = error 587 ), 588 print_message(Level, init_goal_failed(failed, Ctx)), 589 halt(1) 590 ).
597init_debug_flags :-
598 once(print_predicate(_, [print], PrintOptions)),
599 Keep = [keep(true)],
600 create_prolog_flag(answer_write_options, PrintOptions, Keep),
601 create_prolog_flag(prompt_alternatives_on, determinism, Keep),
602 create_prolog_flag(toplevel_extra_white_line, true, Keep),
603 create_prolog_flag(toplevel_print_factorized, false, Keep),
604 create_prolog_flag(print_write_options,
605 [ portray(true), quoted(true), numbervars(true) ],
606 Keep),
607 create_prolog_flag(toplevel_residue_vars, false, Keep),
608 create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
609 '$set_debugger_write_options'(print).
615setup_backtrace :-
616 ( \+ current_prolog_flag(backtrace, false),
617 load_setup_file(library(prolog_stack))
618 -> true
619 ; true
620 ).
626setup_colors :-
627 ( \+ current_prolog_flag(color_term, false),
628 stream_property(user_input, tty(true)),
629 stream_property(user_error, tty(true)),
630 stream_property(user_output, tty(true)),
631 \+ getenv('TERM', dumb),
632 load_setup_file(user:library(ansi_term))
633 -> true
634 ; true
635 ).
641setup_history :-
642 ( \+ current_prolog_flag(save_history, false),
643 stream_property(user_input, tty(true)),
644 \+ current_prolog_flag(readline, false),
645 load_setup_file(library(prolog_history))
646 -> prolog_history(enable)
647 ; true
648 ),
649 set_default_history,
650 '$load_history'.
656setup_readline :- 657 ( current_prolog_flag(readline, swipl_win) 658 -> true 659 ; stream_property(user_input, tty(true)), 660 current_prolog_flag(tty_control, true), 661 \+ getenv('TERM', dumb), 662 ( current_prolog_flag(readline, ReadLine) 663 -> true 664 ; ReadLine = true 665 ), 666 readline_library(ReadLine, Library), 667 load_setup_file(library(Library)) 668 -> set_prolog_flag(readline, Library) 669 ; set_prolog_flag(readline, false) 670 ). 671 672readline_library(true, Library) :- 673 !, 674 preferred_readline(Library). 675readline_library(false, _) :- 676 !, 677 fail. 678readline_library(Library, Library). 679 680preferred_readline(editline). 681preferred_readline(readline).
687load_setup_file(File) :- 688 catch(load_files(File, 689 [ silent(true), 690 if(not_loaded) 691 ]), _, fail). 692 693 694:- '$hide'('$toplevel'/0). % avoid in the GUI stacktrace
700'$toplevel' :-
701 '$runtoplevel',
702 print_message(informational, halt).
default
and prolog
both
start the interactive toplevel, where prolog
implies the user gave
-t prolog
.
712'$runtoplevel' :- 713 current_prolog_flag(toplevel_goal, TopLevel0), 714 toplevel_goal(TopLevel0, TopLevel), 715 user:TopLevel. 716 717:- dynamic setup_done/0. 718:- volatile setup_done/0. 719 720toplevel_goal(default, '$query_loop') :- 721 !, 722 setup_interactive. 723toplevel_goal(prolog, '$query_loop') :- 724 !, 725 setup_interactive. 726toplevel_goal(Goal, Goal). 727 728setup_interactive :- 729 setup_done, 730 !. 731setup_interactive :- 732 asserta(setup_done), 733 catch(setup_backtrace, E, print_message(warning, E)), 734 catch(setup_readline, E, print_message(warning, E)), 735 catch(setup_history, E, print_message(warning, E)).
741'$compile' :- 742 ( catch('$compile_', E, (print_message(error, E), halt(1))) 743 -> true 744 ; print_message(error, error(goal_failed('$compile'), _)), 745 halt(1) 746 ). 747 748'$compile_' :- 749 '$load_system_init_file', 750 '$set_file_search_paths', 751 init_debug_flags, 752 '$run_initialization', 753 opt_attach_packs, 754 use_module(library(qsave)), 755 qsave:qsave_toplevel.
761'$config' :- 762 '$load_system_init_file', 763 '$set_file_search_paths', 764 init_debug_flags, 765 '$run_initialization', 766 load_files(library(prolog_config)), 767 ( catch(prolog_dump_runtime_variables, E, 768 (print_message(error, E), halt(1))) 769 -> true 770 ; print_message(error, error(goal_failed(prolog_dump_runtime_variables),_)) 771 ). 772 773 774 /******************************** 775 * USER INTERACTIVE LOOP * 776 *********************************/
784prolog :- 785 break. 786 787:- create_prolog_flag(toplevel_mode, backtracking, []).
query_loop()
. This ensures that unhandled
exceptions are really unhandled (in Prolog).796'$query_loop' :- 797 current_prolog_flag(toplevel_mode, recursive), 798 !, 799 break_level(Level), 800 read_expanded_query(Level, Query, Bindings), 801 ( Query == end_of_file 802 -> print_message(query, query(eof)) 803 ; '$call_no_catch'('$execute_query'(Query, Bindings, _)), 804 ( current_prolog_flag(toplevel_mode, recursive) 805 -> '$query_loop' 806 ; '$switch_toplevel_mode'(backtracking), 807 '$query_loop' % Maybe throw('$switch_toplevel_mode')? 808 ) 809 ). 810'$query_loop' :- 811 break_level(BreakLev), 812 repeat, 813 read_expanded_query(BreakLev, Query, Bindings), 814 ( Query == end_of_file 815 -> !, print_message(query, query(eof)) 816 ; '$execute_query'(Query, Bindings, _), 817 ( current_prolog_flag(toplevel_mode, recursive) 818 -> !, 819 '$switch_toplevel_mode'(recursive), 820 '$query_loop' 821 ; fail 822 ) 823 ). 824 825break_level(BreakLev) :- 826 ( current_prolog_flag(break_level, BreakLev) 827 -> true 828 ; BreakLev = -1 829 ). 830 831read_expanded_query(BreakLev, ExpandedQuery, ExpandedBindings) :- 832 '$current_typein_module'(TypeIn), 833 ( stream_property(user_input, tty(true)) 834 -> '$system_prompt'(TypeIn, BreakLev, Prompt), 835 prompt(Old, '| ') 836 ; Prompt = '', 837 prompt(Old, '') 838 ), 839 trim_stacks, 840 repeat, 841 read_query(Prompt, Query, Bindings), 842 prompt(_, Old), 843 catch(call_expand_query(Query, ExpandedQuery, 844 Bindings, ExpandedBindings), 845 Error, 846 (print_message(error, Error), fail)), 847 !.
856read_query(Prompt, Goal, Bindings) :- 857 current_prolog_flag(history, N), 858 integer(N), N > 0, 859 !, 860 read_term_with_history( 861 Goal, 862 [ show(h), 863 help('!h'), 864 no_save([trace, end_of_file]), 865 prompt(Prompt), 866 variable_names(Bindings) 867 ]). 868read_query(Prompt, Goal, Bindings) :- 869 remove_history_prompt(Prompt, Prompt1), 870 repeat, % over syntax errors 871 prompt1(Prompt1), 872 read_query_line(user_input, Line), 873 '$save_history_line'(Line), % save raw line (edit syntax errors) 874 '$current_typein_module'(TypeIn), 875 catch(read_term_from_atom(Line, Goal, 876 [ variable_names(Bindings), 877 module(TypeIn) 878 ]), E, 879 ( print_message(error, E), 880 fail 881 )), 882 !, 883 '$save_history_event'(Line). % save event (no syntax errors)
887read_query_line(Input, Line) :-
888 catch(read_term_as_atom(Input, Line), Error, true),
889 save_debug_after_read,
890 ( var(Error)
891 -> true
892 ; Error = error(syntax_error(_),_)
893 -> print_message(error, Error),
894 fail
895 ; print_message(error, Error),
896 throw(Error)
897 ).
904read_term_as_atom(In, Line) :-
905 '$raw_read'(In, Line),
906 ( Line == end_of_file
907 -> true
908 ; skip_to_nl(In)
909 ).
916skip_to_nl(In) :- 917 repeat, 918 peek_char(In, C), 919 ( C == '%' 920 -> skip(In, '\n') 921 ; char_type(C, space) 922 -> get_char(In, _), 923 C == '\n' 924 ; true 925 ), 926 !. 927 928remove_history_prompt('', '') :- !. 929remove_history_prompt(Prompt0, Prompt) :- 930 atom_chars(Prompt0, Chars0), 931 clean_history_prompt_chars(Chars0, Chars1), 932 delete_leading_blanks(Chars1, Chars), 933 atom_chars(Prompt, Chars). 934 935clean_history_prompt_chars([], []). 936clean_history_prompt_chars(['~', !|T], T) :- !. 937clean_history_prompt_chars([H|T0], [H|T]) :- 938 clean_history_prompt_chars(T0, T). 939 940delete_leading_blanks([' '|T0], T) :- 941 !, 942 delete_leading_blanks(T0, T). 943delete_leading_blanks(L, L).
952set_default_history :- 953 current_prolog_flag(history, _), 954 !. 955set_default_history :- 956 ( ( \+ current_prolog_flag(readline, false) 957 ; current_prolog_flag(emacs_inferior_process, true) 958 ) 959 -> create_prolog_flag(history, 0, []) 960 ; create_prolog_flag(history, 25, []) 961 ). 962 963 964 /******************************* 965 * TOPLEVEL DEBUG * 966 *******************************/
thread_signal(main, gdebug)
981save_debug_after_read :- 982 current_prolog_flag(debug, true), 983 !, 984 save_debug. 985save_debug_after_read. 986 987save_debug :- 988 ( tracing, 989 notrace 990 -> Tracing = true 991 ; Tracing = false 992 ), 993 current_prolog_flag(debug, Debugging), 994 set_prolog_flag(debug, false), 995 create_prolog_flag(query_debug_settings, 996 debug(Debugging, Tracing), []). 997 998restore_debug :- 999 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)), 1000 set_prolog_flag(debug, Debugging), 1001 ( Tracing == true 1002 -> trace 1003 ; true 1004 ). 1005 1006:- initialization 1007 create_prolog_flag(query_debug_settings, debug(false, false), []). 1008 1009 1010 /******************************** 1011 * PROMPTING * 1012 ********************************/ 1013 1014'$system_prompt'(Module, BrekLev, Prompt) :- 1015 current_prolog_flag(toplevel_prompt, PAtom), 1016 atom_codes(PAtom, P0), 1017 ( Module \== user 1018 -> '$substitute'('~m', [Module, ': '], P0, P1) 1019 ; '$substitute'('~m', [], P0, P1) 1020 ), 1021 ( BrekLev > 0 1022 -> '$substitute'('~l', ['[', BrekLev, '] '], P1, P2) 1023 ; '$substitute'('~l', [], P1, P2) 1024 ), 1025 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)), 1026 ( Tracing == true 1027 -> '$substitute'('~d', ['[trace] '], P2, P3) 1028 ; Debugging == true 1029 -> '$substitute'('~d', ['[debug] '], P2, P3) 1030 ; '$substitute'('~d', [], P2, P3) 1031 ), 1032 atom_chars(Prompt, P3). 1033 1034'$substitute'(From, T, Old, New) :- 1035 atom_codes(From, FromCodes), 1036 phrase(subst_chars(T), T0), 1037 '$append'(Pre, S0, Old), 1038 '$append'(FromCodes, Post, S0) -> 1039 '$append'(Pre, T0, S1), 1040 '$append'(S1, Post, New), 1041 !. 1042'$substitute'(_, _, Old, Old). 1043 1044subst_chars([]) --> 1045 []. 1046subst_chars([H|T]) --> 1047 { atomic(H), 1048 !, 1049 atom_codes(H, Codes) 1050 }, 1051 , 1052 subst_chars(T). 1053subst_chars([H|T]) --> 1054 , 1055 subst_chars(T). 1056 1057 1058 /******************************** 1059 * EXECUTION * 1060 ********************************/
1066'$execute_query'(Var, _, true) :- 1067 var(Var), 1068 !, 1069 print_message(informational, var_query(Var)). 1070'$execute_query'(Goal, Bindings, Truth) :- 1071 '$current_typein_module'(TypeIn), 1072 '$dwim_correct_goal'(TypeIn:Goal, Bindings, Corrected), 1073 !, 1074 setup_call_cleanup( 1075 '$set_source_module'(M0, TypeIn), 1076 expand_goal(Corrected, Expanded), 1077 '$set_source_module'(M0)), 1078 print_message(silent, toplevel_goal(Expanded, Bindings)), 1079 '$execute_goal2'(Expanded, Bindings, Truth). 1080'$execute_query'(_, _, false) :- 1081 notrace, 1082 print_message(query, query(no)). 1083 1084'$execute_goal2'(Goal, Bindings, true) :- 1085 restore_debug, 1086 '$current_typein_module'(TypeIn), 1087 residue_vars(TypeIn:Goal, Vars, TypeIn:Delays), 1088 deterministic(Det), 1089 ( save_debug 1090 ; restore_debug, fail 1091 ), 1092 flush_output(user_output), 1093 call_expand_answer(Bindings, NewBindings), 1094 ( \+ \+ write_bindings(NewBindings, Vars, Delays, Det) 1095 -> ! 1096 ). 1097'$execute_goal2'(_, _, false) :- 1098 save_debug, 1099 print_message(query, query(no)). 1100 1101residue_vars(Goal, Vars, Delays) :- 1102 current_prolog_flag(toplevel_residue_vars, true), 1103 !, 1104 '$wfs_call'(call_residue_vars(stop_backtrace(Goal), Vars), Delays). 1105residue_vars(Goal, [], Delays) :- 1106 '$wfs_call'(stop_backtrace(Goal), Delays). 1107 1108stop_backtrace(Goal) :- 1109 toplevel_call(Goal), 1110 no_lco. 1111 1112toplevel_call(Goal) :- 1113 call(Goal), 1114 no_lco. 1115 1116no_lco.
groundness
gives the classical behaviour,
determinism
is considered more adequate and informative.
Succeeds if the user accepts the answer and fails otherwise.
1132write_bindings(Bindings, ResidueVars, Delays, Det) :- 1133 '$current_typein_module'(TypeIn), 1134 translate_bindings(Bindings, Bindings1, ResidueVars, TypeIn:Residuals), 1135 omit_qualifier(Delays, TypeIn, Delays1), 1136 write_bindings2(Bindings1, Residuals, Delays1, Det). 1137 1138write_bindings2([], Residuals, Delays, _) :- 1139 current_prolog_flag(prompt_alternatives_on, groundness), 1140 !, 1141 print_message(query, query(yes(Delays, Residuals))). 1142write_bindings2(Bindings, Residuals, Delays, true) :- 1143 current_prolog_flag(prompt_alternatives_on, determinism), 1144 !, 1145 print_message(query, query(yes(Bindings, Delays, Residuals))). 1146write_bindings2(Bindings, Residuals, Delays, _Det) :- 1147 repeat, 1148 print_message(query, query(more(Bindings, Delays, Residuals))), 1149 get_respons(Action), 1150 ( Action == redo 1151 -> !, fail 1152 ; Action == show_again 1153 -> fail 1154 ; !, 1155 print_message(query, query(done)) 1156 ).
1163:- multifile 1164 residual_goal_collector/1. 1165 1166:- meta_predicate 1167 residual_goals( ). 1168 1169residual_goals(NonTerminal) :- 1170 throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)). 1171 1172systemterm_expansion((:- residual_goals(NonTerminal)), 1173 '$toplevel':residual_goal_collector(M2:Head)) :- 1174 prolog_load_context(module, M), 1175 strip_module(M:NonTerminal, M2, Head), 1176 '$must_be'(callable, Head).
1183:- public prolog:residual_goals//0. 1184 1185prolog:residual_goals --> 1186 { findall(NT, residual_goal_collector(NT), NTL) }, 1187 collect_residual_goals(NTL). 1188 1189collect_residual_goals([]) --> []. 1190collect_residual_goals([H|T]) --> 1191 ( call(H) -> [] ; [] ), 1192 collect_residual_goals(T).
1217:- public 1218 prolog:translate_bindings/5. 1219:- meta_predicate 1220 prolog:translate_bindings( , , , , ). 1221 1222prologtranslate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals) :- 1223 translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals). 1224 1225translate_bindings(Bindings0, Bindings, ResidueVars, Residuals) :- 1226 prolog:residual_goals(ResidueGoals, []), 1227 translate_bindings(Bindings0, Bindings, ResidueVars, ResidueGoals, 1228 Residuals). 1229 1230translate_bindings(Bindings0, Bindings, [], [], _:[]-[]) :- 1231 term_attvars(Bindings0, []), 1232 !, 1233 join_same_bindings(Bindings0, Bindings1), 1234 factorize_bindings(Bindings1, Bindings2), 1235 bind_vars(Bindings2, Bindings3), 1236 filter_bindings(Bindings3, Bindings). 1237translate_bindings(Bindings0, Bindings, ResidueVars, ResGoals0, 1238 TypeIn:Residuals-HiddenResiduals) :- 1239 project_constraints(Bindings0, ResidueVars), 1240 hidden_residuals(ResidueVars, Bindings0, HiddenResiduals0), 1241 omit_qualifiers(HiddenResiduals0, TypeIn, HiddenResiduals), 1242 copy_term(Bindings0+ResGoals0, Bindings1+ResGoals1, Residuals0), 1243 '$append'(ResGoals1, Residuals0, Residuals1), 1244 omit_qualifiers(Residuals1, TypeIn, Residuals), 1245 join_same_bindings(Bindings1, Bindings2), 1246 factorize_bindings(Bindings2, Bindings3), 1247 bind_vars(Bindings3, Bindings4), 1248 filter_bindings(Bindings4, Bindings). 1249 ResidueVars, Bindings, Goal) (:- 1251 term_attvars(ResidueVars, Remaining), 1252 term_attvars(Bindings, QueryVars), 1253 subtract_vars(Remaining, QueryVars, HiddenVars), 1254 copy_term(HiddenVars, _, Goal). 1255 1256subtract_vars(All, Subtract, Remaining) :- 1257 sort(All, AllSorted), 1258 sort(Subtract, SubtractSorted), 1259 ord_subtract(AllSorted, SubtractSorted, Remaining). 1260 1261ord_subtract([], _Not, []). 1262ord_subtract([H1|T1], L2, Diff) :- 1263 diff21(L2, H1, T1, Diff). 1264 1265diff21([], H1, T1, [H1|T1]). 1266diff21([H2|T2], H1, T1, Diff) :- 1267 compare(Order, H1, H2), 1268 diff3(Order, H1, T1, H2, T2, Diff). 1269 1270diff12([], _H2, _T2, []). 1271diff12([H1|T1], H2, T2, Diff) :- 1272 compare(Order, H1, H2), 1273 diff3(Order, H1, T1, H2, T2, Diff). 1274 1275diff3(<, H1, T1, H2, T2, [H1|Diff]) :- 1276 diff12(T1, H2, T2, Diff). 1277diff3(=, _H1, T1, _H2, T2, Diff) :- 1278 ord_subtract(T1, T2, Diff). 1279diff3(>, H1, T1, _H2, T2, Diff) :- 1280 diff21(T2, H1, T1, Diff).
toplevel_residue_vars
is set to project
.1288project_constraints(Bindings, ResidueVars) :- 1289 !, 1290 term_attvars(Bindings, AttVars), 1291 phrase(attribute_modules(AttVars), Modules0), 1292 sort(Modules0, Modules), 1293 term_variables(Bindings, QueryVars), 1294 project_attributes(Modules, QueryVars, ResidueVars). 1295project_constraints(_, _). 1296 1297project_attributes([], _, _). 1298project_attributes([M|T], QueryVars, ResidueVars) :- 1299 ( current_predicate(M:project_attributes/2), 1300 catch(M:project_attributes(QueryVars, ResidueVars), E, 1301 print_message(error, E)) 1302 -> true 1303 ; true 1304 ), 1305 project_attributes(T, QueryVars, ResidueVars). 1306 1307attribute_modules([]) --> []. 1308attribute_modules([H|T]) --> 1309 { get_attrs(H, Attrs) }, 1310 attrs_modules(Attrs), 1311 attribute_modules(T). 1312 1313attrs_modules([]) --> []. 1314attrs_modules(att(Module, _, More)) --> 1315 [Module], 1316 attrs_modules(More).
1327join_same_bindings([], []). 1328join_same_bindings([Name=V0|T0], [[Name|Names]=V|T]) :- 1329 take_same_bindings(T0, V0, V, Names, T1), 1330 join_same_bindings(T1, T). 1331 1332take_same_bindings([], Val, Val, [], []). 1333take_same_bindings([Name=V1|T0], V0, V, [Name|Names], T) :- 1334 V0 == V1, 1335 !, 1336 take_same_bindings(T0, V1, V, Names, T). 1337take_same_bindings([Pair|T0], V0, V, Names, [Pair|T]) :- 1338 take_same_bindings(T0, V0, V, Names, T).
1347omit_qualifiers([], _, []). 1348omit_qualifiers([Goal0|Goals0], TypeIn, [Goal|Goals]) :- 1349 omit_qualifier(Goal0, TypeIn, Goal), 1350 omit_qualifiers(Goals0, TypeIn, Goals). 1351 1352omit_qualifier(M:G0, TypeIn, G) :- 1353 M == TypeIn, 1354 !, 1355 omit_meta_qualifiers(G0, TypeIn, G). 1356omit_qualifier(M:G0, TypeIn, G) :- 1357 predicate_property(TypeIn:G0, imported_from(M)), 1358 \+ predicate_property(G0, transparent), 1359 !, 1360 G0 = G. 1361omit_qualifier(_:G0, _, G) :- 1362 predicate_property(G0, built_in), 1363 \+ predicate_property(G0, transparent), 1364 !, 1365 G0 = G. 1366omit_qualifier(M:G0, _, M:G) :- 1367 atom(M), 1368 !, 1369 omit_meta_qualifiers(G0, M, G). 1370omit_qualifier(G0, TypeIn, G) :- 1371 omit_meta_qualifiers(G0, TypeIn, G). 1372 1373omit_meta_qualifiers(V, _, V) :- 1374 var(V), 1375 !. 1376omit_meta_qualifiers((QA,QB), TypeIn, (A,B)) :- 1377 !, 1378 omit_qualifier(QA, TypeIn, A), 1379 omit_qualifier(QB, TypeIn, B). 1380omit_meta_qualifiers(tnot(QA), TypeIn, tnot(A)) :- 1381 !, 1382 omit_qualifier(QA, TypeIn, A). 1383omit_meta_qualifiers(freeze(V, QGoal), TypeIn, freeze(V, Goal)) :- 1384 callable(QGoal), 1385 !, 1386 omit_qualifier(QGoal, TypeIn, Goal). 1387omit_meta_qualifiers(when(Cond, QGoal), TypeIn, when(Cond, Goal)) :- 1388 callable(QGoal), 1389 !, 1390 omit_qualifier(QGoal, TypeIn, Goal). 1391omit_meta_qualifiers(G, _, G).
1400bind_vars(Bindings0, Bindings) :- 1401 bind_query_vars(Bindings0, Bindings, SNames), 1402 bind_skel_vars(Bindings, Bindings, SNames, 1, _). 1403 1404bind_query_vars([], [], []). 1405bind_query_vars([binding(Names,Var,[Var2=Cycle])|T0], 1406 [binding(Names,Cycle,[])|T], [Name|SNames]) :- 1407 Var == Var2, % also implies var(Var) 1408 !, 1409 '$last'(Names, Name), 1410 Var = '$VAR'(Name), 1411 bind_query_vars(T0, T, SNames). 1412bind_query_vars([B|T0], [B|T], AllNames) :- 1413 B = binding(Names,Var,Skel), 1414 bind_query_vars(T0, T, SNames), 1415 ( var(Var), \+ attvar(Var), Skel == [] 1416 -> AllNames = [Name|SNames], 1417 '$last'(Names, Name), 1418 Var = '$VAR'(Name) 1419 ; AllNames = SNames 1420 ). 1421 1422 1423 1424bind_skel_vars([], _, _, N, N). 1425bind_skel_vars([binding(_,_,Skel)|T], Bindings, SNames, N0, N) :- 1426 bind_one_skel_vars(Skel, Bindings, SNames, N0, N1), 1427 bind_skel_vars(T, Bindings, SNames, N1, N).
1446bind_one_skel_vars([], _, _, N, N). 1447bind_one_skel_vars([Var=Value|T], Bindings, Names, N0, N) :- 1448 ( var(Var) 1449 -> ( '$member'(binding(Names, VVal, []), Bindings), 1450 same_term(Value, VVal) 1451 -> '$last'(Names, VName), 1452 Var = '$VAR'(VName), 1453 N2 = N0 1454 ; between(N0, infinite, N1), 1455 atom_concat('_S', N1, Name), 1456 \+ memberchk(Name, Names), 1457 !, 1458 Var = '$VAR'(Name), 1459 N2 is N1 + 1 1460 ) 1461 ; N2 = N0 1462 ), 1463 bind_one_skel_vars(T, Bindings, Names, N2, N).
1470factorize_bindings([], []). 1471factorize_bindings([Name=Value|T0], [binding(Name, Skel, Subst)|T]) :- 1472 '$factorize_term'(Value, Skel, Subst0), 1473 ( current_prolog_flag(toplevel_print_factorized, true) 1474 -> Subst = Subst0 1475 ; only_cycles(Subst0, Subst) 1476 ), 1477 factorize_bindings(T0, T). 1478 1479 1480only_cycles([], []). 1481only_cycles([B|T0], List) :- 1482 ( B = (Var=Value), 1483 Var = Value, 1484 acyclic_term(Var) 1485 -> only_cycles(T0, List) 1486 ; List = [B|T], 1487 only_cycles(T0, T) 1488 ).
1497filter_bindings([], []). 1498filter_bindings([H0|T0], T) :- 1499 hide_vars(H0, H), 1500 ( ( arg(1, H, []) 1501 ; self_bounded(H) 1502 ) 1503 -> filter_bindings(T0, T) 1504 ; T = [H|T1], 1505 filter_bindings(T0, T1) 1506 ). 1507 1508hide_vars(binding(Names0, Skel, Subst), binding(Names, Skel, Subst)) :- 1509 hide_names(Names0, Skel, Subst, Names). 1510 1511hide_names([], _, _, []). 1512hide_names([Name|T0], Skel, Subst, T) :- 1513 ( sub_atom(Name, 0, _, _, '_'), 1514 current_prolog_flag(toplevel_print_anon, false), 1515 sub_atom(Name, 1, 1, _, Next), 1516 char_type(Next, prolog_var_start) 1517 -> true 1518 ; Subst == [], 1519 Skel == '$VAR'(Name) 1520 ), 1521 !, 1522 hide_names(T0, Skel, Subst, T). 1523hide_names([Name|T0], Skel, Subst, [Name|T]) :- 1524 hide_names(T0, Skel, Subst, T). 1525 1526self_bounded(binding([Name], Value, [])) :- 1527 Value == '$VAR'(Name).
1533get_respons(Action) :- 1534 repeat, 1535 flush_output(user_output), 1536 get_single_char(Char), 1537 answer_respons(Char, Action), 1538 ( Action == again 1539 -> print_message(query, query(action)), 1540 fail 1541 ; ! 1542 ). 1543 1544answer_respons(Char, again) :- 1545 '$in_reply'(Char, '?h'), 1546 !, 1547 print_message(help, query(help)). 1548answer_respons(Char, redo) :- 1549 '$in_reply'(Char, ';nrNR \t'), 1550 !, 1551 print_message(query, if_tty([ansi(bold, ';', [])])). 1552answer_respons(Char, redo) :- 1553 '$in_reply'(Char, 'tT'), 1554 !, 1555 trace, 1556 save_debug, 1557 print_message(query, if_tty([ansi(bold, '; [trace]', [])])). 1558answer_respons(Char, continue) :- 1559 '$in_reply'(Char, 'ca\n\ryY.'), 1560 !, 1561 print_message(query, if_tty([ansi(bold, '.', [])])). 1562answer_respons(0'b, show_again) :- 1563 !, 1564 break. 1565answer_respons(Char, show_again) :- 1566 print_predicate(Char, Pred, Options), 1567 !, 1568 print_message(query, if_tty(['~w'-[Pred]])), 1569 set_prolog_flag(answer_write_options, Options). 1570answer_respons(-1, show_again) :- 1571 !, 1572 print_message(query, halt('EOF')), 1573 halt(0). 1574answer_respons(Char, again) :- 1575 print_message(query, no_action(Char)). 1576 1577print_predicate(0'w, [write], [ quoted(true), 1578 spacing(next_argument) 1579 ]). 1580print_predicate(0'p, [print], [ quoted(true), 1581 portray(true), 1582 max_depth(10), 1583 spacing(next_argument) 1584 ]). 1585 1586 1587 /******************************* 1588 * EXPANSION * 1589 *******************************/ 1590 1591:- user:dynamic(expand_query/4). 1592:- user:multifile(expand_query/4). 1593 1594call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :- 1595 user:expand_query(Goal, Expanded, Bindings, ExpandedBindings), 1596 !. 1597call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :- 1598 toplevel_variables:expand_query(Goal, Expanded, Bindings, ExpandedBindings), 1599 !. 1600call_expand_query(Goal, Goal, Bindings, Bindings). 1601 1602 1603:- user:dynamic(expand_answer/2). 1604:- user:multifile(expand_answer/2). 1605 1606call_expand_answer(Goal, Expanded) :- 1607 user:expand_answer(Goal, Expanded), 1608 !. 1609call_expand_answer(Goal, Expanded) :- 1610 toplevel_variables:expand_answer(Goal, Expanded), 1611 !. 1612call_expand_answer(Goal, Goal)