-- | Module providing helpers to get a Dot representation of tracked -- dependencies during a DepTrack computation. -- -- This module currently uses 'Text.Dot' from 'dotgen' as a Dot generator, this -- choice may change in the future. module DepTrack.Dot (DotDescription(..), dotifyGraphWith, dotify) where import DepTrack (DepTrackT, GraphData, buildGraph, evalDepForest1) import Data.Graph (edges, vertices) import qualified Text.Dot as Dot -- | A type to hide a Dot program. newtype DotDescription = DotDescription { getDotDescription :: String } deriving (Eq, Ord, Show) -- | Dotify some pre-calculed GraphData. dotifyGraphWith :: (x -> [(String,String)]) -- ^ Function to return a set of graphviz key-value attributes (e.g., ("shape","egg")) -> GraphData x k -- ^ The graph data to represent. -> DotDescription dotifyGraphWith attributes (g,lookupF,_) = DotDescription $ Dot.showDot dotted where dotted :: Dot.Dot () dotted = do let node v = y where (y,_,_) = lookupF v let vs = vertices g let es = filter (uncurry (/=)) $ edges g mapM_ (\i -> Dot.userNode (Dot.userNodeId i) (attributes (node i))) vs mapM_ (\(i,j) -> Dot.edge (Dot.userNodeId i) (Dot.userNodeId j) []) es -- | Graphs the dependenciees of a DepTrack computation. -- -- Throws away the result and only keep the DotDescription. dotify :: (Monad m, Ord k, Show x) => (x -> [(String,String)]) -- ^ Function to return a set of graphviz key-value attributes (e.g., ("shape","egg")) -> (x -> k) -- ^ Function to identify every node in the graph uniquely. If this function -- is non injective you may confuse two distinct nodes as a same node. -> DepTrackT x m a -- ^ The computation to graph. -> m DotDescription dotify labelsF keyF x = dotifyGraphWith labelsF . buildGraph keyF . snd <$> evalDepForest1 x