antiquoter-0.1.1.0: src/Language/Haskell/AntiQuoter/Combinators.hs
{-# LANGUAGE RankNTypes #-}
-- | Several combinators for `AntiQuoters`, mainly `EP` related.
module Language.Haskell.AntiQuoter.Combinators(
-- * Lifted constructors.
varQ, conQ, litQ, tupQ, listQ,
-- * Ignoring
ignore, ignorePat, onlyExp, ignoreExp, onlyPat,
-- * Unsorted
splice, wild,
nonsenseP, nonsenseE,
) where
import Language.Haskell.TH
import Language.Haskell.AntiQuoter.Base
import Language.Haskell.AntiQuoter.ExpPat
-- | Generalized `varE`/`varP`.
varQ :: EP q => Name -> Q q
varQ = return . var
-- | Generalized `conP` or combination of `conE` and `appE`.
conQ :: EP q => Name -> [Q q] -> Q q
conQ n = fmap (con n) . sequence
-- | Generalized `litE`/`litP`.
litQ :: EP q => Lit -> Q q
litQ = return . lit
tupQ, listQ :: EP q => [Q q] -> Q q
-- | Generalized `tupE`/`tupP`.
tupQ = fmap tup . sequence
-- | Generalized `listE`/`listP`.
listQ = fmap list . sequence
-- | Uses/Binds a variable of the given name.
--
-- > splice = varQ . mkName
--
splice :: EP q => String -> Q q
splice = varQ . mkName
-- | Use a wildcard in pattern context and the given expression in expression
-- contexts. Consider for example the folowing constructor
--
-- > EX SrcLoc OtherType
--
-- When pattern matching the pattern should look like @EX _ x@, using a
-- wildcard for the source location. On the other hand making an expression
-- should use some result say resulting in @EX someSrcLoc x@. With the `wild`
-- function this general quoter can be written as
--
-- > con ''EX [wild someSrcLoc', splice "x"]
--
-- Assuming that @someSrcLoc' :: ExpQ@ and that its result is of type @SrcLoc@.
wild :: EP q => Q Exp -> Q q
wild e = epValue e wildP
-- | An results that does not output anything.
ignore :: AQResult q
ignore = Nothing
-- | Yielding only a result for expressions and ignoring in patterns.
ignorePat, onlyExp :: EP q => AQResult Exp -> AQResult q
ignorePat e = epResult e ignore
-- | Alias for `ignorePat`.
onlyExp = ignorePat
-- | Yielding only a result for patterns and ignoring in expressions.
ignoreExp, onlyPat :: EP q => AQResult Pat -> AQResult q
ignoreExp = epResult ignore
-- | Alias for `ignoreExp`.
onlyPat = ignoreExp
-- | A `fail`ing result for patterns, useful for when a the pattern matched by
-- the using functions should never happen when antiquoting patterns.
nonsenseP :: EP q => String -> AQResult Exp -> AQResult q
nonsenseP msg e = e `epResult` (Just $ fail msg)
-- | See `nonsenseP` but failing on expresions.
nonsenseE :: EP q => String -> AQResult Pat -> AQResult q
nonsenseE msg p = (Just $ fail msg) `epResult` p