registry-0.1.0.0: src/Data/Registry/Internal/Operations.hs
{- |
Nested datatype to track the resolution algorithm
From this data type we can draw a graph of the full
instantation of a value
-}
module Data.Registry.Internal.Operations where
import Data.Registry.Internal.Types
import Data.Text as T
import Protolude
-- | A list of function applications created
-- when creating a value out of the Registry
type Operations = [AppliedFunction]
-- | A function application with an output value and a list of input values
data AppliedFunction = AppliedFunction {
_outputValue :: Value
, _inputValues ::[Value]
} deriving (Show)
-- | Make a list of graph edges from the list of function applications
makeEdges :: Operations -> [(Value, Value)]
makeEdges [] = []
makeEdges (AppliedFunction out ins : rest) =
((out,) <$> ins) <>
makeEdges rest
-- | A DOT graph
newtype Dot = Dot {
unDot :: Text
} deriving (Eq, Show)
-- | Make a DOT graph out of all the function applications
toDot :: Operations -> Dot
toDot op = Dot $ T.unlines $
[ "strict digraph {"
, " node [shape=record]"
]
<> (toDotEdge <$> makeEdges op)
<> ["}"]
-- | A DOT edge representing the dependency between 2 values
toDotEdge :: (Value, Value) -> Text
toDotEdge (v1, v2) =
adjust (nodeDescription . valDescription $ v1)
<> " -> "
<> adjust (nodeDescription . valDescription $ v2)
<> ";"
-- | Description of a Value in the DOT graph
nodeDescription :: ValueDescription -> Text
nodeDescription (ValueDescription t Nothing) = t
nodeDescription (ValueDescription t (Just v)) = t <> "\n" <> v
-- | We need to process the node descriptions
-- - we add quotes arountd the text
-- - we remove quotes (") inside the text
-- - we escape newlines
adjust :: Text -> Text
adjust t = "\"" <> (escapeNewlines . removeQuotes) t <> "\""
-- | Remove quotes from a textual description to avoid breaking the DOT format
removeQuotes :: Text -> Text
removeQuotes = T.replace "\"" ""
-- | Replace \n with \\n so that newlines are kept in
-- node descriptions
escapeNewlines :: Text -> Text
escapeNewlines = T.replace "\n" "\\n"