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 ¶
- func EvalCondition(env *lisp.LEnv, condition string) bool
- func EvalInContext(env *lisp.LEnv, source string) *lisp.LVal
- func FormatValue(v *lisp.LVal) string
- type Breakpoint
- type BreakpointStore
- func (s *BreakpointStore) All() []*Breakpoint
- func (s *BreakpointStore) ClearFile(file string)
- func (s *BreakpointStore) ExceptionBreak() ExceptionBreakMode
- func (s *BreakpointStore) Match(src *token.Location) *Breakpoint
- func (s *BreakpointStore) Remove(file string, line int) bool
- func (s *BreakpointStore) Set(file string, line int, condition string) *Breakpoint
- func (s *BreakpointStore) SetExceptionBreak(mode ExceptionBreakMode)
- func (s *BreakpointStore) SetForFile(file string, lines []int, conditions []string) []*Breakpoint
- type Engine
- func (e *Engine) Breakpoints() *BreakpointStore
- func (e *Engine) Disable()
- func (e *Engine) Disconnect()
- func (e *Engine) Enable()
- func (e *Engine) IsEnabled() bool
- func (e *Engine) IsPaused() bool
- func (e *Engine) OnError(env *lisp.LEnv, lerr *lisp.LVal) bool
- func (e *Engine) OnEval(env *lisp.LEnv, expr *lisp.LVal) bool
- func (e *Engine) OnFunEntry(env *lisp.LEnv, fun *lisp.LVal, fenv *lisp.LEnv)
- func (e *Engine) OnFunReturn(env *lisp.LEnv, fun, result *lisp.LVal)
- func (e *Engine) PausedState() (*lisp.LEnv, *lisp.LVal)
- func (e *Engine) Resume()
- func (e *Engine) SetEventCallback(cb EventCallback)
- func (e *Engine) StepInto()
- func (e *Engine) StepOut()
- func (e *Engine) StepOver()
- func (e *Engine) WaitIfPaused(env *lisp.LEnv, expr *lisp.LVal) lisp.DebugAction
- type Event
- type EventCallback
- type EventType
- type ExceptionBreakMode
- type Option
- type ScopeBinding
- type StepMode
- type Stepper
- type StopReason
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EvalCondition ¶
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 ¶
EvalInContext parses and evaluates an expression in the paused environment. This allows the debug console to inspect and mutate state. Returns the result or an error LVal.
func FormatValue ¶
FormatValue returns a human-readable string representation of an LVal, suitable for display in a debugger variables view.
Types ¶
type Breakpoint ¶
type Breakpoint struct {
ID int
File string
Line int
Condition string // optional: Lisp expression to evaluate
Enabled bool
}
Breakpoint represents a location where execution should pause.
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) 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).
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 (*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) 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) IsPaused ¶
IsPaused returns true if the eval goroutine is currently blocked in WaitIfPaused.
func (*Engine) OnError ¶
OnError implements lisp.Debugger. Called when an error condition is created. Returns true if execution should pause.
func (*Engine) OnEval ¶
OnEval implements lisp.Debugger. Called before each expression with a real source location.
func (*Engine) OnFunEntry ¶
OnFunEntry implements lisp.Debugger.
func (*Engine) OnFunReturn ¶
OnFunReturn implements lisp.Debugger.
func (*Engine) PausedState ¶
PausedState returns the env and expr where execution is paused, or nil if not paused.
func (*Engine) Resume ¶
func (e *Engine) Resume()
Resume sends a Continue action to the paused eval goroutine.
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) 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 ¶
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
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 Option ¶
type Option func(*Engine)
Option configures an Engine.
func WithEventCallback ¶
func WithEventCallback(cb EventCallback) Option
WithEventCallback sets the function called on debugger state changes.
func WithStopOnEntry ¶
WithStopOnEntry makes the debugger pause before the first expression.
type ScopeBinding ¶
ScopeBinding represents a single variable binding in a scope.
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 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 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 (*Stepper) Reset ¶
func (s *Stepper) Reset()
Reset clears the stepper to StepNone (free-running).
func (*Stepper) SetStepInto ¶
func (s *Stepper) SetStepInto()
SetStepInto configures the stepper to pause on the next OnEval.
func (*Stepper) SetStepOut ¶
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 ¶
SetStepOver configures the stepper to pause on the next OnEval at the same or lesser stack depth.
func (*Stepper) ShouldPause ¶
ShouldPause returns true if the stepper should cause a pause at the given stack 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" )