Print last choice point - Reply 3

Cute! I normally re-run using the graphical debugger to find out. Maybe we should extend this to show a couple of frames of the stack above the choicepoint? In many cases I do an “up” in the gui tracer to find the call. Should we add it to the debug primitives?

1 Like

Can you elaborate? No clear idea comes to mind reading that statement.

Just considering to make it work nicely, e.g., by adding source location and the immediate caller (you often do not need more), invent a good name and add it to the core system just like spy/1, trap/1, etc.

An alternative could be to add some key binding to the toplevel you can use after an nondet answer. For example, typing ? could provide this. Thus

?- p.
true ?
   % choice point in r(a,b), File:Line
   % called by s(x), File:Line
true
3 Likes

Could the use of identifying the choice points also be used when det/1 is used, the code encounters a choice point when executed and throws an error? The error could be enhanced with the details as prototyped above.

I think this would be great.

Sound good to me, most especially to add it to plunit when it prints:

PL-Unit: Test my_test: Test succeeded with choicepoint

That’s where I find it most useful.

1 Like

For the fun, some progress. To use this, get the latest git version of Prolog as I’ve added a way to get access to the next candidate clause (according to clause indexing)

chp.pl (2.3 KB)

Some output

109 ?- p, print_chpoint.
Warning: Last choice after success r <alt clause>
Warning:   /home/janw/src/swipl-devel/build.debug/chp.pl:7: clause succeeded
Warning:   /home/janw/src/swipl-devel/build.debug/chp.pl:8: next candidate clause
Warning: Called from
Warning:   [11] p at /home/janw/src/swipl-devel/build.debug/chp.pl:4
true .

110 ?- p2, print_chpoint.
Warning: Last choice after success r2 <in clause choice>
Warning:   /home/janw/src/swipl-devel/build.debug/chp.pl:16
Warning: Called from
Warning:   [11] p2 at /home/janw/src/swipl-devel/build.debug/chp.pl:11
true .

111 ?- p3, print_chpoint.
Warning: Last choice after success between(1,2,1) <foreign>
Warning: Called from
Warning:   [11] p3 at /home/janw/src/swipl-devel/build.debug/chp.pl:23
true ;
true.

My plan is to add this to library(prolog_stack). First I let it shimmer a bit and wait for suggesting to make the messages clearer. One annoying thing is that it might be better to show the call rather than the success of the goal that left a choicepoint. We can’t access that without backtracking though :frowning:

3 Likes

Nice! :slightly_smiling_face:The only suggestion I would have is to reword the messages like this:

109 ?- p, print_chpoint.
% rename "Warning: Last choice after success r <alt clause>" to
Warning: r left a choice point in alternate clause (after success)
% rename "Warning:   ...chp.pl:7: clause succeeded"  to
Warning:   /home/janw/src/swipl-devel/build.debug/chp.pl:7: this clause succeeded
Warning:   /home/janw/src/swipl-devel/build.debug/chp.pl:8: next candidate clause
Warning: Called from
Warning:   [11] p at /home/janw/src/swipl-devel/build.debug/chp.pl:4
true .

110 ?- p2, print_chpoint.
% rename "Warning: Last choice after success r2 <in clause choice>" to
Warning: r2 left an in-clause choice point (after success)
Warning:   /home/janw/src/swipl-devel/build.debug/chp.pl:16
Warning: Called from
Warning:   [11] p2 at /home/janw/src/swipl-devel/build.debug/chp.pl:11
true .

111 ?- p3, print_chpoint.
% rename "Warning: Last choice after success between(1,2,1) <foreign>" to
Warning: between(1,2,1) left a foreign choice point (after success)
Warning: Called from
Warning:   [11] p3 at /home/janw/src/swipl-devel/build.debug/chp.pl:23
true ;
true.

Escape sequences

What would be really nice is to add escape sequences to the file and line number so one could click on it, on the terminal, and the editor would open.

Many terminal emulators support these links, (including teminator, by checking the “use custom URL handler” and providing a simple shell script to open the editor) and it is easy to do from SWI-Prolog:

link :-
   Line = 10,
   Url = 'file:///tmp/chp.pl',
   format('\e]8;;~w#~w\e\\This is a link to chp.pl:~w\e]8;;\e\\~n',[Url,Line,Line]).
9 ?- link.
This is a link to chp.pl:10    % this would be clickable in modern terminal emulators
true.

A simple script that can be used with e.g. terminator 's custom url handler (to open vim when the link is clicked):

#!/usr/bin/env swipl

:- use_module(library(url)).

:- initialization(main,main).

main([Url]) :-
   parse_url(Url,Attrs),
   memberchk(path(File),Attrs),
   memberchk(fragment(Line),Attrs),
   format(string(Cmd),"terminator -x vim +~w '~w'",[Line,File]),
   shell(Cmd).

gcc and ls --hyperlink=auto are now emitting these kinds of links, albeit gcc decided to use it only for -Wname-of-option documentation links.

Thanks for the text updates. I think that is better. I wasn’t very happy with the text anyway.

Nice to know about this escape sequence. I already hacked something using a plugin in terminator that does this for anything that looks like a filename followed by :Line. That was not very nice though. A much more widely supported option is better. Mostly means we must have a central rule to link to file locations and use this from all messages that include a file position. Should be doable :slight_smile: Guess we do need a flag to avoid problems with some terminal emulators? Even good old xterm doesn’t get upset though (doesn’t like either :slight_smile: )

A post was split to a new topic: Hyperlinks in terminal

Pushed some stuff that allows for * as a reply to a toplevel answer that will call this. Added the core functionality as print_last_choice_point/0,2 to library(prolog_stack). Adding with unit tests is an exercise to the user :slight_smile:

2 Likes

That is very nice, the ‘*’ in the toplevel result is useful too, good addition.

Could you add it to pl_unit when it prints:

PL-Unit: Test my_test: Test succeeded with choicepoint

? I think that would be useful too.

I left it as an exercise :slight_smile: Haven’t looked at it. There is quite some indirection in plunit, so you may need to add the choicepoint as output argument in quite a few places :frowning:

1 Like

:grinning_face_with_smiling_eyes:

The ‘*’ at the toplevel result menu has already proven useful many times already in a short time! Quite good thinking adding that to the menu.

Finally needed to use the * at the toplevel to find a choice-point.

Normally I work on Windows and just use gtrace/0 in the code to find such problems but for a current problem need to work on Ubuntu and don’t have the graphics (X-windows) installed and working so gtrace/0 is out.

Was going nuts looking for the choice-point so when the toplevel showed true instead of pressing the space bar or hitting enter just entered *, bingo, out comes the call stack and identifies the predicate with the choice-point.

Turns out the code was using _ with setof/3 in the goal instead of using existential (caret) operator (^),

Choice-point version

setof(A,info(A,_),As)

No choice-point version

setof(A,[B]^info(A,B),As)