{- | 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 -- * DOT GRAPH -- | 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"