module UHC.Light.Compiler.Gam.DataGam
( DataFldMp, DataFldInfo (..), emptyDataFldInfo
, DataConFldAnnInfo (..), emptyDataConFldAnnInfo
, DataTagInfo (..), emptyDataTagInfo, DataConstrTagMp
, DataGamInfo (..)
, DataGam
, mkDGI
, mkDGIPlain
, emptyDataGamInfo, emptyDGI
, dgiDtiOfCon
, dataGamLookup, dataGamLookupErr
, dataGamDgiOfTy
, dtiOffsetOfFld
, DataFldInConstr (..), DataFldInConstrMp
, mkDGIForCodegenOnly
, dataGamDTIsOfTyNm, dataGamDTIsOfTy
, dataGamTagsOfTy, dataGamTagsOfTyNm
, dataGamLookupTag
, dataGamTagLookup
, dgiIsEnumable
, dgiConstrTagAssocL
, DataGamInfoVariant (..)
, dgiMbNewtype, dgiIsNewtype
, dgiIsRec )
where
import UHC.Util.Pretty
import UHC.Util.Utils
import UHC.Light.Compiler.Base.Common
import UHC.Light.Compiler.Base.TermLike
import UHC.Light.Compiler.Base.HsName.Builtin
import UHC.Light.Compiler.Ty
import UHC.Light.Compiler.Ty.Pretty
import UHC.Light.Compiler.Gam
import UHC.Light.Compiler.Error
import qualified Data.Map as Map
import qualified Data.Set as Set
import UHC.Light.Compiler.VarMp
import UHC.Light.Compiler.Substitutable
import UHC.Light.Compiler.Ty.Trf.Quantify
import UHC.Light.Compiler.Base.Debug
import UHC.Util.Pretty
import Control.Monad
import UHC.Util.Binary
import UHC.Util.Serialize
import Data.Maybe
data DataFldInfo
= DataFldInfo
{ dfiOffset :: !Fld
}
deriving Show
type DataFldMp = Map.Map HsName DataFldInfo
emptyDataFldInfo
= DataFldInfo
noFld
data DataConFldAnnInfo
= DataConFldAnnInfo
{ dcfaiStrictness :: !Strictness
}
deriving Show
emptyDataConFldAnnInfo :: DataConFldAnnInfo
emptyDataConFldAnnInfo
= DataConFldAnnInfo
Strictness_NonStrict
data DataTagInfo
= DataTagInfo
{ dtiFldMp :: !DataFldMp
, dtiFldTyL :: !FldTyL
, dtiConFldAnnL :: ![DataConFldAnnInfo]
, dtiConNm :: !HsName
, dtiConTy :: !Ty
, dtiCTag :: !CTag
, dtiFldRefL :: ![Fld]
, dtiMbFixityPrio :: !(Maybe (Int,Fixity))
} deriving Show
type DataConstrTagMp = Map.Map HsName DataTagInfo
emptyDataTagInfo
= DataTagInfo
Map.empty [] [] hsnUnknown (appDbg "emptyDataTagInfo")
emptyCTag []
Nothing
dtiOffsetOfFld :: HsName -> DataTagInfo -> Fld
dtiOffsetOfFld fldNm dti = dfiOffset $ panicJust "dtiOffsetOfFld" $ Map.lookup fldNm $ dtiFldMp dti
data DataFldInConstr
= DataFldInConstr
{ dficInTagMp :: !(Map.Map CTag Fld)
}
type DataFldInConstrMp = Map.Map HsName DataFldInConstr
data DataGamInfoVariant
= DataGamInfoVariant_Plain
| DataGamInfoVariant_Newtype
Ty
| DataGamInfoVariant_Rec
deriving Eq
data DataGamInfo
= DataGamInfo
{ dgiTyNm :: !HsName
, dgiDataTy :: !Ty
, dgiDataKi :: !Ty
, dgiConstrNmL :: ![HsName]
, dgiConstrTagMp :: !DataConstrTagMp
, dgiFldInConstrMp :: !DataFldInConstrMp
, dgiVariant :: !DataGamInfoVariant
, dgiMaxConstrArity :: !Int
, dgiMbGenerInfo :: !(Maybe Int)
}
instance Show DataGamInfo where
show _ = "DataGamInfo"
dgiMbNewtype :: DataGamInfo -> Maybe Ty
dgiMbNewtype (DataGamInfo {dgiVariant = DataGamInfoVariant_Newtype t}) = Just t
dgiMbNewtype _ = Nothing
dgiIsNewtype :: DataGamInfo -> Bool
dgiIsNewtype = isJust . dgiMbNewtype
dgiIsRec :: DataGamInfo -> Bool
dgiIsRec dgi = dgiVariant dgi == DataGamInfoVariant_Rec
type DataGam = Gam HsName DataGamInfo
mkDGI
:: HsName
-> Ty -> Ty -> [HsName] -> DataConstrTagMp -> DataGamInfoVariant
-> Maybe Int
-> DataGamInfo
mkDGI tyNm dty ki cNmL m nt
mbGener
= DataGamInfo
tyNm
dty
ki
cNmL
m'
fm nt mx
mbGener
where fm = Map.map DataFldInConstr $ Map.unionsWith Map.union
$ [ Map.singleton f (Map.singleton (dtiCTag ci) (dfiOffset fi)) | ci <- Map.elems m', (f,fi) <- Map.toList $ dtiFldMp ci ]
mx = maximum
( (if Map.null m then (1) else (ctagMaxArity $ dtiCTag $ head $ Map.elems m))
: [ ctagArity $ dtiCTag dti | dti <- Map.elems m ]
)
m' = Map.map (\dti -> dti {dtiCTag = patchTyInfoCTag tyNm mx $ dtiCTag dti}) m
mkDGIPlain :: HsName -> Ty -> Ty -> [HsName] -> DataConstrTagMp -> DataGamInfo
mkDGIPlain tyNm dty dki cNmL m
= mkDGI tyNm dty dki cNmL m
DataGamInfoVariant_Plain
Nothing
mkDGIForCodegenOnly :: HsName -> DataConstrTagMp -> DataGamInfo
mkDGIForCodegenOnly tyNm m
= mkDGIPlain tyNm Ty_Any Ty_Any (Map.keys m) m
emptyDataGamInfo, emptyDGI :: DataGamInfo
emptyDataGamInfo = mkDGIPlain hsnUnknown (appDbg "emptyDataGamInfo") (appDbg "mkDGIPlain") [] Map.empty
emptyDGI = emptyDataGamInfo
dgiConstrTagAssocL :: DataGamInfo -> AssocL HsName DataTagInfo
dgiConstrTagAssocL dgi = [ (cn,panicJust "dgiConstrTagAssocL" $ Map.lookup cn $ dgiConstrTagMp dgi) | cn <- dgiConstrNmL dgi ]
dgiDtiOfCon :: HsName -> DataGamInfo -> DataTagInfo
dgiDtiOfCon conNm dgi = panicJust "dgiDtiOfCon" $ Map.lookup conNm $ dgiConstrTagMp dgi
dataGamLookup :: HsName -> DataGam -> Maybe DataGamInfo
dataGamLookup nm g
= case gamLookup nm g of
Nothing
| hsnIsProd nm
-> Just emptyDataGamInfo
Just dgi -> Just dgi
_ -> Nothing
dataGamLookupErr :: HsName -> DataGam -> (DataGamInfo,ErrL)
dataGamLookupErr n g
= case dataGamLookup n g of
Nothing -> (emptyDGI,[rngLift emptyRange mkErr_NamesNotIntrod "data" [n]])
Just tgi -> (tgi,[])
dataGamDgiOfTy :: Ty -> DataGam -> Maybe DataGamInfo
dataGamDgiOfTy conTy dg = dataGamLookup (tyAppFunConNm conTy) dg
dataGamDTIsOfTyNm :: HsName -> DataGam -> Maybe [DataTagInfo]
dataGamDTIsOfTyNm tn g
= fmap
(assocLElts . dgiConstrTagAssocL)
$ gamLookup tn
$ g
dataGamDTIsOfTy :: Ty -> DataGam -> Maybe [DataTagInfo]
dataGamDTIsOfTy = dataGamDTIsOfTyNm . tyDataTyNm
dataGamTagsOf :: (t -> DataGam -> Maybe [DataTagInfo]) -> t -> DataGam -> Maybe [CTag]
dataGamTagsOf lkup t g = fmap (map dtiCTag) (lkup t g)
dataGamTagsOfTy :: Ty -> DataGam -> Maybe [CTag]
dataGamTagsOfTy = dataGamTagsOf dataGamDTIsOfTy
dataGamTagsOfTyNm :: HsName -> DataGam -> Maybe [CTag]
dataGamTagsOfTyNm = dataGamTagsOf dataGamDTIsOfTyNm
dataGamLookupTag :: HsName -> HsName -> DataGam -> Maybe CTag
dataGamLookupTag t c g
= do dgi <- dataGamLookup t g
dti <- Map.lookup c $ dgiConstrTagMp dgi
return $ dtiCTag dti
dataGamTagLookup :: TagLike t => t -> DataGam -> Maybe (DataGamInfo,DataTagInfo)
dataGamTagLookup tag g
| tagIsData tag
= do dgi <- dataGamLookup (tagDataTypeNm tag) g
dti <- Map.lookup (tagDataConstrNm tag) $ dgiConstrTagMp dgi
return (dgi,dti)
| otherwise
= Nothing
dgiIsEnumable :: DataGamInfo -> Bool
dgiIsEnumable dgi = dgiMaxConstrArity dgi == 0
deriving instance Typeable DataFldInfo
deriving instance Data DataFldInfo
deriving instance Typeable DataConFldAnnInfo
deriving instance Data DataConFldAnnInfo
deriving instance Typeable DataTagInfo
deriving instance Data DataTagInfo
deriving instance Typeable DataFldInConstr
deriving instance Data DataFldInConstr
deriving instance Typeable DataGamInfo
deriving instance Data DataGamInfo
deriving instance Typeable DataGamInfoVariant
deriving instance Data DataGamInfoVariant
instance Serialize DataGamInfoVariant where
sput (DataGamInfoVariant_Plain ) = sputWord8 0
sput (DataGamInfoVariant_Newtype a) = sputWord8 1 >> sput a
sput (DataGamInfoVariant_Rec ) = sputWord8 2
sget = do
t <- sgetWord8
case t of
0 -> return DataGamInfoVariant_Plain
1 -> liftM DataGamInfoVariant_Newtype sget
2 -> return DataGamInfoVariant_Rec
instance Serialize DataFldInfo where
sput (DataFldInfo a) = sput a
sget = liftM DataFldInfo sget
instance Serialize DataConFldAnnInfo where
sput (DataConFldAnnInfo a) = sput a
sget = liftM DataConFldAnnInfo sget
instance Serialize DataTagInfo where
sput (DataTagInfo a b c d e f g h) = sput a >> sput b >> sput c >> sput d >> sput e >> sput f >> sput g >> sput h
sget = liftM8 DataTagInfo sget sget sget sget sget sget sget sget
instance Serialize DataFldInConstr where
sput (DataFldInConstr a) = sput a
sget = liftM DataFldInConstr sget
instance Serialize DataGamInfo where
sput (DataGamInfo a b c d e f g h i) = sput a >> sput b >> sput c >> sput d >> sput e >> sput f >> sput g >> sput h >> sput i
sget = liftM9 DataGamInfo sget sget sget sget sget sget sget sget sget