moonlight-category-0.1.0.0: src-site/Moonlight/Category/Pure/Site/Graph.hs
-- | Import-graph queries over a site manifest: edges, reachable closure, and
-- import-cycle detection. Reachability and cycle reporting both run on the
-- shared dense closure kernel
-- ("Moonlight.Category.Pure.Finite.DenseReachability").
module Moonlight.Category.Pure.Site.Graph
( siteImportEdges,
siteReachable,
reachableClosure,
importCycles,
)
where
import Data.Function ((&))
import Data.List.NonEmpty (NonEmpty)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Set (Set)
import qualified Data.Set as Set
import qualified Data.Vector as Vector
import Moonlight.Category.Pure.Site.Core (SiteManifest (..))
import Moonlight.Category.Pure.Finite.DenseReachability
( denseClosureCycleComponents,
denseClosureReachabilityRows,
denseReachabilityWithCycles,
objectComponentsFromIndices,
objectIndexOf,
objectSetFromBits,
relationBitRows,
relationUniverse,
)
siteImportEdges :: Ord obj => SiteManifest obj -> Set (obj, obj)
siteImportEdges manifest =
siteImports manifest
& Map.foldMapWithKey
(\targetObject sources -> Set.map (\sourceObject -> (targetObject, sourceObject)) sources)
siteReachable :: Ord obj => SiteManifest obj -> obj -> Set obj
siteReachable manifest start =
Map.findWithDefault Set.empty start (reachableClosure (siteImports manifest))
reachableClosure :: Ord obj => Map obj (Set obj) -> Map obj (Set obj)
reachableClosure adjacency =
let objectVector = Vector.fromList (Set.toAscList (relationUniverse adjacency))
objectIndex = objectIndexOf objectVector
closureRows =
denseClosureReachabilityRows
(denseReachabilityWithCycles (relationBitRows objectIndex objectVector adjacency))
reachableSet objectValue =
maybe
Set.empty
(objectSetFromBits objectVector)
(Map.lookup objectValue objectIndex >>= (closureRows Vector.!?))
in Map.mapWithKey (\objectValue _ -> reachableSet objectValue) adjacency
importCycles :: Ord obj => SiteManifest obj -> [NonEmpty obj]
importCycles manifest =
let objectVector = Vector.fromList (Set.toAscList (siteObjects manifest))
objectIndex = objectIndexOf objectVector
closure =
denseReachabilityWithCycles
(relationBitRows objectIndex objectVector (siteImports manifest))
in objectComponentsFromIndices objectVector (denseClosureCycleComponents closure)