{-# OPTIONS_GHC -cpp #-} module Shim.GhcCompat ( load , getModuleGraph , getSessionDynFlags , getRdrNamesInScope , findModule , exprType , getPrintUnqual , compileExpr , setSessionDynFlags , setTargets , setContext , getModuleInfo , lookupName , newSession , getContext , modInfoLookupName , checkModule , parseDynamicFlags , workingDirectoryChanged , getNamesInScope ) where #if __GLASGOW_HASKELL__ >= 610 import GHC hiding ( load, getModuleGraph, getSessionDynFlags, getRdrNamesInScope, findModule, exprType, getPrintUnqual, compileExpr, setSessionDynFlags, setTargets, setContext, load, getModuleInfo, lookupName, getContext, modInfoLookupName, parseDynamicFlags, workingDirectoryChanged, getNamesInScope) #else import GHC hiding ( load, newSession, parseDynamicFlags ) #endif import qualified GHC as GHC import StaticFlags import Panic import HscTypes -- FIX: we should check for Cabal version instead #if __GLASGOW_HASKELL__ >= 610 import qualified Distribution.PackageDescription.Parse as DP #else import qualified Distribution.PackageDescription as DP #endif import Distribution.Verbosity import Control.Concurrent.MVar ( tryTakeMVar, modifyMVar_, newMVar, readMVar, putMVar ) import Data.List ( nub, find ) import System.IO.Unsafe ( unsafePerformIO ) import Data.IORef #if __GLASGOW_HASKELL__ == 606 {- needed to work around a bug in ghc 6.6: newSession hangs when called for the second time because 6.6 release has: interruptTargetThread = unsafePerformIO newEmptyMVar ... putMVar interruptTargetThread [main_thread] ghc > 6.6 has: interruptTargetThread = unsafePerformIO (newMVar []) ... modifyMVar_ interruptTargetThread (return . (main_thread :)) -} newSession :: GhcMode -> Maybe FilePath -> IO Session newSession mode mb_top_dir = do old <- tryTakeMVar interruptTargetThread case old of Nothing -> -- =6.6, first newSession and empty MVar do modifyMVar_ haveNewSessionBug (const $ return True) GHC.newSession mode mb_top_dir Just tids -> -- both ghc versions, nonempty MVar do bug <- readMVar haveNewSessionBug if bug then do ses <- GHC.newSession mode mb_top_dir modifyMVar_ interruptTargetThread (return . (++tids)) return ses else do putMVar interruptTargetThread tids GHC.newSession mode mb_top_dir {-# NOINLINE haveNewSessionBug #-} haveNewSessionBug = unsafePerformIO (newMVar False) #elif __GLASGOW_HASKELL__ == 608 -- Hack to get parseStaticFlags called only once initGhc = unsafePerformIO$ parseStaticFlags [] newSession :: Maybe FilePath -> IO Session newSession fp = initGhc `seq` GHC.newSession fp -- >= 6.10 #else newSession :: Maybe FilePath -> IO Session newSession fp = runGhc fp getRealSession getRealSession :: Ghc Session getRealSession = do hscEnv <- getSession warns <- getWarnings ref1 <- liftIO $ newIORef hscEnv ref2 <- liftIO $ newIORef warns return $ Session ref1 ref2 #endif readPackageDescription = DP.readPackageDescription silent #if __GLASGOW_HASKELL__ < 610 type TypecheckedModule = CheckedModule parseDynamicFlags ses a b = GHC.parseDynamicFlags a b #endif #if __GLASGOW_HASKELL__ >= 610 getModuleGraph session = reflectGhc GHC.getModuleGraph session getSessionDynFlags session = reflectGhc GHC.getSessionDynFlags session setSessionDynFlags session f = reflectGhc (GHC.setSessionDynFlags f) session findModule session a b = reflectGhc (GHC.findModule a b) session getRdrNamesInScope session = reflectGhc GHC.getRdrNamesInScope session -- FIX: we should catch the exception exprType session e = fmap Just $ reflectGhc (GHC.exprType e) session getPrintUnqual session = reflectGhc GHC.getPrintUnqual session -- FIX: we should catch the exception compileExpr session e = fmap Just $ reflectGhc (GHC.compileExpr e) session setTargets session ts = reflectGhc (GHC.setTargets ts) session setContext session a b = reflectGhc (GHC.setContext a b) session load session a = reflectGhc (GHC.load a) session getModuleInfo session a = reflectGhc (GHC.getModuleInfo a) session lookupName session a = reflectGhc (GHC.lookupName a) session modInfoLookupName session a b = reflectGhc (GHC.modInfoLookupName a b) session parseDynamicFlags session a b = fmap (\(a,b,_) -> (a,b)) $ reflectGhc (GHC.parseDynamicFlags a (map noLoc b)) session getContext session = reflectGhc GHC.getContext session workingDirectoryChanged session = reflectGhc GHC.workingDirectoryChanged session getNamesInScope session = reflectGhc GHC.getNamesInScope session checkModule :: Session -> ModuleName -> Bool -> IO (Maybe TypecheckedModule) checkModule session modname _ = do graph <- getModuleGraph session let res = find ((modname ==) . moduleName . ms_mod) graph case res of Just modsum -> fmap Just $ reflectGhc (typecheckModule =<< parseModule modsum) session Nothing -> return Nothing #endif