{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_HADDOCK not-home #-}
module Polysemy.Internal.TH.Effect
  ( makeSem
  , makeSem_
  ) where
import Control.Monad
import Language.Haskell.TH
import Language.Haskell.TH.Datatype
import Polysemy.Internal.CustomErrors (DefiningModule)
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]
  (Name
dt_name, [ConLiftInfo]
cl_infos) <- Name -> Q (Name, [ConLiftInfo])
getEffectMetadata Name
type_name
  Bool
tyfams_on  <- Extension -> Q Bool
isExtEnabled Extension
TypeFamilies
  [Dec]
def_mod_fi <- [Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [ Name -> Maybe [Q TyVarBndrUnit] -> [TypeQ] -> TypeQ -> Q Dec
tySynInstDCompat
                             ''DefiningModule
                             Maybe [Q TyVarBndrUnit]
forall a. Maybe a
Nothing
                             [Type -> TypeQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Type -> TypeQ) -> Type -> TypeQ
forall a b. (a -> b) -> a -> b
$ Name -> Type
ConT Name
dt_name]
                             (TyLit -> Type
LitT (TyLit -> Type) -> (Loc -> TyLit) -> Loc -> Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> TyLit
StrTyLit (String -> TyLit) -> (Loc -> String) -> Loc -> TyLit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Loc -> String
loc_module (Loc -> Type) -> Q Loc -> TypeQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Q Loc
location)
                         | Bool
tyfams_on
                         ]
  [[Dec]]
decs <- (ConLiftInfo -> Q [Dec]) -> [ConLiftInfo] -> Q [[Dec]]
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 (ConLiftInfo -> [Dec]) -> [ConLiftInfo] -> [[Dec]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ConLiftInfo]
cl_infos else []
  [Dec] -> Q [Dec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Dec] -> Q [Dec]) -> [Dec] -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ [[Dec]] -> [Dec]
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join ([[Dec]] -> [Dec]) -> [[Dec]] -> [Dec]
forall a b. (a -> b) -> a -> b
$ [Dec]
def_mod_fi [Dec] -> [[Dec]] -> [[Dec]]
forall a. a -> [a] -> [a]
: [[Dec]]
sigs [[Dec]] -> [[Dec]] -> [[Dec]]
forall a. [a] -> [a] -> [a]
++ [[Dec]]
decs
genSig :: ConLiftInfo -> [Dec]
genSig :: ConLiftInfo -> [Dec]
genSig ConLiftInfo
cli
  =  [Dec] -> (Fixity -> [Dec]) -> Maybe Fixity -> [Dec]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Dec -> [Dec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Dec -> [Dec]) -> (Fixity -> Dec) -> Fixity -> [Dec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Fixity -> Name -> Dec) -> Name -> Fixity -> Dec
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)
  [Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
++ [ Name -> Type -> Dec
SigD (ConLiftInfo -> Name
cliFunName ConLiftInfo
cli) (Type -> Dec) -> Type -> Dec
forall a b. (a -> b) -> a -> b
$ Type -> Type
quantifyType
       (Type -> Type) -> Type -> Type
forall a b. (a -> b) -> a -> b
$ [TyVarBndrUnit] -> Cxt -> Type -> Type
ForallT [] (Type
member_cxt Type -> Cxt -> Cxt
forall a. a -> [a] -> [a]
: ConLiftInfo -> Cxt
cliFunCxt ConLiftInfo
cli)
       (Type -> Type) -> Type -> Type
forall a b. (a -> b) -> a -> b
$ Type -> Cxt -> Type
foldArrowTs Type
sem
       (Cxt -> Type) -> Cxt -> Type
forall a b. (a -> b) -> a -> b
$ ((Name, Type) -> Type) -> [(Name, Type)] -> Cxt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Name, Type) -> Type
forall a b. (a, b) -> b
snd
       ([(Name, Type)] -> Cxt) -> [(Name, Type)] -> Cxt
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 = (Name, Type) -> Name
forall a b. (a, b) -> a
fst ((Name, Type) -> Name) -> [(Name, Type)] -> [Name]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ConLiftInfo -> [(Name, Type)]
cliFunArgs ConLiftInfo
cli
  [Dec] -> Q [Dec]
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    [ Pragma -> Dec
PragmaD (Pragma -> Dec) -> Pragma -> Dec
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 (Name -> Pat) -> [Name] -> [Pat]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Name]
fun_args_names)
                 (Exp -> Body
NormalB (Exp -> Body) -> Exp -> Body
forall a b. (a -> b) -> a -> b
$ Bool -> ConLiftInfo -> Exp
makeUnambiguousSend Bool
should_mk_sigs ConLiftInfo
cli)
                 []
        ]
    ]