diff options
Diffstat (limited to 'src/Haddock/InterfaceFile.hs')
-rw-r--r-- | src/Haddock/InterfaceFile.hs | 189 |
1 files changed, 167 insertions, 22 deletions
diff --git a/src/Haddock/InterfaceFile.hs b/src/Haddock/InterfaceFile.hs index 7964a3a5..c4f24bef 100644 --- a/src/Haddock/InterfaceFile.hs +++ b/src/Haddock/InterfaceFile.hs @@ -1,50 +1,195 @@ module Haddock.InterfaceFile ( InterfaceFile(..), writeInterfaceFile, - readInterfaceFile + readInterfaceFile, + hmod2interface ) where import Haddock.Types import Haddock.Exception -import Binary -import System.IO +import Data.List import Data.Word +import Data.Array +import Data.IORef import qualified Data.Map as Map +import System.IO import Control.Monad +import Binary +import Name +import UniqSupply +import UniqFM +import IfaceEnv +import Module +import Packages +import SrcLoc +import HscTypes +import FastMutInt +import InstEnv +import HsDoc + +data InterfaceMod = InterfaceMod { + imModule :: Module, + imFilename :: FilePath, + imExportItems :: [ExportItem DocName] +} + data InterfaceFile = InterfaceFile { - ifDocEnv :: DocEnv + ifDocEnv :: DocEnv +-- ifModules :: [InterfaceMod] } instance Binary InterfaceFile where - put_ bh (InterfaceFile docEnv) = put_ bh (Map.toList docEnv) - get bh = do - envList <- get bh - return (InterfaceFile (Map.fromList envList)) + put_ bh (InterfaceFile x) = put_ bh (Map.toList x) + get bh = do + env <- get bh + return (InterfaceFile (Map.fromList env)) -packageFileMagic = 0xDA303001 :: Word32 -packageFileVersion = 0 :: Word16 +hmod2interface hmod = InterfaceMod { + imModule = hmod_mod hmod, + imFilename = hmod_orig_filename hmod, + imExportItems = hmod_rn_export_items hmod +} + +binaryInterfaceMagic = 0xD0Cface :: Word32 +binaryInterfaceVersion = 0 :: Word16 + +initBinMemSize = (1024*1024) :: Int writeInterfaceFile :: FilePath -> InterfaceFile -> IO () writeInterfaceFile filename iface = do - h <- openBinaryFile filename WriteMode - bh <- openBinIO h + bh <- openBinMem initBinMemSize + put_ bh binaryInterfaceMagic + put_ bh binaryInterfaceVersion + + -- remember where the dictionary pointer will go + dict_p_p <- tellBin bh + put_ bh dict_p_p + + -- remember where the symbol table pointer will go + symtab_p_p <- tellBin bh + put_ bh symtab_p_p + + -- Make some intial state ud <- newWriteState + + -- put the main thing bh <- return $ setUserData bh ud - put_ bh packageFileMagic - put_ bh packageFileVersion put_ bh iface - hClose h + + -- write the symtab pointer at the fornt of the file + symtab_p <- tellBin bh + putAt bh symtab_p_p symtab_p + seekBin bh symtab_p + + -- write the symbol table itself + symtab_next <- readFastMutInt (ud_symtab_next ud) + symtab_map <- readIORef (ud_symtab_map ud) + putSymbolTable bh symtab_next symtab_map + + -- write the dictionary pointer at the fornt of the file + dict_p <- tellBin bh + putAt bh dict_p_p dict_p + seekBin bh dict_p + + -- write the dictionary itself + dict_next <- readFastMutInt (ud_dict_next ud) + dict_map <- readIORef (ud_dict_map ud) + putDictionary bh dict_next dict_map + + -- snd send the result to the file + writeBinMem bh filename + return () readInterfaceFile :: FilePath -> IO InterfaceFile readInterfaceFile filename = do - h <- openBinaryFile filename ReadMode - bh <- openBinIO h - ud <- newReadState undefined - bh <- return (setUserData bh ud) + bh <- readBinMem filename + magic <- get bh - when (magic /= packageFileMagic) $ throwE $ + when (magic /= binaryInterfaceMagic) $ throwE $ "Magic number mismatch: couldn't load interface file: " ++ filename - (version :: Word16) <- get bh - get bh + + version <- get bh + when (version /= binaryInterfaceVersion) $ throwE $ + "Interface file is of wrong version: " ++ filename + + -- get the dictionary + dict_p <- get bh + data_p <- tellBin bh + seekBin bh dict_p + dict <- getDictionary bh + seekBin bh data_p + + -- initialise the user-data field of bh + ud <- newReadState dict + bh <- return (setUserData bh ud) + + -- get the symbol table + symtab_p <- get bh + data_p <- tellBin bh + seekBin bh symtab_p + -- (construct an empty name cache) + u <- mkSplitUniqSupply 'a' -- ?? + let nc = initNameCache u [] + (_, symtab) <- getSymbolTable bh nc + seekBin bh data_p + + -- set the symbol table + let ud = getUserData bh + bh <- return $! setUserData bh ud{ud_symtab = symtab} + + -- load the actual data + iface <- get bh + return iface + +------------------------------------------------------------------------------- +-- Symbol table +------------------------------------------------------------------------------- + +putSymbolTable :: BinHandle -> Int -> UniqFM (Int,Name) -> IO () +putSymbolTable bh next_off symtab = do + put_ bh next_off + let names = elems (array (0,next_off-1) (eltsUFM symtab)) + mapM_ (\n -> serialiseName bh n symtab) names + +getSymbolTable :: BinHandle -> NameCache -> IO (NameCache, Array Int Name) +getSymbolTable bh namecache = do + sz <- get bh + od_names <- sequence (replicate sz (get bh)) + let + arr = listArray (0,sz-1) names + (namecache', names) = + mapAccumR (fromOnDiskName arr) namecache od_names + -- + return (namecache', arr) + +type OnDiskName = (PackageId, ModuleName, OccName) + +fromOnDiskName + :: Array Int Name + -> NameCache + -> OnDiskName + -> (NameCache, Name) +fromOnDiskName arr nc (pid, mod_name, occ) = + let + mod = mkModule pid mod_name + cache = nsNames nc + in + case lookupOrigNameCache cache mod occ of + Just name -> (nc, name) + Nothing -> + let + us = nsUniqs nc + uniq = uniqFromSupply us + name = mkExternalName uniq mod occ noSrcLoc + new_cache = extendNameCache cache mod occ name + in + case splitUniqSupply us of { (us',_) -> + ( nc{ nsUniqs = us', nsNames = new_cache }, name ) + } + +serialiseName :: BinHandle -> Name -> UniqFM (Int,Name) -> IO () +serialiseName bh name symtab = do + let mod = nameModule name + put_ bh (modulePackageId mod, moduleName mod, nameOccName name) |