tools/pas2c/unitCycles.hs
author Wuzzy <Wuzzy2@mail.ru>
Tue, 04 Sep 2018 14:20:15 +0200
changeset 13761 a0d6404a80a2
parent 7969 7fcbbd46704a
permissions -rw-r--r--
Rework rankings of losing clans: Rank them in the reverse order they died New ranking rule: - The clan that survived is ranked 1st. - The clan that died last is ranked 2nd. - The clan that died second last is ranked 3rd. - The clan that died third last is ranked 4th. - And so on ... Old ranking rule: - The clan that survived is ranked 1st. - The losing teams are ranked in the order they started with, which isn't fair. Draws are not handled properly in rankings yet.

module Main where

import PascalParser
import System
import Control.Monad
import Data.Either
import Data.List
import Data.Graph
import Data.Maybe

unident :: Identificator -> String
unident (Identificator s) = s

extractUnits :: PascalUnit -> (String, [String])
extractUnits (Program (Identificator name) (Implementation (Uses idents) _ _) _) = ("program " ++ name, map unident idents)
extractUnits (Unit (Identificator name) (Interface (Uses idents1) _) (Implementation (Uses idents2) _ _) _ _) = (name, map unident $ idents1 ++ idents2)

f :: [(String, [String])] -> String
f = unlines . map showSCC . stronglyConnComp . map (\(a, b) -> (a, a, b))
    where
    showSCC (AcyclicSCC v) = v
    showSCC (CyclicSCC vs) = intercalate ", " vs

myf :: [(String, [String])] -> String
myf d = unlines . map (findCycle . fst) $ d
    where
    findCycle :: String -> String
    findCycle searched = searched ++ ": " ++ (intercalate ", " $ fc searched [])
        where
        fc :: String -> [String] -> [String]
        fc curSearch visited = let uses = curSearch `lookup` d; res = dropWhile null . map t $ fromJust uses in if isNothing uses || null res then [] else head res
            where
            t u =
                if u == searched then
                    [u]
                    else
                    if u `elem` visited then
                        []
                        else
                        let chain = fc u (u:visited) in if null chain then [] else u:chain


main = do
    fileNames <- getArgs
    files <- mapM readFile fileNames
    putStrLn . myf . map extractUnits . rights . map parsePascalUnit $ files