{-# LANGUAGE RecordWildCards #-}

-- | Information attached to Breakpoints generated from Ticks
--
-- The breakpoint information stored in 'ModBreaks' is generated during
-- desugaring from the ticks annotating the source expressions.
--
-- This information can be queried per-breakpoint using the 'BreakpointId'
-- datatype, which indexes tick-level breakpoint information.
--
-- 'ModBreaks' and 'BreakpointId's are not to be confused with
-- 'InternalModBreaks' and 'InternalBreakId's. The latter are constructed
-- during bytecode generation and can be found in 'GHC.ByteCode.Breakpoints'.
--
-- See Note [ModBreaks vs InternalModBreaks] and Note [Breakpoint identifiers]
module GHC.HsToCore.Breakpoints.Types
  ( -- * ModBreaks
    ModBreaks(..), modBreaks_locs

    -- ** Re-exports BreakpointId
  , BreakpointId(..), BreakTickIndex
  ) where

import GHC.Prelude
import Data.Array
import qualified Data.ByteString.Short as SBS

import GHC.Types.SrcLoc (SrcSpan)
import GHC.Types.Name (OccName)
import GHC.Types.Tickish (BreakTickIndex, BreakpointId(..))
import GHC.Unit.Module (Module)
import Data.Coerce
import GHC.Utils.Binary (BinSrcSpan(..), Binary(..))
import Control.DeepSeq

--------------------------------------------------------------------------------
-- ModBreaks
--------------------------------------------------------------------------------

-- | All the information about the source-relevant breakpoints for a module
--
-- This information is constructed once during desugaring (with `mkModBreaks`)
-- from breakpoint ticks and fixed/unchanged from there on forward. It could be
-- exported as an abstract datatype because it should never be updated after
-- construction, only queried.
--
-- The arrays can be indexed using the int in the corresponding 'BreakpointId'
-- (i.e. the 'BreakpointId' whose 'Module' matches the 'Module' corresponding
-- to these 'ModBreaks') with the accessors 'modBreaks_locs', 'modBreaks_vars',
-- and 'modBreaks_decls'.
data ModBreaks
   = ModBreaks
   { ModBreaks -> Array BreakTickIndex BinSrcSpan
modBreaks_locs_   :: !(Array BreakTickIndex BinSrcSpan)
        -- ^ An array giving the source span of each breakpoint.
   , ModBreaks -> Array BreakTickIndex [OccName]
modBreaks_vars   :: !(Array BreakTickIndex [OccName])
        -- ^ An array giving the names of the free variables at each breakpoint.
   , ModBreaks -> Array BreakTickIndex [String]
modBreaks_decls  :: !(Array BreakTickIndex [String])
        -- ^ An array giving the names of the declarations enclosing each breakpoint.
        -- See Note [Field modBreaks_decls]
   , ModBreaks
-> Array BreakTickIndex (ShortByteString, ShortByteString)
modBreaks_ccs    :: !(Array BreakTickIndex (SBS.ShortByteString, SBS.ShortByteString))
        -- ^ Array pointing to cost centre info for each breakpoint;
        -- actual 'CostCentre' allocation is done at link-time.
   , ModBreaks -> Module
modBreaks_module :: !Module
        -- ^ The module to which this ModBreaks is associated.
        -- We also cache this here for internal sanity checks.
   }

modBreaks_locs :: ModBreaks -> Array BreakTickIndex SrcSpan
modBreaks_locs :: ModBreaks -> Array BreakTickIndex SrcSpan
modBreaks_locs = Array BreakTickIndex BinSrcSpan -> Array BreakTickIndex SrcSpan
forall a b. Coercible a b => a -> b
coerce (Array BreakTickIndex BinSrcSpan -> Array BreakTickIndex SrcSpan)
-> (ModBreaks -> Array BreakTickIndex BinSrcSpan)
-> ModBreaks
-> Array BreakTickIndex SrcSpan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModBreaks -> Array BreakTickIndex BinSrcSpan
modBreaks_locs_

instance Binary ModBreaks where
  get :: ReadBinHandle -> IO ModBreaks
get ReadBinHandle
bh = Array BreakTickIndex BinSrcSpan
-> Array BreakTickIndex [OccName]
-> Array BreakTickIndex [String]
-> Array BreakTickIndex (ShortByteString, ShortByteString)
-> Module
-> ModBreaks
Array BreakTickIndex BinSrcSpan
-> Array BreakTickIndex [OccName]
-> Array BreakTickIndex [String]
-> Array BreakTickIndex (ShortByteString, ShortByteString)
-> Module
-> ModBreaks
ModBreaks (Array BreakTickIndex BinSrcSpan
 -> Array BreakTickIndex [OccName]
 -> Array BreakTickIndex [String]
 -> Array BreakTickIndex (ShortByteString, ShortByteString)
 -> Module
 -> ModBreaks)
-> IO (Array BreakTickIndex BinSrcSpan)
-> IO
     (Array BreakTickIndex [OccName]
      -> Array BreakTickIndex [String]
      -> Array BreakTickIndex (ShortByteString, ShortByteString)
      -> Module
      -> ModBreaks)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadBinHandle -> IO (Array BreakTickIndex BinSrcSpan)
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO
  (Array BreakTickIndex [OccName]
   -> Array BreakTickIndex [String]
   -> Array BreakTickIndex (ShortByteString, ShortByteString)
   -> Module
   -> ModBreaks)
-> IO (Array BreakTickIndex [OccName])
-> IO
     (Array BreakTickIndex [String]
      -> Array BreakTickIndex (ShortByteString, ShortByteString)
      -> Module
      -> ModBreaks)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO (Array BreakTickIndex [OccName])
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO
  (Array BreakTickIndex [String]
   -> Array BreakTickIndex (ShortByteString, ShortByteString)
   -> Module
   -> ModBreaks)
-> IO (Array BreakTickIndex [String])
-> IO
     (Array BreakTickIndex (ShortByteString, ShortByteString)
      -> Module -> ModBreaks)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO (Array BreakTickIndex [String])
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO
  (Array BreakTickIndex (ShortByteString, ShortByteString)
   -> Module -> ModBreaks)
-> IO (Array BreakTickIndex (ShortByteString, ShortByteString))
-> IO (Module -> ModBreaks)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle
-> IO (Array BreakTickIndex (ShortByteString, ShortByteString))
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO (Module -> ModBreaks) -> IO Module -> IO ModBreaks
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO Module
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh

  put_ :: WriteBinHandle -> ModBreaks -> IO ()
put_ WriteBinHandle
bh ModBreaks {Array BreakTickIndex [String]
Array BreakTickIndex [OccName]
Array BreakTickIndex (ShortByteString, ShortByteString)
Array BreakTickIndex BinSrcSpan
Module
modBreaks_vars :: ModBreaks -> Array BreakTickIndex [OccName]
modBreaks_decls :: ModBreaks -> Array BreakTickIndex [String]
modBreaks_locs_ :: ModBreaks -> Array BreakTickIndex BinSrcSpan
modBreaks_ccs :: ModBreaks
-> Array BreakTickIndex (ShortByteString, ShortByteString)
modBreaks_module :: ModBreaks -> Module
modBreaks_locs_ :: Array BreakTickIndex BinSrcSpan
modBreaks_vars :: Array BreakTickIndex [OccName]
modBreaks_decls :: Array BreakTickIndex [String]
modBreaks_ccs :: Array BreakTickIndex (ShortByteString, ShortByteString)
modBreaks_module :: Module
..} =
    WriteBinHandle -> Array BreakTickIndex BinSrcSpan -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Array BreakTickIndex BinSrcSpan
modBreaks_locs_
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> Array BreakTickIndex [OccName] -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Array BreakTickIndex [OccName]
modBreaks_vars
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> Array BreakTickIndex [String] -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Array BreakTickIndex [String]
modBreaks_decls
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle
-> Array BreakTickIndex (ShortByteString, ShortByteString) -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Array BreakTickIndex (ShortByteString, ShortByteString)
modBreaks_ccs
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> Module -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Module
modBreaks_module

instance NFData ModBreaks where
  rnf :: ModBreaks -> ()
rnf (ModBreaks Array BreakTickIndex BinSrcSpan
a Array BreakTickIndex [OccName]
b Array BreakTickIndex [String]
c Array BreakTickIndex (ShortByteString, ShortByteString)
d Module
e) = Array BreakTickIndex BinSrcSpan -> ()
forall a. NFData a => a -> ()
rnf Array BreakTickIndex BinSrcSpan
a () -> () -> ()
forall a b. a -> b -> b
`seq` Array BreakTickIndex [OccName] -> ()
forall a. NFData a => a -> ()
rnf Array BreakTickIndex [OccName]
b () -> () -> ()
forall a b. a -> b -> b
`seq` Array BreakTickIndex [String] -> ()
forall a. NFData a => a -> ()
rnf Array BreakTickIndex [String]
c () -> () -> ()
forall a b. a -> b -> b
`seq` Array BreakTickIndex (ShortByteString, ShortByteString) -> ()
forall a. NFData a => a -> ()
rnf Array BreakTickIndex (ShortByteString, ShortByteString)
d () -> () -> ()
forall a b. a -> b -> b
`seq` Module -> ()
forall a. NFData a => a -> ()
rnf Module
e