packages feed

kempe-0.1.1.0: src/Kempe/Module.hs

-- | Pretty easy since doesn't need renaming.
--
-- Just thread lexer state through, remove duplicates.
module Kempe.Module ( parseProcess
                    ) where

import           Control.Exception          (Exception, throwIO)
import qualified Data.ByteString.Lazy       as BSL
import qualified Data.ByteString.Lazy.Char8 as ASCII
import qualified Data.Set                   as S
import           Data.Tuple.Extra           (fst3, third3)
import           Kempe.AST
import           Kempe.Lexer
import           Kempe.Parser


parseProcess :: FilePath -> IO (Int, Declarations AlexPosn AlexPosn AlexPosn)
parseProcess fp = do
    (st, [], ds) <- loopFps [fp] alexInitUserState
    pure (fst3 st, {-# SCC "dedup" #-} dedup ds)

yeetIO :: Exception e => Either e a -> IO a
yeetIO = either throwIO pure

loopFps :: [FilePath] -> AlexUserState -> IO (AlexUserState, [FilePath], Declarations AlexPosn AlexPosn AlexPosn)
loopFps [] st = pure (st, [], [])
loopFps (fp:fps) st = do
    (st', Module is ds) <- parseStep fp st
    third3 (++ ds) <$> loopFps (fmap ASCII.unpack (reverse is) ++ fps) st'

parseStep :: FilePath -> AlexUserState -> IO (AlexUserState, Module AlexPosn AlexPosn AlexPosn)
parseStep fp st = do
    contents <- BSL.readFile fp
    yeetIO $ parseWithCtx contents st

dedup :: Ord a => [a] -> [a]
dedup = loop S.empty
    where loop _ [] = []
          loop acc (x:xs) =
            if S.member x acc
                then loop acc xs
                else x : loop (S.insert x acc) xs