{-# OPTIONS_GHC -Wno-orphans #-} -- TODO: drop this and Show GHC.InternalBreakpointId...
{-# LANGUAGE LambdaCase,
             StandaloneDeriving,
             DataKinds,
             OverloadedStrings,
             DuplicateRecordFields,
             TypeApplications
             #-}
{-# LANGUAGE DerivingStrategies #-}

-- | 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
import GHCi.RemoteTypes (ForeignRef)

import GHC.Debugger.Runtime.Term.Key
import Data.Binary (Binary)
import qualified GHC.Stack as Stack
import System.FilePath (isAbsolute, (</>), normalise)
import Control.Exception (assert)
import qualified GHC.Exts.Heap.Closures as Heap
import GHC.Generics

{-
Note [Paths should be made absolute at the source]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We get `FilePath`s from a few different sources, and those sources do not always agree on what the paths should be relative to.

To avoid mistakes in interpreting relative paths, they should be made absolute as soon as we get them.

At the time of writing (25/07/2026), we handle paths from:
- CLI: relative to getCurrentDirectory.
- GHC: relative to getCurrentDirectory.
- DAP: relative to projectRoot.
- HIE: relative to projectRoot/workingDir, these are made absolute when creating DynFlags.
-}

-- | See Note [Paths should be made absolute at the source]
newtype AbsFilePath = MkAbsFilePath {AbsFilePath -> FilePath
unAbs :: FilePath}
  deriving newtype (AbsFilePath -> AbsFilePath -> Bool
(AbsFilePath -> AbsFilePath -> Bool)
-> (AbsFilePath -> AbsFilePath -> Bool) -> Eq AbsFilePath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AbsFilePath -> AbsFilePath -> Bool
== :: AbsFilePath -> AbsFilePath -> Bool
$c/= :: AbsFilePath -> AbsFilePath -> Bool
/= :: AbsFilePath -> AbsFilePath -> Bool
Eq,Int -> AbsFilePath -> ShowS
[AbsFilePath] -> ShowS
AbsFilePath -> FilePath
(Int -> AbsFilePath -> ShowS)
-> (AbsFilePath -> FilePath)
-> ([AbsFilePath] -> ShowS)
-> Show AbsFilePath
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AbsFilePath -> ShowS
showsPrec :: Int -> AbsFilePath -> ShowS
$cshow :: AbsFilePath -> FilePath
show :: AbsFilePath -> FilePath
$cshowList :: [AbsFilePath] -> ShowS
showList :: [AbsFilePath] -> ShowS
Show)

mkAbsolute :: FilePath -> AbsFilePath
mkAbsolute :: FilePath -> AbsFilePath
mkAbsolute FilePath
fp = Bool -> AbsFilePath -> AbsFilePath
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (FilePath -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null FilePath
fp Bool -> Bool -> Bool
|| FilePath -> Bool
isAbsolute FilePath
fp) (AbsFilePath -> AbsFilePath) -> AbsFilePath -> AbsFilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> AbsFilePath
MkAbsFilePath FilePath
fp

(/>) :: AbsFilePath -> FilePath -> AbsFilePath
MkAbsFilePath FilePath
fp /> :: AbsFilePath -> FilePath -> AbsFilePath
/> FilePath
fp' = FilePath -> AbsFilePath
MkAbsFilePath (FilePath -> AbsFilePath) -> FilePath -> AbsFilePath
forall a b. (a -> b) -> a -> b
$ ShowS
normalise ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ FilePath
fp FilePath -> ShowS
</> FilePath
fp'

--------------------------------------------------------------------------------
-- Commands
--------------------------------------------------------------------------------

-- | The commands sent to the debugger
data Command

  -- | Set a breakpoint on a given function, or module by line number
  = SetBreakpoint { Command -> Breakpoint
brk       :: Breakpoint
                  , Command -> Maybe Int
hitCount  :: Maybe Int
                  -- ^ Stop after N hits (if @isJust condition@, count down only when @eval condition == True@)
                  , Command -> Maybe FilePath
condition :: Maybe String
                  -- ^ Stop if condition evalutes to True
                  , Command -> Maybe FilePath
logMessage :: Maybe String
                  -- ^ Log only if @condition@ (and @hitCondition@ when supported) are @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 { Command -> AbsFilePath
file :: AbsFilePath }

  -- | Clear all function breakpoints
  | ClearFunctionBreakpoints

  -- | Get all threads
  | GetThreads

  -- | Get the evaluation stacktrace until the current breakpoint.
  | GetStacktrace RemoteThreadId

  -- | Get the list of available scopes at the current breakpoint
  | GetScopes RemoteThreadId Int

  -- | 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 RemoteThreadId Int{-stack frame positional ix-} VariableReference

  -- | Evaluate an expression at the current breakpoint.
  | DoEval String

  -- | Get information about the current exception (if any) on a thread.
  | GetExceptionInfo RemoteThreadId

  -- | 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 { Command -> EntryPoint
entryPoint :: EntryPoint, Command -> AbsFilePath
entryFile :: AbsFilePath, Command -> [FilePath]
runArgs :: [String] }

-- | An entry point for program execution.
data EntryPoint = MainEntry { EntryPoint -> Maybe FilePath
mainName :: Maybe String } | FunctionEntry { EntryPoint -> FilePath
fnName :: String }
  deriving (Int -> EntryPoint -> ShowS
[EntryPoint] -> ShowS
EntryPoint -> FilePath
(Int -> EntryPoint -> ShowS)
-> (EntryPoint -> FilePath)
-> ([EntryPoint] -> ShowS)
-> Show EntryPoint
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EntryPoint -> ShowS
showsPrec :: Int -> EntryPoint -> ShowS
$cshow :: EntryPoint -> FilePath
show :: EntryPoint -> FilePath
$cshowList :: [EntryPoint] -> ShowS
showList :: [EntryPoint] -> ShowS
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 { Breakpoint -> AbsFilePath
path :: AbsFilePath, Breakpoint -> Int
lineNum :: Int, Breakpoint -> Maybe Int
columnNum :: Maybe Int }
  | FunctionBreak { Breakpoint -> FilePath
function  :: String }
  | OnExceptionsBreak
  | OnUncaughtExceptionsBreak
  deriving (Int -> Breakpoint -> ShowS
[Breakpoint] -> ShowS
Breakpoint -> FilePath
(Int -> Breakpoint -> ShowS)
-> (Breakpoint -> FilePath)
-> ([Breakpoint] -> ShowS)
-> Show Breakpoint
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Breakpoint -> ShowS
showsPrec :: Int -> Breakpoint -> ShowS
$cshow :: Breakpoint -> FilePath
show :: Breakpoint -> FilePath
$cshowList :: [Breakpoint] -> ShowS
showList :: [Breakpoint] -> ShowS
Show)

-- | Information about a scope
data ScopeInfo = ScopeInfo
      { ScopeInfo -> ScopeVariablesReference
kind :: ScopeVariablesReference
      , ScopeInfo -> SourceSpan
sourceSpan :: SourceSpan
      , ScopeInfo -> Maybe Int
numVars :: Maybe Int
      , ScopeInfo -> Bool
expensive :: Bool }
  deriving (Int -> ScopeInfo -> ShowS
[ScopeInfo] -> ShowS
ScopeInfo -> FilePath
(Int -> ScopeInfo -> ShowS)
-> (ScopeInfo -> FilePath)
-> ([ScopeInfo] -> ShowS)
-> Show ScopeInfo
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ScopeInfo -> ShowS
showsPrec :: Int -> ScopeInfo -> ShowS
$cshow :: ScopeInfo -> FilePath
show :: ScopeInfo -> FilePath
$cshowList :: [ScopeInfo] -> ShowS
showList :: [ScopeInfo] -> ShowS
Show)

newtype VarFields = VarFields [VarInfo]

-- | Information about a variable
data VarInfo = VarInfo
      { VarInfo -> FilePath
varName  :: String
      , VarInfo -> FilePath
varType  :: String
      , VarInfo -> FilePath
varValue :: String
      , VarInfo -> Bool
isThunk  :: Bool
      , VarInfo -> VariableReference
varRef   :: VariableReference
      -- ^ A reference back to this variable

      -- TODO:
      --  memory reference using ghc-debug.
      }

-- | Result of requesting variables.
--
-- If the variable you requested is a thunk then `ForcedVariable` is returned, which
-- is the variable you requested but forced.
--
-- If the variable you requested is not a thunk, then 'VariableFields` is returned which
-- contains the subfields of the variable.
data VariableResult
  = ForcedVariable VarInfo
  | VariableFields [VarInfo]

variableResultToList :: VariableResult -> [VarInfo]
variableResultToList :: VariableResult -> [VarInfo]
variableResultToList = \case
  ForcedVariable VarInfo
vi -> [VarInfo
vi]
  VariableFields [VarInfo]
vis -> [VarInfo]
vis

-- | 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 (Int -> BreakpointKind -> ShowS
[BreakpointKind] -> ShowS
BreakpointKind -> FilePath
(Int -> BreakpointKind -> ShowS)
-> (BreakpointKind -> FilePath)
-> ([BreakpointKind] -> ShowS)
-> Show BreakpointKind
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BreakpointKind -> ShowS
showsPrec :: Int -> BreakpointKind -> ShowS
$cshow :: BreakpointKind -> FilePath
show :: BreakpointKind -> FilePath
$cshowList :: [BreakpointKind] -> ShowS
showList :: [BreakpointKind] -> ShowS
Show, BreakpointKind -> BreakpointKind -> Bool
(BreakpointKind -> BreakpointKind -> Bool)
-> (BreakpointKind -> BreakpointKind -> Bool) -> Eq BreakpointKind
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BreakpointKind -> BreakpointKind -> Bool
== :: BreakpointKind -> BreakpointKind -> Bool
$c/= :: BreakpointKind -> BreakpointKind -> Bool
/= :: BreakpointKind -> BreakpointKind -> Bool
Eq)

instance GHC.Outputable BreakpointKind where ppr :: BreakpointKind -> SDoc
ppr = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
GHC.text (FilePath -> SDoc)
-> (BreakpointKind -> FilePath) -> BreakpointKind -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BreakpointKind -> FilePath
forall a. Show a => a -> FilePath
show

-- | Referring to existing scopes
data ScopeVariablesReference
  = LocalVariablesScope
  | ModuleVariablesScope
  | GlobalVariablesScope
  deriving (Int -> ScopeVariablesReference -> ShowS
[ScopeVariablesReference] -> ShowS
ScopeVariablesReference -> FilePath
(Int -> ScopeVariablesReference -> ShowS)
-> (ScopeVariablesReference -> FilePath)
-> ([ScopeVariablesReference] -> ShowS)
-> Show ScopeVariablesReference
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ScopeVariablesReference -> ShowS
showsPrec :: Int -> ScopeVariablesReference -> ShowS
$cshow :: ScopeVariablesReference -> FilePath
show :: ScopeVariablesReference -> FilePath
$cshowList :: [ScopeVariablesReference] -> ShowS
showList :: [ScopeVariablesReference] -> ShowS
Show, ScopeVariablesReference -> ScopeVariablesReference -> Bool
(ScopeVariablesReference -> ScopeVariablesReference -> Bool)
-> (ScopeVariablesReference -> ScopeVariablesReference -> Bool)
-> Eq ScopeVariablesReference
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
== :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
$c/= :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
/= :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
Eq, Eq ScopeVariablesReference
Eq ScopeVariablesReference =>
(ScopeVariablesReference -> ScopeVariablesReference -> Ordering)
-> (ScopeVariablesReference -> ScopeVariablesReference -> Bool)
-> (ScopeVariablesReference -> ScopeVariablesReference -> Bool)
-> (ScopeVariablesReference -> ScopeVariablesReference -> Bool)
-> (ScopeVariablesReference -> ScopeVariablesReference -> Bool)
-> (ScopeVariablesReference
    -> ScopeVariablesReference -> ScopeVariablesReference)
-> (ScopeVariablesReference
    -> ScopeVariablesReference -> ScopeVariablesReference)
-> Ord ScopeVariablesReference
ScopeVariablesReference -> ScopeVariablesReference -> Bool
ScopeVariablesReference -> ScopeVariablesReference -> Ordering
ScopeVariablesReference
-> ScopeVariablesReference -> ScopeVariablesReference
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ScopeVariablesReference -> ScopeVariablesReference -> Ordering
compare :: ScopeVariablesReference -> ScopeVariablesReference -> Ordering
$c< :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
< :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
$c<= :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
<= :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
$c> :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
> :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
$c>= :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
>= :: ScopeVariablesReference -> ScopeVariablesReference -> Bool
$cmax :: ScopeVariablesReference
-> ScopeVariablesReference -> ScopeVariablesReference
max :: ScopeVariablesReference
-> ScopeVariablesReference -> ScopeVariablesReference
$cmin :: ScopeVariablesReference
-> ScopeVariablesReference -> ScopeVariablesReference
min :: ScopeVariablesReference
-> ScopeVariablesReference -> ScopeVariablesReference
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 TermKey

scopeToVarRef :: ScopeVariablesReference -> VariableReference
scopeToVarRef :: ScopeVariablesReference -> VariableReference
scopeToVarRef = \case
  ScopeVariablesReference
LocalVariablesScope -> VariableReference
LocalVariables
  ScopeVariablesReference
ModuleVariablesScope -> VariableReference
ModuleVariables
  ScopeVariablesReference
GlobalVariablesScope -> VariableReference
GlobalVariables

-- | A source span type for the interface. Like 'RealSrcSpan'.
data SourceSpan = SourceSpan
      { SourceSpan -> AbsFilePath
file :: !AbsFilePath
      -- ^ Path to file where this span is located.
      -- See Note [Paths should be made absolute at the source]
      , SourceSpan -> Int
startLine :: {-# UNPACK #-} !Int
      -- ^ RealSrcSpan start line
      , SourceSpan -> Int
endLine :: {-# UNPACK #-} !Int
      -- ^ RealSrcSpan end line
      , SourceSpan -> Int
startCol :: {-# UNPACK #-} !Int
      -- ^ RealSrcSpan start col
      , SourceSpan -> Int
endCol :: {-# UNPACK #-} !Int
      -- ^ RealSrcSpan end col
      }
      deriving (Int -> SourceSpan -> ShowS
[SourceSpan] -> ShowS
SourceSpan -> FilePath
(Int -> SourceSpan -> ShowS)
-> (SourceSpan -> FilePath)
-> ([SourceSpan] -> ShowS)
-> Show SourceSpan
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SourceSpan -> ShowS
showsPrec :: Int -> SourceSpan -> ShowS
$cshow :: SourceSpan -> FilePath
show :: SourceSpan -> FilePath
$cshowList :: [SourceSpan] -> ShowS
showList :: [SourceSpan] -> ShowS
Show, SourceSpan -> SourceSpan -> Bool
(SourceSpan -> SourceSpan -> Bool)
-> (SourceSpan -> SourceSpan -> Bool) -> Eq SourceSpan
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SourceSpan -> SourceSpan -> Bool
== :: SourceSpan -> SourceSpan -> Bool
$c/= :: SourceSpan -> SourceSpan -> Bool
/= :: SourceSpan -> SourceSpan -> Bool
Eq)

-- | This is a completely unhelpful source span!
-- It doesn't point to anything and is of no help to the user
-- whatsoever.
--
-- Use this only as a last resort if no other source span can be provided.
unhelpfulSourceSpan :: SourceSpan
unhelpfulSourceSpan :: SourceSpan
unhelpfulSourceSpan = SourceSpan
  { file :: AbsFilePath
file = FilePath -> AbsFilePath
mkAbsolute FilePath
""
  , startLine :: Int
startLine = Int
0
  , endLine :: Int
endLine = Int
0
  , startCol :: Int
startCol = Int
0
  , endCol :: Int
endCol = Int
0
  }

-- | See Note [Paths should be made absolute at the source]
srcLocToSourceSpan :: AbsFilePath -> Stack.SrcLoc -> SourceSpan
srcLocToSourceSpan :: AbsFilePath -> SrcLoc -> SourceSpan
srcLocToSourceSpan AbsFilePath
prefix SrcLoc
srcLoc =
  SourceSpan
    { file :: AbsFilePath
file = AbsFilePath
prefix AbsFilePath -> FilePath -> AbsFilePath
/> SrcLoc -> FilePath
Stack.srcLocFile SrcLoc
srcLoc
    , startLine :: Int
startLine = SrcLoc -> Int
Stack.srcLocStartLine SrcLoc
srcLoc
    , endLine :: Int
endLine = SrcLoc -> Int
Stack.srcLocEndLine SrcLoc
srcLoc
    , startCol :: Int
startCol = SrcLoc -> Int
Stack.srcLocStartCol SrcLoc
srcLoc
    , endCol :: Int
endCol = SrcLoc -> Int
Stack.srcLocEndCol SrcLoc
srcLoc
    }

--------------------------------------------------------------------------------
-- 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
  | GotThreads [DebuggeeThread]
  | GotStacktrace [DbgStackFrame]
  | GotScopes [ScopeInfo]
  | GotVariables VariableResult
  | GotExceptionInfo ExceptionInfo
  | Aborted String
  | NonFatalError String
  | Initialised

data BreakFound
  = BreakFound
    { BreakFound -> Bool
changed :: !Bool
    -- ^ Did the status of the found breakpoint change?
    , BreakFound -> [InternalBreakpointId]
breakId :: [GHC.InternalBreakpointId]
    -- ^ Internal breakpoint identifier (module + ix) (TODO: Don't expose GHC)
    , BreakFound -> SourceSpan
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 (Int -> BreakFound -> ShowS
[BreakFound] -> ShowS
BreakFound -> FilePath
(Int -> BreakFound -> ShowS)
-> (BreakFound -> FilePath)
-> ([BreakFound] -> ShowS)
-> Show BreakFound
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BreakFound -> ShowS
showsPrec :: Int -> BreakFound -> ShowS
$cshow :: BreakFound -> FilePath
show :: BreakFound -> FilePath
$cshowList :: [BreakFound] -> ShowS
showList :: [BreakFound] -> ShowS
Show)

-- | A reference to a remote thread by remote id
-- See 'getRemoteThreadId'.
newtype RemoteThreadId = RemoteThreadId
    { RemoteThreadId -> Int
remoteThreadIntRef :: Int
    -- ^ The number identifier of the thread on the (remote) interpreter. To
    -- find the proper remote 'ThreadId' corresponding to this numeric
    -- identifier, lookup the 'remoteThreadIntRef' in the 'ThreadMap'
    }
    deriving (Int -> RemoteThreadId -> ShowS
[RemoteThreadId] -> ShowS
RemoteThreadId -> FilePath
(Int -> RemoteThreadId -> ShowS)
-> (RemoteThreadId -> FilePath)
-> ([RemoteThreadId] -> ShowS)
-> Show RemoteThreadId
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RemoteThreadId -> ShowS
showsPrec :: Int -> RemoteThreadId -> ShowS
$cshow :: RemoteThreadId -> FilePath
show :: RemoteThreadId -> FilePath
$cshowList :: [RemoteThreadId] -> ShowS
showList :: [RemoteThreadId] -> ShowS
Show, RemoteThreadId -> RemoteThreadId -> Bool
(RemoteThreadId -> RemoteThreadId -> Bool)
-> (RemoteThreadId -> RemoteThreadId -> Bool) -> Eq RemoteThreadId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RemoteThreadId -> RemoteThreadId -> Bool
== :: RemoteThreadId -> RemoteThreadId -> Bool
$c/= :: RemoteThreadId -> RemoteThreadId -> Bool
/= :: RemoteThreadId -> RemoteThreadId -> Bool
Eq, Eq RemoteThreadId
Eq RemoteThreadId =>
(RemoteThreadId -> RemoteThreadId -> Ordering)
-> (RemoteThreadId -> RemoteThreadId -> Bool)
-> (RemoteThreadId -> RemoteThreadId -> Bool)
-> (RemoteThreadId -> RemoteThreadId -> Bool)
-> (RemoteThreadId -> RemoteThreadId -> Bool)
-> (RemoteThreadId -> RemoteThreadId -> RemoteThreadId)
-> (RemoteThreadId -> RemoteThreadId -> RemoteThreadId)
-> Ord RemoteThreadId
RemoteThreadId -> RemoteThreadId -> Bool
RemoteThreadId -> RemoteThreadId -> Ordering
RemoteThreadId -> RemoteThreadId -> RemoteThreadId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RemoteThreadId -> RemoteThreadId -> Ordering
compare :: RemoteThreadId -> RemoteThreadId -> Ordering
$c< :: RemoteThreadId -> RemoteThreadId -> Bool
< :: RemoteThreadId -> RemoteThreadId -> Bool
$c<= :: RemoteThreadId -> RemoteThreadId -> Bool
<= :: RemoteThreadId -> RemoteThreadId -> Bool
$c> :: RemoteThreadId -> RemoteThreadId -> Bool
> :: RemoteThreadId -> RemoteThreadId -> Bool
$c>= :: RemoteThreadId -> RemoteThreadId -> Bool
>= :: RemoteThreadId -> RemoteThreadId -> Bool
$cmax :: RemoteThreadId -> RemoteThreadId -> RemoteThreadId
max :: RemoteThreadId -> RemoteThreadId -> RemoteThreadId
$cmin :: RemoteThreadId -> RemoteThreadId -> RemoteThreadId
min :: RemoteThreadId -> RemoteThreadId -> RemoteThreadId
Ord, Get RemoteThreadId
[RemoteThreadId] -> Put
RemoteThreadId -> Put
(RemoteThreadId -> Put)
-> Get RemoteThreadId
-> ([RemoteThreadId] -> Put)
-> Binary RemoteThreadId
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
$cput :: RemoteThreadId -> Put
put :: RemoteThreadId -> Put
$cget :: Get RemoteThreadId
get :: Get RemoteThreadId
$cputList :: [RemoteThreadId] -> Put
putList :: [RemoteThreadId] -> Put
Binary)

data SourceKind = IsExpr | IsStmt

data EvalResult
  = EvalCompleted { EvalResult -> FilePath
resultVal :: String
                  , EvalResult -> FilePath
resultType :: String
                  , EvalResult -> Maybe SourceKind
resultSourceKind :: Maybe SourceKind
                  , EvalResult -> VariableReference
resultStructureRef :: VariableReference
                  -- ^ A structured representation of the result of evaluating
                  -- the expression given as a "virtual" 'VariableReference'
                  -- that the user can use to refer to the result and inspect
                  -- interactively and expand it.
                  }
  | EvalException { resultVal :: String, resultType :: String }
  | EvalStopped   { EvalResult -> Maybe InternalBreakpointId
breakId :: Maybe GHC.InternalBreakpointId
                  -- ^ Did we stop at an exception (@Nothing@) or at a breakpoint (@Just@)?
                  , EvalResult -> RemoteThreadId
breakThread :: RemoteThreadId
                  -- ^ In which thread did we hit the breakpoint?
                  }
  -- | Evaluation failed for some reason other than completed/completed-with-exception/stopped.
  | EvalAbortedWith String

data DebuggeeThread
  = DebuggeeThread
    { DebuggeeThread -> RemoteThreadId
tId :: !RemoteThreadId
    -- ^ An identifier for a thread on the (possibly remote) debuggee process
    , DebuggeeThread -> Maybe FilePath
tName :: !(Maybe String)
    -- ^ Thread label, if there is one
    }
    deriving (Int -> DebuggeeThread -> ShowS
[DebuggeeThread] -> ShowS
DebuggeeThread -> FilePath
(Int -> DebuggeeThread -> ShowS)
-> (DebuggeeThread -> FilePath)
-> ([DebuggeeThread] -> ShowS)
-> Show DebuggeeThread
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DebuggeeThread -> ShowS
showsPrec :: Int -> DebuggeeThread -> ShowS
$cshow :: DebuggeeThread -> FilePath
show :: DebuggeeThread -> FilePath
$cshowList :: [DebuggeeThread] -> ShowS
showList :: [DebuggeeThread] -> ShowS
Show)


data DbgStackFrameBCOArgs ref
  = DbgStackFrameBCOArgs
    { forall (ref :: * -> *).
DbgStackFrameBCOArgs ref -> NoShow (ref [StackField])
bcoArgs :: NoShow (ref [Heap.StackField])
    -- ^ payload of the frame, c.f. @Heap.RetBCO@.
    , forall (ref :: * -> *). DbgStackFrameBCOArgs ref -> Maybe Word
bcoArgsOffset :: Maybe Word
    -- ^ offset of bcoArgs in an hypotethical AP_STACK closure,
    --   see Note [Ask the RTS for memory layout of AP_STACK].
    }
  deriving ((forall x.
 DbgStackFrameBCOArgs ref -> Rep (DbgStackFrameBCOArgs ref) x)
-> (forall x.
    Rep (DbgStackFrameBCOArgs ref) x -> DbgStackFrameBCOArgs ref)
-> Generic (DbgStackFrameBCOArgs ref)
forall x.
Rep (DbgStackFrameBCOArgs ref) x -> DbgStackFrameBCOArgs ref
forall x.
DbgStackFrameBCOArgs ref -> Rep (DbgStackFrameBCOArgs ref) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (ref :: * -> *) x.
Rep (DbgStackFrameBCOArgs ref) x -> DbgStackFrameBCOArgs ref
forall (ref :: * -> *) x.
DbgStackFrameBCOArgs ref -> Rep (DbgStackFrameBCOArgs ref) x
$cfrom :: forall (ref :: * -> *) x.
DbgStackFrameBCOArgs ref -> Rep (DbgStackFrameBCOArgs ref) x
from :: forall x.
DbgStackFrameBCOArgs ref -> Rep (DbgStackFrameBCOArgs ref) x
$cto :: forall (ref :: * -> *) x.
Rep (DbgStackFrameBCOArgs ref) x -> DbgStackFrameBCOArgs ref
to :: forall x.
Rep (DbgStackFrameBCOArgs ref) x -> DbgStackFrameBCOArgs ref
Generic, Int -> DbgStackFrameBCOArgs ref -> ShowS
[DbgStackFrameBCOArgs ref] -> ShowS
DbgStackFrameBCOArgs ref -> FilePath
(Int -> DbgStackFrameBCOArgs ref -> ShowS)
-> (DbgStackFrameBCOArgs ref -> FilePath)
-> ([DbgStackFrameBCOArgs ref] -> ShowS)
-> Show (DbgStackFrameBCOArgs ref)
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
forall (ref :: * -> *). Int -> DbgStackFrameBCOArgs ref -> ShowS
forall (ref :: * -> *). [DbgStackFrameBCOArgs ref] -> ShowS
forall (ref :: * -> *). DbgStackFrameBCOArgs ref -> FilePath
$cshowsPrec :: forall (ref :: * -> *). Int -> DbgStackFrameBCOArgs ref -> ShowS
showsPrec :: Int -> DbgStackFrameBCOArgs ref -> ShowS
$cshow :: forall (ref :: * -> *). DbgStackFrameBCOArgs ref -> FilePath
show :: DbgStackFrameBCOArgs ref -> FilePath
$cshowList :: forall (ref :: * -> *). [DbgStackFrameBCOArgs ref] -> ShowS
showList :: [DbgStackFrameBCOArgs ref] -> ShowS
Show)

data DbgStackFrame
  = DbgStackFrame
    { DbgStackFrame -> FilePath
name :: String
    -- ^ Title of stack frame
    , DbgStackFrame -> SourceSpan
sourceSpan :: SourceSpan
    -- ^ Source span for this stack frame
    , DbgStackFrame -> Maybe InternalBreakpointId
breakId :: Maybe (GHC.InternalBreakpointId)
    -- ^ Is this a BCO continuation frame with a breakpoint?
    -- If yes, we can leverage the breakpoint info to report scopes.
    , DbgStackFrame -> Maybe (DbgStackFrameBCOArgs ForeignRef)
args :: Maybe (DbgStackFrameBCOArgs ForeignRef)
    }
  deriving (Int -> DbgStackFrame -> ShowS
[DbgStackFrame] -> ShowS
DbgStackFrame -> FilePath
(Int -> DbgStackFrame -> ShowS)
-> (DbgStackFrame -> FilePath)
-> ([DbgStackFrame] -> ShowS)
-> Show DbgStackFrame
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DbgStackFrame -> ShowS
showsPrec :: Int -> DbgStackFrame -> ShowS
$cshow :: DbgStackFrame -> FilePath
show :: DbgStackFrame -> FilePath
$cshowList :: [DbgStackFrame] -> ShowS
showList :: [DbgStackFrame] -> ShowS
Show)

data ExceptionInfo = ExceptionInfo
  { ExceptionInfo -> FilePath
exceptionInfoTypeName     :: String
  , ExceptionInfo -> FilePath
exceptionInfoFullTypeName :: String
  , ExceptionInfo -> FilePath
exceptionInfoMessage      :: String
  , ExceptionInfo -> Maybe FilePath
exceptionInfoContext      :: Maybe String
  , ExceptionInfo -> Maybe SourceSpan
exceptionInfoSourceSpan   :: Maybe SourceSpan
  , ExceptionInfo -> [ExceptionInfo]
exceptionInfoInner        :: [ExceptionInfo]
  }
  deriving (Int -> ExceptionInfo -> ShowS
[ExceptionInfo] -> ShowS
ExceptionInfo -> FilePath
(Int -> ExceptionInfo -> ShowS)
-> (ExceptionInfo -> FilePath)
-> ([ExceptionInfo] -> ShowS)
-> Show ExceptionInfo
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExceptionInfo -> ShowS
showsPrec :: Int -> ExceptionInfo -> ShowS
$cshow :: ExceptionInfo -> FilePath
show :: ExceptionInfo -> FilePath
$cshowList :: [ExceptionInfo] -> ShowS
showList :: [ExceptionInfo] -> ShowS
Show)

--------------------------------------------------------------------------------
-- Instances
--------------------------------------------------------------------------------

instance Show GHC.InternalBreakpointId where
  show :: InternalBreakpointId -> FilePath
show (GHC.InternalBreakpointId Module
m Int
ix) = FilePath
"InternalBreakpointId " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ Module -> FilePath
forall a. Outputable a => a -> FilePath
GHC.showPprUnsafe Module
m FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
" " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show Int
ix

newtype NoShow a = NoShow a

instance Show (NoShow a) where
  show :: NoShow a -> FilePath
show NoShow a
_ = FilePath
"<noshow>"