module LLVM.Extra.Multi.Iterator (
takeWhile,
countDown,
take,
Enum(..),
) where
import qualified LLVM.Extra.Multi.Value as MultiValue
import qualified LLVM.Extra.Iterator as Iter
import qualified LLVM.Extra.ScalarOrVector as SoV
import qualified LLVM.Extra.MaybePrivate as Maybe
import qualified LLVM.Extra.Arithmetic as A
import qualified LLVM.Extra.Control as C
import LLVM.Extra.Class (undefTuple)
import qualified LLVM.Core as LLVM
import LLVM.Core (CodeGenFunction)
import Control.Applicative (liftA2)
import qualified Data.Enum.Storable as Enum
import qualified Prelude as P
import Prelude hiding (take, takeWhile, Enum, enumFrom, enumFromTo)
takeWhile ::
(a -> CodeGenFunction r (MultiValue.T Bool)) ->
Iter.T r a -> Iter.T r a
takeWhile p = Iter.takeWhile (fmap unpackBool . p)
unpackBool :: MultiValue.T Bool -> LLVM.Value Bool
unpackBool (MultiValue.Cons b) = b
countDown ::
(MultiValue.Additive i, MultiValue.Comparison i,
MultiValue.IntegerConstant i) =>
MultiValue.T i -> Iter.T r (MultiValue.T i)
countDown len =
takeWhile (MultiValue.cmp LLVM.CmpLT MultiValue.zero) $
Iter.iterate MultiValue.dec len
take ::
(MultiValue.Additive i, MultiValue.Comparison i,
MultiValue.IntegerConstant i) =>
MultiValue.T i -> Iter.T r a -> Iter.T r a
take len xs = liftA2 const xs (countDown len)
class Enum a where
succ, pred :: MultiValue.T a -> LLVM.CodeGenFunction r (MultiValue.T a)
enumFrom :: MultiValue.T a -> Iter.T r (MultiValue.T a)
enumFromTo :: MultiValue.T a -> MultiValue.T a -> Iter.T r (MultiValue.T a)
instance
(LLVM.IsInteger w, SoV.IntegerConstant w, Num w,
LLVM.CmpRet w, LLVM.CmpResult w ~ Bool, P.Enum e) =>
Enum (Enum.T w e) where
succ = MultiValue.succ
pred = MultiValue.pred
enumFrom = Iter.iterate MultiValue.succ
enumFromTo from to =
Iter.takeWhileJust $
Iter.iterate (Maybe.maybeArg undefTuple (succMax to)) (Maybe.just from)
succMax ::
(LLVM.IsInteger w, SoV.IntegerConstant w, Num w,
LLVM.CmpRet w, LLVM.CmpResult w ~ Bool, P.Enum e) =>
MultiValue.T (Enum.T w e) ->
MultiValue.T (Enum.T w e) ->
LLVM.CodeGenFunction r (Maybe.T (MultiValue.T (Enum.T w e)))
succMax to e = do
MultiValue.Cons less <- MultiValue.cmpEnum A.CmpLT e to
C.ifThen less (Maybe.nothing undefTuple) $
fmap Maybe.just $ MultiValue.succ e
_enumFromToSimple ::
(LLVM.IsInteger w, SoV.IntegerConstant w, Num w,
LLVM.CmpRet w, LLVM.CmpResult w ~ Bool, P.Enum e) =>
MultiValue.T (Enum.T w e) ->
MultiValue.T (Enum.T w e) ->
Iter.T r (MultiValue.T (Enum.T w e))
_enumFromToSimple from to =
takeWhile (MultiValue.cmpEnum LLVM.CmpGE to) $ enumFrom from