Remove autotools dependency to ease packaging and installation
Fix issue with debugging non-module source files
Support next request to skip over a goal
Support stepOut request to skip to the end of a goal
Support exceptionInfo request
Hereās an example of using debug_adapter to step through code in various directions:
Please let me know if you hit any issues stepping around youāre code. SWI-Prolog is complicated and Iād like to collect some test cases
Comments and requests are welcome. There are still several desirable features to be implemented, specifically I intend to tackle breakpoints of all sorts next.
Yes, the way I see it LSP and DAP serve different and complementary goals - an LSP server is in charge of exposing semantic analysis of a language (Prolog) to the IDE, while the DAP server is in charge of facilitating debugging code.
So a DAP server essentially handles runtime notions where LSP may rely on static analysis for most of its operations.
And thanks you! Iāll definitely ask for help if/when I get stuck. Up to this point xpce source code was a great resource.
Note that wrong behavior may well not be your mistake. Verify how the built-in debugger works first. Notably unifications immediately following the head, the => rules and $ are not all correctly handled by the debugger.
Basic examples would include finding references to some defined predicate and deciding whether a certain term in a body of a clause written in a source file represents ācodeā or ādataā, and providing these insights to the IDE.
Hereās an example of setting a breakpoint on the fly and using (c)ontinue from inside test_noun1/2 to run until backtracking and hitting the breakpoint inside test_noun2/2:
Now, DAP also defines conditional breakpoints where the user submits a piece of code to act as a condition for entering the tracer while setting a breakpoint. This feature should be straightforward to support with break_hook/6 (in fact this is the first use case listed in this hookās docs), and dap-mode implements support for it on the client-side for Emacs (certainly also VSCode has it, but I havenāt checked), so I think it can be a nice addition in the next version, although Iām not sure how often itāll actually come useful.
I use it often when i debug more complex use cases that have to generate all kinds of structures first, before the one is reached that requires debugging.
Usually, i then place an (Arg = āknown valueā ā trace ; true) into the code to conditionally start the debugger exactly there ā¦
Conditional breakpoints are now available in version 0.4.5 of the debug_adapter, along with DAP ālog pointsā which are a similar feature to the familiar trace points SWI-Prolog provides via trace/1,2.
Hereās an illustration:
Each breakpoint can be associated with a condition, which is a Prolog goal that will be executed in the context of the frame where the breakpoint was hit, including variables bindings.
Also visible in the above screenshot is the āHit Conditionā feature, which is a simple skip count that can be set per breakpoint using e.g. M-x dap-breakpoint-hit-condition with dap-mode - requesting that the breakpoint will be skipped for the specified number of visits periodically, so in the example above the first breakpoint only fires every other time.
Lastly, one can also turn a breakpoint into a logpoint (with e.g. M-x dap-breakpoint-log-message), causing the specified message to be logged whenever the breakpoint is hit, instead of breaking the program run, as exemplified with the print me! message printed in the above example.
Logpoints also respect breakpoint conditions and hit conditions, so the message is only logged when X = 2 in the screenshot.