module Haddock.Interface.AttachInstances (attachInstances) where
import Haddock.Types
import Haddock.Convert
import Control.Arrow
import Data.List
import qualified Data.Map as Map
import qualified Data.Set as Set
import Class
import FastString
import GHC
import GhcMonad (withSession)
import Id
import InstEnv
import MonadUtils (liftIO)
import Name
import PrelNames
import TcRnDriver (tcRnGetInfo)
import TyCon
import TypeRep
import TysPrim( funTyCon )
import Var hiding (varName)
#define FSLIT(x) (mkFastString# (x#))
type ExportedNames = Set.Set Name
type Modules = Set.Set Module
type ExportInfo = (ExportedNames, Modules)
attachInstances :: ExportInfo -> [Interface] -> InstIfaceMap -> Ghc [Interface]
attachInstances expInfo ifaces instIfaceMap = mapM attach ifaces
where
ifaceMap = Map.fromList [ (ifaceMod i, i) | i <- ifaces ]
attach iface = do
newItems <- mapM (attachToExportItem expInfo iface ifaceMap instIfaceMap)
(ifaceExportItems iface)
return $ iface { ifaceExportItems = newItems }
attachToExportItem :: ExportInfo -> Interface -> IfaceMap -> InstIfaceMap -> ExportItem Name -> Ghc (ExportItem Name)
attachToExportItem expInfo iface ifaceMap instIfaceMap export =
case export of
ExportDecl { expItemDecl = L _ (TyClD d) } -> do
mb_info <- getAllInfo (unLoc (tcdLName d))
let export' =
export {
expItemInstances =
case mb_info of
Just (_, _, instances) ->
let insts = map (first synifyInstHead) $ sortImage (first instHead) $
filter (\((_,_,cls,tys),_) -> not $ isInstanceHidden expInfo cls tys)
[ (instanceHead' i, getName i) | i <- instances ]
in [ (inst, lookupInstDoc name iface ifaceMap instIfaceMap)
| (inst, name) <- insts ]
Nothing -> []
}
return export'
_ -> return export
lookupInstDoc :: Name -> Interface -> IfaceMap -> InstIfaceMap -> Maybe (Doc Name)
lookupInstDoc name iface ifaceMap instIfaceMap =
case Map.lookup name (ifaceDocMap iface) of
Just doc -> Just doc
Nothing ->
case Map.lookup modName ifaceMap of
Just iface2 ->
case Map.lookup name (ifaceDocMap iface2) of
Just doc -> Just doc
Nothing -> Nothing
Nothing ->
case Map.lookup modName instIfaceMap of
Just instIface -> Map.lookup name (instDocMap instIface)
Nothing -> Nothing
where
modName = nameModule name
instanceHead' :: ClsInst -> ([TyVar], ThetaType, Class, [Type])
instanceHead' ispec = (tvs, dropSilentArgs dfun theta, cls, tys)
where
dfun = is_dfun ispec
(tvs, theta, cls, tys) = instanceHead ispec
dropSilentArgs :: DFunId -> ThetaType -> ThetaType
dropSilentArgs dfun theta = drop (dfunNSilent dfun) theta
getAllInfo :: GhcMonad m => Name -> m (Maybe (TyThing,Fixity,[ClsInst]))
getAllInfo name = withSession $ \hsc_env -> do
(_msgs, r) <- liftIO $ tcRnGetInfo hsc_env name
return r
data SimpleType = SimpleType Name [SimpleType]
| SimpleTyLit TyLit
deriving (Eq,Ord)
instHead :: ([TyVar], [PredType], Class, [Type]) -> ([Int], Name, [SimpleType])
instHead (_, _, cls, args)
= (map argCount args, className cls, map simplify args)
where
argCount (AppTy t _) = argCount t + 1
argCount (TyConApp _ ts) = length ts
argCount (FunTy _ _ ) = 2
argCount (ForAllTy _ t) = argCount t
argCount _ = 0
simplify (ForAllTy _ t) = simplify t
simplify (FunTy t1 t2) =
SimpleType funTyConName [simplify t1, simplify t2]
simplify (AppTy t1 t2) = SimpleType s (ts ++ [simplify t2])
where (SimpleType s ts) = simplify t1
simplify (TyVarTy v) = SimpleType (tyVarName v) []
simplify (TyConApp tc ts) = SimpleType (tyConName tc) (map simplify ts)
simplify (LitTy l) = SimpleTyLit l
sortImage :: Ord b => (a -> b) -> [a] -> [a]
sortImage f xs = map snd $ sortBy cmp_fst [(f x, x) | x <- xs]
where cmp_fst (x,_) (y,_) = compare x y
funTyConName :: Name
funTyConName = mkWiredInName gHC_PRIM
(mkOccNameFS tcName FSLIT("(->)"))
funTyConKey
(ATyCon funTyCon)
BuiltInSyntax
isNameHidden :: ExportInfo -> Name -> Bool
isNameHidden (names, modules) name =
nameModule name `Set.member` modules &&
not (name `Set.member` names)
isInstanceHidden :: ExportInfo -> Class -> [Type] -> Bool
isInstanceHidden expInfo cls tys =
instClassHidden || instTypeHidden
where
instClassHidden :: Bool
instClassHidden = isNameHidden expInfo $ getName cls
instTypeHidden :: Bool
instTypeHidden = any typeHidden tys
nameHidden :: Name -> Bool
nameHidden = isNameHidden expInfo
typeHidden :: Type -> Bool
typeHidden t =
case t of
TyVarTy {} -> False
AppTy t1 t2 -> typeHidden t1 || typeHidden t2
TyConApp tcon args -> nameHidden (getName tcon) || any typeHidden args
FunTy t1 t2 -> typeHidden t1 || typeHidden t2
ForAllTy _ ty -> typeHidden ty
LitTy _ -> False