-- | Composes two size-change graphs.
compose :: Eq a => SizeChangeGraph a (Sym, Size) -> SizeChangeGraph a (Sym, Size) -> Maybe (SizeChangeGraph a (Sym, Size))
compose g@(x, xy, y) g'@(y', yz, z)
  | areComposable g g' = Just (x, composeArrows xy yz, z)
  | otherwise          = Nothing
  where
    composeArrows :: [SCArc (Sym, Size)] -> [SCArc (Sym, Size)] -> [SCArc (Sym, Size)]
    composeArrows xy yz =
          [ (DataPos (x,xs), Descending, DataPos (z,zs)) |
              (DataPos (x,xs), arr, DataPos (y,_)) <- xy, (DataPos (y',_), arr', DataPos (z,zs)) <- yz, y == y',
              arr == Descending || arr' == Descending       ] ++
          [ (DataPos (x,xs), NonIncreasing, DataPos (z,zs)) |
              (DataPos (x,xs), arr, DataPos (y,_)) <- xy, (DataPos (y',_), arr', DataPos (z,zs)) <- yz, y == y',
              arr == NonIncreasing && arr' == NonIncreasing ]


-- | Finds all cyclic multipaths from a list of size-change graphs.
-- | The size-change graphs are generated from the calls in the call graph.
compose :: Eq a => SizeChangeGraph a (Sym, Size) -> SizeChangeGraph a (Sym, Size) -> Maybe (SizeChangeGraph a (Sym, Size))
compose g@(x, xy, y) g'@(y', yz, z)
  | areComposable g g' = Just (x, composeArrows xy yz, z)
  | otherwise          = Nothing
  where
    composeArrows :: [SCArc (Sym, Size)] -> [SCArc (Sym, Size)] -> [SCArc (Sym, Size)]
    composeArrows xy yz =
          [ (DataPos (x,xs), Descending, DataPos (z,zs)) |
              (DataPos (x,xs), arr, DataPos (y,_)) <- xy, (DataPos (y',_), arr', DataPos (z,zs)) <- yz, y == y',
              arr == Descending || arr' == Descending       ] ++
          [ (DataPos (x,xs), NonIncreasing, DataPos (z,zs)) |
              (DataPos (x,xs), arr, DataPos (y,_)) <- xy, (DataPos (y',_), arr', DataPos (z,zs)) <- yz, y == y',
              arr == NonIncreasing && arr' == NonIncreasing ]


-- | Finds all cyclic multipaths from a list of size-change graphs.
-- | The size-change graphs are generated from the calls in the call graph.
compose g@(x, xy, y) g'@(y', yz, z)
  | areComposable g g' = Just (x, composeArrows xy yz, z)
  | otherwise          = Nothing
  where
    composeArrows :: [SCArc (Sym, Size)] -> [SCArc (Sym, Size)] -> [SCArc (Sym, Size)]
    composeArrows xy yz =
          [ (DataPos (x,xs), Descending, DataPos (z,zs)) |
              (DataPos (x,xs), arr, DataPos (y,_)) <- xy, (DataPos (y',_), arr', DataPos (z,zs)) <- yz, y == y',
              arr == Descending || arr' == Descending       ] ++
          [ (DataPos (x,xs), NonIncreasing, DataPos (z,zs)) |
              (DataPos (x,xs), arr, DataPos (y,_)) <- xy, (DataPos (y',_), arr', DataPos (z,zs)) <- yz, y == y',
              arr == NonIncreasing && arr' == NonIncreasing ]


-- | Finds all cyclic multipaths from a list of size-change graphs.
-- | The size-change graphs are generated from the calls in the call graph.