/*
*/ % buginit/1 - optionally opens a file to which debugging % output is directed. The argument is the file name. % buginit/0 - optionally opens file 'bug.log' for debugging % output. % user_bugwrite/1 - The user can define an output predicate % that outputs a term, and most likely follows it with % a newline. % bug/1 - brackets a call to a predicate with debugging % information % ?/1 - an operator synonym for bug/1. % bugclose/0 - closes the debugging file, if one was open % % flow/1,3 - can be used to note the flow of control at a % point in the program, for both normal code and DCG. % :- export buginit/1, buginit/0, bug/1, ? /1, bugclose/0, flow/1, flow/3. :- import user_bugwrite/1, bug$file/1. :- op(900, fy, [?, bug]). /*
*/ buginit(FileName) :- fopen(B, FileName, w), assert(bug$file(B)). buginit :- buginit('bug.log'). /*
*/ bugclose :- retract(bug$file(B)), !, fclose(B). bugclose. /*
You can also define your own output predicate, user_bugwrite/1, which will be used for all output if it is defined.
For example, bug/1, ?/1 can be used to debug the append/3 predicate as follows:
append([A|X], Y, [A|Z]) :- ? append(X,Y,Z).In this case the call, exit, redo, and fail ports around the recursive call to append/3 will all be written to either the standard output stream, the bugfile, or whereever user_bugwrite/1 sends the output.
*/ bug(X) :- bug$callfail(X), call(X), bug$exitredo(X). ? X :- bug(X). % Try user's bugwrite first, if not see if there's a bugfile % if not, just writeq. bug$write(X) :- user_bugwrite(X), !. bug$write(X) :- bug$file(B), !, writeq(B, X), nl(B). bug$write(X) :- writeq(X), nl. % bug$callfail/1 - writes a quoted term with the message % CALL when called, and FAIL when backtracked through % bug$exitredo/1 - writes a quoted term with the message % EXIT when called, and REDO when backtracked through bug$callfail(X) :- bug$write('CALL':X). bug$callfail(X) :- bug$write('FAIL':X), fail. bug$exitredo(X) :- bug$write('EXIT':X). bug$exitredo(X) :- bug$write('REDO':X), fail. /*
*/ flow(X):- bug$write('>':X). flow(X):- bug$write('<':X),fail. flow(X, Y, Y):- flow(X). % threaded for dcg rules