module Data.LookupTable (generateLUT) where
import Control.Applicative
import Control.Monad.Primitive
import Data.Word
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import GHC.Ptr
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
toWord8s :: Storable a => a -> IO [Word8]
toWord8s x = alloca $ \ptr -> do
poke ptr x
mapM (peekElemOff (castPtr ptr)) [0 .. sizeOf x 1]
lookupTable :: (Bounded a, Enum a, Storable b) => (a -> b) -> Q Exp
lookupTable f = do
word8ss <- runIO (mapM (toWord8s . f) [minBound .. maxBound])
litE (stringPrimL (concat word8ss))
generateLUT :: (Bounded a, Enum a, Storable b) => (a -> b) -> Q (TExp (a -> b))
generateLUT f =
TExp <$> [| \a -> unsafeInlineIO (peekElemOff (Ptr $(lookupTable f)) (fromEnum a fromEnum (minBound `asTypeOf` a))) |]