module Language.Haskell.Liquid.UX.CTags (
TagKey, TagEnv
, defaultTag
, makeTagEnv
, getTag
, memTagEnv
) where
import Var
import CoreSyn
import Prelude hiding (error)
import qualified Data.HashSet as S
import qualified Data.HashMap.Strict as M
import qualified Data.Graph as G
import Language.Fixpoint.Types (Tag)
import Language.Haskell.Liquid.Types.Visitors (freeVars)
import Language.Haskell.Liquid.Types.PrettyPrint ()
import Language.Fixpoint.Misc (mapSnd)
type TagKey = Var
type TagEnv = M.HashMap TagKey Tag
defaultTag :: Tag
defaultTag = [0]
memTagEnv :: TagKey -> TagEnv -> Bool
memTagEnv = M.member
makeTagEnv :: [CoreBind] -> TagEnv
makeTagEnv = M.map (:[]) . callGraphRanks . makeCallGraph
getTag :: TagKey -> TagEnv -> Tag
getTag = M.lookupDefault defaultTag
type CallGraph = [(Var, [Var])]
callGraphRanks :: CallGraph -> M.HashMap Var Int
callGraphRanks = M.fromList . concat . index . mkScc
where mkScc cg = G.stronglyConnComp [(u, u, vs) | (u, vs) <- cg]
index = zipWith (\i -> map (, i) . G.flattenSCC) [1..]
makeCallGraph :: [CoreBind] -> CallGraph
makeCallGraph cbs = mapSnd calls `fmap` xes
where xes = concatMap bindEqns cbs
xs = S.fromList $ map fst xes
calls = filter (`S.member` xs) . freeVars S.empty
bindEqns :: Bind t -> [(t, Expr t)]
bindEqns (NonRec x e) = [(x, e)]
bindEqns (Rec xes) = xes