Filled in all the gaps such that the CheckTest tests now run (including some debug output, for now)

One of the tests fails at the moment because the specification node has two entries associated with it in the flowgraph.  One is the scope-in and one is the scope-out.  I think the analysis is currently picking the scope-out node and looking beyond that, where -- surprise, surprise -- the variable is not used again.  So I need some easy way of telling the flow analyses which of the two nodes I want to start from, in this case and other ones where I also add two nodes related to the same point in the AST.
This commit is contained in:
Neil Brown 2008-11-12 16:54:00 +00:00
parent 76cfb4d8f5
commit 2a15f4ef5f
7 changed files with 51 additions and 9 deletions

View File

@ -279,6 +279,7 @@ checkUnusedVar :: CheckOptM ()
checkUnusedVar = forAnyAST $ \(A.Spec _ (A.Specification _ name _) scope :: A.Structured
A.Process) -> do
vars <- withChild [1] $ getVarsTouchedAfter
liftIO $ putStrLn $ "Vars: " ++ show vars
when (not $ (Var $ A.Variable emptyMeta name) `Set.member` vars) $
substitute scope

View File

@ -23,15 +23,18 @@ import Control.Monad.Error
import Control.Monad.Reader
import Control.Monad.State
import Data.Generics
import Data.Graph.Inductive (Node)
import Data.Graph.Inductive
import qualified Data.Map as Map
import Data.Maybe
import qualified Data.Set as Set
import Control.Exception
import qualified AST as A
import CompState
import Errors
import FlowAlgorithms
import FlowGraph
import FlowUtils
import GenericUtils
import Metadata
import Pass
@ -54,7 +57,8 @@ data CheckOptData = CheckOptData
data FlowGraphAnalysis res = FlowGraphAnalysis
{ getFlowGraphAnalysis :: CheckOptData -> Maybe res
, setFlowGraphAnalysis :: res -> CheckOptData -> CheckOptData
, doFlowGraphAnalysis :: (FlowGraph CheckOptM UsageLabel, Node) -> CheckOptM res
, doFlowGraphAnalysis :: (FlowGraph CheckOptM UsageLabel, Map.Map [Int] Node,
Node) -> CheckOptM res
}
invalidateAll :: (A.AST -> A.AST) -> CheckOptData -> CheckOptData
@ -67,6 +71,9 @@ newtype CheckOptM a = CheckOptM (StateT CheckOptData PassM a)
instance Die CheckOptM where
dieReport = CheckOptM . lift . dieReport
instance CSMR CheckOptM where
getCompState = CheckOptM . lift $ getCompState
deCheckOptM :: CheckOptM a -> StateT CheckOptData PassM a
deCheckOptM (CheckOptM x) = x
@ -254,8 +261,33 @@ getVarsTouchedAfter = do
varsTouchedAfter :: FlowGraphAnalysis (Map.Map [Int] (Set.Set Var))
varsTouchedAfter = FlowGraphAnalysis
nextVarsTouched (\x d -> d {nextVarsTouched = Just x}) $
todo
nextVarsTouched (\x d -> d {nextVarsTouched = Just x}) $ \(g, lu, startNode) ->
case flowAlgorithm (funcs g) (rdfs [startNode] g) (startNode, Set.empty) of
Left err -> dieP emptyMeta err
Right nodesToVars -> (liftIO $ putStrLn $ show g) >> return (Map.fromList [(y, z) |
(Just y, z) <- map (\(k,v) -> (reverseLookup k lu, v)) $ Map.toList nodesToVars])
where
funcs :: FlowGraph CheckOptM UsageLabel -> GraphFuncs Node EdgeLabel (Set.Set Var)
funcs g = GF
{ nodeFunc = iterate g
-- Backwards data flow:
, nodesToProcess = lsuc g
, nodesToReAdd = lpre g
, defVal = Set.empty
, userErrLabel = ("for node at: " ++) . show . fmap getNodeMeta . lab g
}
iterate :: FlowGraph CheckOptM UsageLabel ->
(Node, EdgeLabel) -> Set.Set Var -> Maybe (Set.Set Var) -> Set.Set Var
iterate g node prevVars maybeVars = case lab g (fst node) of
Just ul ->
let vs = nodeVars $ getNodeData ul
readFromVars = readVars vs
writtenToVars = writtenVars vs
addTo = fromMaybe prevVars maybeVars
in (readFromVars `Set.union` addTo) `Set.union` Map.keysSet writtenToVars
Nothing -> error "Node label not found in calculateUsedAgainAfter"
--getLastPlacesWritten :: CheckOptM' t [(Route, Maybe A.Expression)]
@ -281,12 +313,13 @@ getCachedAnalysis an = getCheckOptData >>= \x -> case getFlowGraphAnalysis an x
r <- askRoute
case Map.lookup (routeId r) nodes of
Just n -> liftCheckOptM $
do z <- doFlowGraphAnalysis an (g, n)
do z <- doFlowGraphAnalysis an (g, nodes, n)
CheckOptM $ modify $ setFlowGraphAnalysis an z
return z
Nothing -> dieP emptyMeta "Node not found in flow graph"
generateFlowGraph :: A.AST -> CheckOptM (FlowGraph CheckOptM UsageLabel, Map.Map [Int] Node)
generateFlowGraph x = buildFlowGraph todo x >>= \g -> case g of
generateFlowGraph x = buildFlowGraph labelUsageFunctions x >>= \g -> case g of
Left err -> dieP emptyMeta err
Right (y,_,_) -> return (y, todo)
Right (y,_,_) -> return (y, Map.fromList $
[(getNodeRouteId l, n)| (n, l) <- labNodes y])

View File

@ -77,7 +77,7 @@ data UsageLabel = Usage
}
instance Show UsageLabel where
show = const ""
show x = "Vars{" ++ show (nodeVars x) ++ "}"
transformParItems :: (a -> b) -> ParItems a -> ParItems b
transformParItems f (SeqItems xs) = SeqItems $ map f xs

View File

@ -171,6 +171,9 @@ instance Eq (Route inner outer) where
instance Ord (Route inner outer) where
compare (Route xns _) (Route yns _) = compare xns yns
instance Show (Route inner outer) where
show (Route ns _) = "Route " ++ show ns
routeId :: Route inner outer -> [Int]
routeId (Route ns _) = ns

View File

@ -349,3 +349,6 @@ eitherToMaybe = either (const Nothing) Just
labelMapWithNodeId :: DynGraph gr => (Node -> a -> b) -> gr a c -> gr b c
labelMapWithNodeId f = gmap (\(x,n,l,y) -> (x,n,f n l,y))
reverseLookup :: (Ord k, Eq v) => v -> Map.Map k v -> Maybe k
reverseLookup x m = lookup x $ map revPair $ Map.toList m

View File

@ -58,6 +58,7 @@ data AlterAST m structType =
|AlterReplicator (ASTModifier m A.Replicator structType)
|AlterSpec (ASTModifier m A.Specification structType)
|AlterNothing [Int]
deriving (Show)
data Monad mAlter => FNode' structType mAlter label
= Node (Meta, label, AlterAST mAlter structType)
@ -71,7 +72,7 @@ type FNode mAlter label = FNode' () mAlter label
--type FEdge = (Node, EdgeLabel, Node)
instance (Monad m, Show a) => Show (FNode' b m a) where
show (Node (m,x,_)) = (filter ((/=) '\"')) $ show m ++ ":" ++ show x
show (Node (m,x,r)) = (filter ((/=) '\"')) $ show m ++ ":" ++ show x ++ "<" ++ show r
type FlowGraph' mAlter label structType = Gr (FNode' structType mAlter label) EdgeLabel

View File

@ -101,6 +101,7 @@ calculateUsedAgainAfter g startNode
in (readFromVars `Set.union` addTo) `Set.difference` Map.keysSet writtenToVars
Nothing -> error "Node label not found in calculateUsedAgainAfter"
--TODO rememember to take note of declarations/scope, otherwise this:
-- seqeach (..) {int:x; ... x = 3;}
-- will look like x is used again on the next loop iteration