{-# 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 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 (String, String)
modBreaks_ccs    :: !(Array BreakTickIndex (String, String))
        -- ^ 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 (String, String)
-> Module
-> ModBreaks
ModBreaks (Array BreakTickIndex BinSrcSpan
 -> Array BreakTickIndex [OccName]
 -> Array BreakTickIndex [String]
 -> Array BreakTickIndex (String, String)
 -> Module
 -> ModBreaks)
-> IO (Array BreakTickIndex BinSrcSpan)
-> IO
     (Array BreakTickIndex [OccName]
      -> Array BreakTickIndex [String]
      -> Array BreakTickIndex (String, String)
      -> 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 (String, String)
   -> Module
   -> ModBreaks)
-> IO (Array BreakTickIndex [OccName])
-> IO
     (Array BreakTickIndex [String]
      -> Array BreakTickIndex (String, String) -> 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 (String, String) -> Module -> ModBreaks)
-> IO (Array BreakTickIndex [String])
-> IO
     (Array BreakTickIndex (String, String) -> 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 (String, String) -> Module -> ModBreaks)
-> IO (Array BreakTickIndex (String, String))
-> 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 (String, String))
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 (String, String)
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 (String, String)
modBreaks_module :: ModBreaks -> Module
modBreaks_locs_ :: Array BreakTickIndex BinSrcSpan
modBreaks_vars :: Array BreakTickIndex [OccName]
modBreaks_decls :: Array BreakTickIndex [String]
modBreaks_ccs :: Array BreakTickIndex (String, String)
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 (String, String) -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Array BreakTickIndex (String, String)
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 (String, String)
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 (String, String) -> ()
forall a. NFData a => a -> ()
rnf Array BreakTickIndex (String, String)
d () -> () -> ()
forall a b. a -> b -> b
`seq` Module -> ()
forall a. NFData a => a -> ()
rnf Module
e