she-0.5: src/Imports.lhs
> module Imports where
> import Control.Applicative
> import System.IO.Error
> import System.FilePath
> import Data.Foldable hiding (elem)
> import Data.Monoid
> import Data.Maybe
> import HaLay
> import Parsley
> import ShesHers
> tryReadFile :: FilePath -> IO String
> tryReadFile s = catch (readFile s) $ \ e ->
> if isDoesNotExistError e then return "" else ioError e
> pImport :: P Tok [String]
> pImport = teq (KW "import") *> spc *> pSep (teq (Sym ".")) uid <* pRest
> grokImports :: [Tok] -> [[FilePath]]
> grokImports cs = foldMap pure $ parse pImport cs
> getHers :: [String] -> IO [[Tok]]
> getHers p = ready f <$> tryReadFile f where f = joinPath p <.> "hers"
> storySoFar :: [[Tok]] -> IO [[Tok]]
> storySoFar hs = (shesHers ++) <$>
> (oneOfEach [] <$> foldMap getHers (hs >>= grokImports))
> pModule :: P Tok String
> pModule = (teq (KW "module") *> spc *> uid) <* pRest
> oneOfEach :: [String] -> [[Tok]] -> [[Tok]]
> oneOfEach xs [] = []
> oneOfEach xs (ts : tss) = case parse pModule ts of
> Just x | elem x xs -> oneOfEach xs tss
> | otherwise -> ts : oneOfEach (x : xs) tss
> Nothing -> ts : oneOfEach xs tss
> pModuleGuts :: P Tok [[Tok]]
> pModuleGuts = teq (KW "module") *> spc *> uid *> spc *> pLay "where" pRest
> getGuts :: [[Tok]] -> [[Tok]]
> getGuts = foldMap (fromMaybe [] . parse pModuleGuts)
> instance Monoid x => Monoid (IO x) where
> mempty = pure mempty
> mappend x y = mappend <$> x <*> y