{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
module Grisette.Internal.Internal.Decl.Unified.EvalMode
( EvalModeBase,
EvalModeInteger,
EvalModeBV,
EvalModeFP,
EvalModeAlgReal,
EvalModeAll,
MonadEvalModeAll,
genEvalMode,
)
where
import Data.List (nub)
import Data.Maybe (mapMaybe)
import Grisette.Internal.Core.Data.Class.TryMerge (TryMerge)
import Grisette.Internal.Internal.Decl.Unified.BVFPConversion
( AllUnifiedBVFPConversion,
)
import Grisette.Internal.Internal.Decl.Unified.FPFPConversion
( AllUnifiedFPFPConversion,
)
import Grisette.Internal.Internal.Decl.Unified.UnifiedBV (AllUnifiedBV)
import Grisette.Internal.Internal.Decl.Unified.UnifiedBool
( UnifiedBool (GetBool),
)
import Grisette.Internal.Internal.Decl.Unified.UnifiedFP (AllUnifiedFP)
import Grisette.Internal.Unified.BVBVConversion (AllUnifiedBVBVConversion)
import Grisette.Internal.Unified.Class.UnifiedSimpleMergeable (UnifiedBranching)
import Grisette.Internal.Unified.EvalModeTag (EvalModeTag (C, S))
import Grisette.Internal.Unified.Theories
( TheoryToUnify (UAlgReal, UFP, UFun, UIntN, UInteger, UWordN),
isUFun,
)
import Grisette.Internal.Unified.UnifiedAlgReal (UnifiedAlgReal)
import Grisette.Internal.Unified.UnifiedData (AllUnifiedData, UnifiedDataBase)
import Grisette.Internal.Unified.UnifiedFun
( genUnifiedFunInstance,
unifiedFunInstanceName,
)
import Grisette.Internal.Unified.UnifiedInteger (UnifiedInteger)
import Grisette.Internal.Unified.UnifiedPrim (UnifiedBasicPrim)
import Grisette.Internal.Unified.Util (DecideEvalMode)
import Language.Haskell.TH
( DecsQ,
Type (AppT, ArrowT, ConT, StarT, VarT),
appT,
classD,
conT,
instanceD,
kindedTV,
mkName,
newName,
promotedT,
tySynD,
varT,
)
class
( DecideEvalMode mode,
UnifiedBool mode,
UnifiedBasicPrim mode (GetBool mode),
AllUnifiedData mode,
UnifiedDataBase mode
) =>
EvalModeBase mode
class (AllUnifiedBV mode, AllUnifiedBVBVConversion mode) => EvalModeBV mode
type EvalModeInteger = UnifiedInteger
class
( AllUnifiedFP mode,
AllUnifiedFPFPConversion mode,
AllUnifiedBVFPConversion mode
) =>
EvalModeFP mode
type EvalModeAlgReal = UnifiedAlgReal
class
( EvalModeBase mode,
EvalModeInteger mode,
EvalModeAlgReal mode,
EvalModeBV mode,
EvalModeFP mode
) =>
EvalModeAll mode
type MonadEvalModeAll mode m =
( EvalModeAll mode,
Monad m,
TryMerge m,
UnifiedBranching mode m
)
genEvalMode :: String -> [TheoryToUnify] -> DecsQ
genEvalMode :: String -> [TheoryToUnify] -> DecsQ
genEvalMode String
nm [TheoryToUnify]
theories = do
Name
modeName <- String -> Q Name
forall (m :: * -> *). Quote m => String -> m Name
newName String
"mode"
let modeType :: Type
modeType = Name -> Type
VarT Name
modeName
Type
baseConstraint <- [t|EvalModeBase $(Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
modeType)|]
[Type]
basicConstraints <- [[Type]] -> [Type]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Type]] -> [Type]) -> Q [[Type]] -> Q [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TheoryToUnify -> Q [Type]) -> [TheoryToUnify] -> Q [[Type]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (Type -> TheoryToUnify -> Q [Type]
forall {f :: * -> *}. Quote f => Type -> TheoryToUnify -> f [Type]
nonFuncConstraint Type
modeType) [TheoryToUnify]
nonFuncs
[Dec]
funcInstances <- [[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Dec]] -> [Dec]) -> Q [[Dec]] -> DecsQ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([TheoryToUnify] -> DecsQ) -> [[TheoryToUnify]] -> Q [[Dec]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (String -> [TheoryToUnify] -> DecsQ
genUnifiedFunInstance String
nm) [[TheoryToUnify]]
funcs
let instanceNames :: [String]
instanceNames = (String
"All" String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String)
-> ([TheoryToUnify] -> String) -> [TheoryToUnify] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [TheoryToUnify] -> String
unifiedFunInstanceName String
nm ([TheoryToUnify] -> String) -> [[TheoryToUnify]] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[TheoryToUnify]]
funcs
[Type]
funcConstraints <- (String -> Q Type) -> [String] -> Q [Type]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (Q Type -> String -> Q Type
forall {m :: * -> *}. Quote m => m Type -> String -> m Type
genFunConstraint (Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
modeType)) [String]
instanceNames
Dec
r <-
Q [Type]
-> Name -> [TyVarBndr BndrVis] -> [FunDep] -> [Q Dec] -> Q Dec
forall (m :: * -> *).
Quote m =>
m [Type]
-> Name -> [TyVarBndr BndrVis] -> [FunDep] -> [m Dec] -> m Dec
classD
([Type] -> Q [Type]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Type] -> Q [Type]) -> [Type] -> Q [Type]
forall a b. (a -> b) -> a -> b
$ Type
baseConstraint Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: [Type]
basicConstraints [Type] -> [Type] -> [Type]
forall a. [a] -> [a] -> [a]
++ [Type]
funcConstraints)
(String -> Name
mkName String
nm)
[Name -> Type -> TyVarBndr BndrVis
forall flag. DefaultBndrFlag flag => Name -> Type -> TyVarBndr flag
kindedTV Name
modeName (Name -> Type
ConT ''EvalModeTag)]
[]
[]
Dec
rc <- Q [Type] -> Q Type -> [Q Dec] -> Q Dec
forall (m :: * -> *).
Quote m =>
m [Type] -> m Type -> [m Dec] -> m Dec
instanceD ([Type] -> Q [Type]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return []) (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 -> Q Type) -> Name -> Q Type
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
nm) (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
promotedT 'C)) []
Dec
rs <- Q [Type] -> Q Type -> [Q Dec] -> Q Dec
forall (m :: * -> *).
Quote m =>
m [Type] -> m Type -> [m Dec] -> m Dec
instanceD ([Type] -> Q [Type]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return []) (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 -> Q Type) -> Name -> Q Type
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
nm) (Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
promotedT 'S)) []
Name
m <- String -> Q Name
forall (m :: * -> *). Quote m => String -> m Name
newName String
"m"
let mType :: Q Type
mType = Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
varT Name
m
Dec
monad <-
Name -> [TyVarBndr BndrVis] -> Q Type -> Q Dec
forall (m :: * -> *).
Quote m =>
Name -> [TyVarBndr BndrVis] -> m Type -> m Dec
tySynD
(String -> Name
mkName (String -> Name) -> String -> Name
forall a b. (a -> b) -> a -> b
$ String
"Monad" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
nm)
[ Name -> Type -> TyVarBndr BndrVis
forall flag. DefaultBndrFlag flag => Name -> Type -> TyVarBndr flag
kindedTV Name
modeName (Name -> Type
ConT ''EvalModeTag),
Name -> Type -> TyVarBndr BndrVis
forall flag. DefaultBndrFlag flag => Name -> Type -> TyVarBndr flag
kindedTV Name
m (Type -> Type -> Type
AppT (Type -> Type -> Type
AppT Type
ArrowT Type
StarT) Type
StarT)
]
[t|
( $(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 -> Q Type) -> Name -> Q Type
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
nm) (Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
modeType)),
Monad $Q Type
mType,
TryMerge $Q Type
mType,
UnifiedBranching $(Type -> Q Type
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
modeType) $Q Type
mType
)
|]
[Dec] -> DecsQ
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Dec] -> DecsQ) -> [Dec] -> DecsQ
forall a b. (a -> b) -> a -> b
$ [Dec]
funcInstances [Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
++ [Dec
r, Dec
rc, Dec
rs, Dec
monad]
where
nonFuncs :: [TheoryToUnify]
nonFuncs =
[TheoryToUnify] -> [TheoryToUnify]
forall a. Eq a => [a] -> [a]
nub ([TheoryToUnify] -> [TheoryToUnify])
-> [TheoryToUnify] -> [TheoryToUnify]
forall a b. (a -> b) -> a -> b
$
(\TheoryToUnify
x -> if TheoryToUnify
x TheoryToUnify -> TheoryToUnify -> Bool
forall a. Eq a => a -> a -> Bool
== TheoryToUnify
UIntN then TheoryToUnify
UWordN else TheoryToUnify
x)
(TheoryToUnify -> TheoryToUnify)
-> [TheoryToUnify] -> [TheoryToUnify]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TheoryToUnify -> Bool) -> [TheoryToUnify] -> [TheoryToUnify]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (TheoryToUnify -> Bool) -> TheoryToUnify -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TheoryToUnify -> Bool
isUFun) ([TheoryToUnify]
theories [TheoryToUnify] -> [TheoryToUnify] -> [TheoryToUnify]
forall a. [a] -> [a] -> [a]
++ [[TheoryToUnify]] -> [TheoryToUnify]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[TheoryToUnify]]
funcs)
funcs :: [[TheoryToUnify]]
funcs =
[[TheoryToUnify]] -> [[TheoryToUnify]]
forall a. Eq a => [a] -> [a]
nub ([[TheoryToUnify]] -> [[TheoryToUnify]])
-> [[TheoryToUnify]] -> [[TheoryToUnify]]
forall a b. (a -> b) -> a -> b
$
(TheoryToUnify -> Maybe [TheoryToUnify])
-> [TheoryToUnify] -> [[TheoryToUnify]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe
( \case
UFun [TheoryToUnify]
x -> [TheoryToUnify] -> Maybe [TheoryToUnify]
forall a. a -> Maybe a
Just [TheoryToUnify]
x
TheoryToUnify
_ -> Maybe [TheoryToUnify]
forall a. Maybe a
Nothing
)
[TheoryToUnify]
theories
nonFuncConstraint :: Type -> TheoryToUnify -> f [Type]
nonFuncConstraint Type
mode TheoryToUnify
UInteger =
(Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: []) (Type -> [Type]) -> f Type -> f [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [t|EvalModeInteger $(Type -> f Type
forall a. a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
mode)|]
nonFuncConstraint Type
mode TheoryToUnify
UAlgReal =
(Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: []) (Type -> [Type]) -> f Type -> f [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [t|EvalModeAlgReal $(Type -> f Type
forall a. a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
mode)|]
nonFuncConstraint Type
mode TheoryToUnify
UWordN =
(Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: []) (Type -> [Type]) -> f Type -> f [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [t|EvalModeBV $(Type -> f Type
forall a. a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
mode)|]
nonFuncConstraint Type
mode TheoryToUnify
UFP = (Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: []) (Type -> [Type]) -> f Type -> f [Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [t|EvalModeFP $(Type -> f Type
forall a. a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return Type
mode)|]
nonFuncConstraint Type
_ TheoryToUnify
_ = [Type] -> f [Type]
forall a. a -> f a
forall (m :: * -> *) a. Monad m => a -> m a
return []
genFunConstraint :: m Type -> String -> m Type
genFunConstraint m Type
mode String
name = m Type -> m Type -> m Type
forall (m :: * -> *). Quote m => m Type -> m Type -> m Type
appT (Name -> m Type
forall (m :: * -> *). Quote m => Name -> m Type
conT (String -> Name
mkName String
name)) m Type
mode