{-# language CPP #-}
module Language.Haskell.TH.Data where
import Data.Char
import Data.Generics
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Compat
type DataDef = Dec
type CtorDef = Con
dataName :: DataDef -> String
#if __GLASGOW_HASKELL__ >= 800
dataName (DataD _ name _ _ _ _) = unqualifiedName name
dataName (NewtypeD _ name _ _ _ _) = unqualifiedName name
#else
dataName (DataD _ name _ _ _) = unqualifiedName name
dataName (NewtypeD _ name _ _ _) = unqualifiedName name
#endif
qualifiedDataName :: DataDef -> Name
#if __GLASGOW_HASKELL__ >= 800
qualifiedDataName (DataD _ name _ _ _ _) = name
qualifiedDataName (NewtypeD _ name _ _ _ _) = name
#else
qualifiedDataName (DataD _ name _ _ _) = name
qualifiedDataName (NewtypeD _ name _ _ _) = name
#endif
dataArity :: DataDef -> Int
#if __GLASGOW_HASKELL__ >= 800
dataArity (DataD _ _ xs _ _ _) = length xs
dataArity (NewtypeD _ _ xs _ _ _) = length xs
#else
dataArity (DataD _ _ xs _ _) = length xs
dataArity (NewtypeD _ _ xs _ _) = length xs
#endif
dataArgs :: DataDef -> [Name]
dataArgs = dataDefinitionTypeArgs
dataCtors :: DataDef -> [CtorDef]
#if __GLASGOW_HASKELL__ >= 800
dataCtors (DataD _ _ _ _ xs _) = xs
dataCtors (NewtypeD _ _ _ _ x _) = [x]
#else
dataCtors (DataD _ _ _ xs _) = xs
dataCtors (NewtypeD _ _ _ x _) = [x]
#endif
ctorName :: CtorDef -> String
ctorName (NormalC name _ ) = unqualifiedName name
ctorName (RecC name _ ) = unqualifiedName name
ctorName (InfixC _ name _) = unqualifiedName name
ctorName (ForallC _ _ c ) = ctorName c
qualifiedCtorName :: CtorDef -> Name
qualifiedCtorName (NormalC name _ ) = name
qualifiedCtorName (RecC name _ ) = name
qualifiedCtorName (InfixC _ name _) = name
qualifiedCtorName (ForallC _ _ c ) = qualifiedCtorName c
ctorArity :: CtorDef -> Int
ctorArity (NormalC _ xs ) = length xs
ctorArity (RecC _ xs ) = length xs
ctorArity (InfixC _ _ _ ) = 2
ctorArity (ForallC _ _ c) = ctorArity c
ctorStrictTypes :: CtorDef -> [StrictType]
ctorStrictTypes (NormalC _ xs ) = xs
ctorStrictTypes (RecC _ xs ) = [(b,c) | (a,b,c) <- xs]
ctorStrictTypes (InfixC x _ y ) = [x,y]
ctorStrictTypes (ForallC _ _ c) = ctorStrictTypes c
ctorTypes :: CtorDef -> [Type]
ctorTypes = map snd . ctorStrictTypes
ctorFields :: CtorDef -> [String]
ctorFields (RecC name varStrictType) = [unqualifiedName name | (name,strict,typ) <- varStrictType]
ctorFields _ = []
dropModule :: String -> String
dropModule xs = case reverse xs of
('.':xs) -> takeWhile (== '.') xs
xs -> reverse $ takeWhile (/= '.') xs
dropNumber :: String -> String
dropNumber xs = if all isDigit a then reverse (tail b) else xs
where (a,b) = break (== '_') $ reverse xs
normData :: DataDef -> DataDef
normData = everywhere (mkT normType)
where
normType :: Type -> Type
normType (ConT x) | show x == "[]" = ListT
normType x = x
unqualifiedName :: Name -> String
unqualifiedName = dropModule . show
typeApp :: Type -> (Type, [Type])
typeApp (AppT l r) = (a, b++[r])
where (a,b) = typeApp l
typeApp t = (t, [])
eqConT :: String -> Type -> Bool
eqConT name (ConT x) = name == show x
eqConT _ _ = False
isTupleT :: Type -> Bool
isTupleT (TupleT _) = True
isTupleT (ConT x) = head sx == '(' && last sx == ')' &&
all (== ',') (take (length sx - 2) (tail sx))
where sx = nameBase x
isTupleT _ = False