module Data.Singletons.Util (
module Data.Singletons.Util,
module Language.Haskell.TH.Desugar )
where
import Prelude hiding ( exp )
import Language.Haskell.TH hiding ( Q )
import Language.Haskell.TH.Syntax ( Quasi(..) )
import Language.Haskell.TH.Desugar ( reifyWithWarning, getDataD )
import Data.Char
import Data.Data
import Control.Monad
import Control.Applicative
import Control.Monad.Writer
import qualified Data.Map as Map
import Data.Generics
mkTyFamInst :: Name -> [Type] -> Type -> Dec
mkTyFamInst name lhs rhs =
#if __GLASGOW_HASKELL__ >= 707
TySynInstD name (TySynEqn lhs rhs)
#else
TySynInstD name lhs rhs
#endif
basicTypes :: [Name]
basicTypes = [ ''Bool
, ''Maybe
, ''Either
, ''Ordering
, ''[]
, ''()
, ''(,)
, ''(,,)
, ''(,,,)
, ''(,,,,)
, ''(,,,,,)
, ''(,,,,,,)
]
newUniqueName :: Quasi q => String -> q Name
newUniqueName str = do
n <- qNewName str
return $ mkName $ show n
qReportWarning :: Quasi q => String -> q ()
qReportWarning = qReport False
tupleDegree_maybe :: String -> Maybe Int
tupleDegree_maybe s = do
'(' : s1 <- return s
(commas, ")") <- return $ span (== ',') s1
let degree
| "" <- commas = 0
| otherwise = length commas + 1
return degree
tupleNameDegree_maybe :: Name -> Maybe Int
tupleNameDegree_maybe = tupleDegree_maybe . nameBase
ctorCases :: (Name -> [Type] -> a) -> ([TyVarBndr] -> Cxt -> Con -> a) -> Con -> a
ctorCases genFun forallFun ctor = case ctor of
NormalC name stypes -> genFun name (map snd stypes)
RecC name vstypes -> genFun name (map (\(_,_,ty) -> ty) vstypes)
InfixC (_,ty1) name (_,ty2) -> genFun name [ty1, ty2]
ForallC [] [] ctor' -> ctorCases genFun forallFun ctor'
ForallC tvbs cx ctor' -> forallFun tvbs cx ctor'
ctor1Case :: (Name -> [Type] -> a) -> Con -> a
ctor1Case mono = ctorCases mono (\_ _ ctor -> ctor1Case mono ctor)
extractNameArgs :: Con -> (Name, Int)
extractNameArgs = ctor1Case (\name tys -> (name, length tys))
reinterpret :: Name -> Name
reinterpret = mkName . nameBase
isUpcase :: Name -> Bool
isUpcase n = let first = head (nameBase n) in isUpper first || first == ':'
upcase :: Name -> Name
upcase n =
let str = nameBase n
first = head str in
if isLetter first
then mkName ((toUpper first) : tail str)
else mkName (':' : str)
locase :: Name -> Name
locase n =
let str = nameBase n
first = head str in
if isLetter first
then mkName ((toLower first) : tail str)
else mkName (tail str)
prefixUCName :: String -> String -> Name -> Name
prefixUCName pre tyPre n = case (nameBase n) of
(':' : rest) -> mkName (tyPre ++ rest)
alpha -> mkName (pre ++ alpha)
prefixLCName :: String -> String -> Name -> Name
prefixLCName pre tyPre n =
let str = nameBase n
first = head str in
if isLetter first
then mkName (pre ++ str)
else mkName (tyPre ++ str)
extractTvbKind :: TyVarBndr -> Kind
extractTvbKind (PlainTV _) = StarT
extractTvbKind (KindedTV _ k) = k
extractTvbName :: TyVarBndr -> Name
extractTvbName (PlainTV n) = n
extractTvbName (KindedTV n _) = n
foldType :: Type -> [Type] -> Type
foldType = foldl AppT
foldExp :: Exp -> [Exp] -> Exp
foldExp = foldl AppE
isVarK :: Kind -> Bool
isVarK (VarT _) = True
isVarK _ = False
mkTupleExp :: [Exp] -> Exp
mkTupleExp [x] = x
mkTupleExp xs = TupE xs
mkTuplePat :: [Pat] -> Pat
mkTuplePat [x] = x
mkTuplePat xs = TupP xs
orIfEmpty :: [a] -> [a] -> [a]
orIfEmpty [] x = x
orIfEmpty x _ = x
emptyMatches :: [Match]
#if __GLASGOW_HASKELL__ >= 707
emptyMatches = []
#else
emptyMatches = [Match WildP (NormalB (AppE (VarE 'error) (LitE (StringL errStr)))) []]
where errStr = "Empty case reached -- this should be impossible"
#endif
multiCase :: [Exp] -> [Pat] -> Exp -> Exp
multiCase [] [] body = body
multiCase scruts pats body =
CaseE (mkTupleExp scruts)
[Match (mkTuplePat pats) (NormalB body) []]
newtype QWithAux m q a = QWA { runQWA :: WriterT m q a }
deriving (Functor, Applicative, Monad, MonadTrans)
instance (Monoid m, Monad q) => MonadWriter m (QWithAux m q) where
writer = QWA . writer
tell = QWA . tell
listen = QWA . listen . runQWA
pass = QWA . pass . runQWA
instance (Quasi q, Monoid m) => Quasi (QWithAux m q) where
qNewName = lift `comp1` qNewName
qReport = lift `comp2` qReport
qLookupName = lift `comp2` qLookupName
qReify = lift `comp1` qReify
qReifyInstances = lift `comp2` qReifyInstances
qLocation = lift qLocation
qRunIO = lift `comp1` qRunIO
qAddDependentFile = lift `comp1` qAddDependentFile
#if __GLASGOW_HASKELL__ >= 707
qReifyRoles = lift `comp1` qReifyRoles
qReifyAnnotations = lift `comp1` qReifyAnnotations
qReifyModule = lift `comp1` qReifyModule
qAddTopDecls = lift `comp1` qAddTopDecls
qAddModFinalizer = lift `comp1` qAddModFinalizer
qGetQ = lift qGetQ
qPutQ = lift `comp1` qPutQ
#endif
qRecover exp handler = do
(result, aux) <- lift $ qRecover (evalForPair exp) (evalForPair handler)
tell aux
return result
comp1 :: (b -> c) -> (a -> b) -> a -> c
comp1 = (.)
comp2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
comp2 f g a b = f (g a b)
evalWithoutAux :: Quasi q => QWithAux m q a -> q a
evalWithoutAux = liftM fst . runWriterT . runQWA
evalForAux :: Quasi q => QWithAux m q a -> q m
evalForAux = execWriterT . runQWA
evalForPair :: Quasi q => QWithAux m q a -> q (a, m)
evalForPair = runWriterT . runQWA
addBinding :: (Quasi q, Ord k) => k -> v -> QWithAux (Map.Map k v) q ()
addBinding k v = tell (Map.singleton k v)
addElement :: Quasi q => elt -> QWithAux [elt] q ()
addElement elt = tell [elt]
containsName :: Data a => Name -> a -> Bool
containsName n = everything (||) (mkQ False (== n))
concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM fn list = do
bss <- mapM fn list
return $ concat bss
listify :: a -> [a]
listify = return