2 % (c) The University of Glasgow, 2000
4 \section[Finder]{Module Finder}
8 initFinder, -- :: [PackageConfig] -> IO (),
9 findModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
10 findPackageModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
11 mkHomeModuleLocn, -- :: ModuleName -> String -> Maybe FilePath
12 -- -> IO ModuleLocation
13 emptyHomeDirCache, -- :: IO ()
14 flushPackageCache -- :: [PackageConfig] -> IO ()
17 #include "HsVersions.h"
19 import HscTypes ( ModuleLocation(..) )
20 import Packages ( PackageConfig(..) )
35 The Finder provides a thin filesystem abstraction to the rest of the
36 compiler. For a given module, it knows (a) which package the module
37 lives in, so it can make a Module from a ModuleName, and (b) where the
38 source, interface, and object files for a module live.
41 initFinder :: [PackageConfig] -> IO ()
42 initFinder pkgs = return ()
44 -- empty, and lazilly fill in the package cache
45 flushPackageCache :: [PackageConfig] -> IO ()
46 flushPackageCache pkgs = return ()
48 emptyHomeDirCache :: IO ()
49 emptyHomeDirCache = return ()
51 findModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
53 = do { j <- maybeHomeModule name
55 Just home_module -> return (Just home_module)
56 Nothing -> findPackageModule name
59 maybeHomeModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
60 maybeHomeModule mod_name = do
61 home_path <- readIORef v_Import_paths
63 let mod_str = moduleNameUserString mod_name
64 basename = map (\c -> if c == '.' then '/' else c) mod_str
65 hs = basename ++ ".hs"
66 lhs = basename ++ ".lhs"
68 found <- findOnPath home_path hs
70 -- special case to avoid getting "./foo.hs" all the time
71 Just "." -> mkHomeModuleLocn mod_name basename (Just hs);
72 Just path -> mkHomeModuleLocn mod_name
73 (path ++ '/':basename) (Just (path ++ '/':hs));
76 found <- findOnPath home_path lhs
78 -- special case to avoid getting "./foo.hs" all the time
79 Just "." -> mkHomeModuleLocn mod_name basename (Just lhs);
80 Just path -> mkHomeModuleLocn mod_name
81 (path ++ '/':basename) (Just (path ++ '/':lhs));
84 -- can't find a source file anywhere, check for a lone .hi file.
85 hisuf <- readIORef v_Hi_suf
86 let hi = basename ++ '.':hisuf
87 found <- findOnPath home_path hi
89 Just path -> mkHiOnlyModuleLocn mod_name hi;
92 -- last chance: .hi-boot-<ver> and .hi-boot
93 let hi_boot = basename ++ ".hi-boot"
94 let hi_boot_ver = basename ++ ".hi-boot-" ++ cHscIfaceFileVersion
95 found <- findOnPath home_path hi_boot_ver
97 Just path -> mkHiOnlyModuleLocn mod_name hi;
99 found <- findOnPath home_path hi_boot
101 Just path -> mkHiOnlyModuleLocn mod_name hi;
102 Nothing -> return Nothing
106 mkHiOnlyModuleLocn mod_name hi_file = do
107 return (Just (mkHomeModule mod_name,
109 ml_hspp_file = Nothing,
110 ml_hs_file = Nothing,
111 ml_hi_file = hi_file,
112 ml_obj_file = Nothing
116 -- The .hi file always follows the module name, whereas the object
117 -- file may follow the name of the source file in the case where the
118 -- two differ (see summariseFile in compMan/CompManager.lhs).
120 mkHomeModuleLocn mod_name basename maybe_source_fn = do
122 hisuf <- readIORef v_Hi_suf
123 hidir <- readIORef v_Hi_dir
125 let hi_rest = basename ++ '.':hisuf
126 hi_file | Just d <- hidir = d ++ '/':hi_rest
127 | otherwise = hi_rest
129 -- figure out the .o file name. It also lives in the same dir
130 -- as the source, but can be overriden by a -odir flag.
131 o_file <- odir_ify (basename ++ '.':phaseInputExt Ln) >>= osuf_ify
133 return (Just (mkHomeModule mod_name,
135 ml_hspp_file = Nothing,
136 ml_hs_file = maybe_source_fn,
137 ml_hi_file = hi_file,
138 ml_obj_file = Just o_file
143 findPackageModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
144 findPackageModule mod_name = do
145 pkgs <- getPackageInfo
147 -- hi-suffix for packages depends on the build tag.
149 do tag <- readIORef v_Build_tag
152 else return (tag ++ "_hi")
154 let mod_str = moduleNameUserString mod_name
155 basename = map (\c -> if c == '.' then '/' else c) mod_str
156 hi = basename ++ '.':package_hisuf
158 found <- findOnPackagePath pkgs hi
160 Nothing -> return Nothing
161 Just (pkg_name,path) ->
162 return (Just (mkModule mod_name pkg_name,
164 ml_hspp_file = Nothing,
165 ml_hs_file = Nothing,
166 ml_hi_file = path ++ '/':hi,
167 ml_obj_file = Nothing
171 findOnPackagePath :: [PackageConfig] -> String
172 -> IO (Maybe (PackageName,FilePath))
173 findOnPackagePath pkgs file = loop pkgs
175 loop [] = return Nothing
177 found <- findOnPath (import_dirs p) file
180 Just path -> return (Just (mkFastString (name p), path))
182 findOnPath :: [String] -> String -> IO (Maybe FilePath)
183 findOnPath path s = loop path
185 loop [] = return Nothing
187 let file = d ++ '/':s
188 b <- doesFileExist file
189 if b then return (Just d) else loop ds