{-# language Safe #-}

module D10.Char.Quotes where

import D10.Char.Conversions
import D10.Char.Splices

import Control.Monad ((>=>))
import Control.Monad.Fail (MonadFail (fail))
import Language.Haskell.TH.Quote (QuasiQuoter (..))
import Prelude hiding (fail)

-- | A single base-10 digit.
--
-- This quasi-quoter, when used as an expression, produces a
-- value of type 'D10'.
--
-- >>> d10Nat [d10|5|]
-- 5
--
-- >>> d10Nat [d10|a|]
-- ...
-- ... d10 must be between 0 and 9
-- ...
--
-- >>> d10Nat [d10|58|]
-- ...
-- ... d10 must be a single character
-- ...
--
-- This quasi-quoter can also be used as a pattern.
--
-- >>> :{
--       case (charD10Maybe '5') of
--         Just [d10|4|] -> "A"
--         Just [d10|5|] -> "B"
--         _             -> "C"
-- >>> :}
-- "B"
--
-- >>> :{
--       case (charD10Maybe '5') of
--         Just [d10|x|] -> "A"
--         Just [d10|5|] -> "B"
--         _             -> "C"
-- >>> :}
-- ...
-- ... d10 must be between 0 and 9
-- ...

d10 :: QuasiQuoter
d10 :: QuasiQuoter
d10 = QuasiQuoter :: (String -> Q Exp)
-> (String -> Q Pat)
-> (String -> Q Type)
-> (String -> Q [Dec])
-> QuasiQuoter
QuasiQuoter
    { quoteExp :: String -> Q Exp
quoteExp  = String -> Q D10
forall (m :: * -> *). MonadFail m => String -> m D10
strD10Fail (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
>=> (Integer -> Q Exp
d10Exp (Integer -> Q Exp) -> (D10 -> Integer) -> D10 -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. D10 -> Integer
d10Integer)
    , quotePat :: String -> Q Pat
quotePat  = String -> Q D10
forall (m :: * -> *). MonadFail m => String -> m D10
strD10Fail (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
>=> (Integer -> Q Pat
d10Pat (Integer -> Q Pat) -> (D10 -> Integer) -> D10 -> Q Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. D10 -> Integer
d10Integer)
    , quoteType :: String -> Q Type
quoteType = \String
_ -> String -> Q Type
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"d10 cannot be used in a type context"
    , quoteDec :: String -> Q [Dec]
quoteDec  = \String
_ -> String -> Q [Dec]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"d10 cannot be used in a declaration context"
    }

-- | A list of base-10 digits.
--
-- This quasi-quoter, when used as an expression, produces a
-- value of type @['D10']@.
--
-- >>> d10Nat <$> [d10list||]
-- []
--
-- >>> d10Nat <$> [d10list|5|]
-- [5]
--
-- >>> d10Nat <$> [d10list|58|]
-- [5,8]
--
-- >>> d10Nat <$> [d10list|a|]
-- ...
-- ... d10 must be between 0 and 9
-- ...
--
-- This quasi-quoter can also be used as a pattern.
--
-- >>> :{
--       case [d10list|56|] of
--         [d10list|41|] -> "A"
--         [d10list|56|] -> "B"
--         _             -> "C"
-- >>> :}
-- "B"
--
-- >>> :{
--       case [d10list|56|] of
--         [d10list|4x|] -> "A"
--         [d10list|56|] -> "B"
--         _             -> "C"
-- >>> :}
-- ...
-- ... d10 must be between 0 and 9
-- ...

d10list :: QuasiQuoter
d10list :: QuasiQuoter
d10list = QuasiQuoter :: (String -> Q Exp)
-> (String -> Q Pat)
-> (String -> Q Type)
-> (String -> Q [Dec])
-> QuasiQuoter
QuasiQuoter
    { quoteExp :: String -> Q Exp
quoteExp  = String -> Q Exp
d10ListExp
    , quotePat :: String -> Q Pat
quotePat  = String -> Q Pat
d10ListPat
    , quoteType :: String -> Q Type
quoteType = \String
_ -> String -> Q Type
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"d10list cannot be used in a type context"
    , quoteDec :: String -> Q [Dec]
quoteDec  = \String
_ -> String -> Q [Dec]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"d10list cannot be used in a declaration context"
    }