-- | Functions to help handle LLVM iteration patterns
module LLVM.Internal.FFI.Iterate where

import LLVM.Prelude

import Foreign.Ptr

-- | retrieve a sequence of objects which form a linked list, given an action to
-- | retrieve the first member and an action to proceed through the list
getXs :: IO (Ptr a) -> (Ptr a -> IO (Ptr a)) -> IO [Ptr a]
getXs :: IO (Ptr a) -> (Ptr a -> IO (Ptr a)) -> IO [Ptr a]
getXs firstX :: IO (Ptr a)
firstX nextX :: Ptr a -> IO (Ptr a)
nextX = Ptr a -> IO [Ptr a]
walk (Ptr a -> IO [Ptr a]) -> IO (Ptr a) -> IO [Ptr a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Ptr a)
firstX
    where walk :: Ptr a -> IO [Ptr a]
walk x :: Ptr a
x | Ptr a
x Ptr a -> Ptr a -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr a
forall a. Ptr a
nullPtr = [Ptr a] -> IO [Ptr a]
forall (m :: * -> *) a. Monad m => a -> m a
return []
          walk x :: Ptr a
x = (Ptr a
xPtr a -> [Ptr a] -> [Ptr a]
forall a. a -> [a] -> [a]
:) ([Ptr a] -> [Ptr a]) -> IO [Ptr a] -> IO [Ptr a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr a -> IO [Ptr a]
walk (Ptr a -> IO [Ptr a])
-> (Ptr a -> IO (Ptr a)) -> Ptr a -> IO [Ptr a]
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Ptr a -> IO (Ptr a)
nextX) Ptr a
x