{-# LANGUAGE Safe #-}
{-# LANGUAGE CPP #-}

module Language.Haskell.TH.QuasiQuoter
  ( QuasiQuoter (QuasiQuoter, quoteExp, quotePat, quoteType, quoteDec)
  , namedDefaultQuasiQuoter
  , defaultQuasiQuoter
  , Q
  , Exp
  , Pat
  , Type
  , Dec
  ) where

#if __GLASGOW_HASKELL__ >= 912
import GHC.Internal.TH.Quote (QuasiQuoter(..))
import GHC.Internal.TH.Syntax
#else
import Language.Haskell.TH.Quote (QuasiQuoter(..))
import Language.Haskell.TH.Syntax (Exp, Q, Pat, Type, Dec)
#endif
#if __GLASGOW_HASKELL__ >= 915
import GHC.Internal.TH.Monad
#endif

-- | A t'QuasiQuoter' that fails with a helpful error message in every
-- context. It is intended to be modified to create a t'QuasiQuoter' that
-- fails in all inappropriate contexts.
--
-- For example, you could write
--
-- @
-- myPatQQ = (namedDefaultQuasiQuoter "myPatQQ")
--   { quotePat = ... }
-- @
--
-- If @myPatQQ@ is used in an expression context, the compiler will report
-- that, naming @myPatQQ@.
--
-- See also 'defaultQuasiQuoter', which does not name the t'QuasiQuoter' in
-- the error message, and might therefore be more appropriate when
-- the users of a particular t'QuasiQuoter' tend to define local \"synonyms\"
-- for it.
namedDefaultQuasiQuoter :: String -> QuasiQuoter
namedDefaultQuasiQuoter :: String -> QuasiQuoter
namedDefaultQuasiQuoter String
name = QuasiQuoter
  { quoteExp :: String -> Q Exp
quoteExp = String -> String -> Q Exp
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"use in expression contexts."
  , quotePat :: String -> Q Pat
quotePat = String -> String -> Q Pat
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"use in pattern contexts."
  , quoteType :: String -> Q Type
quoteType = String -> String -> Q Type
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"use in types."
  , quoteDec :: String -> Q [Dec]
quoteDec = String -> String -> Q [Dec]
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"creating declarations."
  }
  where
    f :: String -> p -> m a
f String
m p
_ = String -> m a
forall a. HasCallStack => String -> m a
forall (m :: * -> *) a.
(MonadFail m, HasCallStack) =>
String -> m a
fail (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"The " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" quasiquoter is not for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
m

-- | A t'QuasiQuoter' that fails with a helpful error message in every
-- context. It is intended to be modified to create a t'QuasiQuoter' that
-- fails in all inappropriate contexts.
--
-- For example, you could write
--
-- @
-- myExpressionQQ = defaultQuasiQuoter
--   { quoteExp = ... }
-- @
--
-- See also 'namedDefaultQuasiQuoter', which names the t'QuasiQuoter' in the
-- error messages.
defaultQuasiQuoter :: QuasiQuoter
defaultQuasiQuoter :: QuasiQuoter
defaultQuasiQuoter = QuasiQuoter
  { quoteExp :: String -> Q Exp
quoteExp = String -> String -> Q Exp
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"use in expression contexts."
  , quotePat :: String -> Q Pat
quotePat = String -> String -> Q Pat
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"use in pattern contexts."
  , quoteType :: String -> Q Type
quoteType = String -> String -> Q Type
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"use in types."
  , quoteDec :: String -> Q [Dec]
quoteDec = String -> String -> Q [Dec]
forall {m :: * -> *} {p} {a}. MonadFail m => String -> p -> m a
f String
"creating declarations."
  }
  where
    f :: String -> p -> m a
f String
m p
_ = String -> m a
forall a. HasCallStack => String -> m a
forall (m :: * -> *) a.
(MonadFail m, HasCallStack) =>
String -> m a
fail (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"This quasiquoter is not for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
m