{-# LANGUAGE TemplateHaskell #-}
module Data.API.TH
( applicativeE
, optionalInstanceD
, funSigD
, simpleD
, simpleSigD
, mkNameText
, fieldNameE
, fieldNameVarE
, typeNameE
) where
import Data.API.TH.Compat
import Data.API.Tools.Combinators
import Data.API.Types
import Control.Applicative
import Control.Monad
import qualified Data.Text as T
import Language.Haskell.TH
import Prelude
applicativeE :: ExpQ -> [ExpQ] -> ExpQ
applicativeE :: ExpQ -> [ExpQ] -> ExpQ
applicativeE ExpQ
ke [ExpQ]
es0 =
case [ExpQ]
es0 of
[] -> ExpQ
ke
ExpQ
e:[ExpQ]
es -> ExpQ -> [ExpQ] -> ExpQ
forall {m :: * -> *}. Quote m => m Exp -> [m Exp] -> m Exp
app' (ExpQ
ke ExpQ -> ExpQ -> ExpQ
forall {m :: * -> *}. Quote m => m Exp -> m Exp -> m Exp
`dl` ExpQ
e) [ExpQ]
es
where
app' :: m Exp -> [m Exp] -> m Exp
app' m Exp
e [] = m Exp
e
app' m Exp
e (m Exp
e':[m Exp]
es) = m Exp -> [m Exp] -> m Exp
app' (m Exp
e m Exp -> m Exp -> m Exp
forall {m :: * -> *}. Quote m => m Exp -> m Exp -> m Exp
`st` m Exp
e') [m Exp]
es
st :: m Exp -> m Exp -> m Exp
st m Exp
e1 m Exp
e2 = m Exp -> m Exp -> m Exp
forall {m :: * -> *}. Quote m => m Exp -> m Exp -> m Exp
appE (m Exp -> m Exp -> m Exp
forall {m :: * -> *}. Quote m => m Exp -> m Exp -> m Exp
appE (Name -> m Exp
forall (m :: * -> *). Quote m => Name -> m Exp
varE '(<*>)) m Exp
e1) m Exp
e2
dl :: m Exp -> m Exp -> m Exp
dl m Exp
e1 m Exp
e2 = m Exp -> m Exp -> m Exp
forall {m :: * -> *}. Quote m => m Exp -> m Exp -> m Exp
appE (m Exp -> m Exp -> m Exp
forall {m :: * -> *}. Quote m => m Exp -> m Exp -> m Exp
appE (Name -> m Exp
forall (m :: * -> *). Quote m => Name -> m Exp
varE '(<$>)) m Exp
e1) m Exp
e2
optionalInstanceD :: ToolSettings -> Name -> [TypeQ] -> [DecQ] -> Q [Dec]
optionalInstanceD :: ToolSettings -> Name -> [TypeQ] -> [DecQ] -> Q [Dec]
optionalInstanceD ToolSettings
stgs Name
c [TypeQ]
tqs [DecQ]
dqs = do
[Type]
ts <- [TypeQ] -> Q [Type]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence [TypeQ]
tqs
[Dec]
ds <- [DecQ] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence [DecQ]
dqs
Bool
exists <- Name -> [Type] -> Q Bool
isInstance Name
c [Type]
ts
if Bool
exists then do Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ToolSettings -> Bool
warnOnOmittedInstance ToolSettings
stgs) (Q () -> Q ()) -> Q () -> Q ()
forall a b. (a -> b) -> a -> b
$ String -> Q ()
reportWarning (String -> Q ()) -> String -> Q ()
forall a b. (a -> b) -> a -> b
$ [Type] -> String
forall {a}. Ppr a => a -> String
msg [Type]
ts
[Dec] -> Q [Dec]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return []
else [Dec] -> Q [Dec]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return [[Type] -> Type -> [Dec] -> Dec
mkInstanceD [] ((Type -> Type -> Type) -> Type -> [Type] -> Type
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Type -> Type -> Type
AppT (Name -> Type
ConT Name
c) [Type]
ts) [Dec]
ds]
where
msg :: a -> String
msg a
ts = String
"instance " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Name -> String
forall {a}. Ppr a => a -> String
pprint Name
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall {a}. Ppr a => a -> String
pprint a
ts String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" already exists, so it was not generated"
funSigD :: Name -> TypeQ -> [ClauseQ] -> Q [Dec]
funSigD :: Name -> TypeQ -> [ClauseQ] -> Q [Dec]
funSigD Name
n TypeQ
t [ClauseQ]
cs = (\ Dec
x Dec
y -> [Dec
x,Dec
y]) (Dec -> Dec -> [Dec]) -> DecQ -> Q (Dec -> [Dec])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Name -> TypeQ -> DecQ
forall (m :: * -> *). Quote m => Name -> m Type -> m Dec
sigD Name
n TypeQ
t Q (Dec -> [Dec]) -> DecQ -> Q [Dec]
forall a b. Q (a -> b) -> Q a -> Q b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Name -> [ClauseQ] -> DecQ
forall (m :: * -> *). Quote m => Name -> [m Clause] -> m Dec
funD Name
n [ClauseQ]
cs
simpleD :: Name -> ExpQ -> Q Dec
simpleD :: Name -> ExpQ -> DecQ
simpleD Name
n ExpQ
e = Name -> [ClauseQ] -> DecQ
forall (m :: * -> *). Quote m => Name -> [m Clause] -> m Dec
funD Name
n [[Q Pat] -> Q Body -> [DecQ] -> ClauseQ
forall (m :: * -> *).
Quote m =>
[m Pat] -> m Body -> [m Dec] -> m Clause
clause [] (ExpQ -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB ExpQ
e) []]
simpleSigD :: Name -> TypeQ -> ExpQ -> Q [Dec]
simpleSigD :: Name -> TypeQ -> ExpQ -> Q [Dec]
simpleSigD Name
n TypeQ
t ExpQ
e = Name -> TypeQ -> [ClauseQ] -> Q [Dec]
funSigD Name
n TypeQ
t [[Q Pat] -> Q Body -> [DecQ] -> ClauseQ
forall (m :: * -> *).
Quote m =>
[m Pat] -> m Body -> [m Dec] -> m Clause
clause [] (ExpQ -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB ExpQ
e) []]
mkNameText :: T.Text -> Name
mkNameText :: Text -> Name
mkNameText = String -> Name
mkName (String -> Name) -> (Text -> String) -> Text -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack
fieldNameE :: FieldName -> ExpQ
fieldNameE :: FieldName -> ExpQ
fieldNameE = String -> ExpQ
forall (m :: * -> *). Quote m => String -> m Exp
stringE (String -> ExpQ) -> (FieldName -> String) -> FieldName -> ExpQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> String) -> (FieldName -> Text) -> FieldName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldName -> Text
_FieldName
fieldNameVarE :: FieldName -> ExpQ
fieldNameVarE :: FieldName -> ExpQ
fieldNameVarE = Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE (Name -> ExpQ) -> (FieldName -> Name) -> FieldName -> ExpQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Name
mkNameText (Text -> Name) -> (FieldName -> Text) -> FieldName -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldName -> Text
_FieldName
typeNameE :: TypeName -> ExpQ
typeNameE :: TypeName -> ExpQ
typeNameE = String -> ExpQ
forall (m :: * -> *). Quote m => String -> m Exp
stringE (String -> ExpQ) -> (TypeName -> String) -> TypeName -> ExpQ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> String) -> (TypeName -> Text) -> TypeName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeName -> Text
_TypeName