This topic has lots of great detail on the text color used for port traces. However, there is still other text coloring going on in the graphical debugger that I’m not sure the meaning of.
For example, the perches/1 and diving_duck/1 predicates below are colored red, while the rest of the predicate names are white. What does that mean?
The colours in the source code are from PceEmacs or more specifically from library(prolog_colour). To figure out what something means, click on the coloured fragment and it will give some explanation at the bottom of the window. If this case it doesn’t really say it is not called Instead, it lists what it knows about the predicate.
A red predicate head means the thing is not called. A red call means the target is not defined. For this to work properly though one needs either a single file or everything to be split up into modules. Notably a program using multiple files but no modules will not give accurate results. If there are user-defined meta predicates these require a proper declaration.
Note that the source view is an embedded PceEmacs editor in read-only mode. You can used the ‘e’ command to switch to write mode, edit and save using ^x^s, compile using ^c^b (compile buffer).
This allows for fixing things are while running:
See the output is incorrect (failure, wrong answer, success while failure was expected, etc).
Use ‘e’, edit, ^x^s, ^c^b, hit ‘r’ to retry and test again.
Another useful command is ^x2, Emacs’ split-window. This is mapped by PceEmacs to create a new editor window showing the same file (initially at the same cursor location). You can use the new window with all usual menu functionality for editing. Multiple editor windows on the same file are kept in sync at any time (they are all visualizations of the same editor buffer).
This strategy for hot-fixing is something unique to Prolog as retry provides us with a time machine. It takes a little while to get used to, but after that it is a life saver for debugging and fixing issues in a program state that takes long to reproduce. Think of long runtime to reach the critical point or a lot of user interaction for interactive programs.
The main difference is the time machine provided by retry, which backtracks to the start of a goal before re-running it. If the program has no interfering side effects this means you are really back at the old state. This has two enormous advantages. While walking around in languages without such a time machine you have to be very careful not to jump over the buggy function because if you did, you often have to restart from the beginning. When it is no problem to skip over the buggy code, one can use hierarchical debugging: first step over the whole goal. If you do not like the result, retry and step over each of the sub goals until you find one that misbehaves, etc.