- = filter ((`notElem` mods_to_zap_names).name_of_summary) modsDone
- let mods_to_keep_names
- = map name_of_summary mods_to_keep
- -- we could get the relevant linkables by filtering newLis, but
- -- it seems easier to drag them out of the updated, cleaned-up UI
- let linkables_to_link
- = map (unJust "linkables_to_link" . findModuleLinkable_maybe ui4)
- mods_to_keep_names
-
- linkresult <- link ghci_mode False linkables_to_link pls1
- case linkresult of
- LinkErrs _ _
- -> panic "cmLoadModule: link failed (2)"
- LinkOK pls4
- -> do let pcms4 = PersistentCMState { hst=hst4, hit=hit4,
- ui=ui4, mg=mods_to_keep,
- pci=pcii, gmode=ghci_mode }
- let cmstate4
- = CmState { pcms=pcms4, pcs=pcs3, pls=pls4 }
- return (cmstate4,
- -- choose rather arbitrarily who to return
- if null mods_to_keep then Nothing
- else Just (last mods_to_keep_names))
-
-
--- Given a bunch of old summaries and a new summary, try and
--- find the corresponding old summary, and, if found, compare
--- its source timestamp with that of the new summary. If in
--- doubt say True.
-summary_indicates_source_changed :: [ModSummary] -> ModSummary -> Bool
-summary_indicates_source_changed old_summaries new_summary
- = panic "SISC"
-#if 0
- = case [old | old <- old_summaries,
- name_of_summary old == name_of_summary new_summary] of
-
- (_:_:_) -> panic "summary_indicates_newer_source"
-
- [] -> -- can't find a corresponding old summary, so
- -- compare source and iface dates in the new summary.
- trace (showSDoc (text "SISC: no old summary, new ="
- <+> pprSummaryTimes new_summary)) (
- case (ms_hs_date new_summary, ms_hi_date new_summary) of
- (Just hs_t, Just hi_t) -> hs_t > hi_t
- other -> True
- )
-
- [old] -> -- found old summary; compare source timestamps
- trace (showSDoc (text "SISC: old ="
- <+> pprSummaryTimes old
- <+> pprSummaryTimes new_summary)) (
- case (ms_hs_date old, ms_hs_date new_summary) of
- (Just old_t, Just new_t) -> new_t > old_t
- other -> True
- )
-#endif
+ = filter ((`notElem` mods_to_zap_names).name_of_summary)
+ modsDone
+
+ let (hst4, hit4, ui4)
+ = retainInTopLevelEnvs (map name_of_summary mods_to_keep)
+ (hst3,hit3,ui3)
+
+ -- clean up after ourselves
+ cleanTempFilesExcept verb (ppFilesFromSummaries mods_to_keep)
+
+ -- link everything together
+ linkresult <- link ghci_mode dflags False ui4 pls2
+
+ cmLoadFinish False linkresult
+ hst4 hit4 ui4 mods_to_keep ghci_mode pcs3
+
+
+-- Finish up after a cmLoad.
+--
+-- Empty the interactive context and set the module context to the topmost
+-- newly loaded module, or the Prelude if none were loaded.
+cmLoadFinish ok linkresult hst hit ui mods ghci_mode pcs
+ = do case linkresult of {
+ LinkErrs _ _ -> panic "cmLoadModule: link failed (2)";
+ LinkOK pls -> do
+
+ def_mod <- readIORef defaultCurrentModule
+ let current_mod = case mods of
+ [] -> def_mod
+ (x:_) -> ms_mod x
+
+ new_ic = emptyInteractiveContext current_mod
+
+ new_cmstate = CmState{ hst=hst, hit=hit,
+ ui=ui, mg=mods,
+ gmode=ghci_mode, pcs=pcs,
+ pls=pls,
+ ic = new_ic }
+ mods_loaded = map (moduleNameUserString.name_of_summary) mods
+
+ return (new_cmstate, ok, mods_loaded)
+ }
+
+-- used to fish out the preprocess output files for the purposes
+-- of cleaning up.
+ppFilesFromSummaries summaries
+ = [ fn | Just fn <- map toPpFile summaries ]
+ where
+ toPpFile sum
+ | hspp /= ml_hs_file loc = hspp
+ | otherwise = Nothing
+ where
+ loc = ms_location sum
+ hspp = ml_hspp_file loc
+
+
+-----------------------------------------------------------------------------
+-- getValidLinkables
+
+-- For each module (or SCC of modules), we take:
+--
+-- - an on-disk linkable, if this is the first time around and one
+-- is available.
+--
+-- - the old linkable, otherwise (and if one is available).
+--
+-- and we throw away the linkable if it is older than the source
+-- file. We ignore the on-disk linkables unless all of the dependents
+-- of this SCC also have on-disk linkables.
+--
+-- If a module has a valid linkable, then it may be STABLE (see below),
+-- and it is classified as SOURCE UNCHANGED for the purposes of calling
+-- compile.
+--
+-- ToDo: this pass could be merged with the preUpsweep.
+
+getValidLinkables
+ :: [Linkable] -- old linkables
+ -> [ModuleName] -- all home modules
+ -> [SCC ModSummary] -- all modules in the program, dependency order
+ -> IO [Linkable] -- still-valid linkables
+
+getValidLinkables old_linkables all_home_mods module_graph
+ = foldM (getValidLinkablesSCC old_linkables all_home_mods) [] module_graph
+
+getValidLinkablesSCC old_linkables all_home_mods new_linkables scc0
+ = let
+ scc = flattenSCC scc0
+ scc_names = map name_of_summary scc
+ home_module m = m `elem` all_home_mods && m `notElem` scc_names
+ scc_allhomeimps = nub (filter home_module (concatMap ms_imps scc))
+ -- NOTE: ms_imps, not ms_allimps above. We don't want to
+ -- force a module's SOURCE imports to be already compiled for
+ -- its object linkable to be valid.
+
+ has_object m = case findModuleLinkable_maybe new_linkables m of
+ Nothing -> False
+ Just l -> isObjectLinkable l
+
+ objects_allowed = all has_object scc_allhomeimps
+ in do
+
+ these_linkables
+ <- foldM (getValidLinkable old_linkables objects_allowed) [] scc
+
+ -- since an scc can contain only all objects or no objects at all,
+ -- we have to check whether we got all objects or not, and re-do
+ -- the linkable check if not.
+ adjusted_linkables
+ <- if objects_allowed && not (all isObjectLinkable these_linkables)
+ then foldM (getValidLinkable old_linkables False) [] scc
+ else return these_linkables
+
+ return (adjusted_linkables ++ new_linkables)
+
+
+getValidLinkable :: [Linkable] -> Bool -> [Linkable] -> ModSummary
+ -> IO [Linkable]
+getValidLinkable old_linkables objects_allowed new_linkables summary
+ = do let mod_name = name_of_summary summary
+
+ maybe_disk_linkable
+ <- if (not objects_allowed)
+ then return Nothing
+ else case ml_obj_file (ms_location summary) of
+ Just obj_fn -> maybe_getFileLinkable mod_name obj_fn
+ Nothing -> return Nothing
+
+ let old_linkable = findModuleLinkable_maybe old_linkables mod_name
+ maybe_old_linkable =
+ case old_linkable of
+ Just l | not (isObjectLinkable l) || stillThere l
+ -> old_linkable
+ -- ToDo: emit a warning if not (stillThere l)
+ other -> Nothing
+
+ -- make sure that if we had an old disk linkable around, that it's
+ -- still there on the disk (in case we need to re-link it).
+ stillThere l =
+ case maybe_disk_linkable of
+ Nothing -> False
+ Just l_disk -> linkableTime l == linkableTime l_disk
+
+ -- we only look for objects on disk the first time around;
+ -- if the user compiles a module on the side during a GHCi session,
+ -- it won't be picked up until the next ":load". This is what the
+ -- "null old_linkables" test below is.
+ linkable | null old_linkables = maybeToList maybe_disk_linkable
+ | otherwise = maybeToList maybe_old_linkable
+
+ -- only linkables newer than the source code are valid
+ src_date = ms_hs_date summary
+
+ valid_linkable
+ = filter (\l -> linkableTime l >= src_date) linkable
+ -- why '>=' rather than '>' above? If the filesystem stores
+ -- times to the nearset second, we may occasionally find that
+ -- the object & source have the same modification time,
+ -- especially if the source was automatically generated
+ -- and compiled. Using >= is slightly unsafe, but it matches
+ -- make's behaviour.
+
+ return (valid_linkable ++ new_linkables)