2 % (c) The University of Glasgow, 2000
4 \section[Finder]{Module Finder}
8 initFinder, -- :: [PackageConfig] -> IO (),
9 findModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
10 mkHomeModuleLocn, -- :: ModuleName -> String -> Maybe FilePath
11 -- -> IO ModuleLocation
12 emptyHomeDirCache, -- :: IO ()
13 flushPackageCache -- :: [PackageConfig] -> IO ()
16 #include "HsVersions.h"
18 import HscTypes ( ModuleLocation(..) )
27 import Panic ( panic )
38 The Finder provides a thin filesystem abstraction to the rest of the
39 compiler. For a given module, it knows (a) which package the module
40 lives in, so it can make a Module from a ModuleName, and (b) where the
41 source, interface, and object files for a module live.
44 initFinder :: [PackageConfig] -> IO ()
45 initFinder pkgs = return ()
47 -- empty, and lazilly fill in the package cache
48 flushPackageCache :: [PackageConfig] -> IO ()
49 flushPackageCache pkgs = return ()
51 emptyHomeDirCache :: IO ()
52 emptyHomeDirCache = return ()
54 findModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
56 = do { j <- maybeHomeModule name
58 Just home_module -> return (Just home_module)
59 Nothing -> maybePackageModule name
62 maybeHomeModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
63 maybeHomeModule mod_name = do
64 home_path <- readIORef v_Import_paths
66 let mod_str = moduleNameUserString mod_name
67 basename = map (\c -> if c == '.' then '/' else c) mod_str
68 hs = basename ++ ".hs"
69 lhs = basename ++ ".lhs"
71 found <- findOnPath home_path hs
73 -- special case to avoid getting "./foo.hs" all the time
74 Just "." -> mkHomeModuleLocn mod_name basename (Just hs);
75 Just path -> mkHomeModuleLocn mod_name
76 (path ++ '/':basename) (Just (path ++ '/':hs));
79 found <- findOnPath home_path lhs
81 -- special case to avoid getting "./foo.hs" all the time
82 Just "." -> mkHomeModuleLocn mod_name basename (Just lhs);
83 Just path -> mkHomeModuleLocn mod_name
84 (path ++ '/':basename) (Just (path ++ '/':lhs));
87 -- can't find a source file anywhere, check for a lone .hi file.
88 hisuf <- readIORef v_Hi_suf
89 let hi = basename ++ '.':hisuf
90 found <- findOnPath home_path hi
92 Just path -> mkHiOnlyModuleLocn mod_name hi;
95 -- last chance: .hi-boot-<ver> and .hi-boot
96 let hi_boot = basename ++ ".hi-boot"
97 let hi_boot_ver = basename ++ ".hi-boot-" ++ cHscIfaceFileVersion
98 found <- findOnPath home_path hi_boot_ver
100 Just path -> mkHiOnlyModuleLocn mod_name hi;
102 found <- findOnPath home_path hi_boot
104 Just path -> mkHiOnlyModuleLocn mod_name hi;
105 Nothing -> return Nothing
109 mkHiOnlyModuleLocn mod_name hi_file = do
110 return (Just (mkHomeModule mod_name,
112 ml_hspp_file = Nothing,
113 ml_hs_file = Nothing,
114 ml_hi_file = hi_file,
115 ml_obj_file = Nothing
119 -- The .hi file always follows the module name, whereas the object
120 -- file may follow the name of the source file in the case where the
121 -- two differ (see summariseFile in compMan/CompManager.lhs).
123 mkHomeModuleLocn mod_name basename maybe_source_fn = do
125 hisuf <- readIORef v_Hi_suf
126 hidir <- readIORef v_Hi_dir
128 let hi_rest = basename ++ '.':hisuf
129 hi_file | Just d <- hidir = d ++ '/':hi_rest
130 | otherwise = hi_rest
132 -- figure out the .o file name. It also lives in the same dir
133 -- as the source, but can be overriden by a -odir flag.
134 o_file <- odir_ify (basename ++ '.':phaseInputExt Ln) >>= osuf_ify
136 return (Just (mkHomeModule mod_name,
138 ml_hspp_file = Nothing,
139 ml_hs_file = maybe_source_fn,
140 ml_hi_file = hi_file,
141 ml_obj_file = Just o_file
146 maybePackageModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
147 maybePackageModule mod_name = do
148 pkgs <- getPackageInfo
150 -- hi-suffix for packages depends on the build tag.
152 do tag <- readIORef v_Build_tag
155 else return (tag ++ "_hi")
157 let basename = moduleNameUserString mod_name
158 hi = basename ++ '.':package_hisuf
160 found <- findOnPackagePath pkgs hi
162 Nothing -> return Nothing
163 Just (pkg_name,path) ->
164 return (Just (mkModule mod_name pkg_name,
166 ml_hspp_file = Nothing,
167 ml_hs_file = Nothing,
169 ml_obj_file = Nothing
173 findOnPackagePath :: [PackageConfig] -> String
174 -> IO (Maybe (PackageName,FilePath))
175 findOnPackagePath pkgs file = loop pkgs
177 loop [] = return Nothing
179 found <- findOnPath (import_dirs p) file
182 Just f -> return (Just (mkFastString (name p), f))
184 findOnPath :: [String] -> String -> IO (Maybe FilePath)
185 findOnPath path s = loop path
187 loop [] = return Nothing
189 let file = d ++ '/':s
190 b <- doesFileExist file
191 if b then return (Just d) else loop ds