on master help sign in
Store hash of the IBC file's interface

This saves rechecking a file if none of its imports have the same interfaces and there are otherwise no changes. The hash function is probably quite bad, so if you know how to do a better one please consider contributing it! Also, this makes an already terrible piece of code in Parser.hs even worse (sorry) and it's crying out for a refactoring if anyone has any enthusiasm for it (as is the whole system of chasing dependencies and loading modules). This is mostly to speed up development of Blodwen, which was really starting to get painful when making small changes to core modules.

commitb2f419b0dd49f7fcaca87f52aab49f0ac5ca230f authorEdwin Brady <ecb10@st-andrews.ac.uk> dateTue 23 Oct 2018, 10:07 (8 years ago) parent8fc6989
3 files changed+263−160
src/Idris/AbsSyntaxTree.hs+1 src/Idris/IBC.hs+74−6 src/Idris/Parser.hs+188−154
src/Idris/AbsSyntaxTree.hs+1
@@ -392,6 +392,7 @@ data IBCWrite = IBCFix FixDecl
392392 | IBCDeprecate Name String
393393 | IBCFragile Name String
394394 | IBCConstraint FC UConstraint
395+ | IBCImportHash FilePath Int
395396 deriving (Show, Generic)
396397
397398initialInteractiveOpts :: InteractiveOpts
src/Idris/IBC.hs+74−6
@@ -12,7 +12,8 @@ Maintainer : The Idris Community.
1212
1313module Idris.IBC (loadIBC, loadPkgIndex,
1414 writeIBC, writePkgIndex,
15− hasValidIBCVersion, IBCPhase(..)) where
15+ hasValidIBCVersion, IBCPhase(..),
16+ getIBCHash, getImportHashes) where
1617
1718import Idris.AbsSyntax
1819import Idris.Core.CaseTree
@@ -40,7 +41,7 @@ import System.Directory
4041import System.FilePath
4142
4243ibcVersion :: Word16
43−ibcVersion = 165
44+ibcVersion = 166
4445
4546-- | When IBC is being loaded - we'll load different things (and omit
4647-- different structures/definitions) depending on which phase we're in.
@@ -50,6 +51,7 @@ data IBCPhase = IBC_Building -- ^ when building the module tree
5051
5152data IBCFile = IBCFile {
5253 ver :: Word16
54+ , iface_hash :: Int
5355 , sourcefile :: FilePath
5456 , ibc_imports :: ![(Bool, FilePath)]
5557 , ibc_importdirs :: ![FilePath]
@@ -101,6 +103,7 @@ data IBCFile = IBCFile {
101103 , ibc_fragile :: ![(Name, String)]
102104 , ibc_constraints :: ![(FC, UConstraint)]
103105 , ibc_langexts :: ![LanguageExt]
106+ , ibc_importhashes :: ![(FilePath, Int)]
104107 }
105108 deriving Show
106109{-!
@@ -108,7 +111,7 @@ deriving instance Binary IBCFile
108111!-}
109112
110113initIBC :: IBCFile
111−initIBC = IBCFile ibcVersion "" [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] Nothing [] [] [] [] [] [] [] [] [] [] []
114+initIBC = IBCFile ibcVersion 0 "" [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] Nothing [] [] [] [] [] [] [] [] [] [] [] []
112115
113116hasValidIBCVersion :: FilePath -> Idris Bool
114117hasValidIBCVersion fp = do
@@ -143,6 +146,21 @@ loadIBC reexport phase fp
143146 else unhide phase fp archive
144147 addImported reexport fp
145148
149+getIBCHash :: FilePath -> Idris Int
150+getIBCHash fp
151+ = do archiveFile <- runIO $ B.readFile fp
152+ case toArchiveOrFail archiveFile of
153+ Left _ -> return 0
154+ Right archive -> getEntry 0 "iface_hash" archive
155+
156+
157+getImportHashes :: FilePath -> Idris [(FilePath, Int)]
158+getImportHashes fp
159+ = do archiveFile <- runIO $ B.readFile fp
160+ case toArchiveOrFail archiveFile of
161+ Left _ -> return []
162+ Right archive -> getEntry [] "ibc_importhashes" archive
163+
146164-- | Load an entire package from its index file
147165loadPkgIndex :: PkgName -> Idris ()
148166loadPkgIndex pkg = do ddir <- runIO getIdrisLibDir
@@ -159,6 +177,7 @@ makeEntry name val = if L.null val
159177
160178entries :: IBCFile -> [Entry]
161179entries i = catMaybes [Just $ toEntry "ver" 0 (encode $ ver i),
180+ Just $ toEntry "iface_hash" 0 (encode $ iface_hash i),
162181 makeEntry "sourcefile" (sourcefile i),
163182 makeEntry "ibc_imports" (ibc_imports i),
164183 makeEntry "ibc_importdirs" (ibc_importdirs i),
@@ -208,7 +227,8 @@ entries i = catMaybes [Just $ toEntry "ver" 0 (encode $ ver i),
208227 makeEntry "ibc_injective" (ibc_injective i),
209228 makeEntry "ibc_access" (ibc_access i),
210229 makeEntry "ibc_fragile" (ibc_fragile i),
211− makeEntry "ibc_langexts" (ibc_langexts i)]
230+ makeEntry "ibc_langexts" (ibc_langexts i),
231+ makeEntry "ibc_importhashes" (ibc_importhashes i)]
212232-- TODO: Put this back in shortly after minimising/pruning constraints
213233-- makeEntry "ibc_constraints" (ibc_constraints i)]
214234
@@ -223,14 +243,61 @@ writeIBC src f
223243 iReport 2 $ "Writing IBC for: " ++ show f
224244 i <- getIState
225245 resetNameIdx
226− ibcf <- mkIBC (ibc_write i) (initIBC { sourcefile = src,
227− ibc_langexts = idris_language_extensions i })
246+ ibc_data <- mkIBC (ibc_write i) (initIBC { sourcefile = src,
247+ ibc_langexts = idris_language_extensions i })
248+ let ibcf = ibc_data { iface_hash = calculateHash i ibc_data }
249+ logIBC 5 $ "Hash for " ++ show f ++ " = " ++ show (iface_hash ibcf)
228250 idrisCatch (do runIO $ createDirectoryIfMissing True (dropFileName f)
229251 writeArchive f ibcf
230252 logIBC 2 "Written")
231253 (\c -> do logIBC 2 $ "Failed " ++ pshow i c)
232254 return ()
233255
256+qhash :: Int -> String -> Int
257+qhash hash [] = abs hash `mod` 0xffffffff
258+qhash hash (x:xs) = qhash (hash * 33 + fromIntegral (fromEnum x)) xs
259+
260+hashTerm :: Term -> Int
261+hashTerm t = qhash 5381 (show t)
262+
263+hashName :: Name -> Int
264+hashName n = qhash 5381 (show n)
265+
266+calculateHash :: IState -> IBCFile -> Int
267+calculateHash ist f
268+ = let acc = L.filter exported (ibc_access f) in
269+ mkHashFrom (map fst acc) (getDefs acc)
270+ where
271+ mkHashFrom :: [Name] -> [Term] -> Int
272+ mkHashFrom ns tms = sum (map hashName ns) + sum (map hashTerm tms)
273+
274+ exported (_, Public) = True
275+ exported (_, Frozen) = True
276+ exported _ = False
277+
278+ findTms :: [(a, Term, Term)] -> [Term]
279+ findTms = L.concatMap (\ (_, x, y) -> [x, y])
280+
281+ patDef :: Name -> [Term]
282+ patDef n
283+ = case lookupCtxtExact n (idris_patdefs ist) of
284+ Nothing -> []
285+ Just (tms, _) -> findTms tms
286+
287+ getDefs :: [(Name, Accessibility)] -> [Term]
288+ getDefs [] = []
289+ getDefs ((n, Public) : ns)
290+ = let ts = getDefs ns in
291+ case lookupTyExact n (tt_ctxt ist) of
292+ Nothing -> ts
293+ Just ty -> ty : patDef n ++ ts
294+ getDefs ((n, Frozen) : ns)
295+ = let ts = getDefs ns in
296+ case lookupTyExact n (tt_ctxt ist) of
297+ Nothing -> ts
298+ Just ty -> ty : ts
299+ getDefs (_ : ns) = getDefs ns
300+
234301-- | Write a package index containing all the imports in the current
235302-- IState Used for ':search' of an entire package, to ensure
236303-- everything is loaded.
@@ -347,6 +414,7 @@ ibc i (IBCAutoHint n h) f = return f { ibc_autohints = (n, h) : ibc_autohints f
347414ibc i (IBCDeprecate n r) f = return f { ibc_deprecated = (n, r) : ibc_deprecated f }
348415ibc i (IBCFragile n r) f = return f { ibc_fragile = (n,r) : ibc_fragile f }
349416ibc i (IBCConstraint fc u) f = return f { ibc_constraints = (fc, u) : ibc_constraints f }
417+ibc i (IBCImportHash fn h) f = return f { ibc_importhashes = (fn, h) : ibc_importhashes f }
350418
351419getEntry :: (Binary b, NFData b) => b -> FilePath -> Archive -> Idris b
352420getEntry alt f a = case findEntryByPath f a of
src/Idris/Parser.hs+188−154
@@ -55,7 +55,7 @@ import Data.Maybe
5555import Data.Ord
5656import qualified Data.Set as S
5757import qualified Data.Text as T
58−import qualified System.Directory as Dir (makeAbsolute)
58+import qualified System.Directory as Dir (makeAbsolute, getModificationTime, doesFileExist)
5959import System.FilePath
6060import Text.Megaparsec ((<?>))
6161import qualified Text.Megaparsec as P
@@ -1640,162 +1640,196 @@ loadSource' lidr r maxline
16401640{-| Load Idris source code-}
16411641loadSource :: Bool -> FilePath -> Maybe Int -> Idris ()
16421642loadSource lidr f toline
1643− = do logParser 1 ("Reading " ++ f)
1644− iReport 2 ("Reading " ++ f)
1645− i <- getIState
1646− let def_total = default_total i
1647− file_in <- runIO $ readSource f
1648− file <- if lidr then tclift $ unlit f file_in else return file_in
1649− (mdocs, mname, imports_in, pos) <- parseImports f file
1650− ai <- getAutoImports
1651− let imports = map (\n -> ImportInfo True n Nothing [] NoFC NoFC) ai ++ imports_in
1652− ids <- rankedImportDirs f
1653− ibcsd <- valIBCSubDir i
1654− mapM_ (\(re, f, ns, nfc) ->
1655− do fp <- findImport ids ibcsd f
1656− case fp of
1657− LIDR fn -> ifail $ "No ibc for " ++ f
1658− IDR fn -> ifail $ "No ibc for " ++ f
1659− IBC fn src ->
1660− do loadIBC True IBC_Building fn
1661− let srcFn = case src of
1662− IDR fn -> Just fn
1663− LIDR fn -> Just fn
1664− _ -> Nothing
1665− srcFnAbs <- case srcFn of
1666− Just fn -> fmap Just (runIO $ Dir.makeAbsolute fn)
1667− Nothing -> return Nothing
1668− sendHighlighting $ S.fromList [(FC' nfc, AnnNamespace ns srcFnAbs)])
1669− [(re, fn, ns, nfc) | ImportInfo re fn _ ns _ nfc <- imports]
1670− reportParserWarnings
1671− sendParserHighlighting
1672−
1673− -- process and check module aliases
1674− let modAliases = M.fromList
1675− [ (prep alias, prep realName)
1676− | ImportInfo { import_reexport = reexport
1677− , import_path = realName
1678− , import_rename = Just (alias, _)
1679− , import_location = fc } <- imports
1680− ]
1681− prep = map T.pack . reverse . Spl.splitOn [pathSeparator]
1682− aliasNames = [ (alias, fc)
1683− | ImportInfo { import_rename = Just (alias, fc)
1684− } <- imports
1685− ]
1686− histogram = groupBy ((==) `on` fst) . sortBy (comparing fst) $ aliasNames
1687− case map head . filter ((/= 1) . length) $ histogram of
1688− [] -> logParser 3 $ "Module aliases: " ++ show (M.toList modAliases)
1689− (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1690−
1691− i <- getIState
1692− putIState (i { default_access = Private, module_aliases = modAliases })
1693− clearIBC -- start a new .ibc file
1694− -- record package info in .ibc
1695− imps <- allImportDirs
1696− mapM_ addIBC (map IBCImportDir imps)
1697− mapM_ (addIBC . IBCImport)
1698− [ (reexport, realName)
1643+ = do logParser 1 ("Reading " ++ f)
1644+ iReport 2 ("Reading " ++ f)
1645+ i <- getIState
1646+ let def_total = default_total i
1647+ file_in <- runIO $ readSource f
1648+ file <- if lidr then tclift $ unlit f file_in else return file_in
1649+ (mdocs, mname, imports_in, pos) <- parseImports f file
1650+ ai <- getAutoImports
1651+ let imports = map (\n -> ImportInfo True n Nothing [] NoFC NoFC) ai ++ imports_in
1652+ ids <- rankedImportDirs f
1653+ ibcsd <- valIBCSubDir i
1654+ let ibc = ibcPathNoFallback ibcsd f
1655+ impHashes <- idrisCatch (getImportHashes ibc)
1656+ (\err -> return [])
1657+ newHashes <- mapM (\ (_, f, _, _) ->
1658+ do fp <- findImport ids ibcsd f
1659+ case fp of
1660+ IBC fn src ->
1661+ idrisCatch (do hash <- getIBCHash fn
1662+ return (Just (fn, hash)))
1663+ (\err -> return Nothing)
1664+ _ -> return Nothing)
1665+ [(re, fn, ns, nfc) | ImportInfo re fn _ ns _ nfc <- imports]
1666+
1667+ fmod <- liftIO $ Dir.getModificationTime f
1668+ ibcexists <- liftIO $ Dir.doesFileExist ibc
1669+ ibcmod <- if ibcexists
1670+ then liftIO $ Dir.getModificationTime ibc
1671+ else return fmod
1672+
1673+ logParser 10 $ ibc ++ " " ++ show ibcmod
1674+ logParser 10 $ f ++ " " ++ show fmod
1675+ logParser 10 $ show impHashes ++ "\n" ++ show newHashes
1676+
1677+ -- If the ibc is newer than the source, and the old import
1678+ -- hashes are the same as the ones we've just read,
1679+ -- quit and just load the IBC
1680+
1681+ let needLoad = (ibcmod <= fmod) ||
1682+ (sort impHashes /= sort (mapMaybe id newHashes))
1683+
1684+ if not needLoad
1685+ then iReport 1 $ "Loading " ++ f
1686+ else do
1687+ mapM_ (\ (re, f, ns, nfc) ->
1688+ do fp <- findImport ids ibcsd f
1689+ case fp of
1690+ LIDR fn -> ifail $ "No ibc for " ++ f
1691+ IDR fn -> ifail $ "No ibc for " ++ f
1692+ IBC fn src ->
1693+ do loadIBC True IBC_Building fn
1694+ let srcFn = case src of
1695+ IDR fn -> Just fn
1696+ LIDR fn -> Just fn
1697+ _ -> Nothing
1698+ srcFnAbs <- case srcFn of
1699+ Just fn -> fmap Just (runIO $ Dir.makeAbsolute fn)
1700+ Nothing -> return Nothing
1701+ sendHighlighting $ S.fromList [(FC' nfc, AnnNamespace ns srcFnAbs)])
1702+ [(re, fn, ns, nfc) | ImportInfo re fn _ ns _ nfc <- imports]
1703+ reportParserWarnings
1704+ sendParserHighlighting
1705+
1706+ -- process and check module aliases
1707+ let modAliases = M.fromList
1708+ [ (prep alias, prep realName)
16991709 | ImportInfo { import_reexport = reexport
17001710 , import_path = realName
1701− } <- imports
1711+ , import_rename = Just (alias, _)
1712+ , import_location = fc } <- imports
17021713 ]
1703− let syntax = defaultSyntax{ syn_namespace = reverse mname,
1704− maxline = toline }
1705− ist <- getIState
1706− -- Save the span from parsing the module header, because
1707− -- an empty program parse might obliterate it.
1708− let oldSpan = idris_parsedSpan ist
1709− ds' <- parseProg syntax f file pos
1710−
1711− case (ds', oldSpan) of
1712− ([], Just fc) ->
1713− -- If no program elements were parsed, we dind't
1714− -- get a loaded region in the IBC file. That
1715− -- means we need to add it back.
1716− do ist <- getIState
1717− putIState ist { idris_parsedSpan = oldSpan
1718− , ibc_write = IBCParsedRegion fc :
1719− ibc_write ist
1720− }
1721− _ -> return ()
1722− sendParserHighlighting
1723−
1724− -- Parsing done, now process declarations
1725−
1726− let ds = namespaces mname ds'
1727− logParser 3 (show $ showDecls verbosePPOption ds)
1728− i <- getIState
1729− logLvl 10 (show (toAlist (idris_implicits i)))
1730− logLvl 3 (show (idris_infixes i))
1731− -- Now add all the declarations to the context
1732− iReport 1 $ "Type checking " ++ f
1733− -- we totality check after every Mutual block, so if
1734− -- anything is a single definition, wrap it in a
1735− -- mutual block on its own
1736− elabDecls (toplevelWith f) (map toMutual ds)
1737− i <- getIState
1738− -- simplify every definition do give the totality checker
1739− -- a better chance
1740− mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1741− ctxt' <-
1742− do ctxt <- getContext
1743− tclift $ simplifyCasedef n [] [] (getErasureInfo i) ctxt
1744− setContext ctxt')
1745− (map snd (idris_totcheck i))
1746− -- build size change graph from simplified definitions
1747− iReport 3 $ "Totality checking " ++ f
1748− logLvl 1 $ "Totality checking " ++ f
1749− i <- getIState
1750− mapM_ buildSCG (idris_totcheck i)
1751− mapM_ checkDeclTotality (idris_totcheck i)
1752− mapM_ verifyTotality (idris_totcheck i)
1753−
1754− -- Redo totality check for deferred names
1755− let deftots = idris_defertotcheck i
1756− logLvl 2 $ "Totality checking " ++ show deftots
1757− mapM_ (\x -> do tot <- getTotality x
1758− case tot of
1759− Total _ ->
1760− do let opts = case lookupCtxtExact x (idris_flags i) of
1761− Just os -> os
1762− Nothing -> []
1763− when (AssertTotal `notElem` opts) $
1764− setTotality x Unchecked
1765− _ -> return ()) (map snd deftots)
1766− mapM_ buildSCG deftots
1767− mapM_ checkDeclTotality deftots
1768−
1769− logLvl 1 ("Finished " ++ f)
1770− ibcsd <- valIBCSubDir i
1771− logLvl 1 $ "Universe checking " ++ f
1772− iReport 3 $ "Universe checking " ++ f
1773− iucheck
1774− let ibc = ibcPathNoFallback ibcsd f
1775− i <- getIState
1776− addHides (hide_list i)
1777−
1778− -- Save module documentation if applicable
1779− i <- getIState
1780− case mdocs of
1781− Nothing -> return ()
1782− Just docs -> addModDoc syntax mname docs
1783−
1784−
1785− -- Finally, write an ibc and highlights if checking was successful
1786− ok <- noErrors
1787− when ok $
1788− do idrisCatch (do writeIBC f ibc; clearIBC)
1789− (\c -> return ()) -- failure is harmless
1790− hl <- getDumpHighlighting
1791− when hl $
1792− idrisCatch (writeHighlights f)
1793− (const $ return ()) -- failure is harmless
1794− clearHighlights
1795− i <- getIState
1796− putIState (i { default_total = def_total,
1797− hide_list = emptyContext })
1798− return ()
1714+ prep = map T.pack . reverse . Spl.splitOn [pathSeparator]
1715+ aliasNames = [ (alias, fc)
1716+ | ImportInfo { import_rename = Just (alias, fc)
1717+ } <- imports
1718+ ]
1719+ histogram = groupBy ((==) `on` fst) . sortBy (comparing fst) $ aliasNames
1720+ case map head . filter ((/= 1) . length) $ histogram of
1721+ [] -> logParser 3 $ "Module aliases: " ++ show (M.toList modAliases)
1722+ (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1723+
1724+ i <- getIState
1725+ putIState (i { default_access = Private, module_aliases = modAliases })
1726+ clearIBC -- start a new .ibc file
1727+ mapM_ addIBC (map (\ (f, h) -> IBCImportHash f h)
1728+ (mapMaybe id newHashes))
1729+ -- record package info in .ibc
1730+ imps <- allImportDirs
1731+ mapM_ addIBC (map IBCImportDir imps)
1732+ mapM_ (addIBC . IBCImport)
1733+ [ (reexport, realName)
1734+ | ImportInfo { import_reexport = reexport
1735+ , import_path = realName
1736+ } <- imports
1737+ ]
1738+ let syntax = defaultSyntax{ syn_namespace = reverse mname,
1739+ maxline = toline }
1740+ ist <- getIState
1741+ -- Save the span from parsing the module header, because
1742+ -- an empty program parse might obliterate it.
1743+ let oldSpan = idris_parsedSpan ist
1744+ ds' <- parseProg syntax f file pos
1745+
1746+ case (ds', oldSpan) of
1747+ ([], Just fc) ->
1748+ -- If no program elements were parsed, we dind't
1749+ -- get a loaded region in the IBC file. That
1750+ -- means we need to add it back.
1751+ do ist <- getIState
1752+ putIState ist { idris_parsedSpan = oldSpan
1753+ , ibc_write = IBCParsedRegion fc :
1754+ ibc_write ist
1755+ }
1756+ _ -> return ()
1757+ sendParserHighlighting
1758+
1759+ -- Parsing done, now process declarations
1760+
1761+ let ds = namespaces mname ds'
1762+ logParser 3 (show $ showDecls verbosePPOption ds)
1763+ i <- getIState
1764+ logLvl 10 (show (toAlist (idris_implicits i)))
1765+ logLvl 3 (show (idris_infixes i))
1766+ -- Now add all the declarations to the context
1767+ iReport 1 $ "Type checking " ++ f
1768+ -- we totality check after every Mutual block, so if
1769+ -- anything is a single definition, wrap it in a
1770+ -- mutual block on its own
1771+ elabDecls (toplevelWith f) (map toMutual ds)
1772+ i <- getIState
1773+ -- simplify every definition do give the totality checker
1774+ -- a better chance
1775+ mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1776+ ctxt' <-
1777+ do ctxt <- getContext
1778+ tclift $ simplifyCasedef n [] [] (getErasureInfo i) ctxt
1779+ setContext ctxt')
1780+ (map snd (idris_totcheck i))
1781+ -- build size change graph from simplified definitions
1782+ iReport 3 $ "Totality checking " ++ f
1783+ logLvl 1 $ "Totality checking " ++ f
1784+ i <- getIState
1785+ mapM_ buildSCG (idris_totcheck i)
1786+ mapM_ checkDeclTotality (idris_totcheck i)
1787+ mapM_ verifyTotality (idris_totcheck i)
1788+
1789+ -- Redo totality check for deferred names
1790+ let deftots = idris_defertotcheck i
1791+ logLvl 2 $ "Totality checking " ++ show deftots
1792+ mapM_ (\x -> do tot <- getTotality x
1793+ case tot of
1794+ Total _ ->
1795+ do let opts = case lookupCtxtExact x (idris_flags i) of
1796+ Just os -> os
1797+ Nothing -> []
1798+ when (AssertTotal `notElem` opts) $
1799+ setTotality x Unchecked
1800+ _ -> return ()) (map snd deftots)
1801+ mapM_ buildSCG deftots
1802+ mapM_ checkDeclTotality deftots
1803+
1804+ logLvl 1 ("Finished " ++ f)
1805+ ibcsd <- valIBCSubDir i
1806+ logLvl 1 $ "Universe checking " ++ f
1807+ iReport 3 $ "Universe checking " ++ f
1808+ iucheck
1809+ i <- getIState
1810+ addHides (hide_list i)
1811+
1812+ -- Save module documentation if applicable
1813+ i <- getIState
1814+ case mdocs of
1815+ Nothing -> return ()
1816+ Just docs -> addModDoc syntax mname docs
1817+
1818+
1819+ -- Finally, write an ibc and highlights if checking was successful
1820+ ok <- noErrors
1821+ when ok $
1822+ do idrisCatch (do writeIBC f ibc; clearIBC)
1823+ (\c -> return ()) -- failure is harmless
1824+ hl <- getDumpHighlighting
1825+ when hl $
1826+ idrisCatch (writeHighlights f)
1827+ (const $ return ()) -- failure is harmless
1828+ clearHighlights
1829+ i <- getIState
1830+ putIState (i { default_total = def_total,
1831+ hide_list = emptyContext })
1832+ return ()
17991833 where
18001834 namespaces :: [String] -> [PDecl] -> [PDecl]
18011835 namespaces [] ds = ds