\begin{code}
module Finder (
initFinder, -- :: [PackageConfig] -> IO (),
- findModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
- findModuleDep, -- :: ModuleName -> Bool -> IO (Maybe (Module, ModuleLocation))
- findPackageModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
+ findModule, -- :: ModuleName -> IO (Maybe (Module, ModLocation))
+ findModuleDep, -- :: ModuleName -> Bool -> IO (Maybe (Module, ModLocation))
+ findPackageModule, -- :: ModuleName -> IO (Maybe (Module, ModLocation))
mkHomeModuleLocn, -- :: ModuleName -> String -> FilePath
- -- -> IO ModuleLocation
+ -- -> IO ModLocation
emptyHomeDirCache, -- :: IO ()
flushPackageCache -- :: [PackageConfig] -> IO ()
) where
#include "HsVersions.h"
-import HscTypes ( ModuleLocation(..) )
+import Module ( Module, ModLocation(..), ModuleName,
+ moduleNameUserString, mkHomeModule, mkPackageModule
+ )
import Packages ( PackageConfig(..) )
import DriverPhases
import DriverState
import DriverUtil
-import Module
import FastString
import Config
-import IOExts
+import DATA_IOREF ( readIORef )
+
import List
import Directory
import IO
\end{code}
The Finder provides a thin filesystem abstraction to the rest of the
-compiler. For a given module, it knows (a) which package the module
-lives in, so it can make a Module from a ModuleName, and (b) where the
-source, interface, and object files for a module live.
+compiler. For a given module, it knows (a) whether the module lives
+in the home package or in another package, so it can make a Module
+from a ModuleName, and (b) where the source, interface, and object
+files for a module live.
+
+It does *not* know which particular package a module lives in, because
+that information is only contained in the interface file.
\begin{code}
initFinder :: [PackageConfig] -> IO ()
emptyHomeDirCache :: IO ()
emptyHomeDirCache = return ()
-findModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
+findModule :: ModuleName -> IO (Maybe (Module, ModLocation))
findModule name = findModuleDep name False
-findModuleDep :: ModuleName -> Bool -> IO (Maybe (Module, ModuleLocation))
+findModuleDep :: ModuleName -> Bool -> IO (Maybe (Module, ModLocation))
findModuleDep name is_source
= do { j <- maybeHomeModule name is_source
; case j of
Just home_module -> return (Just home_module)
- Nothing -> findPackageMod name False
+ Nothing -> findPackageMod name False is_source
}
-maybeHomeModule :: ModuleName -> Bool -> IO (Maybe (Module, ModuleLocation))
+maybeHomeModule :: ModuleName -> Bool -> IO (Maybe (Module, ModLocation))
maybeHomeModule mod_name is_source = do
home_path <- readIORef v_Import_paths
hisuf <- readIORef v_Hi_suf
-- When generating dependencies, we're interested in either category.
--
source_exts =
- [ ("hs", \ _ fName path -> mkHomeModuleLocn mod_name path fName)
- , ("lhs", \ _ fName path -> mkHomeModuleLocn mod_name path fName)
- ]
- hi_exts = [ (hisuf, \ _ fName path -> mkHiOnlyModuleLocn mod_name fName) ]
+ [ ("hs", \ fName path -> mkHomeModuleLocn mod_name path fName)
+ , ("lhs", \ fName path -> mkHomeModuleLocn mod_name path fName)
+ ]
+ hi_exts = [ (hisuf, \ fName path -> mkHiOnlyModuleLocn mod_name fName) ]
std_exts
| mode == DoMkDependHS = hi_exts ++ source_exts
hi_boot_ver = "hi-boot-" ++ cHscIfaceFileVersion
boot_exts =
- [ (hi_boot_ver, \ _ fName path -> mkHiOnlyModuleLocn mod_name fName)
- , ("hi-boot", \ _ fName path -> mkHiOnlyModuleLocn mod_name fName)
+ [ (hi_boot_ver, \ fName path -> mkHiOnlyModuleLocn mod_name fName)
+ , ("hi-boot", \ fName path -> mkHiOnlyModuleLocn mod_name fName)
]
- searchPathExts
- (map ((,) undefined) home_path)
- basename
- (if is_source then (boot_exts++std_exts) else std_exts ++ boot_exts)
+ searchPathExts home_path basename
+ (if is_source then boot_exts else (std_exts ++ boot_exts))
-- for SOURCE imports, check the hi-boot extensions
-- before the source/iface ones, to avoid
-- creating circ Makefile deps.
+
mkHiOnlyModuleLocn mod_name hi_file =
return
( mkHomeModule mod_name
- , ModuleLocation{ ml_hspp_file = Nothing
+ , ModLocation{ ml_hspp_file = Nothing
, ml_hs_file = Nothing
, ml_hi_file = hi_file
, ml_obj_file = Nothing
o_file <- odir_ify (basename ++ '.':phaseInputExt Ln) >>= osuf_ify
return (mkHomeModule mod_name,
- ModuleLocation{ ml_hspp_file = Nothing
+ ModLocation{ ml_hspp_file = Nothing
, ml_hs_file = Just source_fn
, ml_hi_file = hi
, ml_obj_file = Just o_file
findPackageMod :: ModuleName
-> Bool
- -> IO (Maybe (Module, ModuleLocation))
-findPackageMod mod_name hiOnly = do
+ -> Bool
+ -> IO (Maybe (Module, ModLocation))
+findPackageMod mod_name hiOnly is_source = do
pkgs <- getPackageInfo
-- hi-suffix for packages depends on the build tag.
if null tag
then return "hi"
else return (tag ++ "_hi")
- let imp_dirs = concatMap (\ pkg -> map ((,) pkg) (import_dirs pkg)) pkgs
+ let imp_dirs = concatMap import_dirs pkgs
mod_str = moduleNameUserString mod_name
basename = map (\c -> if c == '.' then '/' else c) mod_str
- mkPackageModule mod_name pkg mbFName path =
- return ( mkModule mod_name (mkFastString (name pkg))
- , ModuleLocation{ ml_hspp_file = Nothing
+ retPackageModule mod_name mbFName path =
+ return ( mkPackageModule mod_name
+ , ModLocation{ ml_hspp_file = Nothing
, ml_hs_file = mbFName
, ml_hi_file = path ++ '.':package_hisuf
, ml_obj_file = Nothing
})
+ -- last chance: .hi-boot-<ver> and .hi-boot
+ hi_boot_ver = "hi-boot-" ++ cHscIfaceFileVersion
+
+ boot_exts =
+ [ (hi_boot_ver, \ fName path -> mkHiOnlyModuleLocn mod_name fName)
+ , ("hi-boot", \ fName path -> mkHiOnlyModuleLocn mod_name fName)
+ ]
+
searchPathExts
imp_dirs basename
- ((package_hisuf,\ pkg fName path -> mkPackageModule mod_name pkg Nothing path) :
- -- can packages contain hi-boots?
- (if hiOnly then [] else
- [ ("hs", \ pkg fName path -> mkPackageModule mod_name pkg (Just fName) path)
- , ("lhs", \ pkg fName path -> mkPackageModule mod_name pkg (Just fName) path)
- ]))
+ (if is_source then boot_exts else
+ ((package_hisuf,\ fName path -> retPackageModule mod_name Nothing path) :
+ (if hiOnly then [] else
+ [ ("hs", \ fName path -> retPackageModule mod_name (Just fName) path)
+ , ("lhs", \ fName path -> retPackageModule mod_name (Just fName) path)
+ ])))
where
-findPackageModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
-findPackageModule mod_name = findPackageMod mod_name True
+findPackageModule :: ModuleName -> IO (Maybe (Module, ModLocation))
+findPackageModule mod_name = findPackageMod mod_name True False
-searchPathExts :: [(a, FilePath)]
+searchPathExts :: [FilePath]
-> String
- -> [(String, a -> FilePath -> String -> IO (Module, ModuleLocation))]
- -> IO (Maybe (Module, ModuleLocation))
-searchPathExts path basename exts = search exts
+ -> [(String, FilePath -> String -> IO (Module, ModLocation))]
+ -> IO (Maybe (Module, ModLocation))
+searchPathExts path basename exts = search path
where
- search [] = return Nothing
- search ((x,f):xs) = do
- let fName = (basename ++ '.':x)
- found <- findOnPath path fName
- case found of
- -- special case to avoid getting "./foo.<ext>" all the time
- Just (v,".") -> fmap Just (f v fName basename)
- Just (v,path) -> fmap Just (f v (path ++ '/':fName)
- (path ++ '/':basename))
- Nothing -> search xs
-
-findOnPath :: [(a,String)] -> String -> IO (Maybe (a, FilePath))
-findOnPath path s = loop path
- where
- loop [] = return Nothing
- loop ((a,d):ds) = do
- let file = d ++ '/':s
- b <- doesFileExist file
- if b then return (Just (a,d)) else loop ds
+ search [] = return Nothing
+ search (p:ps) = loop exts
+ where
+ base | p == "." = basename
+ | otherwise = p ++ '/':basename
+
+ loop [] = search ps
+ loop ((ext,fn):exts) = do
+ let file = base ++ '.':ext
+ b <- doesFileExist file
+ if b then Just `liftM` fn file base
+ else loop exts
\end{code}