36
37:- module('$toplevel',
38 [ '$initialise'/0, 39 '$toplevel'/0, 40 '$compile'/0, 41 '$config'/0, 42 initialize/0, 43 version/0, 44 version/1, 45 prolog/0, 46 '$query_loop'/0, 47 '$execute_query'/3, 48 '$answer_class'/1, 49 residual_goals/1, 50 (initialization)/1, 51 '$thread_init'/0, 52 (thread_initialization)/1 53 ]). 54
55
56 59
60:- dynamic prolog:version_msg/1. 61:- multifile prolog:version_msg/1. 62
67
68version :-
69 print_message(banner, welcome).
70
74
75:- multifile
76 system:term_expansion/2. 77
78system:term_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 91
98
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(_).
111
115
116:- dynamic
117 loaded_init_file/2. 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 197
198:- meta_predicate
199 initialization(0). 200
201:- '$iso'((initialization)/1). 202
209
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. 223
224prolog:initialize_now(load_foreign_library(_),
225 'use :- use_foreign_library/1 instead').
226prolog:initialize_now(load_foreign_library(_,_),
227 'use :- use_foreign_library/2 instead').
228
229prolog:message(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'.
239
244
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 262
263:- meta_predicate
264 thread_initialization(0). 265:- dynamic
266 '$at_thread_initialization'/1. 267
271
272thread_initialization(Goal) :-
273 assert('$at_thread_initialization'(Goal)),
274 call(Goal),
275 !.
276
280
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 295
299
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 355
387
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 ).
461
468
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. 479
483
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.
494
495
499
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 526
532
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', 547 set_toplevel, 548 '$set_file_search_paths', 549 init_debug_flags,
550 setup_app,
551 start_pldoc, 552 main_thread_init.
553
559
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. 583
584
588
589user_thread_init :-
590 opt_attach_packs,
591 argv_prolog_files(Files, ScriptMode),
592 load_init_file(ScriptMode), 593 catch(setup_colors, E, print_message(warning, E)),
594 win_associated_files(Files), 595 '$load_script_file', 596 load_associated_files(Files),
597 '$cmd_option_val'(goals, Goals), 598 ( ScriptMode == app
599 -> run_program_init, 600 run_main_init(true)
601 ; Goals == [],
602 \+ '$init_goal'(when(_), _, _) 603 -> version 604 ; run_init_goals(Goals), 605 ( load_only 606 -> version
607 ; run_program_init, 608 run_main_init(false) 609 )
610 ).
611
617
618:- multifile
619 prolog:theme/1. 620
621setup_theme :-
622 current_prolog_flag(theme, Theme),
623 load_theme_file(Theme).
624
625load_theme_file(Theme) :-
626 prolog:theme(Theme),
627 !.
628load_theme_file(Theme) :-
629 exists_source(library(theme/Theme)),
630 !,
631 use_module(library(theme/Theme)).
632load_theme_file(_).
633
641
642:- multifile
643 prolog:theme_hook/1. 644
645:- public theme_changed/1. 646
647theme_changed(Theme) :-
648 forall(prolog:theme_hook(Theme), true).
649
650prolog:theme_hook(Theme) :-
651 load_theme_file(Theme).
652
656
657apply_defines :-
658 '$cmd_option_val'(defines, Defs),
659 apply_defines(Defs).
660
661apply_defines([]).
662apply_defines([H|T]) :-
663 apply_define(H),
664 apply_defines(T).
665
666apply_define(Def) :-
667 sub_atom(Def, B, _, A, '='),
668 !,
669 sub_atom(Def, 0, B, _, Flag),
670 sub_atom(Def, _, A, 0, Value0),
671 ( '$current_prolog_flag'(Flag, Value0, _Scope, Access, Type)
672 -> ( Access \== write
673 -> '$permission_error'(set, prolog_flag, Flag)
674 ; text_flag_value(Type, Value0, Value)
675 ),
676 set_prolog_flag(Flag, Value)
677 ; ( atom_number(Value0, Value)
678 -> true
679 ; Value = Value0
680 ),
681 set_defined(Flag, Value)
682 ).
683apply_define(Def) :-
684 atom_concat('no-', Flag, Def),
685 !,
686 set_user_boolean_flag(Flag, false).
687apply_define(Def) :-
688 set_user_boolean_flag(Def, true).
689
690set_user_boolean_flag(Flag, Value) :-
691 current_prolog_flag(Flag, Old),
692 !,
693 ( Old == Value
694 -> true
695 ; set_prolog_flag(Flag, Value)
696 ).
697set_user_boolean_flag(Flag, Value) :-
698 set_defined(Flag, Value).
699
700text_flag_value(integer, Text, Int) :-
701 atom_number(Text, Int),
702 !.
703text_flag_value(float, Text, Float) :-
704 atom_number(Text, Float),
705 !.
706text_flag_value(term, Text, Term) :-
707 term_string(Term, Text, []),
708 !.
709text_flag_value(_, Value, Value).
710
711set_defined(Flag, Value) :-
712 define_options(Flag, Options), !,
713 create_prolog_flag(Flag, Value, Options).
714
719
720define_options('SDL_VIDEODRIVER', []).
721define_options(_, [warn_not_accessed(true)]).
722
726
727init_optimise :-
728 current_prolog_flag(optimise, true),
729 !,
730 use_module(user:library(apply_macros)).
731init_optimise.
732
733opt_attach_packs :-
734 current_prolog_flag(packs, true),
735 !,
736 attach_packs.
737opt_attach_packs.
738
739set_toplevel :-
740 '$cmd_option_val'(toplevel, TopLevelAtom),
741 catch(term_to_atom(TopLevel, TopLevelAtom), E,
742 (print_message(error, E),
743 halt(1))),
744 create_prolog_flag(toplevel_goal, TopLevel, [type(term)]).
745
746load_only :-
747 current_prolog_flag(os_argv, OSArgv),
748 memberchk('-l', OSArgv),
749 current_prolog_flag(argv, Argv),
750 \+ memberchk('-l', Argv).
751
756
757run_init_goals([]).
758run_init_goals([H|T]) :-
759 run_init_goal(H),
760 run_init_goals(T).
761
762run_init_goal(Text) :-
763 catch(term_to_atom(Goal, Text), E,
764 ( print_message(error, init_goal_syntax(E, Text)),
765 halt(2)
766 )),
767 run_init_goal(Goal, Text).
768
772
773run_program_init :-
774 forall('$init_goal'(when(program), Goal, Ctx),
775 run_init_goal(Goal, @(Goal,Ctx))).
776
777run_main_init(_) :-
778 findall(Goal-Ctx, '$init_goal'(when(main), Goal, Ctx), Pairs),
779 '$last'(Pairs, Goal-Ctx),
780 !,
781 ( current_prolog_flag(toplevel_goal, default)
782 -> set_prolog_flag(toplevel_goal, halt)
783 ; true
784 ),
785 run_init_goal(Goal, @(Goal,Ctx)).
786run_main_init(true) :-
787 '$existence_error'(initialization, main).
788run_main_init(_).
789
790run_init_goal(Goal, Ctx) :-
791 ( catch_with_backtrace(user:Goal, E, true)
792 -> ( var(E)
793 -> true
794 ; init_goal_failed(E, Ctx)
795 )
796 ; ( current_prolog_flag(verbose, silent)
797 -> Level = silent
798 ; Level = error
799 ),
800 print_message(Level, init_goal_failed(failed, Ctx)),
801 halt(1)
802 ).
803
804init_goal_failed(E, Ctx) :-
805 print_message(error, init_goal_failed(E, Ctx)),
806 init_goal_failed(E).
807
808init_goal_failed(_) :-
809 thread_self(main),
810 !,
811 halt(2).
812init_goal_failed(_).
813
818
819init_debug_flags :-
820 Keep = [keep(true)],
821 create_prolog_flag(answer_write_options,
822 [ quoted(true), portray(true), max_depth(10),
823 spacing(next_argument)], Keep),
824 create_prolog_flag(prompt_alternatives_on, determinism, Keep),
825 create_prolog_flag(toplevel_extra_white_line, true, Keep),
826 create_prolog_flag(toplevel_print_factorized, false, Keep),
827 create_prolog_flag(print_write_options,
828 [ portray(true), quoted(true), numbervars(true) ],
829 Keep),
830 create_prolog_flag(toplevel_residue_vars, false, Keep),
831 create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
832 '$set_debugger_write_options'(print).
833
837
838setup_backtrace :-
839 ( \+ current_prolog_flag(backtrace, false),
840 load_setup_file(library(prolog_stack))
841 -> true
842 ; true
843 ).
844
848
849setup_colors :-
850 ( \+ current_prolog_flag(color_term, false),
851 stream_property(user_input, tty(true)),
852 stream_property(user_error, tty(true)),
853 stream_property(user_output, tty(true)),
854 \+ getenv('TERM', dumb),
855 load_setup_file(user:library(ansi_term))
856 -> true
857 ; true
858 ).
859
863
864setup_history :-
865 ( \+ current_prolog_flag(save_history, false),
866 stream_property(user_input, tty(true)),
867 \+ current_prolog_flag(readline, false),
868 load_setup_file(library(prolog_history))
869 -> prolog_history(enable)
870 ; true
871 ).
872
876
877setup_readline :-
878 ( stream_property(user_input, tty(true)),
879 current_prolog_flag(tty_control, true),
880 \+ getenv('TERM', dumb),
881 ( current_prolog_flag(readline, ReadLine)
882 -> true
883 ; ReadLine = true
884 ),
885 readline_library(ReadLine, Library),
886 ( load_setup_file(library(Library))
887 -> true
888 ; current_prolog_flag(epilog, true),
889 print_message(warning,
890 error(existence_error(library, library(Library)),
891 _)),
892 fail
893 )
894 -> set_prolog_flag(readline, Library)
895 ; set_prolog_flag(readline, false)
896 ).
897
898readline_library(true, Library) :-
899 !,
900 preferred_readline(Library).
901readline_library(false, _) :-
902 !,
903 fail.
904readline_library(Library, Library).
905
906preferred_readline(editline).
907
911
912load_setup_file(File) :-
913 catch(load_files(File,
914 [ silent(true),
915 if(not_loaded)
916 ]), error(_,_), fail).
917
918
927
928:- if(current_prolog_flag(windows,true)). 929
930setup_app :-
931 current_prolog_flag(associated_file, _),
932 !.
933setup_app :-
934 '$cmd_option_val'(win_app, true),
935 !,
936 catch(my_prolog, E, print_message(warning, E)).
937setup_app.
938
939my_prolog :-
940 win_folder(personal, MyDocs),
941 atom_concat(MyDocs, '/Prolog', PrologDir),
942 ( ensure_dir(PrologDir)
943 -> working_directory(_, PrologDir)
944 ; working_directory(_, MyDocs)
945 ).
946
947ensure_dir(Dir) :-
948 exists_directory(Dir),
949 !.
950ensure_dir(Dir) :-
951 catch(make_directory(Dir), E, (print_message(warning, E), fail)).
952
953:- elif(current_prolog_flag(apple, true)). 954use_app_settings(true). 955
956setup_app :-
957 apple_set_locale,
958 current_prolog_flag(associated_file, _),
959 !.
960setup_app :-
961 current_prolog_flag(bundle, true),
962 current_prolog_flag(epilog, true),
963 getenv('__CFBundleIdentifier', _),
964 !,
965 setup_macos_app.
966setup_app.
967
968apple_set_locale :-
969 ( getenv('LC_CTYPE', 'UTF-8'),
970 apple_current_locale_identifier(LocaleID),
971 atom_concat(LocaleID, '.UTF-8', Locale),
972 catch(setlocale(ctype, _Old, Locale), _, fail)
973 -> setenv('LANG', Locale),
974 unsetenv('LC_CTYPE')
975 ; true
976 ).
977
978setup_macos_app :-
979 restore_working_directory,
980 !.
981setup_macos_app :-
982 expand_file_name('~/Prolog', [PrologDir]),
983 ( exists_directory(PrologDir)
984 -> true
985 ; catch(make_directory(PrologDir), MkDirError,
986 print_message(warning, MkDirError))
987 ),
988 catch(working_directory(_, PrologDir), CdError,
989 print_message(warning, CdError)),
990 !.
991setup_macos_app.
992
993:- elif(current_prolog_flag(emscripten, true)). 994setup_app.
995:- else. 996use_app_settings(true). 997
999setup_app :-
1000 running_as_app,
1001 restore_working_directory,
1002 !.
1003setup_app.
1004
1008
1009running_as_app :-
1011 current_prolog_flag(epilog, true),
1012 stream_property(In, file_no(0)),
1013 \+ stream_property(In, tty(true)),
1014 !.
1015
1016:- endif. 1017
1018
1019:- if((current_predicate(use_app_settings/1),
1020 use_app_settings(true))). 1021
1022
1023 1026
1027save_working_directory :-
1028 working_directory(WD, WD),
1029 app_settings(Settings),
1030 ( Settings.get(working_directory) == WD
1031 -> true
1032 ; app_save_settings(Settings.put(working_directory, WD))
1033 ).
1034
1035restore_working_directory :-
1036 at_halt(save_working_directory),
1037 app_settings(Settings),
1038 WD = Settings.get(working_directory),
1039 catch(working_directory(_, WD), _, fail),
1040 !.
1041
1042 1045
1049
1050app_settings(Settings) :-
1051 app_settings_file(File),
1052 access_file(File, read),
1053 catch(setup_call_cleanup(
1054 open(File, read, In, [encoding(utf8)]),
1055 read_term(In, Settings, []),
1056 close(In)),
1057 Error,
1058 (print_message(warning, Error), fail)),
1059 !.
1060app_settings(#{}).
1061
1065
1066app_save_settings(Settings) :-
1067 app_settings_file(File),
1068 catch(setup_call_cleanup(
1069 open(File, write, Out, [encoding(utf8)]),
1070 write_term(Out, Settings,
1071 [ quoted(true),
1072 module(system), 1073 fullstop(true),
1074 nl(true)
1075 ]),
1076 close(Out)),
1077 Error,
1078 (print_message(warning, Error), fail)).
1079
1080
1081app_settings_file(File) :-
1082 absolute_file_name(user_app_config('app_settings.pl'), File,
1083 [ access(write),
1084 file_errors(fail)
1085 ]).
1086:- endif. 1087
1088 1091
1092:- '$hide'('$toplevel'/0). 1093
1097
1098'$toplevel' :-
1099 '$runtoplevel',
1100 print_message(informational, halt).
1101
1109
1110'$runtoplevel' :-
1111 current_prolog_flag(toplevel_goal, TopLevel0),
1112 toplevel_goal(TopLevel0, TopLevel),
1113 user:TopLevel.
1114
1115:- dynamic setup_done/0. 1116:- volatile setup_done/0. 1117
1118toplevel_goal(default, '$query_loop') :-
1119 !,
1120 setup_interactive.
1121toplevel_goal(prolog, '$query_loop') :-
1122 !,
1123 setup_interactive.
1124toplevel_goal(Goal, Goal).
1125
1126setup_interactive :-
1127 setup_done,
1128 !.
1129setup_interactive :-
1130 asserta(setup_done),
1131 catch(setup_backtrace, E, print_message(warning, E)),
1132 catch(setup_readline, E, print_message(warning, E)),
1133 catch(setup_history, E, print_message(warning, E)).
1134
1138
1139'$compile' :-
1140 ( catch('$compile_', E, (print_message(error, E), halt(1)))
1141 -> true
1142 ; print_message(error, error(goal_failed('$compile'), _)),
1143 halt(1)
1144 ),
1145 halt. 1146
1147'$compile_' :-
1148 '$load_system_init_file',
1149 catch(setup_colors, _, true),
1150 '$set_file_search_paths',
1151 init_debug_flags,
1152 '$run_initialization',
1153 opt_attach_packs,
1154 use_module(library(qsave)),
1155 qsave:qsave_toplevel.
1156
1160
1161'$config' :-
1162 '$load_system_init_file',
1163 '$set_file_search_paths',
1164 init_debug_flags,
1165 '$run_initialization',
1166 load_files(library(prolog_config)),
1167 ( catch(prolog_dump_runtime_variables, E,
1168 (print_message(error, E), halt(1)))
1169 -> true
1170 ; print_message(error, error(goal_failed(prolog_dump_runtime_variables),_))
1171 ).
1172
1173
1174 1177
1188
1189:- multifile
1190 prolog:repl_loop_hook/2. 1191
1197
1198prolog :-
1199 break.
1200
1201:- create_prolog_flag(toplevel_mode, backtracking, []). 1202
1209
1210'$query_loop' :-
1211 break_level(BreakLev),
1212 setup_call_cleanup(
1213 notrace(call_repl_loop_hook(begin, BreakLev, IsToplevel)),
1214 '$query_loop'(BreakLev),
1215 notrace(call_repl_loop_hook(end, BreakLev, IsToplevel))).
1216
1217call_repl_loop_hook(begin, BreakLev, IsToplevel) =>
1218 ( current_prolog_flag(toplevel_thread, IsToplevel)
1219 -> true
1220 ; IsToplevel = false
1221 ),
1222 set_prolog_flag(toplevel_thread, true),
1223 call_repl_loop_hook_(begin, BreakLev).
1224call_repl_loop_hook(end, BreakLev, IsToplevel) =>
1225 set_prolog_flag(toplevel_thread, IsToplevel),
1226 call_repl_loop_hook_(end, BreakLev).
1227
1228call_repl_loop_hook_(BeginEnd, BreakLev) :-
1229 forall(prolog:repl_loop_hook(BeginEnd, BreakLev), true).
1230
1231
1232'$query_loop'(BreakLev) :-
1233 current_prolog_flag(toplevel_mode, recursive),
1234 !,
1235 read_expanded_query(BreakLev, Query, Bindings),
1236 ( Query == end_of_file
1237 -> print_message(query, query(eof))
1238 ; '$call_no_catch'('$execute_query'(Query, Bindings, _)),
1239 ( current_prolog_flag(toplevel_mode, recursive)
1240 -> '$query_loop'(BreakLev)
1241 ; '$switch_toplevel_mode'(backtracking),
1242 '$query_loop'(BreakLev) 1243 )
1244 ).
1245'$query_loop'(BreakLev) :-
1246 repeat,
1247 read_expanded_query(BreakLev, Query, Bindings),
1248 ( Query == end_of_file
1249 -> !, print_message(query, query(eof))
1250 ; '$execute_query'(Query, Bindings, _),
1251 ( current_prolog_flag(toplevel_mode, recursive)
1252 -> !,
1253 '$switch_toplevel_mode'(recursive),
1254 '$query_loop'(BreakLev)
1255 ; fail
1256 )
1257 ).
1258
1259break_level(BreakLev) :-
1260 ( current_prolog_flag(break_level, BreakLev)
1261 -> true
1262 ; BreakLev = -1
1263 ).
1264
1265read_expanded_query(BreakLev, ExpandedQuery, ExpandedBindings) :-
1266 '$current_typein_module'(TypeIn),
1267 ( stream_property(user_input, tty(true))
1268 -> '$system_prompt'(TypeIn, BreakLev, Prompt),
1269 decorate_prompt('| ', Continue),
1270 prompt(Old, Continue)
1271 ; Prompt = '',
1272 prompt(Old, '')
1273 ),
1274 reset_answer_count,
1275 trim_stacks,
1276 trim_heap,
1277 repeat,
1278 ( catch(call_cleanup(read_query(Prompt, Query, Bindings),
1279 end_input_style),
1280 error(io_error(_,_),_), fail)
1281 -> prompt(_, Old),
1282 catch(call_expand_query(Query, ExpandedQuery,
1283 Bindings, ExpandedBindings),
1284 Error,
1285 (print_message(error, Error), fail))
1286 ; set_prolog_flag(debug_on_error, false),
1287 thread_exit(io_error)
1288 ),
1289 !.
1290
1291
1297
1298:- multifile
1299 prolog:history/2. 1300
1301:- if(current_prolog_flag(emscripten, true)). 1302read_query(_Prompt, Goal, Bindings) :-
1303 '$can_yield',
1304 !,
1305 await(query, GoalString),
1306 term_string(Goal, GoalString, [variable_names(Bindings)]).
1307:- endif. 1308read_query(Prompt, Goal, Bindings) :-
1309 prolog:history(current_input, enabled),
1310 !,
1311 decorate_prompt(Prompt, DPrompt),
1312 read_term_with_history(
1313 Goal,
1314 [ show(h),
1315 help('!h'),
1316 no_save([trace]),
1317 prompt(DPrompt),
1318 variable_names(Bindings)
1319 ]).
1320read_query(Prompt, Goal, Bindings) :-
1321 remove_history_prompt(Prompt, Prompt0),
1322 decorate_prompt(Prompt0, Prompt1),
1323 repeat, 1324 prompt1(Prompt1),
1325 read_query_line(user_input, Line),
1326 '$current_typein_module'(TypeIn),
1327 catch(read_term_from_atom(Line, Goal,
1328 [ variable_names(Bindings),
1329 module(TypeIn),
1330 blob(resolve)
1331 ]), E,
1332 ( print_message(error, E),
1333 fail
1334 )),
1335 !.
1336
1342
1343read_query_line(Input, Line) :-
1344 stream_property(Input, error(true)),
1345 !,
1346 Line = end_of_file.
1347read_query_line(Input, Line) :-
1348 catch(read_term_as_atom(Input, Line0), Error, true),
1349 end_input_style, 1350 save_debug_after_read,
1351 ( var(Error)
1352 -> ( catch(term_string(Goal, Line0), error(_,_), fail),
1353 Goal = '$silent'(SilentGoal)
1354 -> Error = error(_,_),
1355 catch_with_backtrace(ignore(SilentGoal), Error,
1356 print_message(error, Error)),
1357 read_query_line(Input, Line)
1358 ; Line = Line0
1359 )
1360 ; catch(print_message(error, Error), _, true),
1361 ( Error = error(syntax_error(_),_)
1362 -> fail
1363 ; throw(Error)
1364 )
1365 ).
1366
1371
1372read_term_as_atom(In, Line) :-
1373 '$raw_read'(In, Line),
1374 ( Line == end_of_file
1375 -> true
1376 ; skip_to_nl(In)
1377 ).
1378
1383
1384skip_to_nl(In) :-
1385 repeat,
1386 peek_char(In, C),
1387 ( C == '%'
1388 -> skip(In, '\n')
1389 ; char_type(C, space)
1390 -> get_char(In, _),
1391 C == '\n'
1392 ; true
1393 ),
1394 !.
1395
1396remove_history_prompt('', '') :- !.
1397remove_history_prompt(Prompt0, Prompt) :-
1398 atom_chars(Prompt0, Chars0),
1399 clean_history_prompt_chars(Chars0, Chars1),
1400 delete_leading_blanks(Chars1, Chars),
1401 atom_chars(Prompt, Chars).
1402
1403clean_history_prompt_chars([], []).
1404clean_history_prompt_chars(['~', !|T], T) :- !.
1405clean_history_prompt_chars([H|T0], [H|T]) :-
1406 clean_history_prompt_chars(T0, T).
1407
1408delete_leading_blanks([' '|T0], T) :-
1409 !,
1410 delete_leading_blanks(T0, T).
1411delete_leading_blanks(L, L).
1412
1413
1414 1417
1430
1431save_debug_after_read :-
1432 current_prolog_flag(debug, true),
1433 !,
1434 save_debug.
1435save_debug_after_read.
1436
1437save_debug :-
1438 ( tracing,
1439 notrace
1440 -> Tracing = true
1441 ; Tracing = false
1442 ),
1443 current_prolog_flag(debug, Debugging),
1444 set_prolog_flag(debug, false),
1445 create_prolog_flag(query_debug_settings,
1446 debug(Debugging, Tracing), []).
1447
1448restore_debug :-
1449 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)),
1450 set_prolog_flag(debug, Debugging),
1451 ( Tracing == true
1452 -> trace
1453 ; true
1454 ).
1455
1456:- initialization
1457 create_prolog_flag(query_debug_settings, debug(false, false), []). 1458
1459
1460 1463
1477
1478'$answer_class'(Class) :-
1479 nb_current('$answer_class', Class),
1480 Class \== none.
1481
1482answer_count(Count) :-
1483 ( nb_current('$answer_count', C)
1484 -> Count = C
1485 ; Count = 0
1486 ).
1487
1488reset_answer_count :-
1489 nb_setval('$answer_count', 0),
1490 no_answer.
1491
1497
1498no_answer :-
1499 nb_setval('$answer_class', none).
1500
1504
1505next_answer([], true, []-[]) :-
1506 !,
1507 no_answer.
1508next_answer(_Bindings, _Delays, _Residuals) :-
1509 answer_count(C0),
1510 C is C0+1,
1511 nb_setval('$answer_count', C),
1512 ( C mod 2 =:= 0
1513 -> Class = answer(even)
1514 ; Class = answer(odd)
1515 ),
1516 nb_setval('$answer_class', Class).
1517
1537
1538decorate_prompt('', Prompt) :-
1539 !,
1540 Prompt = ''. 1541decorate_prompt(Plain, Decorated) :-
1542 prompt_sgr(input, Input),
1543 prompt_sgr(prompt, Prompt),
1544 line_editor_attributes(Input),
1545 ( Input == '',
1546 Prompt == ''
1547 -> Decorated = Plain
1548 ; Input == '' 1549 -> atomic_list_concat([Prompt, Plain, '\e[0m'], Decorated)
1550 ; atomic_list_concat([Input, '\e[K', Prompt, Plain, '\e[0m', Input],
1551 Decorated)
1552 ).
1553
1568
1569line_editor_attributes(Input) :-
1570 ( Input == ''
1571 -> Off = '', On = ''
1572 ; Off = '\e[0m', On = Input
1573 ),
1574 ignore(prolog:line_editor_attributes(Off, On)).
1575
1576prompt_sgr(Class, Sequence) :-
1577 colour_console,
1578 current_predicate(ansi_term:ansi_sgr/2),
1579 catch(ansi_term:ansi_sgr(Class, String), _, fail),
1580 String \== "",
1581 !,
1582 atom_string(Sequence, String).
1583prompt_sgr(_, '').
1584
1585colour_console :-
1586 current_prolog_flag(color_term, true),
1587 stream_property(user_output, tty(true)).
1588
1594
1595end_input_style :-
1596 ( colour_console
1597 -> write(user_output, '\e[0m'),
1598 flush_output(user_output)
1599 ; true
1600 ).
1601
1602'$system_prompt'(Module, BrekLev, Prompt) :-
1603 current_prolog_flag(toplevel_prompt, PAtom),
1604 atom_codes(PAtom, P0),
1605 ( Module \== user
1606 -> '$substitute'('~m', [Module, ': '], P0, P1)
1607 ; '$substitute'('~m', [], P0, P1)
1608 ),
1609 ( BrekLev > 0
1610 -> '$substitute'('~l', ['[', BrekLev, '] '], P1, P2)
1611 ; '$substitute'('~l', [], P1, P2)
1612 ),
1613 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)),
1614 ( Tracing == true
1615 -> '$substitute'('~d', ['[trace] '], P2, P3)
1616 ; Debugging == true
1617 -> '$substitute'('~d', ['[debug] '], P2, P3)
1618 ; '$substitute'('~d', [], P2, P3)
1619 ),
1620 atom_chars(Prompt, P3).
1621
1622'$substitute'(From, T, Old, New) :-
1623 atom_codes(From, FromCodes),
1624 phrase(subst_chars(T), T0),
1625 '$append'(Pre, S0, Old),
1626 '$append'(FromCodes, Post, S0) ->
1627 '$append'(Pre, T0, S1),
1628 '$append'(S1, Post, New),
1629 !.
1630'$substitute'(_, _, Old, Old).
1631
1632subst_chars([]) -->
1633 [].
1634subst_chars([H|T]) -->
1635 { atomic(H),
1636 !,
1637 atom_codes(H, Codes)
1638 },
1639 Codes,
1640 subst_chars(T).
1641subst_chars([H|T]) -->
1642 H,
1643 subst_chars(T).
1644
1645
1646 1649
1653
1654'$execute_query'(Var, _, true) :-
1655 var(Var),
1656 !,
1657 print_message(informational, var_query(Var)).
1658'$execute_query'(Goal, Bindings, Truth) :-
1659 '$current_typein_module'(TypeIn),
1660 '$dwim_correct_goal'(TypeIn:Goal, Bindings, Corrected),
1661 !,
1662 setup_call_cleanup(
1663 '$set_source_module'(M0, TypeIn),
1664 expand_goal(Corrected, Expanded),
1665 '$set_source_module'(M0)),
1666 print_message(silent, toplevel_goal(Expanded, Bindings)),
1667 '$execute_goal2'(Expanded, Bindings, Truth).
1668'$execute_query'(_, _, false) :-
1669 notrace,
1670 no_answer,
1671 print_message(query, query(no)).
1672
1673'$execute_goal2'(Goal, Bindings, true) :-
1674 restore_debug,
1675 '$current_typein_module'(TypeIn),
1676 residue_vars(TypeIn:Goal, Vars, TypeIn:Delays, Chp),
1677 deterministic(Det),
1678 ( save_debug
1679 ; restore_debug, fail
1680 ),
1681 flush_output(user_output),
1682 ( Det == true
1683 -> DetOrChp = true
1684 ; DetOrChp = Chp
1685 ),
1686 call_expand_answer(Goal, Bindings, NewBindings),
1687 ( \+ \+ write_bindings(NewBindings, Vars, Delays, DetOrChp)
1688 -> !
1689 ).
1690'$execute_goal2'(_, _, false) :-
1691 save_debug,
1692 no_answer,
1693 print_message(query, query(no)).
1694
1695residue_vars(Goal, Vars, Delays, Chp) :-
1696 current_prolog_flag(toplevel_residue_vars, true),
1697 !,
1698 '$wfs_call'(call_residue_vars(stop_backtrace(Goal, Chp), Vars), Delays).
1699residue_vars(Goal, [], Delays, Chp) :-
1700 '$wfs_call'(stop_backtrace(Goal, Chp), Delays).
1701
1702stop_backtrace(Goal, Chp) :-
1703 toplevel_call(Goal),
1704 prolog_current_choice(Chp).
1705
1706toplevel_call(Goal) :-
1707 call(Goal),
1708 no_lco.
1709
1710no_lco.
1711
1725
1726write_bindings(Bindings, ResidueVars, Delays, DetOrChp) :-
1727 '$current_typein_module'(TypeIn),
1728 translate_bindings(Bindings, Bindings1, ResidueVars, TypeIn:Residuals),
1729 omit_qualifier(Delays, TypeIn, Delays1),
1730 next_answer(Bindings1, Delays1, Residuals),
1731 write_bindings2(Bindings, Bindings1, Residuals, Delays1, DetOrChp).
1732
1733write_bindings2(OrgBindings, [], Residuals, Delays, _) :-
1734 current_prolog_flag(prompt_alternatives_on, groundness),
1735 !,
1736 name_vars(OrgBindings, [], t(Residuals, Delays)),
1737 print_message(query, query(yes(Delays, Residuals))).
1738write_bindings2(OrgBindings, Bindings, Residuals, Delays, true) :-
1739 current_prolog_flag(prompt_alternatives_on, determinism),
1740 !,
1741 name_vars(OrgBindings, Bindings, t(Residuals, Delays)),
1742 print_message(query, query(yes(Bindings, Delays, Residuals))).
1743write_bindings2(OrgBindings, Bindings, Residuals, Delays, Chp) :-
1744 repeat,
1745 name_vars(OrgBindings, Bindings, t(Residuals, Delays)),
1746 print_message(query, query(more(Bindings, Delays, Residuals))),
1747 get_respons(Action, Chp),
1748 ( Action == redo
1749 -> !, fail
1750 ; Action == show_again
1751 -> fail
1752 ; !,
1753 no_answer,
1754 print_message(query, query(done))
1755 ).
1756
1770
1771name_vars(OrgBindings, Bindings, Term) :-
1772 current_prolog_flag(toplevel_name_variables, true),
1773 answer_flags_imply_numbervars,
1774 !,
1775 '$term_multitons'(t(Bindings,Term), Vars),
1776 bindings_var_names(OrgBindings, Bindings, VarNames),
1777 name_vars_(Vars, VarNames, 0),
1778 term_variables(t(Bindings,Term), SVars),
1779 anon_vars(SVars).
1780name_vars(_OrgBindings, _Bindings, _Term).
1781
1782name_vars_([], _, _).
1783name_vars_([H|T], Bindings, N) :-
1784 name_var(Bindings, Name, N, N1),
1785 H = '$VAR'(Name),
1786 name_vars_(T, Bindings, N1).
1787
1788anon_vars([]).
1789anon_vars(['$VAR'('_')|T]) :-
1790 anon_vars(T).
1791
1796
1797name_var(Reserved, Name, N0, N) :-
1798 between(N0, infinite, N1),
1799 I is N1//26,
1800 J is 0'A + N1 mod 26,
1801 ( I == 0
1802 -> format(atom(Name), '_~c', [J])
1803 ; format(atom(Name), '_~c~d', [J, I])
1804 ),
1805 \+ memberchk(Name, Reserved),
1806 !,
1807 N is N1+1.
1808
1815
1816bindings_var_names(OrgBindings, TransBindings, VarNames) :-
1817 phrase(bindings_var_names_(OrgBindings), VarNames0, Tail),
1818 phrase(bindings_var_names_(TransBindings), Tail, []),
1819 sort(VarNames0, VarNames).
1820
1825
1826bindings_var_names_([]) --> [].
1827bindings_var_names_([H|T]) -->
1828 binding_var_names(H),
1829 bindings_var_names_(T).
1830
1831binding_var_names(binding(Vars,_Value,_Subst)) ==>
1832 var_names(Vars).
1833binding_var_names(Name=_Value) ==>
1834 [Name].
1835
1836var_names([]) --> [].
1837var_names([H|T]) --> [H], var_names(T).
1838
1839
1844
1845answer_flags_imply_numbervars :-
1846 current_prolog_flag(answer_write_options, Options),
1847 numbervars_option(Opt),
1848 '$option'(Opt, Options),
1849 !.
1850
1851numbervars_option(portray(true)).
1852numbervars_option(portrayed(true)).
1853numbervars_option(numbervars(true)).
1854
1859
1860:- multifile
1861 residual_goal_collector/1. 1862
1863:- meta_predicate
1864 residual_goals(2). 1865
1866residual_goals(NonTerminal) :-
1867 throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)).
1868
1869system:term_expansion((:- residual_goals(NonTerminal)),
1870 '$toplevel':residual_goal_collector(M2:Head)) :-
1871 \+ current_prolog_flag(xref, true),
1872 prolog_load_context(module, M),
1873 strip_module(M:NonTerminal, M2, Head),
1874 '$must_be'(callable, Head).
1875
1880
1881:- public prolog:residual_goals//0. 1882
1883prolog:residual_goals -->
1884 { findall(NT, residual_goal_collector(NT), NTL) },
1885 collect_residual_goals(NTL).
1886
1887collect_residual_goals([]) --> [].
1888collect_residual_goals([H|T]) -->
1889 ( call(H) -> [] ; [] ),
1890 collect_residual_goals(T).
1891
1892
1893
1914
1915:- public
1916 prolog:translate_bindings/5. 1917:- meta_predicate
1918 prolog:translate_bindings(+, -, +, +, :). 1919
1920prolog:translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals) :-
1921 translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals),
1922 name_vars(Bindings0, Bindings, t(ResVars, ResGoals, Residuals)).
1923
1925prolog:name_vars(Bindings, Term) :- name_vars([], Bindings, Term).
1926prolog:name_vars(Bindings0, Bindings, Term) :- name_vars(Bindings0, Bindings, Term).
1927
1928translate_bindings(Bindings0, Bindings, ResidueVars, Residuals) :-
1929 prolog:residual_goals(ResidueGoals, []),
1930 translate_bindings(Bindings0, Bindings, ResidueVars, ResidueGoals,
1931 Residuals).
1932
1933translate_bindings(Bindings0, Bindings, [], [], _:[]-[]) :-
1934 term_attvars(Bindings0, []),
1935 !,
1936 join_same_bindings(Bindings0, Bindings1),
1937 factorize_bindings(Bindings1, Bindings2),
1938 bind_vars(Bindings2, Bindings3),
1939 filter_bindings(Bindings3, Bindings).
1940translate_bindings(Bindings0, Bindings, ResidueVars, ResGoals0,
1941 TypeIn:Residuals-HiddenResiduals) :-
1942 project_constraints(Bindings0, ResidueVars),
1943 hidden_residuals(ResidueVars, Bindings0, HiddenResiduals0),
1944 omit_qualifiers(HiddenResiduals0, TypeIn, HiddenResiduals),
1945 copy_term(Bindings0+ResGoals0, Bindings1+ResGoals1, Residuals0),
1946 '$append'(ResGoals1, Residuals0, Residuals1),
1947 omit_qualifiers(Residuals1, TypeIn, Residuals),
1948 join_same_bindings(Bindings1, Bindings2),
1949 factorize_bindings(Bindings2, Bindings3),
1950 bind_vars(Bindings3, Bindings4),
1951 filter_bindings(Bindings4, Bindings).
1952
1953hidden_residuals(ResidueVars, Bindings, Goal) :-
1954 term_attvars(ResidueVars, Remaining),
1955 term_attvars(Bindings, QueryVars),
1956 subtract_vars(Remaining, QueryVars, HiddenVars),
1957 copy_term(HiddenVars, _, Goal).
1958
1959subtract_vars(All, Subtract, Remaining) :-
1960 sort(All, AllSorted),
1961 sort(Subtract, SubtractSorted),
1962 ord_subtract(AllSorted, SubtractSorted, Remaining).
1963
1964ord_subtract([], _Not, []).
1965ord_subtract([H1|T1], L2, Diff) :-
1966 diff21(L2, H1, T1, Diff).
1967
1968diff21([], H1, T1, [H1|T1]).
1969diff21([H2|T2], H1, T1, Diff) :-
1970 compare(Order, H1, H2),
1971 diff3(Order, H1, T1, H2, T2, Diff).
1972
1973diff12([], _H2, _T2, []).
1974diff12([H1|T1], H2, T2, Diff) :-
1975 compare(Order, H1, H2),
1976 diff3(Order, H1, T1, H2, T2, Diff).
1977
1978diff3(<, H1, T1, H2, T2, [H1|Diff]) :-
1979 diff12(T1, H2, T2, Diff).
1980diff3(=, _H1, T1, _H2, T2, Diff) :-
1981 ord_subtract(T1, T2, Diff).
1982diff3(>, H1, T1, _H2, T2, Diff) :-
1983 diff21(T2, H1, T1, Diff).
1984
1985
1990
1991project_constraints(Bindings, ResidueVars) :-
1992 !,
1993 term_attvars(Bindings, AttVars),
1994 phrase(attribute_modules(AttVars), Modules0),
1995 sort(Modules0, Modules),
1996 term_variables(Bindings, QueryVars),
1997 project_attributes(Modules, QueryVars, ResidueVars).
1998project_constraints(_, _).
1999
2000project_attributes([], _, _).
2001project_attributes([M|T], QueryVars, ResidueVars) :-
2002 ( current_predicate(M:project_attributes/2),
2003 catch(M:project_attributes(QueryVars, ResidueVars), E,
2004 print_message(error, E))
2005 -> true
2006 ; true
2007 ),
2008 project_attributes(T, QueryVars, ResidueVars).
2009
2010attribute_modules([]) --> [].
2011attribute_modules([H|T]) -->
2012 { get_attrs(H, Attrs) },
2013 attrs_modules(Attrs),
2014 attribute_modules(T).
2015
2016attrs_modules([]) --> [].
2017attrs_modules(att(Module, _, More)) -->
2018 [Module],
2019 attrs_modules(More).
2020
2021
2029
2030join_same_bindings([], []).
2031join_same_bindings([Name=V0|T0], [[Name|Names]=V|T]) :-
2032 take_same_bindings(T0, V0, V, Names, T1),
2033 join_same_bindings(T1, T).
2034
2035take_same_bindings([], Val, Val, [], []).
2036take_same_bindings([Name=V1|T0], V0, V, [Name|Names], T) :-
2037 V0 == V1,
2038 !,
2039 take_same_bindings(T0, V1, V, Names, T).
2040take_same_bindings([Pair|T0], V0, V, Names, [Pair|T]) :-
2041 take_same_bindings(T0, V0, V, Names, T).
2042
2043
2048
2049
2050omit_qualifiers([], _, []).
2051omit_qualifiers([Goal0|Goals0], TypeIn, [Goal|Goals]) :-
2052 omit_qualifier(Goal0, TypeIn, Goal),
2053 omit_qualifiers(Goals0, TypeIn, Goals).
2054
2055omit_qualifier(M:G0, TypeIn, G) :-
2056 M == TypeIn,
2057 !,
2058 omit_meta_qualifiers(G0, TypeIn, G).
2059omit_qualifier(M:G0, TypeIn, G) :-
2060 predicate_property(TypeIn:G0, imported_from(M)),
2061 \+ predicate_property(G0, transparent),
2062 !,
2063 G0 = G.
2064omit_qualifier(_:G0, _, G) :-
2065 predicate_property(G0, built_in),
2066 \+ predicate_property(G0, transparent),
2067 !,
2068 G0 = G.
2069omit_qualifier(M:G0, _, M:G) :-
2070 atom(M),
2071 !,
2072 omit_meta_qualifiers(G0, M, G).
2073omit_qualifier(G0, TypeIn, G) :-
2074 omit_meta_qualifiers(G0, TypeIn, G).
2075
2076omit_meta_qualifiers(V, _, V) :-
2077 var(V),
2078 !.
2079omit_meta_qualifiers((QA,QB), TypeIn, (A,B)) :-
2080 !,
2081 omit_qualifier(QA, TypeIn, A),
2082 omit_qualifier(QB, TypeIn, B).
2083omit_meta_qualifiers(tnot(QA), TypeIn, tnot(A)) :-
2084 !,
2085 omit_qualifier(QA, TypeIn, A).
2086omit_meta_qualifiers(freeze(V, QGoal), TypeIn, freeze(V, Goal)) :-
2087 callable(QGoal),
2088 !,
2089 omit_qualifier(QGoal, TypeIn, Goal).
2090omit_meta_qualifiers(when(Cond, QGoal), TypeIn, when(Cond, Goal)) :-
2091 callable(QGoal),
2092 !,
2093 omit_qualifier(QGoal, TypeIn, Goal).
2094omit_meta_qualifiers(G, _, G).
2095
2096
2102
2103bind_vars(Bindings0, Bindings) :-
2104 bind_query_vars(Bindings0, Bindings, SNames),
2105 bind_skel_vars(Bindings, Bindings, SNames, 1, _).
2106
2107bind_query_vars([], [], []).
2108bind_query_vars([binding(Names,Var,[Var2=Cycle])|T0],
2109 [binding(Names,Cycle,[])|T], [Name|SNames]) :-
2110 Var == Var2, 2111 !,
2112 '$last'(Names, Name),
2113 Var = '$VAR'(Name),
2114 bind_query_vars(T0, T, SNames).
2115bind_query_vars([B|T0], [B|T], AllNames) :-
2116 B = binding(Names,Var,Skel),
2117 bind_query_vars(T0, T, SNames),
2118 ( var(Var), \+ attvar(Var), Skel == []
2119 -> AllNames = [Name|SNames],
2120 '$last'(Names, Name),
2121 Var = '$VAR'(Name)
2122 ; AllNames = SNames
2123 ).
2124
2125
2126
2127bind_skel_vars([], _, _, N, N).
2128bind_skel_vars([binding(_,_,Skel)|T], Bindings, SNames, N0, N) :-
2129 bind_one_skel_vars(Skel, Bindings, SNames, N0, N1),
2130 bind_skel_vars(T, Bindings, SNames, N1, N).
2131
2148
2149bind_one_skel_vars([], _, _, N, N).
2150bind_one_skel_vars([Var=Value|T], Bindings, Names, N0, N) :-
2151 ( var(Var)
2152 -> ( '$member'(binding(Names, VVal, []), Bindings),
2153 same_term(Value, VVal)
2154 -> '$last'(Names, VName),
2155 Var = '$VAR'(VName),
2156 N2 = N0
2157 ; between(N0, infinite, N1),
2158 atom_concat('_S', N1, Name),
2159 \+ memberchk(Name, Names),
2160 !,
2161 Var = '$VAR'(Name),
2162 N2 is N1 + 1
2163 )
2164 ; N2 = N0
2165 ),
2166 bind_one_skel_vars(T, Bindings, Names, N2, N).
2167
2168
2172
2173factorize_bindings([], []).
2174factorize_bindings([Name=Value|T0], [binding(Name, Skel, Subst)|T]) :-
2175 '$factorize_term'(Value, Skel, Subst0),
2176 ( current_prolog_flag(toplevel_print_factorized, true)
2177 -> Subst = Subst0
2178 ; only_cycles(Subst0, Subst)
2179 ),
2180 factorize_bindings(T0, T).
2181
2182
2183only_cycles([], []).
2184only_cycles([B|T0], List) :-
2185 ( B = (Var=Value),
2186 Var = Value,
2187 acyclic_term(Var)
2188 -> only_cycles(T0, List)
2189 ; List = [B|T],
2190 only_cycles(T0, T)
2191 ).
2192
2193
2199
2200filter_bindings([], []).
2201filter_bindings([H0|T0], T) :-
2202 hide_vars(H0, H),
2203 ( ( arg(1, H, [])
2204 ; self_bounded(H)
2205 )
2206 -> filter_bindings(T0, T)
2207 ; T = [H|T1],
2208 filter_bindings(T0, T1)
2209 ).
2210
2211hide_vars(binding(Names0, Skel, Subst), binding(Names, Skel, Subst)) :-
2212 hide_names(Names0, Skel, Subst, Names).
2213
2214hide_names([], _, _, []).
2215hide_names([Name|T0], Skel, Subst, T) :-
2216 ( anon_var_name(Name),
2217 current_prolog_flag(toplevel_print_anon, false)
2218 -> true
2219 ; Subst == [],
2220 Skel == '$VAR'(Name)
2221 ),
2222 !,
2223 hide_names(T0, Skel, Subst, T).
2224hide_names([Name|T0], Skel, Subst, [Name|T]) :-
2225 hide_names(T0, Skel, Subst, T).
2226
2230
2231anon_var_name(Name) :-
2232 ( sub_atom(Name, 0, 1, _, '_')
2233 -> S = 1
2234 ; sub_atom(Name, 0, 1, _, P),
2235 char_type(P, prolog_symbol),
2236 sub_atom(Name, 1, 1, _, '_')
2237 -> S = 2
2238 ),
2239 sub_atom(Name, S, 1, _, Next),
2240 char_type(Next, prolog_var_start).
2241
2242self_bounded(binding([Name], Value, [])) :-
2243 Value == '$VAR'(Name).
2244
2248
2249:- if(current_prolog_flag(emscripten, true)). 2250get_respons(Action, Chp) :-
2251 '$can_yield',
2252 !,
2253 repeat,
2254 await(more, CommandS),
2255 atom_string(Command, CommandS),
2256 more_action(Command, Chp, Action),
2257 ( Action == again
2258 -> print_message(query, query(action)),
2259 fail
2260 ; !
2261 ).
2262:- endif. 2263get_respons(Action, Chp) :-
2264 repeat,
2265 flush_output(user_output),
2266 get_single_char(Code),
2267 find_more_command(Code, Command, Feedback, Style),
2268 ( Style \== '-'
2269 -> print_message(query, if_tty([ansi(Style, '~w', [Feedback])]))
2270 ; true
2271 ),
2272 more_action(Command, Chp, Action),
2273 ( Action == again
2274 -> print_message(query, query(action)),
2275 fail
2276 ; !
2277 ).
2278
2279find_more_command(-1, end_of_file, 'EOF', warning) :-
2280 !.
2281find_more_command(Code, Command, Feedback, Style) :-
2282 more_command(Command, Atom, Feedback, Style),
2283 '$in_reply'(Code, Atom),
2284 !.
2285find_more_command(Code, again, '', -) :-
2286 print_message(query, no_action(Code)).
2287
2288more_command(help, '?h', '', -).
2289more_command(redo, ';nrNR \t', ';', bold).
2290more_command(trace, 'tT', '; [trace]', comment).
2291more_command(continue, 'ca\n\ryY.', '.', bold).
2292more_command(break, 'b', '', -).
2293more_command(choicepoint, '*', '', -).
2294more_command(write, 'w', '[write]', comment).
2295more_command(print, 'p', '[print]', comment).
2296more_command(depth_inc, '+', Change, comment) :-
2297 ( print_depth(Depth0)
2298 -> depth_step(Step),
2299 NewDepth is Depth0*Step,
2300 format(atom(Change), '[max_depth(~D)]', [NewDepth])
2301 ; Change = 'no max_depth'
2302 ).
2303more_command(depth_dec, '-', Change, comment) :-
2304 ( print_depth(Depth0)
2305 -> depth_step(Step),
2306 NewDepth is max(1, Depth0//Step),
2307 format(atom(Change), '[max_depth(~D)]', [NewDepth])
2308 ; Change = '[max_depth(10)]'
2309 ).
2310
2311more_action(help, _, Action) =>
2312 Action = again,
2313 print_message(help, query(help)).
2314more_action(redo, _, Action) => 2315 Action = redo.
2316more_action(trace, _, Action) =>
2317 Action = redo,
2318 trace,
2319 save_debug.
2320more_action(continue, _, Action) => 2321 Action = continue.
2322more_action(break, _, Action) =>
2323 Action = show_again,
2324 break.
2325more_action(choicepoint, Chp, Action) =>
2326 Action = show_again,
2327 print_last_chpoint(Chp).
2328more_action(end_of_file, _, Action) =>
2329 Action = show_again,
2330 halt(0).
2331more_action(again, _, Action) =>
2332 Action = again.
2333more_action(Command, _, Action),
2334 current_prolog_flag(answer_write_options, Options0),
2335 print_predicate(Command, Options0, Options) =>
2336 Action = show_again,
2337 set_prolog_flag(answer_write_options, Options).
2338
2339print_depth(Depth) :-
2340 current_prolog_flag(answer_write_options, Options),
2341 '$option'(max_depth(Depth), Options),
2342 !.
2343
2348
2349print_predicate(write, Options0, Options) :-
2350 edit_options([-portrayed(true),-portray(true)],
2351 Options0, Options).
2352print_predicate(print, Options0, Options) :-
2353 edit_options([+portrayed(true)],
2354 Options0, Options).
2355print_predicate(depth_inc, Options0, Options) :-
2356 ( '$select'(max_depth(D0), Options0, Options1)
2357 -> depth_step(Step),
2358 D is D0*Step,
2359 Options = [max_depth(D)|Options1]
2360 ; Options = Options0
2361 ).
2362print_predicate(depth_dec, Options0, Options) :-
2363 ( '$select'(max_depth(D0), Options0, Options1)
2364 -> depth_step(Step),
2365 D is max(1, D0//Step),
2366 Options = [max_depth(D)|Options1]
2367 ; D = 10,
2368 Options = [max_depth(D)|Options0]
2369 ).
2370
2371depth_step(5).
2372
2373edit_options([], Options, Options).
2374edit_options([H|T], Options0, Options) :-
2375 edit_option(H, Options0, Options1),
2376 edit_options(T, Options1, Options).
2377
2378edit_option(-Term, Options0, Options) =>
2379 ( '$select'(Term, Options0, Options)
2380 -> true
2381 ; Options = Options0
2382 ).
2383edit_option(+Term, Options0, Options) =>
2384 functor(Term, Name, 1),
2385 functor(Var, Name, 1),
2386 ( '$select'(Var, Options0, Options1)
2387 -> Options = [Term|Options1]
2388 ; Options = [Term|Options0]
2389 ).
2390
2394
2395print_last_chpoint(Chp) :-
2396 current_predicate(print_last_choice_point/0),
2397 !,
2398 print_last_chpoint_(Chp).
2399print_last_chpoint(Chp) :-
2400 use_module(library(prolog_stack), [print_last_choicepoint/2]),
2401 print_last_chpoint_(Chp).
2402
2403print_last_chpoint_(Chp) :-
2404 print_last_choicepoint(Chp, [message_level(information)]).
2405
2406
2407 2410
2411:- user:dynamic(expand_query/4). 2412:- user:multifile(expand_query/4). 2413
2414call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :-
2415 ( '$replace_toplevel_vars'(Goal, Expanded0, Bindings, ExpandedBindings0)
2416 -> true
2417 ; Expanded0 = Goal, ExpandedBindings0 = Bindings
2418 ),
2419 ( user:expand_query(Expanded0, Expanded, ExpandedBindings0, ExpandedBindings)
2420 -> true
2421 ; Expanded = Expanded0, ExpandedBindings = ExpandedBindings0
2422 ).
2423
2424
2425:- dynamic
2426 user:expand_answer/2,
2427 prolog:expand_answer/3. 2428:- multifile
2429 user:expand_answer/2,
2430 prolog:expand_answer/3. 2431
2432call_expand_answer(Goal, BindingsIn, BindingsOut) :-
2433 ( prolog:expand_answer(Goal, BindingsIn, BindingsOut)
2434 -> true
2435 ; user:expand_answer(BindingsIn, BindingsOut)
2436 -> true
2437 ; BindingsOut = BindingsIn
2438 ),
2439 '$save_toplevel_vars'(BindingsOut),
2440 !.
2441call_expand_answer(_, Bindings, Bindings)