module Language.Haskell.Names.Exports
( exportedSymbols
, annotateExportSpecList
) where
import qualified Data.Map as Map
import qualified Data.Set as Set
import Control.Applicative
import Control.Monad
import Control.Monad.Writer
import Data.Data
import qualified Language.Haskell.Exts as UnAnn (QName(Qual,UnQual))
import Language.Haskell.Exts.Annotated.Simplify (sQName,sModuleName)
import Language.Haskell.Exts.Annotated
import Language.Haskell.Names.Types
import Language.Haskell.Names.ScopeUtils
import Language.Haskell.Names.SyntaxUtils
import Language.Haskell.Names.ModuleSymbols
import Language.Haskell.Names.GlobalSymbolTable as Global
import Data.List (nub)
exportedSymbols :: (Data l, Eq l) => Global.Table -> Module l -> [Symbol]
exportedSymbols globalTable modul = case getExportSpecList modul of
Nothing -> moduleSymbols globalTable modul
Just (ExportSpecList _ exportSpecs) ->
concatMap (exportSpecSymbols globalTable) exportSpecs
exportSpecSymbols :: Global.Table -> ExportSpec l -> [Symbol]
exportSpecSymbols globalTable exportSpec =
case exportSpec of
EVar _ qn ->
case Global.lookupValue qn globalTable of
Global.Error _ -> []
Global.SymbolFound i -> [i]
Global.Special {} -> error "Global.Special in export list?"
EAbs _ _ qn ->
case Global.lookupType qn globalTable of
Global.Error _ -> []
Global.SymbolFound i -> [i]
Global.Special {} -> error "Global.Special in export list?"
EThingAll _ qn ->
case Global.lookupType qn globalTable of
Global.Error _ -> []
Global.SymbolFound i -> [i] ++ subs where
subs = nub (do
symbol <- concat (Map.elems globalTable)
Just n' <- return $ symbolParent symbol
guard (n' == symbolName i)
return symbol)
Global.Special {} -> error "Global.Special in export list?"
EThingWith _ qn cns ->
case Global.lookupType qn globalTable of
Global.Error _ -> []
Global.SymbolFound i -> [i] ++ subs where
(_, subs) =
resolveCNames
(concat (Map.elems globalTable))
(symbolName i)
(\cn -> ENotInScope (UnQual (ann cn) (unCName cn)))
cns
Global.Special {} -> error "Global.Special in export list?"
EModuleContents _ modulename -> exportedSymbols where
exportedSymbols = Set.toList (
Set.intersection inScopeQualified inScopeUnqualified)
inScopeQualified = Set.fromList (do
(UnAnn.Qual prefix _, symbols) <- Map.toList globalTable
guard (prefix == sModuleName modulename)
symbols)
inScopeUnqualified = Set.fromList (do
(UnAnn.UnQual _, symbols) <- Map.toList globalTable
symbols)
annotateExportSpecList :: Global.Table -> ExportSpecList l -> ExportSpecList (Scoped l)
annotateExportSpecList globalTable (ExportSpecList l exportSpecs) =
ExportSpecList (none l) (map (annotateExportSpec globalTable) exportSpecs)
annotateExportSpec :: Global.Table -> ExportSpec l -> ExportSpec (Scoped l)
annotateExportSpec globalTable exportSpec =
case exportSpec of
EVar l qn ->
case Global.lookupValue qn globalTable of
Global.Error err ->
scopeError err exportSpec
Global.SymbolFound i ->
EVar (Scoped (Export [i]) l)
(Scoped (GlobalSymbol i (sQName qn)) <$> qn)
Global.Special {} -> error "Global.Special in export list?"
EAbs l ns qn ->
case Global.lookupType qn globalTable of
Global.Error err ->
scopeError err exportSpec
Global.SymbolFound i ->
EAbs (Scoped (Export [i]) l)
(noScope ns)
(Scoped (GlobalSymbol i (sQName qn)) <$> qn)
Global.Special {} -> error "Global.Special in export list?"
EThingAll l qn ->
case Global.lookupType qn globalTable of
Global.Error err ->
scopeError err exportSpec
Global.SymbolFound i ->
let
subs = nub (do
symbol <- concat (Map.elems globalTable)
Just n' <- return $ symbolParent symbol
guard (n' == symbolName i)
return symbol)
s = [i] <> subs
in
EThingAll (Scoped (Export s) l) (Scoped (GlobalSymbol i (sQName qn)) <$> qn)
Global.Special {} -> error "Global.Special in export list?"
EThingWith l qn cns ->
case Global.lookupType qn globalTable of
Global.Error err ->
scopeError err exportSpec
Global.SymbolFound i ->
let
(cns', subs) =
resolveCNames
(concat (Map.elems globalTable))
(symbolName i)
(\cn -> ENotInScope (UnQual (ann cn) (unCName cn)))
cns
s = [i] <> subs
in
EThingWith (Scoped (Export s) l) (Scoped (GlobalSymbol i (sQName qn)) <$> qn) cns'
Global.Special {} -> error "Global.Special in export list?"
EModuleContents _ modulename -> Scoped (Export exportedSymbols) <$> exportSpec where
exportedSymbols = Set.toList (Set.intersection inScopeQualified inScopeUnqualified)
inScopeQualified = Set.fromList (do
(UnAnn.Qual prefix _, symbols) <- Map.toList globalTable
guard (prefix == sModuleName modulename)
symbols)
inScopeUnqualified = Set.fromList (do
(UnAnn.UnQual _, symbols) <- Map.toList globalTable
symbols)