packages feed

ariadne-0.1.2: Ariadne/GlobalNameIndex.hs

{-# LANGUAGE TupleSections, TypeFamilies #-}
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

mkGlobalNameIndex
  :: Global.Table -> Module SrcLoc -> GlobalNameIndex
mkGlobalNameIndex tbl mod =
  let
    Module _ _ _ _ ds = mod
    ModuleName _ modname = getModuleName mod

    names = concatMap (indexDecl tbl) ds

  in
    Map.fromList
      [ ((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 _ -> [(hname dh, TypeLevel)]
    TypeFamDecl _ dh _ -> [(hname dh, TypeLevel)]

    DataDecl _ _ _ dh qualConDecls _ ->
      ((hname 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.)
          (hname dh, TypeLevel) :
        [ (cn, ValueLevel)
        | GadtDecl _ cn _ <- gadtDecls
        ]

    ClassDecl _ _ dh _ mds ->
      let
        ms = getBound tbl d
        cdecls = fromMaybe [] mds
      in
          (hname dh, TypeLevel) :
        [ (hname dh, TypeLevel) | ClsTyFam   _   dh _ <- cdecls ] ++
        [ (hname 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)]

    _ -> []
  where
    hname = fst . splitDeclHead