diff options
author | davve <davve@dtek.chalmers.se> | 2006-08-14 00:56:07 +0000 |
---|---|---|
committer | davve <davve@dtek.chalmers.se> | 2006-08-14 00:56:07 +0000 |
commit | 7ef7e7beb6e79166dec2f31cfbd16f7170066a6b (patch) | |
tree | 02598bd2eecba0277b7707bb1ce46f7b0a3aaebb | |
parent | 454fd062f579dab7daa6f0c8ae94e173f2d46211 (diff) |
Some refactoring
-rw-r--r-- | src/Main.hs | 183 |
1 files changed, 89 insertions, 94 deletions
diff --git a/src/Main.hs b/src/Main.hs index 1043482a..c0e9745f 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -60,13 +60,21 @@ import Packages ----------------------------------------------------------------------------- -- Top-level stuff +type CheckedMods = [(Module, FullyCheckedMod, FilePath)] + main :: IO () main = do args <- getArgs - (libDir, rest) <- getLibDir args - (session, nonGHCOpts) <- startGHC libDir rest - (flags, args) <- parseHaddockOpts nonGHCOpts - run flags args session + (libDir, rest) <- getLibDir args + (session, ghcFlags, nonGHCOpts) <- startGHC libDir rest + (flags, args) <- parseHaddockOpts nonGHCOpts + handleEagerFlags flags + modules <- sortAndCheckModules session ghcFlags args + (ifaces, htmls) <- getIfacesAndHtmls flags ghcFlags + let (modss, envs) = unzip ifaces + updateHTMLXRefs htmls modss + -- TODO: continue to break up the run function into parts + run flags modules envs parseHaddockOpts :: [String] -> IO ([Flag], [String]) parseHaddockOpts words = @@ -76,15 +84,18 @@ parseHaddockOpts words = prog <- getProgramName die (concat errors ++ usageInfo (usageHeader prog) (options False)) +usageHeader :: String -> String +usageHeader prog = "Usage: " ++ prog ++ " [OPTION...] file...\n" + getLibDir :: [String] -> IO (String, [String]) getLibDir ("-B":dir:rest) = return (dir, rest) getLibDir (('-':'B':dir):rest) | not (null dir) = return (dir, rest) getLibDir _ = die "Missing GHC lib dir option: -B <dir>\n" --- | Initialize GHC, then parse the passed in strings and set the corresponding +-- | Initialize GHC, parse the passed in strings and set the corresponding -- GHC flags (if any). Also add the -haddock flag. Return the Session handle -- and the strings that were not GHC flags. -startGHC :: String -> [String] -> IO (Session, [String]) +startGHC :: String -> [String] -> IO (Session, DynFlags, [String]) startGHC libDir possibleOpts = do GHC.init (Just libDir) let ghcMode = JustTypecheck @@ -94,10 +105,48 @@ startGHC libDir possibleOpts = do (flags'', nonOpts) <- parseDynamicFlags flags' possibleOpts let flags''' = dopt_set flags'' Opt_Haddock setSessionDynFlags session flags''' - return (session, nonOpts) - -usageHeader :: String -> String -usageHeader prog = "Usage: " ++ prog ++ " [OPTION...] file...\n" + return (session, flags''', nonOpts) + +sortAndCheckModules :: Session -> DynFlags -> [FilePath] -> + IO [(Module, FullyCheckedMod, FilePath)] +sortAndCheckModules session flags files = defaultErrorHandler flags $ do + targets <- mapM (\s -> guessTarget s Nothing) files + setTargets session targets + mbModGraph <- depanal session [] True + moduleGraph <- case mbModGraph of + Just mg -> return mg + Nothing -> die "Failed to load all modules\n" + let + modSumFile = fromJust . ml_hs_file . ms_location + sortedGraph = topSortModuleGraph False moduleGraph Nothing + sortedModules = concatMap Digraph.flattenSCC sortedGraph + modsAndFiles = [ (ms_mod modsum, modSumFile modsum) | + modsum <- sortedModules, + modSumFile modsum `elem` files ] + checkedMods <- mapM (\(mod, file) -> do + mbMod <- checkModule session mod + checkedMod <- case mbMod of + Just m -> return m + Nothing -> die ("Failed to load module: " ++ moduleString mod) + return (mod, checkedMod, file)) modsAndFiles + ensureFullyChecked checkedMods + where + ensureFullyChecked modules + | length modules' == length modules = return modules' + | otherwise = die "Fail to check all modules properly\n" + where modules' = [ (mod, (a,b,c,d), f) | + (mod, CheckedModule a (Just b) (Just c) (Just d), f) + <- modules ] + +getIfacesAndHtmls :: [Flag] -> DynFlags -> IO ([Interface], [FilePath]) +getIfacesAndHtmls flags dynflags = do + packageFiles <- getPackageFiles dynflags + let + readIfaceFlags = [ parseIfaceOption str | Flag_ReadInterface str <- flags ] + totalFiles = packageFiles ++ readIfaceFlags + (htmlPaths, ifacePaths) = unzip totalFiles + ifaces <- mapM readIface ifacePaths + return (ifaces, htmlPaths) data Flag = Flag_CSS String @@ -198,19 +247,23 @@ options backwardsCompat = "the modules being processed depend on PACKAGE" ] -run :: [Flag] -> [FilePath] -> Session -> IO () -run flags files session = do - +handleEagerFlags flags = do whenFlag Flag_Help $ do prog <- getProgramName bye (usageInfo (usageHeader prog) (options False)) - whenFlag Flag_Version $ bye ("Haddock version " ++ projectVersion ++ ", (c) Simon Marlow 2003; port to GHC-api by David Waern 2006\n") + when ((Flag_GenIndex `elem` flags || Flag_GenContents `elem` flags) + && Flag_Html `elem` flags) $ + die ("-h cannot be used with --gen-index or --gen-contents") + where + whenFlag flag action = when (flag `elem` flags) action - let +run :: [Flag] -> CheckedMods -> [Map Name Name] -> IO () +run flags modules extEnvs = do + let title = case [str | Flag_Heading str <- flags] of [] -> "" (t:_) -> t @@ -245,8 +298,6 @@ run flags files session = do [] -> Nothing fs -> Just (last fs) - readIfaceFlags = [ parseIfaceOption str | Flag_ReadInterface str <- flags ] - maybe_contents_url = case [url | Flag_UseContents url <- flags] of [] -> Nothing @@ -264,88 +315,36 @@ run flags files session = do prologue <- getPrologue flags - when ((Flag_GenIndex `elem` flags || Flag_GenContents `elem` flags) - && Flag_Html `elem` flags) $ - die ("-h cannot be used with --gen-index or --gen-contents") - - ghcFlags <- getSessionDynFlags session - - sorted_checked_modules <- defaultErrorHandler ghcFlags $ do - targets <- mapM (\s -> guessTarget s Nothing) files - setTargets session targets - maybe_module_graph <- depanal session [] True - module_graph <- case maybe_module_graph of - Just module_graph -> return module_graph - Nothing -> die "Failed to load modules 1\n" - - let - modSumFile = fromJust . ml_hs_file . ms_location - sorted_modules = concatMap Digraph.flattenSCC (topSortModuleGraph False module_graph Nothing) - (modules, filenames) = unzip [ (ms_mod modsum, modSumFile modsum) | modsum <- sorted_modules, - modSumFile modsum `elem` files ] - - --print_ modules - mb_checked_modules <- mapM (checkModule session) modules - let checked_modules = catMaybes mb_checked_modules - if length checked_modules /= length mb_checked_modules - then die "Failed to load all modules 2\n" - else return (zip3 modules checked_modules filenames) - - sorted_checked_modules' <- remove_maybes sorted_checked_modules - - let (modMap, messages) = runWriter (pass1 sorted_checked_modules' flags package) - - haddockModules = catMaybes [ Map.lookup mod modMap | - (mod, _, file) <- sorted_checked_modules', - file `elem` files ] - - packageFiles <- getPackageFiles ghcFlags - --print packageFiles let - totalFiles = packageFiles ++ readIfaceFlags - (htmlPaths, ifacePaths) = unzip totalFiles - ifaces <- mapM readIface ifacePaths - - let - (moduless, extEnvs) = unzip ifaces - homeEnv = buildGlobalDocEnv haddockModules + (modMap, messages) = runWriter (pass1 modules flags package) + haddockMods = catMaybes [ Map.lookup mod modMap | (mod,_,_) <- modules ] + homeEnv = buildGlobalDocEnv haddockMods env = Map.unions (homeEnv:extEnvs) - haddockModules' = attachInstances haddockModules - (haddockModules'', messages') = runWriter $ mapM (renameModule env) haddockModules' + haddockMods' = attachInstances haddockMods + (haddockMods'', messages') = runWriter $ mapM (renameModule env) haddockMods' - updateHTMLXRefs htmlPaths moduless - --- putStrLn "pass 1 messages:" mapM_ putStrLn messages -{- putStrLn "pass 1 export items:" - printSDoc (ppr (map hmod_export_items haddockModules')) defaultUserStyle - - putStrLn "pass 2 env:" - printSDoc (ppr (Map.toList env)) defaultUserStyle - - putStrLn "pass 2 export items:" - printSDoc (ppr (map hmod_rn_export_items haddockModules'')) defaultUserStyle -} mapM_ putStrLn messages' - let visibleModules = [ m | m <- haddockModules'', OptHide `notElem` (hmod_options m) ] + let visibleMods = [ m | m <- haddockMods'', OptHide `notElem` (hmod_options m) ] when (Flag_GenIndex `elem` flags) $ do ppHtmlIndex odir title package maybe_html_help_format maybe_contents_url maybe_source_urls maybe_wiki_urls - visibleModules + visibleMods copyHtmlBits odir libdir css_file when (Flag_GenContents `elem` flags && Flag_GenIndex `elem` flags) $ do - ppHtmlHelpFiles title package visibleModules odir maybe_html_help_format [] + ppHtmlHelpFiles title package visibleMods odir maybe_html_help_format [] when (Flag_GenContents `elem` flags) $ do ppHtmlContents odir title package maybe_html_help_format maybe_index_url maybe_source_urls maybe_wiki_urls - visibleModules prologue + visibleMods prologue copyHtmlBits odir libdir css_file when (Flag_Html `elem` flags) $ do - ppHtml title package visibleModules odir + ppHtml title package visibleMods odir prologue maybe_html_help_format maybe_source_urls maybe_wiki_urls maybe_contents_url maybe_index_url @@ -356,18 +355,12 @@ run flags files session = do -- dump an interface if requested case dumpIface of Nothing -> return () - Just fn -> dumpInterfaces env (map hmod_mod visibleModules) fn + Just fn -> dumpInterfaces env (map hmod_mod visibleMods) fn where - whenFlag flag action = when (flag `elem` flags) action - pprList [] = [] pprList [x] = show x pprList (x:xs) = show x ++ ", " ++ pprList xs - remove_maybes modules | length modules' == length modules = return modules' - | otherwise = die "Missing checked module phase information\n" - where modules' = [ (mod, (a,b,c,d), f) | (mod, CheckedModule a (Just b) (Just c) (Just d), f) <- modules ] - print_ x = printSDoc (ppr x) defaultUserStyle instance Outputable (DocEntity Name) where @@ -382,18 +375,18 @@ instance Show a => Show (DocDecl a) where show (DocCommentPrev doc) = "prev" ++ show doc show _ = "other" -type FullyCheckedModule = (ParsedSource, - RenamedSource, - TypecheckedSource, - ModuleInfo) +type FullyCheckedMod = (ParsedSource, + RenamedSource, + TypecheckedSource, + ModuleInfo) printEntity (DocEntity doc) = show doc printEntity (DeclEntity name) = show $ ppr name defaultUserStyle -pass1 :: [(Module, FullyCheckedModule, FilePath)] -> [Flag] -> Maybe String -> ErrMsgM ModuleMap2 +pass1 :: [(Module, FullyCheckedMod, FilePath)] -> [Flag] -> Maybe String -> ErrMsgM ModuleMap2 pass1 modules flags package = worker modules (Map.empty) flags where - worker :: [(Module, FullyCheckedModule, FilePath)] -> ModuleMap2 -> [Flag] -> ErrMsgM ModuleMap2 + worker :: [(Module, FullyCheckedMod, FilePath)] -> ModuleMap2 -> [Flag] -> ErrMsgM ModuleMap2 worker [] moduleMap _ = return moduleMap worker ((mod, checked_mod, filename):rest_modules) moduleMap flags = do @@ -1075,7 +1068,7 @@ getPackageFiles dynflags = do ifaceExists <- doesFileExist iface when (not ifaceExists) $ - throwIO (ErrorCall ("Interace " ++ iface ++ " does not exist.")) + throwIO (ErrorCall ("Interface " ++ iface ++ " does not exist.")) return (html, iface) where @@ -1117,7 +1110,9 @@ mkName mdl occ = mkExternalName (mkUnique 'X' 0) mdl occ Nothing noSrcLoc --type StoredInterface2 = -- (Module,Maybe Doc,Maybe String,Bool,[(HsName,Module)], [(HsName,[HsName])]) -readIface :: FilePath -> IO ([Module], Map Name Name) +type Interface = ([Module], Map Name Name) + +readIface :: FilePath -> IO Interface readIface fileName = do bh <- readBinMem fileName formatVersion <- get bh |