module Language.Haskell.Names.ModuleSymbols
( moduleSymbols
, moduleTable
, getTopDeclSymbols
)
where
import Data.Maybe
import Data.Data
import qualified Data.Map as Map
import qualified Language.Haskell.Exts as UnAnn (ModuleName,Name)
import Language.Haskell.Exts.Annotated hiding (NewType)
import Language.Haskell.Exts.Annotated.Simplify (sModuleName,sName)
import qualified Language.Haskell.Exts.Annotated as Syntax (DataOrNew(NewType))
import Language.Haskell.Names.Types
import qualified Language.Haskell.Names.GlobalSymbolTable as Global
import Language.Haskell.Names.SyntaxUtils
import Language.Haskell.Names.ScopeUtils
import Language.Haskell.Names.GetBound
moduleTable
:: (Eq l, Data l)
=> Global.Table
-> Module l
-> Global.Table
moduleTable impTbl m = Global.mergeTables impTbl (computeSymbolTable
False (sModuleName (getModuleName m)) (moduleSymbols impTbl m))
moduleSymbols
:: (Eq l, Data l)
=> Global.Table
-> Module l
-> [Symbol]
moduleSymbols impTbl m =
concatMap (getTopDeclSymbols impTbl $ getModuleName m) (getModuleDecls m)
getTopDeclSymbols
:: forall l . (Eq l, Data l)
=> Global.Table
-> ModuleName l
-> Decl l
-> [Symbol]
getTopDeclSymbols impTbl modulename d = (case d of
TypeDecl _ dh _ -> [declHeadSymbol Type dh]
TypeFamDecl _ dh _ -> [declHeadSymbol TypeFam dh]
DataDecl _ dataOrNew _ dh qualConDecls _ -> declHeadSymbol (dataOrNewCon dataOrNew) dh : infos where
cons :: [(Name l,[Name l])]
cons = do
QualConDecl _ _ _ conDecl <- qualConDecls
case conDecl of
ConDecl _ n _ -> return (n, [])
InfixConDecl _ _ n _ -> return (n, [])
RecDecl _ n fields ->
return (n , [f | FieldDecl _ fNames _ <- fields, f <- fNames])
dq = getDeclHeadName dh
infos = constructorsToInfos modulename dq cons
GDataDecl _ dataOrNew _ dh _ gadtDecls _ -> declHeadSymbol (dataOrNewCon dataOrNew) dh : infos where
dq = getDeclHeadName dh
cons :: [(Name l,[Name l])]
cons = do
GadtDecl _ cn (fromMaybe [] -> fields) _ty <- gadtDecls
return (cn , [f | FieldDecl _ fNames _ <- fields, f <- fNames])
infos = constructorsToInfos modulename dq cons
DataFamDecl _ _ dh _ -> [declHeadSymbol DataFam dh]
ClassDecl _ _ dh _ mds ->
let
ms = getBound impTbl d
cdecls = fromMaybe [] mds
in
(declHeadSymbol Class dh) :
[ declHeadSymbol TypeFam dh | ClsTyFam _ dh _ <- cdecls ] ++
[ declHeadSymbol DataFam dh | ClsDataFam _ _ dh _ <- cdecls ] ++
[ Method (sModuleName modulename) (sName mn) (sName (getDeclHeadName dh)) | mn <- ms ]
FunBind _ ms -> [ Value (sModuleName modulename) (sName vn) ] where
vn : _ = getBound impTbl ms
PatBind _ p _ _ -> [ Value (sModuleName modulename) (sName vn) | vn <- getBound impTbl p ]
ForImp _ _ _ _ fn _ -> [ Value (sModuleName modulename) (sName fn)]
_ -> [])
where
declHeadSymbol c dh = c (sModuleName modulename) (sName (getDeclHeadName dh))
constructorsToInfos :: ModuleName l -> Name l -> [(Name l,[Name l])] -> [Symbol]
constructorsToInfos modulename typename constructors = conInfos ++ selInfos where
conInfos = do
(constructorname,_) <- constructors
return (Constructor (sModuleName modulename) (sName constructorname) (sName typename))
selectorsMap = Map.fromListWith (++) (do
(constructorname,selectornames) <- constructors
selectorname <- selectornames
return (nameToString selectorname,[constructorname]))
selInfos = do
(_,selectornames) <- constructors
selectorname <- selectornames
constructornames <- maybeToList (Map.lookup (nameToString selectorname) selectorsMap)
return (Selector (sModuleName modulename) (sName selectorname) (sName typename) (map sName constructornames))
dataOrNewCon :: Syntax.DataOrNew l -> UnAnn.ModuleName -> UnAnn.Name -> Symbol
dataOrNewCon dataOrNew = case dataOrNew of DataType {} -> Data; Syntax.NewType {} -> NewType