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(..) )
19 import Packages ( PackageConfig(..) )
34 The Finder provides a thin filesystem abstraction to the rest of the
35 compiler. For a given module, it knows (a) which package the module
36 lives in, so it can make a Module from a ModuleName, and (b) where the
37 source, interface, and object files for a module live.
40 initFinder :: [PackageConfig] -> IO ()
41 initFinder pkgs = return ()
43 -- empty, and lazilly fill in the package cache
44 flushPackageCache :: [PackageConfig] -> IO ()
45 flushPackageCache pkgs = return ()
47 emptyHomeDirCache :: IO ()
48 emptyHomeDirCache = return ()
50 findModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
52 = do { j <- maybeHomeModule name
54 Just home_module -> return (Just home_module)
55 Nothing -> maybePackageModule name
58 maybeHomeModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
59 maybeHomeModule mod_name = do
60 home_path <- readIORef v_Import_paths
62 let mod_str = moduleNameUserString mod_name
63 basename = map (\c -> if c == '.' then '/' else c) mod_str
64 hs = basename ++ ".hs"
65 lhs = basename ++ ".lhs"
67 found <- findOnPath home_path hs
69 -- special case to avoid getting "./foo.hs" all the time
70 Just "." -> mkHomeModuleLocn mod_name basename (Just hs);
71 Just path -> mkHomeModuleLocn mod_name
72 (path ++ '/':basename) (Just (path ++ '/':hs));
75 found <- findOnPath home_path lhs
77 -- special case to avoid getting "./foo.hs" all the time
78 Just "." -> mkHomeModuleLocn mod_name basename (Just lhs);
79 Just path -> mkHomeModuleLocn mod_name
80 (path ++ '/':basename) (Just (path ++ '/':lhs));
83 -- can't find a source file anywhere, check for a lone .hi file.
84 hisuf <- readIORef v_Hi_suf
85 let hi = basename ++ '.':hisuf
86 found <- findOnPath home_path hi
88 Just path -> mkHiOnlyModuleLocn mod_name hi;
91 -- last chance: .hi-boot-<ver> and .hi-boot
92 let hi_boot = basename ++ ".hi-boot"
93 let hi_boot_ver = basename ++ ".hi-boot-" ++ cHscIfaceFileVersion
94 found <- findOnPath home_path hi_boot_ver
96 Just path -> mkHiOnlyModuleLocn mod_name hi;
98 found <- findOnPath home_path hi_boot
100 Just path -> mkHiOnlyModuleLocn mod_name hi;
101 Nothing -> return Nothing
105 mkHiOnlyModuleLocn mod_name hi_file = do
106 return (Just (mkHomeModule mod_name,
108 ml_hspp_file = Nothing,
109 ml_hs_file = Nothing,
110 ml_hi_file = hi_file,
111 ml_obj_file = Nothing
115 -- The .hi file always follows the module name, whereas the object
116 -- file may follow the name of the source file in the case where the
117 -- two differ (see summariseFile in compMan/CompManager.lhs).
119 mkHomeModuleLocn mod_name basename maybe_source_fn = do
121 hisuf <- readIORef v_Hi_suf
122 hidir <- readIORef v_Hi_dir
124 let hi_rest = basename ++ '.':hisuf
125 hi_file | Just d <- hidir = d ++ '/':hi_rest
126 | otherwise = hi_rest
128 -- figure out the .o file name. It also lives in the same dir
129 -- as the source, but can be overriden by a -odir flag.
130 o_file <- odir_ify (basename ++ '.':phaseInputExt Ln) >>= osuf_ify
132 return (Just (mkHomeModule mod_name,
134 ml_hspp_file = Nothing,
135 ml_hs_file = maybe_source_fn,
136 ml_hi_file = hi_file,
137 ml_obj_file = Just o_file
142 maybePackageModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
143 maybePackageModule mod_name = do
144 pkgs <- getPackageInfo
146 -- hi-suffix for packages depends on the build tag.
148 do tag <- readIORef v_Build_tag
151 else return (tag ++ "_hi")
153 let basename = moduleNameUserString mod_name
154 hi = basename ++ '.':package_hisuf
156 found <- findOnPackagePath pkgs hi
158 Nothing -> return Nothing
159 Just (pkg_name,path) ->
160 return (Just (mkModule mod_name pkg_name,
162 ml_hspp_file = Nothing,
163 ml_hs_file = Nothing,
165 ml_obj_file = Nothing
169 findOnPackagePath :: [PackageConfig] -> String
170 -> IO (Maybe (PackageName,FilePath))
171 findOnPackagePath pkgs file = loop pkgs
173 loop [] = return Nothing
175 found <- findOnPath (import_dirs p) file
178 Just path -> return (Just (mkFastString (name p), path ++ '/':file))
180 findOnPath :: [String] -> String -> IO (Maybe FilePath)
181 findOnPath path s = loop path
183 loop [] = return Nothing
185 let file = d ++ '/':s
186 b <- doesFileExist file
187 if b then return (Just d) else loop ds