Move interactive read-eval-print out of runtime
This is not required for a server process like Gerrit Code Review.
Yanking it out of the runtime JAR slims the binary down by a few
hundred KiBs as the interactive debugger and associated code can
also be trimmed out.
Consulting a file in the interactive console now requires using
consult('path/to/file.pl').
instead of the short-hand ["path/to/file.pl"] that many Prolog
implementations honor.
Change-Id: I5c8df131df349d5ca65d5684ed7cc1881247563b
diff --git a/BUCK b/BUCK
index decdbb1..f170833 100644
--- a/BUCK
+++ b/BUCK
@@ -4,6 +4,7 @@
name = 'all',
cmd = ':>all',
deps = [
+ ':cafeteria',
':compiler',
':runtime',
],
@@ -20,7 +21,10 @@
java_library(
name = 'lang',
- srcs = glob([SRC + 'lang/*.java']),
+ srcs = glob(
+ [SRC + 'lang/*.java'],
+ excludes = [SRC + 'lang/PrologMain.java'],
+ ),
)
java_library(
@@ -67,3 +71,27 @@
src = 'src/compiler/am2j.pl',
out = 'am2j.src.zip',
)
+
+java_binary(
+ name = 'cafeteria',
+ main_class = 'com.googlecode.prolog_cafe.lang.PrologMain',
+ deps = [':cafeteria_lib'],
+)
+
+java_library(
+ name = 'cafeteria_lib',
+ srcs = [
+ SRC + 'lang/PrologMain.java',
+ ':cafeteria_srcs',
+ ],
+ deps = [
+ ':builtin',
+ ':lang',
+ ],
+)
+
+pl2j(
+ name = 'cafeteria_srcs',
+ src = 'src/builtin/cafeteria.pl',
+ out = 'cafeteria.src.zip',
+)
diff --git a/src/builtin/builtins.pl b/src/builtin/builtins.pl
index 2d8e6cf..3349f93 100644
--- a/src/builtin/builtins.pl
+++ b/src/builtin/builtins.pl
@@ -48,15 +48,6 @@
'$meta_call'(X, _, _, _, _) :- var(X), !, illarg(var, call(X), 1).
'$meta_call'(X, _, _, _, _) :- closure(X), !, '$call_closure'(X).
'$meta_call'(true, _, _, _, _) :- !.
-'$meta_call'(trace, _, _, _, _) :- !, trace.
-'$meta_call'(debug, _, _, _, _) :- !, debug.
-'$meta_call'(notrace, _, _, _, _) :- !, notrace.
-'$meta_call'(nodebug, _, _, _, _) :- !, nodebug.
-'$meta_call'(spy(L), _, _, _, _) :- !, spy(L).
-'$meta_call'(nospy(L), _, _, _, _) :- !, nospy(L).
-'$meta_call'(nospyall, _, _, _, _) :- !, nospyall.
-'$meta_call'(leash(L), _, _, _, _) :- !, leash(L).
-'$meta_call'([X|Xs], _, _, _, _) :- !, consult([X|Xs]).
'$meta_call'(_^X, P, Cut, Depth, Mode) :- !,
'$meta_call'(X, P, Cut, Depth, Mode).
'$meta_call'(P:X, _, Cut, Depth, Mode) :- !,
@@ -104,7 +95,7 @@
'$meta_call'(trace, Depth, P, X) :- !,
functor(X, F, A),
- '$trace_goal'(X, P, F/A, Depth).
+ '$call'('com.googlecode.prolog_cafe.builtin', '$trace_goal'(X, P, F/A, Depth)).
'$meta_call'(interpret, Depth, P, X) :-
functor(X, F, A),
'$call_internal'(X, P, F/A, Depth, interpret).
@@ -1902,109 +1893,13 @@
:- op(1150, fx, (multifile)).
:- op(1150, fx, (block)).
-:- public cafeteria/0.
-:- public consult/1.
:- public consult_stream/1.
-:- public trace/0, notrace/0.
-:- public debug/0, nodebug/0.
-:- public leash/1.
-:- public spy/1, nospy/1, nospyall/0.
-:- public listing/0.
-:- public listing/1.
-
-:- dynamic '$current_leash'/1.
-:- dynamic '$current_spypoint'/3.
-:- dynamic '$leap_flag'/1.
:- dynamic '$consulted_file'/1.
:- dynamic '$consulted_import'/2.
:- dynamic '$consulted_package'/1.
:- dynamic '$consulted_predicate'/3.
-%%% Main
-cafeteria :-
- '$cafeteria_init',
- repeat,
- '$toplvel_loop',
- on_exception(Msg, '$cafeteria'(Goal), print_message(error, Msg)),
- Goal == end_of_file,
- !,
- nl, '$fast_write'(bye), nl.
-
-'$cafeteria_init' :-
- retractall('$leap_flag'(_)),
- retractall('$current_leash'(_)),
- retractall('$current_spypoint'(_,_,_)),
- retractall('$consulted_file'(_)),
- retractall('$consulted_package'(_)),
- retractall('$consulted_predicate'(_,_,_)),
- assertz('$leap_flag'(no)),
- assertz('$current_leash'(call)),
- assertz('$current_leash'(exit)),
- assertz('$current_leash'(redo)),
- assertz('$current_leash'(fail)),
- !.
-
-'$toplvel_loop' :-
- current_prolog_flag(debug, Mode),
- (Mode == off -> true ; print_message(info,[debug])),
- '$fast_write'('| ?- '),
- flush_output.
-
-'$cafeteria'(Goal) :-
- read_with_variables(Goal, Vars),
- '$process_order'(Goal, Vars).
-
-'$process_order'(G, _) :- var(G), !, illarg(var, (?- G), 1).
-'$process_order'(end_of_file, _) :- !.
-'$process_order'([File|Files], _) :- !, consult([File|Files]).
-'$process_order'(G, Vars) :-
- current_prolog_flag(debug, Mode),
- ( Mode == off -> call(user:G) ; '$trace_goal'(user:G) ), nl,
- '$rm_redundant_vars'(Vars, Vars1),
- '$give_answers_with_prompt'(Vars1),
- !,
- '$fast_write'(yes), nl.
-'$process_order'(_, _) :- nl, '$fast_write'(no), nl.
-
-'$rm_redundant_vars'([], []) :- !.
-'$rm_redundant_vars'(['_'=_|Xs], Vs) :- !,
- '$rm_redundant_vars'(Xs, Vs).
-'$rm_redundant_vars'([X|Xs], [X|Vs]) :-
- '$rm_redundant_vars'(Xs, Vs).
-
-'$give_answers_with_prompt'([]) :- !.
-'$give_answers_with_prompt'(Vs) :-
- '$give_an_answer'(Vs),
- '$fast_write'(' ? '), flush_output,
- read_line(Str),
- Str \== ";",
- nl.
-
-'$give_an_answer'([]) :- !, '$fast_write'(true).
-'$give_an_answer'([X]) :- !, '$print_an answer'(X).
-'$give_an_answer'([X|Xs]) :-
- '$print_an answer'(X), '$fast_write'(','), nl,
- '$give_an_answer'(Xs).
-
-'$print_an answer'(N = V) :-
- write(N), '$fast_write'(' = '), writeq(V).
-
%%% Read Program
-consult(Files) :- var(Files), !, illarg(var, consult(Files), 1).
-consult([]) :- !.
-consult([File|Files]) :- !, consult(File), consult(Files).
-consult(File) :- atom(File), !, '$consult'(File).
-
-'$consult'(F) :-
- '$prolog_file_name'(F, PF),
- open(PF, read, In),
- stream_property(In, file_name(File)),
- print_message(info, [consulting,File,'...']),
- statistics(runtime, _),
- consult_stream(File, In),
- statistics(runtime, [_,T]),
- print_message(info, [File,consulted,T,msec]),
- close(In).
consult_stream(File, In) :-
'$consult_init'(File),
@@ -2014,9 +1909,6 @@
Cl == end_of_file,
!.
-'$prolog_file_name'(File, File) :- sub_atom(File, _, _, After, '.'), After > 0, !.
-'$prolog_file_name'(File0, File) :- atom_concat(File0, '.pl', File).
-
'$consult_init'(File) :-
retractall('$consulted_file'(_)),
retractall('$consulted_package'(_)),
@@ -2069,231 +1961,6 @@
assertz('$consulted_predicate'(P,F/A,File)),
!.
-%%% Trace
-trace :- current_prolog_flag(debug, on), !.
-trace :-
- set_prolog_flag(debug, on),
- '$trace_init',
- '$fast_write'('{Small debugger is switch on}'),
- nl, !.
-
-'$trace_init' :-
- retractall('$leap_flag'(_)),
- retractall('$current_leash'(_)),
- retractall('$current_spypoint'(_,_,_)),
- assertz('$leap_flag'(no)),
- assertz('$current_leash'(call)),
- assertz('$current_leash'(exit)),
- assertz('$current_leash'(redo)),
- assertz('$current_leash'(fail)),
- !.
-
-notrace :- current_prolog_flag(debug, off), !.
-notrace :-
- set_prolog_flag(debug, off),
- '$fast_write'('{Small debugger is switch off}'),
- nl, !.
-
-debug :- trace.
-nodebug :- notrace.
-
-%%% Spy-Points
-spy(T) :-
- '$term_to_predicateindicator'(T, PI, spy(T)),
- trace,
- '$assert_spypoint'(PI),
- '$set_debug_flag'(leap, yes),
- !.
-
-'$assert_spypoint'(P:F/A) :-
- clause('$current_spypoint'(P,F,A), _),
- print_message(info, [spypoint,P:F/A,is,already,added]),
- !.
-'$assert_spypoint'(P:F/A) :-
- clause('$consulted_predicate'(P,F/A,_), _),
- assertz('$current_spypoint'(P,F,A)),
- print_message(info, [spypoint,P:F/A,is,added]),
- !.
-'$assert_spypoint'(P:F/A) :-
- print_message(warning, [no,matching,predicate,for,spy,P:F/A]).
-
-nospy(T) :-
- '$term_to_predicateindicator'(T, PI, nospy(T)),
- '$retract_spypoint'(PI),
- '$set_debug_flag'(leap, no),
- !.
-
-'$retract_spypoint'(P:F/A) :-
- retract('$current_spypoint'(P,F,A)),
- print_message(info, [spypoint,P:F/A,is,removed]),
- !.
-'$retract_spypoint'(_).
-
-nospyall :-
- retractall('$current_spypoint'(_,_,_)),
- '$set_debug_flag'(leap, no).
-
-%%% Leash
-leash(L) :- nonvar(L), '$leash'(L), !.
-leash(L) :- illarg(type('leash_specifier'), leash(L), 1).
-
-'$leash'([]) :- !,
- retractall('$current_leash'(_)),
- print_message(info, [no,leashing]).
-'$leash'(Ms) :-
- retractall('$current_leash'(_)),
- '$assert_leash'(Ms),
- print_message(info,[leashing,stopping,on,Ms]).
-
-'$assert_leash'([]) :- !.
-'$assert_leash'([X|Xs]) :-
- '$leash_specifier'(X),
- assertz('$current_leash'(X)),
- '$assert_leash'(Xs).
-
-'$leash_specifier'(call).
-'$leash_specifier'(exit).
-'$leash_specifier'(redo).
-'$leash_specifier'(fail).
-%'$leash_specifier'(exception).
-
-%%% Trace a Goal
-'$trace_goal'(Term) :-
- '$set_debug_flag'(leap, no),
- '$get_current_B'(Cut),
- '$meta_call'(Term, user, Cut, 0, trace).
-
-'$trace_goal'(X, P, FA, Depth) :-
- print_procedure_box(call, X, P, FA, Depth),
- '$call_internal'(X, P, FA, Depth, trace),
- print_procedure_box(exit, X, P, FA, Depth),
- redo_procedure_box(X, P, FA, Depth).
-'$trace_goal'(X, P, FA, Depth) :-
- print_procedure_box(fail, X, P, FA, Depth),
- fail.
-
-print_procedure_box(Mode, G, P, F/A, Depth) :-
- clause('$current_spypoint'(P, F, A), _),
- !,
- '$builtin_message'(['+',Depth,Mode,':',P:G]),
- '$read_blocked'(print_procedure_box(Mode,G,P,F/A,Depth)).
-print_procedure_box(Mode, G, P, FA, Depth) :-
- clause('$leap_flag'(no), _),
- !,
- '$builtin_message'([' ',Depth,Mode,':',P:G]),
- ( clause('$current_leash'(Mode), _)
- ->
- '$read_blocked'(print_procedure_box(Mode,G,P,FA,Depth))
- ;
- nl
- ).
-print_procedure_box(_, _, _, _, _).
-
-redo_procedure_box(_, _, _, _).
-redo_procedure_box(X, P, FA, Depth) :-
- print_procedure_box(redo, X, P, FA, Depth),
- fail.
-
-'$read_blocked'(G) :-
- '$fast_write'(' ? '),
- flush_output,
- read_line(C),
- (C == [] -> DOP = 99 ; C = [DOP|_]),
- '$debug_option'(DOP, G).
-
-'$debug_option'(97, _) :- !, notrace, abort. % a for abort
-'$debug_option'(99, _) :- !, '$set_debug_flag'(leap, no). % c for creep
-'$debug_option'(108, _) :- !, '$set_debug_flag'(leap, yes). % l for leap
-'$debug_option'(43, print_procedure_box(Mode,G,P,FA,Depth)) :- !, % + for spy this
- spy(P:FA),
- call(print_procedure_box(Mode,G,P,FA,Depth)).
-'$debug_option'(45, print_procedure_box(Mode,G,P,FA,Depth)) :- !, % - for nospy this
- nospy(P:FA),
- call(print_procedure_box(Mode,G,P,FA,Depth)).
-'$debug_option'(63, G) :- !, '$show_debug_option', call(G).
-'$debug_option'(104, G) :- !, '$show_debug_option', call(G).
-'$debug_option'(_, _).
-
-'$show_debug_option' :-
- tab(4), '$fast_write'('Debuggin options:'), nl,
- tab(4), '$fast_write'('a abort'), nl,
- tab(4), '$fast_write'('RET creep'), nl,
- tab(4), '$fast_write'('c creep'), nl,
- tab(4), '$fast_write'('l leap'), nl,
- tab(4), '$fast_write'('+ spy this'), nl,
- tab(4), '$fast_write'('- nospy this'), nl,
- tab(4), '$fast_write'('? help'), nl,
- tab(4), '$fast_write'('h help'), nl.
-
-'$set_debug_flag'(leap, Flag) :-
- clause('$leap_flag'(Flag), _),
- !.
-'$set_debug_flag'(leap, Flag) :-
- retractall('$leap_flag'(_)),
- assertz('$leap_flag'(Flag)).
-
-%%% Listing
-listing :- '$listing'(_, user).
-
-listing(T) :- var(T), !, illarg(var, listing(T), 1).
-listing(P) :- atom(P), !, '$listing'(_, P).
-listing(F/A) :- !, '$listing'(F/A, user).
-listing(P:PI) :- atom(P), !, '$listing'(PI, P).
-listing(T) :- illarg(type(predicate_indicator), listing(T), 1).
-
-'$listing'(PI, P) :- var(PI), !,
- '$listing_dynamic_clause'(P, _).
-'$listing'(F/A, P) :- atom(F), integer(A), !,
- '$listing_dynamic_clause'(P, F/A).
-'$listing'(PI, P) :- illarg(type(predicate_indicator), listing(P:PI), 1).
-
-'$listing_dynamic_clause'(P, PI) :-
- '$new_internal_database'(P),
- hash_keys(P, Keys),
- '$builtin_member'(PI, Keys),
- PI = F/A,
- functor(H, F, A),
- '$clause_internal'(P, PI, H, Cl, _),
- '$write_dynamic_clause'(P, Cl),
- fail.
-'$listing_dynamic_clause'(_, _).
-
-'$write_dynamic_clause'(_, Cl) :- var(Cl), !, fail.
-'$write_dynamic_clause'(P, (H :- true)) :- !,
- numbervars(H, 0, _),
- '$write_dynamic_head'(P, H),
- write('.'), nl.
-'$write_dynamic_clause'(P, (H :- B)) :- !,
- numbervars((H :- B), 0, _),
- '$write_dynamic_head'(P, H),
- write(' :-'), nl,
- '$write_dynamic_body'(B, 8),
- write('.'), nl.
-
-'$write_dynamic_head'(user, H) :- !, writeq(H).
-'$write_dynamic_head'(P, H) :-
- write(P), write(':'), writeq(H).
-
-'$write_dynamic_body'((G1,G2), N) :- !,
- '$write_dynamic_body'(G1, N), write(','), nl,
- '$write_dynamic_body'(G2, N).
-'$write_dynamic_body'((G1;G2), N) :- !,
- N1 is N+4,
- tab(N), write('('), nl,
- '$write_dynamic_body'(G1, N1), nl,
- tab(N), write(';'), nl,
- '$write_dynamic_body'(G2, N1), nl,
- tab(N), write(')').
-'$write_dynamic_body'((G1->G2), N) :- !,
- N1 is N+4,
- tab(N), write('('), nl,
- '$write_dynamic_body'(G1, N1), nl,
- tab(N), write('->'), nl,
- '$write_dynamic_body'(G2, N1), nl,
- tab(N), write(')').
-'$write_dynamic_body'(B, N) :-
- tab(N), writeq(B).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Misc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/builtin/cafeteria.pl b/src/builtin/cafeteria.pl
new file mode 100644
index 0000000..cb63123
--- /dev/null
+++ b/src/builtin/cafeteria.pl
@@ -0,0 +1,341 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Interactive interpreter of Prolog Cafe
+%
+% Mutsunori Banbara (banbara@kobe-u.ac.jp)
+% Naoyuki Tamura (tamura@kobe-u.ac.jp)
+% Kobe University
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+:- package 'com.googlecode.prolog_cafe.builtin'.
+:- public cafeteria/0.
+
+%%% Main
+cafeteria :-
+ '$cafeteria_init',
+ repeat,
+ '$toplvel_loop',
+ on_exception(Msg, '$cafeteria'(Goal), print_message(error, Msg)),
+ Goal == end_of_file,
+ !,
+ nl, '$fast_write'(bye), nl.
+
+'$cafeteria_init' :-
+ '$new_indexing_hash'('com.googlecode.prolog_cafe.builtin','$leap_flag'/1, _),
+ '$new_indexing_hash'('com.googlecode.prolog_cafe.builtin','$current_spypoint'/3, _),
+ '$new_indexing_hash'('com.googlecode.prolog_cafe.builtin','$current_leash'/1, _),
+ retractall('$leap_flag'(_)),
+ retractall('$current_leash'(_)),
+ retractall('$current_spypoint'(_,_,_)),
+ retractall('$consulted_file'(_)),
+ retractall('$consulted_package'(_)),
+ retractall('$consulted_predicate'(_,_,_)),
+ assertz('$leap_flag'(no)),
+ assertz('$current_leash'(call)),
+ assertz('$current_leash'(exit)),
+ assertz('$current_leash'(redo)),
+ assertz('$current_leash'(fail)),
+ !.
+
+'$toplvel_loop' :-
+ current_prolog_flag(debug, Mode),
+ (Mode == off -> true ; print_message(info,[debug])),
+ '$fast_write'('| ?- '),
+ flush_output.
+
+'$cafeteria'(Goal) :-
+ read_with_variables(Goal, Vars),
+ '$process_order'(Goal, Vars).
+
+'$process_order'(G, _) :- var(G), !, illarg(var, (?- G), 1).
+'$process_order'(end_of_file, _) :- !.
+'$process_order'([File|Files], _) :- !, consult([File|Files]).
+'$process_order'(G, Vars) :-
+ current_prolog_flag(debug, Mode),
+ ( Mode == off -> call(user:G) ; '$trace_goal'(user:G) ), nl,
+ '$rm_redundant_vars'(Vars, Vars1),
+ '$give_answers_with_prompt'(Vars1),
+ !,
+ '$fast_write'(yes), nl.
+'$process_order'(_, _) :- nl, '$fast_write'(no), nl.
+
+'$rm_redundant_vars'([], []) :- !.
+'$rm_redundant_vars'(['_'=_|Xs], Vs) :- !,
+ '$rm_redundant_vars'(Xs, Vs).
+'$rm_redundant_vars'([X|Xs], [X|Vs]) :-
+ '$rm_redundant_vars'(Xs, Vs).
+
+'$give_answers_with_prompt'([]) :- !.
+'$give_answers_with_prompt'(Vs) :-
+ '$give_an_answer'(Vs),
+ '$fast_write'(' ? '), flush_output,
+ read_line(Str),
+ Str \== ";",
+ nl.
+
+'$give_an_answer'([]) :- !, '$fast_write'(true).
+'$give_an_answer'([X]) :- !, '$print_an answer'(X).
+'$give_an_answer'([X|Xs]) :-
+ '$print_an answer'(X), '$fast_write'(','), nl,
+ '$give_an_answer'(Xs).
+
+'$print_an answer'(N = V) :-
+ write(N), '$fast_write'(' = '), writeq(V).
+
+%%% Read Program
+:- public consult/1.
+
+consult(Files) :- var(Files), !, illarg(var, consult(Files), 1).
+consult([]) :- !.
+consult([File|Files]) :- !, consult(File), consult(Files).
+consult(File) :- atom(File), !, '$consult'(File).
+
+'$consult'(F) :-
+ '$prolog_file_name'(F, PF),
+ open(PF, read, In),
+ stream_property(In, file_name(File)),
+ print_message(info, [consulting,File,'...']),
+ statistics(runtime, _),
+ consult_stream(File, In),
+ statistics(runtime, [_,T]),
+ print_message(info, [File,consulted,T,msec]),
+ close(In).
+
+'$prolog_file_name'(File, File) :- sub_atom(File, _, _, After, '.'), After > 0, !.
+'$prolog_file_name'(File0, File) :- atom_concat(File0, '.pl', File).
+
+%%% Trace
+:- public trace/0, notrace/0.
+:- public debug/0, nodebug/0.
+
+trace :- current_prolog_flag(debug, on), !.
+trace :-
+ set_prolog_flag(debug, on),
+ '$trace_init',
+ '$fast_write'('{Small debugger is switch on}'),
+ nl, !.
+
+'$trace_init' :-
+ retractall('$leap_flag'(_)),
+ retractall('$current_leash'(_)),
+ retractall('$current_spypoint'(_,_,_)),
+ assertz('$leap_flag'(no)),
+ assertz('$current_leash'(call)),
+ assertz('$current_leash'(exit)),
+ assertz('$current_leash'(redo)),
+ assertz('$current_leash'(fail)),
+ !.
+
+notrace :- current_prolog_flag(debug, off), !.
+notrace :-
+ set_prolog_flag(debug, off),
+ '$fast_write'('{Small debugger is switch off}'),
+ nl, !.
+
+debug :- trace.
+nodebug :- notrace.
+
+%%% Trace a Goal
+'$trace_goal'(Term) :-
+ '$set_debug_flag'(leap, no),
+ '$get_current_B'(Cut),
+ '$meta_call'(Term, user, Cut, 0, trace).
+
+'$trace_goal'(nodebug, _, _, _) :- nodebug.
+'$trace_goal'(notrace, _, _, _) :- notrace.
+'$trace_goal'(X, P, FA, Depth) :-
+ print_procedure_box(call, X, P, FA, Depth),
+ '$call_internal'(X, P, FA, Depth, trace),
+ print_procedure_box(exit, X, P, FA, Depth),
+ redo_procedure_box(X, P, FA, Depth).
+'$trace_goal'(X, P, FA, Depth) :-
+ print_procedure_box(fail, X, P, FA, Depth),
+ fail.
+
+print_procedure_box(Mode, G, P, F/A, Depth) :-
+ clause('$current_spypoint'(P, F, A), _),
+ !,
+ '$builtin_message'(['+',Depth,Mode,':',P:G]),
+ '$read_blocked'(print_procedure_box(Mode,G,P,F/A,Depth)).
+print_procedure_box(Mode, G, P, FA, Depth) :-
+ clause('$leap_flag'(no), _),
+ !,
+ '$builtin_message'([' ',Depth,Mode,':',P:G]),
+ ( clause('$current_leash'(Mode), _)
+ ->
+ '$read_blocked'(print_procedure_box(Mode,G,P,FA,Depth))
+ ;
+ nl
+ ).
+print_procedure_box(_, _, _, _, _).
+
+redo_procedure_box(_, _, _, _).
+redo_procedure_box(X, P, FA, Depth) :-
+ print_procedure_box(redo, X, P, FA, Depth),
+ fail.
+
+'$read_blocked'(G) :-
+ '$fast_write'(' ? '),
+ flush_output,
+ read_line(C),
+ (C == [] -> DOP = 99 ; C = [DOP|_]),
+ '$debug_option'(DOP, G).
+
+'$debug_option'(97, _) :- !, notrace, abort. % a for abort
+'$debug_option'(99, _) :- !, '$set_debug_flag'(leap, no). % c for creep
+'$debug_option'(108, _) :- !, '$set_debug_flag'(leap, yes). % l for leap
+'$debug_option'(43, print_procedure_box(Mode,G,P,FA,Depth)) :- !, % + for spy this
+ spy(P:FA),
+ call(print_procedure_box(Mode,G,P,FA,Depth)).
+'$debug_option'(45, print_procedure_box(Mode,G,P,FA,Depth)) :- !, % - for nospy this
+ nospy(P:FA),
+ call(print_procedure_box(Mode,G,P,FA,Depth)).
+'$debug_option'(63, G) :- !, '$show_debug_option', call(G).
+'$debug_option'(104, G) :- !, '$show_debug_option', call(G).
+'$debug_option'(_, _).
+
+'$show_debug_option' :-
+ tab(4), '$fast_write'('Debugging options:'), nl,
+ tab(4), '$fast_write'('a abort'), nl,
+ tab(4), '$fast_write'('RET creep'), nl,
+ tab(4), '$fast_write'('c creep'), nl,
+ tab(4), '$fast_write'('l leap'), nl,
+ tab(4), '$fast_write'('+ spy this'), nl,
+ tab(4), '$fast_write'('- nospy this'), nl,
+ tab(4), '$fast_write'('? help'), nl,
+ tab(4), '$fast_write'('h help'), nl.
+
+'$set_debug_flag'(leap, Flag) :-
+ clause('$leap_flag'(Flag), _),
+ !.
+'$set_debug_flag'(leap, Flag) :-
+ retractall('$leap_flag'(_)),
+ assertz('$leap_flag'(Flag)).
+
+%%% Spy-Points
+:- public spy/1, nospy/1, nospyall/0.
+
+spy(T) :-
+ '$term_to_predicateindicator'(T, PI, spy(T)),
+ trace,
+ '$assert_spypoint'(PI),
+ '$set_debug_flag'(leap, yes),
+ !.
+
+'$assert_spypoint'(P:F/A) :-
+ clause('$current_spypoint'(P,F,A), _),
+ print_message(info, [spypoint,P:F/A,is,already,added]),
+ !.
+'$assert_spypoint'(P:F/A) :-
+ clause('$consulted_predicate'(P,F/A,_), _),
+ assertz('$current_spypoint'(P,F,A)),
+ print_message(info, [spypoint,P:F/A,is,added]),
+ !.
+'$assert_spypoint'(P:F/A) :-
+ print_message(warning, [no,matching,predicate,for,spy,P:F/A]).
+
+nospy(T) :-
+ '$term_to_predicateindicator'(T, PI, nospy(T)),
+ '$retract_spypoint'(PI),
+ '$set_debug_flag'(leap, no),
+ !.
+
+'$retract_spypoint'(P:F/A) :-
+ retract('$current_spypoint'(P,F,A)),
+ print_message(info, [spypoint,P:F/A,is,removed]),
+ !.
+'$retract_spypoint'(_).
+
+nospyall :-
+ retractall('$current_spypoint'(_,_,_)),
+ '$set_debug_flag'(leap, no).
+
+%%% Leash
+:- public leash/1.
+
+leash(L) :- nonvar(L), '$leash'(L), !.
+leash(L) :- illarg(type('leash_specifier'), leash(L), 1).
+
+'$leash'([]) :- !,
+ retractall('$current_leash'(_)),
+ print_message(info, [no,leashing]).
+'$leash'(Ms) :-
+ retractall('$current_leash'(_)),
+ '$assert_leash'(Ms),
+ print_message(info,[leashing,stopping,on,Ms]).
+
+'$assert_leash'([]) :- !.
+'$assert_leash'([X|Xs]) :-
+ '$leash_specifier'(X),
+ assertz('$current_leash'(X)),
+ '$assert_leash'(Xs).
+
+'$leash_specifier'(call).
+'$leash_specifier'(exit).
+'$leash_specifier'(redo).
+'$leash_specifier'(fail).
+%'$leash_specifier'(exception).
+
+%%% Listing
+:- public listing/0.
+:- public listing/1.
+
+listing :- '$listing'(_, user).
+
+listing(T) :- var(T), !, illarg(var, listing(T), 1).
+listing(P) :- atom(P), !, '$listing'(_, P).
+listing(F/A) :- !, '$listing'(F/A, user).
+listing(P:PI) :- atom(P), !, '$listing'(PI, P).
+listing(T) :- illarg(type(predicate_indicator), listing(T), 1).
+
+'$listing'(PI, P) :- var(PI), !,
+ '$listing_dynamic_clause'(P, _).
+'$listing'(F/A, P) :- atom(F), integer(A), !,
+ '$listing_dynamic_clause'(P, F/A).
+'$listing'(PI, P) :- illarg(type(predicate_indicator), listing(P:PI), 1).
+
+'$listing_dynamic_clause'(P, PI) :-
+ '$new_internal_database'(P),
+ hash_keys(P, Keys),
+ '$builtin_member'(PI, Keys),
+ PI = F/A,
+ functor(H, F, A),
+ '$clause_internal'(P, PI, H, Cl, _),
+ '$write_dynamic_clause'(P, Cl),
+ fail.
+'$listing_dynamic_clause'(_, _).
+
+'$write_dynamic_clause'(_, Cl) :- var(Cl), !, fail.
+'$write_dynamic_clause'(P, (H :- true)) :- !,
+ numbervars(H, 0, _),
+ '$write_dynamic_head'(P, H),
+ write('.'), nl.
+'$write_dynamic_clause'(P, (H :- B)) :- !,
+ numbervars((H :- B), 0, _),
+ '$write_dynamic_head'(P, H),
+ write(' :-'), nl,
+ '$write_dynamic_body'(B, 8),
+ write('.'), nl.
+
+'$write_dynamic_head'(user, H) :- !, writeq(H).
+'$write_dynamic_head'(P, H) :-
+ write(P), write(':'), writeq(H).
+
+'$write_dynamic_body'((G1,G2), N) :- !,
+ '$write_dynamic_body'(G1, N), write(','), nl,
+ '$write_dynamic_body'(G2, N).
+'$write_dynamic_body'((G1;G2), N) :- !,
+ N1 is N+4,
+ tab(N), write('('), nl,
+ '$write_dynamic_body'(G1, N1), nl,
+ tab(N), write(';'), nl,
+ '$write_dynamic_body'(G2, N1), nl,
+ tab(N), write(')').
+'$write_dynamic_body'((G1->G2), N) :- !,
+ N1 is N+4,
+ tab(N), write('('), nl,
+ '$write_dynamic_body'(G1, N1), nl,
+ tab(N), write('->'), nl,
+ '$write_dynamic_body'(G2, N1), nl,
+ tab(N), write(')').
+'$write_dynamic_body'(B, N) :-
+ tab(N), writeq(B).