----------------------------------------------------------------------------
-- |
-- Module      :  Data.Emacs.Module.SymbolName.TH
-- Copyright   :  (c) Sergey Vinokurov 2018
-- License     :  Apache-2.0 (see LICENSE)
-- Maintainer  :  serg.foo@gmail.com
----------------------------------------------------------------------------

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE TemplateHaskell     #-}

module Data.Emacs.Module.SymbolName.TH (esym) where

import Data.ByteString.Char8 qualified as C8
import Language.Haskell.TH
import Language.Haskell.TH.Quote

import Data.Emacs.Module.SymbolName.Internal

-- | Quasi-quoter for 'SymbolName'. Avoids some runtime overhead of
-- creating a 'SymbolName', but in other respects is absolutely equivalent
-- to 'mkSymbolName'.
--
-- > [esym|foo|] == mkSymbolName "foo"
-- True
esym :: QuasiQuoter
esym :: QuasiQuoter
esym = QuasiQuoter :: (String -> Q Exp)
-> (String -> Q Pat)
-> (String -> Q Type)
-> (String -> Q [Dec])
-> QuasiQuoter
QuasiQuoter
  { quoteExp :: String -> Q Exp
quoteExp  = String -> Q Exp
mkESym
  , quotePat :: String -> Q Pat
quotePat  = Q Pat -> String -> Q Pat
forall a b. a -> b -> a
const (Q Pat -> String -> Q Pat) -> Q Pat -> String -> Q Pat
forall a b. (a -> b) -> a -> b
$ String -> Q Pat
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Only defined for values"
  , quoteType :: String -> Q Type
quoteType = Q Type -> String -> Q Type
forall a b. a -> b -> a
const (Q Type -> String -> Q Type) -> Q Type -> String -> Q Type
forall a b. (a -> b) -> a -> b
$ String -> Q Type
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Only defined for values"
  , quoteDec :: String -> Q [Dec]
quoteDec  = Q [Dec] -> String -> Q [Dec]
forall a b. a -> b -> a
const (Q [Dec] -> String -> Q [Dec]) -> Q [Dec] -> String -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ String -> Q [Dec]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Only defined for values"
  }

mkESym :: String -> ExpQ
mkESym :: String -> Q Exp
mkESym String
s = [e| SymbolName (C8.pack $(stringE $ s ++ "\0")) |]