recover-rtti-0.3.0.0: src/Debug/RecoverRTTI/Modules.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeFamilies #-}
-- | Modules we recognize types from
module Debug.RecoverRTTI.Modules (
KnownPkg(..)
, KnownModule(..)
, IsKnownPkg(..)
-- * Matching
, inKnownModule
, inKnownModuleNested
) where
import Control.Monad
import Data.List (isPrefixOf)
import Debug.RecoverRTTI.FlatClosure
{-------------------------------------------------------------------------------
Packages
-------------------------------------------------------------------------------}
data KnownPkg =
PkgGhcPrim
| PkgBase
| PkgByteString
| PkgText
| PkgIntegerWiredIn
| PkgGhcBignum
| PkgContainers
| PkgAeson
| PkgUnorderedContainers
| PkgVector
data family KnownModule (pkg :: KnownPkg)
{-------------------------------------------------------------------------------
Singleton instance for KnownPkg
-------------------------------------------------------------------------------}
data SPkg (pkg :: KnownPkg) where
SGhcPrim :: SPkg 'PkgGhcPrim
SBase :: SPkg 'PkgBase
SByteString :: SPkg 'PkgByteString
SText :: SPkg 'PkgText
SIntegerWiredIn :: SPkg 'PkgIntegerWiredIn
SGhcBignum :: SPkg 'PkgGhcBignum
SContainers :: SPkg 'PkgContainers
SAeson :: SPkg 'PkgAeson
SUnorderedContainers :: SPkg 'PkgUnorderedContainers
SVector :: SPkg 'PkgVector
class IsKnownPkg pkg where
singPkg :: SPkg pkg
instance IsKnownPkg 'PkgGhcPrim where singPkg = SGhcPrim
instance IsKnownPkg 'PkgBase where singPkg = SBase
instance IsKnownPkg 'PkgByteString where singPkg = SByteString
instance IsKnownPkg 'PkgText where singPkg = SText
instance IsKnownPkg 'PkgIntegerWiredIn where singPkg = SIntegerWiredIn
instance IsKnownPkg 'PkgGhcBignum where singPkg = SGhcBignum
instance IsKnownPkg 'PkgContainers where singPkg = SContainers
instance IsKnownPkg 'PkgAeson where singPkg = SAeson
instance IsKnownPkg 'PkgUnorderedContainers where singPkg = SUnorderedContainers
instance IsKnownPkg 'PkgVector where singPkg = SVector
{-------------------------------------------------------------------------------
Modules in @ghc-pri@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgGhcPrim =
GhcTypes
| GhcTuple
{-------------------------------------------------------------------------------
Modules in @base@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgBase =
GhcInt
| GhcWord
| GhcSTRef
| GhcMVar
| GhcConcSync
| GhcMaybe
| GhcReal
| DataEither
{-------------------------------------------------------------------------------
Modules in @bytestring@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgByteString =
DataByteStringInternal
| DataByteStringLazyInternal
| DataByteStringShortInternal
{-------------------------------------------------------------------------------
Modules in @text@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgText =
DataTextInternal
| DataTextInternalLazy
{-------------------------------------------------------------------------------
Modules in @integer-wired-in@ (this is a virtual package)
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgIntegerWiredIn =
GhcIntegerType
{-------------------------------------------------------------------------------
Modules in @ghc-bignum@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgGhcBignum =
GhcNumInteger
{-------------------------------------------------------------------------------
Modules in @containers@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgContainers =
DataSetInternal
| DataMapInternal
| DataIntSetInternal
| DataIntMapInternal
| DataSequenceInternal
| DataTree
{-------------------------------------------------------------------------------
Modules in @aeson@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgAeson =
DataAesonTypesInternal
{-------------------------------------------------------------------------------
Modules in @unordered-containers@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgUnorderedContainers =
DataHashMapInternal
| DataHashMapInternalArray
{-------------------------------------------------------------------------------
Modules in @vector@
-------------------------------------------------------------------------------}
data instance KnownModule 'PkgVector =
DataVector
{-------------------------------------------------------------------------------
Matching
-------------------------------------------------------------------------------}
-- | Check if the given closure is from a known package/module
inKnownModule :: IsKnownPkg pkg
=> KnownModule pkg
-> FlatClosure -> Maybe String
inKnownModule modl = fmap fst . inKnownModuleNested modl
-- | Generalization of 'inKnownModule' that additionally returns nested pointers
inKnownModuleNested :: IsKnownPkg pkg
=> KnownModule pkg
-> FlatClosure -> Maybe (String, [Box])
inKnownModuleNested = go singPkg
where
go :: SPkg pkg -> KnownModule pkg -> FlatClosure -> Maybe (String, [Box])
go knownPkg knownModl ConstrClosure{pkg, modl, name, ptrArgs} = do
guard (namePkg knownPkg `isPrefixOf` pkg) -- ignore the version number
guard (modl == nameModl knownPkg knownModl)
return (name, ptrArgs)
go _ _ _otherClosure = Nothing
namePkg :: SPkg pkg -> String
namePkg SGhcPrim = "ghc-prim"
namePkg SBase = "base"
namePkg SByteString = "bytestring"
namePkg SText = "text"
namePkg SIntegerWiredIn = "integer-wired-in"
namePkg SGhcBignum = "ghc-bignum"
namePkg SContainers = "containers"
namePkg SAeson = "aeson"
namePkg SUnorderedContainers = "unordered-containers"
namePkg SVector = "vector"
nameModl :: SPkg pkg -> KnownModule pkg -> String
nameModl SGhcPrim GhcTypes = "GHC.Types"
nameModl SGhcPrim GhcTuple = "GHC.Tuple"
nameModl SBase GhcInt = "GHC.Int"
nameModl SBase GhcWord = "GHC.Word"
nameModl SBase GhcSTRef = "GHC.STRef"
nameModl SBase GhcMVar = "GHC.MVar"
nameModl SBase GhcConcSync = "GHC.Conc.Sync"
nameModl SBase GhcMaybe = "GHC.Maybe"
nameModl SBase GhcReal = "GHC.Real"
nameModl SBase DataEither = "Data.Either"
nameModl SByteString DataByteStringInternal = "Data.ByteString.Internal"
nameModl SByteString DataByteStringLazyInternal = "Data.ByteString.Lazy.Internal"
nameModl SByteString DataByteStringShortInternal = "Data.ByteString.Short.Internal"
nameModl SText DataTextInternal = "Data.Text.Internal"
nameModl SText DataTextInternalLazy = "Data.Text.Internal.Lazy"
nameModl SIntegerWiredIn GhcIntegerType = "GHC.Integer.Type"
nameModl SGhcBignum GhcNumInteger = "GHC.Num.Integer"
nameModl SContainers DataSetInternal = "Data.Set.Internal"
nameModl SContainers DataMapInternal = "Data.Map.Internal"
nameModl SContainers DataIntSetInternal = "Data.IntSet.Internal"
nameModl SContainers DataIntMapInternal = "Data.IntMap.Internal"
nameModl SContainers DataSequenceInternal = "Data.Sequence.Internal"
nameModl SContainers DataTree = "Data.Tree"
nameModl SAeson DataAesonTypesInternal = "Data.Aeson.Types.Internal"
nameModl SUnorderedContainers DataHashMapInternal = "Data.HashMap.Internal"
nameModl SUnorderedContainers DataHashMapInternalArray = "Data.HashMap.Internal.Array"
nameModl SVector DataVector = "Data.Vector"