module Data.API.Tools.Combinators
( Tool
, APITool
, APINodeTool
, runTool
, simpleTool
, mkTool
, contramapTool
, readTool
, subTools
, apiNodeTool
, apiDataTypeTool
, apiSpecTool
, ToolSettings
, warnOnOmittedInstance
, newtypeSmartConstructors
, defaultToolSettings
) where
import Data.API.Types
import Control.Applicative
import Data.Monoid
import Language.Haskell.TH
import Prelude
data ToolSettings = ToolSettings
{ warnOnOmittedInstance :: Bool
, newtypeSmartConstructors :: Bool
}
defaultToolSettings :: ToolSettings
defaultToolSettings = ToolSettings
{ warnOnOmittedInstance = False
, newtypeSmartConstructors = False
}
newtype Tool a = Tool
{ runTool :: ToolSettings -> a -> Q [Dec]
}
type APITool = Tool API
type APINodeTool = Tool APINode
instance Monoid (Tool a) where
mempty = Tool $ \ _ _ -> return []
Tool t1 `mappend` Tool t2 = Tool $ \ ts x -> (++) <$> t1 ts x <*> t2 ts x
simpleTool :: (a -> Q [Dec]) -> Tool a
simpleTool f = Tool $ const f
mkTool :: (ToolSettings -> a -> Q [Dec]) -> Tool a
mkTool = Tool
contramapTool :: (a -> b) -> Tool b -> Tool a
contramapTool f t = Tool $ \ ts a -> runTool t ts (f a)
readTool :: (a -> Tool a) -> Tool a
readTool t = mkTool $ \ ts x -> runTool (t x) ts x
subTools :: Tool a -> Tool [a]
subTools t = Tool $ \ ts as -> concat <$> mapM (runTool t ts) as
apiNodeTool :: Tool APINode -> Tool API
apiNodeTool = contramapTool (\ api -> [an | ThNode an <- api ]) . subTools
apiDataTypeTool :: Tool APINode -> Tool API
apiDataTypeTool = contramapTool (\ api -> [an | ThNode an <- api, hasDataType $ anSpec an ]) . subTools
where
hasDataType (SpSynonym _) = False
hasDataType _ = True
apiSpecTool :: Tool (APINode, SpecNewtype)
-> Tool (APINode, SpecRecord )
-> Tool (APINode, SpecUnion )
-> Tool (APINode, SpecEnum )
-> Tool (APINode, APIType )
-> Tool APINode
apiSpecTool n r u e s = Tool $ \ ts an -> case anSpec an of
SpNewtype sn -> runTool n ts (an, sn)
SpRecord sr -> runTool r ts (an, sr)
SpUnion su -> runTool u ts (an, su)
SpEnum se -> runTool e ts (an, se)
SpSynonym ss -> runTool s ts (an, ss)