Avoids running goals to produce output that is only relevant while debugging. Includes pre-canned, often used calls that print informative messages for common debugging tasks.
See file examples/exo.pl
for a full pallette of examples.
?- debug( ex ). ?- debug_call( ex, length, list1/[x,y,z] ). % Length for list, list1: 3 ?- debug_call( ex, length, [list1,list2]/[[x,y,z],[a,b,c]], prefix('Some prefix') ). % Some prefix lengths for lists, list1: 3, list2: 3 ?- debug_call( ex, dims, [m1,m2]/[[a(x),a(y),a(z)],[xy(a,b),xy(c,d),xy(e,f)]] ). % Dimensions for matrices, (m1) nR: 3, nC: 1. (m2) nR: 3, nC: 2. ?- debug_call( ex, enum, testo/[a,b,c] ). % Starting enumeration of list: testo % 1.a % 2.b % 3.c % Ended enumeration of list: testo true. ?- debug_call( ex, info, 'My message is ~w.'/long ). % My message is long. true. % message above is printed in informational colour ?- debuc( ex, wrote, loc(file,csv) ). % Could not locate wrote on file specified by: file, and extensions: csv ?- csv_write_file( 'file.csv', [] ). ?- debuc( ex, wrote, loc(file,csv) ). % Wrote on file: 'file.csv' ?- debuc( ex, task(stop), 'write on file' ). At 15:44:1 on 2nd of Jul 2024 finished task: write on file. ?- assert( (simple_mess(KVs,Mess,Args):- KVs =[a=A,b=B], atom_concat(A,B,Mess), Args=[]) ). ?- debuc( ex, simple_mess([a=1,b=2]) ). % 12 true.
This library avoids the messy way in which package(debug)
deals with variable debug topics.
That is, their term expansion and subsequent pattern matching mishandles goals of the form
debugging/1 and debug/3 that have an unbound variable in the 1st argument.
debug_calls uses dynamic =.. .
?- debug_call_version( -V, -D ). V = 1:5:0, D = date(2022,12,29).
If Goal with arity +2 is available call that instead of Goal with extra arguments Mess and Args
that will be passed to debug/3. If the goal (original or +2) fail, nothing is printed by
debug_call and the debug_call(T,G)
itself succeeds.
?- goal( Goal, Mess, Args ).
Examples
?- assert( (simple_mess(KVs,Mess,Args):- KVs =[a=A,b=B], atom_concat(A,B,Mess), Args=[]) ). ?- debug_call( ex, simple_mess([a=1,b=2],
lib(debug)
does not create a record by inspecting the term (via expansion).
Particularly useful in sending uninstantiated Topics.
lib(debug)
does not create a record by inspecting the term (via expansion).
Particularly useful in sending uninstantiated Topics.
debugging(Topic)
succeeds. Else, it is false.
Similar to debugging/2, but does not fail for undefined Topic.
?- debug( something ). true. ?- debugging_status( something, Some ). Some = true. ?- debugging_status( some_else, Else ). Else = false.
?- nodebug( chained ). true. ?- debug( testo ). Warning: testo: no matching debug topic (yet) true. ?- debug( chained, 'debugs chains 1', [] ). true. ?- debug_chain( testo, chained, Prior ). Prior = false. ?- debug( chained, 'debugs chains 2', [] ). % debugs chains 2 true. ?- Prior = false, debug_set( Prior, chained ). Prior = false. ?- debug( chained, 'debugs chains 3', [] ). true
options(debug(true),Opts)
, with Restore
being instantiated to a term that can be used to restore the
original debug state of Topic (see options_restore/2). If options(debug(false),Opts)
then Topic is stopped from being debugged (Restore still holds the
correct term for restoring debugging state for topic to precall status).
?- assert( ( on_t(I,Topic) :- (debugging(Topic) -> write(I-y(Topic)) ; write(I-n(Topic))), nl ) ). ?- T = options, debug(T), on_t(1,T), debug_topic(T,[debug(false)],R), on_t(2,T), debug_set(R,T), on_t(3,T). 1-y(options) 2-n(options) 3-y(options) T = options, R = true. ?- T = options, nodebug(T), on_t(1,T), debug_topic(T,[debug(true)],R), on_t(2,T), debug_set(R,T), on_t(3,T). 1-n(options) 2-y(options) 3-n(options) T = options, R = false.
?- debug_topic( true, example ).
portray_clause(Term)
if we are debugging Topic.
The main novelty is the introduction of abbreviated Goals, that print bespoke message for often used debugging information. For example the following code ejects info on the legth of the list. Not only the code for calculating the length only happens if debugging for the topic ex, is on, but the message is also tailored to reporting lengths of lists.
?- debug(ex). ?- debug_call(ex, length, math_vars/[x,y,z]). % Length for list, math_vars: 3
Predicate can be used to call arbitrary Goal and then print a message after it has successfull completed.
When Goal is a known abbreviation from those shown below, the Arg usually qualifies the output generated.
When Goal is of the form call(Goal)
, Arg will be passed to debug(Topic,Mess,Arg)
.
As of v2 the last two arguments of the /4 version of the predicate where switched from Pfx and Arg
to Arg and Opts. Opts pass arbitary things to Goal, each abbreviation Goal can demand different options.
All abbreviation Goal them can take =prefix(Pfx)
= which corresponds to Pfx in the old /4 verison.
Opts will be forced to be a list via en_list/2, Goal will know what todo with it.
As of v1.2 it can work as a replacement to debug/3.
With v1.3 the debuc/3 shorthand was introduced.
Goal in:
debug(Topic, Mess, Arg)
. (Goal is called in non-deterministic context.)call(Goal)
loc(File,Exts)
or simply File in which case Exts = ''.
As of v2.0 the default is to print the basename, use path(abs)
in Opts.pred(Pid)
, the caller predicate, all(OrigOpts)
, shows all options,
internal(true)
, shows also '$' starting options.pred(Pid)
, the caller predicate, internal(true)
, shows also '$' starting options.arg(1)
) and its current instantiation (arg(2)
)loc(File,Exts)
or simply File in which case Exts = ''.
As of v2.0 the default is to print the basename, use path(abs)
in Opts.
See file examples/exo.pl
for a test suit including at least one example from each shorthand call.
?- debug(ex). ?- debuc( ex, (length([a,b,c],L),write(len(L)),nl) ). len(3) L = 3. ?- debug_call(ex, length, list1/[x,y,z]). % Length for list, list1: 3 ?- debug_call(ex, length, [list1,list2]/[[x,y,z],[a,b,c]] prefix('some prefix')). % some prefix lengths for lists, list1: 3, list2: 3 ?- debuc(ex, wrote, loc(file,csv)). % Could not locate wrote on file specified by: file, and extensions: csv ?- csv_write_file( 'file.csv', []). ?- debuc(ex, wrote, loc(file,csv)). % Wrote on file: 'file.csv' ?- debuc(ex, wrote, loc(file,csv), path(abs)). % Wrote on file: '/home/nicos/pl/lib/src/trace/file.csv' ?- debuc(ex, task(stop), 'write on file'). % At 15:44:1 on 2nd of Jul 2014 finished task: write on file. ?- debuc( ex, pwd, here ). % Pwd at, here, is: '/home/nicos/.local/share/swi-prolog/pack/Downloads/bio_db_repo-publish/bio_db_repo-20.09.14/data/hs/maps/hgnc/' true. ?- debuc( ex, pwd, false ). % Pwd: '/home/nicos/.local/share/swi-prolog/pack/Downloads/bio_db_repo-publish/bio_db_repo-20.09.14/data/hs/maps/hgnc/' true. ?- Etcs = [suv-17.09.26.txg,suv-17.09.21.txg], Etc = suv-17.09.26.txg, debuc(suv, ns_sel, c(Etc,Etcs,'suv file',true)). Continuing with: suv file, as: suv-17.09.26.txg, from non singleton list: [suv-17.09.26.txg,suv-17.09.21.txg]
At some point around SWI-Prolog 8, behaviour of debug/3 changed in being more strict about messages with no arguments. As of version 1.2 debug_call/3 can act as a replacement of debug/3 but with the old behaviour.
?- debug( ex, 'Messagging...', true ). Messagging... [[ EXCEPTION while printing message 'Messagging...' with arguments user:true: raised: format('too many arguments') ]] true. ?- debuc( ex, 'Messagging...', true ). % Messagging... true.
?- debug( dbg ). ?- debug_consec( dbg, 'what:~w', when ). % what: when <- in blue ?- debug_consec( dbg, 'what:~w', when ). % what: when <- in magenta ?- debug_consec( dbg, [blue,green], 'what:~w', when ). % what: when <- in blue ?- debug_consec( dbg, [blue,green], 'what:~w', when ). % what: when <- in green
Version 0.2
?- debug_consec( dbg, magenta, 'what:~w', when ). % what: when <- in magenta