haskell-debugger-0.10.0.0: haskell-debugger/GHC/Debugger/Interface/Messages.hs
{-# LANGUAGE LambdaCase,
StandaloneDeriving,
OverloadedStrings,
DuplicateRecordFields,
TypeApplications
#-}
-- | Types for sending and receiving messages to/from haskell-debugger
module GHC.Debugger.Interface.Messages where
import qualified GHC
import qualified GHC.Utils.Outputable as GHC
--------------------------------------------------------------------------------
-- Commands
--------------------------------------------------------------------------------
-- | The commands sent to the debugger
data Command
-- | Set a breakpoint on a given function, or module by line number
= SetBreakpoint { brk :: Breakpoint
, hitCount :: Maybe Int
-- ^ Stop after N hits (if @isJust condition@, count down only when @eval condition == True@)
, condition :: Maybe String
-- ^ Stop if condition evalutes to True
}
-- | Delete a breakpoint on a given function, or module by line number
| DelBreakpoint Breakpoint
-- | Find the valid breakpoints locations for the given module Breakpoint
| GetBreakpointsAt Breakpoint
-- | Clear all breakpoints in the specified file.
-- This is useful because DAP's `setBreakpoints` re-sets all breakpoints from zero for a source rather than incrementally.
| ClearModBreakpoints { file :: FilePath }
-- | Clear all function breakpoints
| ClearFunctionBreakpoints
-- | Get the evaluation stacktrace until the current breakpoint.
| GetStacktrace
-- | Get the list of available scopes at the current breakpoint
| GetScopes
-- | Get the variables in scope for the current breakpoint.
--
-- Note: for GHCs <9.16 this only reports the variables free in the expression
-- we're stopped at rather than all variables in scope.
| GetVariables VariableReference
-- | Evaluate an expression at the current breakpoint.
| DoEval String
-- | Continue executing from the current breakpoint
| DoContinue
-- | Step local, which executes until next breakpoint in the same function.
| DoStepLocal
-- | Single step always to the next breakpoint. Used for "step-in".
| DoSingleStep
-- | Step out to the breakpoint immediately following a return.
| DoStepOut
-- | Execute a prog with debugging enabled. Breaks on the existing breakpoints.
--
-- Constructed with an entry point function name and the arguments to pass it.
--
-- When the @'EntryPoint'@ is @'Main'@, @'runArgs'@ are set as process
-- invocation arguments (as in @argv@) rather than passed directly as a
-- Haskell function arguments.
| DebugExecution { entryPoint :: EntryPoint, entryFile :: FilePath, runArgs :: [String] }
-- | Terminate haskell-debugger and exit
| TerminateProcess
-- | An entry point for program execution.
data EntryPoint = MainEntry { mainName :: Maybe String } | FunctionEntry { fnName :: String }
deriving (Show)
-- | A breakpoint can be set/removed on functions by name, or in modules by
-- line number. And, globally, for all exceptions, or just uncaught exceptions.
data Breakpoint
= ModuleBreak { path :: FilePath, lineNum :: Int, columnNum :: Maybe Int }
| FunctionBreak { function :: String }
| OnExceptionsBreak
| OnUncaughtExceptionsBreak
deriving (Show)
-- | Information about a scope
data ScopeInfo = ScopeInfo
{ kind :: ScopeVariablesReference
, sourceSpan :: SourceSpan
, numVars :: Maybe Int
, expensive :: Bool }
deriving (Show)
newtype VarFields = VarFields [VarInfo]
deriving (Show, Eq)
-- | Information about a variable
data VarInfo = VarInfo
{ varName :: String
, varType :: String
, varValue :: String
, isThunk :: Bool
, varRef :: VariableReference
-- ^ A reference back to this variable
-- TODO:
-- memory reference using ghc-debug.
}
deriving (Show, Eq)
-- | What kind of breakpoint are we referring to, module or function breakpoints?
-- Used e.g. in the 'ClearBreakpoints' request
data BreakpointKind
-- | Module breakpoints
= ModuleBreakpointKind
-- | Function breakpoints
| FunctionBreakpointKind
deriving (Show, Eq)
instance GHC.Outputable BreakpointKind where ppr = GHC.text . show
-- | Referring to existing scopes
data ScopeVariablesReference
= LocalVariablesScope
| ModuleVariablesScope
| GlobalVariablesScope
deriving (Show, Eq, Ord)
-- | The type of variables referenced, or a particular variable referenced for its fields or value (when inspecting a thunk)
data VariableReference
-- | A void reference to nothing at all. Used e.g. for ty cons and data cons
= NoVariables
-- | Variables in the local context (includes arguments, previous bindings)
| LocalVariables
-- | Variables in the module where we're stopped
| ModuleVariables
-- | Variables in the global context
| GlobalVariables
-- | A reference to a specific variable.
-- Used to force its result or get its structured children
| SpecificVariable Int
deriving (Show, Eq, Ord)
-- | From 'ScopeVariablesReference' to a 'VariableReference' that can be used in @"variable"@ requests
scopeToVarRef :: ScopeVariablesReference -> VariableReference
scopeToVarRef = \case
LocalVariablesScope -> LocalVariables
ModuleVariablesScope -> ModuleVariables
GlobalVariablesScope -> GlobalVariables
instance Bounded VariableReference where
minBound = NoVariables
maxBound = SpecificVariable maxBound
instance Enum VariableReference where
toEnum 0 = NoVariables
toEnum 1 = LocalVariables
toEnum 2 = ModuleVariables
toEnum 3 = GlobalVariables
toEnum n = SpecificVariable (n - 4)
fromEnum NoVariables = 0
fromEnum LocalVariables = 1
fromEnum ModuleVariables = 2
fromEnum GlobalVariables = 3
fromEnum (SpecificVariable n) = 4 + n
-- | A source span type for the interface. Like 'RealSrcSpan'.
data SourceSpan = SourceSpan
{ file :: !FilePath
-- ^ Path to file where this span is located
, startLine :: {-# UNPACK #-} !Int
-- ^ RealSrcSpan start line
, endLine :: {-# UNPACK #-} !Int
-- ^ RealSrcSpan end line
, startCol :: {-# UNPACK #-} !Int
-- ^ RealSrcSpan start col
, endCol :: {-# UNPACK #-} !Int
-- ^ RealSrcSpan end col
}
deriving (Show)
--------------------------------------------------------------------------------
-- Responses
--------------------------------------------------------------------------------
-- | The responses sent by `haskell-debugger` to the client
data Response
= DidEval EvalResult
| DidSetBreakpoint BreakFound
| DidRemoveBreakpoint BreakFound
| DidGetBreakpoints (Maybe SourceSpan)
| DidClearBreakpoints
| DidContinue EvalResult
| DidStep EvalResult
| DidExec EvalResult
| GotStacktrace [StackFrame]
| GotScopes [ScopeInfo]
| GotVariables (Either VarInfo [VarInfo])
| Aborted String
| Initialised
data BreakFound
= BreakFound
{ changed :: !Bool
-- ^ Did the status of the found breakpoint change?
, breakId :: [GHC.InternalBreakpointId]
-- ^ Internal breakpoint identifier (module + ix) (TODO: Don't expose GHC)
, sourceSpan :: SourceSpan
-- ^ Source span for interface
}
-- | Breakpoint found but without location info.
-- This happens when setting breakpoints on exceptions.
| BreakFoundNoLoc
{ changed :: Bool }
-- | No breakpoints found
| BreakNotFound
-- | Found many breakpoints.
-- Caused by setting breakpoint on a name with multiple matches or many equations.
| ManyBreaksFound [BreakFound]
deriving (Show)
data EvalResult
= EvalCompleted { resultVal :: String
, resultType :: String
, resultStructureRef :: VariableReference
-- ^ A structured representation of the result of evaluating
-- the expression given as a "virtual" 'VariableReference'
-- that the user can expand as a normal variable.
}
| EvalException { resultVal :: String, resultType :: String }
| EvalStopped { breakId :: Maybe GHC.InternalBreakpointId {-^ Did we stop at an exception (@Nothing@) or at a breakpoint (@Just@)? -} }
-- | Evaluation failed for some reason other than completed/completed-with-exception/stopped.
| EvalAbortedWith String
deriving (Show)
data StackFrame
= StackFrame
{ name :: String
-- ^ Title of stack frame
, sourceSpan :: SourceSpan
-- ^ Source span for this stack frame
}
deriving (Show)
--------------------------------------------------------------------------------
-- Instances
--------------------------------------------------------------------------------
deriving instance Show Command
deriving instance Show Response
instance Show GHC.InternalBreakpointId where
show (GHC.InternalBreakpointId m ix) = "InternalBreakpointId " ++ GHC.showPprUnsafe m ++ " " ++ show ix