packages feed

Allure-0.4.2: src/Kind.hs

module Kind
  ( Id, Kind.getKind, getId, frequency, foldrWithKey, boundsId
  , Array, (!), (//), listArray, bounds
  ) where

import Data.Binary
import qualified Data.List as L
import qualified Data.IntMap as IM
import qualified Data.Word as Word
import qualified Data.Array.Unboxed as A
import qualified Data.Ix as Ix

import Utils.Assert
import Content.Content
import Frequency

newtype Id a = Id{kindId :: Word8} deriving (Show, Eq, Ord, Ix.Ix)

instance Binary (Id a) where
  put (Id i) = put i
  get = fmap Id get

getKind :: Content a => Id a -> a
getKind (Id i) = kindMap IM.! (fromEnum i)

getId :: Content a => (a -> Bool) -> Id a
getId f = case [Id i | (i, k) <- kindAssocs, f k] of
            [i] -> i
            l -> assert `failure` l

frequency :: Content a => Frequency (Id a, a)
frequency = Frequency [(getFreq k, (Id i, k)) | (i, k) <- kindAssocs]

foldrWithKey :: Content a => (Id a -> a -> b -> b) -> b -> b
foldrWithKey f z = L.foldr (\ (i, a) -> f (Id i) a) z kindAssocs

limitsId :: Content a => ((Id a, a), (Id a, a))
limitsId = let (i1, a1) = IM.findMin kindMap
               (i2, a2) = IM.findMax kindMap
           in ((Id (toEnum i1), a1), (Id (toEnum i2), a2))

boundsId :: Content a => (Id a, Id a)
boundsId = (Id 0, (fst . snd) limitsId)

newtype Array i c = Array{_kindArray :: A.UArray i Word.Word8} deriving Show

-- TODO: save/restore is still too slow, but we are already past
-- the point of diminishing returns. A dramatic change would be
-- low-level conversion to ByteString and serializing that.
instance (Ix.Ix i, Binary i) => Binary (Array i c) where
  put (Array a) = put a
  get = fmap Array get

(!) :: Ix.Ix i => Array i c -> i -> Id c
(!) (Array a) i = Id $ a A.! i

(//) :: Ix.Ix i => Array i c -> [(i, Id c)] -> Array i c
(//) (Array a) l = Array $ a A.// [(i, kindId e) | (i, e) <- l]

listArray :: Ix.Ix i => (i, i) -> [Id c] -> Array i c
listArray bds l = Array $ A.listArray bds [(kindId e) | e <- l]

bounds :: Ix.Ix i => Array i c -> (i, i)
bounds (Array a) = A.bounds a