PageRenderTime 64ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/utils/haddock/src/Haddock/InterfaceFile.hs

https://bitbucket.org/khibino/ghc-hack
Haskell | 566 lines | 435 code | 84 blank | 47 comment | 4 complexity | ad5e965f7658e3311c8a389debf7878c MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-3.0
  1. {-# LANGUAGE RankNTypes #-}
  2. {-# OPTIONS_GHC -fno-warn-orphans #-}
  3. -----------------------------------------------------------------------------
  4. -- |
  5. -- Module : Haddock.InterfaceFile
  6. -- Copyright : (c) David Waern 2006-2009
  7. -- License : BSD-like
  8. --
  9. -- Maintainer : haddock@projects.haskell.org
  10. -- Stability : experimental
  11. -- Portability : portable
  12. --
  13. -- Reading and writing the .haddock interface file
  14. -----------------------------------------------------------------------------
  15. module Haddock.InterfaceFile (
  16. InterfaceFile(..), ifPackageId,
  17. readInterfaceFile, nameCacheFromGhc, freshNameCache, NameCacheAccessor,
  18. writeInterfaceFile, binaryInterfaceVersion
  19. ) where
  20. import Haddock.Types
  21. import Haddock.Utils hiding (out)
  22. import Data.List
  23. import Data.Word
  24. import Data.Array
  25. import Data.IORef
  26. import qualified Data.Map as Map
  27. import Data.Map (Map)
  28. import GHC hiding (NoLink)
  29. import Binary
  30. import BinIface (getSymtabName, getDictFastString)
  31. import Name
  32. import UniqSupply
  33. import UniqFM
  34. import IfaceEnv
  35. import HscTypes
  36. import GhcMonad (withSession)
  37. import FastMutInt
  38. import FastString
  39. import Unique
  40. data InterfaceFile = InterfaceFile {
  41. ifLinkEnv :: LinkEnv,
  42. ifInstalledIfaces :: [InstalledInterface]
  43. }
  44. ifPackageId :: InterfaceFile -> PackageId
  45. ifPackageId if_ =
  46. case ifInstalledIfaces if_ of
  47. [] -> error "empty InterfaceFile"
  48. iface:_ -> modulePackageId $ instMod iface
  49. binaryInterfaceMagic :: Word32
  50. binaryInterfaceMagic = 0xD0Cface
  51. -- Since datatypes in the GHC API might change between major versions, and
  52. -- because we store GHC datatypes in our interface files, we need to make sure
  53. -- we version our interface files accordingly.
  54. binaryInterfaceVersion :: Word16
  55. #if __GLASGOW_HASKELL__ == 702
  56. binaryInterfaceVersion = 19
  57. #elif __GLASGOW_HASKELL__ == 703
  58. binaryInterfaceVersion = 19
  59. #elif __GLASGOW_HASKELL__ == 704
  60. binaryInterfaceVersion = 19
  61. #elif __GLASGOW_HASKELL__ == 705
  62. binaryInterfaceVersion = 19
  63. #else
  64. #error Unknown GHC version
  65. #endif
  66. initBinMemSize :: Int
  67. initBinMemSize = 1024*1024
  68. writeInterfaceFile :: FilePath -> InterfaceFile -> IO ()
  69. writeInterfaceFile filename iface = do
  70. bh0 <- openBinMem initBinMemSize
  71. put_ bh0 binaryInterfaceMagic
  72. put_ bh0 binaryInterfaceVersion
  73. -- remember where the dictionary pointer will go
  74. dict_p_p <- tellBin bh0
  75. put_ bh0 dict_p_p
  76. -- remember where the symbol table pointer will go
  77. symtab_p_p <- tellBin bh0
  78. put_ bh0 symtab_p_p
  79. -- Make some intial state
  80. symtab_next <- newFastMutInt
  81. writeFastMutInt symtab_next 0
  82. symtab_map <- newIORef emptyUFM
  83. let bin_symtab = BinSymbolTable {
  84. bin_symtab_next = symtab_next,
  85. bin_symtab_map = symtab_map }
  86. dict_next_ref <- newFastMutInt
  87. writeFastMutInt dict_next_ref 0
  88. dict_map_ref <- newIORef emptyUFM
  89. let bin_dict = BinDictionary {
  90. bin_dict_next = dict_next_ref,
  91. bin_dict_map = dict_map_ref }
  92. -- put the main thing
  93. bh <- return $ setUserData bh0 $ newWriteState (putName bin_symtab)
  94. (putFastString bin_dict)
  95. put_ bh iface
  96. -- write the symtab pointer at the front of the file
  97. symtab_p <- tellBin bh
  98. putAt bh symtab_p_p symtab_p
  99. seekBin bh symtab_p
  100. -- write the symbol table itself
  101. symtab_next' <- readFastMutInt symtab_next
  102. symtab_map' <- readIORef symtab_map
  103. putSymbolTable bh symtab_next' symtab_map'
  104. -- write the dictionary pointer at the fornt of the file
  105. dict_p <- tellBin bh
  106. putAt bh dict_p_p dict_p
  107. seekBin bh dict_p
  108. -- write the dictionary itself
  109. dict_next <- readFastMutInt dict_next_ref
  110. dict_map <- readIORef dict_map_ref
  111. putDictionary bh dict_next dict_map
  112. -- and send the result to the file
  113. writeBinMem bh filename
  114. return ()
  115. type NameCacheAccessor m = (m NameCache, NameCache -> m ())
  116. nameCacheFromGhc :: NameCacheAccessor Ghc
  117. nameCacheFromGhc = ( read_from_session , write_to_session )
  118. where
  119. read_from_session = do
  120. ref <- withSession (return . hsc_NC)
  121. liftIO $ readIORef ref
  122. write_to_session nc' = do
  123. ref <- withSession (return . hsc_NC)
  124. liftIO $ writeIORef ref nc'
  125. freshNameCache :: NameCacheAccessor IO
  126. freshNameCache = ( create_fresh_nc , \_ -> return () )
  127. where
  128. create_fresh_nc = do
  129. u <- mkSplitUniqSupply 'a' -- ??
  130. return (initNameCache u [])
  131. -- | Read a Haddock (@.haddock@) interface file. Return either an
  132. -- 'InterfaceFile' or an error message.
  133. --
  134. -- This function can be called in two ways. Within a GHC session it will
  135. -- update the use and update the session's name cache. Outside a GHC session
  136. -- a new empty name cache is used. The function is therefore generic in the
  137. -- monad being used. The exact monad is whichever monad the first
  138. -- argument, the getter and setter of the name cache, requires.
  139. --
  140. readInterfaceFile :: forall m.
  141. MonadIO m
  142. => NameCacheAccessor m
  143. -> FilePath
  144. -> m (Either String InterfaceFile)
  145. readInterfaceFile (get_name_cache, set_name_cache) filename = do
  146. bh0 <- liftIO $ readBinMem filename
  147. magic <- liftIO $ get bh0
  148. version <- liftIO $ get bh0
  149. case () of
  150. _ | magic /= binaryInterfaceMagic -> return . Left $
  151. "Magic number mismatch: couldn't load interface file: " ++ filename
  152. | version /= binaryInterfaceVersion -> return . Left $
  153. "Interface file is of wrong version: " ++ filename
  154. | otherwise -> with_name_cache $ \update_nc -> do
  155. dict <- get_dictionary bh0
  156. -- read the symbol table so we are capable of reading the actual data
  157. bh1 <- do
  158. let bh1 = setUserData bh0 $ newReadState (error "getSymtabName")
  159. (getDictFastString dict)
  160. symtab <- update_nc (get_symbol_table bh1)
  161. return $ setUserData bh1 $ newReadState (getSymtabName (NCU (\f -> update_nc (return . f))) dict symtab)
  162. (getDictFastString dict)
  163. -- load the actual data
  164. iface <- liftIO $ get bh1
  165. return (Right iface)
  166. where
  167. with_name_cache :: forall a.
  168. ((forall n b. MonadIO n
  169. => (NameCache -> n (NameCache, b))
  170. -> n b)
  171. -> m a)
  172. -> m a
  173. with_name_cache act = do
  174. nc_var <- get_name_cache >>= (liftIO . newIORef)
  175. x <- act $ \f -> do
  176. nc <- liftIO $ readIORef nc_var
  177. (nc', x) <- f nc
  178. liftIO $ writeIORef nc_var nc'
  179. return x
  180. liftIO (readIORef nc_var) >>= set_name_cache
  181. return x
  182. get_dictionary bin_handle = liftIO $ do
  183. dict_p <- get bin_handle
  184. data_p <- tellBin bin_handle
  185. seekBin bin_handle dict_p
  186. dict <- getDictionary bin_handle
  187. seekBin bin_handle data_p
  188. return dict
  189. get_symbol_table bh1 theNC = liftIO $ do
  190. symtab_p <- get bh1
  191. data_p' <- tellBin bh1
  192. seekBin bh1 symtab_p
  193. (nc', symtab) <- getSymbolTable bh1 theNC
  194. seekBin bh1 data_p'
  195. return (nc', symtab)
  196. -------------------------------------------------------------------------------
  197. -- * Symbol table
  198. -------------------------------------------------------------------------------
  199. putName :: BinSymbolTable -> BinHandle -> Name -> IO ()
  200. putName BinSymbolTable{
  201. bin_symtab_map = symtab_map_ref,
  202. bin_symtab_next = symtab_next } bh name
  203. = do
  204. symtab_map <- readIORef symtab_map_ref
  205. case lookupUFM symtab_map name of
  206. Just (off,_) -> put_ bh (fromIntegral off :: Word32)
  207. Nothing -> do
  208. off <- readFastMutInt symtab_next
  209. writeFastMutInt symtab_next (off+1)
  210. writeIORef symtab_map_ref
  211. $! addToUFM symtab_map name (off,name)
  212. put_ bh (fromIntegral off :: Word32)
  213. data BinSymbolTable = BinSymbolTable {
  214. bin_symtab_next :: !FastMutInt, -- The next index to use
  215. bin_symtab_map :: !(IORef (UniqFM (Int,Name)))
  216. -- indexed by Name
  217. }
  218. putFastString :: BinDictionary -> BinHandle -> FastString -> IO ()
  219. putFastString BinDictionary { bin_dict_next = j_r,
  220. bin_dict_map = out_r} bh f
  221. = do
  222. out <- readIORef out_r
  223. let unique = getUnique f
  224. case lookupUFM out unique of
  225. Just (j, _) -> put_ bh (fromIntegral j :: Word32)
  226. Nothing -> do
  227. j <- readFastMutInt j_r
  228. put_ bh (fromIntegral j :: Word32)
  229. writeFastMutInt j_r (j + 1)
  230. writeIORef out_r $! addToUFM out unique (j, f)
  231. data BinDictionary = BinDictionary {
  232. bin_dict_next :: !FastMutInt, -- The next index to use
  233. bin_dict_map :: !(IORef (UniqFM (Int,FastString)))
  234. -- indexed by FastString
  235. }
  236. putSymbolTable :: BinHandle -> Int -> UniqFM (Int,Name) -> IO ()
  237. putSymbolTable bh next_off symtab = do
  238. put_ bh next_off
  239. let names = elems (array (0,next_off-1) (eltsUFM symtab))
  240. mapM_ (\n -> serialiseName bh n symtab) names
  241. getSymbolTable :: BinHandle -> NameCache -> IO (NameCache, Array Int Name)
  242. getSymbolTable bh namecache = do
  243. sz <- get bh
  244. od_names <- sequence (replicate sz (get bh))
  245. let
  246. arr = listArray (0,sz-1) names
  247. (namecache', names) =
  248. mapAccumR (fromOnDiskName arr) namecache od_names
  249. --
  250. return (namecache', arr)
  251. type OnDiskName = (PackageId, ModuleName, OccName)
  252. fromOnDiskName
  253. :: Array Int Name
  254. -> NameCache
  255. -> OnDiskName
  256. -> (NameCache, Name)
  257. fromOnDiskName _ nc (pid, mod_name, occ) =
  258. let
  259. modu = mkModule pid mod_name
  260. cache = nsNames nc
  261. in
  262. case lookupOrigNameCache cache modu occ of
  263. Just name -> (nc, name)
  264. Nothing ->
  265. let
  266. us = nsUniqs nc
  267. u = uniqFromSupply us
  268. name = mkExternalName u modu occ noSrcSpan
  269. new_cache = extendNameCache cache modu occ name
  270. in
  271. case splitUniqSupply us of { (us',_) ->
  272. ( nc{ nsUniqs = us', nsNames = new_cache }, name )
  273. }
  274. serialiseName :: BinHandle -> Name -> UniqFM (Int,Name) -> IO ()
  275. serialiseName bh name _ = do
  276. let modu = nameModule name
  277. put_ bh (modulePackageId modu, moduleName modu, nameOccName name)
  278. -------------------------------------------------------------------------------
  279. -- * GhcBinary instances
  280. -------------------------------------------------------------------------------
  281. instance (Ord k, Binary k, Binary v) => Binary (Map k v) where
  282. put_ bh m = put_ bh (Map.toList m)
  283. get bh = fmap (Map.fromList) (get bh)
  284. instance Binary InterfaceFile where
  285. put_ bh (InterfaceFile env ifaces) = do
  286. put_ bh env
  287. put_ bh ifaces
  288. get bh = do
  289. env <- get bh
  290. ifaces <- get bh
  291. return (InterfaceFile env ifaces)
  292. instance Binary InstalledInterface where
  293. put_ bh (InstalledInterface modu info docMap argMap exps visExps opts subMap) = do
  294. put_ bh modu
  295. put_ bh info
  296. put_ bh docMap
  297. put_ bh argMap
  298. put_ bh exps
  299. put_ bh visExps
  300. put_ bh opts
  301. put_ bh subMap
  302. get bh = do
  303. modu <- get bh
  304. info <- get bh
  305. docMap <- get bh
  306. argMap <- get bh
  307. exps <- get bh
  308. visExps <- get bh
  309. opts <- get bh
  310. subMap <- get bh
  311. return (InstalledInterface modu info docMap argMap
  312. exps visExps opts subMap)
  313. instance Binary DocOption where
  314. put_ bh OptHide = do
  315. putByte bh 0
  316. put_ bh OptPrune = do
  317. putByte bh 1
  318. put_ bh OptIgnoreExports = do
  319. putByte bh 2
  320. put_ bh OptNotHome = do
  321. putByte bh 3
  322. get bh = do
  323. h <- getByte bh
  324. case h of
  325. 0 -> do
  326. return OptHide
  327. 1 -> do
  328. return OptPrune
  329. 2 -> do
  330. return OptIgnoreExports
  331. 3 -> do
  332. return OptNotHome
  333. _ -> fail "invalid binary data found"
  334. instance Binary Example where
  335. put_ bh (Example expression result) = do
  336. put_ bh expression
  337. put_ bh result
  338. get bh = do
  339. expression <- get bh
  340. result <- get bh
  341. return (Example expression result)
  342. {-* Generated by DrIFT : Look, but Don't Touch. *-}
  343. instance (Binary id) => Binary (Doc id) where
  344. put_ bh DocEmpty = do
  345. putByte bh 0
  346. put_ bh (DocAppend aa ab) = do
  347. putByte bh 1
  348. put_ bh aa
  349. put_ bh ab
  350. put_ bh (DocString ac) = do
  351. putByte bh 2
  352. put_ bh ac
  353. put_ bh (DocParagraph ad) = do
  354. putByte bh 3
  355. put_ bh ad
  356. put_ bh (DocIdentifier ae) = do
  357. putByte bh 4
  358. put_ bh ae
  359. put_ bh (DocModule af) = do
  360. putByte bh 5
  361. put_ bh af
  362. put_ bh (DocEmphasis ag) = do
  363. putByte bh 6
  364. put_ bh ag
  365. put_ bh (DocMonospaced ah) = do
  366. putByte bh 7
  367. put_ bh ah
  368. put_ bh (DocUnorderedList ai) = do
  369. putByte bh 8
  370. put_ bh ai
  371. put_ bh (DocOrderedList aj) = do
  372. putByte bh 9
  373. put_ bh aj
  374. put_ bh (DocDefList ak) = do
  375. putByte bh 10
  376. put_ bh ak
  377. put_ bh (DocCodeBlock al) = do
  378. putByte bh 11
  379. put_ bh al
  380. put_ bh (DocURL am) = do
  381. putByte bh 12
  382. put_ bh am
  383. put_ bh (DocPic x) = do
  384. putByte bh 13
  385. put_ bh x
  386. put_ bh (DocAName an) = do
  387. putByte bh 14
  388. put_ bh an
  389. put_ bh (DocExamples ao) = do
  390. putByte bh 15
  391. put_ bh ao
  392. put_ bh (DocIdentifierUnchecked x) = do
  393. putByte bh 16
  394. put_ bh x
  395. get bh = do
  396. h <- getByte bh
  397. case h of
  398. 0 -> do
  399. return DocEmpty
  400. 1 -> do
  401. aa <- get bh
  402. ab <- get bh
  403. return (DocAppend aa ab)
  404. 2 -> do
  405. ac <- get bh
  406. return (DocString ac)
  407. 3 -> do
  408. ad <- get bh
  409. return (DocParagraph ad)
  410. 4 -> do
  411. ae <- get bh
  412. return (DocIdentifier ae)
  413. 5 -> do
  414. af <- get bh
  415. return (DocModule af)
  416. 6 -> do
  417. ag <- get bh
  418. return (DocEmphasis ag)
  419. 7 -> do
  420. ah <- get bh
  421. return (DocMonospaced ah)
  422. 8 -> do
  423. ai <- get bh
  424. return (DocUnorderedList ai)
  425. 9 -> do
  426. aj <- get bh
  427. return (DocOrderedList aj)
  428. 10 -> do
  429. ak <- get bh
  430. return (DocDefList ak)
  431. 11 -> do
  432. al <- get bh
  433. return (DocCodeBlock al)
  434. 12 -> do
  435. am <- get bh
  436. return (DocURL am)
  437. 13 -> do
  438. x <- get bh
  439. return (DocPic x)
  440. 14 -> do
  441. an <- get bh
  442. return (DocAName an)
  443. 15 -> do
  444. ao <- get bh
  445. return (DocExamples ao)
  446. 16 -> do
  447. x <- get bh
  448. return (DocIdentifierUnchecked x)
  449. _ -> fail "invalid binary data found"
  450. instance Binary name => Binary (HaddockModInfo name) where
  451. put_ bh hmi = do
  452. put_ bh (hmi_description hmi)
  453. put_ bh (hmi_portability hmi)
  454. put_ bh (hmi_stability hmi)
  455. put_ bh (hmi_maintainer hmi)
  456. put_ bh (hmi_safety hmi)
  457. get bh = do
  458. descr <- get bh
  459. porta <- get bh
  460. stabi <- get bh
  461. maint <- get bh
  462. safet <- get bh
  463. return (HaddockModInfo descr porta stabi maint safet)
  464. instance Binary DocName where
  465. put_ bh (Documented name modu) = do
  466. putByte bh 0
  467. put_ bh name
  468. put_ bh modu
  469. put_ bh (Undocumented name) = do
  470. putByte bh 1
  471. put_ bh name
  472. get bh = do
  473. h <- getByte bh
  474. case h of
  475. 0 -> do
  476. name <- get bh
  477. modu <- get bh
  478. return (Documented name modu)
  479. 1 -> do
  480. name <- get bh
  481. return (Undocumented name)
  482. _ -> error "get DocName: Bad h"