{-# LANGUAGE CPP, TemplateHaskell #-}
{-# OPTIONS_HADDOCK not-home #-}
module Polysemy.Internal.TH.Effect
( makeSem
, makeSem_
) where
import Control.Monad
import Language.Haskell.TH
#if __GLASGOW_HASKELL__ >= 902
import Language.Haskell.TH.Syntax (addModFinalizer)
#endif
import Language.Haskell.TH.Datatype
import Polysemy.Internal.TH.Common
makeSem :: Name -> Q [Dec]
makeSem :: Name -> Q [Dec]
makeSem = Bool -> Name -> Q [Dec]
genFreer Bool
True
makeSem_ :: Name -> Q [Dec]
makeSem_ :: Name -> Q [Dec]
makeSem_ = Bool -> Name -> Q [Dec]
genFreer Bool
False
genFreer :: Bool -> Name -> Q [Dec]
genFreer :: Bool -> Name -> Q [Dec]
genFreer Bool
should_mk_sigs Name
type_name = do
[Extension] -> Q ()
checkExtensions [Extension
ScopedTypeVariables, Extension
FlexibleContexts, Extension
DataKinds]
[ConLiftInfo]
cl_infos <- Name -> Q [ConLiftInfo]
getEffectMetadata Name
type_name
[[Dec]]
decs <- forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Bool -> ConLiftInfo -> Q [Dec]
genDec Bool
should_mk_sigs) [ConLiftInfo]
cl_infos
let sigs :: [[Dec]]
sigs = if Bool
should_mk_sigs then ConLiftInfo -> [Dec]
genSig forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ConLiftInfo]
cl_infos else []
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ [[Dec]]
sigs forall a. [a] -> [a] -> [a]
++ [[Dec]]
decs
genSig :: ConLiftInfo -> [Dec]
genSig :: ConLiftInfo -> [Dec]
genSig ConLiftInfo
cli
= forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip Fixity -> Name -> Dec
InfixD (ConLiftInfo -> Name
cliFunName ConLiftInfo
cli)) (ConLiftInfo -> Maybe Fixity
cliFunFixity ConLiftInfo
cli)
forall a. [a] -> [a] -> [a]
++ [ Name -> Type -> Dec
SigD (ConLiftInfo -> Name
cliFunName ConLiftInfo
cli) forall a b. (a -> b) -> a -> b
$ Type -> Type
quantifyType
forall a b. (a -> b) -> a -> b
$ [TyVarBndr Specificity] -> Cxt -> Type -> Type
ForallT [] (Type
member_cxt forall a. a -> [a] -> [a]
: ConLiftInfo -> Cxt
cliFunCxt ConLiftInfo
cli)
forall a b. (a -> b) -> a -> b
$ Type -> Cxt -> Type
foldArrowTs Type
sem
forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd
forall a b. (a -> b) -> a -> b
$ ConLiftInfo -> [(Name, Type)]
cliFunArgs ConLiftInfo
cli
]
where
member_cxt :: Type
member_cxt = Name -> ConLiftInfo -> Type
makeMemberConstraint (ConLiftInfo -> Name
cliUnionName ConLiftInfo
cli) ConLiftInfo
cli
sem :: Type
sem = Name -> Type -> Type
makeSemType (ConLiftInfo -> Name
cliUnionName ConLiftInfo
cli) (ConLiftInfo -> Type
cliEffRes ConLiftInfo
cli)
genDec :: Bool -> ConLiftInfo -> Q [Dec]
genDec :: Bool -> ConLiftInfo -> Q [Dec]
genDec Bool
should_mk_sigs ConLiftInfo
cli = do
let fun_args_names :: [Name]
fun_args_names = forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ConLiftInfo -> [(Name, Type)]
cliFunArgs ConLiftInfo
cli
#if __GLASGOW_HASKELL__ >= 902
Maybe String
doc <- DocLoc -> Q (Maybe String)
getDoc forall a b. (a -> b) -> a -> b
$ Name -> DocLoc
DeclDoc forall a b. (a -> b) -> a -> b
$ ConLiftInfo -> Name
cliConName ConLiftInfo
cli
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (Q () -> Q ()
addModFinalizer forall b c a. (b -> c) -> (a -> b) -> a -> c
. DocLoc -> String -> Q ()
putDoc (Name -> DocLoc
DeclDoc forall a b. (a -> b) -> a -> b
$ ConLiftInfo -> Name
cliFunName ConLiftInfo
cli)) Maybe String
doc
#endif
forall (f :: * -> *) a. Applicative f => a -> f a
pure
[ Pragma -> Dec
PragmaD forall a b. (a -> b) -> a -> b
$ Name -> Inline -> RuleMatch -> Phases -> Pragma
InlineP (ConLiftInfo -> Name
cliFunName ConLiftInfo
cli) Inline
Inlinable RuleMatch
ConLike Phases
AllPhases
, Name -> [Clause] -> Dec
FunD (ConLiftInfo -> Name
cliFunName ConLiftInfo
cli)
[ [Pat] -> Body -> [Dec] -> Clause
Clause (Name -> Pat
VarP forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Name]
fun_args_names)
(Exp -> Body
NormalB forall a b. (a -> b) -> a -> b
$ Bool -> ConLiftInfo -> Exp
makeUnambiguousSend Bool
should_mk_sigs ConLiftInfo
cli)
[]
]
]