diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Haddock/InterfaceFile.hs | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/src/Haddock/InterfaceFile.hs b/src/Haddock/InterfaceFile.hs index 6d96ffa5..226d3acc 100644 --- a/src/Haddock/InterfaceFile.hs +++ b/src/Haddock/InterfaceFile.hs @@ -8,7 +8,7 @@ module Haddock.InterfaceFile ( InterfaceFile(..), - readInterfaceFile, + readInterfaceFile, nameCacheFromGhc, freshNameCache, NameCacheAccessor, writeInterfaceFile ) where @@ -37,6 +37,7 @@ import FastMutInt import HsDoc import FastString import Unique +import MonadUtils ( MonadIO(..) ) data InterfaceFile = InterfaceFile { @@ -142,16 +143,42 @@ writeInterfaceFile filename iface = do writeBinMem bh filename return () +type NameCacheAccessor m = (m NameCache, NameCache -> m ()) + +nameCacheFromGhc :: NameCacheAccessor Ghc +nameCacheFromGhc = ( read_from_session , write_to_session ) + where + read_from_session = do + ref <- withSession (return . hsc_NC) + liftIO $ readIORef ref + write_to_session nc' = do + ref <- withSession (return . hsc_NC) + liftIO $ writeIORef ref nc' + +freshNameCache :: NameCacheAccessor IO +freshNameCache = ( create_fresh_nc , \_ -> return () ) + where + create_fresh_nc = do + u <- mkSplitUniqSupply 'a' -- ?? + return (initNameCache u []) -- | Read a Haddock (@.haddock@) interface file. Return either an --- 'InterfaceFile' or an error message. If given a GHC 'Session', the function --- registers all read names in the name cache of the session. -readInterfaceFile :: Maybe Session -> FilePath -> IO (Either String InterfaceFile) -readInterfaceFile mbSession filename = do - bh0 <- readBinMem filename +-- 'InterfaceFile' or an error message. +-- +-- This function can be called in two ways. Within a GHC session it will +-- update the use and update the session's name cache. Outside a GHC session +-- a new empty name cache is used. The function is therefore generic in the +-- monad being used. The exact monad is whichever monad the first +-- argument, the getter and setter of the name cache, requires. +-- +readInterfaceFile :: MonadIO m => + NameCacheAccessor m + -> FilePath -> m (Either String InterfaceFile) +readInterfaceFile (get_name_cache, set_name_cache) filename = do + bh0 <- liftIO $ readBinMem filename - magic <- get bh0 - version <- get bh0 + magic <- liftIO $ get bh0 + version <- liftIO $ get bh0 case () of _ | magic /= binaryInterfaceMagic -> return . Left $ @@ -160,49 +187,40 @@ readInterfaceFile mbSession filename = do "Interface file is of wrong version: " ++ filename | otherwise -> do - -- get the dictionary - dict_p <- get bh0 - data_p <- tellBin bh0 - seekBin bh0 dict_p - dict <- getDictionary bh0 - seekBin bh0 data_p + dict <- get_dictionary bh0 + bh1 <- init_handle_user_data bh0 dict - -- initialise the user-data field of bh0 - ud <- newReadState dict - bh1 <- return (setUserData bh0 ud) - - -- get the name cache from ghc if we have a ghc session, - -- otherwise create a new one - (theNC, mbRef) <- case mbSession of - Just session -> do - ref <- withSession session (return . hsc_NC) - nc <- readIORef ref - return (nc, Just ref) - Nothing -> do - -- construct an empty name cache - u <- mkSplitUniqSupply 'a' -- ?? - return (initNameCache u [], Nothing) - - -- get the symbol table - symtab_p <- get bh1 - data_p' <- tellBin bh1 - seekBin bh1 symtab_p - (nc', symtab) <- getSymbolTable bh1 theNC - seekBin bh1 data_p' - - -- write back the new name cache if we have a ghc session - case mbRef of - Just ref -> writeIORef ref nc' - Nothing -> return () + theNC <- get_name_cache + (nc', symtab) <- get_symbol_table bh1 theNC + set_name_cache nc' -- set the symbol table let ud' = getUserData bh1 bh2 <- return $! setUserData bh1 ud'{ud_symtab = symtab} -- load the actual data - iface <- get bh2 + iface <- liftIO $ get bh2 return (Right iface) + where + get_dictionary bin_handle = liftIO $ do + dict_p <- get bin_handle + data_p <- tellBin bin_handle + seekBin bin_handle dict_p + dict <- getDictionary bin_handle + seekBin bin_handle data_p + return dict + + init_handle_user_data bin_handle dict = liftIO $ do + ud <- newReadState dict + return (setUserData bin_handle ud) + get_symbol_table bh1 theNC = liftIO $ do + symtab_p <- get bh1 + data_p' <- tellBin bh1 + seekBin bh1 symtab_p + (nc', symtab) <- getSymbolTable bh1 theNC + seekBin bh1 data_p' + return (nc', symtab) ------------------------------------------------------------------------------- -- Symbol table |