module Data.Singletons.TH.Single.Data
( singDataD
, singCtor
) where
import Language.Haskell.TH.Desugar as Desugar
import Language.Haskell.TH.Syntax
import Data.Maybe
import Data.Singletons.TH.Names
import Data.Singletons.TH.Options
import Data.Singletons.TH.Promote.Type
import Data.Singletons.TH.Single.Defun
import Data.Singletons.TH.Single.Fixity
import Data.Singletons.TH.Single.Monad
import Data.Singletons.TH.Syntax
import Data.Singletons.TH.Util
import Control.Monad
singDataD :: DataDecl -> SgM [DDec]
singDataD :: DataDecl -> SgM [DDec]
singDataD (DataDecl DataFlavor
df Name
name [DTyVarBndrVis]
tvbs [DCon]
ctors) = do
opts <- SgM Options
forall (m :: * -> *). OptionsMonad m => m Options
getOptions
let reqTvbNames = (DTyVarBndrVis -> Name) -> [DTyVarBndrVis] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map DTyVarBndrVis -> Name
forall flag. DTyVarBndr flag -> Name
extractTvbName ([DTyVarBndrVis] -> [Name]) -> [DTyVarBndrVis] -> [Name]
forall a b. (a -> b) -> a -> b
$
(DTyVarBndrVis -> Bool) -> [DTyVarBndrVis] -> [DTyVarBndrVis]
forall a. (a -> Bool) -> [a] -> [a]
filter (\DTyVarBndrVis
tvb -> DTyVarBndrVis -> BndrVis
forall flag. DTyVarBndr flag -> flag
extractTvbFlag DTyVarBndrVis
tvb BndrVis -> BndrVis -> Bool
forall a. Eq a => a -> a -> Bool
== BndrVis
BndrReq) [DTyVarBndrVis]
tvbs
ctor_names = (DCon -> Name) -> [DCon] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map DCon -> Name
extractName [DCon]
ctors
rec_sel_names = (DCon -> [Name]) -> [DCon] -> [Name]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap DCon -> [Name]
extractRecSelNames [DCon]
ctors
k <- promoteType (foldTypeTvbs (DConT name) tvbs)
mb_data_sak <- dsReifyType name
ctors' <- mapM (singCtor name) ctors
fixityDecs <- singReifiedInfixDecls $ ctor_names ++ rec_sel_names
fromSingClauses <- mapM mkFromSingClause ctors
emptyFromSingClause <- mkEmptyFromSingClause
toSingClauses <- mapM mkToSingClause ctors
emptyToSingClause <- mkEmptyToSingClause
let singKindInst =
Maybe Overlap
-> Maybe [DTyVarBndrUnit] -> DCxt -> DKind -> [DDec] -> DDec
DInstanceD Maybe Overlap
forall a. Maybe a
Nothing Maybe [DTyVarBndrUnit]
forall a. Maybe a
Nothing
((Name -> DKind) -> [Name] -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map (DKind -> DKind
singKindConstraint (DKind -> DKind) -> (Name -> DKind) -> Name -> DKind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> DKind
DVarT) [Name]
reqTvbNames)
(DKind -> DKind -> DKind
DAppT (Name -> DKind
DConT Name
singKindClassName) DKind
k)
[ DTySynEqn -> DDec
DTySynInstD (DTySynEqn -> DDec) -> DTySynEqn -> DDec
forall a b. (a -> b) -> a -> b
$ Maybe [DTyVarBndrUnit] -> DKind -> DKind -> DTySynEqn
DTySynEqn Maybe [DTyVarBndrUnit]
forall a. Maybe a
Nothing
(Name -> DKind
DConT Name
demoteName DKind -> DKind -> DKind
`DAppT` DKind
k)
(DKind -> DCxt -> DKind
foldType (Name -> DKind
DConT Name
name)
((Name -> DKind) -> [Name] -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map (DKind -> DKind -> DKind
DAppT DKind
demote (DKind -> DKind) -> (Name -> DKind) -> Name -> DKind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> DKind
DVarT) [Name]
reqTvbNames))
, DLetDec -> DDec
DLetDec (DLetDec -> DDec) -> DLetDec -> DDec
forall a b. (a -> b) -> a -> b
$ Name -> [DClause] -> DLetDec
DFunD Name
fromSingName
([DClause]
fromSingClauses [DClause] -> [DClause] -> [DClause]
forall a. [a] -> [a] -> [a]
`orIfEmpty` [DClause
emptyFromSingClause])
, DLetDec -> DDec
DLetDec (DLetDec -> DDec) -> DLetDec -> DDec
forall a b. (a -> b) -> a -> b
$ Name -> [DClause] -> DLetDec
DFunD Name
toSingName
([DClause]
toSingClauses [DClause] -> [DClause] -> [DClause]
forall a. [a] -> [a] -> [a]
`orIfEmpty` [DClause
emptyToSingClause]) ]
let singDataName = Options -> Name -> Name
singledDataTypeName Options
opts Name
name
singSynInst =
DTySynEqn -> DDec
DTySynInstD (DTySynEqn -> DDec) -> DTySynEqn -> DDec
forall a b. (a -> b) -> a -> b
$ Maybe [DTyVarBndrUnit] -> DKind -> DKind -> DTySynEqn
DTySynEqn Maybe [DTyVarBndrUnit]
forall a. Maybe a
Nothing
(Name -> DKind
DConT Name
singFamilyName DKind -> DKind -> DKind
`DAppKindT` DKind
k)
(Name -> DKind
DConT Name
singDataName)
mk_data_dec DKind
kind =
DataFlavor
-> DCxt
-> Name
-> [DTyVarBndrVis]
-> Maybe DKind
-> [DCon]
-> [DDerivClause]
-> DDec
DDataD DataFlavor
Data [] Name
singDataName [] (DKind -> Maybe DKind
forall a. a -> Maybe a
Just DKind
kind) [DCon]
ctors' []
data_decs <- case mb_data_sak of
Maybe DKind
Nothing -> do
let sing_tvbs :: [DTyVarBndr Specificity]
sing_tvbs = Specificity -> [DTyVarBndrUnit] -> [DTyVarBndr Specificity]
forall newFlag oldFlag.
newFlag -> [DTyVarBndr oldFlag] -> [DTyVarBndr newFlag]
changeDTVFlags Specificity
SpecifiedSpec ([DTyVarBndrUnit] -> [DTyVarBndr Specificity])
-> [DTyVarBndrUnit] -> [DTyVarBndr Specificity]
forall a b. (a -> b) -> a -> b
$
DCxt -> [DTyVarBndrUnit]
toposortTyVarsOf (DCxt -> [DTyVarBndrUnit]) -> DCxt -> [DTyVarBndrUnit]
forall a b. (a -> b) -> a -> b
$ (DTyVarBndrVis -> DKind) -> [DTyVarBndrVis] -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map DTyVarBndrVis -> DKind
forall flag. DTyVarBndr flag -> DKind
dTyVarBndrToDType [DTyVarBndrVis]
tvbs
kinded_sing_ty :: DKind
kinded_sing_ty = DForallTelescope -> DKind -> DKind
DForallT ([DTyVarBndr Specificity] -> DForallTelescope
DForallInvis [DTyVarBndr Specificity]
sing_tvbs) (DKind -> DKind) -> DKind -> DKind
forall a b. (a -> b) -> a -> b
$
DKind
DArrowT DKind -> DKind -> DKind
`DAppT` DKind
k DKind -> DKind -> DKind
`DAppT` Name -> DKind
DConT Name
typeKindName
[DDec] -> SgM [DDec]
forall a. a -> SgM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [DKind -> DDec
mk_data_dec DKind
kinded_sing_ty]
Just DKind
data_sak -> do
sing_data_sak <- DKind -> [DTyVarBndrVis] -> DKind -> SgM DKind
forall (q :: * -> *).
MonadFail q =>
DKind -> [DTyVarBndrVis] -> DKind -> q DKind
singDataSAK DKind
data_sak [DTyVarBndrVis]
tvbs DKind
k
pure [ DKiSigD singDataName sing_data_sak
, mk_data_dec sing_data_sak
]
return $ data_decs ++
singSynInst :
[ singKindInst | genSingKindInsts opts
,
df /= Desugar.TypeData
] ++
fixityDecs
where
mkConName :: Name -> SgM Name
mkConName :: Name -> SgM Name
mkConName
| Name -> String
nameBase Name
name String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== Name -> String
nameBase Name
repName = String -> SgM Name
forall (q :: * -> *). Quasi q => String -> q Name
mkDataName (String -> SgM Name) -> (Name -> String) -> Name -> SgM Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> String
nameBase
| Bool
otherwise = Name -> SgM Name
forall a. a -> SgM a
forall (m :: * -> *) a. Monad m => a -> m a
return
mkFromSingClause :: DCon -> SgM DClause
mkFromSingClause :: DCon -> SgM DClause
mkFromSingClause DCon
c = do
opts <- SgM Options
forall (m :: * -> *). OptionsMonad m => m Options
getOptions
let (cname, numArgs) = extractNameArgs c
cname' <- mkConName cname
varNames <- replicateM numArgs (qNewName "b")
return $ DClause [DConP (singledDataConName opts cname) [] (map DVarP varNames)]
(foldExp
(DConE cname')
(map (DAppE (DVarE fromSingName) . DVarE) varNames))
mkToSingClause :: DCon -> SgM DClause
mkToSingClause :: DCon -> SgM DClause
mkToSingClause (DCon [DTyVarBndr Specificity]
_tvbs DCxt
_cxt Name
cname DConFields
fields DKind
_rty) = do
opts <- SgM Options
forall (m :: * -> *). OptionsMonad m => m Options
getOptions
let types = DConFields -> DCxt
tysOfConFields DConFields
fields
varNames <- mapM (const $ qNewName "b") types
svarNames <- mapM (const $ qNewName "c") types
promoted <- mapM promoteType types
cname' <- mkConName cname
let varPats = (Name -> DKind -> DPat) -> [Name] -> DCxt -> [DPat]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Name -> DKind -> DPat
mkToSingVarPat [Name]
varNames DCxt
promoted
recursiveCalls = (Name -> DKind -> DExp) -> [Name] -> DCxt -> [DExp]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Name -> DKind -> DExp
mkRecursiveCall [Name]
varNames DCxt
promoted
return $
DClause [DConP cname' [] varPats]
(multiCase recursiveCalls
(map (DConP someSingDataName [] . listify . DVarP)
svarNames)
(DAppE (DConE someSingDataName)
(foldExp (DConE (singledDataConName opts cname))
(map DVarE svarNames))))
mkToSingVarPat :: Name -> DKind -> DPat
mkToSingVarPat :: Name -> DKind -> DPat
mkToSingVarPat Name
varName DKind
ki =
DPat -> DKind -> DPat
DSigP (Name -> DPat
DVarP Name
varName) (DKind -> DKind -> DKind
DAppT (Name -> DKind
DConT Name
demoteName) DKind
ki)
mkRecursiveCall :: Name -> DKind -> DExp
mkRecursiveCall :: Name -> DKind -> DExp
mkRecursiveCall Name
var_name DKind
ki =
DExp -> DKind -> DExp
DSigE (DExp -> DExp -> DExp
DAppE (Name -> DExp
DVarE Name
toSingName) (Name -> DExp
DVarE Name
var_name))
(DKind -> DKind -> DKind
DAppT (Name -> DKind
DConT Name
someSingTypeName) DKind
ki)
mkEmptyFromSingClause :: SgM DClause
mkEmptyFromSingClause :: SgM DClause
mkEmptyFromSingClause = do
x <- String -> SgM Name
forall (q :: * -> *). Quasi q => String -> q Name
qNewName String
"x"
pure $ DClause [DVarP x]
$ dCaseE (DVarE x) []
mkEmptyToSingClause :: SgM DClause
mkEmptyToSingClause :: SgM DClause
mkEmptyToSingClause = do
x <- String -> SgM Name
forall (q :: * -> *). Quasi q => String -> q Name
qNewName String
"x"
pure $ DClause [DVarP x]
$ DConE someSingDataName `DAppE` dCaseE (DVarE x) []
singCtor :: Name -> DCon -> SgM DCon
singCtor :: Name -> DCon -> SgM DCon
singCtor Name
dataName (DCon [DTyVarBndr Specificity]
con_tvbs DCxt
cxt Name
name DConFields
fields DKind
rty)
| Bool -> Bool
not (DCxt -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null DCxt
cxt)
= String -> SgM DCon
forall a. String -> SgM a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Singling of constrained constructors not yet supported"
| Bool
otherwise
= do
opts <- SgM Options
forall (m :: * -> *). OptionsMonad m => m Options
getOptions
let types = DConFields -> DCxt
tysOfConFields DConFields
fields
numTypes = DCxt -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length DCxt
types
sName = Options -> Name -> Name
singledDataConName Options
opts Name
name
sCon = Name -> DExp
DConE Name
sName
pCon = Name -> DKind
DConT (Name -> DKind) -> Name -> DKind
forall a b. (a -> b) -> a -> b
$ Options -> Name -> Name
promotedDataTypeOrConName Options
opts Name
name
checkVanillaDType $ ravelVanillaDType con_tvbs [] types rty
indexNames <- mapM (const $ qNewName "n") types
kinds <- mapM promoteType_NC types
rty' <- promoteType_NC rty
let indices = (Name -> DKind) -> [Name] -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map Name -> DKind
DVarT [Name]
indexNames
kindedIndices = (DKind -> DKind -> DKind) -> DCxt -> DCxt -> DCxt
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith DKind -> DKind -> DKind
DSigT DCxt
indices DCxt
kinds
kvbs | [DTyVarBndr Specificity] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [DTyVarBndr Specificity]
con_tvbs
= Specificity -> [DTyVarBndrUnit] -> [DTyVarBndr Specificity]
forall newFlag oldFlag.
newFlag -> [DTyVarBndr oldFlag] -> [DTyVarBndr newFlag]
changeDTVFlags Specificity
SpecifiedSpec (DCxt -> [DTyVarBndrUnit]
toposortTyVarsOf (DCxt
kinds DCxt -> DCxt -> DCxt
forall a. [a] -> [a] -> [a]
++ [DKind
rty'])) [DTyVarBndr Specificity]
-> [DTyVarBndr Specificity] -> [DTyVarBndr Specificity]
forall a. [a] -> [a] -> [a]
++
[DTyVarBndr Specificity]
con_tvbs
| Bool
otherwise
= [DTyVarBndr Specificity]
con_tvbs
all_tvbs = [DTyVarBndr Specificity]
kvbs [DTyVarBndr Specificity]
-> [DTyVarBndr Specificity] -> [DTyVarBndr Specificity]
forall a. [a] -> [a] -> [a]
++ (Name -> DKind -> DTyVarBndr Specificity)
-> [Name] -> DCxt -> [DTyVarBndr Specificity]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Name -> Specificity -> DKind -> DTyVarBndr Specificity
forall flag. Name -> flag -> DKind -> DTyVarBndr flag
`DKindedTV` Specificity
SpecifiedSpec) [Name]
indexNames DCxt
kinds
let mb_SingI_dec :: Int -> Maybe DDec
mb_SingI_dec Int
k
| Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
numTypes
= let take_until_k :: [a] -> [a]
take_until_k = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take (Int
numTypes Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) in
DDec -> Maybe DDec
forall a. a -> Maybe a
Just (DDec -> Maybe DDec) -> DDec -> Maybe DDec
forall a b. (a -> b) -> a -> b
$ Maybe Overlap
-> Maybe [DTyVarBndrUnit] -> DCxt -> DKind -> [DDec] -> DDec
DInstanceD Maybe Overlap
forall a. Maybe a
Nothing Maybe [DTyVarBndrUnit]
forall a. Maybe a
Nothing
((DKind -> DKind) -> DCxt -> DCxt
forall a b. (a -> b) -> [a] -> [b]
map (DKind -> DKind -> DKind
DAppT (Name -> DKind
DConT Name
singIName)) (DCxt -> DCxt
forall {a}. [a] -> [a]
take_until_k DCxt
indices))
(DKind -> DKind -> DKind
DAppT (Name -> DKind
DConT (Int -> Name
mkSingIName Int
k))
(DKind -> DCxt -> DKind
foldType DKind
pCon (DCxt -> DCxt
forall {a}. [a] -> [a]
take_until_k DCxt
kindedIndices)))
[DLetDec -> DDec
DLetDec (DLetDec -> DDec) -> DLetDec -> DDec
forall a b. (a -> b) -> a -> b
$ DPat -> DExp -> DLetDec
DValD (Name -> DPat
DVarP (Int -> Name
mkSingMethName Int
k))
(DExp -> [DExp] -> DExp
foldExp DExp
sCon (Int -> DExp -> [DExp]
forall a. Int -> a -> [a]
replicate (Int
numTypes Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) (Name -> DExp
DVarE Name
singMethName)))]
| Bool
otherwise
= Maybe DDec
forall a. Maybe a
Nothing
emitDecs $ mapMaybe mb_SingI_dec [0, 1, 2]
emitDecs =<< singDefuns name DataName [] (map Just kinds) (Just rty')
conFields <- case fields of
DNormalC Bool
dInfix [DBangType]
bts -> Bool -> [DBangType] -> DConFields
DNormalC Bool
dInfix ([DBangType] -> DConFields) -> SgM [DBangType] -> SgM DConFields
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
(DBangType -> DKind -> SgM DBangType)
-> [DBangType] -> DCxt -> SgM [DBangType]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (\(Bang
b, DKind
_) DKind
index -> Bang -> DKind -> SgM DBangType
mk_bang_type Bang
b DKind
index)
[DBangType]
bts DCxt
indices
DRecC [DVarBangType]
vbts -> Bool -> [DBangType] -> DConFields
DNormalC Bool
False ([DBangType] -> DConFields) -> SgM [DBangType] -> SgM DConFields
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
(DVarBangType -> DKind -> SgM DBangType)
-> [DVarBangType] -> DCxt -> SgM [DBangType]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (\(Name
_, Bang
b, DKind
_) DKind
index -> Bang -> DKind -> SgM DBangType
mk_bang_type Bang
b DKind
index)
[DVarBangType]
vbts DCxt
indices
return $ DCon all_tvbs [] sName conFields
(DConT (singledDataTypeName opts dataName) `DAppT`
(foldType pCon indices `DSigT` rty'))
where
mk_source_unpackedness :: SourceUnpackedness -> SgM SourceUnpackedness
mk_source_unpackedness :: SourceUnpackedness -> SgM SourceUnpackedness
mk_source_unpackedness SourceUnpackedness
su = case SourceUnpackedness
su of
SourceUnpackedness
NoSourceUnpackedness -> SourceUnpackedness -> SgM SourceUnpackedness
forall a. a -> SgM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SourceUnpackedness
su
SourceUnpackedness
SourceNoUnpack -> SourceUnpackedness -> SgM SourceUnpackedness
forall a. a -> SgM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SourceUnpackedness
su
SourceUnpackedness
SourceUnpack -> do
String -> SgM ()
forall (q :: * -> *). Quasi q => String -> q ()
qReportWarning String
"{-# UNPACK #-} pragmas are ignored by `singletons-th`."
SourceUnpackedness -> SgM SourceUnpackedness
forall a. a -> SgM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SourceUnpackedness
NoSourceUnpackedness
mk_bang :: Bang -> SgM Bang
mk_bang :: Bang -> SgM Bang
mk_bang (Bang SourceUnpackedness
su SourceStrictness
ss) = do su' <- SourceUnpackedness -> SgM SourceUnpackedness
mk_source_unpackedness SourceUnpackedness
su
pure $ Bang su' ss
mk_bang_type :: Bang -> DType -> SgM DBangType
mk_bang_type :: Bang -> DKind -> SgM DBangType
mk_bang_type Bang
b DKind
index = do b' <- Bang -> SgM Bang
mk_bang Bang
b
pure (b', DAppT singFamily index)
singDataSAK ::
MonadFail q
=> DKind
-> [DTyVarBndrVis]
-> DKind
-> q DKind
singDataSAK :: forall (q :: * -> *).
MonadFail q =>
DKind -> [DTyVarBndrVis] -> DKind -> q DKind
singDataSAK DKind
data_sak [DTyVarBndrVis]
data_bndrs DKind
data_k = do
sing_sak_tvbs <- DKind -> [DTyVarBndrVis] -> q [DTyVarBndr ForAllTyFlag]
forall (q :: * -> *).
MonadFail q =>
DKind -> [DTyVarBndrVis] -> q [DTyVarBndr ForAllTyFlag]
dMatchUpSAKWithDecl DKind
data_sak [DTyVarBndrVis]
data_bndrs
let sing_sak_tvbs' = [DTyVarBndr ForAllTyFlag] -> [DTyVarBndr Specificity]
dtvbForAllTyFlagsToSpecs [DTyVarBndr ForAllTyFlag]
sing_sak_tvbs
pure $ DForallT (DForallInvis sing_sak_tvbs')
$ DArrowT `DAppT` data_k `DAppT` DConT typeKindName