Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/src/compiler98/Scc.hs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


module Scc (sccDepend,Depend(..),isRec) where

import List
import qualified Data.Set as Set
import qualified Data.Map as Map

addSet :: Ord a => Set.Set a -> a -> Set.Set a
addSet as a = if a `Set.member` as then as else Set.insert a as


-- scc :: (Eq a)  => (a->[a]) -> (a->[a]) -> [a] -> [Set a]
scc :: (Ord a) => (a->[a]) -> (a->[a]) -> [a] -> [Set.Set a]
scc ins outs = span . depth
    where depth = snd . depthSearch outs (Set.empty,[])
          span  = snd . spanSearch  ins  (Set.empty,[])


--depthSearch :: (Eq a)  => (a->[a]) -> (Set a,[a]) -> [a] -> (Set a,[a])
depthSearch :: (Ord a) => (a->[a]) -> (Set.Set a,[a]) -> [a] -> (Set.Set a,[a])
depthSearch = foldl . dsearch
    where dsearch rel (visited,seq) v | v `Set.member` visited = (visited,seq)
                                      | otherwise              = (visited',v:seq')
                                     where (visited',seq') = depthSearch rel 
                                                                         (addSet visited v,seq)
                                                                         (rel v)


--spanSearch :: (Eq a)  => (a->[a]) -> (Set a,[Set a]) -> [a] -> (Set a,[Set a])
spanSearch :: (Ord a) => (a->[a]) -> (Set.Set a,[Set.Set a]) -> [a] -> (Set.Set a,[Set.Set a])
spanSearch = foldl . search
     where search rel (visited,setseq) v | v `Set.member` visited = (visited,setseq)
                                         | otherwise        = (visited',Set.fromList (v:seq):setseq)
                                     where (visited',seq) = depthSearch rel 
                                                                        (addSet visited v,[])
                                                                        (rel v)


sccAssoc :: Ord a => Map.Map a [a] -> a -> [a]
sccAssoc at d =
  case Map.lookup d at of
    Nothing -> [d]
    Just ds -> ds

mkout :: Ord k => [(k, [k])] -> k -> [k]
mkout ds = sccAssoc (foldr ( \ (k,vs) at -> Map.insert k vs at ) Map.empty ds)

mkin :: Ord k => [(k, [k])] -> k -> [k]
mkin ds = sccAssoc (foldr ( \ (k,vs) at ->
                                let ks = [k]
                                in foldr ( \ v at -> Map.insertWith comb v ks at) at vs) Map.empty ds)
  where comb [v] vs = v:vs

data Depend a = NoRec a
              | Rec   [a]

isRec :: Depend a -> Bool
isRec (NoRec _) = False
isRec (Rec _) = True

instance (Show a) => Show (Depend a) where
  showsPrec d (NoRec x)    = ("NoRec "++).showsPrec d x
  showsPrec d (Rec  xs)    = ("Rec "++).showsPrec d xs

sccDepend :: (Ord a) => [(a, [a])] -> [Depend a]
sccDepend dep = fix' (map Set.toList (scc (mkin dep) out (map fst dep)))
        where
          out = mkout dep

          fix' [] = []
          fix' ([x]:r) = (if x `elem` out x then Rec [x] else NoRec x) : fix' r
          fix' (xs:r)  = Rec xs : fix' r


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.