Trace, debug and expansion of ellipses

When I invoke trace/0, the nested arguments are sometimes abbreviated with …, and I can get the full text with ‘w’, shorthand for write.

For illustration, consider this little toy example:

mylist([], empty) :-
    unknown. % raises an error

mylist([H | T], mylist(H, U)) :-
    mylist(T, U).

Now I invoke the predicate with a long list:

?- [mylist].
true.

?- trace.
true.

[trace]  ?- mylist([1,2,3,4,5,6,7,8,9], L).
   Call: (10) mylist([1, 2, 3, 4, 5, 6, 7, 8|...], _13658) ? write
   Call: (10) mylist([1, 2, 3, 4, 5, 6, 7, 8, 9], _13658) ? creep

Ok this works, I get the full display in the trace. Creeping on…

   Call: (11) mylist([2, 3, 4, 5, 6, 7, 8, 9], _14274) ? creep
   Call: (12) mylist([3, 4, 5, 6, 7, 8, 9], _14328) ? creep
   Call: (13) mylist([4, 5, 6, 7, 8, 9], _14382) ? creep
   Call: (14) mylist([5, 6, 7, 8, 9], _14436) ? creep
   Call: (15) mylist([6, 7, 8, 9], _14490) ? creep
   Call: (16) mylist([7, 8, 9], _14544) ? creep
   Call: (17) mylist([8, 9], _14598) ? creep
   Call: (18) mylist([9], _14652) ? creep
   Call: (19) mylist([], _14706) ? creep
ERROR: Unknown procedure: unknown/0
ERROR: In:
ERROR:   [20] unknown
ERROR:   [19] mylist([],empty) at c:/users/c7201178/documents/prolog/mylist.pl:2
ERROR:   [18] mylist([9],mylist(9,empty)) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [17] mylist([8,9],mylist(8,mylist(9,empty))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [16] mylist([7,8|...],mylist(7,mylist(8,...))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [15] mylist([6,7|...],mylist(6,mylist(7,...))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [14] mylist([5,6|...],mylist(5,mylist(6,...))) at c:/users/c7201178/documents/prolog/mylist.pl:5

In the stack trace, the list is still abbreviated. Is there a way to enable expansion of … in the stack trace, as well?

My use case is debugging the http server, that is, use_module(library(http/http_error)). In other words, the interactive “w” during the trace would be less helpful, rather a little command-line switch such as debug(…, [abbreviation(false)]).

Thank you for your consideration.

Best wishes,

Matthias

The stack traces by http_error are produced by library(prolog_stack). See the source for a number of Prolog flags that control the level of detail in the stack. Note that Prolog flags are inherited using copy semantics (they use copy-on-write). This implies that on a running server it doesn’t help to change this flag in the toplevel. You must do so before you start the HTTP server.

Ok, I see. If I increase the goal depth a bit, I get more detail:

(default goal depth is 3)

?- debug.
true.

[debug]  ?- mylist([1, 2, 3, 4, 5, 6, 7, 8, 9], L).
ERROR: Unknown procedure: unknown/0
ERROR: In:
ERROR:   [20] unknown
ERROR:   [19] mylist([],empty) at c:/users/c7201178/documents/prolog/mylist.pl:2
ERROR:   [18] mylist([9],mylist(9,empty)) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [17] mylist([8,9],mylist(8,mylist(9,empty))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [16] mylist([7,8|...],mylist(7,mylist(8,...))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [15] mylist([6,7|...],mylist(6,mylist(7,...))) at c:/users/c7201178/documents/prolog/mylist.pl:5

Now I increase it to 4:

[debug]  ?- set_prolog_flag(backtrace_goal_depth, 4).
true.

[debug]  ?- mylist([1, 2, 3, 4, 5, 6, 7, 8, 9], L).
ERROR: Unknown procedure: unknown/0
ERROR: In:
ERROR:   [20] unknown
ERROR:   [19] mylist([],empty) at c:/users/c7201178/documents/prolog/mylist.pl:2
ERROR:   [18] mylist([9],mylist(9,empty)) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [17] mylist([8,9],mylist(8,mylist(9,empty))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [16] mylist([7,8,9],mylist(7,mylist(8,mylist(9,empty)))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [15] mylist([6,7,8|...],mylist(6,mylist(7,mylist(8,...)))) at c:/users/c7201178/documents/prolog/mylist.pl:5
ERROR:   [14] mylist([5,6,7|...],mylist(5,mylist(6,mylist(7,...)))) at c:/users/c7201178/documents/prolog/mylist.pl:5

Indeed, I get one more list element, and a few more recursions in the second compound.

Thanks! Much appreciated.

In the http server, it looks like this:

:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_error)).
:- use_module(library(http/http_log)).
:- use_module(library(http/html_write)).
:- use_module(library(http/http_files)).
:- use_module(library(http/http_unix_daemon)).
:- use_module(library(http/http_parameters)).
:- use_module(library(http/http_wrapper)).

:- set_prolog_flag(backtrace_goal_depth, 10).
:- debug.
:- initialization http_daemon.

etc.

swipl server.pl --port=8001

Yes. A few small notes:

  • Since some versions (also 8.4.x), there is library(http/http_server) that gets you all the stuff you need for a basic http server. See the source or docs on what it bundled.

  • debug/0 runs everything in debug mode. Not sure you always want that. It makes things sometimes really slow and run out of memory. From the toplevel you can run ?- tdebug. to switch all threads in debug mode if you need it (and tnodebug/0 to go back to normal mode).

  • The http_unix_daemon library already uses :- initialization(http_daemon,main). The main initialization only has one goal, later registration replaces the already registered and runs after all other initialization unless swipl -l file.pl arg ... is used. So, you get

    swipl server.pl     % runs the server
    swipl -l server.pl  % loads the code, but doesn't run it, so you can play at the toplevel before running it.

Interesting, thanks!

Some of the tutorials haven’t been updated to use library(http/http_server). Here’s my attempt at some “tutorial” code: swipl-server-js-client/simple_server.pl at 9494950e461105f41e7a7f2b1123e1876aa2a057 · kamahen/swipl-server-js-client · GitHub

2 Likes