{-# LANGUAGE TemplateHaskell #-}
module Generics.SOP.TH
( deriveGeneric
, deriveGenericOnly
, deriveGenericSubst
, deriveGenericOnlySubst
, deriveGenericFunctions
, deriveMetadataValue
, deriveMetadataType
) where
import Control.Monad (join, replicateM, unless)
import Data.List (foldl')
import Data.Maybe (fromMaybe)
import Data.Proxy
import Language.Haskell.TH.Datatype.TyVarBndr
import Language.Haskell.TH
import Language.Haskell.TH.Datatype as TH
import Generics.SOP.BasicFunctors
import qualified Generics.SOP.Metadata as SOP
import qualified Generics.SOP.Type.Metadata as SOP.T
import Generics.SOP.NP
import Generics.SOP.NS
import Generics.SOP.Universe
deriveGeneric :: Name -> Q [Dec]
deriveGeneric :: Name -> Q [Dec]
deriveGeneric Name
n =
Name -> (Name -> Q Type) -> Q [Dec]
deriveGenericSubst Name
n Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT
deriveGenericOnly :: Name -> Q [Dec]
deriveGenericOnly :: Name -> Q [Dec]
deriveGenericOnly Name
n =
Name -> (Name -> Q Type) -> Q [Dec]
deriveGenericOnlySubst Name
n Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT
deriveGenericSubst :: Name -> (Name -> Q Type) -> Q [Dec]
deriveGenericSubst :: Name -> (Name -> Q Type) -> Q [Dec]
deriveGenericSubst Name
n Name -> Q Type
f = do
DatatypeInfo
dec <- Name -> Q DatatypeInfo
reifyDatatype Name
n
[Dec]
ds1 <- DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a.
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q a)
-> Q a
withDataDec DatatypeInfo
dec ((Name -> Q Type)
-> DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec]
deriveGenericForDataDec Name -> Q Type
f)
[Dec]
ds2 <- DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a.
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q a)
-> Q a
withDataDec DatatypeInfo
dec ((Name -> Q Type)
-> DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec]
deriveMetadataForDataDec Name -> Q Type
f)
[Dec] -> Q [Dec]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Dec]
ds1 [Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
++ [Dec]
ds2)
deriveGenericOnlySubst :: Name -> (Name -> Q Type) -> Q [Dec]
deriveGenericOnlySubst :: Name -> (Name -> Q Type) -> Q [Dec]
deriveGenericOnlySubst Name
n Name -> Q Type
f = do
DatatypeInfo
dec <- Name -> Q DatatypeInfo
reifyDatatype Name
n
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a.
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q a)
-> Q a
withDataDec DatatypeInfo
dec ((Name -> Q Type)
-> DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec]
deriveGenericForDataDec Name -> Q Type
f)
deriveGenericFunctions :: Name -> String -> String -> String -> Q [Dec]
deriveGenericFunctions :: Name -> String -> String -> String -> Q [Dec]
deriveGenericFunctions Name
n String
codeName String
fromName String
toName = do
let codeName' :: Name
codeName' = String -> Name
mkName String
codeName
let fromName' :: Name
fromName' = String -> Name
mkName String
fromName
let toName' :: Name
toName' = String -> Name
mkName String
toName
DatatypeInfo
dec <- Name -> Q DatatypeInfo
reifyDatatype Name
n
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a.
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q a)
-> Q a
withDataDec DatatypeInfo
dec ((DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec])
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a b. (a -> b) -> a -> b
$ \DatatypeVariant
_variant Cxt
_cxt Name
name [TyVarBndrUnit]
bndrs Cxt
instTys [ConstructorInfo]
cons -> do
let codeType :: Q Type
codeType = (Name -> Q Type) -> [ConstructorInfo] -> Q Type
codeFor Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT [ConstructorInfo]
cons
let origType :: Q Type
origType = (Name -> Q Type) -> Name -> Cxt -> Q Type
appTysSubst Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT Name
name Cxt
instTys
let repType :: Q Type
repType = [t| SOP I $(appTyVars varT codeName' bndrs) |]
[Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence
[ Name -> [TyVarBndrUnit] -> Q Type -> Q Dec
forall (m :: * -> *).
Quote m =>
Name -> [TyVarBndrUnit] -> m Type -> m Dec
tySynD Name
codeName' [TyVarBndrUnit]
bndrs Q Type
codeType
, Name -> Q Type -> Q Dec
forall (m :: * -> *). Quote m => Name -> m Type -> m Dec
sigD Name
fromName' [t| $origType -> $repType |]
, Name -> [ConstructorInfo] -> Q Dec
embedding Name
fromName' [ConstructorInfo]
cons
, Name -> Q Type -> Q Dec
forall (m :: * -> *). Quote m => Name -> m Type -> m Dec
sigD Name
toName' [t| $repType -> $origType |]
, Name -> [ConstructorInfo] -> Q Dec
projection Name
toName' [ConstructorInfo]
cons
]
deriveMetadataValue :: Name -> String -> String -> Q [Dec]
deriveMetadataValue :: Name -> String -> String -> Q [Dec]
deriveMetadataValue Name
n String
codeName String
datatypeInfoName = do
let codeName' :: Name
codeName' = String -> Name
mkName String
codeName
let datatypeInfoName' :: Name
datatypeInfoName' = String -> Name
mkName String
datatypeInfoName
DatatypeInfo
dec <- Name -> Q DatatypeInfo
reifyDatatype Name
n
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a.
DatatypeInfo
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q a)
-> Q a
withDataDec DatatypeInfo
dec ((DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec])
-> (DatatypeVariant
-> Cxt
-> Name
-> [TyVarBndrUnit]
-> Cxt
-> [ConstructorInfo]
-> Q [Dec])
-> Q [Dec]
forall a b. (a -> b) -> a -> b
$ \DatatypeVariant
variant Cxt
_cxt Name
name [TyVarBndrUnit]
bndrs Cxt
_instTys [ConstructorInfo]
cons -> do
[Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [ Name -> Q Type -> Q Dec
forall (m :: * -> *). Quote m => Name -> m Type -> m Dec
sigD Name
datatypeInfoName' [t| SOP.DatatypeInfo $(appTyVars varT codeName' bndrs) |]
, Name -> [Q Clause] -> Q Dec
forall (m :: * -> *). Quote m => Name -> [m Clause] -> m Dec
funD Name
datatypeInfoName' [[Q Pat] -> Q Body -> [Q Dec] -> Q Clause
forall (m :: * -> *).
Quote m =>
[m Pat] -> m Body -> [m Dec] -> m Clause
clause [] (Q Exp -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB (Q Exp -> Q Body) -> Q Exp -> Q Body
forall a b. (a -> b) -> a -> b
$ DatatypeVariant -> Name -> [ConstructorInfo] -> Q Exp
metadata' DatatypeVariant
variant Name
name [ConstructorInfo]
cons) []]
]
{-# DEPRECATED deriveMetadataValue "Use 'deriveMetadataType' and 'demoteDatatypeInfo' instead." #-}
deriveMetadataType :: Name -> String -> Q [Dec]
deriveMetadataType :: Name -> String -> Q [Dec]
deriveMetadataType Name
n String
datatypeInfoName = do
let <