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

View File

@ -23,15 +23,18 @@ import Control.Monad.Error
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.State import Control.Monad.State
import Data.Generics import Data.Generics
import Data.Graph.Inductive (Node) import Data.Graph.Inductive
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Maybe import Data.Maybe
import qualified Data.Set as Set import qualified Data.Set as Set
import Control.Exception import Control.Exception
import qualified AST as A import qualified AST as A
import CompState
import Errors import Errors
import FlowAlgorithms
import FlowGraph import FlowGraph
import FlowUtils
import GenericUtils import GenericUtils
import Metadata import Metadata
import Pass import Pass
@ -54,7 +57,8 @@ data CheckOptData = CheckOptData
data FlowGraphAnalysis res = FlowGraphAnalysis data FlowGraphAnalysis res = FlowGraphAnalysis
{ getFlowGraphAnalysis :: CheckOptData -> Maybe res { getFlowGraphAnalysis :: CheckOptData -> Maybe res
, setFlowGraphAnalysis :: res -> CheckOptData -> CheckOptData , 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 invalidateAll :: (A.AST -> A.AST) -> CheckOptData -> CheckOptData
@ -67,6 +71,9 @@ newtype CheckOptM a = CheckOptM (StateT CheckOptData PassM a)
instance Die CheckOptM where instance Die CheckOptM where
dieReport = CheckOptM . lift . dieReport dieReport = CheckOptM . lift . dieReport
instance CSMR CheckOptM where
getCompState = CheckOptM . lift $ getCompState
deCheckOptM :: CheckOptM a -> StateT CheckOptData PassM a deCheckOptM :: CheckOptM a -> StateT CheckOptData PassM a
deCheckOptM (CheckOptM x) = x deCheckOptM (CheckOptM x) = x
@ -254,8 +261,33 @@ getVarsTouchedAfter = do
varsTouchedAfter :: FlowGraphAnalysis (Map.Map [Int] (Set.Set Var)) varsTouchedAfter :: FlowGraphAnalysis (Map.Map [Int] (Set.Set Var))
varsTouchedAfter = FlowGraphAnalysis varsTouchedAfter = FlowGraphAnalysis
nextVarsTouched (\x d -> d {nextVarsTouched = Just x}) $ nextVarsTouched (\x d -> d {nextVarsTouched = Just x}) $ \(g, lu, startNode) ->
todo 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)] --getLastPlacesWritten :: CheckOptM' t [(Route, Maybe A.Expression)]
@ -281,12 +313,13 @@ getCachedAnalysis an = getCheckOptData >>= \x -> case getFlowGraphAnalysis an x
r <- askRoute r <- askRoute
case Map.lookup (routeId r) nodes of case Map.lookup (routeId r) nodes of
Just n -> liftCheckOptM $ Just n -> liftCheckOptM $
do z <- doFlowGraphAnalysis an (g, n) do z <- doFlowGraphAnalysis an (g, nodes, n)
CheckOptM $ modify $ setFlowGraphAnalysis an z CheckOptM $ modify $ setFlowGraphAnalysis an z
return z return z
Nothing -> dieP emptyMeta "Node not found in flow graph" Nothing -> dieP emptyMeta "Node not found in flow graph"
generateFlowGraph :: A.AST -> CheckOptM (FlowGraph CheckOptM UsageLabel, Map.Map [Int] Node) 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 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 instance Show UsageLabel where
show = const "" show x = "Vars{" ++ show (nodeVars x) ++ "}"
transformParItems :: (a -> b) -> ParItems a -> ParItems b transformParItems :: (a -> b) -> ParItems a -> ParItems b
transformParItems f (SeqItems xs) = SeqItems $ map f xs 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 instance Ord (Route inner outer) where
compare (Route xns _) (Route yns _) = compare xns yns 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 inner outer -> [Int]
routeId (Route ns _) = ns 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 :: DynGraph gr => (Node -> a -> b) -> gr a c -> gr b c
labelMapWithNodeId f = gmap (\(x,n,l,y) -> (x,n,f n l,y)) 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) |AlterReplicator (ASTModifier m A.Replicator structType)
|AlterSpec (ASTModifier m A.Specification structType) |AlterSpec (ASTModifier m A.Specification structType)
|AlterNothing [Int] |AlterNothing [Int]
deriving (Show)
data Monad mAlter => FNode' structType mAlter label data Monad mAlter => FNode' structType mAlter label
= Node (Meta, label, AlterAST mAlter structType) = Node (Meta, label, AlterAST mAlter structType)
@ -71,7 +72,7 @@ type FNode mAlter label = FNode' () mAlter label
--type FEdge = (Node, EdgeLabel, Node) --type FEdge = (Node, EdgeLabel, Node)
instance (Monad m, Show a) => Show (FNode' b m a) where 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 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 in (readFromVars `Set.union` addTo) `Set.difference` Map.keysSet writtenToVars
Nothing -> error "Node label not found in calculateUsedAgainAfter" Nothing -> error "Node label not found in calculateUsedAgainAfter"
--TODO rememember to take note of declarations/scope, otherwise this: --TODO rememember to take note of declarations/scope, otherwise this:
-- seqeach (..) {int:x; ... x = 3;} -- seqeach (..) {int:x; ... x = 3;}
-- will look like x is used again on the next loop iteration -- will look like x is used again on the next loop iteration