{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE LambdaCase #-}
module GHC.Linker.Types
( Loader (..)
, LoaderState (..)
, uninitializedLoader
, modifyClosureEnv
, LinkerEnv(..)
, filterLinkerEnv
, ClosureEnv
, emptyClosureEnv
, extendClosureEnv
, LinkableSet
, mkLinkableSet
, unionLinkableSet
, ObjFile
, SptEntry(..)
, LibrarySpec(..)
, LoadedPkgInfo(..)
, PkgsLoaded
, Linkable(..)
, LinkablePart(..)
, LinkableObjectSort (..)
, linkableIsNativeCodeOnly
, linkableObjs
, linkableLibs
, linkableFiles
, linkableBCOs
, linkableNativeParts
, linkablePartitionParts
, linkablePartPath
, linkablePartAllBCOs
, isNativeCode
, isNativeLib
, linkableFilterByteCode
, linkableFilterNative
, partitionLinkables
)
where
import GHC.Prelude
import GHC.Unit ( UnitId, Module )
import GHC.ByteCode.Types ( ItblEnv, AddrEnv, CompiledByteCode )
import GHCi.RemoteTypes ( ForeignHValue, RemotePtr )
import GHCi.Message ( LoadedDLL )
import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnvList, filterNameEnv )
import GHC.Types.Name ( Name )
import GHC.Types.SptEntry
import GHC.Utils.Outputable
import Control.Concurrent.MVar
import Data.Time ( UTCTime )
import GHC.Unit.Module.Env
import GHC.Types.Unique.DSet
import GHC.Types.Unique.DFM
import GHC.Unit.Module.WholeCoreBindings
import Data.Maybe (mapMaybe)
import Data.List.NonEmpty (NonEmpty, nonEmpty)
import qualified Data.List.NonEmpty as NE
newtype Loader = Loader { Loader -> MVar (Maybe LoaderState)
loader_state :: MVar (Maybe LoaderState) }
data LoaderState = LoaderState
{ LoaderState -> LinkerEnv
linker_env :: !LinkerEnv
, LoaderState -> LinkableSet
bcos_loaded :: !LinkableSet
, LoaderState -> LinkableSet
objs_loaded :: !LinkableSet
, LoaderState -> PkgsLoaded
pkgs_loaded :: !PkgsLoaded
, LoaderState -> [(FilePath, FilePath)]
temp_sos :: ![(FilePath, String)]
}
uninitializedLoader :: IO Loader
uninitializedLoader :: IO Loader
uninitializedLoader = MVar (Maybe LoaderState) -> Loader
Loader (MVar (Maybe LoaderState) -> Loader)
-> IO (MVar (Maybe LoaderState)) -> IO Loader
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe LoaderState -> IO (MVar (Maybe LoaderState))
forall a. a -> IO (MVar a)
newMVar Maybe LoaderState
forall a. Maybe a
Nothing
modifyClosureEnv :: LoaderState -> (ClosureEnv -> ClosureEnv) -> LoaderState
modifyClosureEnv :: LoaderState -> (ClosureEnv -> ClosureEnv) -> LoaderState
modifyClosureEnv LoaderState
pls ClosureEnv -> ClosureEnv
f =
let le :: LinkerEnv
le = LoaderState -> LinkerEnv
linker_env LoaderState
pls
ce :: ClosureEnv
ce = LinkerEnv -> ClosureEnv
closure_env LinkerEnv
le
in LoaderState
pls { linker_env = le { closure_env = f ce } }
data LinkerEnv = LinkerEnv
{ LinkerEnv -> ClosureEnv
closure_env :: !ClosureEnv
, LinkerEnv -> ItblEnv
itbl_env :: !ItblEnv
, LinkerEnv -> AddrEnv
addr_env :: !AddrEnv
}
filterLinkerEnv :: (Name -> Bool) -> LinkerEnv -> LinkerEnv
filterLinkerEnv :: (Name -> Bool) -> LinkerEnv -> LinkerEnv
filterLinkerEnv Name -> Bool
f LinkerEnv
le = LinkerEnv
{ closure_env :: ClosureEnv
closure_env = ((Name, ForeignHValue) -> Bool) -> ClosureEnv -> ClosureEnv
forall elt. (elt -> Bool) -> NameEnv elt -> NameEnv elt
filterNameEnv (Name -> Bool
f (Name -> Bool)
-> ((Name, ForeignHValue) -> Name) -> (Name, ForeignHValue) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Name, ForeignHValue) -> Name
forall a b. (a, b) -> a
fst) (LinkerEnv -> ClosureEnv
closure_env LinkerEnv
le)
, itbl_env :: ItblEnv
itbl_env = ((Name, ItblPtr) -> Bool) -> ItblEnv -> ItblEnv
forall elt. (elt -> Bool) -> NameEnv elt -> NameEnv elt
filterNameEnv (Name -> Bool
f (Name -> Bool)
-> ((Name, ItblPtr) -> Name) -> (Name, ItblPtr) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Name, ItblPtr) -> Name
forall a b. (a, b) -> a
fst) (LinkerEnv -> ItblEnv
itbl_env LinkerEnv
le)
, addr_env :: AddrEnv
addr_env = ((Name, AddrPtr) -> Bool) -> AddrEnv -> AddrEnv
forall elt. (elt -> Bool) -> NameEnv elt -> NameEnv elt
filterNameEnv (Name -> Bool
f (Name -> Bool)
-> ((Name, AddrPtr) -> Name) -> (Name, AddrPtr) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Name, AddrPtr) -> Name
forall a b. (a, b) -> a
fst) (LinkerEnv -> AddrEnv
addr_env LinkerEnv
le)
}
type ClosureEnv = NameEnv (Name, ForeignHValue)
emptyClosureEnv :: ClosureEnv
emptyClosureEnv :: ClosureEnv
emptyClosureEnv = ClosureEnv
forall a. NameEnv a
emptyNameEnv
extendClosureEnv :: ClosureEnv -> [(Name,ForeignHValue)] -> ClosureEnv
extendClosureEnv :: ClosureEnv -> [(Name, ForeignHValue)] -> ClosureEnv
extendClosureEnv ClosureEnv
cl_env [(Name, ForeignHValue)]
pairs
= ClosureEnv -> [(Name, (Name, ForeignHValue))] -> ClosureEnv
forall a. NameEnv a -> [(Name, a)] -> NameEnv a
extendNameEnvList ClosureEnv
cl_env [ (Name
n, (Name
n,ForeignHValue
v)) | (Name
n,ForeignHValue
v) <- [(Name, ForeignHValue)]
pairs]
type PkgsLoaded = UniqDFM UnitId LoadedPkgInfo
data LoadedPkgInfo
= LoadedPkgInfo
{ LoadedPkgInfo -> UnitId
loaded_pkg_uid :: !UnitId
, LoadedPkgInfo -> [LibrarySpec]
loaded_pkg_hs_objs :: ![LibrarySpec]
, LoadedPkgInfo -> [LibrarySpec]
loaded_pkg_non_hs_objs :: ![LibrarySpec]
, LoadedPkgInfo -> [RemotePtr LoadedDLL]
loaded_pkg_hs_dlls :: ![RemotePtr LoadedDLL]
, LoadedPkgInfo -> UniqDSet UnitId
loaded_pkg_trans_deps :: UniqDSet UnitId
}
instance Outputable LoadedPkgInfo where
ppr :: LoadedPkgInfo -> SDoc
ppr (LoadedPkgInfo UnitId
uid [LibrarySpec]
hs_objs [LibrarySpec]
non_hs_objs [RemotePtr LoadedDLL]
_ UniqDSet UnitId
trans_deps) =
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [UnitId -> SDoc
forall a. Outputable a => a -> SDoc
ppr UnitId
uid
, [LibrarySpec] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [LibrarySpec]
hs_objs
, [LibrarySpec] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [LibrarySpec]
non_hs_objs
, UniqDSet UnitId -> SDoc
forall a. Outputable a => a -> SDoc
ppr UniqDSet UnitId
trans_deps ]
data Linkable = Linkable
{ Linkable -> UTCTime
linkableTime :: !UTCTime
, Linkable -> Module
linkableModule :: !Module
, Linkable -> NonEmpty LinkablePart
linkableParts :: NonEmpty LinkablePart
}
type LinkableSet = ModuleEnv Linkable
mkLinkableSet :: [Linkable] -> LinkableSet
mkLinkableSet :: [Linkable] -> LinkableSet
mkLinkableSet [Linkable]
ls = [(Module, Linkable)] -> LinkableSet
forall a. [(Module, a)] -> ModuleEnv a
mkModuleEnv [(Linkable -> Module
linkableModule Linkable
l, Linkable
l) | Linkable
l <- [Linkable]
ls]
unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
unionLinkableSet = (Linkable -> Linkable -> Linkable)
-> LinkableSet -> LinkableSet -> LinkableSet
forall a.
(a -> a -> a) -> ModuleEnv a -> ModuleEnv a -> ModuleEnv a
plusModuleEnv_C Linkable -> Linkable -> Linkable
go
where
go :: Linkable -> Linkable -> Linkable
go Linkable
l1 Linkable
l2
| Linkable -> UTCTime
linkableTime Linkable
l1 UTCTime -> UTCTime -> Bool
forall a. Ord a => a -> a -> Bool
> Linkable -> UTCTime
linkableTime Linkable
l2 = Linkable
l1
| Bool
otherwise = Linkable
l2
instance Outputable Linkable where
ppr :: Linkable -> SDoc
ppr (Linkable UTCTime
when_made Module
mod NonEmpty LinkablePart
parts)
= (FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"Linkable" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens (FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text (UTCTime -> FilePath
forall a. Show a => a -> FilePath
show UTCTime
when_made)) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
mod)
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Int -> SDoc -> SDoc
nest Int
3 (NonEmpty LinkablePart -> SDoc
forall a. Outputable a => a -> SDoc
ppr NonEmpty LinkablePart
parts)
type ObjFile = FilePath
data LinkableObjectSort =
ModuleObject
|
ForeignObject
data LinkablePart
= DotO
ObjFile
LinkableObjectSort
| DotA FilePath
| DotDLL FilePath
| CoreBindings WholeCoreBindings
| LazyBCOs
CompiledByteCode
[FilePath]
| BCOs CompiledByteCode
instance Outputable LinkablePart where
ppr :: LinkablePart -> SDoc
ppr (DotO FilePath
path LinkableObjectSort
sort) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"DotO" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
path SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LinkableObjectSort -> SDoc
pprSort LinkableObjectSort
sort
where
pprSort :: LinkableObjectSort -> SDoc
pprSort = \case
LinkableObjectSort
ModuleObject -> SDoc
forall doc. IsOutput doc => doc
empty
LinkableObjectSort
ForeignObject -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
brackets (FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"foreign")
ppr (DotA FilePath
path) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"DotA" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
path
ppr (DotDLL FilePath
path) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"DotDLL" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
path
ppr (BCOs CompiledByteCode
bco) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"BCOs" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CompiledByteCode -> SDoc
forall a. Outputable a => a -> SDoc
ppr CompiledByteCode
bco
ppr (LazyBCOs{}) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"LazyBCOs"
ppr (CoreBindings {}) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"CoreBindings"
linkableIsNativeCodeOnly :: Linkable -> Bool
linkableIsNativeCodeOnly :: Linkable -> Bool
linkableIsNativeCodeOnly Linkable
l = (LinkablePart -> Bool) -> [LinkablePart] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all LinkablePart -> Bool
isNativeCode (NonEmpty LinkablePart -> [LinkablePart]
forall a. NonEmpty a -> [a]
NE.toList (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l))
linkableBCOs :: Linkable -> [CompiledByteCode]
linkableBCOs :: Linkable -> [CompiledByteCode]
linkableBCOs Linkable
l = [ CompiledByteCode
cbc | BCOs CompiledByteCode
cbc <- NonEmpty LinkablePart -> [LinkablePart]
forall a. NonEmpty a -> [a]
NE.toList (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l) ]
linkableNativeParts :: Linkable -> [LinkablePart]
linkableNativeParts :: Linkable -> [LinkablePart]
linkableNativeParts Linkable
l = (LinkablePart -> Bool) -> NonEmpty LinkablePart -> [LinkablePart]
forall a. (a -> Bool) -> NonEmpty a -> [a]
NE.filter LinkablePart -> Bool
isNativeCode (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l)
linkablePartitionParts :: Linkable -> ([LinkablePart],[LinkablePart])
linkablePartitionParts :: Linkable -> ([LinkablePart], [LinkablePart])
linkablePartitionParts Linkable
l = (LinkablePart -> Bool)
-> NonEmpty LinkablePart -> ([LinkablePart], [LinkablePart])
forall a. (a -> Bool) -> NonEmpty a -> ([a], [a])
NE.partition LinkablePart -> Bool
isNativeCode (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l)
linkableObjs :: Linkable -> [FilePath]
linkableObjs :: Linkable -> [FilePath]
linkableObjs Linkable
l = (LinkablePart -> [FilePath]) -> NonEmpty LinkablePart -> [FilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap LinkablePart -> [FilePath]
linkablePartObjectPaths (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l)
linkableLibs :: Linkable -> [LinkablePart]
linkableLibs :: Linkable -> [LinkablePart]
linkableLibs Linkable
l = (LinkablePart -> Bool) -> NonEmpty LinkablePart -> [LinkablePart]
forall a. (a -> Bool) -> NonEmpty a -> [a]
NE.filter LinkablePart -> Bool
isNativeLib (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l)
linkableFiles :: Linkable -> [FilePath]
linkableFiles :: Linkable -> [FilePath]
linkableFiles Linkable
l = (LinkablePart -> [FilePath]) -> [LinkablePart] -> [FilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap LinkablePart -> [FilePath]
linkablePartNativePaths (NonEmpty LinkablePart -> [LinkablePart]
forall a. NonEmpty a -> [a]
NE.toList (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
l))
isNativeCode :: LinkablePart -> Bool
isNativeCode :: LinkablePart -> Bool
isNativeCode = \case
DotO {} -> Bool
True
DotA {} -> Bool
True
DotDLL {} -> Bool
True
BCOs {} -> Bool
False
LazyBCOs{} -> Bool
False
CoreBindings {} -> Bool
False
isNativeLib :: LinkablePart -> Bool
isNativeLib :: LinkablePart -> Bool
isNativeLib = \case
DotO {} -> Bool
False
DotA {} -> Bool
True
DotDLL {} -> Bool
True
BCOs {} -> Bool
False
LazyBCOs{} -> Bool
False
CoreBindings {} -> Bool
False
linkablePartPath :: LinkablePart -> Maybe FilePath
linkablePartPath :: LinkablePart -> Maybe FilePath
linkablePartPath = \case
DotO FilePath
fn LinkableObjectSort
_ -> FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
fn
DotA FilePath
fn -> FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
fn
DotDLL FilePath
fn -> FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
fn
CoreBindings {} -> Maybe FilePath
forall a. Maybe a
Nothing
LazyBCOs {} -> Maybe FilePath
forall a. Maybe a
Nothing
BCOs {} -> Maybe FilePath
forall a. Maybe a
Nothing
linkablePartNativePaths :: LinkablePart -> [FilePath]
linkablePartNativePaths :: LinkablePart -> [FilePath]
linkablePartNativePaths = \case
DotO FilePath
fn LinkableObjectSort
_ -> [FilePath
fn]
DotA FilePath
fn -> [FilePath
fn]
DotDLL FilePath
fn -> [FilePath
fn]
CoreBindings {} -> []
LazyBCOs CompiledByteCode
_ [FilePath]
fos -> [FilePath]
fos
BCOs {} -> []
linkablePartObjectPaths :: LinkablePart -> [FilePath]
linkablePartObjectPaths :: LinkablePart -> [FilePath]
linkablePartObjectPaths = \case
DotO FilePath
fn LinkableObjectSort
_ -> [FilePath
fn]
DotA FilePath
_ -> []
DotDLL FilePath
_ -> []
CoreBindings {} -> []
LazyBCOs CompiledByteCode
_ [FilePath]
fos -> [FilePath]
fos
BCOs {} -> []
linkablePartAllBCOs :: LinkablePart -> [CompiledByteCode]
linkablePartAllBCOs :: LinkablePart -> [CompiledByteCode]
linkablePartAllBCOs = \case
BCOs CompiledByteCode
bco -> [CompiledByteCode
bco]
LazyBCOs CompiledByteCode
bcos [FilePath]
_ -> [CompiledByteCode
bcos]
LinkablePart
_ -> []
linkableFilter :: (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
linkableFilter :: (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
linkableFilter LinkablePart -> [LinkablePart]
f Linkable
linkable = do
new <- [LinkablePart] -> Maybe (NonEmpty LinkablePart)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty ((LinkablePart -> [LinkablePart])
-> NonEmpty LinkablePart -> [LinkablePart]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap LinkablePart -> [LinkablePart]
f (Linkable -> NonEmpty LinkablePart
linkableParts Linkable
linkable))
Just linkable {linkableParts = new}
linkablePartNative :: LinkablePart -> [LinkablePart]
linkablePartNative :: LinkablePart -> [LinkablePart]
linkablePartNative = \case
u :: LinkablePart
u@DotO {} -> [LinkablePart
u]
u :: LinkablePart
u@DotA {} -> [LinkablePart
u]
u :: LinkablePart
u@DotDLL {} -> [LinkablePart
u]
LazyBCOs CompiledByteCode
_ [FilePath]
os -> [FilePath -> LinkableObjectSort -> LinkablePart
DotO FilePath
f LinkableObjectSort
ForeignObject | FilePath
f <- [FilePath]
os]
LinkablePart
_ -> []
linkablePartByteCode :: LinkablePart -> [LinkablePart]
linkablePartByteCode :: LinkablePart -> [LinkablePart]
linkablePartByteCode = \case
u :: LinkablePart
u@BCOs {} -> [LinkablePart
u]
LazyBCOs CompiledByteCode
bcos [FilePath]
_ -> [CompiledByteCode -> LinkablePart
BCOs CompiledByteCode
bcos]
LinkablePart
_ -> []
linkableFilterNative :: Linkable -> Maybe Linkable
linkableFilterNative :: Linkable -> Maybe Linkable
linkableFilterNative = (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
linkableFilter LinkablePart -> [LinkablePart]
linkablePartNative
linkableFilterByteCode :: Linkable -> Maybe Linkable
linkableFilterByteCode :: Linkable -> Maybe Linkable
linkableFilterByteCode = (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
linkableFilter LinkablePart -> [LinkablePart]
linkablePartByteCode
partitionLinkables :: [Linkable] -> ([Linkable], [Linkable])
partitionLinkables :: [Linkable] -> ([Linkable], [Linkable])
partitionLinkables [Linkable]
linkables =
(
(Linkable -> Maybe Linkable) -> [Linkable] -> [Linkable]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Linkable -> Maybe Linkable
linkableFilterNative [Linkable]
linkables,
(Linkable -> Maybe Linkable) -> [Linkable] -> [Linkable]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Linkable -> Maybe Linkable
linkableFilterByteCode [Linkable]
linkables
)
data LibrarySpec
= Objects [FilePath]
| Archive FilePath
| DLL String
| DLLPath FilePath
| Framework String
instance Outputable LibrarySpec where
ppr :: LibrarySpec -> SDoc
ppr (Objects [FilePath]
objs) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"Objects" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [SDoc] -> SDoc
forall a. Outputable a => a -> SDoc
ppr ((FilePath -> SDoc) -> [FilePath] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (forall doc. IsLine doc => FilePath -> doc
text @SDoc) [FilePath]
objs)
ppr (Archive FilePath
a) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"Archive" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
a
ppr (DLL FilePath
s) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"DLL" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
s
ppr (DLLPath FilePath
f) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"DLLPath" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
f
ppr (Framework FilePath
s) = FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
"Framework" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FilePath -> SDoc
forall doc. IsLine doc => FilePath -> doc
text FilePath
s