If I have a program that I use as a command-line tool, what are my options for debugging?
For the sake of the example, let's say that the program looks like this.
Listing of do_stuff.pl
:
main :-
current_prolog_flag(argv, Argv),
do_stuff(Argv),
halt.
main :-
halt(1).
With SWI-Prolog, I can compile this with:
swipl --goal=main -o do_stuff -c do_stuff.pl
And I can run it by simply calling
$ ./do_stuff foo bar baz
As it stands, this will exit with 1 if do_stuff/1
fails. How can I see the first (earliest, deepest) goal that failed? Or even better, the whole backtrace? I assumed that I should be able to use debug
and leash
, for example:
main :-
current_prolog_flag(argv, Argv),
debug, leash(+fail),
do_stuff(Argv),
halt.
... but there was nothing that I tried that worked.
The only half-assed idea I had was to throw an error for every predicate that I expect to succeed deterministically but does not. This is of course doable but seems a bit excessive?
Motivation
A program used as a command line tool is (usually) meant to run once, take its arguments, read its input, write output. In this context, what does failure mean? My interpretation is, an unexpected failure is an error in the program.
Unit testing might help (testing predicates in isolation); however, this will by definition not help for errors that are due to the programmers lack of understanding of the problem, the scope, or the tools. Only running the program with realistic input will catch this class of errors.
So, given the example above, if a certain use case causes do_stuff/1
to fail, and the program to exit with a non-zero code, what options does the programmer have in figuring out which predicate failed?
The answer linked in the comments gives one solution. But (if I understand it correctly) this does require that the programmer systematically checks along the execution flow until the offending predicate call is found.
This is exactly what I was hoping to avoid.