Changed the types involved in the control-flow graph so that I can customise the Show implementation
This commit is contained in:
parent
a0c54220e2
commit
cf17814b98
|
@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along
|
||||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module FlowGraph (EdgeLabel(..), FlowGraph, buildFlowGraph) where
|
module FlowGraph (EdgeLabel(..), FNode(..), FlowGraph, buildFlowGraph, makeFlowGraphInstr) where
|
||||||
|
|
||||||
import Control.Monad.Error
|
import Control.Monad.Error
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
|
@ -31,15 +31,21 @@ data EdgeLabel = EChoice | ESeq | EPar deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
data OuterType = None | Seq | Par
|
data OuterType = None | Seq | Par
|
||||||
|
|
||||||
type FNode a = (Meta, a)
|
newtype FNode a = Node (Meta, a)
|
||||||
--type FEdge = (Node, EdgeLabel, Node)
|
--type FEdge = (Node, EdgeLabel, Node)
|
||||||
|
|
||||||
|
instance Show a => Show (FNode a) where
|
||||||
|
show (Node (m,x)) = (filter ((/=) '\"')) $ show m ++ ":" ++ show x
|
||||||
|
|
||||||
type FlowGraph a = Gr (FNode a) EdgeLabel
|
type FlowGraph a = Gr (FNode a) EdgeLabel
|
||||||
|
|
||||||
type NodesEdges a = ([LNode (FNode a)],[LEdge EdgeLabel])
|
type NodesEdges a = ([LNode (FNode a)],[LEdge EdgeLabel])
|
||||||
|
|
||||||
type GraphMaker m a b = ErrorT String (StateT (Node, NodesEdges a) m) b
|
type GraphMaker m a b = ErrorT String (StateT (Node, NodesEdges a) m) b
|
||||||
|
|
||||||
|
-- | Builds the instructions to send to GraphViz
|
||||||
|
makeFlowGraphInstr :: Show a => FlowGraph a -> String
|
||||||
|
makeFlowGraphInstr = graphviz'
|
||||||
|
|
||||||
-- The primary reason for having the blank generator take a Meta as an argument is actually for testing. But other uses can simply ignore it if they want.
|
-- The primary reason for having the blank generator take a Meta as an argument is actually for testing. But other uses can simply ignore it if they want.
|
||||||
buildFlowGraph :: Monad m => (Meta -> m a) -> (forall t. Data t => t -> m a) -> A.Structured -> m (Either String (FlowGraph a))
|
buildFlowGraph :: Monad m => (Meta -> m a) -> (forall t. Data t => t -> m a) -> A.Structured -> m (Either String (FlowGraph a))
|
||||||
|
@ -51,9 +57,9 @@ buildFlowGraph blank f s
|
||||||
where
|
where
|
||||||
-- All the functions return the new graph, and the identifier of the node just added
|
-- All the functions return the new graph, and the identifier of the node just added
|
||||||
|
|
||||||
addNode :: Monad m => FNode a -> GraphMaker m a Node
|
addNode :: Monad m => (Meta, a) -> GraphMaker m a Node
|
||||||
addNode x = do (n,(nodes, edges)) <- get
|
addNode x = do (n,(nodes, edges)) <- get
|
||||||
put (n+1, ((n, x):nodes, edges))
|
put (n+1, ((n, Node x):nodes, edges))
|
||||||
return n
|
return n
|
||||||
|
|
||||||
addEdge :: Monad m => EdgeLabel -> Node -> Node -> GraphMaker m a ()
|
addEdge :: Monad m => EdgeLabel -> Node -> Node -> GraphMaker m a ()
|
||||||
|
@ -71,7 +77,9 @@ buildFlowGraph blank f s
|
||||||
buildStructured outer (A.Several m ss)
|
buildStructured outer (A.Several m ss)
|
||||||
= do nodes <- mapM (buildStructured outer) ss
|
= do nodes <- mapM (buildStructured outer) ss
|
||||||
case outer of
|
case outer of
|
||||||
None -> throwError "Cannot handle Several without an outer context"
|
None -> -- If there is no context, they should be left as disconnected graphs.
|
||||||
|
do n <- addDummyNode m
|
||||||
|
return (n, n)
|
||||||
Seq -> do sequence_ $ mapPairs (\(_,s) (e,_) -> addEdge ESeq s e) nodes
|
Seq -> do sequence_ $ mapPairs (\(_,s) (e,_) -> addEdge ESeq s e) nodes
|
||||||
case nodes of
|
case nodes of
|
||||||
[] -> do n <- addDummyNode m
|
[] -> do n <- addDummyNode m
|
||||||
|
|
|
@ -30,12 +30,13 @@ import Test.HUnit hiding (Node, State)
|
||||||
import qualified AST as A
|
import qualified AST as A
|
||||||
import FlowGraph
|
import FlowGraph
|
||||||
import Metadata
|
import Metadata
|
||||||
|
import TestUtil
|
||||||
import Utils
|
import Utils
|
||||||
|
|
||||||
makeMeta :: Int -> Meta
|
makeMeta :: Int -> Meta
|
||||||
makeMeta n = Meta (Just "FlowGraphTest") n 0
|
makeMeta n = Meta (Just "FlowGraphTest") n 0
|
||||||
|
|
||||||
-- To make typing the tests as short as possible:
|
-- To make typing the tests as short as possible (typing a function call means bracketing is needed, which is a pain):
|
||||||
m0 = makeMeta 0
|
m0 = makeMeta 0
|
||||||
m1 = makeMeta 1
|
m1 = makeMeta 1
|
||||||
m2 = makeMeta 2
|
m2 = makeMeta 2
|
||||||
|
@ -84,9 +85,15 @@ testGraph testName nodes edges proc
|
||||||
-- Checks two graphs are equal by creating a node mapping from the expected graph to the real map (checkNodeEquality),
|
-- Checks two graphs are equal by creating a node mapping from the expected graph to the real map (checkNodeEquality),
|
||||||
-- then mapping the edges across (transformEdge) and checking everything is right (in checkGraphEquality)
|
-- then mapping the edges across (transformEdge) and checking everything is right (in checkGraphEquality)
|
||||||
|
|
||||||
checkGraphEquality :: (Graph g, Show b, Ord b) => ([(Int, Meta)], [(Int, Int, b)]) -> g (Meta, Int) b -> Assertion
|
deNode :: FNode a -> (Meta, a)
|
||||||
|
deNode (Node x) = x
|
||||||
|
|
||||||
|
mapPair :: (x -> a) -> (y -> b) -> (x,y) -> (a,b)
|
||||||
|
mapPair f g (x,y) = (f x, g y)
|
||||||
|
|
||||||
|
checkGraphEquality :: (Graph g, Show b, Ord b) => ([(Int, Meta)], [(Int, Int, b)]) -> g (FNode Int) b -> Assertion
|
||||||
checkGraphEquality (nodes, edges) g
|
checkGraphEquality (nodes, edges) g
|
||||||
= do let (remainingNodes, nodeLookup, ass) = foldl checkNodeEquality (Map.fromList (map revPair nodes),Map.empty, return ()) (labNodes g)
|
= do let (remainingNodes, nodeLookup, ass) = foldl checkNodeEquality (Map.fromList (map revPair nodes),Map.empty, return ()) (map (mapPair id deNode) $ labNodes g)
|
||||||
ass
|
ass
|
||||||
assertBool (testName ++ " Test graph had nodes not found in the real graph: " ++ show remainingNodes ++ ", real graph: " ++ showGraph g) (Map.null remainingNodes)
|
assertBool (testName ++ " Test graph had nodes not found in the real graph: " ++ show remainingNodes ++ ", real graph: " ++ showGraph g) (Map.null remainingNodes)
|
||||||
edges' <- mapM (transformEdge nodeLookup) edges
|
edges' <- mapM (transformEdge nodeLookup) edges
|
||||||
|
|
Loading…
Reference in New Issue
Block a user