{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module Language.Fixpoint.Graph.Types (
CVertex (..)
, CEdge
, isRealEdge
, KVGraph (..)
, Comps
, KVComps
, writeGraph
, writeEdges
, F.SubcId
, KVRead
, DepEdge
, Slice (..)
, CGraph (..)
, F.CMap
, lookupCMap
, Rank (..)
, CDeps (..)
, SolverInfo (..)
)
where
import GHC.Generics (Generic)
import Data.Hashable
import Text.PrettyPrint.HughesPJ.Compat
import Language.Fixpoint.Misc
import Language.Fixpoint.Types.PrettyPrint
import Language.Fixpoint.Types.Refinements
import qualified Language.Fixpoint.Types.Solutions as F
import qualified Language.Fixpoint.Types as F
import qualified Data.HashMap.Strict as M
import qualified Data.HashSet as S
import GHC.Stack
data CVertex = KVar !KVar
| DKVar !KVar
| EBind !F.Symbol
| Cstr !Integer
deriving (Eq, Ord, Show, Generic)
instance PPrint CVertex where
pprintTidy _ (KVar k) = doubleQuotes $ pprint $ kv k
pprintTidy _ (EBind s) = doubleQuotes $ pprint $ s
pprintTidy _ (Cstr i) = text "id_" <-> pprint i
pprintTidy _ (DKVar k) = pprint k <-> text "*"
instance Hashable CVertex
data KVGraph = KVGraph { kvgEdges :: [(CVertex, CVertex, [CVertex])] }
type CEdge = (CVertex, CVertex)
type Comps a = [[a]]
type KVComps = Comps CVertex
instance PPrint KVGraph where
pprintTidy _ = pprint . kvgEdges
writeGraph :: FilePath -> KVGraph -> IO ()
writeGraph f = writeEdges f . graphEdges
where
graphEdges :: KVGraph -> [CEdge]
graphEdges (KVGraph g) = [ (v, v') | (v,_,vs) <- g, v' <- vs]
writeEdges :: FilePath -> [CEdge] -> IO ()
writeEdges f = writeFile f . render . ppEdges
ppEdges :: [CEdge] -> Doc
ppEdges = vcat . wrap ["digraph Deps {"] ["}"]
. map ppE
. (if True then filter isRealEdge else txEdges)
where
ppE (v, v') = pprint v <+> "->" <+> pprint v'
isRealEdge :: CEdge -> Bool
isRealEdge (DKVar _, _) = False
isRealEdge (_, DKVar _) = False
isRealEdge (Cstr _, Cstr _) = False
isRealEdge _ = True
txEdges :: [CEdge] -> [CEdge]
txEdges es = concatMap iEs is
where
is = [i | (Cstr i, Cstr _) <- es]
kvInM = group [ (i, k) | (KVar k, Cstr i) <- es]
kvOutM = group [ (i, k') | (Cstr i, KVar k') <- es]
ins i = M.lookupDefault [] i kvInM
outs i = M.lookupDefault [] i kvOutM
iEs i = case (ins i, outs i) of
(ks, [] ) -> [(KVar k, Cstr i ) | k <- ks ]
([], ks') -> [(Cstr i, KVar k') | k' <- ks']
(ks, ks') -> [(KVar k, KVar k') | k <- ks, k' <- ks']
type KVRead = M.HashMap F.KVar [F.SubcId]
type DepEdge = (F.SubcId, F.SubcId, [F.SubcId])
data Slice = Slice { slKVarCs :: [F.SubcId]
, slConcCs :: [F.SubcId]
, slEdges :: [DepEdge]
} deriving (Eq, Show)
data CGraph = CGraph { gEdges :: [DepEdge]
, gRanks :: !(F.CMap Int)
, gSucc :: !(F.CMap [F.SubcId])
, gSccs :: !Int
}
lookupCMap :: (?callStack :: CallStack) => F.CMap a -> F.SubcId -> a
lookupCMap rm i = safeLookup err i rm
where
err = "lookupCMap: cannot find info for " ++ show i
data CDeps = CDs { cSucc :: !(F.CMap [F.SubcId])
, cPrev :: !(F.CMap [F.KVar])
, cRank :: !(F.CMap Rank)
, cNumScc :: !Int
}
data Rank = Rank { rScc :: !Int
, rIcc :: !Int
, rTag :: !F.Tag
} deriving (Eq, Show)
instance PPrint Rank where
pprintTidy _ = text . show
data SolverInfo a b = SI
{ siSol :: !(F.Sol b F.QBind)
, siQuery :: !(F.SInfo a)
, siDeps :: !CDeps
, siVars :: !(S.HashSet F.KVar)
}