{-# LANGUAGE TypeFamilies #-}
module LLVM.Extra.MaybePrivate where

import qualified LLVM.Extra.TuplePrivate as Tuple
import qualified LLVM.Extra.Control as C
import LLVM.Extra.Control (ifThenElse, )

import qualified LLVM.Core as LLVM
import LLVM.Core (Value, valueOf, CodeGenFunction, )

import qualified Control.Monad as Monad

import Prelude hiding (map, sequence)


{- |
If @isJust = False@, then @fromJust@ is an @undefTuple@.
-}
data T a = Cons {forall a. T a -> Value Bool
isJust :: Value Bool, forall a. T a -> a
fromJust :: a}


instance Functor T where
   fmap :: forall a b. (a -> b) -> T a -> T b
fmap a -> b
f (Cons Value Bool
b a
a) = Value Bool -> b -> T b
forall a. Value Bool -> a -> T a
Cons Value Bool
b (a -> b
f a
a)

instance (Tuple.Undefined a) => Tuple.Undefined (T a) where
   undef :: T a
undef = Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons Value Bool
forall a. Undefined a => a
Tuple.undef a
forall a. Undefined a => a
Tuple.undef

instance (Tuple.Phi a) => Tuple.Phi (T a) where
   phi :: forall r. BasicBlock -> T a -> CodeGenFunction r (T a)
phi BasicBlock
bb (Cons Value Bool
b a
a) = (Value Bool -> a -> T a)
-> CodeGenFunction r (Value Bool)
-> CodeGenFunction r a
-> CodeGenFunction r (T a)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
Monad.liftM2 Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons (BasicBlock -> Value Bool -> CodeGenFunction r (Value Bool)
forall r.
BasicBlock -> Value Bool -> CodeGenFunction r (Value Bool)
forall a r. Phi a => BasicBlock -> a -> CodeGenFunction r a
Tuple.phi BasicBlock
bb Value Bool
b) (BasicBlock -> a -> CodeGenFunction r a
forall r. BasicBlock -> a -> CodeGenFunction r a
forall a r. Phi a => BasicBlock -> a -> CodeGenFunction r a
Tuple.phi BasicBlock
bb a
a)
   addPhi :: forall r. BasicBlock -> T a -> T a -> CodeGenFunction r ()
addPhi BasicBlock
bb (Cons Value Bool
b0 a
a0) (Cons Value Bool
b1 a
a1) =
      BasicBlock -> Value Bool -> Value Bool -> CodeGenFunction r ()
forall r.
BasicBlock -> Value Bool -> Value Bool -> CodeGenFunction r ()
forall a r. Phi a => BasicBlock -> a -> a -> CodeGenFunction r ()
Tuple.addPhi BasicBlock
bb Value Bool
b0 Value Bool
b1 CodeGenFunction r ()
-> CodeGenFunction r () -> CodeGenFunction r ()
forall a b.
CodeGenFunction r a -> CodeGenFunction r b -> CodeGenFunction r b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> BasicBlock -> a -> a -> CodeGenFunction r ()
forall r. BasicBlock -> a -> a -> CodeGenFunction r ()
forall a r. Phi a => BasicBlock -> a -> a -> CodeGenFunction r ()
Tuple.addPhi BasicBlock
bb a
a0 a
a1


{- |
counterpart to 'maybe'
-}
run ::
   (Tuple.Phi b) =>
   T a ->
   CodeGenFunction r b ->
   (a -> CodeGenFunction r b) ->
   CodeGenFunction r b
run :: forall b a r.
Phi b =>
T a
-> CodeGenFunction r b
-> (a -> CodeGenFunction r b)
-> CodeGenFunction r b
run (Cons Value Bool
b a
a) CodeGenFunction r b
n a -> CodeGenFunction r b
j =
   Value Bool
-> CodeGenFunction r b
-> CodeGenFunction r b
-> CodeGenFunction r b
forall a r.
Phi a =>
Value Bool
-> CodeGenFunction r a
-> CodeGenFunction r a
-> CodeGenFunction r a
ifThenElse Value Bool
b (a -> CodeGenFunction r b
j a
a) CodeGenFunction r b
n

for ::
   T a ->
   (a -> CodeGenFunction r ()) ->
   CodeGenFunction r ()
for :: forall a r.
T a -> (a -> CodeGenFunction r ()) -> CodeGenFunction r ()
for = (T a
 -> CodeGenFunction r ()
 -> (a -> CodeGenFunction r ())
 -> CodeGenFunction r ())
-> CodeGenFunction r ()
-> T a
-> (a -> CodeGenFunction r ())
-> CodeGenFunction r ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip T a
-> CodeGenFunction r ()
-> (a -> CodeGenFunction r ())
-> CodeGenFunction r ()
forall b a r.
Phi b =>
T a
-> CodeGenFunction r b
-> (a -> CodeGenFunction r b)
-> CodeGenFunction r b
run (() -> CodeGenFunction r ()
forall a. a -> CodeGenFunction r a
forall (m :: * -> *) a. Monad m => a -> m a
return ())

{- |
counterpart to 'Data.Maybe.fromMaybe' with swapped arguments
-}
select ::
   (C.Select a) =>
   T a ->
   a ->
   CodeGenFunction r a
select :: forall a r. Select a => T a -> a -> CodeGenFunction r a
select (Cons Value Bool
b a
a) a
d = Value Bool -> a -> a -> CodeGenFunction r a
forall r. Value Bool -> a -> a -> CodeGenFunction r a
forall a r. Select a => Value Bool -> a -> a -> CodeGenFunction r a
C.select Value Bool
b a
a a
d

alternative ::
   (C.Select a) =>
   T a -> T a -> CodeGenFunction r (T a)
alternative :: forall a r. Select a => T a -> T a -> CodeGenFunction r (T a)
alternative (Cons Value Bool
b0 a
a0) (Cons Value Bool
b1 a
a1) =
   (Value Bool -> a -> T a)
-> CodeGenFunction r (Value Bool)
-> CodeGenFunction r a
-> CodeGenFunction r (T a)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
Monad.liftM2 Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons
      (Value Bool
-> Value Bool -> CodeGenFunction r (BinOpValue Value Value Bool)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.or Value Bool
b0 Value Bool
b1)
      (Value Bool -> a -> a -> CodeGenFunction r a
forall r. Value Bool -> a -> a -> CodeGenFunction r a
forall a r. Select a => Value Bool -> a -> a -> CodeGenFunction r a
C.select Value Bool
b0 a
a0 a
a1)


{- |
counterpart to Data.Maybe.HT.toMaybe
-}
fromBool :: Value Bool -> a -> T a
fromBool :: forall a. Value Bool -> a -> T a
fromBool = Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons

toBool :: T a -> (Value Bool, a)
toBool :: forall a. T a -> (Value Bool, a)
toBool (Cons Value Bool
b a
a) = (Value Bool
b,a
a)

just :: a -> T a
just :: forall a. a -> T a
just = Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons (Bool -> Value Bool
forall a. IsConst a => a -> Value a
valueOf Bool
True)

nothing :: a -> T a
nothing :: forall a. a -> T a
nothing a
undef = Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons (Bool -> Value Bool
forall a. IsConst a => a -> Value a
valueOf Bool
False) a
undef

getIsNothing :: T a -> CodeGenFunction r (Value Bool)
getIsNothing :: forall a r. T a -> CodeGenFunction r (Value Bool)
getIsNothing (Cons Value Bool
b a
_a) = Value Bool -> CodeGenFunction r (Value Bool)
forall (value :: * -> *) a r.
(ValueCons value, IsInteger a) =>
value a -> CodeGenFunction r (value a)
LLVM.inv Value Bool
b


lift2 ::
   (a -> b -> c) ->
   T a -> T b -> CodeGenFunction r (T c)
lift2 :: forall a b c r.
(a -> b -> c) -> T a -> T b -> CodeGenFunction r (T c)
lift2 a -> b -> c
f (Cons Value Bool
b0 a
a0) (Cons Value Bool
b1 b
a1) =
   (Value Bool -> T c)
-> CodeGenFunction r (Value Bool) -> CodeGenFunction r (T c)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
Monad.liftM ((Value Bool -> c -> T c) -> c -> Value Bool -> T c
forall a b c. (a -> b -> c) -> b -> a -> c
flip Value Bool -> c -> T c
forall a. Value Bool -> a -> T a
Cons (a -> b -> c
f a
a0 b
a1)) (Value Bool
-> Value Bool -> CodeGenFunction r (BinOpValue Value Value Bool)
forall (value0 :: * -> *) (value1 :: * -> *) a r.
(ValueCons2 value0 value1, IsInteger a) =>
value0 a
-> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)
LLVM.and Value Bool
b0 Value Bool
b1)

sequence :: T (CodeGenFunction r a) -> CodeGenFunction r (T a)
sequence :: forall r a. T (CodeGenFunction r a) -> CodeGenFunction r (T a)
sequence (Cons Value Bool
b0 CodeGenFunction r a
a0) =
   (a -> T a) -> CodeGenFunction r a -> CodeGenFunction r (T a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
Monad.liftM (Value Bool -> a -> T a
forall a. Value Bool -> a -> T a
Cons Value Bool
b0) CodeGenFunction r a
a0

traverse ::
   (a -> CodeGenFunction r b) ->
   T a -> CodeGenFunction r (T b)
traverse :: forall a r b.
(a -> CodeGenFunction r b) -> T a -> CodeGenFunction r (T b)
traverse a -> CodeGenFunction r b
f = T (CodeGenFunction r b) -> CodeGenFunction r (T b)
forall r a. T (CodeGenFunction r a) -> CodeGenFunction r (T a)
sequence (T (CodeGenFunction r b) -> CodeGenFunction r (T b))
-> (T a -> T (CodeGenFunction r b))
-> T a
-> CodeGenFunction r (T b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> CodeGenFunction r b) -> T a -> T (CodeGenFunction r b)
forall a b. (a -> b) -> T a -> T b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> CodeGenFunction r b
f

liftM2 ::
   (a -> b -> CodeGenFunction r c) ->
   T a -> T b -> CodeGenFunction r (T c)
liftM2 :: forall a b r c.
(a -> b -> CodeGenFunction r c)
-> T a -> T b -> CodeGenFunction r (T c)
liftM2 a -> b -> CodeGenFunction r c
f T a
ma T b
mb = CodeGenFunction r (CodeGenFunction r (T c))
-> CodeGenFunction r (T c)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
Monad.join (CodeGenFunction r (CodeGenFunction r (T c))
 -> CodeGenFunction r (T c))
-> CodeGenFunction r (CodeGenFunction r (T c))
-> CodeGenFunction r (T c)
forall a b. (a -> b) -> a -> b
$ (T (CodeGenFunction r c) -> CodeGenFunction r (T c))
-> CodeGenFunction r (T (CodeGenFunction r c))
-> CodeGenFunction r (CodeGenFunction r (T c))
forall a b. (a -> b) -> CodeGenFunction r a -> CodeGenFunction r b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap T (CodeGenFunction r c) -> CodeGenFunction r (T c)
forall r a. T (CodeGenFunction r a) -> CodeGenFunction r (T a)
sequence (CodeGenFunction r (T (CodeGenFunction r c))
 -> CodeGenFunction r (CodeGenFunction r (T c)))
-> CodeGenFunction r (T (CodeGenFunction r c))
-> CodeGenFunction r (CodeGenFunction r (T c))
forall a b. (a -> b) -> a -> b
$ (a -> b -> CodeGenFunction r c)
-> T a -> T b -> CodeGenFunction r (T (CodeGenFunction r c))
forall a b c r.
(a -> b -> c) -> T a -> T b -> CodeGenFunction r (T c)
lift2 a -> b -> CodeGenFunction r c
f T a
ma T b
mb


maybeArg ::
   (Tuple.Phi b) =>
   b ->
   (a -> CodeGenFunction r (T b)) ->
   T a -> CodeGenFunction r (T b)
maybeArg :: forall b a r.
Phi b =>
b
-> (a -> CodeGenFunction r (T b)) -> T a -> CodeGenFunction r (T b)
maybeArg b
undef a -> CodeGenFunction r (T b)
f T a
m = T a
-> CodeGenFunction r (T b)
-> (a -> CodeGenFunction r (T b))
-> CodeGenFunction r (T b)
forall b a r.
Phi b =>
T a
-> CodeGenFunction r b
-> (a -> CodeGenFunction r b)
-> CodeGenFunction r b
run T a
m (T b -> CodeGenFunction r (T b)
forall a. a -> CodeGenFunction r a
forall (m :: * -> *) a. Monad m => a -> m a
return (T b -> CodeGenFunction r (T b)) -> T b -> CodeGenFunction r (T b)
forall a b. (a -> b) -> a -> b
$ b -> T b
forall a. a -> T a
nothing b
undef) a -> CodeGenFunction r (T b)
f