Readjusted the parameters of flowAlgorithm so that the initial value for the starting node is passed in more obviously (since that was the only use of initVal, which has now been removed)

This commit is contained in:
Neil Brown 2008-01-29 21:05:37 +00:00
parent 28fd400d89
commit 95d99706e3
3 changed files with 9 additions and 8 deletions

View File

@ -143,13 +143,17 @@ showCodeExSet (NormalSet s)
-- | Checks that no variable is used uninitialised. That is, it checks that every variable is written to before it is read. -- | Checks that no variable is used uninitialised. That is, it checks that every variable is written to before it is read.
checkInitVar :: forall m. (Monad m, Die m, CSM m) => Meta -> FlowGraph m (Maybe Decl, Vars) -> Node -> m () checkInitVar :: forall m. (Monad m, Die m, CSM m) => Meta -> FlowGraph m (Maybe Decl, Vars) -> Node -> m ()
checkInitVar m graph startNode checkInitVar m graph startNode
= do vwb <- case flowAlgorithm graphFuncs (dfs [startNode] graph) startNode of = do startLabel <- checkJust (Just m, "Could not find starting node in the control-flow graph")
(lab graph startNode) >>* writeNode
vwb <- case flowAlgorithm graphFuncs connectedNodes (startNode, startLabel) of
Left err -> dieP m $ "Error building control-flow graph: " ++ err Left err -> dieP m $ "Error building control-flow graph: " ++ err
Right x -> return x Right x -> return x
-- vwb is a map from Node to a set of Vars that have been written by that point -- vwb is a map from Node to a set of Vars that have been written by that point
-- Now we check that for every variable read in each node, it has already been written to by then -- Now we check that for every variable read in each node, it has already been written to by then
mapM_ (checkInitVar' vwb) (map readNode (labNodes graph)) mapM_ (checkInitVar' vwb) (map readNode (labNodes graph))
where where
connectedNodes = dfs [startNode] graph
-- Gets all variables read-from in a particular node, and the node identifier -- Gets all variables read-from in a particular node, and the node identifier
readNode :: (Node, FNode m (Maybe Decl, Vars)) -> (Node, ExSet Var) readNode :: (Node, FNode m (Maybe Decl, Vars)) -> (Node, ExSet Var)
readNode (n, Node (_,(_,Vars read _ _),_)) = (n,NormalSet read) readNode (n, Node (_,(_,Vars read _ _),_)) = (n,NormalSet read)
@ -170,7 +174,6 @@ checkInitVar m graph startNode
nodeFunc = nodeFunction nodeFunc = nodeFunction
,prevNodes = lpre graph ,prevNodes = lpre graph
,nextNodes = lsuc graph ,nextNodes = lsuc graph
,initVal = emptySet
,defVal = Everything ,defVal = Everything
} }

View File

@ -98,7 +98,7 @@ checkPar f g = map f allParItems
-- | Returns either an error, or map *from* the node with a read, *to* the node whose definitions might be available at that point -- | Returns either an error, or map *from* the node with a read, *to* the node whose definitions might be available at that point
findReachDef :: forall m. Monad m => FlowGraph m (Maybe Decl, Vars) -> Node -> Either String (Map.Map Node (Map.Map Var (Set.Set Node))) findReachDef :: forall m. Monad m => FlowGraph m (Maybe Decl, Vars) -> Node -> Either String (Map.Map Node (Map.Map Var (Set.Set Node)))
findReachDef graph startNode findReachDef graph startNode
= do r <- flowAlgorithm graphFuncs (nodes graph) startNode = do r <- flowAlgorithm graphFuncs (nodes graph) (startNode, Map.empty)
-- These lines remove the maps where the variable is not read in that particular node: -- These lines remove the maps where the variable is not read in that particular node:
let r' = Map.mapWithKey (\n -> Map.filterWithKey (readInNode' n)) r let r' = Map.mapWithKey (\n -> Map.filterWithKey (readInNode' n)) r
return $ Map.filter (not . Map.null) r' return $ Map.filter (not . Map.null) r'
@ -109,7 +109,6 @@ findReachDef graph startNode
nodeFunc = processNode nodeFunc = processNode
,prevNodes = lpre graph ,prevNodes = lpre graph
,nextNodes = lsuc graph ,nextNodes = lsuc graph
,initVal = Map.empty
,defVal = Map.empty ,defVal = Map.empty
} }

View File

@ -28,7 +28,6 @@ data GraphFuncs n e a = GF {
nodeFunc :: (n,e) -> a -> Maybe a -> a nodeFunc :: (n,e) -> a -> Maybe a -> a
,prevNodes :: n -> [(n,e)] ,prevNodes :: n -> [(n,e)]
,nextNodes :: n -> [(n,e)] ,nextNodes :: n -> [(n,e)]
,initVal :: a
-- defVal should be the unit of the aggregation. That is, if (nodeFunc a b) == defVal, then (nodeFunc a b defVal) == defVal too -- defVal should be the unit of the aggregation. That is, if (nodeFunc a b) == defVal, then (nodeFunc a b defVal) == defVal too
-- TODO not sure if the above is still true -- TODO not sure if the above is still true
,defVal :: a ,defVal :: a
@ -39,11 +38,11 @@ data GraphFuncs n e a = GF {
-- | Given the graph functions, a list of nodes and an entry node, performs -- | Given the graph functions, a list of nodes and an entry node, performs
-- an iterative data-flow analysis. All the nodes in the list should be connected to -- an iterative data-flow analysis. All the nodes in the list should be connected to
-- the entry node, and there should be no nodes without predecessors in the list. -- the entry node, and there should be no nodes without predecessors in the list.
flowAlgorithm :: forall n e a. (Ord n, Show n, Eq a) => GraphFuncs n e a -> [n] -> n -> Either String (Map.Map n a) flowAlgorithm :: forall n e a. (Ord n, Show n, Eq a) => GraphFuncs n e a -> [n] -> (n, a) -> Either String (Map.Map n a)
flowAlgorithm funcs nodes startNode flowAlgorithm funcs nodes (startNode, startVal)
= iterate = iterate
(Set.fromList nonStartNodes) (Set.fromList nonStartNodes)
(Map.fromList $ (startNode,initVal funcs):(zip nonStartNodes (repeat (defVal funcs)))) (Map.fromList $ (startNode, startVal):(zip nonStartNodes (repeat (defVal funcs))))
where where
nonStartNodes = (filter ((/=) startNode) nodes) nonStartNodes = (filter ((/=) startNode) nodes)