Skip to content

Debugger#1410

Merged
LadyCailin merged 17 commits intomasterfrom
debugger
Apr 4, 2026
Merged

Debugger#1410
LadyCailin merged 17 commits intomasterfrom
debugger

Conversation

@LadyCailin
Copy link
Copy Markdown
Member

@LadyCailin LadyCailin commented Mar 13, 2026

This PR implements a DAP server, to support debugging via the VS Code plugin.

This is a major change in the script evaluation process, which changes
how "special execution" functions work. Previously, functions could
choose to implement execs instead of exec, which received a ParseTree,
instead of Mixed. This allowed the individual function to decide how or
even if the ParseTree nodes were further executed. This works in
general, however it has several drawbacks.

In particular, the core evaluation loop loses control over the script
once it decends into individual functions. Therefore features like
Ctrl+C in command line scripts relied on each of these "flow" functions
to implement that feature correctly, and only some of them did. This
also prevents new features from being implemented as easily, like a debugger,
since the evaluation loop would need to be modified, and every single
flow function would need to make the same changes as well.

This also has several performance benefits. Using a recursive approach
meant that each frame of MethodScript had about 3 Java frames, which is
inefficient. The biggest performance change with this is moving away
from exception based control flow. Previously, return, break, and
continue were all implemented with Java exceptions. This is way more
expensive than it needs to be, especially for very unexecptional cases
such as return(). Now, when a proc or closure returns, it triggers a
different phase in the state machine, instead of throwing an exception.

This also unlocks future features that were not possible today. A
debugger could have been implemented before (though it would have been
difficult) but now an asynchronous debugger can be implemented.
async/await is also possible now. Tail call optimizations can be done,
execution time quotas, and the profiler can probably be improved.
Previously, callback invocations required re-entering the eval loop from
the top, which defeats the purpose of the iterative loop. In principal,
the functions that call Callables need to become flow functions to
behave correctly, but for basic yield-style invocations, this
infrastructure is too heavy, so CallbackYield is a new class which puts
the function in terms of an exec-like mechanism, only introducing the
Yield object, which is just a queue of operations, effectively.

More functions need to convert to this, but as a first start, array_map
has been converted. Some of the simpler FlowFunctions might be able to
be simplified to this as well.
These are the "easy" functions to convert.
This adds on a debugger to the evaluation loop, that allows for pausing,
saving state, then resuming from saved state.
…ebug support

   - Add MSDebugServer implementing the Debug Adapter Protocol over TCP,
     with launch/attach modes, breakpoints, step-over/step-in/step-out,
     variable inspection, exception breakpoints, and watch expressions
   - Add multi-thread DAP support: register/unregister threads, per-thread
     pause states, sync and async stepping modes (sync blocks in place,
     async snapshots state and resumes on a new thread)
   - Refactor DebugContext into a full thread-aware debug state manager with
     per-thread StepMode, ThreadDebugState, and a thread registry for DAP
   - Add DaemonManager lifecycle listeners and thread-aware waitForThreads,
     so the debug session stays alive while background threads run
   - Extract spawnExecutionThread() to centralize execution thread lifecycle
     (run, await daemons, signal completion) in one place
   - Fix StackTraceManager thread affinity: remove isDebugAdopted flag so
     background threads (x_new_thread) get their own STM instead of sharing
     the main thread's, which was corrupting call depth for step-over
   - Fix skippingResume flag: clear unconditionally on source line change
     rather than requiring shouldStop=true, which blocked step-over returns
   - Add StackTraceFrame.getTarget() for debugger source mapping
   - Add Breakpoint condition/hitCount/logMessage support
   - Wire up cmdline interpreter (--debug flag) and lang server for DAP
   - Add DAPTestHarness and dual sync/async integration tests for step-over
     and multi-thread step-over scenarios
   - Add debugger dependency (lsp4j.debug) to pom.xml
@LadyCailin LadyCailin changed the base branch from iterativeInterpreter to master March 21, 2026 15:01
…e tests

 - Enable managed execution mode in CommandHelperPlugin so the debug
   session survives script completion on embedded (Minecraft) servers
 - Fix hit-count breakpoint deduplication: multiple AST nodes on the same
   source line no longer increment the hit counter more than once per
   visit. Uses column-based caching in ThreadDebugState to distinguish
   "same line, different node" from "new loop iteration, same first node"
 - Add evaluateBreakpointCondition() to DebugContext with per-thread
   cache-aware hit-count and condition evaluation
 - Add Breakpoint.getHitCount() getter
 - Add MSDebugServer managed mode support: setManagedExecution(),
   startedOnHostMainThread capture, resumeOnHostMainThread() for
   resuming on the server main thread, dynamic scripting mode flag
   in evaluate handler
 - Add 21 new DAP integration tests (39 total) covering: managed mode
   step-over, thread events, disconnect; variables/scopes; CArray
   expansion (indexed, associative, nested); evaluate expressions;
   exception breakpoints; conditional and hit-count breakpoints;
   step-in, step-out, step-in targets; disconnect resumes execution
@LadyCailin LadyCailin merged commit fbe26dd into master Apr 4, 2026
3 of 4 checks passed
@LadyCailin LadyCailin deleted the debugger branch April 4, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant