X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fmain%2FFinder.lhs;h=d8a627167c2e3935451b96a113951d8a1b0a9753;hb=f2aaae9757e7532485c97f6c9a9ed5437542d1dd;hp=ca49aa2216b10ba1d83eadd0ce5781d823f8ecc2;hpb=ba9431759b4b753c214f346538a9148395afab92;p=ghc-hetmet.git diff --git a/compiler/main/Finder.lhs b/compiler/main/Finder.lhs index ca49aa2..d8a6271 100644 --- a/compiler/main/Finder.lhs +++ b/compiler/main/Finder.lhs @@ -10,6 +10,7 @@ module Finder ( findImportedModule, findExactModule, findHomeModule, + findExposedPackageModule, mkHomeModLocation, mkHomeModLocation2, mkHiOnlyModLocation, @@ -25,25 +26,28 @@ module Finder ( ) where +#include "HsVersions.h" + import Module import HscTypes import Packages import FastString import Util import PrelNames ( gHC_PRIM ) -import DynFlags ( DynFlags(..), isOneShot, GhcMode(..) ) +import DynFlags import Outputable -import FiniteMap -import LazyUniqFM +import UniqFM import Maybes ( expectJust ) +import Exception ( evaluate ) -import Data.IORef ( IORef, writeIORef, readIORef, modifyIORef ) -import Data.List +import Distribution.Text +import Distribution.Package hiding (PackageId) +import Data.IORef ( IORef, writeIORef, readIORef, atomicModifyIORef ) import System.Directory import System.FilePath -import System.IO import Control.Monad import System.Time ( ClockTime ) +import Data.List ( partition ) type FileExt = String -- Filename extension @@ -66,6 +70,7 @@ type BaseName = String -- Basename of file -- assumed to not move around during a session. flushFinderCaches :: HscEnv -> IO () flushFinderCaches hsc_env = do + -- Ideally the update to both caches be a single atomic operation. writeIORef fc_ref emptyUFM flushModLocationCache this_pkg mlc_ref where @@ -75,23 +80,27 @@ flushFinderCaches hsc_env = do flushModLocationCache :: PackageId -> IORef ModLocationCache -> IO () flushModLocationCache this_pkg ref = do - fm <- readIORef ref - writeIORef ref $! filterFM is_ext fm + atomicModifyIORef ref $ \fm -> (filterModuleEnv is_ext fm, ()) + _ <- evaluate =<< readIORef ref return () where is_ext mod _ | modulePackageId mod /= this_pkg = True | otherwise = False addToFinderCache :: IORef FinderCache -> ModuleName -> FindResult -> IO () -addToFinderCache ref key val = modifyIORef ref $ \c -> addToUFM c key val +addToFinderCache ref key val = + atomicModifyIORef ref $ \c -> (addToUFM c key val, ()) addToModLocationCache :: IORef ModLocationCache -> Module -> ModLocation -> IO () -addToModLocationCache ref key val = modifyIORef ref $ \c -> addToFM c key val +addToModLocationCache ref key val = + atomicModifyIORef ref $ \c -> (extendModuleEnv c key val, ()) removeFromFinderCache :: IORef FinderCache -> ModuleName -> IO () -removeFromFinderCache ref key = modifyIORef ref $ \c -> delFromUFM c key +removeFromFinderCache ref key = + atomicModifyIORef ref $ \c -> (delFromUFM c key, ()) removeFromModLocationCache :: IORef ModLocationCache -> Module -> IO () -removeFromModLocationCache ref key = modifyIORef ref $ \c -> delFromFM c key +removeFromModLocationCache ref key = + atomicModifyIORef ref $ \c -> (delModuleEnv c key, ()) lookupFinderCache :: IORef FinderCache -> ModuleName -> IO (Maybe FindResult) lookupFinderCache ref key = do @@ -102,7 +111,7 @@ lookupModLocationCache :: IORef ModLocationCache -> Module -> IO (Maybe ModLocation) lookupModLocationCache ref key = do c <- readIORef ref - return $! lookupFM c key + return $! lookupModuleEnv c key -- ----------------------------------------------------------------------------- -- The two external entry points @@ -113,27 +122,20 @@ lookupModLocationCache ref key = do -- packages to find the module, if a package is specified then only -- that package is searched for the module. -findImportedModule :: HscEnv -> ModuleName -> Maybe PackageId -> IO FindResult -findImportedModule hsc_env mod_name mb_pkgid = - case mb_pkgid of - Nothing -> unqual_import - Just pkg | pkg == this_pkg -> home_import - | otherwise -> pkg_import pkg +findImportedModule :: HscEnv -> ModuleName -> Maybe FastString -> IO FindResult +findImportedModule hsc_env mod_name mb_pkg = + case mb_pkg of + Nothing -> unqual_import + Just pkg | pkg == fsLit "this" -> home_import -- "this" is special + | otherwise -> pkg_import where - dflags = hsc_dflags hsc_env - this_pkg = thisPackage dflags - - home_import = findHomeModule hsc_env mod_name + home_import = findHomeModule hsc_env mod_name - pkg_import pkg = findPackageModule hsc_env (mkModule pkg mod_name) - -- ToDo: this isn't quite right, the module we want - -- might actually be in another package, but re-exposed - -- ToDo: should return NotFoundInPackage if - -- the module isn't exposed by the package. + pkg_import = findExposedPackageModule hsc_env mod_name mb_pkg - unqual_import = home_import - `orIfNotFound` - findExposedPackageModule hsc_env mod_name + unqual_import = home_import + `orIfNotFound` + findExposedPackageModule hsc_env mod_name Nothing -- | Locate a specific 'Module'. The purpose of this function is to -- create a 'ModLocation' for a given 'Module', that is to find out @@ -152,14 +154,21 @@ findExactModule hsc_env mod = -- Helpers orIfNotFound :: IO FindResult -> IO FindResult -> IO FindResult -this `orIfNotFound` or_this = do +orIfNotFound this or_this = do res <- this case res of - NotFound here _ -> do - res2 <- or_this - case res2 of - NotFound or_here pkg -> return (NotFound (here ++ or_here) pkg) - _other -> return res2 + NotFound { fr_paths = paths1, fr_mods_hidden = mh1 + , fr_pkgs_hidden = ph1, fr_suggestions = s1 } + -> do res2 <- or_this + case res2 of + NotFound { fr_paths = paths2, fr_pkg = mb_pkg2, fr_mods_hidden = mh2 + , fr_pkgs_hidden = ph2, fr_suggestions = s2 } + -> return (NotFound { fr_paths = paths1 ++ paths2 + , fr_pkg = mb_pkg2 -- snd arg is the package search + , fr_mods_hidden = mh1 ++ mh2 + , fr_pkgs_hidden = ph1 ++ ph2 + , fr_suggestions = s1 ++ s2 }) + _other -> return res2 _other -> return res @@ -176,28 +185,42 @@ homeSearchCache hsc_env mod_name do_this = do _other -> return () return result -findExposedPackageModule :: HscEnv -> ModuleName -> IO FindResult -findExposedPackageModule hsc_env mod_name +findExposedPackageModule :: HscEnv -> ModuleName -> Maybe FastString + -> IO FindResult +findExposedPackageModule hsc_env mod_name mb_pkg -- not found in any package: - | null found = return (NotFound [] Nothing) - -- found in just one exposed package: - | [(pkg_conf, _)] <- found_exposed - = let pkgid = mkPackageId (package pkg_conf) in - findPackageModule_ hsc_env (mkModule pkgid mod_name) pkg_conf - -- not found in any exposed package, report how it was hidden: - | null found_exposed, ((pkg_conf, exposed_mod):_) <- found - = let pkgid = mkPackageId (package pkg_conf) in - if not (exposed_mod) - then return (ModuleHidden pkgid) - else return (PackageHidden pkgid) - | otherwise - = return (FoundMultiple (map (mkPackageId.package.fst) found_exposed)) - where - dflags = hsc_dflags hsc_env - found = lookupModuleInAllPackages dflags mod_name - found_exposed = filter is_exposed found - is_exposed (pkg_conf,exposed_mod) = exposed pkg_conf && exposed_mod - + = case lookupModuleWithSuggestions (hsc_dflags hsc_env) mod_name of + Left suggest -> return (NotFound { fr_paths = [], fr_pkg = Nothing + , fr_pkgs_hidden = [], fr_mods_hidden = [] + , fr_suggestions = suggest }) + Right found + | null found_exposed -- Found, but with no exposed copies + -> return (NotFound { fr_paths = [], fr_pkg = Nothing + , fr_pkgs_hidden = pkg_hiddens, fr_mods_hidden = mod_hiddens + , fr_suggestions = [] }) + + | [(pkg_conf,_)] <- found_exposed -- Found uniquely + -> let pkgid = packageConfigId pkg_conf in + findPackageModule_ hsc_env (mkModule pkgid mod_name) pkg_conf + + | otherwise -- Found in more than one place + -> return (FoundMultiple (map (packageConfigId.fst) found_exposed)) + where + for_this_pkg = case mb_pkg of + Nothing -> found + Just p -> filter ((`matches` p) . fst) found + found_exposed = filter is_exposed for_this_pkg + is_exposed (pkg_conf,exposed_mod) = exposed pkg_conf && exposed_mod + + mod_hiddens = [ packageConfigId pkg_conf + | (pkg_conf,False) <- found ] + + pkg_hiddens = [ packageConfigId pkg_conf + | (pkg_conf,_) <- found, not (exposed pkg_conf) ] + + pkg_conf `matches` pkg + = case packageName pkg_conf of + PackageName n -> pkg == mkFastString n modLocationCache :: HscEnv -> Module -> IO FindResult -> IO FindResult modLocationCache hsc_env mod do_this = do @@ -293,24 +316,22 @@ findPackageModule_ hsc_env mod pkg_conf = -- hi-suffix for packages depends on the build tag. package_hisuf | null tag = "hi" | otherwise = tag ++ "_hi" - hi_exts = - [ (package_hisuf, mkHiOnlyModLocation dflags package_hisuf) ] - source_exts = - [ ("hs", mkHiOnlyModLocation dflags package_hisuf) - , ("lhs", mkHiOnlyModLocation dflags package_hisuf) - ] - - -- mkdependHS needs to look for source files in packages too, so - -- that we can make dependencies between package before they have - -- been built. - exts - | MkDepend <- ghcMode dflags = hi_exts ++ source_exts - | otherwise = hi_exts + mk_hi_loc = mkHiOnlyModLocation dflags package_hisuf + + import_dirs = importDirs pkg_conf -- we never look for a .hi-boot file in an external package; -- .hi-boot files only make sense for the home package. in - searchPathExts (importDirs pkg_conf) mod exts + case import_dirs of + [one] | MkDepend <- ghcMode dflags -> do + -- there's only one place that this .hi file can be, so + -- don't bother looking for it. + let basename = moduleNameSlashes (moduleName mod) + loc <- mk_hi_loc one basename + return (Found loc mod) + _otherwise -> + searchPathExts import_dirs mod [(package_hisuf, mk_hi_loc)] -- ----------------------------------------------------------------------------- -- General path searching @@ -349,7 +370,11 @@ searchPathExts paths mod exts file = base <.> ext ] - search [] = return (NotFound (map fst to_search) (Just (modulePackageId mod))) + search [] = return (NotFound { fr_paths = map fst to_search + , fr_pkg = Just (modulePackageId mod) + , fr_mods_hidden = [], fr_pkgs_hidden = [] + , fr_suggestions = [] }) + search ((file, mk_result) : rest) = do b <- doesFileExist file if b @@ -489,23 +514,14 @@ mkStubPaths dflags mod location stub_basename = stub_basename0 ++ "_stub" - -- this is the filename we're going to use when - -- #including the stub_h file from the .hc file. - -- Without -stubdir, we just #include the basename - -- (eg. for a module A.B, we #include "B_stub.h"), - -- relying on the fact that we add an implicit -I flag - -- for the directory in which the source file resides - -- (see DriverPipeline.hs). With -stubdir, we - -- #include "A/B.h", assuming that the user has added - -- -I