| ... |
... |
@@ -5,8 +5,6 @@ |
|
5
|
5
|
{-# LANGUAGE RecordWildCards #-}
|
|
6
|
6
|
{-# LANGUAGE BlockArguments #-}
|
|
7
|
7
|
{-# LANGUAGE ViewPatterns #-}
|
|
8
|
|
-{-# LANGUAGE TypeFamilies #-}
|
|
9
|
|
-{-# LANGUAGE FunctionalDependencies #-}
|
|
10
|
8
|
module GHC.Driver.Downsweep
|
|
11
|
9
|
( downsweep
|
|
12
|
10
|
, downsweepThunk
|
| ... |
... |
@@ -148,6 +146,9 @@ See also Note [Downsweep Control Flow and Caching] |
|
148
|
146
|
-}
|
|
149
|
147
|
|
|
150
|
148
|
-----------------------------------------------------------------------------
|
|
|
149
|
+-- * Top-level entry to downsweep
|
|
|
150
|
+-----------------------------------------------------------------------------
|
|
|
151
|
+
|
|
151
|
152
|
--
|
|
152
|
153
|
-- | Downsweep (dependency analysis) for --make mode
|
|
153
|
154
|
--
|
| ... |
... |
@@ -159,7 +160,7 @@ See also Note [Downsweep Control Flow and Caching] |
|
159
|
160
|
-- cache to avoid recalculating a module summary if the source is
|
|
160
|
161
|
-- unchanged.
|
|
161
|
162
|
--
|
|
162
|
|
--- Downsweeping can start from scratch for from a given module graph. In the
|
|
|
163
|
+-- Downsweeping can start from scratch or from a given module graph. In the
|
|
163
|
164
|
-- latter case, the given graph is fully included in the resulting graph, even
|
|
164
|
165
|
-- if parts of it are not reachable from any of the given roots. When an import
|
|
165
|
166
|
-- is processed, the source of the imported module is not consulted if this
|
| ... |
... |
@@ -231,6 +232,35 @@ downsweep hsc_env diag_wrapper msg old_summaries maybe_base_graph excl_mods allo |
|
231
|
232
|
unitModuleNodes summaries uid hue =
|
|
232
|
233
|
maybeToList (linkNodes summaries uid hue)
|
|
233
|
234
|
|
|
|
235
|
+ -- The linking plan for each module. If we need to do linking for a home unit
|
|
|
236
|
+ -- then this function returns a graph node which depends on all the modules in the home unit.
|
|
|
237
|
+
|
|
|
238
|
+ -- At the moment nothing can depend on these LinkNodes.
|
|
|
239
|
+ linkNodes :: [ModuleGraphNode] -> UnitId -> HomeUnitEnv -> Maybe (Either (Messages DriverMessage) ModuleGraphNode)
|
|
|
240
|
+ linkNodes summaries uid hue =
|
|
|
241
|
+ let dflags = homeUnitEnv_dflags hue
|
|
|
242
|
+ ofile = outputFile_ dflags
|
|
|
243
|
+
|
|
|
244
|
+ unit_nodes :: [NodeKey]
|
|
|
245
|
+ unit_nodes = map mkNodeKey (filter ((== uid) . mgNodeUnitId) summaries)
|
|
|
246
|
+ -- Issue a warning for the confusing case where the user
|
|
|
247
|
+ -- said '-o foo' but we're not going to do any linking.
|
|
|
248
|
+ -- We attempt linking if either (a) one of the modules is
|
|
|
249
|
+ -- called Main, or (b) the user said -no-hs-main, indicating
|
|
|
250
|
+ -- that main() is going to come from somewhere else.
|
|
|
251
|
+ --
|
|
|
252
|
+ no_hs_main = gopt Opt_NoHsMain dflags
|
|
|
253
|
+
|
|
|
254
|
+ main_sum = any (== NodeKey_Module (ModNodeKeyWithUid (GWIB (mainModuleNameIs dflags) NotBoot) uid)) unit_nodes
|
|
|
255
|
+
|
|
|
256
|
+ do_linking = main_sum || no_hs_main || ghcLink dflags == LinkDynLib || ghcLink dflags == LinkStaticLib || ghcLink dflags == LinkBytecodeLib
|
|
|
257
|
+
|
|
|
258
|
+ in if | isExecutableLink (ghcLink dflags) && isJust ofile && not do_linking ->
|
|
|
259
|
+ Just (Left $ singleMessage $ mkPlainErrorMsgEnvelope noSrcSpan (DriverRedirectedNoMain $ mainModuleNameIs dflags))
|
|
|
260
|
+ -- This should be an error, not a warning (#10895).
|
|
|
261
|
+ | ghcLink dflags /= NoLink, do_linking -> Just (Right (LinkNode unit_nodes uid))
|
|
|
262
|
+ | otherwise -> Nothing
|
|
|
263
|
+
|
|
234
|
264
|
-- | Calculate the module graph starting from a single ModSummary. The result is a
|
|
235
|
265
|
-- thunk, which when forced will perform the downsweep. This is useful in oneshot
|
|
236
|
266
|
-- mode where the module graph may never be needed.
|
| ... |
... |
@@ -322,7 +352,32 @@ downsweepInstalledModules hsc_env mods = do |
|
322
|
352
|
|
|
323
|
353
|
return (mkModuleGraph mg)
|
|
324
|
354
|
|
|
|
355
|
+-----------------------------------------------------------------------------
|
|
|
356
|
+-- * Orchestrator: downsweepFromRootNodes
|
|
|
357
|
+-----------------------------------------------------------------------------
|
|
325
|
358
|
|
|
|
359
|
+type ModSummaryCache = IORef ModSummaryCacheMap
|
|
|
360
|
+type ImportsCache = IORef ImportsCacheMap
|
|
|
361
|
+
|
|
|
362
|
+-- | A cache from file paths to the already summarised modules. The same file
|
|
|
363
|
+-- can be used in multiple units so the map is actually also keyed by which
|
|
|
364
|
+-- unit the file was used in.
|
|
|
365
|
+--
|
|
|
366
|
+-- We want to reuse ModSummaries as far as possible because the most expensive
|
|
|
367
|
+-- part of downsweep is reading and parsing the headers.
|
|
|
368
|
+--
|
|
|
369
|
+-- See Note [Downsweep Control Flow and Caching]
|
|
|
370
|
+type ModSummaryCacheMap
|
|
|
371
|
+ -- The cache can't be keyed by 'Module' because that isn't sufficient to
|
|
|
372
|
+ -- distinguish .hs from .hs-boot files. Use path+unit instead.
|
|
|
373
|
+ = ( M.Map (UnitId, OsPath) (Either DriverMessages (ModSummary, SummProvenance)) )
|
|
|
374
|
+
|
|
|
375
|
+data SummProvenance
|
|
|
376
|
+ -- | Constructed during this downsweep: trivially up to date
|
|
|
377
|
+ = SummFresh
|
|
|
378
|
+ -- | Carried over from a previous run: may be stale, must be hash-checked
|
|
|
379
|
+ -- (and considered by -fforce-recomp)
|
|
|
380
|
+ | SummOld
|
|
326
|
381
|
|
|
327
|
382
|
-- | Whether downsweep should use compiler or fixed nodes. Compile nodes are used
|
|
328
|
383
|
-- by --make mode, and fixed nodes by oneshot mode.
|
| ... |
... |
@@ -387,14 +442,9 @@ downsweepFromRootNodes hsc_env summ_cache imps_cache maybe_base_graph excl_mods |
|
387
|
442
|
|
|
388
|
443
|
sec = initSourceErrorContext (hsc_dflags hsc_env)
|
|
389
|
444
|
|
|
390
|
|
-calcDeps :: ModSummary -> [(ImportLevel, PkgQual, GenWithIsBoot (Located ModuleName))]
|
|
391
|
|
-calcDeps ms =
|
|
392
|
|
- -- Add a dependency on the HsBoot file if it exists
|
|
393
|
|
- -- This gets passed to the loopImports function which just ignores it if it
|
|
394
|
|
- -- can't be found.
|
|
395
|
|
- [(NormalLevel, NoPkgQual, GWIB (noLoc $ ms_mod_name ms) IsBoot) | NotBoot <- [isBootSummary ms] ] ++
|
|
396
|
|
- [(lvl, b, c) | (lvl, b, c) <- msDeps ms ]
|
|
397
|
|
-
|
|
|
445
|
+--------------------------------------------------------------------------------
|
|
|
446
|
+-- ** 'DownsweepM'
|
|
|
447
|
+--------------------------------------------------------------------------------
|
|
398
|
448
|
|
|
399
|
449
|
type DownsweepM a = ReaderT DownsweepEnv IO a
|
|
400
|
450
|
data DownsweepEnv = DownsweepEnv {
|
| ... |
... |
@@ -405,29 +455,6 @@ data DownsweepEnv = DownsweepEnv { |
|
405
|
455
|
, _downsweep_excl_mods :: [ModuleName]
|
|
406
|
456
|
}
|
|
407
|
457
|
|
|
408
|
|
-type ModSummaryCache = IORef ModSummaryCacheMap
|
|
409
|
|
-type ImportsCache = IORef ImportsCacheMap
|
|
410
|
|
-
|
|
411
|
|
--- | A cache from file paths to the already summarised modules. The same file
|
|
412
|
|
--- can be used in multiple units so the map is actually also keyed by which
|
|
413
|
|
--- unit the file was used in.
|
|
414
|
|
---
|
|
415
|
|
--- We want to reuse ModSummaries as far as possible because the most expensive
|
|
416
|
|
--- part of downsweep is reading and parsing the headers.
|
|
417
|
|
---
|
|
418
|
|
--- See Note [Downsweep Control Flow and Caching]
|
|
419
|
|
-type ModSummaryCacheMap
|
|
420
|
|
- -- The cache can't be keyed by 'Module' because that isn't sufficient to
|
|
421
|
|
- -- distinguish .hs from .hs-boot files. Use path+unit instead.
|
|
422
|
|
- = ( M.Map (UnitId, OsPath) (Either DriverMessages (ModSummary, SummProvenance)) )
|
|
423
|
|
-
|
|
424
|
|
-data SummProvenance
|
|
425
|
|
- -- | Constructed during this downsweep: trivially up to date
|
|
426
|
|
- = SummFresh
|
|
427
|
|
- -- | Carried over from a previous run: may be stale, must be hash-checked
|
|
428
|
|
- -- (and considered by -fforce-recomp)
|
|
429
|
|
- | SummOld
|
|
430
|
|
-
|
|
431
|
458
|
mkModSummaryCache :: [(ModSummary, SummProvenance)] -> ModSummaryCacheMap
|
|
432
|
459
|
mkModSummaryCache summs = foldl' (flip (uncurry addModSummaryCache)) M.empty summs
|
|
433
|
460
|
|
| ... |
... |
@@ -471,6 +498,8 @@ loopUnits base_map homud = loopDownsweepNodes base_map . map (DSUnit h |
|
471
|
498
|
loopInstantiations base_map = loopDownsweepNodes base_map . map (uncurry DSInst)
|
|
472
|
499
|
loopFromInteractive base_map m = loopDownsweepNodes base_map . (:[]) . DSInteractive m
|
|
473
|
500
|
|
|
|
501
|
+--------------------------------------------------------------------------------
|
|
|
502
|
+-- * Expanding 'DownsweepNode's into payload and node dependencies
|
|
474
|
503
|
--------------------------------------------------------------------------------
|
|
475
|
504
|
|
|
476
|
505
|
-- | A 'DownsweepNode' is the basic block of the downsweep algorithm which
|
| ... |
... |
@@ -530,7 +559,24 @@ expandModuleSummary ms = do -- Didn't work out what the imports mean yet, now do |
|
530
|
559
|
hsc_env <- asks downsweep_hsc_env
|
|
531
|
560
|
let home_uid = ms_unitid ms
|
|
532
|
561
|
home_unit = ue_unitHomeUnit home_uid (hsc_unit_env hsc_env)
|
|
533
|
|
- (final_deps, todo) <- fmap unzip $ forM (calcDeps ms) $ \(imp,mb_pkg,gwib) -> do
|
|
|
562
|
+ (final_deps, todo) <- unzip <$> mapM (expandModImport home_uid home_unit) (calcDeps ms)
|
|
|
563
|
+
|
|
|
564
|
+ -- This has the effect of finding a .hs file if we are looking at the .hs-boot file.
|
|
|
565
|
+ boot_todo <-
|
|
|
566
|
+ if | HsBootFile <- ms_hsc_src ms
|
|
|
567
|
+ -> do
|
|
|
568
|
+ r <- downsweepSummarise home_unit NotBoot (noLoc $ ms_mod_name ms) NoPkgQual Nothing
|
|
|
569
|
+ case r of
|
|
|
570
|
+ FoundHome s -> pure [DSMod s]
|
|
|
571
|
+ _ -> pure []
|
|
|
572
|
+ | otherwise -> pure []
|
|
|
573
|
+
|
|
|
574
|
+ return $ NSuccess
|
|
|
575
|
+ ( ModuleNode (catMaybes final_deps) (ModuleNodeCompile ms)
|
|
|
576
|
+ , boot_todo ++ concat todo
|
|
|
577
|
+ )
|
|
|
578
|
+ where
|
|
|
579
|
+ expandModImport home_uid home_unit (imp,mb_pkg,gwib) = do
|
|
534
|
580
|
let GWIB { gwib_mod = L loc mod, gwib_isBoot = is_boot } = gwib
|
|
535
|
581
|
wanted_mod = L loc mod
|
|
536
|
582
|
mb_s <- downsweepSummarise home_unit is_boot wanted_mod mb_pkg Nothing
|
| ... |
... |
@@ -552,20 +598,13 @@ expandModuleSummary ms = do -- Didn't work out what the imports mean yet, now do |
|
552
|
598
|
( Just $ mkModuleEdge imp (NodeKey_Module (mnKey s))
|
|
553
|
599
|
, [DSMod s] )
|
|
554
|
600
|
|
|
555
|
|
- -- This has the effect of finding a .hs file if we are looking at the .hs-boot file.
|
|
556
|
|
- boot_todo <-
|
|
557
|
|
- if | HsBootFile <- ms_hsc_src ms
|
|
558
|
|
- -> do
|
|
559
|
|
- r <- downsweepSummarise home_unit NotBoot (noLoc $ ms_mod_name ms) NoPkgQual Nothing
|
|
560
|
|
- case r of
|
|
561
|
|
- FoundHome s -> pure [DSMod s]
|
|
562
|
|
- _ -> pure []
|
|
563
|
|
- | otherwise -> pure []
|
|
564
|
|
-
|
|
565
|
|
- return $ NSuccess
|
|
566
|
|
- ( ModuleNode (catMaybes final_deps) (ModuleNodeCompile ms)
|
|
567
|
|
- , boot_todo ++ concat todo
|
|
568
|
|
- )
|
|
|
601
|
+ calcDeps :: ModSummary -> [(ImportLevel, PkgQual, GenWithIsBoot (Located ModuleName))]
|
|
|
602
|
+ calcDeps ms =
|
|
|
603
|
+ -- Add a dependency on the HsBoot file if it exists
|
|
|
604
|
+ -- This gets passed to the loopImports function which just ignores it if it
|
|
|
605
|
+ -- can't be found.
|
|
|
606
|
+ [(NormalLevel, NoPkgQual, GWIB (noLoc $ ms_mod_name ms) IsBoot) | NotBoot <- [isBootSummary ms] ] ++
|
|
|
607
|
+ [(lvl, b, c) | (lvl, b, c) <- msDeps ms ]
|
|
569
|
608
|
|
|
570
|
609
|
-- | Expand a 'ModuleNodeFixed' node
|
|
571
|
610
|
-- NB: If you ever reach a Fixed node, everything under that also must be fixed.
|
| ... |
... |
@@ -603,7 +642,7 @@ expandFixedModuleNode key loc = do |
|
603
|
642
|
pure $ Just $ DSMod (ModuleNodeFixed key loc)
|
|
604
|
643
|
_otherwise ->
|
|
605
|
644
|
-- If the finder fails, just keep going, there will be another
|
|
606
|
|
- -- error later.
|
|
|
645
|
+ -- error later when we try to expand this dependency.
|
|
607
|
646
|
pure Nothing
|
|
608
|
647
|
mk_dep _ (Right uid_dep) = do
|
|
609
|
648
|
-- Set active unit so that looking loopUnit finds the correct
|
| ... |
... |
@@ -611,6 +650,19 @@ expandFixedModuleNode key loc = do |
|
611
|
650
|
let home_uid = mnkUnitId key
|
|
612
|
651
|
pure (Just DSUnit{node_uid=uid_dep, home_context_uid=home_uid})
|
|
613
|
652
|
|
|
|
653
|
+ mkFixedEdge :: Either (ImportLevel, ModNodeKeyWithUid) (ImportLevel, UnitId) -> ModuleNodeEdge
|
|
|
654
|
+ mkFixedEdge (Left (lvl, key)) = mkModuleEdge lvl (NodeKey_Module key)
|
|
|
655
|
+ mkFixedEdge (Right (lvl, uid)) = mkModuleEdge lvl (NodeKey_ExternalUnit uid)
|
|
|
656
|
+
|
|
|
657
|
+ ifaceDeps :: Dependencies -> [Either (ImportLevel, ModNodeKeyWithUid) (ImportLevel, UnitId)]
|
|
|
658
|
+ ifaceDeps deps =
|
|
|
659
|
+ [ Left (tcImportLevel lvl, ModNodeKeyWithUid dep uid)
|
|
|
660
|
+ | (lvl, uid, dep) <- Set.toList (dep_direct_mods deps)
|
|
|
661
|
+ ] ++
|
|
|
662
|
+ [ Right (tcImportLevel lvl, uid)
|
|
|
663
|
+ | (lvl, uid) <- Set.toList (dep_direct_pkgs deps)
|
|
|
664
|
+ ]
|
|
|
665
|
+
|
|
614
|
666
|
-- | Expand a unit id under the context of a certain home unit
|
|
615
|
667
|
expandUnitNode :: UnitId {-^ @node_uid@ -} -> UnitId {-^ Home unit from where @node_uid@ was introduced -}
|
|
616
|
668
|
-> DownsweepM (MGRes (ModuleGraphNode, [DownsweepNode]))
|
| ... |
... |
@@ -686,19 +738,8 @@ expandInteractiveImports imod imps = do |
|
686
|
738
|
node_type = ModuleNodeFixed key ml
|
|
687
|
739
|
|
|
688
|
740
|
--------------------------------------------------------------------------------
|
|
689
|
|
-
|
|
690
|
|
-mkFixedEdge :: Either (ImportLevel, ModNodeKeyWithUid) (ImportLevel, UnitId) -> ModuleNodeEdge
|
|
691
|
|
-mkFixedEdge (Left (lvl, key)) = mkModuleEdge lvl (NodeKey_Module key)
|
|
692
|
|
-mkFixedEdge (Right (lvl, uid)) = mkModuleEdge lvl (NodeKey_ExternalUnit uid)
|
|
693
|
|
-
|
|
694
|
|
-ifaceDeps :: Dependencies -> [Either (ImportLevel, ModNodeKeyWithUid) (ImportLevel, UnitId)]
|
|
695
|
|
-ifaceDeps deps =
|
|
696
|
|
- [ Left (tcImportLevel lvl, ModNodeKeyWithUid dep uid)
|
|
697
|
|
- | (lvl, uid, dep) <- Set.toList (dep_direct_mods deps)
|
|
698
|
|
- ] ++
|
|
699
|
|
- [ Right (tcImportLevel lvl, uid)
|
|
700
|
|
- | (lvl, uid) <- Set.toList (dep_direct_pkgs deps)
|
|
701
|
|
- ]
|
|
|
741
|
+-- * Constructing Module Summaries
|
|
|
742
|
+--------------------------------------------------------------------------------
|
|
702
|
743
|
|
|
703
|
744
|
downsweepSummarise :: HomeUnit
|
|
704
|
745
|
-> IsBootInterface
|
| ... |
... |
@@ -745,35 +786,6 @@ instantiationNodes uid unit_state = map (uid,) iuids_to_check |
|
745
|
786
|
, recur <- (indef :) $ goUnitId $ moduleUnit $ snd inst
|
|
746
|
787
|
]
|
|
747
|
788
|
|
|
748
|
|
--- The linking plan for each module. If we need to do linking for a home unit
|
|
749
|
|
--- then this function returns a graph node which depends on all the modules in the home unit.
|
|
750
|
|
-
|
|
751
|
|
--- At the moment nothing can depend on these LinkNodes.
|
|
752
|
|
-linkNodes :: [ModuleGraphNode] -> UnitId -> HomeUnitEnv -> Maybe (Either (Messages DriverMessage) ModuleGraphNode)
|
|
753
|
|
-linkNodes summaries uid hue =
|
|
754
|
|
- let dflags = homeUnitEnv_dflags hue
|
|
755
|
|
- ofile = outputFile_ dflags
|
|
756
|
|
-
|
|
757
|
|
- unit_nodes :: [NodeKey]
|
|
758
|
|
- unit_nodes = map mkNodeKey (filter ((== uid) . mgNodeUnitId) summaries)
|
|
759
|
|
- -- Issue a warning for the confusing case where the user
|
|
760
|
|
- -- said '-o foo' but we're not going to do any linking.
|
|
761
|
|
- -- We attempt linking if either (a) one of the modules is
|
|
762
|
|
- -- called Main, or (b) the user said -no-hs-main, indicating
|
|
763
|
|
- -- that main() is going to come from somewhere else.
|
|
764
|
|
- --
|
|
765
|
|
- no_hs_main = gopt Opt_NoHsMain dflags
|
|
766
|
|
-
|
|
767
|
|
- main_sum = any (== NodeKey_Module (ModNodeKeyWithUid (GWIB (mainModuleNameIs dflags) NotBoot) uid)) unit_nodes
|
|
768
|
|
-
|
|
769
|
|
- do_linking = main_sum || no_hs_main || ghcLink dflags == LinkDynLib || ghcLink dflags == LinkStaticLib || ghcLink dflags == LinkBytecodeLib
|
|
770
|
|
-
|
|
771
|
|
- in if | isExecutableLink (ghcLink dflags) && isJust ofile && not do_linking ->
|
|
772
|
|
- Just (Left $ singleMessage $ mkPlainErrorMsgEnvelope noSrcSpan (DriverRedirectedNoMain $ mainModuleNameIs dflags))
|
|
773
|
|
- -- This should be an error, not a warning (#10895).
|
|
774
|
|
- | ghcLink dflags /= NoLink, do_linking -> Just (Right (LinkNode unit_nodes uid))
|
|
775
|
|
- | otherwise -> Nothing
|
|
776
|
|
-
|
|
777
|
789
|
getRootSummary ::
|
|
778
|
790
|
[ModuleName] ->
|
|
779
|
791
|
ModSummaryCache ->
|
| ... |
... |
@@ -858,6 +870,10 @@ rootSummariesParallel n_jobs hsc_env diag_wrapper msg get_summary = do |
|
858
|
870
|
throwIO e
|
|
859
|
871
|
a -> pure a
|
|
860
|
872
|
|
|
|
873
|
+--------------------------------------------------------------------------------
|
|
|
874
|
+-- * Check/validate properties and error out
|
|
|
875
|
+--------------------------------------------------------------------------------
|
|
|
876
|
+
|
|
861
|
877
|
-- | This function checks then important property that if both p and q are home units
|
|
862
|
878
|
-- then any dependency of p, which transitively depends on q is also a home unit.
|
|
863
|
879
|
--
|
| ... |
... |
@@ -905,6 +921,10 @@ checkHomeUnitsClosed ue |
|
905
|
921
|
let todo'' = (depends Set.\\ done) `Set.union` todo'
|
|
906
|
922
|
in DigraphNode uid uid (Set.toList depends) : go (Set.insert uid done) todo''
|
|
907
|
923
|
|
|
|
924
|
+--------------------------------------------------------------------------------
|
|
|
925
|
+-- * Enable Code Gen for Template Haskell
|
|
|
926
|
+--------------------------------------------------------------------------------
|
|
|
927
|
+
|
|
908
|
928
|
-- | Update the every ModSummary that is depended on
|
|
909
|
929
|
-- by a module that needs template haskell. We enable codegen to
|
|
910
|
930
|
-- the specified target, disable optimization and change the .hi
|
| ... |
... |
@@ -1223,7 +1243,8 @@ Potential TODOS: |
|
1223
|
1243
|
-}
|
|
1224
|
1244
|
|
|
1225
|
1245
|
-----------------------------------------------------------------------------
|
|
1226
|
|
--- Summarising modules
|
|
|
1246
|
+-- * Pre-processing and Summarising and modules
|
|
|
1247
|
+-----------------------------------------------------------------------------
|
|
1227
|
1248
|
|
|
1228
|
1249
|
-- We have two types of summarisation:
|
|
1229
|
1250
|
--
|
| ... |
... |
@@ -1639,6 +1660,8 @@ getPreprocessedImports hsc_env src_fn mb_phase maybe_buf = do |
|
1639
|
1660
|
return PreprocessedImports {..}
|
|
1640
|
1661
|
|
|
1641
|
1662
|
--------------------------------------------------------------------------------
|
|
|
1663
|
+-- * Generic traversal of iteratively-built graph: dfsBuild
|
|
|
1664
|
+--------------------------------------------------------------------------------
|
|
1642
|
1665
|
|
|
1643
|
1666
|
-- | The result of expanding a node in 'dfsBuild'.
|
|
1644
|
1667
|
data MGRes v
|
| ... |
... |
@@ -1657,8 +1680,8 @@ data MGRes v |
|
1657
|
1680
|
-- graph by iteratively expanding a node into a payload and a list of children
|
|
1658
|
1681
|
-- nodes to visit next.
|
|
1659
|
1682
|
--
|
|
1660
|
|
--- A node is NEVER visited/expanded more than once, as long as the the
|
|
1661
|
|
--- node key @k@, computed from the node @n@, uniquely identifies that node.
|
|
|
1683
|
+-- A node is NEVER visited/expanded more than once, as long as the node key
|
|
|
1684
|
+-- @k@, computed from the node @n@, uniquely identifies that node.
|
|
1662
|
1685
|
--
|
|
1663
|
1686
|
-- The first argument @base_map@ is the starting set of already visited nodes
|
|
1664
|
1687
|
-- (these nodes won't be expanded again!).
|
| ... |
... |
@@ -1704,7 +1727,7 @@ dfsBuild base_map roots key expand = go roots (fromMaybe Map.empty base_map) |
|
1704
|
1727
|
go ss
|
|
1705
|
1728
|
(Map.insert k NSkip visited) -- Skip!
|
|
1706
|
1729
|
NSuccess (v,ns) ->
|
|
1707
|
|
- go (ns ++ ss {- todo: not use ++ here? -})
|
|
|
1730
|
+ go (ns ++ ss)
|
|
1708
|
1731
|
(Map.insert k (NSuccess v) visited)
|
|
1709
|
1732
|
where
|
|
1710
|
1733
|
k = key s
|