{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE OverloadedStrings #-}
module Language.Fixpoint.Graph.Reducible ( isReducible ) where
import qualified Data.Tree as T
import qualified Data.HashMap.Strict as M
import Data.Graph.Inductive
import Language.Fixpoint.Misc
import qualified Language.Fixpoint.Types.Visitor as V
import qualified Language.Fixpoint.Types as F
isReducible :: (F.TaggedC c a) => F.GInfo c a -> Bool
isReducible fi = all (isReducibleWithStart g) vs
where
g = convertToGraph fi
vs = nodes g
isReducibleWithStart :: Gr a b -> Node -> Bool
isReducibleWithStart g x = all (isBackEdge domList) rEdges
where
dfsTree = head $ dff [x] g
rEdges = [ e | e@(a,b) <- edges g, isDescendant a b dfsTree]
domList = dom g x
convertToGraph :: (F.TaggedC c a) => F.GInfo c a -> Gr Int ()
convertToGraph fi = mkGraph vs es
where
subCs = M.elems (F.cm fi)
es = lUEdge <$> concatMap (subcEdges' kvI $ F.bs fi) subCs
ks = M.keys (F.ws fi)
kiM = M.fromList $ zip ks [0..]
kvI k = safeLookup ("convertToGraph: " ++ show k) k kiM
vs = lNode . kvI <$> M.keys (F.ws fi)
lNode i = (i, i)
lUEdge (i,j) = (i, j, ())
isDescendant :: Node -> Node -> T.Tree Node -> Bool
isDescendant x y (T.Node z f) | z == y = f `contains` x
| z == x = False
| otherwise = any (isDescendant x y) f
contains :: [T.Tree Node] -> Node -> Bool
contains t x = x `elem` concatMap T.flatten t
isBackEdge :: [(Node, [Node])] -> Edge -> Bool
isBackEdge t (u,v) = v `elem` xs
where
(Just xs) = lookup u t
subcEdges' :: (F.TaggedC c a) => (F.KVar -> Node) -> F.BindEnv -> c a -> [(Node, Node)]
subcEdges' kvI be c = [(kvI k1, kvI k2) | k1 <- V.envKVars be c
, k2 <- V.kvars $ F.crhs c]