module DDC.Type.DataDef
( DataDef (..)
, kindOfDataDef
, dataTypeOfDataDef
, dataCtorNamesOfDataDef
, makeDataDefAlg
, makeDataDefAbs
, DataDefs (..)
, DataMode (..)
, emptyDataDefs
, insertDataDef
, unionDataDefs
, fromListDataDefs
, DataType (..)
, kindOfDataType
, lookupModeOfDataType
, DataCtor (..)
, typeOfDataCtor)
where
import DDC.Type.Exp
import DDC.Type.Compounds
import Data.Map (Map)
import qualified Data.Map.Strict as Map
import Data.Maybe
import Control.Monad
import Control.DeepSeq
data DataDef n
= DataDef
{
dataDefTypeName :: !n
, dataDefParams :: ![Bind n]
, dataDefCtors :: !(Maybe [DataCtor n])
, dataDefIsAlgebraic :: Bool }
deriving Show
instance NFData n => NFData (DataDef n) where
rnf !def
= rnf (dataDefTypeName def)
`seq` rnf (dataDefParams def)
`seq` rnf (dataDefCtors def)
`seq` rnf (dataDefIsAlgebraic def)
kindOfDataDef :: DataDef n -> Kind n
kindOfDataDef def
= let ksParam = map typeOfBind $ dataDefParams def
in kFuns ksParam kData
dataTypeOfDataDef :: DataDef n -> Type n
dataTypeOfDataDef def
= let usParam = takeSubstBoundsOfBinds $ dataDefParams def
ksParam = map typeOfBind $ dataDefParams def
tc = TyConBound (UName (dataDefTypeName def))
(kFuns ksParam kData)
in tApps (TCon tc) (map TVar usParam)
dataCtorNamesOfDataDef :: DataDef n -> Maybe [n]
dataCtorNamesOfDataDef def
= case dataDefCtors def of
Nothing -> Nothing
Just ctors -> Just $ map dataCtorName ctors
makeDataDefAlg
:: n
-> [Bind n]
-> Maybe [(n, [Type n])]
-> DataDef n
makeDataDefAlg nData bsParam Nothing
= DataDef
{ dataDefTypeName = nData
, dataDefParams = bsParam
, dataDefCtors = Nothing
, dataDefIsAlgebraic = True }
makeDataDefAlg nData bsParam (Just ntsField)
= let usParam = takeSubstBoundsOfBinds bsParam
ksParam = map typeOfBind bsParam
tc = TyConBound (UName nData)
(kFuns ksParam kData)
tResult = tApps (TCon tc) (map TVar usParam)
ctors = [ DataCtor n tag tsField tResult nData bsParam
| tag <- [0..]
| (n, tsField) <- ntsField]
in DataDef
{ dataDefTypeName = nData
, dataDefParams = bsParam
, dataDefCtors = Just ctors
, dataDefIsAlgebraic = True }
makeDataDefAbs :: n -> [Bind n] -> DataDef n
makeDataDefAbs nData bsParam
= DataDef
{ dataDefTypeName = nData
, dataDefParams = bsParam
, dataDefCtors = Just []
, dataDefIsAlgebraic = False }
data DataDefs n
= DataDefs
{ dataDefsTypes :: !(Map n (DataType n))
, dataDefsCtors :: !(Map n (DataCtor n)) }
deriving Show
data DataMode n
= DataModeSmall ![n]
| DataModeLarge
deriving Show
data DataType n
= DataType
{
dataTypeName :: !n
, dataTypeParams :: ![Bind n]
, dataTypeMode :: !(DataMode n)
, dataTypeIsAlgebraic :: Bool }
deriving Show
data DataCtor n
= DataCtor
{
dataCtorName :: !n
, dataCtorTag :: !Integer
, dataCtorFieldTypes :: ![Type n]
, dataCtorResultType :: !(Type n)
, dataCtorTypeName :: !n
, dataCtorTypeParams :: ![Bind n] }
deriving Show
typeOfDataCtor :: DataCtor n -> Type n
typeOfDataCtor ctor
= let Just t = tFunOfList ( dataCtorFieldTypes ctor
++ [dataCtorResultType ctor] )
in foldr TForall t (dataCtorTypeParams ctor)
instance NFData n => NFData (DataCtor n) where
rnf (DataCtor n t fs tR nT bsParam)
= rnf n `seq` rnf t `seq` rnf fs `seq` rnf tR `seq` rnf nT `seq` rnf bsParam
emptyDataDefs :: DataDefs n
emptyDataDefs
= DataDefs
{ dataDefsTypes = Map.empty
, dataDefsCtors = Map.empty }
insertDataDef :: Ord n => DataDef n -> DataDefs n -> DataDefs n
insertDataDef (DataDef nType bsParam mCtors isAlg) dataDefs
= let defType = DataType
{ dataTypeName = nType
, dataTypeParams = bsParam
, dataTypeMode = defMode
, dataTypeIsAlgebraic = isAlg }
defMode = case mCtors of
Nothing -> DataModeLarge
Just ctors -> DataModeSmall (map dataCtorName ctors)
in dataDefs
{ dataDefsTypes = Map.insert nType defType (dataDefsTypes dataDefs)
, dataDefsCtors = Map.union (dataDefsCtors dataDefs)
$ Map.fromList [(n, def)
| def@(DataCtor n _ _ _ _ _) <- concat $ maybeToList mCtors ]}
unionDataDefs :: Ord n => DataDefs n -> DataDefs n -> DataDefs n
unionDataDefs defs1 defs2
= DataDefs
{ dataDefsTypes = Map.union (dataDefsTypes defs1) (dataDefsTypes defs2)
, dataDefsCtors = Map.union (dataDefsCtors defs1) (dataDefsCtors defs2) }
fromListDataDefs :: Ord n => [DataDef n] -> DataDefs n
fromListDataDefs defs
= foldr insertDataDef emptyDataDefs defs
lookupModeOfDataType :: Ord n => n -> DataDefs n -> Maybe (DataMode n)
lookupModeOfDataType n defs
= liftM dataTypeMode $ Map.lookup n (dataDefsTypes defs)
kindOfDataType :: DataType n -> Kind n
kindOfDataType def
= let ksParam = map typeOfBind $ dataTypeParams def
in kFuns ksParam kData