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 residual_goals/1, 49 (initialization)/1, 50 '$thread_init'/0, 51 (thread_initialization)/1 52 ]). 53
54
55 58
59:- dynamic
60 prolog:version_msg/1. 61
66
67version :-
68 print_message(banner, welcome).
69
73
74:- multifile
75 system:term_expansion/2. 76
77system:term_expansion((:- version(Message)),
78 prolog:version_msg(Message)).
79
80version(Message) :-
81 ( prolog:version_msg(Message)
82 -> true
83 ; assertz(prolog:version_msg(Message))
84 ).
85
86
87 90
97
98load_init_file :-
99 '$cmd_option_val'(init_file, OsFile),
100 !,
101 prolog_to_os_filename(File, OsFile),
102 load_init_file(File, explicit).
103load_init_file :-
104 load_init_file('init.pl', implicit).
105
109
110:- dynamic
111 loaded_init_file/2. 112
113load_init_file(none, _) :- !.
114load_init_file(Base, _) :-
115 loaded_init_file(Base, _),
116 !.
117load_init_file(InitFile, explicit) :-
118 exists_file(InitFile),
119 !,
120 ensure_loaded(user:InitFile).
121load_init_file(Base, _) :-
122 absolute_file_name(user_app_config(Base), InitFile,
123 [ access(read),
124 file_errors(fail)
125 ]),
126 asserta(loaded_init_file(Base, InitFile)),
127 load_files(user:InitFile,
128 [ scope_settings(false)
129 ]).
130load_init_file('init.pl', implicit) :-
131 ( current_prolog_flag(windows, true),
132 absolute_file_name(user_profile('swipl.ini'), InitFile,
133 [ access(read),
134 file_errors(fail)
135 ])
136 ; expand_file_name('~/.swiplrc', [InitFile]),
137 exists_file(InitFile)
138 ),
139 !,
140 print_message(warning, backcomp(init_file_moved(InitFile))).
141load_init_file(_, _).
142
143'$load_system_init_file' :-
144 loaded_init_file(system, _),
145 !.
146'$load_system_init_file' :-
147 '$cmd_option_val'(system_init_file, Base),
148 Base \== none,
149 current_prolog_flag(home, Home),
150 file_name_extension(Base, rc, Name),
151 atomic_list_concat([Home, '/', Name], File),
152 absolute_file_name(File, Path,
153 [ file_type(prolog),
154 access(read),
155 file_errors(fail)
156 ]),
157 asserta(loaded_init_file(system, Path)),
158 load_files(user:Path,
159 [ silent(true),
160 scope_settings(false)
161 ]),
162 !.
163'$load_system_init_file'.
164
165'$load_script_file' :-
166 loaded_init_file(script, _),
167 !.
168'$load_script_file' :-
169 '$cmd_option_val'(script_file, OsFiles),
170 load_script_files(OsFiles).
171
172load_script_files([]).
173load_script_files([OsFile|More]) :-
174 prolog_to_os_filename(File, OsFile),
175 ( absolute_file_name(File, Path,
176 [ file_type(prolog),
177 access(read),
178 file_errors(fail)
179 ])
180 -> asserta(loaded_init_file(script, Path)),
181 load_files(user:Path, []),
182 load_files(More)
183 ; throw(error(existence_error(script_file, File), _))
184 ).
185
186
187 190
191:- meta_predicate
192 initialization(0). 193
194:- '$iso'((initialization)/1). 195
202
203initialization(Goal) :-
204 Goal = _:G,
205 prolog:initialize_now(G, Use),
206 !,
207 print_message(warning, initialize_now(G, Use)),
208 initialization(Goal, now).
209initialization(Goal) :-
210 initialization(Goal, after_load).
211
212:- multifile
213 prolog:initialize_now/2,
214 prolog:message//1. 215
216prolog:initialize_now(load_foreign_library(_),
217 'use :- use_foreign_library/1 instead').
218prolog:initialize_now(load_foreign_library(_,_),
219 'use :- use_foreign_library/2 instead').
220
221prolog:message(initialize_now(Goal, Use)) -->
222 [ 'Initialization goal ~p will be executed'-[Goal],nl,
223 'immediately for backward compatibility reasons', nl,
224 '~w'-[Use]
225 ].
226
227'$run_initialization' :-
228 '$run_initialization'(_, []),
229 '$thread_init'.
230
235
236initialize :-
237 forall('$init_goal'(when(program), Goal, Ctx),
238 run_initialize(Goal, Ctx)).
239
240run_initialize(Goal, Ctx) :-
241 ( catch(Goal, E, true),
242 ( var(E)
243 -> true
244 ; throw(error(initialization_error(E, Goal, Ctx), _))
245 )
246 ; throw(error(initialization_error(failed, Goal, Ctx), _))
247 ).
248
249
250 253
254:- meta_predicate
255 thread_initialization(0). 256:- dynamic
257 '$at_thread_initialization'/1. 258
262
263thread_initialization(Goal) :-
264 assert('$at_thread_initialization'(Goal)),
265 call(Goal),
266 !.
267
268'$thread_init' :-
269 ( '$at_thread_initialization'(Goal),
270 ( call(Goal)
271 -> fail
272 ; fail
273 )
274 ; true
275 ).
276
277
278 281
285
286'$set_file_search_paths' :-
287 '$cmd_option_val'(search_paths, Paths),
288 ( '$member'(Path, Paths),
289 atom_chars(Path, Chars),
290 ( phrase('$search_path'(Name, Aliases), Chars)
291 -> '$reverse'(Aliases, Aliases1),
292 forall('$member'(Alias, Aliases1),
293 asserta(user:file_search_path(Name, Alias)))
294 ; print_message(error, commandline_arg_type(p, Path))
295 ),
296 fail ; true
297 ).
298
299'$search_path'(Name, Aliases) -->
300 '$string'(NameChars),
301 [=],
302 !,
303 {atom_chars(Name, NameChars)},
304 '$search_aliases'(Aliases).
305
306'$search_aliases'([Alias|More]) -->
307 '$string'(AliasChars),
308 path_sep,
309 !,
310 { '$make_alias'(AliasChars, Alias) },
311 '$search_aliases'(More).
312'$search_aliases'([Alias]) -->
313 '$string'(AliasChars),
314 '$eos',
315 !,
316 { '$make_alias'(AliasChars, Alias) }.
317
318path_sep -->
319 { current_prolog_flag(windows, true)
320 },
321 !,
322 [;].
323path_sep -->
324 [:].
325
326'$string'([]) --> [].
327'$string'([H|T]) --> [H], '$string'(T).
328
329'$eos'([], []).
330
331'$make_alias'(Chars, Alias) :-
332 catch(term_to_atom(Alias, Chars), _, fail),
333 ( atom(Alias)
334 ; functor(Alias, F, 1),
335 F \== /
336 ),
337 !.
338'$make_alias'(Chars, Alias) :-
339 atom_chars(Alias, Chars).
340
341
342 345
349
350argv_files(Files) :-
351 current_prolog_flag(argv, Argv),
352 no_option_files(Argv, Argv1, Files, ScriptArgs),
353 ( ( ScriptArgs == true
354 ; Argv1 == []
355 )
356 -> ( Argv1 \== Argv
357 -> set_prolog_flag(argv, Argv1)
358 ; true
359 )
360 ; '$usage',
361 halt(1)
362 ).
363
364no_option_files([--|Argv], Argv, [], true) :- !.
365no_option_files([Opt|_], _, _, ScriptArgs) :-
366 ScriptArgs \== true,
367 sub_atom(Opt, 0, _, _, '-'),
368 !,
369 '$usage',
370 halt(1).
371no_option_files([OsFile|Argv0], Argv, [File|T], ScriptArgs) :-
372 file_name_extension(_, Ext, OsFile),
373 user:prolog_file_type(Ext, prolog),
374 !,
375 ScriptArgs = true,
376 prolog_to_os_filename(File, OsFile),
377 no_option_files(Argv0, Argv, T, ScriptArgs).
378no_option_files([OsScript|Argv], Argv, [Script], ScriptArgs) :-
379 ScriptArgs \== true,
380 !,
381 prolog_to_os_filename(Script, OsScript),
382 ( exists_file(Script)
383 -> true
384 ; '$existence_error'(file, Script)
385 ),
386 ScriptArgs = true.
387no_option_files(Argv, Argv, [], _).
388
389clean_argv :-
390 ( current_prolog_flag(argv, [--|Argv])
391 -> set_prolog_flag(argv, Argv)
392 ; true
393 ).
394
401
402associated_files([]) :-
403 current_prolog_flag(saved_program_class, runtime),
404 !,
405 clean_argv.
406associated_files(Files) :-
407 '$set_prolog_file_extension',
408 argv_files(Files),
409 ( Files = [File|_]
410 -> absolute_file_name(File, AbsFile),
411 set_prolog_flag(associated_file, AbsFile),
412 set_working_directory(File),
413 set_window_title(Files)
414 ; true
415 ).
416
424
425set_working_directory(File) :-
426 current_prolog_flag(console_menu, true),
427 access_file(File, read),
428 !,
429 file_directory_name(File, Dir),
430 working_directory(_, Dir).
431set_working_directory(_).
432
433set_window_title([File|More]) :-
434 current_predicate(system:window_title/2),
435 !,
436 ( More == []
437 -> Extra = []
438 ; Extra = ['...']
439 ),
440 atomic_list_concat(['SWI-Prolog --', File | Extra], ' ', Title),
441 system:window_title(_, Title).
442set_window_title(_).
443
444
449
450start_pldoc :-
451 '$cmd_option_val'(pldoc_server, Server),
452 ( Server == ''
453 -> call((doc_server(_), doc_browser))
454 ; catch(atom_number(Server, Port), _, fail)
455 -> call(doc_server(Port))
456 ; print_message(error, option_usage(pldoc)),
457 halt(1)
458 ).
459start_pldoc.
460
461
465
466load_associated_files(Files) :-
467 ( '$member'(File, Files),
468 load_files(user:File, [expand(false)]),
469 fail
470 ; true
471 ).
472
473hkey('HKEY_CURRENT_USER/Software/SWI/Prolog').
474hkey('HKEY_LOCAL_MACHINE/Software/SWI/Prolog').
475
476'$set_prolog_file_extension' :-
477 current_prolog_flag(windows, true),
478 hkey(Key),
479 catch(win_registry_get_value(Key, fileExtension, Ext0),
480 _, fail),
481 !,
482 ( atom_concat('.', Ext, Ext0)
483 -> true
484 ; Ext = Ext0
485 ),
486 ( user:prolog_file_type(Ext, prolog)
487 -> true
488 ; asserta(user:prolog_file_type(Ext, prolog))
489 ).
490'$set_prolog_file_extension'.
491
492
493 496
502
503'$initialise' :-
504 catch(initialise_prolog, E, initialise_error(E)).
505
506initialise_error('$aborted') :- !.
507initialise_error(E) :-
508 print_message(error, initialization_exception(E)),
509 fail.
510
511initialise_prolog :-
512 '$clean_history',
513 apple_setup_app,
514 '$run_initialization',
515 '$load_system_init_file',
516 set_toplevel,
517 '$set_file_search_paths',
518 init_debug_flags,
519 start_pldoc,
520 opt_attach_packs,
521 load_init_file,
522 catch(setup_colors, E, print_message(warning, E)),
523 associated_files(Files),
524 '$load_script_file',
525 load_associated_files(Files),
526 '$cmd_option_val'(goals, Goals),
527 ( Goals == [],
528 \+ '$init_goal'(when(_), _, _)
529 -> version 530 ; run_init_goals(Goals),
531 ( load_only
532 -> version
533 ; run_program_init,
534 run_main_init
535 )
536 ).
537
538:- if(current_prolog_flag(apple,true)). 539apple_set_working_directory :-
540 ( expand_file_name('~', [Dir]),
541 exists_directory(Dir)
542 -> working_directory(_, Dir)
543 ; true
544 ).
545
546apple_set_locale :-
547 ( getenv('LC_CTYPE', 'UTF-8'),
548 apple_current_locale_identifier(LocaleID),
549 atom_concat(LocaleID, '.UTF-8', Locale),
550 catch(setlocale(ctype, _Old, Locale), _, fail)
551 -> setenv('LANG', Locale),
552 unsetenv('LC_CTYPE')
553 ; true
554 ).
555
556apple_setup_app :-
557 current_prolog_flag(apple, true),
558 current_prolog_flag(console_menu, true), 559 apple_set_working_directory,
560 apple_set_locale.
561:- endif. 562apple_setup_app.
563
564opt_attach_packs :-
565 current_prolog_flag(packs, true),
566 !,
567 attach_packs.
568opt_attach_packs.
569
570set_toplevel :-
571 '$cmd_option_val'(toplevel, TopLevelAtom),
572 catch(term_to_atom(TopLevel, TopLevelAtom), E,
573 (print_message(error, E),
574 halt(1))),
575 create_prolog_flag(toplevel_goal, TopLevel, [type(term)]).
576
577load_only :-
578 current_prolog_flag(os_argv, OSArgv),
579 memberchk('-l', OSArgv),
580 current_prolog_flag(argv, Argv),
581 \+ memberchk('-l', Argv).
582
587
588run_init_goals([]).
589run_init_goals([H|T]) :-
590 run_init_goal(H),
591 run_init_goals(T).
592
593run_init_goal(Text) :-
594 catch(term_to_atom(Goal, Text), E,
595 ( print_message(error, init_goal_syntax(E, Text)),
596 halt(2)
597 )),
598 run_init_goal(Goal, Text).
599
603
604run_program_init :-
605 forall('$init_goal'(when(program), Goal, Ctx),
606 run_init_goal(Goal, @(Goal,Ctx))).
607
608run_main_init :-
609 findall(Goal-Ctx, '$init_goal'(when(main), Goal, Ctx), Pairs),
610 '$last'(Pairs, Goal-Ctx),
611 !,
612 ( current_prolog_flag(toplevel_goal, default)
613 -> set_prolog_flag(toplevel_goal, halt)
614 ; true
615 ),
616 run_init_goal(Goal, @(Goal,Ctx)).
617run_main_init.
618
619run_init_goal(Goal, Ctx) :-
620 ( catch_with_backtrace(user:Goal, E, true)
621 -> ( var(E)
622 -> true
623 ; print_message(error, init_goal_failed(E, Ctx)),
624 halt(2)
625 )
626 ; ( current_prolog_flag(verbose, silent)
627 -> Level = silent
628 ; Level = error
629 ),
630 print_message(Level, init_goal_failed(failed, Ctx)),
631 halt(1)
632 ).
633
638
639init_debug_flags :-
640 once(print_predicate(_, [print], PrintOptions)),
641 Keep = [keep(true)],
642 create_prolog_flag(answer_write_options, PrintOptions, Keep),
643 create_prolog_flag(prompt_alternatives_on, determinism, Keep),
644 create_prolog_flag(toplevel_extra_white_line, true, Keep),
645 create_prolog_flag(toplevel_print_factorized, false, Keep),
646 create_prolog_flag(print_write_options,
647 [ portray(true), quoted(true), numbervars(true) ],
648 Keep),
649 create_prolog_flag(toplevel_residue_vars, false, Keep),
650 create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
651 '$set_debugger_write_options'(print).
652
656
657setup_backtrace :-
658 ( \+ current_prolog_flag(backtrace, false),
659 load_setup_file(library(prolog_stack))
660 -> true
661 ; true
662 ).
663
667
668setup_colors :-
669 ( \+ current_prolog_flag(color_term, false),
670 stream_property(user_input, tty(true)),
671 stream_property(user_error, tty(true)),
672 stream_property(user_output, tty(true)),
673 \+ getenv('TERM', dumb),
674 load_setup_file(user:library(ansi_term))
675 -> true
676 ; true
677 ).
678
682
683setup_history :-
684 ( \+ current_prolog_flag(save_history, false),
685 stream_property(user_input, tty(true)),
686 \+ current_prolog_flag(readline, false),
687 load_setup_file(library(prolog_history))
688 -> prolog_history(enable)
689 ; true
690 ),
691 set_default_history,
692 '$load_history'.
693
697
698setup_readline :-
699 ( current_prolog_flag(readline, swipl_win)
700 -> true
701 ; stream_property(user_input, tty(true)),
702 current_prolog_flag(tty_control, true),
703 \+ getenv('TERM', dumb),
704 ( current_prolog_flag(readline, ReadLine)
705 -> true
706 ; ReadLine = true
707 ),
708 readline_library(ReadLine, Library),
709 load_setup_file(library(Library))
710 -> set_prolog_flag(readline, Library)
711 ; set_prolog_flag(readline, false)
712 ).
713
714readline_library(true, Library) :-
715 !,
716 preferred_readline(Library).
717readline_library(false, _) :-
718 !,
719 fail.
720readline_library(Library, Library).
721
722preferred_readline(editline).
723preferred_readline(readline).
724
728
729load_setup_file(File) :-
730 catch(load_files(File,
731 [ silent(true),
732 if(not_loaded)
733 ]), _, fail).
734
735
736:- '$hide'('$toplevel'/0). 737
741
742'$toplevel' :-
743 '$runtoplevel',
744 print_message(informational, halt).
745
753
754'$runtoplevel' :-
755 current_prolog_flag(toplevel_goal, TopLevel0),
756 toplevel_goal(TopLevel0, TopLevel),
757 user:TopLevel.
758
759:- dynamic setup_done/0. 760:- volatile setup_done/0. 761
762toplevel_goal(default, '$query_loop') :-
763 !,
764 setup_interactive.
765toplevel_goal(prolog, '$query_loop') :-
766 !,
767 setup_interactive.
768toplevel_goal(Goal, Goal).
769
770setup_interactive :-
771 setup_done,
772 !.
773setup_interactive :-
774 asserta(setup_done),
775 catch(setup_backtrace, E, print_message(warning, E)),
776 catch(setup_readline, E, print_message(warning, E)),
777 catch(setup_history, E, print_message(warning, E)).
778
782
783'$compile' :-
784 ( catch('$compile_', E, (print_message(error, E), halt(1)))
785 -> true
786 ; print_message(error, error(goal_failed('$compile'), _)),
787 halt(1)
788 ),
789 halt. 790
791'$compile_' :-
792 '$load_system_init_file',
793 catch(setup_colors, _, true),
794 '$set_file_search_paths',
795 init_debug_flags,
796 '$run_initialization',
797 opt_attach_packs,
798 use_module(library(qsave)),
799 qsave:qsave_toplevel.
800
804
805'$config' :-
806 '$load_system_init_file',
807 '$set_file_search_paths',
808 init_debug_flags,
809 '$run_initialization',
810 load_files(library(prolog_config)),
811 ( catch(prolog_dump_runtime_variables, E,
812 (print_message(error, E), halt(1)))
813 -> true
814 ; print_message(error, error(goal_failed(prolog_dump_runtime_variables),_))
815 ).
816
817
818 821
827
828prolog :-
829 break.
830
831:- create_prolog_flag(toplevel_mode, backtracking, []). 832
839
840'$query_loop' :-
841 current_prolog_flag(toplevel_mode, recursive),
842 !,
843 break_level(Level),
844 read_expanded_query(Level, Query, Bindings),
845 ( Query == end_of_file
846 -> print_message(query, query(eof))
847 ; '$call_no_catch'('$execute_query'(Query, Bindings, _)),
848 ( current_prolog_flag(toplevel_mode, recursive)
849 -> '$query_loop'
850 ; '$switch_toplevel_mode'(backtracking),
851 '$query_loop' 852 )
853 ).
854'$query_loop' :-
855 break_level(BreakLev),
856 repeat,
857 read_expanded_query(BreakLev, Query, Bindings),
858 ( Query == end_of_file
859 -> !, print_message(query, query(eof))
860 ; '$execute_query'(Query, Bindings, _),
861 ( current_prolog_flag(toplevel_mode, recursive)
862 -> !,
863 '$switch_toplevel_mode'(recursive),
864 '$query_loop'
865 ; fail
866 )
867 ).
868
869break_level(BreakLev) :-
870 ( current_prolog_flag(break_level, BreakLev)
871 -> true
872 ; BreakLev = -1
873 ).
874
875read_expanded_query(BreakLev, ExpandedQuery, ExpandedBindings) :-
876 '$current_typein_module'(TypeIn),
877 ( stream_property(user_input, tty(true))
878 -> '$system_prompt'(TypeIn, BreakLev, Prompt),
879 prompt(Old, '| ')
880 ; Prompt = '',
881 prompt(Old, '')
882 ),
883 trim_stacks,
884 trim_heap,
885 repeat,
886 read_query(Prompt, Query, Bindings),
887 prompt(_, Old),
888 catch(call_expand_query(Query, ExpandedQuery,
889 Bindings, ExpandedBindings),
890 Error,
891 (print_message(error, Error), fail)),
892 !.
893
894
900
901:- if(current_prolog_flag(emscripten, true)). 902read_query(_Prompt, Goal, Bindings) :-
903 '$can_yield',
904 !,
905 await(goal, GoalString),
906 term_string(Goal, GoalString, [variable_names(Bindings)]).
907:- endif. 908read_query(Prompt, Goal, Bindings) :-
909 current_prolog_flag(history, N),
910 integer(N), N > 0,
911 !,
912 read_term_with_history(
913 Goal,
914 [ show(h),
915 help('!h'),
916 no_save([trace, end_of_file]),
917 prompt(Prompt),
918 variable_names(Bindings)
919 ]).
920read_query(Prompt, Goal, Bindings) :-
921 remove_history_prompt(Prompt, Prompt1),
922 repeat, 923 prompt1(Prompt1),
924 read_query_line(user_input, Line),
925 '$save_history_line'(Line), 926 '$current_typein_module'(TypeIn),
927 catch(read_term_from_atom(Line, Goal,
928 [ variable_names(Bindings),
929 module(TypeIn)
930 ]), E,
931 ( print_message(error, E),
932 fail
933 )),
934 !,
935 '$save_history_event'(Line). 936
938
939read_query_line(Input, Line) :-
940 stream_property(Input, error(true)),
941 !,
942 Line = end_of_file.
943read_query_line(Input, Line) :-
944 catch(read_term_as_atom(Input, Line), Error, true),
945 save_debug_after_read,
946 ( var(Error)
947 -> true
948 ; catch(print_message(error, Error), _, true),
949 ( Error = error(syntax_error(_),_)
950 -> fail
951 ; throw(Error)
952 )
953 ).
954
959
960read_term_as_atom(In, Line) :-
961 '$raw_read'(In, Line),
962 ( Line == end_of_file
963 -> true
964 ; skip_to_nl(In)
965 ).
966
971
972skip_to_nl(In) :-
973 repeat,
974 peek_char(In, C),
975 ( C == '%'
976 -> skip(In, '\n')
977 ; char_type(C, space)
978 -> get_char(In, _),
979 C == '\n'
980 ; true
981 ),
982 !.
983
984remove_history_prompt('', '') :- !.
985remove_history_prompt(Prompt0, Prompt) :-
986 atom_chars(Prompt0, Chars0),
987 clean_history_prompt_chars(Chars0, Chars1),
988 delete_leading_blanks(Chars1, Chars),
989 atom_chars(Prompt, Chars).
990
991clean_history_prompt_chars([], []).
992clean_history_prompt_chars(['~', !|T], T) :- !.
993clean_history_prompt_chars([H|T0], [H|T]) :-
994 clean_history_prompt_chars(T0, T).
995
996delete_leading_blanks([' '|T0], T) :-
997 !,
998 delete_leading_blanks(T0, T).
999delete_leading_blanks(L, L).
1000
1001
1007
1008set_default_history :-
1009 current_prolog_flag(history, _),
1010 !.
1011set_default_history :-
1012 ( ( \+ current_prolog_flag(readline, false)
1013 ; current_prolog_flag(emacs_inferior_process, true)
1014 )
1015 -> create_prolog_flag(history, 0, [])
1016 ; create_prolog_flag(history, 25, [])
1017 ).
1018
1019
1020 1023
1036
1037save_debug_after_read :-
1038 current_prolog_flag(debug, true),
1039 !,
1040 save_debug.
1041save_debug_after_read.
1042
1043save_debug :-
1044 ( tracing,
1045 notrace
1046 -> Tracing = true
1047 ; Tracing = false
1048 ),
1049 current_prolog_flag(debug, Debugging),
1050 set_prolog_flag(debug, false),
1051 create_prolog_flag(query_debug_settings,
1052 debug(Debugging, Tracing), []).
1053
1054restore_debug :-
1055 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)),
1056 set_prolog_flag(debug, Debugging),
1057 ( Tracing == true
1058 -> trace
1059 ; true
1060 ).
1061
1062:- initialization
1063 create_prolog_flag(query_debug_settings, debug(false, false), []). 1064
1065
1066 1069
1070'$system_prompt'(Module, BrekLev, Prompt) :-
1071 current_prolog_flag(toplevel_prompt, PAtom),
1072 atom_codes(PAtom, P0),
1073 ( Module \== user
1074 -> '$substitute'('~m', [Module, ': '], P0, P1)
1075 ; '$substitute'('~m', [], P0, P1)
1076 ),
1077 ( BrekLev > 0
1078 -> '$substitute'('~l', ['[', BrekLev, '] '], P1, P2)
1079 ; '$substitute'('~l', [], P1, P2)
1080 ),
1081 current_prolog_flag(query_debug_settings, debug(Debugging, Tracing)),
1082 ( Tracing == true
1083 -> '$substitute'('~d', ['[trace] '], P2, P3)
1084 ; Debugging == true
1085 -> '$substitute'('~d', ['[debug] '], P2, P3)
1086 ; '$substitute'('~d', [], P2, P3)
1087 ),
1088 atom_chars(Prompt, P3).
1089
1090'$substitute'(From, T, Old, New) :-
1091 atom_codes(From, FromCodes),
1092 phrase(subst_chars(T), T0),
1093 '$append'(Pre, S0, Old),
1094 '$append'(FromCodes, Post, S0) ->
1095 '$append'(Pre, T0, S1),
1096 '$append'(S1, Post, New),
1097 !.
1098'$substitute'(_, _, Old, Old).
1099
1100subst_chars([]) -->
1101 [].
1102subst_chars([H|T]) -->
1103 { atomic(H),
1104 !,
1105 atom_codes(H, Codes)
1106 },
1107 Codes,
1108 subst_chars(T).
1109subst_chars([H|T]) -->
1110 H,
1111 subst_chars(T).
1112
1113
1114 1117
1121
1122'$execute_query'(Var, _, true) :-
1123 var(Var),
1124 !,
1125 print_message(informational, var_query(Var)).
1126'$execute_query'(Goal, Bindings, Truth) :-
1127 '$current_typein_module'(TypeIn),
1128 '$dwim_correct_goal'(TypeIn:Goal, Bindings, Corrected),
1129 !,
1130 setup_call_cleanup(
1131 '$set_source_module'(M0, TypeIn),
1132 expand_goal(Corrected, Expanded),
1133 '$set_source_module'(M0)),
1134 print_message(silent, toplevel_goal(Expanded, Bindings)),
1135 '$execute_goal2'(Expanded, Bindings, Truth).
1136'$execute_query'(_, _, false) :-
1137 notrace,
1138 print_message(query, query(no)).
1139
1140'$execute_goal2'(Goal, Bindings, true) :-
1141 restore_debug,
1142 '$current_typein_module'(TypeIn),
1143 residue_vars(TypeIn:Goal, Vars, TypeIn:Delays, Chp),
1144 deterministic(Det),
1145 ( save_debug
1146 ; restore_debug, fail
1147 ),
1148 flush_output(user_output),
1149 ( Det == true
1150 -> DetOrChp = true
1151 ; DetOrChp = Chp
1152 ),
1153 call_expand_answer(Bindings, NewBindings),
1154 ( \+ \+ write_bindings(NewBindings, Vars, Delays, DetOrChp)
1155 -> !
1156 ).
1157'$execute_goal2'(_, _, false) :-
1158 save_debug,
1159 print_message(query, query(no)).
1160
1161residue_vars(Goal, Vars, Delays, Chp) :-
1162 current_prolog_flag(toplevel_residue_vars, true),
1163 !,
1164 '$wfs_call'(call_residue_vars(stop_backtrace(Goal, Chp), Vars), Delays).
1165residue_vars(Goal, [], Delays, Chp) :-
1166 '$wfs_call'(stop_backtrace(Goal, Chp), Delays).
1167
1168stop_backtrace(Goal, Chp) :-
1169 toplevel_call(Goal),
1170 prolog_current_choice(Chp).
1171
1172toplevel_call(Goal) :-
1173 call(Goal),
1174 no_lco.
1175
1176no_lco.
1177
1191
1192write_bindings(Bindings, ResidueVars, Delays, DetOrChp) :-
1193 '$current_typein_module'(TypeIn),
1194 translate_bindings(Bindings, Bindings1, ResidueVars, TypeIn:Residuals),
1195 omit_qualifier(Delays, TypeIn, Delays1),
1196 name_vars(Bindings1, Residuals, Delays1),
1197 write_bindings2(Bindings1, Residuals, Delays1, DetOrChp).
1198
1199write_bindings2([], Residuals, Delays, _) :-
1200 current_prolog_flag(prompt_alternatives_on, groundness),
1201 !,
1202 print_message(query, query(yes(Delays, Residuals))).
1203write_bindings2(Bindings, Residuals, Delays, true) :-
1204 current_prolog_flag(prompt_alternatives_on, determinism),
1205 !,
1206 print_message(query, query(yes(Bindings, Delays, Residuals))).
1207write_bindings2(Bindings, Residuals, Delays, Chp) :-
1208 repeat,
1209 print_message(query, query(more(Bindings, Delays, Residuals))),
1210 get_respons(Action, Chp),
1211 ( Action == redo
1212 -> !, fail
1213 ; Action == show_again
1214 -> fail
1215 ; !,
1216 print_message(query, query(done))
1217 ).
1218
1219name_vars(Bindings, Residuals, Delays) :-
1220 current_prolog_flag(toplevel_name_variables, true),
1221 !,
1222 '$term_multitons'(t(Bindings,Residuals,Delays), Vars),
1223 name_vars_(Vars, Bindings, 0),
1224 term_variables(t(Bindings,Residuals,Delays), SVars),
1225 anon_vars(SVars).
1226name_vars(_Bindings, _Residuals, _Delays).
1227
1228name_vars_([], _, _).
1229name_vars_([H|T], Bindings, N) :-
1230 name_var(Bindings, Name, N, N1),
1231 H = '$VAR'(Name),
1232 name_vars_(T, Bindings, N1).
1233
1234anon_vars([]).
1235anon_vars(['$VAR'('_')|T]) :-
1236 anon_vars(T).
1237
1238name_var(Bindings, Name, N0, N) :-
1239 between(N0, infinite, N1),
1240 I is N1//26,
1241 J is 0'A + N1 mod 26,
1242 ( I == 0
1243 -> format(atom(Name), '_~c', [J])
1244 ; format(atom(Name), '_~c~d', [J, I])
1245 ),
1246 ( current_prolog_flag(toplevel_print_anon, false)
1247 -> true
1248 ; \+ is_bound(Bindings, Name)
1249 ),
1250 !,
1251 N is N1+1.
1252
1253is_bound([Vars=_|T], Name) :-
1254 ( in_vars(Vars, Name)
1255 -> true
1256 ; is_bound(T, Name)
1257 ).
1258
1259in_vars(Name, Name) :- !.
1260in_vars(Names, Name) :-
1261 '$member'(Name, Names).
1262
1267
1268:- multifile
1269 residual_goal_collector/1. 1270
1271:- meta_predicate
1272 residual_goals(2). 1273
1274residual_goals(NonTerminal) :-
1275 throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)).
1276
1277system:term_expansion((:- residual_goals(NonTerminal)),
1278 '$toplevel':residual_goal_collector(M2:Head)) :-
1279 \+ current_prolog_flag(xref, true),
1280 prolog_load_context(module, M),
1281 strip_module(M:NonTerminal, M2, Head),
1282 '$must_be'(callable, Head).
1283
1288
1289:- public prolog:residual_goals//0. 1290
1291prolog:residual_goals -->
1292 { findall(NT, residual_goal_collector(NT), NTL) },
1293 collect_residual_goals(NTL).
1294
1295collect_residual_goals([]) --> [].
1296collect_residual_goals([H|T]) -->
1297 ( call(H) -> [] ; [] ),
1298 collect_residual_goals(T).
1299
1300
1301
1322
1323:- public
1324 prolog:translate_bindings/5. 1325:- meta_predicate
1326 prolog:translate_bindings(+, -, +, +, :). 1327
1328prolog:translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals) :-
1329 translate_bindings(Bindings0, Bindings, ResVars, ResGoals, Residuals).
1330
1331translate_bindings(Bindings0, Bindings, ResidueVars, Residuals) :-
1332 prolog:residual_goals(ResidueGoals, []),
1333 translate_bindings(Bindings0, Bindings, ResidueVars, ResidueGoals,
1334 Residuals).
1335
1336translate_bindings(Bindings0, Bindings, [], [], _:[]-[]) :-
1337 term_attvars(Bindings0, []),
1338 !,
1339 join_same_bindings(Bindings0, Bindings1),
1340 factorize_bindings(Bindings1, Bindings2),
1341 bind_vars(Bindings2, Bindings3),
1342 filter_bindings(Bindings3, Bindings).
1343translate_bindings(Bindings0, Bindings, ResidueVars, ResGoals0,
1344 TypeIn:Residuals-HiddenResiduals) :-
1345 project_constraints(Bindings0, ResidueVars),
1346 hidden_residuals(ResidueVars, Bindings0, HiddenResiduals0),
1347 omit_qualifiers(HiddenResiduals0, TypeIn, HiddenResiduals),
1348 copy_term(Bindings0+ResGoals0, Bindings1+ResGoals1, Residuals0),
1349 '$append'(ResGoals1, Residuals0, Residuals1),
1350 omit_qualifiers(Residuals1, TypeIn, Residuals),
1351 join_same_bindings(Bindings1, Bindings2),
1352 factorize_bindings(Bindings2, Bindings3),
1353 bind_vars(Bindings3, Bindings4),
1354 filter_bindings(Bindings4, Bindings).
1355
1356hidden_residuals(ResidueVars, Bindings, Goal) :-
1357 term_attvars(ResidueVars, Remaining),
1358 term_attvars(Bindings, QueryVars),
1359 subtract_vars(Remaining, QueryVars, HiddenVars),
1360 copy_term(HiddenVars, _, Goal).
1361
1362subtract_vars(All, Subtract, Remaining) :-
1363 sort(All, AllSorted),
1364 sort(Subtract, SubtractSorted),
1365 ord_subtract(AllSorted, SubtractSorted, Remaining).
1366
1367ord_subtract([], _Not, []).
1368ord_subtract([H1|T1], L2, Diff) :-
1369 diff21(L2, H1, T1, Diff).
1370
1371diff21([], H1, T1, [H1|T1]).
1372diff21([H2|T2], H1, T1, Diff) :-
1373 compare(Order, H1, H2),
1374 diff3(Order, H1, T1, H2, T2, Diff).
1375
1376diff12([], _H2, _T2, []).
1377diff12([H1|T1], H2, T2, Diff) :-
1378 compare(Order, H1, H2),
1379 diff3(Order, H1, T1, H2, T2, Diff).
1380
1381diff3(<, H1, T1, H2, T2, [H1|Diff]) :-
1382 diff12(T1, H2, T2, Diff).
1383diff3(=, _H1, T1, _H2, T2, Diff) :-
1384 ord_subtract(T1, T2, Diff).
1385diff3(>, H1, T1, _H2, T2, Diff) :-
1386 diff21(T2, H1, T1, Diff).
1387
1388
1393
1394project_constraints(Bindings, ResidueVars) :-
1395 !,
1396 term_attvars(Bindings, AttVars),
1397 phrase(attribute_modules(AttVars), Modules0),
1398 sort(Modules0, Modules),
1399 term_variables(Bindings, QueryVars),
1400 project_attributes(Modules, QueryVars, ResidueVars).
1401project_constraints(_, _).
1402
1403project_attributes([], _, _).
1404project_attributes([M|T], QueryVars, ResidueVars) :-
1405 ( current_predicate(M:project_attributes/2),
1406 catch(M:project_attributes(QueryVars, ResidueVars), E,
1407 print_message(error, E))
1408 -> true
1409 ; true
1410 ),
1411 project_attributes(T, QueryVars, ResidueVars).
1412
1413attribute_modules([]) --> [].
1414attribute_modules([H|T]) -->
1415 { get_attrs(H, Attrs) },
1416 attrs_modules(Attrs),
1417 attribute_modules(T).
1418
1419attrs_modules([]) --> [].
1420attrs_modules(att(Module, _, More)) -->
1421 [Module],
1422 attrs_modules(More).
1423
1424
1432
1433join_same_bindings([], []).
1434join_same_bindings([Name=V0|T0], [[Name|Names]=V|T]) :-
1435 take_same_bindings(T0, V0, V, Names, T1),
1436 join_same_bindings(T1, T).
1437
1438take_same_bindings([], Val, Val, [], []).
1439take_same_bindings([Name=V1|T0], V0, V, [Name|Names], T) :-
1440 V0 == V1,
1441 !,
1442 take_same_bindings(T0, V1, V, Names, T).
1443take_same_bindings([Pair|T0], V0, V, Names, [Pair|T]) :-
1444 take_same_bindings(T0, V0, V, Names, T).
1445
1446
1451
1452
1453omit_qualifiers([], _, []).
1454omit_qualifiers([Goal0|Goals0], TypeIn, [Goal|Goals]) :-
1455 omit_qualifier(Goal0, TypeIn, Goal),
1456 omit_qualifiers(Goals0, TypeIn, Goals).
1457
1458omit_qualifier(M:G0, TypeIn, G) :-
1459 M == TypeIn,
1460 !,
1461 omit_meta_qualifiers(G0, TypeIn, G).
1462omit_qualifier(M:G0, TypeIn, G) :-
1463 predicate_property(TypeIn:G0, imported_from(M)),
1464 \+ predicate_property(G0, transparent),
1465 !,
1466 G0 = G.
1467omit_qualifier(_:G0, _, G) :-
1468 predicate_property(G0, built_in),
1469 \+ predicate_property(G0, transparent),
1470 !,
1471 G0 = G.
1472omit_qualifier(M:G0, _, M:G) :-
1473 atom(M),
1474 !,
1475 omit_meta_qualifiers(G0, M, G).
1476omit_qualifier(G0, TypeIn, G) :-
1477 omit_meta_qualifiers(G0, TypeIn, G).
1478
1479omit_meta_qualifiers(V, _, V) :-
1480 var(V),
1481 !.
1482omit_meta_qualifiers((QA,QB), TypeIn, (A,B)) :-
1483 !,
1484 omit_qualifier(QA, TypeIn, A),
1485 omit_qualifier(QB, TypeIn, B).
1486omit_meta_qualifiers(tnot(QA), TypeIn, tnot(A)) :-
1487 !,
1488 omit_qualifier(QA, TypeIn, A).
1489omit_meta_qualifiers(freeze(V, QGoal), TypeIn, freeze(V, Goal)) :-
1490 callable(QGoal),
1491 !,
1492 omit_qualifier(QGoal, TypeIn, Goal).
1493omit_meta_qualifiers(when(Cond, QGoal), TypeIn, when(Cond, Goal)) :-
1494 callable(QGoal),
1495 !,
1496 omit_qualifier(QGoal, TypeIn, Goal).
1497omit_meta_qualifiers(G, _, G).
1498
1499
1505
1506bind_vars(Bindings0, Bindings) :-
1507 bind_query_vars(Bindings0, Bindings, SNames),
1508 bind_skel_vars(Bindings, Bindings, SNames, 1, _).
1509
1510bind_query_vars([], [], []).
1511bind_query_vars([binding(Names,Var,[Var2=Cycle])|T0],
1512 [binding(Names,Cycle,[])|T], [Name|SNames]) :-
1513 Var == Var2, 1514 !,
1515 '$last'(Names, Name),
1516 Var = '$VAR'(Name),
1517 bind_query_vars(T0, T, SNames).
1518bind_query_vars([B|T0], [B|T], AllNames) :-
1519 B = binding(Names,Var,Skel),
1520 bind_query_vars(T0, T, SNames),
1521 ( var(Var), \+ attvar(Var), Skel == []
1522 -> AllNames = [Name|SNames],
1523 '$last'(Names, Name),
1524 Var = '$VAR'(Name)
1525 ; AllNames = SNames
1526 ).
1527
1528
1529
1530bind_skel_vars([], _, _, N, N).
1531bind_skel_vars([binding(_,_,Skel)|T], Bindings, SNames, N0, N) :-
1532 bind_one_skel_vars(Skel, Bindings, SNames, N0, N1),
1533 bind_skel_vars(T, Bindings, SNames, N1, N).
1534
1551
1552bind_one_skel_vars([], _, _, N, N).
1553bind_one_skel_vars([Var=Value|T], Bindings, Names, N0, N) :-
1554 ( var(Var)
1555 -> ( '$member'(binding(Names, VVal, []), Bindings),
1556 same_term(Value, VVal)
1557 -> '$last'(Names, VName),
1558 Var = '$VAR'(VName),
1559 N2 = N0
1560 ; between(N0, infinite, N1),
1561 atom_concat('_S', N1, Name),
1562 \+ memberchk(Name, Names),
1563 !,
1564 Var = '$VAR'(Name),
1565 N2 is N1 + 1
1566 )
1567 ; N2 = N0
1568 ),
1569 bind_one_skel_vars(T, Bindings, Names, N2, N).
1570
1571
1575
1576factorize_bindings([], []).
1577factorize_bindings([Name=Value|T0], [binding(Name, Skel, Subst)|T]) :-
1578 '$factorize_term'(Value, Skel, Subst0),
1579 ( current_prolog_flag(toplevel_print_factorized, true)
1580 -> Subst = Subst0
1581 ; only_cycles(Subst0, Subst)
1582 ),
1583 factorize_bindings(T0, T).
1584
1585
1586only_cycles([], []).
1587only_cycles([B|T0], List) :-
1588 ( B = (Var=Value),
1589 Var = Value,
1590 acyclic_term(Var)
1591 -> only_cycles(T0, List)
1592 ; List = [B|T],
1593 only_cycles(T0, T)
1594 ).
1595
1596
1602
1603filter_bindings([], []).
1604filter_bindings([H0|T0], T) :-
1605 hide_vars(H0, H),
1606 ( ( arg(1, H, [])
1607 ; self_bounded(H)
1608 )
1609 -> filter_bindings(T0, T)
1610 ; T = [H|T1],
1611 filter_bindings(T0, T1)
1612 ).
1613
1614hide_vars(binding(Names0, Skel, Subst), binding(Names, Skel, Subst)) :-
1615 hide_names(Names0, Skel, Subst, Names).
1616
1617hide_names([], _, _, []).
1618hide_names([Name|T0], Skel, Subst, T) :-
1619 ( sub_atom(Name, 0, _, _, '_'),
1620 current_prolog_flag(toplevel_print_anon, false),
1621 sub_atom(Name, 1, 1, _, Next),
1622 char_type(Next, prolog_var_start)
1623 -> true
1624 ; Subst == [],
1625 Skel == '$VAR'(Name)
1626 ),
1627 !,
1628 hide_names(T0, Skel, Subst, T).
1629hide_names([Name|T0], Skel, Subst, [Name|T]) :-
1630 hide_names(T0, Skel, Subst, T).
1631
1632self_bounded(binding([Name], Value, [])) :-
1633 Value == '$VAR'(Name).
1634
1638
1639:- if(current_prolog_flag(emscripten, true)). 1640get_respons(Action, _Chp) :-
1641 '$can_yield',
1642 !,
1643 await(more, ActionS),
1644 atom_string(Action, ActionS).
1645:- endif. 1646get_respons(Action, Chp) :-
1647 repeat,
1648 flush_output(user_output),
1649 get_single_char(Char),
1650 answer_respons(Char, Chp, Action),
1651 ( Action == again
1652 -> print_message(query, query(action)),
1653 fail
1654 ; !
1655 ).
1656
1657answer_respons(Char, _, again) :-
1658 '$in_reply'(Char, '?h'),
1659 !,
1660 print_message(help, query(help)).
1661answer_respons(Char, _, redo) :-
1662 '$in_reply'(Char, ';nrNR \t'),
1663 !,
1664 print_message(query, if_tty([ansi(bold, ';', [])])).
1665answer_respons(Char, _, redo) :-
1666 '$in_reply'(Char, 'tT'),
1667 !,
1668 trace,
1669 save_debug,
1670 print_message(query, if_tty([ansi(bold, '; [trace]', [])])).
1671answer_respons(Char, _, continue) :-
1672 '$in_reply'(Char, 'ca\n\ryY.'),
1673 !,
1674 print_message(query, if_tty([ansi(bold, '.', [])])).
1675answer_respons(0'b, _, show_again) :-
1676 !,
1677 break.
1678answer_respons(0'*, Chp, show_again) :-
1679 !,
1680 print_last_chpoint(Chp).
1681answer_respons(Char, _, show_again) :-
1682 print_predicate(Char, Pred, Options),
1683 !,
1684 print_message(query, if_tty(['~w'-[Pred]])),
1685 set_prolog_flag(answer_write_options, Options).
1686answer_respons(-1, _, show_again) :-
1687 !,
1688 print_message(query, halt('EOF')),
1689 halt(0).
1690answer_respons(Char, _, again) :-
1691 print_message(query, no_action(Char)).
1692
1693print_predicate(0'w, [write], [ quoted(true),
1694 spacing(next_argument)
1695 ]).
1696print_predicate(0'p, [print], [ quoted(true),
1697 portray(true),
1698 max_depth(10),
1699 spacing(next_argument)
1700 ]).
1701
1702
1703print_last_chpoint(Chp) :-
1704 current_predicate(print_last_choice_point/0),
1705 !,
1706 print_last_chpoint_(Chp).
1707print_last_chpoint(Chp) :-
1708 use_module(library(prolog_stack), [print_last_choicepoint/2]),
1709 print_last_chpoint_(Chp).
1710
1711print_last_chpoint_(Chp) :-
1712 print_last_choicepoint(Chp, [message_level(information)]).
1713
1714
1715 1718
1719:- user:dynamic(expand_query/4). 1720:- user:multifile(expand_query/4). 1721
1722call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :-
1723 user:expand_query(Goal, Expanded, Bindings, ExpandedBindings),
1724 !.
1725call_expand_query(Goal, Expanded, Bindings, ExpandedBindings) :-
1726 toplevel_variables:expand_query(Goal, Expanded, Bindings, ExpandedBindings),
1727 !.
1728call_expand_query(Goal, Goal, Bindings, Bindings).
1729
1730
1731:- user:dynamic(expand_answer/2). 1732:- user:multifile(expand_answer/2). 1733
1734call_expand_answer(Goal, Expanded) :-
1735 user:expand_answer(Goal, Expanded),
1736 !.
1737call_expand_answer(Goal, Expanded) :-
1738 toplevel_variables:expand_answer(Goal, Expanded),
1739 !.
1740call_expand_answer(Goal, Goal)