/* DEBUG : an experimental debugger. Dave Bowen Updated: 19 January 1984 This is an experimental Prolog debugger. I would be most interested in comments as to whether any features of it are found to be more useful or less useful than those in the existing debugger. Currently it only allows user interaction at the CALL port of a procedure. The predicates offered are debug/1 invokes the debugger on a specified goal tracing/0 (cf trace/0) switches trace mode on (the default) notracing/0 (cf notrace/0) switches trace mode off spying/1 (cf spy/1) sets a spypoint nospying/1 (cf nospy/1) removes a spypoint spying/0 (cf debugging/0) lists current spypoints Note that spying/1 and nospying/1 take the same variety of forms of argument as their counterparts spy/1 and nospy/1. Both of these, and also debug/1, are declared as prefix operators, so you can invoke the debugger by e.g. | ?- debug grandparent(X,Y). MAJOR OMISSION: cut is not supported. When at a spy point or when single-stepping through a program using trace mode, the options currently available are & list continuation path g list goal stack | list backtrack path m list matching clauses a abort e exit from Prolog cr (carriage return) creep, i.e. single step l leap, i.e. continue till next spy point ? print this help information (Important omissions are skip, retry and break.) */ :- unknown(_,fail). :- op(1050,fy,(debug)). :- op(900,fy,[spying,nospying]). debug Goals :- makelist(Goals,[],Glist), debug([cont(true,[],Glist)],[]). debug([],_) :- !, trace(['*** Solution *** ']). debug([ cont(Head,Done,[]) | Cont ], ChPts) :- !, trace(['** Exiting: ', Head]), debug(Cont,ChPts). debug([ cont(Head,Done,[Goal|Goals]) | Cont ], ChPts) :- !, reduce(Goal, [ cont(Head,[Goal|Done],Goals) | Cont ], NewCont, ChPts, NewChPts), debug(NewCont,NewChPts). reduce(Goal,Cont,_,ChPts,_) :- tracing(Goal), interact(Goal,Cont,ChPts), fail. reduce(P,Cont,Cont,Chpts,Chpts) :- system(P), !, % NB backtrace will not show trace(['*** Built in *** ', P]), % any system predicates. call(P). reduce(P,Cont,[cont(P,[],Goals)|Cont],ChPts,NewChPts) :- find_clause(P,Q,ChPts,NewChPts), makelist(Q,[],Goals), trace(['** Using clause: ', clause(P,Goals)]). reduce(_,_,_,[chpt(Goal,_)|ChPts],_) :- trace(['** Redoing: ', Goal]), fail. find_clause(Head,Body,ChPts,NewChPts) :- bagof((Head,Body),clause(Head,Body),Bag), !, copy(Bag,BagCopy), copy(Head,H0), choice_point(Bag,BagCopy,(Head,Body),H0,ChPts,NewChPts). find_clause(Goal,_,_,_) :- trace(['** No matching clauses for: ', Goal]), fail. choice_point([X],_,X,_,ChPts,ChPts) :- !. choice_point([X|_],BagCopy,X,H0,ChPts,[chpt(H0,BagCopy)|ChPts]) :- trace('** Choice point:'). choice_point([_|Bag],[_|BagCopy],X,H0,ChPts,NewChPts) :- choice_point(Bag,BagCopy,X,H0,ChPts,NewChPts). copy(Old, New) :- asserta(copy(Old)), retract(copy(Mid)), !, New = Mid. interact(P,Cont,Choices) :- seeing(S), see(user), telling(T), tell(user), current_goal(Cont,G), repeat, prompt_user(G), get0(C), skiptonl(C), action(C,Cont,Choices), !, see(S), tell(T). prompt_user(G) :- nl, nl, ( spy_point(G), !, print('*** Spy point: ') ; print('*** Call: ') ), print(G), print(' ? '), nl. action(38,Cont,_) :- !, % 38 is "&" nl, print('&&& continuation &&&'), numbervars(Cont,0,_), member(cont(Head,[Current|Done],Rest),Cont), revlist(Done,[0,Current|Rest],Goals), print_clause(Head,Goals), fail. action(103,Cont,_) :- !, % 103 is "g" nl, print('&&& goal stack &&&'), numbervars(Cont,0,_), current_goal(Cont,G), nl, print(G), member(cont(_,_,Rest),Cont), member(Goal,Rest), nl, print(Goal), fail. action(124,_,[]) :- !, % 124 is "|" print('||| No backtrack points |||'), fail. action(124,_,Choices) :- !, nl, print('||| backtrace |||'), member(chpt(Goal,[Chosen|Alternatives]), Choices), nl, print('** Goal: '), print(Goal), print(' was matched with: '), print_inst_clause(Goal,Chosen), nl, print('** Alternative(s): '), member(Next,Alternatives), print_inst_clause(Goal,Next), fail. action(109,Cont,_) :- % 109 is "m" current_goal(Cont,P), bagof((P,Goals),clause(P,Goals),Bag), !, nl, print('=== matching clauses ==='), member((P,Goals),Bag), makelist(Goals,[],GoalList), print_clause(P,GoalList), fail. action(109,_,_) :- !, % m print('=== No matching clauses ==='), fail. action(63,_,_) :- !, % 63 is "?" nl, print('*** Debugging Options ***'), nl, tab, print(&), tab, print('list continuation path'), nl, tab, print(g), tab, print('list goal stack'), nl, tab, print('|'), tab, print('list backtrack path'), nl, tab, print(m), tab, print('list matching clauses'), nl, tab, print(a), tab, print('abort'), nl, tab, print(e), tab, print('exit from Prolog'), nl, tab, print(cr), tab, print('(carriage return) creep, i.e. single step'), nl, tab, print(l), tab, print('leap, i.e. continue till next spy point'), nl, tab, print(?), tab, print('print this help information'), nl, fail. action(10,_,_) :- !, % 31 is carriage return ( trace_mode, ! % (DEC10 Prolog only) ; assert(trace_mode)). % but 10 in EMAS prolog action(108,_,_) :- !, % 108 is "l" ( \+ trace_mode, ! ; abolish(trace_mode,0)). % changed lf(10) to l(108) for last clause action(97,_,_) :- abort. % 97 is "a" action(101,_,_) :- halt. % 101 is "e" action(_,_,_) :- bell, print('*** Type ? for help ***'), fail. current_goal([cont(_,[P|_],_)|_],P). trace(List) :- trace_mode, !, nl, print_list(List). trace(_). print_list([H|T]) :- !, print_list(H), print_list(T). print_list([]) :- !. print_list(clause(H,G)) :- !, print_clause(H,G). print_list(X) :- print(X). print_clause(H,G) :- nl, numbervars((H,G),0,_), print_head(H), print_body(G), fail. print_clause(_,_). print_inst_clause(Goal,(Goal,Body)) :- makelist(Body,[],GoalList), print_clause(Goal,GoalList), fail. print_inst_clause(_,_). print_head(true) :- !. print_head(Head) :- print(Head). print_body([]) :- !, put("."). print_body(G) :- print(' :-'), nl, print_goals(G). print_goals([0|Goals]) :- !, print('==>'), print_goals(Goals). print_goals([Goal]) :- !, tab, print(Goal), put("."). print_goals([Goal|Goals]) :- tab, print(Goal), put(","), nl, print_goals(Goals). /* skiptonl(31) :- !. % carriage return */ skiptonl(10) :- !. % line feed skiptonl(_) :- get0(C), skiptonl(C). bell :- put(7). /* tab :- put(9). */ tab :- tab(4). tracing(P) :- spy_point(P), !. tracing(P) :- trace_mode. trace_mode. tracing :- trace_mode, !, print_list('Trace mode already on'). tracing :- assert(trace_mode), print_list('Trace mode switched on'). notracing :- trace_mode, !, abolish(trace_mode,0), print_list('Trace mode switched off'). notracing :- print_list('Trace mode already off'). spying([P]) :- !, spying(P). spying([P|L]) :- !, spying(P), spying(L). spying(Name) :- atom(Name), bagof(P,current_predicate(Name,P),Bag), spying(Bag). spying(P) :- (P=F/N ; functor(P,F,N)), !, atom(F), ( spy_point(P), !, print_list(['Already spying on ', F/N]) ; assert(spy_point(P)), print_list(['Spy point placed on ', F/N]) ). nospying([P]) :- !, nospying(P). nospying([P|L]) :- !, nospying(P), nospying(L). nospying(Name) :- atom(Name), bagof(P,(current_predicate(Name,P), spy_point(Name,P)),Bag), nospying(Bag). nospying(P) :- (P=F/N, ! ; functor(P,F,N)), atom(F), ( retract(spy_point(P)), !, print_list(['Spy point removed from ', F/N]) ; print_list(['Not spying on ', F/N]) ). spying :- listing(spy_point/1). append([],L,L). append([X|L1],L2,[X|L3]) :- append(L1,L2,L3). member(X,[X|_]). member(X,[_|L]) :- member(X,L). makelist((A,B),L0,[A|L1]) :- !, makelist(B,L0,L1). makelist(true,L0,L0) :- !. makelist(A,L0,[A|L0]). revlist([],L,L). revlist([X|L],L0,L1) :- revlist(L,[X|L0],L1). /* test data: family tree predicates */ ancestor(X, Y) :- parent(X, Y). ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z). sibling(X, Y) :- parent(P, X), parent(P, Y), X \== Y. parent(abraham, ishmael). parent(abraham, isaac). parent(isaac, esau). parent(isaac, jacob). grandparent(X, Y) :- parent(X, Z), parent(Z, Y). cousin(X,Y) :- parent(P,X), parent(Q,Y), sibling(P,Q). /* XREF.DEF - system definitions for use with XREF.PL. Updated: 12 July 1983 These are the functors that have special significance as predicates */ system([_|_]). system(abolish(_,_)). system(revive(_,_)). system(incore(_)). system(asserta(_,_)). system(asserta(_)). system(assertz(_,_)). system(assertz(_)). system(retract(_)). system(clause(_,_,_)). system(clause(_,_)). system(recorda(_,_,_)). system(recordz(_,_,_)). system(recorded(_,_,_)). system(instance(_,_)). system(erase(_)). system(true). system(length(_,_)). system(name(_,_)). system(op(_,_,_)). system(var(_)). system(atom(_)). system(!). system(statistics). system(statistics(_,_)). system(functor(_,_,_)). system(call(_)). system(expand_term(_,_)). system(debug). system(debugging). system(display(_)). system(get(_)). system(get0(_)). system(leash(_)). system(nl). system(nodebug). system(print(_)). system(put(_)). system(skip(_)). system(tab(_)). system(trace). system(nl). system(ttyget(_)). system(ttyget0(_)). system(ttynl). system(ttyput(_)). system(ttyskip(_)). system(ttytab(_)). system(write(_)). system(writeq(_)). system(ancestors(_)). system(depth(_)). system(maxdepth(_)). system(subgoal_of(_)). system(abort). system(arg(_,_,_)). system(assert(_)). system(atomic(_)). system(bagof(_,_,_)). system(break). system(close(_)). system(compare(_,_,_)). system(compile(_)). system(consult(_)). system(current_atom(_)). system(current_functor(_,_)). system(current_predicate(_,_)). system(current_op(_,_,_)). system(fail). system(fileerrors). system(gc). system(gcguide(_)). system(halt). system(integer(_)). system(keysort(_,_)). system(listing). system(listing(_)). system(log). system(mode(_)). % not an evaluable predicate system(nofileerrors). system(nogc). system(nolog). system(nonvar(_)). system(numbervars(_,_,_)). system('C'(_,_,_)). % generated in grammar rules system(phrase(_,_)). system(prompt(_,_)). system(public(_)). % not an evaluable predicate system(read(_)). system(reconsult(_)). system(rename(_,_)). system(repeat). system(restore(_)). system(save(_)). system(save(_,_)). system(see(_)). system(seeing(_)). system(seen). system(setof(_,_,_)). system(sort(_,_)). system(tell(_)). system(telling(_)). system(told). system(trimcore). system(plsys(_)). % Note that portray/1 is not included here system(end_of_file). system('LC'). system('NOLC'). system(\+_). system((_->_)). system(spy _). system(nospy _). system(_=_). system(_ is _). system(_==_). system(_\==_). system(_=.._). system(_<_). system(_>_). system(_=<_). system(_>=_). system(_@<_). system(_@=<_). system(_@>=_). system(_@>_). system(_^_). system(_=\=_). system(_=:=_). /**/