th-extras-0.0.0.1: src/Language/Haskell/TH/Extras.hs
{-# LANGUAGE CPP #-}
module Language.Haskell.TH.Extras where
import Control.Monad
import Data.Generics
import Data.Maybe
import Language.Haskell.TH
intIs64 :: Bool
intIs64 = toInteger (maxBound :: Int) > 2^32
replace :: (a -> Maybe a) -> (a -> a)
replace = ap fromMaybe
namesBoundInPat :: Pat -> [Name]
namesBoundInPat (VarP name) = [name]
namesBoundInPat (TupP pats) = pats >>= namesBoundInPat
namesBoundInPat (ConP _ pats) = pats >>= namesBoundInPat
namesBoundInPat (InfixP p1 _ p2) = namesBoundInPat p1 ++ namesBoundInPat p2
namesBoundInPat (TildeP pat) = namesBoundInPat pat
namesBoundInPat (AsP name pat) = name : namesBoundInPat pat
namesBoundInPat (RecP _ fieldPats) = map snd fieldPats >>= namesBoundInPat
namesBoundInPat (ListP pats) = pats >>= namesBoundInPat
namesBoundInPat (SigP pat _) = namesBoundInPat pat
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 612
namesBoundInPat (BangP pat) = namesBoundInPat pat
#endif
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 700
namesBoundInPat (ViewP _ pat) = namesBoundInPat pat
#endif
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
namesBoundInPat (UnboxedTupP pats) = pats >>= namesBoundInPat
#endif
namesBoundInPat _ = []
namesBoundInDec :: Dec -> [Name]
namesBoundInDec (FunD name _) = [name]
namesBoundInDec (ValD pat _ _) = namesBoundInPat pat
namesBoundInDec (DataD _ name _ _ _) = [name]
namesBoundInDec (NewtypeD _ name _ _ _) = [name]
namesBoundInDec (TySynD name _ _) = [name]
namesBoundInDec (ClassD _ name _ _ _) = [name]
namesBoundInDec (ForeignD (ImportF _ _ _ name _)) = [name]
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 612
namesBoundInDec (FamilyD _ name _ _) = [name]
#endif
namesBoundInDec _ = []
genericalizeName :: Name -> Name
genericalizeName = mkName . nameBase
-- Genericalize all names defined at the top level, to fix the lunacy introduced in GHC 7.2.
-- Why they should be fresh is beyond me; it really seems absurd because there is no way whatsoever
-- to refer to names known to be bound in [d||] quotes other than to scrounge around inside the
-- generated 'Dec's.
genericalizeDecs :: [Dec] -> [Dec]
genericalizeDecs decs = everywhere (mkT fixName) decs
where
-- get all names bound in the decs and make them generic
-- at every occurence in decs.
names = decs >>= namesBoundInDec
genericalizedNames = [ (n, genericalizeName n) | n <- names]
fixName = replace (`lookup` genericalizedNames)