module UHC.Light.Compiler.Base.UID
( mkNewLevUID, mkNewLevUID2, mkNewLevUID3, mkNewLevUID4, mkNewLevUID5, mkNewLevUID6, mkNewLevUID7, mkNewLevUID8, uidNext, mkNewUID, mkNewUIDL, uidNull, uidChild, mkInfNewUIDL
, FreshUidT, FreshUid, runFreshUidT, runFreshUid, evalFreshUid
, MonadFreshUID (..)
, UID (..)
, mkUID
, uidFromInt
, uidStart, uidUnused
, nextUnique
, UIDS
, mkNewLevUIDL, mkInfNewLevUIDL
, showUIDParseable, ppUIDParseable
, uidSimplifications )
where
import UHC.Util.Pretty
import qualified Data.Set as Set
import Data.List
import Control.Monad.State
import Control.Monad.Identity
import Control.Monad
import UHC.Util.Binary as B
import UHC.Util.Serialize
import Data.Hashable
type FreshUidT m = StateT UID m
type FreshUid = FreshUidT Identity
runFreshUidT :: Monad m => FreshUidT m a -> UID -> m (a,UID)
runFreshUidT f u = runStateT f u
runFreshUid :: FreshUid a -> UID -> (a,UID)
runFreshUid f u = runIdentity $ runFreshUidT f u
evalFreshUid :: FreshUid a -> UID -> a
evalFreshUid f u = fst $ runIdentity $ runFreshUidT f u
class Monad m => MonadFreshUID m where
freshUID :: m UID
freshUID = freshInfUID
freshInfUID :: m UID
freshInfUID = freshUID
instance Monad m => MonadFreshUID (FreshUidT m) where
freshUID = state $ \x -> (x, uidNext x)
freshInfUID = state $ \x -> (uidChild x, uidNext x)
data UID = UID { uidHash :: !Int, uidInts :: ![Int] }
deriving (Eq,Ord)
mkUID :: [Int] -> UID
mkUID is = UID (hash is) is
type UIDL = [UID]
type UIDS = Set.Set UID
instance Show UID where
show uid = concat . intersperse "_" . map show . reverse $ uidInts uid
instance Hashable UID where
hashWithSalt salt (UID h _) = salt `hashWithSalt` h
uidNext :: UID -> UID
uidNext (UID _ (n:ns)) = mkUID (n+1:ns)
uidChild :: UID -> UID
uidChild (UID _ ns) = mkUID (0:ns)
mkNewLevUID :: UID -> (UID,UID)
mkNewLevUID u = (uidNext u, uidChild u)
uidFromInt :: Int -> UID
uidFromInt i = mkUID [i]
uidStart :: UID
uidStart = uidFromInt 0
uidUnused :: UID
uidUnused = uidFromInt (1)
mkNewLevUID2 u = let { (u',u1) = mkNewLevUID u; (u'',u2) = mkNewLevUID u'} in (u'',u1,u2)
mkNewLevUID3 u = let { (u',u1,u2) = mkNewLevUID2 u; (u'',u3) = mkNewLevUID u'} in (u'',u1,u2,u3)
mkNewLevUID4 u = let { (u',u1,u2) = mkNewLevUID2 u; (u'',u3,u4) = mkNewLevUID2 u'} in (u'',u1,u2,u3,u4)
mkNewLevUID5 u = let { (u',u1,u2) = mkNewLevUID2 u; (u'',u3,u4,u5) = mkNewLevUID3 u'} in (u'',u1,u2,u3,u4,u5)
mkNewLevUID6 u = let { (u',u1,u2,u3) = mkNewLevUID3 u; (u'',u4,u5,u6) = mkNewLevUID3 u'} in (u'',u1,u2,u3,u4,u5,u6)
mkNewLevUID7 u = let { (u',u1,u2,u3,u4) = mkNewLevUID4 u; (u'',u5,u6,u7) = mkNewLevUID3 u'} in (u'',u1,u2,u3,u4,u5,u6,u7)
mkNewLevUID8 u = let { (u',u1,u2,u3,u4) = mkNewLevUID4 u; (u'',u5,u6,u7,u8) = mkNewLevUID4 u'} in (u'',u1,u2,u3,u4,u5,u6,u7,u8)
uidNull :: UID
uidNull = mkUID []
mkNewUID :: UID -> (UID,UID)
mkNewUID uid = (uidNext uid,uid)
mkInfNewUIDL' :: (UID -> (UID,UID)) -> UID -> [UID]
mkInfNewUIDL' mk uid
= let l = drop 1 $ iterate (\(nxt,uid) -> mk nxt) $ mkNewUID uid
in map snd l
mkNewUIDL' :: (UID -> (UID,UID)) -> Int -> UID -> [UID]
mkNewUIDL' mk sz uid
= take sz (mkInfNewUIDL' mk uid)
mkNewUIDL :: Int -> UID -> [UID]
mkNewUIDL = mkNewUIDL' mkNewUID
mkInfNewUIDL :: UID -> [UID]
mkInfNewUIDL = mkInfNewUIDL' mkNewUID
instance PP UID where
pp = text . show
showUIDParseable :: UID -> String
showUIDParseable uid = "`{" ++ (concat $ intersperse "," $ map show $ uidInts uid) ++ "}"
ppUIDParseable :: UID -> PP_Doc
ppUIDParseable = pp . showUIDParseable
mkInfNewLevUIDL :: UID -> [UID]
mkInfNewLevUIDL = mkInfNewUIDL' mkNewLevUID
mkNewLevUIDL :: Int -> UID -> [UID]
mkNewLevUIDL = mkNewUIDL' mkNewLevUID
uidSimplifications :: UID -> [UID]
uidSimplifications = map (mkUID . reverse) . drop 1 . init . inits . reverse . uidInts
nextUnique = mkNewLevUID
deriving instance Typeable UID
deriving instance Data UID
instance Binary UID where
put (UID a b) = B.put a >> B.put b
get = liftM2 UID B.get B.get
instance Serialize UID where
sput = sputShared
sget = sgetShared
sputNested = sputPlain
sgetNested = sgetPlain