If there is a guard, the implementation is basically
Head ?=> Guard, !, Body.
The ?=> operator from picat, which performs SSU but does not commit is not public, but is internally used to deal with guards. I think the trick would be to extend the trace condition code and use the program counter to find that we are in the guard. You have the clause. A flag will tell you it is an SSU rule. Next you need to step over the VM code to find that the current PC is between the SSU neck and subsequent !. That does not help if the guard is not a simple built-in, but a user defined predicate that calls other predicates. One option to that could be to use the silent skip only for system predicates. Doable, but some work … If I get a PR, great. Otherwise it just goes on the stack
It all depends how you implement this. The tracer runs on calls from the VM (Virtual machine). When in debug mode it always makes these calls. The trace function first does some filtering, e.g., are we in debug or trace mode, when in debug mode, did we hit a spy point? When in trace mode, are we “skipping”, etc. If that all is positive it calls prolog_trace_interception/4, which drives also the graphical debugger. If that fails it uses the C defined command line debugger.
My suggesting was be to add hiding the guards to conditions in the trace filtering. An alternative might be to “move” the unify port. This port is an addition to the normal port model. It fires after the head unification. It is used by the gui tracer, such that stepping into a call first shows the clause whose head unified. We could change the VM such that for guarded SSU rules the unify code fires at the ! that ends the guard by introducing a new instruction that simply uses the cut,
and then triggers the unify port. That would make @mgondan1’s idea work for the guitracer, but not for the conventional tracer.
As you point out, a command to skip all the guards could be a serious alternative.
Its not correct because if the guard fails the debugger is still off. Besides that, the deal with SWI-Prolog has always been that code did not have to be prepared to be able to debug. I’d rather keep it that way unless we get something big in return. The simplest solution is probably one of the two I suggested: play around with the location of the unify port or filter the guard calls away in the trace function condition.