debugger

package
v1.21.0 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2026 License: BSD-3-Clause Imports: 6 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 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

func FormatValue(v *lisp.LVal) string

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 New

func New(opts ...Option) *Engine

New creates a new debugger engine.

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) 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) 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.

func (*Engine) OnFunReturn

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

OnFunReturn implements lisp.Debugger.

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) 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

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
	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

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 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 NewStepper

func NewStepper() *Stepper

NewStepper returns a stepper in the StepNone state.

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()

SetStepInto configures the stepper to pause on the next OnEval.

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(currentDepth int)

SetStepOver configures the stepper to pause on the next OnEval at the same or lesser stack depth.

func (*Stepper) ShouldPause

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

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"
)

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.

Jump to

Keyboard shortcuts

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