module Language.Haskell.Names.ScopeUtils where import Control.Arrow import Data.Monoid import Language.Haskell.Names.Types import Language.Haskell.Names.SyntaxUtils import Language.Haskell.Exts import qualified Language.Haskell.Names.GlobalSymbolTable as Global import Control.Monad (guard) import Data.List (nub) scopeError :: Functor f => Error l -> f l -> f (Scoped l) scopeError e f = Scoped (ScopeError e) <$> f none :: l -> Scoped l none = Scoped None noScope :: (Annotated a) => a l -> a (Scoped l) noScope = fmap none symbolParent :: Symbol -> Maybe (Name ()) symbolParent (Selector { typeName = n }) = Just n symbolParent (Constructor { typeName = n }) = Just n symbolParent (Method { className = n }) = Just n symbolParent (TypeFam { associate = as }) = as symbolParent (DataFam { associate = as }) = as symbolParent (PatternConstructor { patternTypeName = mn}) = mn symbolParent (PatternSelector { patternTypeName = mn}) = mn symbolParent _ = Nothing computeSymbolTable :: Bool -- ^ If 'True' (\"qualified\"), then only the qualified names are -- inserted. -- -- If 'False', then both qualified and unqualified names are insterted. -> ModuleName () -> [Symbol] -> Global.Table computeSymbolTable qual modulename symbols = Global.fromList (qualified <> if qual then [] else unqualified) where qualified = do symbol <- symbols return (Qual ()modulename (symbolName symbol),symbol) unqualified = do symbol <- symbols return (UnQual () (symbolName symbol),symbol) -- | Find a single constructor or method name in a list of symbols resolveCName :: [Symbol] -> Name () -> (CName l -> Error l) -- ^ error for "not found" condition -> CName l -> (CName (Scoped l), [Symbol]) resolveCName symbols parent notFound cn = let vs = nub (do symbol <- symbols guard (Global.isValue symbol) let name = symbolName symbol guard (dropAnn (unCName cn) == name) Just p <- return $ symbolParent symbol guard (p == parent) return symbol) in case vs of [] -> (scopeError (notFound cn) cn, []) [symbol] -> (Scoped (GlobalSymbol symbol (UnQual () (dropAnn (unCName cn)))) <$> cn, [symbol]) _ -> (scopeError (EInternal "resolveCName") cn, []) -- | Find a list of constructor or method names in a list of symbols. resolveCNames :: [Symbol] -> Name () -> (CName l -> Error l) -- ^ error for "not found" condition -> [CName l] -> ([CName (Scoped l)], [Symbol]) resolveCNames syms orig notFound = second mconcat . unzip . map (resolveCName syms orig notFound)