gpah-0.0.1: src/Generics/GPAH/Derive/Analyze.hs
{-# LANGUAGE FlexibleContexts #-}
module Generics.GPAH.Derive.Analyze where
import Generics.GPAH.Derive.Base
import qualified Generics.GPAH.Hackage.Base as Hackage
import qualified Data.Map as M
import Data.Monoid
import Language.Haskell.Exts
import Language.Haskell.Exts.Comments
import Text.ParserCombinators.UU
import Text.ParserCombinators.UU.BasicInstances
import Text.ParserCombinators.UU.Utils
import Generics.SYB
analyzeModule :: ParseResult (Module, [Comment]) -> Hackage.Analysis -> Analysis
analyzeModule (ParseOk (m, c)) hacPkg = Analysis
(runDeriveTH m hacPkg)
(runDerivePP c)
(runDriftPP c)
(runDriftGL c)
analyzeModule _ _ = mempty
runDeriveTH :: Module -> Hackage.Analysis -> M.Map String Int
runDeriveTH m hacPkg | "derive" `elem` (M.keys (Hackage.reverseDeps hacPkg)) = everything (M.unionWith (+)) (mempty `mkQ` thDecl) m
where
thDecl :: Splice -> M.Map String Int
thDecl (ParenSplice (App (App (Var (UnQual (Ident "derive"))) (Var (UnQual (Ident class_)))) (TypQuote (UnQual (Ident dt))))) = M.singleton class_ 1
thDecl (ParenSplice (App (App (Var (UnQual (Ident "derive"))) (Var (UnQual (Ident class_)))) (List dts))) = M.singleton class_ (length dts)
thDecl (ParenSplice (App (App (Var (UnQual (Ident "derive"))) (List classes_ids)) (TypQuote (UnQual (Ident dt))))) = let classes = map (\ (Var (UnQual (Ident class_))) -> class_) classes_ids
in
M.fromList (zip classes (repeat 1))
thDecl (ParenSplice (App (App (Var (UnQual (Ident "derive"))) (List classes_ids)) (List dts))) = let classes = map (\ (Var (UnQual (Ident class_))) -> class_) classes_ids
in
M.fromList (zip classes (repeat (length dts)))
thDecl _ = mempty
runDeriveTH _ _ = mempty
runDerivePP :: [Comment] -> M.Map String Int
runDerivePP cs = foldl (\ m r -> M.insertWith (+) r 1 m) mempty $ concatMap (\ (Comment ml _ s) -> case (ml, execParser pDerivePP s) of
(True, (res, [])) -> res
_ -> [] -- error in parsing or single-line
) cs
runDriftPP :: [Comment] -> M.Map String Int
runDriftPP cs = foldl (\ m r -> M.insertWith (+) r 1 m) mempty $ concatMap (\ (Comment _ _ s) -> case execParser pDriftPP s of
(res, []) -> res
_ -> [] -- error in parsing
) cs
runDriftGL :: [Comment] -> M.Map String Int
runDriftGL cs =foldl (\ m r -> M.insertWith (+) r 1 m) mempty $ concatMap (\ (Comment _ _ s) -> case execParser pDriftGL s of
(res, []) -> res
_ -> [] -- error in parsing
) cs
pDerivePP :: Parser [String]
pDerivePP = deriveStandalone <|> deriveInline
where
deriveInline :: Parser [String]
deriveInline = pSym '!' *> pList1Sep (pSym ',') pcl <* pSpaces <* pSym '!'
where
pcl :: Parser String
pcl =foldl1 (<|>) (map (\ c -> pSpaces *> pToken c) deriveClasses)
deriveStandalone :: Parser [String]
deriveStandalone = pSym '!' *> pSpaces *> pToken "deriving" *> pSpaces *> pToken "instance" *> pList1Sep (pSym ',') pcl <* pSpaces <* pSym '!'
where
pcl :: Parser String
pcl =foldl1 (<|>) (map (\ c -> pSpaces *> pToken c) deriveClasses)
pDriftPP :: Parser [String]
pDriftPP = driftInline <|> driftStandalone
where
driftInline :: Parser [String]
driftInline = pSym '!' *> pSpaces *> pToken "derive:" *> pList1Sep (pSym ',') pcl <* pSpaces <* pSym '!'
where
pcl :: Parser String
pcl =foldl1 (<|>) (map (\ c -> pSpaces *> pToken c) driftClasses)
driftStandalone :: Parser [String]
driftStandalone = pSym '!' *> pSpaces *> pToken "for" *> pSpaces *> pMunch (`notElem` " \n\r") *> pSpaces *> pToken "derive:" *> pList1Sep (pSym ',') pcl <* pSpaces <* pSym '!'
where
pcl :: Parser String
pcl =foldl1 (<|>) (map (\ c -> pSpaces *> pToken c) driftClasses)
pDriftGL :: Parser [String]
pDriftGL = driftGlobal
where
driftGlobal :: Parser [String]
driftGlobal = pSym '!' *> pSpaces *> pToken "global:" *> pList1Sep (pSym ',') pcl <* pSpaces <* pSym '!'
where
pcl :: Parser String
pcl =foldl1 (<|>) (map (\ c -> pSpaces *> pToken c) driftClasses)