packages feed

mohws-0.2: src/Network/MoHWS/Part/DynHS/GHCUtil.hs

module Network.MoHWS.Part.DynHS.GHCUtil
    (Session,
     initGHC,
     setLogAction,
     withCleanUp,
     getFileValue,
     -- * Error logging
     Severity(..), SrcSpan, PprStyle, Message,
     mkLocMessage
    ) where

-- GHC API stuff
import DynFlags (initDynFlags, defaultDynFlags, )
import ErrUtils (Message, mkLocMessage, )
import GHC
import HscMain (newHscEnv, )
import HscTypes (Session(..), )
import Outputable (PprStyle, )
import SrcLoc (SrcSpan, )
import SysTools (initSysTools, )

import Data.Dynamic (Typeable, fromDynamic, )
import Data.IORef (newIORef, )


initGHC :: FilePath -> IO Session
initGHC pkgDir =
    do s <- newSession' CompManager (Just pkgDir)
       modifySessionDynFlags s (\dflags -> dflags{ hscTarget = HscInterpreted })
       return s



-- Like newSession, but does not install signal handlers
newSession' :: GhcMode -> Maybe FilePath -> IO Session
newSession' mode mb_top_dir = do
  dflags0 <- initSysTools mb_top_dir defaultDynFlags
  dflags  <- initDynFlags dflags0
  env <- newHscEnv dflags{ ghcMode=mode }
  ref <- newIORef env
  return (Session ref)

setLogAction :: Session -> (String -> IO ()) -> IO ()
setLogAction s f =
    modifySessionDynFlags s (\dflags -> dflags { log_action = mkLogAction f })

mkLogAction :: (String -> IO ())
            -> Severity -> SrcSpan -> PprStyle -> Message -> IO ()
mkLogAction f severity srcSpan style msg =
    case severity of
      SevInfo  -> f (show (msg style))
      SevFatal -> f (show (msg style))
      _        -> f (show ((mkLocMessage srcSpan msg) style))


modifySessionDynFlags :: Session -> (DynFlags -> DynFlags) -> IO ()
modifySessionDynFlags s f =
    do dflags <- getSessionDynFlags s
       setSessionDynFlags s (f dflags)
       return ()

withCleanUp :: Session -> IO a -> IO a
withCleanUp s f =
    do dflags <- getSessionDynFlags s
       defaultCleanupHandler dflags f

loadFile :: Session -> FilePath -> IO GHC.Module
loadFile s file =
    do let t = Target (TargetFile file Nothing) Nothing
       setTargets s [t]
       success <- load s LoadAllTargets
       case success of
         Succeeded -> do m <- fileModule s file
                         setContext s [] [m]
                         return m
         Failed    -> fail $ "Failed to load " ++ show file

fileModule :: Session -> FilePath -> IO GHC.Module
fileModule s f =
    do gr <- getModuleGraph s
       case [ms_mod ms | ms <- gr, ml_hs_file (ms_location ms) == Just f]  of
         [m] -> return m
         _   -> fail $ "File " ++ f ++ " does not correspond to a module"

getValue :: Typeable a => Session -> String -> IO a
getValue s x =
    do mdyn <- dynCompileExpr s x
       case mdyn of
         Nothing -> fail $ "dynCompileExpr " ++ show x ++ " failed"
         Just dyn -> case fromDynamic dyn of
                       Nothing -> fail $ "Type error: " ++ x
                                         ++ " is an " ++ show dyn
                       Just y  -> return y

getFileValue :: Typeable a => Session -> FilePath -> String -> IO a
getFileValue s file x =
    do loadFile s file
       getValue s x