{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module LLVM.DSL.Expression.Maybe (
   T(Cons),
   select,
   ) where

import qualified LLVM.DSL.Expression as Expr
import LLVM.DSL.Expression (Exp)

import qualified LLVM.Extra.Multi.Value as MultiValue
import qualified LLVM.Extra.Maybe as Maybe

import qualified LLVM.Core as LLVM

import qualified Control.Monad.HT as Monad


data T a = Cons (Exp Bool) a


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


instance (Expr.Aggregate exp mv) => Expr.Aggregate (T exp) (Maybe.T mv) where
   type MultiValuesOf (T exp) = Maybe.T (Expr.MultiValuesOf exp)
   type ExpressionsOf (Maybe.T mv) = T (Expr.ExpressionsOf mv)
   bundle :: forall r. T exp -> CodeGenFunction r (T mv)
bundle (Cons Exp Bool
b exp
a) =
      (Value Bool -> mv -> T mv)
-> CodeGenFunction r (Value Bool)
-> CodeGenFunction r mv
-> CodeGenFunction r (T mv)
forall (m :: * -> *) a b r.
Monad m =>
(a -> b -> r) -> m a -> m b -> m r
Monad.lift2 Value Bool -> mv -> T mv
forall a. Value Bool -> a -> T a
Maybe.Cons ((T Bool -> Value Bool)
-> CodeGenFunction r (T Bool) -> CodeGenFunction r (Value Bool)
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 Bool -> Value Bool
unbool (CodeGenFunction r (T Bool) -> CodeGenFunction r (Value Bool))
-> CodeGenFunction r (T Bool) -> CodeGenFunction r (Value Bool)
forall a b. (a -> b) -> a -> b
$ Exp Bool -> CodeGenFunction r (T Bool)
forall r. Exp Bool -> CodeGenFunction r (T Bool)
forall exp mv r. Aggregate exp mv => exp -> CodeGenFunction r mv
Expr.bundle Exp Bool
b) (exp -> CodeGenFunction r mv
forall r. exp -> CodeGenFunction r mv
forall exp mv r. Aggregate exp mv => exp -> CodeGenFunction r mv
Expr.bundle exp
a)
   dissect :: T mv -> T exp
dissect (Maybe.Cons Value Bool
b mv
a) =
      Exp Bool -> exp -> T exp
forall a. Exp Bool -> a -> T a
Cons (T Bool -> Exp Bool
forall exp mv. Aggregate exp mv => mv -> exp
Expr.dissect (Repr Bool -> T Bool
forall a. Repr a -> T a
MultiValue.Cons Repr Bool
Value Bool
b)) (mv -> exp
forall exp mv. Aggregate exp mv => mv -> exp
Expr.dissect mv
a)

unbool :: MultiValue.T Bool -> LLVM.Value Bool
unbool :: T Bool -> Value Bool
unbool (MultiValue.Cons Repr Bool
b) = Repr Bool
Value Bool
b