ariadne-0.1.2.2: Ariadne/GlobalNameIndex.hs
{-# LANGUAGE TupleSections, TypeFamilies #-}
-- | Construction of the global name index. See 'GlobalNameIndex' for the
-- description.
module Ariadne.GlobalNameIndex (mkGlobalNameIndex) where
import Language.Haskell.Names
import qualified Language.Haskell.Names.GlobalSymbolTable as Global
import Language.Haskell.Names.SyntaxUtils
import Language.Haskell.Names.GetBound
import Language.Haskell.Exts.Annotated
import Distribution.HaskellSuite.Modules
import qualified Data.Map as Map
import Data.Maybe
import Ariadne.Types
-- | Create the global name index for a given module.
--
-- This function assumes that the module's import table is calculated
-- somewhere outside (probably using 'processImports').
-- Why we don't calculate the import table right here? First, it would
-- bring all the complexity of ModuleT here. Second, what about recursive
-- modules? Third, this avoids double cost of resolution if it's needed
-- somewhere else too.
mkGlobalNameIndex
:: Global.Table -> Module SrcLoc -> GlobalNameIndex
mkGlobalNameIndex tbl mod =
let
Module _ _ _ _ ds = mod
ModuleName _ modname = getModuleName mod
names = concatMap (indexDecl tbl) ds
in
Map.fromListWith (const id) -- prefer earlier names
[ ((OrigName Nothing (GName modname (nameToString n)), level), ann n)
| (n, level) <- names
]
indexDecl :: Global.Table -> Decl SrcLoc -> [(Name SrcLoc, NameLevel)]
indexDecl tbl d =
case d of
TypeDecl _ dh _ -> [(getDeclHeadName dh, TypeLevel)]
TypeFamDecl _ dh _ -> [(getDeclHeadName dh, TypeLevel)]
DataDecl _ _ _ dh qualConDecls _ ->
((getDeclHeadName dh, TypeLevel) :) . map (, ValueLevel) $ do -- list monad
QualConDecl _ _ _ conDecl <- qualConDecls
case conDecl of
ConDecl _ n _ -> return n
InfixConDecl _ _ n _ -> return n
RecDecl _ n fields ->
n :
[f | FieldDecl _ fNames _ <- fields, f <- fNames]
GDataDecl _ dataOrNew _ dh _ gadtDecls _ ->
-- As of 1.14.0, HSE doesn't support GADT records.
-- When it does, this code should be rewritten similarly to the
-- DataDecl case.
-- (Also keep in mind that GHC doesn't create selectors for fields
-- with existential type variables.)
-- TODO HSE 1.16 now supports GADT records
(getDeclHeadName dh, TypeLevel) :
[ (cn, ValueLevel)
| GadtDecl _ cn names _ <- gadtDecls
]
ClassDecl _ _ dh _ mds ->
let
ms = getBound tbl d
cdecls = fromMaybe [] mds
in
(getDeclHeadName dh, TypeLevel) :
[ (getDeclHeadName dh, TypeLevel) | ClsTyFam _ dh _ <- cdecls ] ++
[ (getDeclHeadName dh, TypeLevel) | ClsDataFam _ _ dh _ <- cdecls ] ++
[ (mn, ValueLevel) | mn <- ms ]
FunBind _ ms -> map (, ValueLevel) $ getBound tbl ms
PatBind _ p _ _ -> map (, ValueLevel) $ getBound tbl p
ForImp _ _ _ _ fn _ -> [(fn, ValueLevel)]
_ -> []