grisette-0.13.0.1: src/Grisette/Internal/TH/Derivation/DeriveUnifiedSymOrd.hs
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Unused LANGUAGE pragma" #-}
-- |
-- Module : Grisette.Internal.TH.Derivation.DeriveUnifiedSymOrd
-- Copyright : (c) Sirui Lu 2024
-- License : BSD-3-Clause (see the LICENSE file)
--
-- Maintainer : siruilu@cs.washington.edu
-- Stability : Experimental
-- Portability : GHC only
module Grisette.Internal.TH.Derivation.DeriveUnifiedSymOrd
( deriveUnifiedSymOrd,
deriveUnifiedSymOrd1,
deriveUnifiedSymOrd2,
)
where
import Grisette.Internal.Internal.Decl.Unified.Class.UnifiedSymOrd
( UnifiedSymOrd (withBaseSymOrd),
UnifiedSymOrd1 (withBaseSymOrd1),
UnifiedSymOrd2 (withBaseSymOrd2),
)
import Grisette.Internal.TH.Derivation.Common (DeriveConfig (evalModeConfig))
import Grisette.Internal.TH.Derivation.UnaryOpCommon
( UnaryOpClassConfig
( UnaryOpClassConfig,
unaryOpAllowExistential,
unaryOpConfigs,
unaryOpContextNames,
unaryOpExtraVars,
unaryOpInstanceNames,
unaryOpInstanceTypeFromConfig
),
UnaryOpConfig (UnaryOpConfig),
genUnaryOpClass,
)
import Grisette.Internal.TH.Derivation.UnifiedOpCommon
( UnaryOpUnifiedConfig (UnaryOpUnifiedConfig, unifiedFun),
defaultUnaryOpUnifiedFun,
)
import Grisette.Internal.Unified.EvalModeTag (EvalModeTag)
import Language.Haskell.TH
( Dec,
Name,
Q,
Type (ConT, VarT),
appT,
conT,
newName,
)
unifiedSymOrdConfig :: UnaryOpClassConfig
unifiedSymOrdConfig =
UnaryOpClassConfig
{ unaryOpConfigs =
[ UnaryOpConfig
UnaryOpUnifiedConfig
{ unifiedFun =
defaultUnaryOpUnifiedFun
['withBaseSymOrd, 'withBaseSymOrd1, 'withBaseSymOrd2]
}
['withBaseSymOrd, 'withBaseSymOrd1, 'withBaseSymOrd2]
],
unaryOpInstanceNames = [''UnifiedSymOrd, ''UnifiedSymOrd1, ''UnifiedSymOrd2],
unaryOpExtraVars = \config -> do
let modeConfigs = evalModeConfig config
case modeConfigs of
[] -> do
nm <- newName "mode"
return [(VarT nm, ConT ''EvalModeTag)]
[_] -> return []
_ -> fail "UnifiedSymOrd does not support multiple evaluation modes",
unaryOpInstanceTypeFromConfig =
\config newModeVars keptNewVars con -> do
let modeConfigs = evalModeConfig config
modeVar <- case modeConfigs of
[] -> return $ head newModeVars
[(i, _)] -> do
if i >= length keptNewVars
then fail "UnifiedSymOrd reference to a non-existent mode variable"
else return $ keptNewVars !! i
_ -> fail "UnifiedSymOrd does not support multiple evaluation modes"
appT (conT con) (return $ fst modeVar),
unaryOpAllowExistential = True,
unaryOpContextNames = Nothing
}
-- | Derive 'UnifiedSymOrd' instance for a data type.
deriveUnifiedSymOrd :: DeriveConfig -> Name -> Q [Dec]
deriveUnifiedSymOrd deriveConfig =
genUnaryOpClass deriveConfig unifiedSymOrdConfig 0
-- | Derive 'UnifiedSymOrd1' instance for a data type.
deriveUnifiedSymOrd1 :: DeriveConfig -> Name -> Q [Dec]
deriveUnifiedSymOrd1 deriveConfig =
genUnaryOpClass deriveConfig unifiedSymOrdConfig 1
-- | Derive 'UnifiedSymOrd2' instance for a data type.
deriveUnifiedSymOrd2 :: DeriveConfig -> Name -> Q [Dec]
deriveUnifiedSymOrd2 deriveConfig =
genUnaryOpClass deriveConfig unifiedSymOrdConfig 2