-
Notifications
You must be signed in to change notification settings - Fork 1
/
Analysis.hs
84 lines (66 loc) · 3.23 KB
/
Analysis.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
module Analysis where
import Control.Monad
import Data.Graph
import Data.List
import Data.Maybe
import Parser
import Util
-- The representation of IAPs used in the message type graph
data GIAP = GIAP { task :: String, gmsgT :: String, gcond :: Maybe String }
deriving (Eq, Ord, Show)
-- Short display version of a GIAP
printGIAP :: GIAP -> String
printGIAP x = task x ++ "." ++ gmsgT x ++ condPart
where condPart = case gcond x of
Nothing -> ""
Just c -> "(" ++ trim c ++ ")"
getCyclicSCCs :: [Task] -> [[GIAP]]
getCyclicSCCs tasks =
let edges = makeMSGTGraphEdges tasks
cyclicSCCs = filter (\s -> case s of
CyclicSCC _ -> True
AcyclicSCC _ -> False) (stronglyConnComp edges)
in map flattenSCC cyclicSCCs
printGIAPList :: [GIAP] -> String
printGIAPList = intercalate ", " . map printGIAP
showCyclicSCCs :: [Task] -> String
showCyclicSCCs = intercalate ", " . map (\s -> "[" ++ s ++ "]") . map printGIAPList . getCyclicSCCs
-- printSCCs :: [Task] -> String
-- printSCCs tasks = -- replace "," ", " .
-- filter (/= '"') . show . map (map printGIAP) $ getSCCs tasks
-- printCyclicSCCs :: [Task] -> String
-- printCyclicSCCs tasks = filter (/= '"') . show . map (map printGIAP) $ getCyclicSCCs tasks
makeMSGTGraph :: [Task] -> (Graph, Vertex -> (GIAP, GIAP, [GIAP]), GIAP -> Maybe Vertex)
makeMSGTGraph tasks = graphFromEdges $ makeMSGTGraphEdges tasks
-- edges = [(giap, giap, sendsTo) |
-- (giap, canSendMsgTs) <- getGIAPsFromTasks tasks,
-- let sendsTo = [giap' | (giap', _) <- getGIAPsFromTasks tasks, (gmsgT giap') `elem` canSendMsgTs] ]
makeMSGTGraphEdges :: [Task] -> [(GIAP, GIAP, [GIAP])]
makeMSGTGraphEdges tasks =
[(giap, giap, sendsTo) |
(giap, canSendMsgTs) <- getGIAPsFromTasks tasks,
let sendsTo = [giap' | (giap', _) <- getGIAPsFromTasks tasks, (gmsgT giap') `elem` canSendMsgTs] ]
-- For a list of Tasks, get a list of the corresponding GIAPs, each together with a list of message types they can send (syntactically, i.e., they include a send or reply statement with that message type)
getGIAPsFromTasks :: [Task] -> [(GIAP, [String])]
getGIAPsFromTasks = join . map getGIAPsFromTask
-- getIAPsFromTasks :: [Task] -> [(String, [String])]
-- getIAPsFromTasks = join . (map (\t -> getIAPsFromTaskElems (elements t)))
-- getIAPsFromTasks = join . (map (\t -> let iaps = getIAPsFromTaskElems (elements t) -- prefix should not be added here
-- in map (\(n, acTs) -> (name t ++ "." ++ n, acTs)) iaps))
-- getGIAPsFromTask :: Task -> [GIAP]
-- getGIAPsFromTask t =
getGIAPsFromTask :: Task -> [(GIAP, [String])]
getGIAPsFromTask task = catMaybes $ map (extractIAP $ name task) (elements task)
-- Extracts an IAP in the form (input msg type, [send/reply message types])
extractIAP :: String -> TaskElem -> Maybe (GIAP, [String])
extractIAP name element =
case element of
IAP inp ac -> Just (GIAP{task = name, gmsgT = msgT inp, gcond = cond inp}, catMaybes $ map extractMsgT ac)
_ -> Nothing
-- Extract a msg type if the ActionElem is a reply or send
extractMsgT :: ActionElem -> Maybe String
extractMsgT e =
case e of
Reply {rmsgT=t} -> Just t
Send {smsgT=t} -> Just t
_ -> Nothing