35
36:- module('$toplevel',
37 [ '$initialise'/0, 38 '$toplevel'/0, 39 '$compile'/0, 40 '$config'/0, 41 initialize/0, 42 version/0, 43 version/1, 44 prolog/0, 45 '$query_loop'/0, 46 '$execute_query'/3, 47 residual_goals/1, 48 (initialization)/1, 49 '$thread_init'/0, 50 (thread_initialization)/1 51 ]). 52
53
54 57
58:- dynamic
59 prolog:version_msg/1. 60
65
66version :-
67 print_message(banner, welcome).
68
72
73:- multifile
74 system:term_expansion/2. 75
76system:term_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 89
92
93:- dynamic
94 loaded_init_file/2. 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 173
174:- meta_predicate
175 initialization(0). 176
177:- '$iso'((initialization)/1). 178
185
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
199prolog:initialize_now(load_foreign_library(_),
200 'use :- use_foreign_library/1 instead').
201prolog:initialize_now(load_foreign_library(_,_),
202 'use :- use_foreign_library/2 instead').
203
204prolog:message(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'.
213
218
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 236
237:- meta_predicate
238 thread_initialization(0). 239:- dynamic
240 '$at_thread_initialization'/1. 241
245
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 264
268
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 328
332
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 ).
377
384
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 ).
399
407
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(_).
426
427
432
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.
443
444
448
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 479
485
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 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).
540
545
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).
557
561
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 ).
591
596
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).
610
614
615setup_backtrace :-
616 ( \+ current_prolog_flag(backtrace, false),
617 load_setup_file(library(prolog_stack))
618 -> true
619 ; true
620 ).
621
625
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 ).
636
640
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'.
651
655
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).
682
686
687load_setup_file(File) :-
688 catch(load_files(File,
689 [ silent(true),
690 if(not_loaded)
691 ]), _, fail).
692
693
694:- '$hide'('$toplevel'/0). 695
699
700'$toplevel' :-
701 '$runtoplevel',
702 print_message(informational, halt).
703
711
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)).
736
740
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.
756
760
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 777
783
784prolog :-
785 break.
786
787:- create_prolog_flag(toplevel_mode, backtracking, []). 788
795
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' 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 !.
848
849
855
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, 871 prompt1(Prompt1),
872 read_query_line(user_input, Line),
873 '$save_history_line'(Line), 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). 884
886
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 ).
898
903
904read_term_as_atom(In, Line) :-
905 '$raw_read'(In, Line),
906 ( Line == end_of_file
907 -> true
908 ; skip_to_nl(In)
909 ).
910
915
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).
944
945
951
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 967
980
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 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 Codes,
1052 subst_chars(T).
1053subst_chars([H|T]) -->
1054 H,
1055 subst_chars(T).
1056
1057
1058 1061
1065
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.
1117
1131
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 ).
1157
1162
1163:- multifile
1164 residual_goal_collector/1. 1165
1166:- meta_predicate
1167 residual_goals(2). 1168
1169residual_goals(NonTerminal) :-
1170 throw(error(context_error(nodirective, residual_goals(NonTerminal)), _)).
1171
1172system:term_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).
1177
1182
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).
1193
1194
1195
1216
1217:- public
1218 prolog:translate_bindings/5. 1219:- meta_predicate
1220 prolog:translate_bindings(+, -, +, +, :). 1221
1222prolog:translate_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
1250hidden_residuals(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).
1281
1282
1287
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).
1317
1318
1326
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).
1339
1340
1345
1346
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).
1392
1393
1399
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, 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).
1428
1445
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).
1464
1465
1469
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 ).
1489
1490
1496
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).
1528
1532
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 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)