{-# LANGUAGE RecordWildCards #-}
module Graph.Trace
( plugin
, module DT
, module Trace
) where
import Control.Monad (when)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.State.Strict
import Control.Monad.Trans.Writer.CPS
import qualified Data.Generics as Syb
import qualified Data.Set as S
import Graph.Trace.Internal.Predicates (addConstraintToSig, removeConstraints)
import qualified Graph.Trace.Internal.GhcFacade as Ghc
import Graph.Trace.Internal.Instrument (modifyClsInstDecl, modifyTyClDecl, modifyValBinds)
import Graph.Trace.Internal.Solver (tcPlugin)
import Graph.Trace.Internal.Types as DT
import Graph.Trace.Internal.Trace as Trace
plugin :: Ghc.Plugin
plugin :: Plugin
plugin =
Plugin
Ghc.defaultPlugin
{ pluginRecompile :: [CommandLineOption] -> IO PluginRecompile
Ghc.pluginRecompile = [CommandLineOption] -> IO PluginRecompile
Ghc.purePlugin
, tcPlugin :: TcPlugin
Ghc.tcPlugin = \[CommandLineOption]
_ -> TcPlugin -> Maybe TcPlugin
forall a. a -> Maybe a
Just TcPlugin
tcPlugin
, renamedResultAction :: [CommandLineOption]
-> TcGblEnv -> HsGroup GhcRn -> TcM (TcGblEnv, HsGroup GhcRn)
Ghc.renamedResultAction = [CommandLineOption]
-> TcGblEnv -> HsGroup GhcRn -> TcM (TcGblEnv, HsGroup GhcRn)
renamedResultAction
}
findImportedModule :: String -> Ghc.TcM Ghc.Module
findImportedModule :: CommandLineOption -> TcM Module
findImportedModule CommandLineOption
moduleName = do
HscEnv
hscEnv <- TcRnIf TcGblEnv TcLclEnv HscEnv
forall gbl lcl. TcRnIf gbl lcl HscEnv
Ghc.getTopEnv
FindResult
result <- IO FindResult -> IOEnv (Env TcGblEnv TcLclEnv) FindResult
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FindResult -> IOEnv (Env TcGblEnv TcLclEnv) FindResult)
-> IO FindResult -> IOEnv (Env TcGblEnv TcLclEnv) FindResult
forall a b. (a -> b) -> a -> b
$
HscEnv -> ModuleName -> Maybe FastString -> IO FindResult
Ghc.findImportedModule HscEnv
hscEnv (CommandLineOption -> ModuleName
Ghc.mkModuleName CommandLineOption
moduleName) Maybe FastString
forall a. Maybe a
Nothing
case FindResult
result of
Ghc.Found ModLocation
_ Module
m -> Module -> TcM Module
forall (f :: * -> *) a. Applicative f => a -> f a
pure Module
m
FindResult
_ -> CommandLineOption -> TcM Module
forall a. HasCallStack => CommandLineOption -> a
error (CommandLineOption -> TcM Module)
-> CommandLineOption -> TcM Module
forall a b. (a -> b) -> a -> b
$ CommandLineOption
"unable to find module: " CommandLineOption -> CommandLineOption -> CommandLineOption
forall a. Semigroup a => a -> a -> a
<> CommandLineOption
moduleName
warnAboutOptimizations :: Ghc.TcM ()
warnAboutOptimizations :: TcM ()
warnAboutOptimizations = do
EnumSet GeneralFlag
generalFlags <- DynFlags -> EnumSet GeneralFlag
Ghc.generalFlags (DynFlags -> EnumSet GeneralFlag)
-> IOEnv (Env TcGblEnv TcLclEnv) DynFlags
-> IOEnv (Env TcGblEnv TcLclEnv) (EnumSet GeneralFlag)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
Ghc.getDynFlags
Bool -> TcM () -> TcM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (GeneralFlag -> EnumSet GeneralFlag -> Bool
forall a. Enum a => a -> EnumSet a -> Bool
Ghc.enumSetMember GeneralFlag
Ghc.Opt_FullLaziness EnumSet GeneralFlag
generalFlags) (TcM () -> TcM ()) -> (IO () -> TcM ()) -> IO () -> TcM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
IO () -> TcM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> TcM ()) -> IO () -> TcM ()
forall a b. (a -> b) -> a -> b
$ CommandLineOption -> IO ()
putStrLn CommandLineOption
" * Full laziness is enabled: it's generally recommended to disable this optimization when using graph-trace. Use the -fno-full-laziness GHC option to disable it."
Bool -> TcM () -> TcM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (GeneralFlag -> EnumSet GeneralFlag -> Bool
forall a. Enum a => a -> EnumSet a -> Bool
Ghc.enumSetMember GeneralFlag
Ghc.Opt_CSE EnumSet GeneralFlag
generalFlags) (TcM () -> TcM ()) -> (IO () -> TcM ()) -> IO () -> TcM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
IO () -> TcM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> TcM ()) -> IO () -> TcM ()
forall a b. (a -> b) -> a -> b
$ CommandLineOption -> IO ()
putStrLn CommandLineOption
" * Common sub-expression elimination is enabled: it's generally recommended to disable this optimization when using graph-trace. Use the -fno-cse GHC option to disable it."
isMonomorphismRestrictionOn :: Ghc.TcM Bool
isMonomorphismRestrictionOn :: TcM Bool
isMonomorphismRestrictionOn =
Extension -> DynFlags -> Bool
Ghc.xopt Extension
Ghc.MonomorphismRestriction (DynFlags -> Bool)
-> IOEnv (Env TcGblEnv TcLclEnv) DynFlags -> TcM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
Ghc.getDynFlags
renamedResultAction
:: [Ghc.CommandLineOption]
-> Ghc.TcGblEnv
-> Ghc.HsGroup Ghc.GhcRn
-> Ghc.TcM (Ghc.TcGblEnv, Ghc.HsGroup Ghc.GhcRn)
renamedResultAction :: [CommandLineOption]
-> TcGblEnv -> HsGroup GhcRn -> TcM (TcGblEnv, HsGroup GhcRn)
renamedResultAction [CommandLineOption]
cmdLineOptions TcGblEnv
tcGblEnv
hsGroup :: HsGroup GhcRn
hsGroup@Ghc.HsGroup{hs_valds :: forall p. HsGroup p -> HsValBinds p
Ghc.hs_valds = Ghc.XValBindsLR{}}
= do
TcM ()
warnAboutOptimizations
Module
debugTypesModule <- CommandLineOption -> TcM Module
findImportedModule CommandLineOption
"Graph.Trace.Internal.Types"
Module
debugTraceModule <- CommandLineOption -> TcM Module
findImportedModule CommandLineOption
"Graph.Trace.Internal.Trace"
Name
traceMutePredName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkClsOcc CommandLineOption
"TraceMute")
Name
traceDeepPredName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkClsOcc CommandLineOption
"TraceDeep")
Name
traceDeepKeyPredName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkClsOcc CommandLineOption
"TraceDeepKey")
Name
tracePredName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkClsOcc CommandLineOption
"Trace")
Name
traceKeyPredName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkClsOcc CommandLineOption
"TraceKey")
Name
traceInertPredName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkClsOcc CommandLineOption
"TraceInert")
Name
entryName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTraceModule (CommandLineOption -> OccName
Ghc.mkVarOcc CommandLineOption
"entry")
Name
debugContextName <- Module -> OccName -> TcRnIf TcGblEnv TcLclEnv Name
forall a b. Module -> OccName -> TcRnIf a b Name
Ghc.lookupOrig Module
debugTypesModule (CommandLineOption -> OccName
Ghc.mkTcOcc CommandLineOption
"DebugContext")
let debugNames :: DebugNames
debugNames = DebugNames :: Name
-> Name
-> Name
-> Name
-> Name
-> Name
-> Name
-> Name
-> DebugNames
DebugNames{Name
debugContextName :: Name
entryName :: Name
traceInertPredName :: Name
traceKeyPredName :: Name
tracePredName :: Name
traceDeepKeyPredName :: Name
traceDeepPredName :: Name
traceMutePredName :: Name
debugContextName :: Name
entryName :: Name
traceInertPredName :: Name
traceKeyPredName :: Name
tracePredName :: Name
traceDeepKeyPredName :: Name
traceDeepPredName :: Name
traceMutePredName :: Name
..}
let traceAllFlag :: Bool
traceAllFlag = CommandLineOption
"trace-all" CommandLineOption -> [CommandLineOption] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [CommandLineOption]
cmdLineOptions
(hsGroup' :: HsGroup GhcRn
hsGroup'@Ghc.HsGroup
{ hs_valds :: forall p. HsGroup p -> HsValBinds p
Ghc.hs_valds = HsValBindsLR GhcRn GhcRn
valBinds
, hs_tyclds :: forall p. HsGroup p -> [TyClGroup p]
Ghc.hs_tyclds = [TyClGroup GhcRn]
tyClGroups
}, Map Name (Maybe FastString, Propagation)
nameMap) = Writer (Map Name (Maybe FastString, Propagation)) (HsGroup GhcRn)
-> (HsGroup GhcRn, Map Name (Maybe FastString, Propagation))
forall w a. Monoid w => Writer w a -> (a, w)
runWriter
(Writer (Map Name (Maybe FastString, Propagation)) (HsGroup GhcRn)
-> (HsGroup GhcRn, Map Name (Maybe FastString, Propagation)))
-> Writer
(Map Name (Maybe FastString, Propagation)) (HsGroup GhcRn)
-> (HsGroup GhcRn, Map Name (Maybe FastString, Propagation))
forall a b. (a -> b) -> a -> b
$ (Sig GhcRn
-> WriterT
(Map Name (Maybe FastString, Propagation)) Identity (Sig GhcRn))
-> a
-> WriterT (Map Name (Maybe FastString, Propagation)) Identity a
forall (m :: * -> *) a b.
(Monad m, Typeable a, Typeable b) =>
(b -> m b) -> a -> m a
Syb.mkM (DebugNames
-> Bool
-> Sig GhcRn
-> WriterT
(Map Name (Maybe FastString, Propagation)) Identity (Sig GhcRn)
addConstraintToSig DebugNames
debugNames Bool
traceAllFlag)
(forall a.
Data a =>
a -> WriterT (Map Name (Maybe FastString, Propagation)) Identity a)
-> HsGroup GhcRn
-> Writer
(Map Name (Maybe FastString, Propagation)) (HsGroup GhcRn)
forall (m :: * -> *). Monad m => GenericM m -> GenericM m
`Syb.everywhereM` HsGroup GhcRn
hsGroup
(HsValBindsLR GhcRn GhcRn
valBinds', Set Name
patBindNames) <- (StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
(HsValBindsLR GhcRn GhcRn, Set Name)
-> Set Name
-> IOEnv
(Env TcGblEnv TcLclEnv) (HsValBindsLR GhcRn GhcRn, Set Name)
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
`evalStateT` Set Name
forall a. Set a
S.empty) (StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
(HsValBindsLR GhcRn GhcRn, Set Name)
-> IOEnv
(Env TcGblEnv TcLclEnv) (HsValBindsLR GhcRn GhcRn, Set Name))
-> (WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(HsValBindsLR GhcRn GhcRn)
-> StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
(HsValBindsLR GhcRn GhcRn, Set Name))
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(HsValBindsLR GhcRn GhcRn)
-> IOEnv
(Env TcGblEnv TcLclEnv) (HsValBindsLR GhcRn GhcRn, Set Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(HsValBindsLR GhcRn GhcRn)
-> StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
(HsValBindsLR GhcRn GhcRn, Set Name)
forall w (m :: * -> *) a. Monoid w => WriterT w m a -> m (a, w)
runWriterT (WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(HsValBindsLR GhcRn GhcRn)
-> IOEnv
(Env TcGblEnv TcLclEnv) (HsValBindsLR GhcRn GhcRn, Set Name))
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(HsValBindsLR GhcRn GhcRn)
-> IOEnv
(Env TcGblEnv TcLclEnv) (HsValBindsLR GhcRn GhcRn, Set Name)
forall a b. (a -> b) -> a -> b
$
(NHsValBindsLR GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(NHsValBindsLR GhcRn))
-> a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a
forall (m :: * -> *) a b.
(Monad m, Typeable a, Typeable b) =>
(b -> m b) -> a -> m a
Syb.mkM (DebugNames
-> Map Name (Maybe FastString, Propagation)
-> NHsValBindsLR GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(NHsValBindsLR GhcRn)
modifyValBinds DebugNames
debugNames Map Name (Maybe FastString, Propagation)
nameMap)
(forall a.
Data a =>
a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a)
-> HsValBindsLR GhcRn GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(HsValBindsLR GhcRn GhcRn)
forall (m :: * -> *). Monad m => GenericM m -> GenericM m
`Syb.everywhereM`
HsValBindsLR GhcRn GhcRn
valBinds
([TyClGroup GhcRn]
tyClGroups', Set Name
tyClPatBindNames) <- (StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
([TyClGroup GhcRn], Set Name)
-> Set Name
-> IOEnv (Env TcGblEnv TcLclEnv) ([TyClGroup GhcRn], Set Name)
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
`evalStateT` Set Name
forall a. Set a
S.empty) (StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
([TyClGroup GhcRn], Set Name)
-> IOEnv (Env TcGblEnv TcLclEnv) ([TyClGroup GhcRn], Set Name))
-> (WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
[TyClGroup GhcRn]
-> StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
([TyClGroup GhcRn], Set Name))
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
[TyClGroup GhcRn]
-> IOEnv (Env TcGblEnv TcLclEnv) ([TyClGroup GhcRn], Set Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
[TyClGroup GhcRn]
-> StateT
(Set Name)
(IOEnv (Env TcGblEnv TcLclEnv))
([TyClGroup GhcRn], Set Name)
forall w (m :: * -> *) a. Monoid w => WriterT w m a -> m (a, w)
runWriterT (WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
[TyClGroup GhcRn]
-> IOEnv (Env TcGblEnv TcLclEnv) ([TyClGroup GhcRn], Set Name))
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
[TyClGroup GhcRn]
-> IOEnv (Env TcGblEnv TcLclEnv) ([TyClGroup GhcRn], Set Name)
forall a b. (a -> b) -> a -> b
$
(ClsInstDecl GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(ClsInstDecl GhcRn))
-> a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a
forall (m :: * -> *) a b.
(Monad m, Typeable a, Typeable b) =>
(b -> m b) -> a -> m a
Syb.mkM (DebugNames
-> Map Name (Maybe FastString, Propagation)
-> ClsInstDecl GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(ClsInstDecl GhcRn)
modifyClsInstDecl DebugNames
debugNames Map Name (Maybe FastString, Propagation)
nameMap)
(a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a)
-> (TyClDecl GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(TyClDecl GhcRn))
-> a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a
forall (m :: * -> *) a b.
(Monad m, Typeable a, Typeable b) =>
(a -> m a) -> (b -> m b) -> a -> m a
`Syb.extM`
DebugNames
-> Map Name (Maybe FastString, Propagation)
-> TyClDecl GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(TyClDecl GhcRn)
modifyTyClDecl DebugNames
debugNames Map Name (Maybe FastString, Propagation)
nameMap
(a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a)
-> (NHsValBindsLR GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(NHsValBindsLR GhcRn))
-> a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a
forall (m :: * -> *) a b.
(Monad m, Typeable a, Typeable b) =>
(a -> m a) -> (b -> m b) -> a -> m a
`Syb.extM`
DebugNames
-> Map Name (Maybe FastString, Propagation)
-> NHsValBindsLR GhcRn
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
(NHsValBindsLR GhcRn)
modifyValBinds DebugNames
debugNames Map Name (Maybe FastString, Propagation)
nameMap
(forall a.
Data a =>
a
-> WriterT
(Set Name) (StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv))) a)
-> [TyClGroup GhcRn]
-> WriterT
(Set Name)
(StateT (Set Name) (IOEnv (Env TcGblEnv TcLclEnv)))
[TyClGroup GhcRn]
forall (m :: * -> *). Monad m => GenericM m -> GenericM m
`Syb.everywhereM`
[TyClGroup GhcRn]
tyClGroups
Bool
mmrOn <- TcM Bool
isMonomorphismRestrictionOn
let (HsValBindsLR GhcRn GhcRn
valBinds'', [TyClGroup GhcRn]
tyClGroups'') =
if Bool
mmrOn
then ( DebugNames
-> Set Name -> HsValBindsLR GhcRn GhcRn -> HsValBindsLR GhcRn GhcRn
forall a. Data a => DebugNames -> Set Name -> a -> a
removeConstraints DebugNames
debugNames Set Name
patBindNames HsValBindsLR GhcRn GhcRn
valBinds'
, DebugNames -> Set Name -> [TyClGroup GhcRn] -> [TyClGroup GhcRn]
forall a. Data a => DebugNames -> Set Name -> a -> a
removeConstraints DebugNames
debugNames Set Name
tyClPatBindNames [TyClGroup GhcRn]
tyClGroups'
)
else (HsValBindsLR GhcRn GhcRn
valBinds', [TyClGroup GhcRn]
tyClGroups')
(TcGblEnv, HsGroup GhcRn) -> TcM (TcGblEnv, HsGroup GhcRn)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( TcGblEnv
tcGblEnv
, HsGroup GhcRn
hsGroup' { hs_valds :: HsValBindsLR GhcRn GhcRn
Ghc.hs_valds = HsValBindsLR GhcRn GhcRn
valBinds''
, hs_tyclds :: [TyClGroup GhcRn]
Ghc.hs_tyclds = [TyClGroup GhcRn]
tyClGroups''
}
)
renamedResultAction [CommandLineOption]
_ TcGblEnv
tcGblEnv HsGroup GhcRn
group = (TcGblEnv, HsGroup GhcRn) -> TcM (TcGblEnv, HsGroup GhcRn)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TcGblEnv
tcGblEnv, HsGroup GhcRn
group)