content: {- | The main API for creating debuggers. For example, this API can be used
  to connect to an instrumented process, query the GC roots and then decode
  the first root up to depth 10 and displayed to the user.
  
  @
  main = withDebuggeeConnect "\/tmp\/ghc-debug" p1
  
  p1 :: Debuggee -> IO ()
  p1 e = do
    pause e
    g <- run e $ do
          precacheBlocks
          (r:_) <- gcRoots
          buildHeapGraph (Just 10) r
    putStrLn (ppHeapGraph (const "") h)
  @
  
  -}
  module GHC.Debug.Client
    ( -- * Running/Connecting to a debuggee
      Debuggee
    , DebugM
    , debuggeeRun
    , debuggeeConnect
    , debuggeeClose
    , withDebuggeeRun
    , withDebuggeeConnect
    , socketDirectory
    , snapshotRun
  
      -- * Running DebugM
    , run
    , runTrace
    , runAnalysis
  
      -- * Pause/Resume
    , pause
    , fork
    , pauseThen
    , resume
    , pausePoll
    , withPause
  
    -- * Basic Requests
    , version
    , gcRoots
    , allBlocks
    , getSourceInfo
    , savedObjects
    , precacheBlocks
    , dereferenceClosure
    , dereferenceClosures
    , dereferenceStack
    , dereferencePapPayload
    , dereferenceConDesc
    , dereferenceInfoTable
  
    , Quadtraversable(..)
  
    -- * Building a Heap Graph
    , buildHeapGraph
    , multiBuildHeapGraph
    , HG.HeapGraph(..)
    , HG.HeapGraphEntry(..)
  
    -- * Printing a heap graph
    , HG.ppHeapGraph
  
    -- * Tracing
    , traceWrite
    , traceMsg
  
    -- * Caching
    , saveCache
    , loadCache
  
    -- * Types
    , module GHC.Debug.Types.Closures
    , SourceInformation(..)
    , RawBlock(..)
    , BlockPtr
    , StackPtr
    , ClosurePtr
    , InfoTablePtr
    , HG.StackHI
    , HG.PapHI
    , HG.HeapGraphIndex
    ) where
  
  import           GHC.Debug.Types
  import           GHC.Debug.Types.Closures
  import           GHC.Debug.Convention (socketDirectory)
  import GHC.Debug.Client.Monad
  import           GHC.Debug.Client.Query
  import qualified GHC.Debug.Types.Graph as HG
  import Data.List.NonEmpty (NonEmpty)
  
  derefFuncM :: HG.DerefFunction DebugM Size
  derefFuncM c = do
    c' <- dereferenceClosure c
    quadtraverse dereferencePapPayload dereferenceConDesc dereferenceStack pure c'
  
  -- | Build a heap graph starting from the given root. The first argument
  -- controls how many levels to recurse. You nearly always want to set this
  -- to a small number ~ 10, as otherwise you can easily run out of memory.
  buildHeapGraph :: Maybe Int -> ClosurePtr -> DebugM (HG.HeapGraph Size)
  buildHeapGraph = HG.buildHeapGraph derefFuncM
  
  -- | Build a heap graph starting from multiple roots. The first argument
  -- controls how many levels to recurse. You nearly always want to set this
  -- value to a small number ~ 10 as otherwise you can easily run out of
  -- memory.
  multiBuildHeapGraph :: Maybe Int -> NonEmpty ClosurePtr -> DebugM (HG.HeapGraph Size)
  multiBuildHeapGraph = HG.multiBuildHeapGraph derefFuncM
  
  -- | Perform the given analysis whilst the debuggee is paused, then resume
  -- and apply the continuation to the result.
  runAnalysis :: DebugM a -> (a -> IO r) -> Debuggee -> IO r
  runAnalysis a k e = do
    pause e
    r <- run e a
    resume e
    k r
  
  