{-# language Safe #-}

module D10.Safe.Splices
    (
    -- * Splice expressions
      d10ListExp
    -- * Splice patterns
    , d10ListPat
    ) where

import D10.Safe.Conversions (strD10ListFail)

import Control.Monad ((>=>))
import Language.Haskell.TH.Syntax (Exp (..), Pat (..), Q, dataToExpQ, dataToPatQ)

-- | Produces an expression of type @['D10']@ that can be used
-- in a Template Haskell splice.
--
-- >>> $(d10ListExp "")
-- []
--
-- >>> $(d10ListExp "5")
-- [D5]
--
-- >>> $(d10ListExp "58")
-- [D5,D8]
--
-- >>> $(d10ListExp "a")
-- ...
-- ... d10 must be between 0 and 9
-- ...
--
-- You may also be interested in 'D10.Safe.Quotes.d10list',
-- a quasi-quoter which does something similar.

d10ListExp :: String -> Q Exp
d10ListExp :: String -> Q Exp
d10ListExp = String -> Q [D10]
forall (m :: * -> *). MonadFail m => String -> m [D10]
strD10ListFail (String -> Q [D10]) -> ([D10] -> Q Exp) -> String -> Q Exp
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> (forall b. Data b => b -> Maybe (Q Exp)) -> [D10] -> Q Exp
forall a.
Data a =>
(forall b. Data b => b -> Maybe (Q Exp)) -> a -> Q Exp
dataToExpQ (Maybe (Q Exp) -> b -> Maybe (Q Exp)
forall a b. a -> b -> a
const Maybe (Q Exp)
forall a. Maybe a
Nothing)

---------------------------------------------------

-- | Produces a pattern that can be used in a splice
-- to match a particular list of 'D10' values.
--
-- >>> :{
--       case [D5, D6] of
--         $(d10ListPat "42") -> "A"
--         $(d10ListPat "56") -> "B"
--         _                  -> "C"
-- >>> :}
-- "B"
--
-- You may also be interested in 'D10.Safe.Quotes.d10list',
-- a quasi-quoter which does something similar.

d10ListPat :: String -> Q Pat
d10ListPat :: String -> Q Pat
d10ListPat = String -> Q [D10]
forall (m :: * -> *). MonadFail m => String -> m [D10]
strD10ListFail (String -> Q [D10]) -> ([D10] -> Q Pat) -> String -> Q Pat
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> \[D10]
xs ->
  do
    [Pat]
pats <- (D10 -> Q Pat) -> [D10] -> Q [Pat]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((forall b. Data b => b -> Maybe (Q Pat)) -> D10 -> Q Pat
forall a.
Data a =>
(forall b. Data b => b -> Maybe (Q Pat)) -> a -> Q Pat
dataToPatQ (Maybe (Q Pat) -> b -> Maybe (Q Pat)
forall a b. a -> b -> a
const Maybe (Q Pat)
forall a. Maybe a
Nothing)) [D10]
xs
    Pat -> Q Pat
forall (m :: * -> *) a. Monad m => a -> m a
return ([Pat] -> Pat
ListP [Pat]
pats)