packages feed

ruler-core-1.0: src/TargetGraph.ag

-- This file is included by Transform.ag
-- Generates code for a dependency graph

SEM Program | Program
  loc.ppGraph   = "digraph Deps {"
                  >-< indent 2 ( vlist
                       [ ppgNode (Map.findWithDefault noPos d @blocks.gathStmtPosMap) d @loc.distRanks
                       | d <- @loc.unqItems
                       ])
                  >-< indent 2 ( vlist
                        [ label' from >#< "->" >#< ppgDeps (map label' [to])
                            >#< pp_block "[" "]" "," ( ppgColor (isOnCycle from @loc.distRanks && isOnCycle to @loc.distRanks)
                                                     : maybe [] (\d -> [ppgProp "label" d]) (ppgReason reason))
                            
                            >|< ";"
                        | (from, (reason, tos)) <- Map.assocs @loc.unqDeps
                        , length tos >= 1
                        , let label' = \item -> ppgKey (Map.findWithDefault noPos item @blocks.gathStmtPosMap) item
                        , to <- tos ]
                      )
                  >-< "}"

{
isOnCycle :: DepItem -> Map DepItem (Bool,Int) -> Bool
isOnCycle d mp
  = case Map.lookup d mp of
      Nothing    -> False
      Just (b,_) -> b

ppgProp :: PP a => String -> a -> PP_Doc
ppgProp s d = s >|< "=" >|< pp_doubleQuotes (pp d)

ppgNms :: QIdent -> PP_Doc
ppgNms = hlist . map show

ppgDeps :: PP a => [a] -> PP_Doc
ppgDeps [x] = pp x
ppgDeps xs  = pp_block "{" "}" ";" (map pp xs)

ppgNode :: Pos -> DepItem -> Map DepItem (Bool,Int) -> PP_Doc
ppgNode pos item rankMap
  = case item of
      DepMatch n      -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "label" l, c] >|< ";"
      DepAssert n     -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "label" l, c] >|< ";"
      DepDefault n    -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "label" l, c] >|< ";"
      DepAttach n     -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "shape" "box",ppgProp "label" l, c] >|< ";"
      DepInvoke nms   -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "shape" "box",ppgProp "skew" ".3",ppgProp "label" l,c] >|< ";"
      DepVisStart nms -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "shape" "box",ppgProp "skew" ".3",ppgProp "label" l,c] >|< ";"
      DepVisEnd nms   -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "shape" "box",ppgProp "skew" ".3",ppgProp "label" l,c] >|< ";"
      DepClause nms   -> ppgKey pos item >#< pp_block "[" "]" "," [ppgProp "shape" "box",ppgProp "skew" ".3",ppgProp "label" l,c] >|< ";"
  where mbInfo = Map.lookup item rankMap
        l = ppgLabel pos item (maybe Nothing (Just . snd) mbInfo)
        c = ppgColor (maybe False fst mbInfo)

ppgColor :: Bool -> PP_Doc
ppgColor True  = ppgProp "color" "red4"
ppgColor False = ppgProp "color" "black"

ppgLabel :: Pos -> DepItem -> Maybe Int -> PP_Doc
ppgLabel pos item mbRank
  = case item of
      DepMatch m   -> r >#< show m >|< "?@" >|< show (line pos)
      DepAssert n  -> r >#< show n >|< "@" >|< show (line pos)
      DepDefault o -> r >#< "d" >|< show o
      DepAttach n  -> r >#< "@" >|< show (line pos)
      DepInvoke (visit:name:_) -> r >#< name >|< "." >|< visit >|< "@" >|< show (line $ identPos name)
      DepInvoke _              -> r >#< text "i???"
      DepVisStart (visit:_)    -> r >#< ">" >|< show visit >|< "@" >|< show (line $ identPos visit)
      DepVisStart _            -> r >#< text ">v???"
      DepVisEnd (visit:_)      -> r >#< show visit >|< "@" >|< show (line $ identPos visit) >|< "<"
      DepVisEnd _              -> r >#< text "<v???"
      DepClause (clause:_)     -> r >#< "|" >|< show clause >|< "@" >|< show (line $ identPos clause)
      DepClause _              -> r >#< text "|???"
  where
    r = case mbRank of
          Nothing -> empty
          Just k  -> show k >|< ":"

ppgKey :: Pos -> DepItem -> PP_Doc
ppgKey pos item
  = case item of
      DepMatch n      -> "s"  >|< show n
      DepAssert n     -> "s"  >|< show n
      DepDefault n    -> "d"  >|< show n
      DepAttach n     -> "a"  >|< show n
      DepInvoke nms   -> "iv" >|< ppgNms nms
      DepVisStart nms -> "vb" >|< ppgNms nms
      DepVisEnd nms   -> "ve" >|< ppgNms nms
      DepClause nms   -> "cl" >|< ppgNms nms

ppgReason :: Reason -> Maybe PP_Doc
ppgReason reason
  = case reason of
      ReasonScopeVisit i      -> Nothing -- Just ("sc-vis-pre" >#< show i)
      ReasonScopeClause i     -> Nothing -- Just ("sc-cl" >#< show i)
      ReasonScopeEnd i        -> Nothing -- Just ("sc-vis-end" >#< show i)
      ReasonAttrReq chld attr -> Just (show chld >|< "." >|< show attr)
      ReasonInvokeReq i       -> Just ("inv" >#< show i)
      ReasonChildReq i        -> Nothing -- Just ("chld" >#< show i)
      ReasonAttach i v        -> Just ("att" >#< show i >|< "." >|< show v)
      ReasonDefault attr      -> Nothing -- Just ("def." >|< show attr)
      ReasonDetach _ _        -> Nothing -- Just $ text "detach"
      ReasonError             -> Just $ text "error"
}