{-# LANGUAGE CPP #-}
-- | Description: Functions for defining quasiquoters
--  used in both the SQL-validating quasiquoter and the simple non-validating QQ.

module Preql.QuasiQuoter.Common where

import Language.Haskell.TH
import Language.Haskell.TH.Quote

-- | A list of n Names beginning with the given character
cNames :: Char -> Int -> Q [Name]
cNames :: Char -> Int -> Q [Name]
cNames Char
c Int
n = (String -> Q Name) -> [String] -> Q [Name]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse String -> Q Name
newName (Int -> String -> [String]
forall a. Int -> a -> [a]
replicate Int
n (Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
""))

tupleOrSingle :: [Name] -> Exp
tupleOrSingle :: [Name] -> Exp
tupleOrSingle [Name]
names = case [Name]
names of
    [Name
name] -> Name -> Exp
VarE Name
name
    [Name]
vs -> [Exp] -> Exp
tupleE ([Exp] -> Exp) -> [Exp] -> Exp
forall a b. (a -> b) -> a -> b
$ (Name -> Exp) -> [Name] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Exp
VarE [Name]
vs

expressionOnly :: String -> (String -> Q Exp) -> QuasiQuoter
expressionOnly :: String -> (String -> Q Exp) -> QuasiQuoter
expressionOnly String
name String -> Q Exp
qq = QuasiQuoter :: (String -> Q Exp)
-> (String -> Q Pat)
-> (String -> Q Type)
-> (String -> Q [Dec])
-> QuasiQuoter
QuasiQuoter
    { quoteExp :: String -> Q Exp
quoteExp = String -> Q Exp
qq
    , quotePat :: String -> Q Pat
quotePat = \String
_ -> String -> Q Pat
forall a. HasCallStack => String -> a
error (String -> Q Pat) -> String -> Q Pat
forall a b. (a -> b) -> a -> b
$ String
"qq " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" cannot be used in pattern context"
    , quoteType :: String -> Q Type
quoteType = \String
_ -> String -> Q Type
forall a. HasCallStack => String -> a
error (String -> Q Type) -> String -> Q Type
forall a b. (a -> b) -> a -> b
$ String
"qq " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" cannot be used in type context"
    , quoteDec :: String -> Q [Dec]
quoteDec = \String
_ -> String -> Q [Dec]
forall a. HasCallStack => String -> a
error (String -> Q [Dec]) -> String -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ String
"qq " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" cannot be used in declaration context"
    }

alphabet :: [String]
alphabet :: [String]
alphabet = [String] -> [String]
forall a. [a] -> [a]
cycle ((Char -> String) -> String -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Char -> String -> String
forall a. a -> [a] -> [a]
:String
"") [Char
'a'..Char
'z'])

tupleE :: [Exp] -> Exp
#if MIN_VERSION_template_haskell(2,16,0)
tupleE :: [Exp] -> Exp
tupleE = [Maybe Exp] -> Exp
TupE ([Maybe Exp] -> Exp) -> ([Exp] -> [Maybe Exp]) -> [Exp] -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> Maybe Exp) -> [Exp] -> [Maybe Exp]
forall a b. (a -> b) -> [a] -> [b]
map Exp -> Maybe Exp
forall a. a -> Maybe a
Just
#else
tupleE = TupE
#endif