{-# LANGUAGE TemplateHaskell, CPP, NamedFieldPuns #-}
module Data.Acid.TemplateHaskell where
import Language.Haskell.TH
import Language.Haskell.TH.Ppr
import Language.Haskell.TH.ExpandSyns
import Data.Acid.Core
import Data.Acid.Common
import Data.List ((\\), nub, delete)
import Data.SafeCopy
import Data.Typeable
import Data.Char
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import Control.Monad
import Control.Monad.State (MonadState)
import Control.Monad.Reader (MonadReader)
#if !MIN_VERSION_template_haskell(2,17,0)
type TyVarBndrUnit = TyVarBndr
#endif
makeAcidic :: Name -> [Name] -> Q [Dec]
makeAcidic :: Name -> [Name] -> Q [Dec]
makeAcidic = SerialiserSpec -> Name -> [Name] -> Q [Dec]
makeAcidicWithSerialiser SerialiserSpec
safeCopySerialiserSpec
data SerialiserSpec =
SerialiserSpec
{ SerialiserSpec -> Name
serialisationClassName :: Name
, SerialiserSpec -> Name
methodSerialiserName :: Name
, SerialiserSpec -> Name -> Type -> DecQ
makeEventSerialiser :: Name -> Type -> DecQ
}
safeCopySerialiserSpec :: SerialiserSpec
safeCopySerialiserSpec :: SerialiserSpec
safeCopySerialiserSpec =
SerialiserSpec { serialisationClassName :: Name
serialisationClassName = ''SafeCopy
, methodSerialiserName :: Name
methodSerialiserName = 'safeCopyMethodSerialiser
, makeEventSerialiser :: Name -> Type -> DecQ
makeEventSerialiser = Name -> Type -> DecQ
makeSafeCopyInstance
}
makeAcidicWithSerialiser :: SerialiserSpec -> Name -> [Name] -> Q [Dec]
makeAcidicWithSerialiser :: SerialiserSpec -> Name -> [Name] -> Q [Dec]
makeAcidicWithSerialiser SerialiserSpec
ss Name
stateName [Name]
eventNames
= do Info
stateInfo <- Name -> Q Info
reify Name
stateName
case Info
stateInfo of
TyConI Dec
tycon
->case Dec
tycon of
#if MIN_VERSION_template_haskell(2,11,0)
DataD Cxt
_cxt Name
_name [TyVarBndr ()]
tyvars Maybe Type
_kind [Con]
constructors [DerivClause]
_derivs
#else
DataD _cxt _name tyvars constructors _derivs
#endif
#if MIN_VERSION_template_haskell(2,21,0)
-> makeAcidic' ss eventNames stateName (map void tyvars) constructors
#else
-> SerialiserSpec
-> [Name] -> Name -> [TyVarBndr ()] -> [Con] -> Q [Dec]
makeAcidic' SerialiserSpec
ss [Name]
eventNames Name
stateName [TyVarBndr ()]
tyvars [Con]
constructors
#endif
#if MIN_VERSION_template_haskell(2,11,0)
NewtypeD Cxt
_cxt Name
_name [TyVarBndr ()]
tyvars Maybe Type
_kind Con
constructor [DerivClause]
_derivs
#else
NewtypeD _cxt _name tyvars constructor _derivs
#endif
#if MIN_VERSION_template_haskell(2,21,0)
-> makeAcidic' ss eventNames stateName (map void tyvars) [constructor]
#else
-> SerialiserSpec
-> [Name] -> Name -> [TyVarBndr ()] -> [Con] -> Q [Dec]
makeAcidic' SerialiserSpec
ss [Name]
eventNames Name
stateName [TyVarBndr ()]
tyvars [Con
constructor]
#endif
TySynD Name
_name [TyVarBndr ()]
tyvars Type
_ty
#if MIN_VERSION_template_haskell(2,21,0)
-> makeAcidic' ss eventNames stateName (map void tyvars) []
#else
-> SerialiserSpec
-> [Name] -> Name -> [TyVarBndr ()] -> [Con] -> Q [Dec]
makeAcidic' SerialiserSpec
ss [Name]
eventNames Name
stateName [TyVarBndr ()]
tyvars []
#endif
Dec
_ -> [Char] -> Q [Dec]
forall a. HasCallStack => [Char] -> a
error [Char]
"Data.Acid.TemplateHaskell: Unsupported state type. Only 'data', 'newtype' and 'type' are supported."
Info
_ -> [Char] -> Q [Dec]
forall a. HasCallStack => [Char] -> a
error [Char]
"Data.Acid.TemplateHaskell: Given state is not a type."
makeAcidic' :: SerialiserSpec -> [Name] -> Name -> [TyVarBndrUnit] -> [Con] -> Q [Dec]
makeAcidic' :: SerialiserSpec
-> [Name] -> Name -> [TyVarBndr ()] -> [Con] -> Q [Dec]
makeAcidic' SerialiserSpec
ss [Name]
eventNames Name
stateName [TyVarBndr ()]
tyvars [Con]
constructors
= do [[Dec]]
events <- [Q [Dec]] -> 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 [ SerialiserSpec -> Name -> Q [Dec]
makeEvent SerialiserSpec
ss Name
eventName | Name
eventName <- [Name]
eventNames ]
Dec
acidic <- SerialiserSpec -> [Name] -> Name -> [TyVarBndr ()] -> [Con] -> DecQ
forall {p}.
SerialiserSpec -> [Name] -> Name -> [TyVarBndr ()] -> p -> DecQ
makeIsAcidic SerialiserSpec
ss [Name]
eventNames Name
stateName [TyVarBndr ()]
tyvars [Con]
constructors
[Dec] -> Q [Dec]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Dec] -> Q [Dec]) -> [Dec] -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ Dec
acidic Dec -> [Dec] -> [Dec]
forall a. a -> [a] -> [a]
: [[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Dec]]
events
makeEvent :: SerialiserSpec -> Name -> Q [Dec]
makeEvent :: SerialiserSpec -> Name -> Q [Dec]
makeEvent SerialiserSpec
ss Name
eventName
= do Bool
exists <- Q Bool -> Q Bool -> Q Bool
forall a. Q a -> Q a -> Q a
recover (Bool -> Q Bool
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False) (Name -> Q Info
reify (Name -> Name
toStructName Name
eventName) Q Info -> Q Bool -> Q Bool
forall a b. Q a -> Q b -> Q b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> Q Bool
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
Type
eventType <- Name -> Q Type
getEventType Name
eventName
if Bool
exists
then do Dec
b <- SerialiserSpec -> Name -> Type -> DecQ
makeEventSerialiser SerialiserSpec
ss Name
eventName Type
eventType
[Dec] -> Q [Dec]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return [Dec
b]
else do Dec
d <- Name -> Type -> DecQ
makeEventDataType Name
eventName Type
eventType
Dec
b <- SerialiserSpec -> Name -> Type -> DecQ
makeEventSerialiser SerialiserSpec
ss Name
eventName Type
eventType
Dec
i <- Name -> Type -> DecQ
makeMethodInstance Name
eventName Type
eventType
Dec
e <- Name -> Type -> DecQ
makeEventInstance Name
eventName Type
eventType
[Dec] -> Q [Dec]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return [Dec
d,Dec
b,Dec
i,Dec
e]
getEventType :: Name -> Q Type
getEventType :: Name -> Q Type
getEventType Name
eventName
= do Info
eventInfo <- Name -> Q Info
reify Name
eventName
case Info
eventInfo of
#if MIN_VERSION_template_haskell(2,11,0)
VarI Name
_name Type
eventType Maybe Dec
_decl
#else
VarI _name eventType _decl _fixity
#endif
-> Type -> Q Type
expandSyns Type
eventType
Info
_ -> [Char] -> Q Type
forall a. HasCallStack => [Char] -> a
error ([Char] -> Q Type) -> [Char] -> Q Type
forall a b. (a -> b) -> a -> b
$ [Char]
"Data.Acid.TemplateHaskell: Events must be functions: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
eventName
makeIsAcidic :: SerialiserSpec -> [Name] -> Name -> [TyVarBndr ()] -> p -> DecQ
makeIsAcidic SerialiserSpec
ss [Name]
eventNames Name
stateName [TyVarBndr ()]
tyvars p
constructors
= do Cxt
types <- (Name -> Q Type) -> [Name] -> Q Cxt
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Name -> Q Type
getEventType [Name]
eventNames
Type
stateType' <- Q Type
stateType
let preds :: [Name]
preds = [ SerialiserSpec -> Name
serialisationClassName SerialiserSpec
ss, ''Typeable ]
ty :: Q Type
ty = Q Type -> Q Type -> Q Type
forall (m :: * -> *). Quote m => m Type -> m Type -> m Type
appT (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT ''IsAcidic) Q Type
stateType
handlers :: [ExpQ]
handlers = (Name -> Type -> ExpQ) -> [Name] -> Cxt -> [ExpQ]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (SerialiserSpec -> Name -> Type -> ExpQ
makeEventHandler SerialiserSpec
ss) [Name]
eventNames Cxt
types
cxtFromEvents :: Cxt
cxtFromEvents = Cxt -> Cxt
forall a. Eq a => [a] -> [a]
nub (Cxt -> Cxt) -> Cxt -> Cxt
forall a b. (a -> b) -> a -> b
$ [Cxt] -> Cxt
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([Cxt] -> Cxt) -> [Cxt] -> Cxt
forall a b. (a -> b) -> a -> b
$ (Name -> Type -> Cxt) -> [Name] -> Cxt -> [Cxt]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Type -> [TyVarBndr ()] -> Name -> Type -> Cxt
eventCxts Type
stateType' [TyVarBndr ()]
tyvars) [Name]
eventNames Cxt
types
Cxt
cxts' <- [Name] -> [TyVarBndr ()] -> Cxt -> Q Cxt
forall {m :: * -> *} {a}.
Quote m =>
[Name] -> [TyVarBndr a] -> Cxt -> m Cxt
mkCxtFromTyVars [Name]
preds [TyVarBndr ()]
tyvars Cxt
cxtFromEvents
Q Cxt -> Q Type -> [DecQ] -> DecQ
forall (m :: * -> *).
Quote m =>
m Cxt -> m Type -> [m Dec] -> m Dec
instanceD (Cxt -> Q Cxt
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Cxt
cxts') Q Type
ty
[ Q Pat -> Q Body -> [DecQ] -> DecQ
forall (m :: * -> *).
Quote m =>
m Pat -> m Body -> [m Dec] -> m Dec
valD (Name -> Q Pat
forall (m :: * -> *). Quote m => Name -> m Pat
varP 'acidEvents) (ExpQ -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB ([ExpQ] -> ExpQ
forall (m :: * -> *). Quote m => [m Exp] -> m Exp
listE [ExpQ]
handlers)) []
]
where stateType :: Q Type
stateType = (Q Type -> Q Type -> Q Type) -> Q Type -> [Q Type] -> Q Type
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Q Type -> Q Type -> Q Type
forall (m :: * -> *). Quote m => m Type -> m Type -> m Type
appT (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT Name
stateName) ((Name -> Q Type) -> [Name] -> [Q Type]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT ([TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars))
eventCxts :: Type
-> [TyVarBndrUnit]
-> Name
-> Type
-> [Pred]
eventCxts :: Type -> [TyVarBndr ()] -> Name -> Type -> Cxt
eventCxts Type
targetStateType [TyVarBndr ()]
targetTyVars Name
eventName Type
eventType =
let TypeAnalysis { context :: TypeAnalysis -> Cxt
context = Cxt
cxt, Type
stateType :: Type
stateType :: TypeAnalysis -> Type
stateType }
= Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
eventType
eventTyVars :: [Name]
eventTyVars = Type -> [Name]
findTyVars Type
stateType
table :: [(Name, Name)]
table = [Name] -> [Name] -> [(Name, Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
eventTyVars ((TyVarBndr () -> Name) -> [TyVarBndr ()] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map TyVarBndr () -> Name
forall a. TyVarBndr a -> Name
tyVarBndrName [TyVarBndr ()]
targetTyVars)
in (Type -> Type) -> Cxt -> Cxt
forall a b. (a -> b) -> [a] -> [b]
map ([(Name, Name)] -> Type -> Type
unify [(Name, Name)]
table)
(Type -> Type -> Cxt -> Cxt
renameState Type
stateType Type
targetStateType Cxt
cxt)
where
unify :: [(Name, Name)] -> Pred -> Pred
#if MIN_VERSION_template_haskell(2,10,0)
unify :: [(Name, Name)] -> Type -> Type
unify [(Name, Name)]
table Type
p = Type -> [(Name, Name)] -> Type -> Type
rename Type
p [(Name, Name)]
table Type
p
#else
unify table p@(ClassP n tys) = ClassP n (map (rename p table) tys)
unify table p@(EqualP a b) = EqualP (rename p table a) (rename p table b)
#endif
rename :: Pred -> [(Name, Name)] -> Type -> Type
rename :: Type -> [(Name, Name)] -> Type -> Type
rename Type
pred [(Name, Name)]
table t :: Type
t@(ForallT [TyVarBndr Specificity]
tyvarbndrs Cxt
cxt Type
typ) =
[TyVarBndr Specificity] -> Cxt -> Type -> Type
ForallT ((TyVarBndr Specificity -> TyVarBndr Specificity)
-> [TyVarBndr Specificity] -> [TyVarBndr Specificity]
forall a b. (a -> b) -> [a] -> [b]
map TyVarBndr Specificity -> TyVarBndr Specificity
forall a. TyVarBndr a -> TyVarBndr a
renameTyVar [TyVarBndr Specificity]
tyvarbndrs) ((Type -> Type) -> Cxt -> Cxt
forall a b. (a -> b) -> [a] -> [b]
map ([(Name, Name)] -> Type -> Type
unify [(Name, Name)]
table) Cxt
cxt) (Type -> [(Name, Name)] -> Type -> Type
rename Type
pred [(Name, Name)]
table Type
typ)
where
#if MIN_VERSION_template_haskell(2,17,0)
renameTyVar :: TyVarBndr a -> TyVarBndr a
renameTyVar :: forall a. TyVarBndr a -> TyVarBndr a
renameTyVar (PlainTV Name
name a
ann) = Name -> a -> TyVarBndr a
forall flag. Name -> flag -> TyVarBndr flag
PlainTV (Type -> [(Name, Name)] -> Name -> Name
renameName Type
pred [(Name, Name)]
table Name
name) a
ann
renameTyVar (KindedTV Name
name a
k Type
ann) = Name -> a -> Type -> TyVarBndr a
forall flag. Name -> flag -> Type -> TyVarBndr flag
KindedTV (Type -> [(Name, Name)] -> Name -> Name
renameName Type
pred [(Name, Name)]
table Name
name) a
k Type
ann
#else
renameTyVar :: TyVarBndr -> TyVarBndr
renameTyVar (PlainTV name) = PlainTV (renameName pred table name)
renameTyVar (KindedTV name k) = KindedTV (renameName pred table name) k
#endif
rename Type
pred [(Name, Name)]
table (VarT Name
n) = Name -> Type
VarT (Name -> Type) -> Name -> Type
forall a b. (a -> b) -> a -> b
$ Type -> [(Name, Name)] -> Name -> Name
renameName Type
pred [(Name, Name)]
table Name
n
rename Type
pred [(Name, Name)]
table (AppT Type
a Type
b) = Type -> Type -> Type
AppT (Type -> [(Name, Name)] -> Type -> Type
rename Type
pred [(Name, Name)]
table Type
a) (Type -> [(Name, Name)] -> Type -> Type
rename Type
pred [(Name, Name)]
table Type
b)
rename Type
pred [(Name, Name)]
table (SigT Type
a Type
k) = Type -> Type -> Type
SigT (Type -> [(Name, Name)] -> Type -> Type
rename Type
pred [(Name, Name)]
table Type
a) Type
k
rename Type
_ [(Name, Name)]
_ Type
typ = Type
typ
renameName :: Pred -> [(Name, Name)] -> Name -> Name
renameName :: Type -> [(Name, Name)] -> Name -> Name
renameName Type
pred [(Name, Name)]
table Name
n =
case Name -> [(Name, Name)] -> Maybe Name
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Name
n [(Name, Name)]
table of
Maybe Name
Nothing -> [Char] -> Name
forall a. HasCallStack => [Char] -> a
error ([Char] -> Name) -> [Char] -> Name
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines [ [Char]
"Data.Acid.TemplateHaskell: "
, [Char]
""
, Doc -> [Char]
forall a. Show a => a -> [Char]
show (Doc -> [Char]) -> Doc -> [Char]
forall a b. (a -> b) -> a -> b
$ Name -> Type -> Doc
ppr_sig Name
eventName Type
eventType
, [Char]
""
, [Char]
"can not be used as an UpdateEvent because the class context: "
, [Char]
""
, Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint Type
pred
, [Char]
""
, [Char]
"contains a type variable which is not found in the state type: "
, [Char]
""
, Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint Type
targetStateType
, [Char]
""
, [Char]
"You may be able to fix this by providing a type signature that fixes these type variable(s)"
]
(Just Name
n') -> Name
n'
renameState :: Type -> Type -> Cxt -> Cxt
renameState :: Type -> Type -> Cxt -> Cxt
renameState Type
tfrom Type
tto Cxt
cxt = (Type -> Type) -> Cxt -> Cxt
forall a b. (a -> b) -> [a] -> [b]
map Type -> Type
renamePred Cxt
cxt
where
#if MIN_VERSION_template_haskell(2,10,0)
renamePred :: Type -> Type
renamePred Type
p = Type -> Type
renameType Type
p
#else
renamePred (ClassP n tys) = ClassP n (map renameType tys)
renamePred (EqualP a b) = EqualP (renameType a) (renameType b)
#endif
renameType :: Type -> Type
renameType Type
n | Type
n Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Type
tfrom = Type
tto
renameType (AppT Type
a Type
b) = Type -> Type -> Type
AppT (Type -> Type
renameType Type
a) (Type -> Type
renameType Type
b)
renameType (SigT Type
a Type
k) = Type -> Type -> Type
SigT (Type -> Type
renameType Type
a) Type
k
renameType Type
typ = Type
typ
makeEventHandler :: SerialiserSpec -> Name -> Type -> ExpQ
makeEventHandler :: SerialiserSpec -> Name -> Type -> ExpQ
makeEventHandler SerialiserSpec
ss Name
eventName Type
eventType
= do Q ()
assertTyVarsOk
[Name]
vars <- Int -> Q Name -> Q [Name]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (Cxt -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Cxt
args) ([Char] -> Q Name
forall (m :: * -> *). Quote m => [Char] -> m Name
newName [Char]
"arg")
let lamClause :: Q Pat
lamClause = Name -> [Q Pat] -> Q Pat
forall (m :: * -> *). Quote m => Name -> [m Pat] -> m Pat
conP Name
eventStructName [Name -> Q Pat
forall (m :: * -> *). Quote m => Name -> m Pat
varP Name
var | Name
var <- [Name]
vars ]
Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
conE Name
constr ExpQ -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`appE` [Q Pat] -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => [m Pat] -> m Exp -> m Exp
lamE [Q Pat
lamClause] ((ExpQ -> ExpQ -> ExpQ) -> ExpQ -> [ExpQ] -> ExpQ
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl ExpQ -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
appE (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
eventName) ((Name -> ExpQ) -> [Name] -> [ExpQ]
forall a b. (a -> b) -> [a] -> [b]
map Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE [Name]
vars))
ExpQ -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`appE` Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE (SerialiserSpec -> Name
methodSerialiserName SerialiserSpec
ss)
where constr :: Name
constr = if Bool
isUpdate then 'UpdateEvent else 'QueryEvent
TypeAnalysis { [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars :: TypeAnalysis -> [TyVarBndr ()]
tyvars, argumentTypes :: TypeAnalysis -> Cxt
argumentTypes = Cxt
args, Type
stateType :: TypeAnalysis -> Type
stateType :: Type
stateType, Bool
isUpdate :: Bool
isUpdate :: TypeAnalysis -> Bool
isUpdate } = Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
eventType
eventStructName :: Name
eventStructName = Name -> Name
toStructName Name
eventName
stateTypeTyVars :: [Name]
stateTypeTyVars = Type -> [Name]
findTyVars Type
stateType
tyVarNames :: [Name]
tyVarNames = (TyVarBndr () -> Name) -> [TyVarBndr ()] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map TyVarBndr () -> Name
forall a. TyVarBndr a -> Name
tyVarBndrName [TyVarBndr ()]
tyvars
assertTyVarsOk :: Q ()
assertTyVarsOk =
case [Name]
tyVarNames [Name] -> [Name] -> [Name]
forall a. Eq a => [a] -> [a] -> [a]
\\ [Name]
stateTypeTyVars of
[] -> () -> Q ()
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
[Name]
ns -> [Char] -> Q ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> Q ()) -> [Char] -> Q ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Data.Acid.TemplateHaskell: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [[Char]] -> [Char]
unlines
[Doc -> [Char]
forall a. Show a => a -> [Char]
show (Doc -> [Char]) -> Doc -> [Char]
forall a b. (a -> b) -> a -> b
$ Name -> Type -> Doc
ppr_sig Name
eventName Type
eventType
, [Char]
""
, [Char]
"can not be used as an UpdateEvent because it contains the type variables: "
, [Char]
""
, [Name] -> [Char]
forall a. Ppr a => a -> [Char]
pprint [Name]
ns
, [Char]
""
, [Char]
"which do not appear in the state type:"
, [Char]
""
, Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint Type
stateType
]
makeEventDataType :: Name -> Type -> DecQ
makeEventDataType :: Name -> Type -> DecQ
makeEventDataType Name
eventName Type
eventType
= do let con :: Q Con
con = Name -> [Q BangType] -> Q Con
forall (m :: * -> *). Quote m => Name -> [m BangType] -> m Con
normalC Name
eventStructName [ Q Strict -> Q Type -> Q BangType
forall (m :: * -> *). Quote m => m Strict -> m Type -> m BangType
strictType Q Strict
forall (m :: * -> *). Quote m => m Strict
notStrict (Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
arg) | Type
arg <- Cxt
args ]
#if MIN_VERSION_template_haskell(2,12,0)
cxt :: [Q DerivClause]
cxt = [Maybe DerivStrategy -> [Q Type] -> Q DerivClause
forall (m :: * -> *).
Quote m =>
Maybe DerivStrategy -> [m Type] -> m DerivClause
derivClause Maybe DerivStrategy
forall a. Maybe a
Nothing [Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT ''Typeable]]
#elif MIN_VERSION_template_haskell(2,11,0)
cxt = mapM conT [''Typeable]
#else
cxt = [''Typeable]
#endif
case Cxt
args of
#if MIN_VERSION_template_haskell(2,21,0)
[_] -> newtypeD (return []) eventStructName (map (BndrReq <$) tyvars) Nothing con cxt
_ -> dataD (return []) eventStructName (map (BndrReq <$) tyvars) Nothing [con] cxt
#elif MIN_VERSION_template_haskell(2,11,0)
[Type
_] -> Q Cxt
-> Name
-> [TyVarBndr ()]
-> Maybe Type
-> Q Con
-> [Q DerivClause]
-> DecQ
forall (m :: * -> *).
Quote m =>
m Cxt
-> Name
-> [TyVarBndr ()]
-> Maybe Type
-> m Con
-> [m DerivClause]
-> m Dec
newtypeD (Cxt -> Q Cxt
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return []) Name
eventStructName [TyVarBndr ()]
tyvars Maybe Type
forall a. Maybe a
Nothing Q Con
con [Q DerivClause]
cxt
Cxt
_ -> Q Cxt
-> Name
-> [TyVarBndr ()]
-> Maybe Type
-> [Q Con]
-> [Q DerivClause]
-> DecQ
forall (m :: * -> *).
Quote m =>
m Cxt
-> Name
-> [TyVarBndr ()]
-> Maybe Type
-> [m Con]
-> [m DerivClause]
-> m Dec
dataD (Cxt -> Q Cxt
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return []) Name
eventStructName [TyVarBndr ()]
tyvars Maybe Type
forall a. Maybe a
Nothing [Q Con
con] [Q DerivClause]
cxt
#else
[_] -> newtypeD (return []) eventStructName tyvars con cxt
_ -> dataD (return []) eventStructName tyvars [con] cxt
#endif
where TypeAnalysis { [TyVarBndr ()]
tyvars :: TypeAnalysis -> [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, argumentTypes :: TypeAnalysis -> Cxt
argumentTypes = Cxt
args } = Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
eventType
eventStructName :: Name
eventStructName = Name -> Name
toStructName Name
eventName
makeSafeCopyInstance :: Name -> Type -> DecQ
makeSafeCopyInstance :: Name -> Type -> DecQ
makeSafeCopyInstance Name
eventName Type
eventType
= do let preds :: [Name]
preds = [ ''SafeCopy ]
ty :: Type
ty = Type -> Type -> Type
AppT (Name -> Type
ConT ''SafeCopy) ((Type -> Type -> Type) -> Type -> Cxt -> 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
eventStructName) ((Name -> Type) -> [Name] -> Cxt
forall a b. (a -> b) -> [a] -> [b]
map Name -> Type
VarT ([TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars)))
getBase :: ExpQ
getBase = ExpQ -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
appE (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE 'return) (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
conE Name
eventStructName)
getArgs :: ExpQ
getArgs = (ExpQ -> Type -> ExpQ) -> ExpQ -> Cxt -> ExpQ
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\ExpQ
a Type
b -> Maybe ExpQ -> ExpQ -> Maybe ExpQ -> ExpQ
forall (m :: * -> *).
Quote m =>
Maybe (m Exp) -> m Exp -> Maybe (m Exp) -> m Exp
infixE (ExpQ -> Maybe ExpQ
forall a. a -> Maybe a
Just ExpQ
a) (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE '(<*>)) (ExpQ -> Maybe ExpQ
forall a. a -> Maybe a
Just (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE 'safeGet))) ExpQ
getBase Cxt
args
contained :: m Exp -> m Exp
contained m Exp
val = Name -> m Exp
forall (m :: * -> *). Quote m => Name -> m Exp
varE 'contain m Exp -> m Exp -> m Exp
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`appE` m Exp
val
[Name]
putVars <- Int -> Q Name -> Q [Name]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (Cxt -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Cxt
args) ([Char] -> Q Name
forall (m :: * -> *). Quote m => [Char] -> m Name
newName [Char]
"arg")
let putClause :: Q Pat
putClause = Name -> [Q Pat] -> Q Pat
forall (m :: * -> *). Quote m => Name -> [m Pat] -> m Pat
conP Name
eventStructName [Name -> Q Pat
forall (m :: * -> *). Quote m => Name -> m Pat
varP Name
var | Name
var <- [Name]
putVars ]
putExp :: ExpQ
putExp = [Q Stmt] -> ExpQ
forall (m :: * -> *). Quote m => [m Stmt] -> m Exp
doE ([Q Stmt] -> ExpQ) -> [Q Stmt] -> ExpQ
forall a b. (a -> b) -> a -> b
$ [ ExpQ -> Q Stmt
forall (m :: * -> *). Quote m => m Exp -> m Stmt
noBindS (ExpQ -> Q Stmt) -> ExpQ -> Q Stmt
forall a b. (a -> b) -> a -> b
$ ExpQ -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
appE (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE 'safePut) (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
var) | Name
var <- [Name]
putVars ] [Q Stmt] -> [Q Stmt] -> [Q Stmt]
forall a. [a] -> [a] -> [a]
++
[ ExpQ -> Q Stmt
forall (m :: * -> *). Quote m => m Exp -> m Stmt
noBindS (ExpQ -> Q Stmt) -> ExpQ -> Q Stmt
forall a b. (a -> b) -> a -> b
$ ExpQ -> ExpQ -> ExpQ
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
appE (Name -> ExpQ
forall (m :: * -> *). Quote m => Name -> m Exp
varE 'return) ([ExpQ] -> ExpQ
forall (m :: * -> *). Quote m => [m Exp] -> m Exp
tupE []) ]
Q Cxt -> Q Type -> [DecQ] -> DecQ
forall (m :: * -> *).
Quote m =>
m Cxt -> m Type -> [m Dec] -> m Dec
instanceD ([Name] -> [TyVarBndr ()] -> Cxt -> Q Cxt
forall {m :: * -> *} {a}.
Quote m =>
[Name] -> [TyVarBndr a] -> Cxt -> m Cxt
mkCxtFromTyVars [Name]
preds [TyVarBndr ()]
tyvars Cxt
context)
(Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
ty)
[ Name -> [Q Clause] -> DecQ
forall (m :: * -> *). Quote m => Name -> [m Clause] -> m Dec
funD 'putCopy [[Q Pat] -> Q Body -> [DecQ] -> Q Clause
forall (m :: * -> *).
Quote m =>
[m Pat] -> m Body -> [m Dec] -> m Clause
clause [Q Pat
putClause] (ExpQ -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB (ExpQ -> ExpQ
forall {m :: * -> *}. Quote m => m Exp -> m Exp
contained ExpQ
putExp)) []]
, Q Pat -> Q Body -> [DecQ] -> DecQ
forall (m :: * -> *).
Quote m =>
m Pat -> m Body -> [m Dec] -> m Dec
valD (Name -> Q Pat
forall (m :: * -> *). Quote m => Name -> m Pat
varP 'getCopy) (ExpQ -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB (ExpQ -> ExpQ
forall {m :: * -> *}. Quote m => m Exp -> m Exp
contained ExpQ
getArgs)) []
, Name -> [Q Clause] -> DecQ
forall (m :: * -> *). Quote m => Name -> [m Clause] -> m Dec
funD 'errorTypeName [[Q Pat] -> Q Body -> [DecQ] -> Q Clause
forall (m :: * -> *).
Quote m =>
[m Pat] -> m Body -> [m Dec] -> m Clause
clause [Q Pat
forall (m :: * -> *). Quote m => m Pat
wildP] (ExpQ -> Q Body
forall (m :: * -> *). Quote m => m Exp -> m Body
normalB (Lit -> ExpQ
forall (m :: * -> *). Quote m => Lit -> m Exp
litE ([Char] -> Lit
stringL (Type -> [Char]
forall a. Ppr a => a -> [Char]
pprint Type
ty)))) []]
]
where TypeAnalysis { [TyVarBndr ()]
tyvars :: TypeAnalysis -> [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
context :: TypeAnalysis -> Cxt
context :: Cxt
context, argumentTypes :: TypeAnalysis -> Cxt
argumentTypes = Cxt
args } = Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
eventType
eventStructName :: Name
eventStructName = Name -> Name
toStructName Name
eventName
mkCxtFromTyVars :: [Name] -> [TyVarBndr a] -> Cxt -> m Cxt
mkCxtFromTyVars [Name]
preds [TyVarBndr a]
tyvars Cxt
extraContext
= [m Type] -> m Cxt
forall (m :: * -> *). Quote m => [m Type] -> m Cxt
cxt ([m Type] -> m Cxt) -> [m Type] -> m Cxt
forall a b. (a -> b) -> a -> b
$ [ Name -> [m Type] -> m Type
forall (m :: * -> *). Quote m => Name -> [m Type] -> m Type
classP Name
classPred [Name -> m Type
forall (m :: * -> *). Quote m => Name -> m Type
varT Name
tyvar] | Name
tyvar <- [TyVarBndr a] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr a]
tyvars, Name
classPred <- [Name]
preds ] [m Type] -> [m Type] -> [m Type]
forall a. [a] -> [a] -> [a]
++
(Type -> m Type) -> Cxt -> [m Type]
forall a b. (a -> b) -> [a] -> [b]
map Type -> m Type
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Cxt
extraContext
makeMethodInstance :: Name -> Type -> DecQ
makeMethodInstance :: Name -> Type -> DecQ
makeMethodInstance Name
eventName Type
eventType = do
let preds :: [Name]
preds =
[ ''Typeable ]
ty :: Type
ty =
Type -> Type -> Type
AppT (Name -> Type
ConT ''Method) ((Type -> Type -> Type) -> Type -> Cxt -> 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
eventStructName) ((Name -> Type) -> [Name] -> Cxt
forall a b. (a -> b) -> [a] -> [b]
map Name -> Type
VarT ([TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars)))
structType :: Q Type
structType =
(Q Type -> Q Type -> Q Type) -> Q Type -> [Q Type] -> Q Type
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Q Type -> Q Type -> Q Type
forall (m :: * -> *). Quote m => m Type -> m Type -> m Type
appT (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT Name
eventStructName) ((Name -> Q Type) -> [Name] -> [Q Type]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT ([TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars))
instanceContext :: Q Cxt
instanceContext =
[Q Type] -> Q Cxt
forall (m :: * -> *). Quote m => [m Type] -> m Cxt
cxt ([Q Type] -> Q Cxt) -> [Q Type] -> Q Cxt
forall a b. (a -> b) -> a -> b
$
[ Name -> [Q Type] -> Q Type
forall (m :: * -> *). Quote m => Name -> [m Type] -> m Type
classP Name
classPred [Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT Name
tyvar]
| Name
tyvar <- [TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars
, Name
classPred <- [Name]
preds
]
[Q Type] -> [Q Type] -> [Q Type]
forall a. [a] -> [a] -> [a]
++ (Type -> Q Type) -> Cxt -> [Q Type]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Cxt
context
Q Cxt -> Q Type -> [DecQ] -> DecQ
forall (m :: * -> *).
Quote m =>
m Cxt -> m Type -> [m Dec] -> m Dec
instanceD
Q Cxt
instanceContext
(Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
ty)
#if MIN_VERSION_template_haskell(2,15,0)
[ Q TySynEqn -> DecQ
forall (m :: * -> *). Quote m => m TySynEqn -> m Dec
tySynInstD (Q TySynEqn -> DecQ) -> Q TySynEqn -> DecQ
forall a b. (a -> b) -> a -> b
$ Maybe [TyVarBndr ()] -> Q Type -> Q Type -> Q TySynEqn
forall (m :: * -> *).
Quote m =>
Maybe [TyVarBndr ()] -> m Type -> m Type -> m TySynEqn
tySynEqn Maybe [TyVarBndr ()]
forall a. Maybe a
Nothing (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT ''MethodResult Q Type -> Q Type -> Q Type
forall (m :: * -> *). Quote m => m Type -> m Type -> m Type
`appT` Q Type
structType) (Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
resultType)
, Q TySynEqn -> DecQ
forall (m :: * -> *). Quote m => m TySynEqn -> m Dec
tySynInstD (Q TySynEqn -> DecQ) -> Q TySynEqn -> DecQ
forall a b. (a -> b) -> a -> b
$ Maybe [TyVarBndr ()] -> Q Type -> Q Type -> Q TySynEqn
forall (m :: * -> *).
Quote m =>
Maybe [TyVarBndr ()] -> m Type -> m Type -> m TySynEqn
tySynEqn Maybe [TyVarBndr ()]
forall a. Maybe a
Nothing (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT ''MethodState Q Type -> Q Type -> Q Type
forall (m :: * -> *). Quote m => m Type -> m Type -> m Type
`appT` Q Type
structType) (Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
stateType)
#elif __GLASGOW_HASKELL__ >= 707
[ tySynInstD ''MethodResult (tySynEqn [structType] (return resultType))
, tySynInstD ''MethodState (tySynEqn [structType] (return stateType))
#else
[ tySynInstD ''MethodResult [structType] (return resultType)
, tySynInstD ''MethodState [structType] (return stateType)
#endif
]
where TypeAnalysis { [TyVarBndr ()]
tyvars :: TypeAnalysis -> [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
context :: TypeAnalysis -> Cxt
context :: Cxt
context, Type
stateType :: TypeAnalysis -> Type
stateType :: Type
stateType, Type
resultType :: Type
resultType :: TypeAnalysis -> Type
resultType } = Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
eventType
eventStructName :: Name
eventStructName = Name -> Name
toStructName Name
eventName
makeEventInstance :: Name -> Type -> DecQ
makeEventInstance :: Name -> Type -> DecQ
makeEventInstance Name
eventName Type
eventType
= do let preds :: [Name]
preds = [ ''Typeable ]
eventClass :: Name
eventClass = if Bool
isUpdate then ''UpdateEvent else ''QueryEvent
ty :: Type
ty = Type -> Type -> Type
AppT (Name -> Type
ConT Name
eventClass) ((Type -> Type -> Type) -> Type -> Cxt -> 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
eventStructName) ((Name -> Type) -> [Name] -> Cxt
forall a b. (a -> b) -> [a] -> [b]
map Name -> Type
VarT ([TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars)))
Q Cxt -> Q Type -> [DecQ] -> DecQ
forall (m :: * -> *).
Quote m =>
m Cxt -> m Type -> [m Dec] -> m Dec
instanceD ([Q Type] -> Q Cxt
forall (m :: * -> *). Quote m => [m Type] -> m Cxt
cxt ([Q Type] -> Q Cxt) -> [Q Type] -> Q Cxt
forall a b. (a -> b) -> a -> b
$ [ Name -> [Q Type] -> Q Type
forall (m :: * -> *). Quote m => Name -> [m Type] -> m Type
classP Name
classPred [Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT Name
tyvar] | Name
tyvar <- [TyVarBndr ()] -> [Name]
forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr ()]
tyvars, Name
classPred <- [Name]
preds ] [Q Type] -> [Q Type] -> [Q Type]
forall a. [a] -> [a] -> [a]
++ (Type -> Q Type) -> Cxt -> [Q Type]
forall a b. (a -> b) -> [a] -> [b]
map Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Cxt
context)
(Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
ty)
[]
where TypeAnalysis { [TyVarBndr ()]
tyvars :: TypeAnalysis -> [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
context :: TypeAnalysis -> Cxt
context :: Cxt
context, Bool
isUpdate :: TypeAnalysis -> Bool
isUpdate :: Bool
isUpdate } = Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
eventType
eventStructName :: Name
eventStructName = Name -> Name
toStructName Name
eventName
data TypeAnalysis = TypeAnalysis
{ TypeAnalysis -> [TyVarBndr ()]
tyvars :: [TyVarBndrUnit]
, TypeAnalysis -> Cxt
context :: Cxt
, TypeAnalysis -> Cxt
argumentTypes :: [Type]
, TypeAnalysis -> Type
stateType :: Type
, TypeAnalysis -> Type
resultType :: Type
, TypeAnalysis -> Bool
isUpdate :: Bool
} deriving (TypeAnalysis -> TypeAnalysis -> Bool
(TypeAnalysis -> TypeAnalysis -> Bool)
-> (TypeAnalysis -> TypeAnalysis -> Bool) -> Eq TypeAnalysis
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TypeAnalysis -> TypeAnalysis -> Bool
== :: TypeAnalysis -> TypeAnalysis -> Bool
$c/= :: TypeAnalysis -> TypeAnalysis -> Bool
/= :: TypeAnalysis -> TypeAnalysis -> Bool
Eq, Int -> TypeAnalysis -> [Char] -> [Char]
[TypeAnalysis] -> [Char] -> [Char]
TypeAnalysis -> [Char]
(Int -> TypeAnalysis -> [Char] -> [Char])
-> (TypeAnalysis -> [Char])
-> ([TypeAnalysis] -> [Char] -> [Char])
-> Show TypeAnalysis
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
$cshowsPrec :: Int -> TypeAnalysis -> [Char] -> [Char]
showsPrec :: Int -> TypeAnalysis -> [Char] -> [Char]
$cshow :: TypeAnalysis -> [Char]
show :: TypeAnalysis -> [Char]
$cshowList :: [TypeAnalysis] -> [Char] -> [Char]
showList :: [TypeAnalysis] -> [Char] -> [Char]
Show)
analyseType :: Name -> Type -> TypeAnalysis
analyseType :: Name -> Type -> TypeAnalysis
analyseType Name
eventName Type
t = [TyVarBndr ()] -> Cxt -> Cxt -> Type -> TypeAnalysis
go [] [] [] Type
t
where
#if MIN_VERSION_template_haskell(2,10,0)
getMonadReader :: Cxt -> Name -> [(Type, Type)]
getMonadReader :: Cxt -> Name -> [(Type, Type)]
getMonadReader Cxt
cxt Name
m = do
constraint :: Type
constraint@(AppT (AppT (ConT Name
c) Type
x) Type
m') <- Cxt
cxt
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Name
c Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== ''MonadReader Bool -> Bool -> Bool
&& Type
m' Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> Type
VarT Name
m)
(Type, Type) -> [(Type, Type)]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Type
constraint, Type
x)
getMonadState :: Cxt -> Name -> [(Type, Type)]
getMonadState :: Cxt -> Name -> [(Type, Type)]
getMonadState Cxt
cxt Name
m = do
constraint :: Type
constraint@(AppT (AppT (ConT Name
c) Type
x) Type
m') <- Cxt
cxt
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Name
c Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== ''MonadState Bool -> Bool -> Bool
&& Type
m' Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> Type
VarT Name
m)
(Type, Type) -> [(Type, Type)]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Type
constraint, Type
x)
#else
getMonadReader :: Cxt -> Name -> [(Pred, Type)]
getMonadReader cxt m = do
constraint@(ClassP c [x, m']) <- cxt
guard (c == ''MonadReader && m' == VarT m)
return (constraint, x)
getMonadState :: Cxt -> Name -> [(Pred, Type)]
getMonadState cxt m = do
constraint@(ClassP c [x, m']) <- cxt
guard (c == ''MonadState && m' == VarT m)
return (constraint, x)
#endif
go :: [TyVarBndr ()] -> Cxt -> Cxt -> Type -> TypeAnalysis
go [TyVarBndr ()]
tyvars Cxt
cxt Cxt
args (AppT (AppT Type
ArrowT Type
a) Type
b)
= [TyVarBndr ()] -> Cxt -> Cxt -> Type -> TypeAnalysis
go [TyVarBndr ()]
tyvars Cxt
cxt (Cxt
args Cxt -> Cxt -> Cxt
forall a. [a] -> [a] -> [a]
++ [Type
a]) Type
b
go [TyVarBndr ()]
tyvars Cxt
context Cxt
argumentTypes (AppT (AppT (ConT Name
con) Type
stateType) Type
resultType)
| Name
con Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== ''Update =
TypeAnalysis
{ [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
context :: Cxt
context :: Cxt
context, Cxt
argumentTypes :: Cxt
argumentTypes :: Cxt
argumentTypes, Type
stateType :: Type
stateType :: Type
stateType, Type
resultType :: Type
resultType :: Type
resultType
, isUpdate :: Bool
isUpdate = Bool
True
}
| Name
con Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== ''Query =
TypeAnalysis
{ [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
context :: Cxt
context :: Cxt
context, Cxt
argumentTypes :: Cxt
argumentTypes :: Cxt
argumentTypes, Type
stateType :: Type
stateType :: Type
stateType, Type
resultType :: Type
resultType :: Type
resultType
, isUpdate :: Bool
isUpdate = Bool
False
}
go [TyVarBndr ()]
tyvars Cxt
cxt Cxt
args (ForallT [TyVarBndr Specificity]
tyvars2 Cxt
cxt2 Type
a)
#if MIN_VERSION_template_haskell(2,17,0)
= [TyVarBndr ()] -> Cxt -> Cxt -> Type -> TypeAnalysis
go ([TyVarBndr ()]
tyvars [TyVarBndr ()] -> [TyVarBndr ()] -> [TyVarBndr ()]
forall a. [a] -> [a] -> [a]
++ (TyVarBndr Specificity -> TyVarBndr ())
-> [TyVarBndr Specificity] -> [TyVarBndr ()]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TyVarBndr Specificity -> TyVarBndr ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void [TyVarBndr Specificity]
tyvars2) (Cxt
cxt Cxt -> Cxt -> Cxt
forall a. [a] -> [a] -> [a]
++ Cxt
cxt2) Cxt
args Type
a
#else
= go (tyvars ++ tyvars2) (cxt ++ cxt2) args a
#endif
go [TyVarBndr ()]
tyvars' Cxt
cxt Cxt
argumentTypes (AppT (VarT Name
m) Type
resultType)
| [] <- [(Type, Type)]
queries, [(Type
cx, Type
stateType)] <- [(Type, Type)]
updates
= TypeAnalysis
{ [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
argumentTypes :: Cxt
argumentTypes :: Cxt
argumentTypes , Type
stateType :: Type
stateType :: Type
stateType, Type
resultType :: Type
resultType :: Type
resultType
, isUpdate :: Bool
isUpdate = Bool
True
, context :: Cxt
context = Type -> Cxt -> Cxt
forall a. Eq a => a -> [a] -> [a]
delete Type
cx Cxt
cxt
}
| [(Type
cx, Type
stateType)] <- [(Type, Type)]
queries, [] <- [(Type, Type)]
updates
= TypeAnalysis
{ [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars :: [TyVarBndr ()]
tyvars, Cxt
argumentTypes :: Cxt
argumentTypes :: Cxt
argumentTypes , Type
stateType :: Type
stateType :: Type
stateType, Type
resultType :: Type
resultType :: Type
resultType
, isUpdate :: Bool
isUpdate = Bool
False
, context :: Cxt
context = Type -> Cxt -> Cxt
forall a. Eq a => a -> [a] -> [a]
delete Type
cx Cxt
cxt
}
where
queries :: [(Type, Type)]
queries = Cxt -> Name -> [(Type, Type)]
getMonadReader Cxt
cxt Name
m
updates :: [(Type, Type)]
updates = Cxt -> Name -> [(Type, Type)]
getMonadState Cxt
cxt Name
m
tyvars :: [TyVarBndr ()]
tyvars = (TyVarBndr () -> Bool) -> [TyVarBndr ()] -> [TyVarBndr ()]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= Name
m) (Name -> Bool) -> (TyVarBndr () -> Name) -> TyVarBndr () -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TyVarBndr () -> Name
forall a. TyVarBndr a -> Name
tyVarBndrName) [TyVarBndr ()]
tyvars'
go [TyVarBndr ()]
_ Cxt
_ Cxt
_ Type
_ = [Char] -> TypeAnalysis
forall a. HasCallStack => [Char] -> a
error ([Char] -> TypeAnalysis) -> [Char] -> TypeAnalysis
forall a b. (a -> b) -> a -> b
$ [Char]
"Data.Acid.TemplateHaskell: Event has an invalid type signature: Not an Update, Query, MonadState, or MonadReader: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
eventName
findTyVars :: Type -> [Name]
findTyVars :: Type -> [Name]
findTyVars (ForallT [TyVarBndr Specificity]
_ Cxt
_ Type
a) = Type -> [Name]
findTyVars Type
a
findTyVars (VarT Name
n) = [Name
n]
findTyVars (AppT Type
a Type
b) = Type -> [Name]
findTyVars Type
a [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
++ Type -> [Name]
findTyVars Type
b
findTyVars (SigT Type
a Type
_) = Type -> [Name]
findTyVars Type
a
findTyVars Type
_ = []
#if MIN_VERSION_template_haskell(2,17,0)
tyVarBndrName :: TyVarBndr a -> Name
tyVarBndrName :: forall a. TyVarBndr a -> Name
tyVarBndrName (PlainTV Name
n a
_) = Name
n
tyVarBndrName (KindedTV Name
n a
_ Type
_) = Name
n
allTyVarBndrNames :: [TyVarBndr a] -> [Name]
allTyVarBndrNames :: forall a. [TyVarBndr a] -> [Name]
allTyVarBndrNames [TyVarBndr a]
tyvars = (TyVarBndr a -> Name) -> [TyVarBndr a] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map TyVarBndr a -> Name
forall a. TyVarBndr a -> Name
tyVarBndrName [TyVarBndr a]
tyvars
#else
tyVarBndrName :: TyVarBndr -> Name
tyVarBndrName (PlainTV n) = n
tyVarBndrName (KindedTV n _) = n
allTyVarBndrNames :: [TyVarBndr] -> [Name]
allTyVarBndrNames tyvars = map tyVarBndrName tyvars
#endif
toStructName :: Name -> Name
toStructName :: Name -> Name
toStructName Name
eventName = [Char] -> Name
mkName ([Char] -> [Char]
structName (Name -> [Char]
nameBase Name
eventName))
where
structName :: [Char] -> [Char]
structName [] = []
structName (Char
x:[Char]
xs) = Char -> Char
toUpper Char
x Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
xs