Debugger
Debug metadata retains positions from the authoring .osp or .ospml source.
Protocol Split [DEBUGGER-PROTOCOLS]
- LSP (
osprey lsp) provides editor analysis. - DAP provides launch, breakpoints, stepping, stack traces, scopes, variables, evaluate, pause, and terminate.
F5 starts a DAP session; osprey.run remains a separate run command. LSP and
DAP use the same source identity and AST positions.
Debug Build Contract [DEBUGGER-BUILD]
osprey --debug --compile builds a native executable suitable for source-level
debugging.
--debugis accepted by--llvm,--compile, and--run.- Native debug builds emit LLVM debug metadata that lowers to DWARF.
- Native debug builds pass
-g -fno-omit-frame-pointerand default to-O0;OSPREY_DEBUG_OPToverrides the optimization flag. - Non-debug builds keep their release-oriented defaults.
--debug --target=wasm32is rejected.- Debug metadata uses DWARF 4 on macOS and DWARF 5 elsewhere.
- The compile unit uses
DW_LANG_Cas its debugger language code.
Minimum emitted metadata:
source_filename.!llvm.dbg.cu.!llvm.module.flagsincluding debug-info version and DWARF version.!DIFile.!DICompileUnit.!DISubprogramfor user functions and generatedmain.!DILocationon instructions derived from executable source statements.
Source Mapping [DEBUGGER-SOURCE-MAP]
The parser and lowerers must preserve source positions for executable statements and declarations.
Rules:
- Osprey AST positions use 1-based lines and 0-based columns.
- DAP/source debugger positions exposed to users use 1-based lines and columns.
- Emitted DWARF/
!DILocationlines and columns are 1-based. The 0-based AST column MUST be converted withcolumn + 1before emission, because LLVM reserves!DILocationcolumn0as the "no column" sentinel — emitting a raw 0-based column collides with it and yields off-by-one or dropped column data. A 1-based AST line maps straight through.
Editor Launch [DEBUGGER-EDITOR-LAUNCH]
For VS Code:
-
The debug provider resolves the Osprey source file (
.ospor.ospml) from the active editor or launch configuration. -
Dirty documents are saved or the debug launch is rejected.
-
The provider runs the version-matched compiler:
osprey--debug --compile -o -
The provider launches a DAP adapter, initially
lldb-dap, against the compiled native binary. -
DAP handles breakpoints, stepping, stack, scopes, and variables.
Launch configuration accepts the program, arguments, working directory, environment, stop-on-entry, debug output path, and LLDB-DAP path. Compiler resolution uses the extension's configured Osprey compiler.
Reusable Debugger Helpers [DEBUGGER-REUSE]
The osprey-debug crate owns source identity and native build policy without
depending on compiler or editor crates. The VS Code extension owns launch
normalization, lldb-dap discovery, and native pre-launch compilation.
Effect Trace [DEBUGGER-EFFECT-TRACE]
A native stack answers "how did control get here" only while control got here
by calling. A resumed continuation did not: the frames below a resume belong
to the handled body, the frames above belong to the arm, and the line joining
them is the perform the arm is answering. The physical stack cannot express
that edge, so a debug build MUST carry the effect trace of
MULTI-TRACE beside it.
A paused session presents the trace as its own view: performed at site,
handled at region, resumed n times, innermost first. Each entry resolves to
a source position through [DEBUGGER-SOURCE-MAP], so selecting one navigates
to the perform or the arm that answered it. Sites belonging to a
static effect MUST NOT appear — the rewrite removed them from the program
before code generation, and a trace naming them would describe code the binary
does not contain
(STAGE-RESIDUE).
For a continuation resumed at most once the trace is a straight line and adds context to the physical stack. For a multi-shot continuation it is the only stack that corresponds to the source, because the physical stack after a second resume describes a control path no source line expresses.
Variables [DEBUGGER-DBG-DECLARE]
Primitive function parameters use llvm.dbg.value. Primitive let bindings
use an addressable debug-only slot and llvm.dbg.declare, so LLDB/DAP can read
them while paused. Composite values have no Osprey-specific renderer.