module UHC.Light.Compiler.Gam.DataGam
( DataFldMp, DataFldInfo (..), emptyDataFldInfo
, DataConFldAnnInfo (..), emptyDataConFldAnnInfo
, DataTagInfo (..), emptyDataTagInfo, DataConstrTagMp
, fldTyLEnsureLabels, mkFldRefAndMp
, 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 Control.Applicative ((<|>))
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Maybe
import UHC.Light.Compiler.VarMp
import UHC.Light.Compiler.Substitutable
import UHC.Light.Compiler.Ty.Trf.Quantify
import UHC.Light.Compiler.CodeGen.RefGenerator
import Control.Monad
import UHC.Util.Binary
import UHC.Util.Serialize
data DataFldInfo
= DataFldInfo
{ dfiOffset :: !Fld
}
instance Show DataFldInfo where
show i = show (dfiOffset i)
instance PP DataFldInfo where
pp = pp . 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))
}
instance Show DataTagInfo where
show _ = "DataTagInfo"
instance PP DataTagInfo where
pp i = dtiConNm i >-< indent 2 (
"flds=" >#< ppCommas [n >#< ppTy t | (n,t) <- dtiFldTyL i]
>-< "fldmp=" >#< ppCommas [n >#< t | (n,t) <- Map.toList $ dtiFldMp i]
>-< "fldrefs=" >#< ppCommas (dtiFldRefL i)
>-< "conty=" >#< ppTy (dtiConTy i)
)
type DataConstrTagMp = Map.Map HsName DataTagInfo
emptyDataTagInfo
= DataTagInfo
Map.empty [] [] hsnUnknown (appDbg "emptyDataTagInfo")
emptyCTag []
Nothing
fldTyLEnsureLabels :: FldTyL -> FldTyL
fldTyLEnsureLabels = zipWith (\pn (ml,t) -> (ml <|> Just pn, t)) positionalFldNames
mkFldRefAndMp :: FldTyL -> (DataFldMp, FldTyL, AssocL HsName Fld)
mkFldRefAndMp fldTyL = (fldMp, fldTyL', fldRefL)
where fldTyL' = fldTyLEnsureLabels fldTyL
fldRefL = refGen 0 1 [ n | (Just n, _) <- fldTyL' ]
fldMp = Map.fromList $ catMaybes $ zipWith (\(_,r) (ml,_) -> fmap (\l -> (l,emptyDataFldInfo {dfiOffset = r})) ml) fldRefL fldTyL
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"
instance PP DataGamInfo where
pp i@(DataGamInfo {dgiTyNm=nm, dgiDataTy=sumprod, dgiDataKi=ki}) = nm >-< indent 2 (
"sumprod=" >#< ppTy sumprod
>-< "ki=" >#< ppTy ki
>-< "constrnms=" >#< ppCommas (dgiConstrNmL i)
>-< "constrmp=" >#< vlist (Map.toList $ dgiConstrTagMp i)
)
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 Typeable DataConFldAnnInfo
deriving instance Typeable DataTagInfo
deriving instance Typeable DataFldInConstr
deriving instance Typeable DataGamInfo
deriving instance Typeable 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