packages feed

synthesizer-llvm-0.2: src/Synthesizer/LLVM/Storable/LazySizeIterator.hs

{-# LANGUAGE ForeignFunctionInterface #-}
module Synthesizer.LLVM.Storable.LazySizeIterator where

import qualified Numeric.NonNegative.Chunky  as Chunky
import qualified Data.StorableVector.Lazy.Pattern as SVP
import qualified Data.StorableVector.Lazy as SVL

import Data.Word (Word32, )

import Foreign.StablePtr (StablePtr, newStablePtr, freeStablePtr, deRefStablePtr, )
import Foreign.Ptr (FunPtr, )
import Data.IORef (IORef, newIORef, readIORef, writeIORef, )
import qualified Data.List.HT as ListHT


newtype T = Cons (IORef [SVL.ChunkSize])

{-
For problems about Storable constraint, see ChunkIterator.
-}
foreign import ccall "&nextSize"
   nextCallBack ::
      FunPtr (StablePtr T -> IO Word32)

foreign export ccall "nextSize"
   next :: StablePtr T -> IO Word32


new ::
   SVP.LazySize -> IO (StablePtr T)
new ls =
   newStablePtr . Cons =<< newIORef (Chunky.toChunks (Chunky.normalize ls))

dispose ::
   StablePtr T -> IO ()
dispose = freeStablePtr

{- |
Zero pieces are filtered out.
If 'next' returns 0 then the end of the lazy size is reached.
-}
next ::
   StablePtr T -> IO Word32
next stable =
   deRefStablePtr stable >>= \state ->
   case state of
      Cons listRef ->
         readIORef listRef >>=
         ListHT.switchL
            (return 0)
            (\(SVL.ChunkSize time) xs ->
               writeIORef listRef xs >>
               return (fromIntegral time))