debugger

package
v1.37.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 13, 2026 License: BSD-3-Clause Imports: 10 Imported by: 0

Documentation

Overview

Package debugger implements the ELPS debugger engine (Layer 1). It provides breakpoint management, stepping, variable inspection, and debug evaluation without any external protocol dependencies.

The engine implements the lisp.Debugger interface and communicates with external consumers (such as a DAP server) through event callbacks and a channel-based pause/resume mechanism.

Concurrency model: The ELPS eval goroutine calls the Debugger hook methods (OnEval, WaitIfPaused, etc.). When paused, it blocks on a channel. The external consumer (DAP server goroutine) sends commands via Resume/StepInto/StepOver/StepOut. This is thread-safe by design.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EvalCondition

func EvalCondition(env *lisp.LEnv, condition string) bool

EvalCondition evaluates a breakpoint's condition expression in the given environment. Returns true if the condition is satisfied (or if there is no condition). The evaluatingCondition flag on the engine must be set before calling this to prevent re-entrancy.

func EvalInContext

func EvalInContext(env *lisp.LEnv, source string) *lisp.LVal

EvalInContext parses and evaluates all expressions in the paused environment, returning the result of the last one (progn semantics). Short-circuits on first error. This allows the debug console to evaluate multi-expression input like "(set 'x 10) (+ x y)".

func EvalSingleInContext added in v1.23.0

func EvalSingleInContext(env *lisp.LEnv, source string) *lisp.LVal

EvalSingleInContext parses and evaluates only the first expression in the paused environment. Used for hover tooltips where multi-expression evaluation is inappropriate.

func ExtractPrefix added in v1.23.1

func ExtractPrefix(text string, column int) string

ExtractPrefix extracts the completion prefix from text at the given column position. Column is 1-based (DAP convention). The prefix is the word being typed, walking backward from the cursor to whitespace or an open paren.

func FormatValue

func FormatValue(v *lisp.LVal) string

FormatValue returns a human-readable string representation of an LVal, suitable for display in a debugger variables view.

func FormatValueWith added in v1.22.0

func FormatValueWith(v *lisp.LVal, eng *Engine) string

FormatValueWith returns a human-readable string representation of an LVal, using the engine's registered formatters for LNative values. For all other types it delegates to FormatValue. If eng is nil, falls back to FormatValue.

func InterpolateLogMessage added in v1.22.0

func InterpolateLogMessage(env *lisp.LEnv, template string) string

InterpolateLogMessage evaluates a log point message template, replacing {expr} placeholders with the result of evaluating each expression.

Types

type Breakpoint

type Breakpoint struct {
	ID           int
	File         string
	Line         int
	Condition    string // optional: Lisp expression to evaluate
	HitCondition string // optional: hit count expression (e.g., ">5", "==3", "%2")
	LogMessage   string // optional: log point message template with {expr} interpolation
	Enabled      bool
	// contains filtered or unexported fields
}

Breakpoint represents a location where execution should pause.

func (*Breakpoint) IncrementHitCount added in v1.22.0

func (bp *Breakpoint) IncrementHitCount() bool

IncrementHitCount increments the breakpoint's hit count and returns whether the hit condition is satisfied.

type BreakpointSpec added in v1.22.0

type BreakpointSpec struct {
	Line         int
	Condition    string
	HitCondition string
	LogMessage   string
}

BreakpointSpec describes a breakpoint to set (used by SetForFileSpecs).

type BreakpointStore

type BreakpointStore struct {
	// contains filtered or unexported fields
}

BreakpointStore manages breakpoints indexed by file:line for O(1) lookup. All methods are safe for concurrent use from the DAP server goroutine while the eval goroutine reads via Match.

func NewBreakpointStore

func NewBreakpointStore() *BreakpointStore

NewBreakpointStore returns an empty breakpoint store.

func (*BreakpointStore) All

func (s *BreakpointStore) All() []*Breakpoint

All returns all breakpoints in the store.

func (*BreakpointStore) ClearFile

func (s *BreakpointStore) ClearFile(file string)

ClearFile removes all breakpoints for the given file.

func (*BreakpointStore) ExceptionBreak

func (s *BreakpointStore) ExceptionBreak() ExceptionBreakMode

ExceptionBreak returns the current exception breakpoint mode.

func (*BreakpointStore) Match

func (s *BreakpointStore) Match(src *token.Location) *Breakpoint

Match returns the breakpoint at the given source location, or nil.

func (*BreakpointStore) Remove

func (s *BreakpointStore) Remove(file string, line int) bool

Remove removes the breakpoint at file:line. Returns true if it existed.

func (*BreakpointStore) RemoveByID added in v1.24.0

func (s *BreakpointStore) RemoveByID(id int) bool

RemoveByID removes the breakpoint with the given ID. Returns true if it existed. This is used by the debug REPL's "delete N" command.

func (*BreakpointStore) Set

func (s *BreakpointStore) Set(file string, line int, condition string) *Breakpoint

Set adds or replaces a breakpoint at the given file:line. Returns the breakpoint with its assigned ID.

func (*BreakpointStore) SetExceptionBreak

func (s *BreakpointStore) SetExceptionBreak(mode ExceptionBreakMode)

SetExceptionBreak sets the exception breakpoint mode.

func (*BreakpointStore) SetForFile

func (s *BreakpointStore) SetForFile(file string, lines []int, conditions []string) []*Breakpoint

SetForFile replaces all breakpoints in a file. This implements the DAP setBreakpoints semantics (full replacement, not incremental).

func (*BreakpointStore) SetForFileSpecs added in v1.22.0

func (s *BreakpointStore) SetForFileSpecs(file string, specs []BreakpointSpec) []*Breakpoint

SetForFileSpecs replaces all breakpoints in a file using full specs. This supports hit conditions and log messages in addition to conditions.

type CommandHandler added in v1.26.0

type CommandHandler func(args string) (response string, refresh bool, err error)

CommandHandler handles a custom slash command in the debug console. args is the text after the command name (may be empty). response is the text shown to the user. refresh indicates whether the Variables pane should be invalidated.

type CompletionCandidate added in v1.23.1

type CompletionCandidate struct {
	Label  string // symbol name (possibly qualified with package prefix)
	Type   string // "variable", "function", "keyword", "module"
	Detail string // e.g. package name or "<builtin>"
}

CompletionCandidate represents a single auto-complete suggestion.

func CompleteInContext added in v1.23.1

func CompleteInContext(env *lisp.LEnv, prefix string) []CompletionCandidate

CompleteInContext returns completion candidates for the given prefix in the context of env. It collects candidates from function locals, current package symbols, qualified package symbols, package names, exported symbols from used packages, and keywords.

An empty prefix returns no candidates (matches REPL behavior).

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine implements lisp.Debugger and provides the core debugging primitives: breakpoints, stepping, variable inspection, and debug eval.

func New

func New(opts ...Option) *Engine

New creates a new debugger engine.

func (*Engine) AfterFunCall added in v1.22.0

func (e *Engine) AfterFunCall(env *lisp.LEnv) bool

AfterFunCall implements lisp.Debugger. Called in Eval after EvalSExpr returns. Uses the stepper's ShouldPausePostCall to check if step-out should fire at the current (post-pop) depth, and clears the stepOutReturned flag.

func (*Engine) AllocSourceRef added in v1.22.0

func (e *Engine) AllocSourceRef(name, content string) int

AllocSourceRef allocates a source reference ID for virtual source content. Returns the reference ID that can be used in DAP source requests.

func (*Engine) Breakpoints

func (e *Engine) Breakpoints() *BreakpointStore

Breakpoints returns the breakpoint store for external management (e.g., by a DAP server handling setBreakpoints requests).

func (*Engine) Command added in v1.26.0

func (e *Engine) Command(name string) CommandHandler

Command returns the handler registered for the given command name, or nil if no handler is registered.

func (*Engine) CommandDescription added in v1.28.0

func (e *Engine) CommandDescription(name string) string

CommandDescription returns the description for a single command, or empty string if the command is not registered or has no description.

func (*Engine) CommandDescriptions added in v1.28.0

func (e *Engine) CommandDescriptions() map[string]string

CommandDescriptions returns a map of command name to description for all registered commands. Commands without descriptions have empty strings.

func (*Engine) CommandNames added in v1.26.0

func (e *Engine) CommandNames() []string

CommandNames returns the sorted list of registered command names.

func (*Engine) Disable

func (e *Engine) Disable()

Disable deactivates the debugger without detaching it.

func (*Engine) Disconnect

func (e *Engine) Disconnect()

Disconnect atomically disables the debugger and resumes execution if paused.

func (*Engine) Enable

func (e *Engine) Enable()

Enable activates the debugger. Hook calls are only made when enabled.

func (*Engine) EvalCount added in v1.22.0

func (e *Engine) EvalCount() int64

EvalCount returns the number of times OnEval has been called. This is useful for tests that need to wait for evaluation to start.

func (*Engine) EvalInContext added in v1.22.0

func (e *Engine) EvalInContext(env *lisp.LEnv, source string) *lisp.LVal

EvalInContext evaluates all expressions in source in a paused environment, returning the last result (progn semantics). Sets the evaluatingCondition guard so that the OnEval hook does not re-enter breakpoint logic (which would deadlock since EvalInContext runs on the DAP server goroutine, not the eval goroutine).

func (*Engine) EvalSingleInContext added in v1.23.0

func (e *Engine) EvalSingleInContext(env *lisp.LEnv, source string) *lisp.LVal

EvalSingleInContext evaluates only the first expression in source in a paused environment. Used for hover tooltips where multi-expression evaluation is inappropriate. Sets the same evaluatingCondition reentrancy guard as EvalInContext.

func (*Engine) FormatNative added in v1.22.0

func (e *Engine) FormatNative(v any) string

FormatNative returns a formatted string for a native Go value using the registered formatter. Returns empty string if no formatter is registered for the value's type.

func (*Engine) GetSourceRef added in v1.22.0

func (e *Engine) GetSourceRef(id int) (string, bool)

GetSourceRef retrieves virtual source content by reference ID. Returns the content and true if found, or empty string and false if not.

func (*Engine) IsEnabled

func (e *Engine) IsEnabled() bool

IsEnabled implements lisp.Debugger.

func (*Engine) IsPaused

func (e *Engine) IsPaused() bool

IsPaused returns true if the eval goroutine is currently blocked in WaitIfPaused.

func (*Engine) NativeChildren added in v1.22.0

func (e *Engine) NativeChildren(v any) []NativeChild

NativeChildren returns the expandable child bindings for a native Go value using the registered formatter. Returns nil if no formatter is registered or the formatter returns no children.

func (*Engine) NotifyExit added in v1.22.0

func (e *Engine) NotifyExit(exitCode int)

NotifyExit fires an EventExited event to notify the DAP server that the program has finished. This should be called from the eval goroutine after evaluation completes, while the DAP server is still running.

func (*Engine) OnError

func (e *Engine) OnError(env *lisp.LEnv, lerr *lisp.LVal) bool

OnError implements lisp.Debugger. Called when an error condition is created. Returns true if execution should pause.

func (*Engine) OnEval

func (e *Engine) OnEval(env *lisp.LEnv, expr *lisp.LVal) bool

OnEval implements lisp.Debugger. Called before each expression with a real source location.

func (*Engine) OnFunEntry

func (e *Engine) OnFunEntry(env *lisp.LEnv, fun *lisp.LVal, fenv *lisp.LEnv)

OnFunEntry implements lisp.Debugger. Checks function breakpoints. OnFunEntry implements lisp.Debugger. Checks function breakpoints and step-in targets (smart step-into).

func (*Engine) OnFunReturn

func (e *Engine) OnFunReturn(env *lisp.LEnv, fun, result *lisp.LVal)

OnFunReturn implements lisp.Debugger. Detects the step-out condition before the frame is popped: if the stepper is in StepOut mode and the post-return depth will be less than the recorded depth, set the stepOutReturned flag so that AfterFunCall (or OnEval as a safety net) can pause at the call-site expression.

func (*Engine) PausedState

func (e *Engine) PausedState() (*lisp.LEnv, *lisp.LVal)

PausedState returns the env and expr where execution is paused, or nil if not paused.

func (*Engine) ReadyCh added in v1.22.0

func (e *Engine) ReadyCh() <-chan struct{}

ReadyCh returns a channel that is closed when SignalReady is called. Embedders can select on this to wait for the DAP client to finish setting breakpoints before starting evaluation.

func (*Engine) RegisterCommand added in v1.26.0

func (e *Engine) RegisterCommand(name string, h CommandHandler, desc ...string)

RegisterCommand registers a custom slash command handler at runtime. name is the command name without the leading "/" (e.g., "reload"). An optional description string can be provided as the third argument. Safe to call before debugging starts.

func (*Engine) RegisterFormatter added in v1.22.0

func (e *Engine) RegisterFormatter(typeName string, f VariableFormatter)

RegisterFormatter registers a custom formatter for a native Go type. typeName should match fmt.Sprintf("%T", value) for the values you want to format. Safe to call before debugging starts.

func (*Engine) RegisterScopeProvider added in v1.23.0

func (e *Engine) RegisterScopeProvider(p ScopeProvider)

RegisterScopeProvider adds a custom scope provider at runtime. Safe to call before debugging starts.

func (*Engine) RequestPause added in v1.22.0

func (e *Engine) RequestPause()

RequestPause requests that the eval goroutine pause at the next expression. This is used by the DAP pause command. The flag is cleared when the engine actually pauses in WaitIfPaused.

func (*Engine) Resume

func (e *Engine) Resume()

Resume sends a Continue action to the paused eval goroutine.

func (*Engine) ScopeProviders added in v1.23.0

func (e *Engine) ScopeProviders() []ScopeProvider

ScopeProviders returns a copy of the registered scope providers.

func (*Engine) SetEventCallback

func (e *Engine) SetEventCallback(cb EventCallback)

SetEventCallback sets or replaces the event callback. It is safe to call after construction (e.g., when a DAP handler wires itself up).

func (*Engine) SetFunctionBreakpoints added in v1.22.0

func (e *Engine) SetFunctionBreakpoints(names []string) []string

SetFunctionBreakpoints replaces the set of function breakpoints. Each name should be a function name as the user would type it (e.g., "add" or "user:add"). Returns the names that were set.

func (*Engine) SetSourceLibrary added in v1.22.1

func (e *Engine) SetSourceLibrary(lib lisp.SourceLibrary)

SetSourceLibrary sets or replaces the source library used to serve source content for the DAP source request handler. This is safe to call after construction, allowing embedders to wire the library once it becomes available (e.g., after loading a phylum archive).

func (*Engine) SetSourceRoot added in v1.32.0

func (e *Engine) SetSourceRoot(dir string)

SetSourceRoot overrides the source root directory at runtime. This allows a DAP handler to reflect the client's sourceRoot preference from launch/ attach arguments. It is safe to call before evaluation starts.

func (*Engine) SetStepGranularity added in v1.23.0

func (e *Engine) SetStepGranularity(g string)

SetStepGranularity sets the stepping granularity for the next step command. The value is consumed by WaitIfPaused when configuring the stepper. Use "instruction" for expression-level stepping; any other value (including empty) defaults to line-level stepping.

func (*Engine) SetStepInTarget added in v1.23.0

func (e *Engine) SetStepInTarget(qualifiedName string, count int)

SetStepInTarget configures targeted step-in. The engine will use StepOver mode but pause via OnFunEntry when the Nth matching function is entered. count=0 means first match.

func (*Engine) SetStopOnEntry added in v1.23.0

func (e *Engine) SetStopOnEntry(stop bool)

SetStopOnEntry overrides the stop-on-entry flag at runtime. This allows a DAP handler to reflect the client's stopOnEntry preference, which may differ from the embedder's WithStopOnEntry option. It is safe to call before evaluation starts. If called while the engine is already paused on entry, the caller must also Resume the engine to unblock it.

func (*Engine) SignalReady added in v1.22.0

func (e *Engine) SignalReady()

SignalReady signals that the external consumer has finished its configuration (e.g., DAP configurationDone). Embedders waiting on ReadyCh() will be unblocked. Safe to call multiple times.

func (*Engine) SourceLibrary added in v1.22.0

func (e *Engine) SourceLibrary() lisp.SourceLibrary

SourceLibrary returns the configured source library, or nil if not set.

func (*Engine) SourceRoot added in v1.22.0

func (e *Engine) SourceRoot() string

SourceRoot returns the configured source root directory, or empty string if not set.

func (*Engine) StepInto

func (e *Engine) StepInto()

StepInto sends a StepInto action to the paused eval goroutine.

func (*Engine) StepOut

func (e *Engine) StepOut()

StepOut sends a StepOut action to the paused eval goroutine.

func (*Engine) StepOver

func (e *Engine) StepOver()

StepOver sends a StepOver action to the paused eval goroutine.

func (*Engine) WaitIfPaused

func (e *Engine) WaitIfPaused(env *lisp.LEnv, expr *lisp.LVal) lisp.DebugAction

WaitIfPaused implements lisp.Debugger. Blocks the eval goroutine until the DAP server sends a resume command.

type Event

type Event struct {
	Type     EventType
	Reason   StopReason
	ExitCode int    // set for EventExited
	Output   string // set for EventOutput (log points)
	Env      *lisp.LEnv
	Expr     *lisp.LVal
	BP       *Breakpoint // non-nil for breakpoint stops
}

Event is sent to the event callback when the debugger state changes.

type EventCallback

type EventCallback func(Event)

EventCallback is called when the debugger state changes. It runs on the eval goroutine, so it must not block.

type EventType

type EventType int

EventType identifies the kind of debug event.

const (
	// EventStopped indicates execution has paused (breakpoint, step, exception).
	EventStopped EventType = iota
	// EventContinued indicates execution has resumed.
	EventContinued
	// EventExited indicates the program has finished.
	EventExited
	// EventOutput indicates the program produced output.
	EventOutput
)

type ExceptionBreakMode

type ExceptionBreakMode int

ExceptionBreakMode controls when the debugger pauses on exceptions.

const (
	// ExceptionBreakNever disables exception breakpoints.
	ExceptionBreakNever ExceptionBreakMode = iota
	// ExceptionBreakAll pauses on all exceptions.
	ExceptionBreakAll
	// ExceptionBreakUncaught pauses only on uncaught exceptions (not yet implemented).
	ExceptionBreakUncaught
)

type FormatterFunc added in v1.22.0

type FormatterFunc func(v any) string

FormatterFunc adapts a simple format function into a VariableFormatter with no children. Useful when you only need custom display text.

func (FormatterFunc) Children added in v1.22.0

func (f FormatterFunc) Children(v any) []NativeChild

func (FormatterFunc) FormatValue added in v1.22.0

func (f FormatterFunc) FormatValue(v any) string

type NativeChild added in v1.22.0

type NativeChild struct {
	Name  string
	Value *lisp.LVal
}

NativeChild represents a single child binding of a native value, exposed for drill-down in the debugger variables view.

type Option

type Option func(*Engine)

Option configures an Engine.

func WithCommands added in v1.26.0

func WithCommands(cmds map[string]CommandHandler) Option

WithCommands sets the custom slash command handlers for the debug console. Keys are command names without the leading "/" (e.g., "reload"). Commands registered via WithCommands have empty descriptions; use RegisterCommand to provide descriptions.

func WithEventCallback

func WithEventCallback(cb EventCallback) Option

WithEventCallback sets the function called on debugger state changes.

func WithFormatters added in v1.22.0

func WithFormatters(fmts map[string]VariableFormatter) Option

WithFormatters sets the custom native type formatters for LNative values. Keys are Go type names as returned by fmt.Sprintf("%T", value).

func WithScopeProviders added in v1.23.0

func WithScopeProviders(providers ...ScopeProvider) Option

WithScopeProviders sets the custom scope providers for the debugger. These appear as additional scopes (alongside Local and Package) in the debugger's Variables panel.

func WithSourceLibrary added in v1.22.0

func WithSourceLibrary(lib lisp.SourceLibrary) Option

WithSourceLibrary sets the source library used to serve source content for the DAP source request handler.

func WithSourceRoot added in v1.22.0

func WithSourceRoot(dir string) Option

WithSourceRoot sets an absolute directory path used to resolve relative Source.Path values into absolute paths. This allows DAP clients (VS Code) to open source files from stack frames. Embedders should pass the root directory of the ELPS source files (e.g., the phylum directory).

func WithStopOnEntry

func WithStopOnEntry(stop bool) Option

WithStopOnEntry makes the debugger pause before the first expression.

type ScopeBinding

type ScopeBinding struct {
	Name  string
	Value *lisp.LVal
}

ScopeBinding represents a single variable binding in a scope.

func InspectFunctionLocals added in v1.22.0

func InspectFunctionLocals(env *lisp.LEnv) []ScopeBinding

InspectFunctionLocals returns all bindings visible from the given environment up through parent scopes, stopping at the root env (Parent==nil) which contains builtins. In ELPS, package symbols live in Runtime.Package, not in the env chain, so walking up to (but not including) the root env collects exactly the function-local bindings. This gives users the local variables they expect to see in a debugger, even when paused inside a sub-expression like (if ...).

func InspectLocals

func InspectLocals(env *lisp.LEnv) []ScopeBinding

InspectLocals returns the local variable bindings from the given environment's immediate scope (not parent scopes). Bindings are returned sorted by name.

func InspectMacroExpansion added in v1.23.0

func InspectMacroExpansion(expr *lisp.LVal) []ScopeBinding

InspectMacroExpansion returns scope bindings representing the macro expansion context: macro name, call-site arguments paired with their positional index, and the call-site location. Returns nil if the expression has no macro expansion info.

func InspectScope

func InspectScope(env *lisp.LEnv) []ScopeBinding

InspectScope returns all bindings visible from the given environment, walking up the parent chain. Local bindings shadow parent bindings. Bindings are returned sorted by name.

type ScopeProvider added in v1.23.0

type ScopeProvider interface {
	// Name returns the scope label displayed in the debugger UI.
	Name() string
	// Expensive indicates whether the scope should be fetched lazily.
	Expensive() bool
	// Variables returns the variables to display for this scope.
	// The env is the paused interpreter environment.
	Variables(env *lisp.LEnv) []ScopeVariable
}

ScopeProvider supplies a custom variable scope visible in the debugger's Variables panel (e.g., "State DB" in VS Code). Embedders implement this interface and register providers via WithScopeProviders or RegisterScopeProvider on the Engine.

The Variables method is called on the DAP server goroutine while the interpreter is paused — it must not resume execution or modify engine state.

type ScopeVariable added in v1.23.0

type ScopeVariable struct {
	Name     string          // display name
	Value    string          // display value
	Type     string          // optional type annotation
	Children []ScopeVariable // expandable sub-variables (nil = leaf)
}

ScopeVariable represents a single variable in a custom scope. Values are strings (not LVal) because custom scopes often expose non-LVal data such as raw database entries.

type StepLocation added in v1.23.0

type StepLocation struct {
	Depth   int    // stack depth
	File    string // source file
	Line    int    // source line
	Col     int    // source column (1-based; 0 means unknown)
	IsSExpr bool   // true if the expression is an s-expression (not an atom)
	MacroID int64  // macro expansion node ID (0 = not in expansion)
}

StepLocation describes a source location for stepping operations. Using a struct (rather than positional arguments) keeps the API stable when new fields are added.

type StepMode

type StepMode int

StepMode represents the current stepping behavior.

const (
	// StepNone means no stepping is active (free-running).
	StepNone StepMode = iota
	// StepInto pauses on the next OnEval call regardless of depth.
	StepInto
	// StepOver pauses on the next OnEval where stack depth <= recorded depth.
	StepOver
	// StepOut pauses on the next OnEval where stack depth < recorded depth.
	StepOut
)

type Stepper

type Stepper struct {
	// contains filtered or unexported fields
}

Stepper implements the step state machine. It tracks the step mode and the reference stack depth to determine when stepping should pause.

Thread safety: Stepper is NOT safe for concurrent use. All access must occur on the eval goroutine. The write path (SetStep*/Reset) runs inside WaitIfPaused after the channel receive, and the read path (ShouldPause) runs in OnEval before the next pause — both on the eval goroutine.

func NewStepper

func NewStepper() *Stepper

NewStepper returns a stepper in the StepNone state.

func (*Stepper) Depth added in v1.22.0

func (s *Stepper) Depth() int

Depth returns the reference stack depth recorded when the step command was issued. Used by Engine to detect the step-out condition in OnFunReturn (before the frame is popped).

func (*Stepper) Mode

func (s *Stepper) Mode() StepMode

Mode returns the current step mode.

func (*Stepper) Reset

func (s *Stepper) Reset()

Reset clears the stepper to StepNone (free-running).

func (*Stepper) SetStepInto

func (s *Stepper) SetStepInto(loc StepLocation, granularity string)

SetStepInto configures the stepper to pause on the next OnEval. For line-level granularity (the default), it skips pauses on the same source line unless the stack depth increased (entered a function body) or the macro expansion ID changed (progress within a macro expansion). For "instruction" granularity, it pauses on every expression.

func (*Stepper) SetStepOut

func (s *Stepper) SetStepOut(currentDepth int)

SetStepOut configures the stepper to pause on the next OnEval at a lesser stack depth (i.e., after the current function returns).

func (*Stepper) SetStepOver

func (s *Stepper) SetStepOver(loc StepLocation, granularity string)

SetStepOver configures the stepper to pause on the next OnEval at the same or lesser stack depth. For line-level granularity (the default), it additionally skips pauses on the same source line (macro ID changes are ignored — step-over treats entire macro expansions as same-line). For "instruction" granularity, it pauses on every expression at the appropriate depth.

func (*Stepper) ShouldPause

func (s *Stepper) ShouldPause(loc StepLocation) bool

ShouldPause returns true if the stepper should cause a pause at the given location. After returning true, the stepper resets to StepNone.

For line-level granularity (the default), StepInto and StepOver skip pauses on the same source line unless the stack depth increased (entered a function body). StepInto additionally pauses when the macro expansion ID changed on the same line (progress within a macro expansion). StepOver ignores macro ID changes (treats entire expansion as same-line). For "instruction" granularity, the original per-expression behavior is preserved.

func (*Stepper) ShouldPausePostCall added in v1.22.0

func (s *Stepper) ShouldPausePostCall(currentDepth int) bool

ShouldPausePostCall returns true if a step-out should pause after a function call returns (post-call check in Eval). This is the primary mechanism for detecting step-out from tail-position functions, where the normal OnEval-based ShouldPause never fires because execution flows back through the call chain without visiting any new expressions at a lesser depth. After returning true, the stepper resets to StepNone.

type StopReason

type StopReason string

StopReason describes why execution paused.

const (
	StopBreakpoint         StopReason = "breakpoint"
	StopStep               StopReason = "step"
	StopException          StopReason = "exception"
	StopEntry              StopReason = "entry"
	StopPause              StopReason = "pause"
	StopFunctionBreakpoint StopReason = "function breakpoint"
)

type VariableFormatter added in v1.22.0

type VariableFormatter interface {
	// FormatValue returns a human-readable string for the native value.
	FormatValue(v any) string
	// Children returns expandable child bindings for the native value.
	// Return nil if the value has no children.
	Children(v any) []NativeChild
}

VariableFormatter customizes how native Go values wrapped in LNative are displayed in the debugger. Embedders register formatters by Go type name (fmt.Sprintf("%T", value)) to provide rich display and drill-down.

Directories

Path Synopsis
Package dapserver implements a DAP (Debug Adapter Protocol) server for the ELPS debugger engine.
Package dapserver implements a DAP (Debug Adapter Protocol) server for the ELPS debugger engine.
Package debugrepl provides an interactive CLI debug REPL built on top of the extensible repl.RunEnv function and the debugger engine.
Package debugrepl provides an interactive CLI debug REPL built on top of the extensible repl.RunEnv function and the debugger engine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL