Overhauled the way that the array usage checking deals with background knowledge, ready to implement usage checking that makes proper use of background knowledge (information from elsewhere in the program)

This commit is contained in:
Neil Brown 2008-06-05 20:37:59 +00:00
parent cf35eb97d3
commit c9da4a7eaf
3 changed files with 109 additions and 121 deletions

View File

@ -16,11 +16,12 @@ 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 ArrayUsageCheck (BackgroundKnowledge(..), checkArrayUsage, FlattenedExp(..), makeEquations, makeExpSet, ModuloCase(..), onlyConst, showFlattenedExp, VarMap) where module ArrayUsageCheck (BackgroundKnowledge(..), BK, checkArrayUsage, FlattenedExp(..), makeEquations, makeExpSet, ModuloCase(..), onlyConst, showFlattenedExp, VarMap) where
import Control.Monad.Error import Control.Monad.Error
import Control.Monad.State import Control.Monad.State
import Data.Array.IArray import Data.Array.IArray
import Data.Generics hiding (GT)
import Data.Int import Data.Int
import Data.List import Data.List
import qualified Data.Map as Map import qualified Data.Map as Map
@ -38,27 +39,40 @@ import Types
import UsageCheckUtils import UsageCheckUtils
import Utils import Utils
-- Each list is a possible set of background knowledge mapping vars to a list
-- of constraints. So it is a disjunction of map from variables to conjunctions
type BK = [Map.Map Var [BackgroundKnowledge]]
type BK' = [Map.Map Var (EqualityProblem, InequalityProblem)]
-- | A check-pass that checks the given ParItems (usually generated from a control-flow graph) -- | A check-pass that checks the given ParItems (usually generated from a control-flow graph)
-- for any overlapping array indices. -- for any overlapping array indices.
checkArrayUsage :: forall m. (Die m, CSMR m, MonadIO m) => (Meta, ParItems UsageLabel) -> m () checkArrayUsage :: forall m. (Die m, CSMR m, MonadIO m) => (Meta, ParItems (BK, UsageLabel)) -> m ()
checkArrayUsage (m,p) = mapM_ (checkIndexes m) $ Map.toList $ checkArrayUsage (m,p) = mapM_ (checkIndexes m) $ Map.toList $
groupArrayIndexes $ transformParItems nodeVars p groupArrayIndexes $ fmap (transformPair id nodeVars) p
where where
-- Takes a ParItems Vars, and returns a map from array-variable-name to a list of writes and a list of reads for that array. -- Takes a ParItems Vars, and returns a map from array-variable-name to a list of writes and a list of reads for that array.
-- Returns (array name, list of written-to indexes, list of read-from indexes) -- Returns (array name, list of written-to indexes, list of read-from indexes)
groupArrayIndexes :: ParItems Vars -> Map.Map String (ParItems ([A.Expression], [A.Expression])) groupArrayIndexes :: ParItems (BK, Vars) -> Map.Map String (ParItems (BK, [A.Expression], [A.Expression]))
groupArrayIndexes vs = filterByKey $ transformParItems (uncurry (zipMap join) . (transformPair (makeList . writtenVars) (makeList . readVars)) . mkPair) vs groupArrayIndexes = filterByKey . fmap
(\(bk,vs) -> zipMap (join bk) (makeList $ Map.keysSet $ writtenVars vs) (makeList $ readVars vs))
where where
join :: Maybe [a] -> Maybe [a] -> Maybe ([a],[a]) join :: b -> Maybe [a] -> Maybe [a] -> Maybe (b, [a],[a])
join x y = Just (fromMaybe [] x, fromMaybe [] y) join k x y = Just (k, fromMaybe [] x, fromMaybe [] y)
-- Turns a set of variables into a map (from array-name to list of index-expressions) -- Turns a set of variables into a map (from array-name to list of index-expressions)
makeList :: Set.Set Var -> Map.Map String [A.Expression] makeList :: Set.Set Var -> Map.Map String [A.Expression]
makeList = Set.fold (maybe id (uncurry $ Map.insertWith (++)) . getArrayIndex) Map.empty makeList = Set.fold (maybe id (uncurry $ Map.insertWith (++)) . getArrayIndex) Map.empty
-- Lifts a map (from array-name to expression-lists) inside a ParItems to being a map (from array-name to ParItems of expression lists) -- Lifts a map (from array-name to expression-lists) inside a ParItems to being a map (from array-name to ParItems of expression lists)
filterByKey :: ParItems (Map.Map String ([A.Expression], [A.Expression])) -> Map.Map String (ParItems ([A.Expression], [A.Expression])) filterByKey :: ParItems (Map.Map String (BK, [A.Expression], [A.Expression])) -> Map.Map String (ParItems (BK,
filterByKey p = Map.fromList $ map (\k -> (k, transformParItems (Map.findWithDefault ([],[]) k) p)) (concatMap Map.keys $ flattenParItems p) [A.Expression], [A.Expression]))
filterByKey p = Map.fromList $ map trans keys
where
keys :: [String]
keys = concatMap Map.keys $ flattenParItems p
trans :: String -> (String, ParItems (BK, [A.Expression], [A.Expression]))
trans k = (k, fmap (Map.findWithDefault ([], [], []) k) p)
-- Gets the (array-name, indexes) from a Var. -- Gets the (array-name, indexes) from a Var.
-- TODO this is quite hacky, and doesn't yet deal with slices and so on: -- TODO this is quite hacky, and doesn't yet deal with slices and so on:
@ -67,19 +81,9 @@ checkArrayUsage (m,p) = mapM_ (checkIndexes m) $ Map.toList $
= Just (A.nameName n, [e]) = Just (A.nameName n, [e])
getArrayIndex _ = Nothing getArrayIndex _ = Nothing
-- Turns a replicator into background knowledge about that replicator
makeRepBounds :: (A.Name, A.Replicator) -> [BackgroundKnowledge]
makeRepBounds (n, A.For m from for) = [LessThanOrEqual from ev, LessThanOrEqual ev $ A.Dyadic m A.Subtr (A.Dyadic m A.Add from for) (makeConstant m 1)]
where
ev = A.ExprVariable m (A.Variable m n)
-- Gets all the replicators present in the argument
listReplicators :: ParItems UsageLabel -> [(A.Name, A.Replicator)]
listReplicators p = mapMaybe nodeRep $ flattenParItems p
-- Checks the given ParItems of writes and reads against each other. The -- Checks the given ParItems of writes and reads against each other. The
-- String (array-name) and Meta are only used for printing out error messages -- String (array-name) and Meta are only used for printing out error messages
checkIndexes :: Meta -> (String,ParItems ([A.Expression],[A.Expression])) -> m () checkIndexes :: Meta -> (String, ParItems (BK, [A.Expression], [A.Expression])) -> m ()
checkIndexes m (arrName, indexes) checkIndexes m (arrName, indexes)
= do userArrName <- getRealName (A.Name undefined arrName) = do userArrName <- getRealName (A.Name undefined arrName)
arrType <- astTypeOf (A.Name undefined arrName) arrType <- astTypeOf (A.Name undefined arrName)
@ -89,7 +93,7 @@ checkArrayUsage (m,p) = mapM_ (checkIndexes m) $ Map.toList $
A.Array (A.UnknownDimension:_) _ -> return $ makeConstant m $ fromInteger $ toInteger (maxBound :: Int32) A.Array (A.UnknownDimension:_) _ -> return $ makeConstant m $ fromInteger $ toInteger (maxBound :: Int32)
-- It's not an array: -- It's not an array:
_ -> dieP m $ "Cannot usage check array \"" ++ userArrName ++ "\"; found to be of type: " ++ show arrType _ -> dieP m $ "Cannot usage check array \"" ++ userArrName ++ "\"; found to be of type: " ++ show arrType
case makeEquations (concatMap makeRepBounds $ listReplicators p) indexes arrLength of case makeEquations indexes arrLength of
Left err -> dieP m $ "Could not work with array indexes for array \"" ++ userArrName ++ "\": " ++ err Left err -> dieP m $ "Could not work with array indexes for array \"" ++ userArrName ++ "\": " ++ err
Right [] -> return () -- No problems to work with Right [] -> return () -- No problems to work with
Right problems -> Right problems ->
@ -311,6 +315,34 @@ data ModuloCase =
| XNegYNegAZero | XNegYNegANonZero | XNegYNegAZero | XNegYNegANonZero
deriving (Show, Eq, Ord) deriving (Show, Eq, Ord)
-- | Transforms background knowledge into problems
-- TODO allow modulo in background knowledge
transformBK :: BackgroundKnowledge -> StateT VarMap (Either String) (EqualityProblem,InequalityProblem)
transformBK (Equal eL eR) = do eL' <- makeSingleEq eL "background knowledge"
eR' <- makeSingleEq eR "background knowledge"
let e = addEq eL' (amap negate eR')
return ([e],[])
transformBK (LessThanOrEqual eL eR)
= do eL' <- makeSingleEq eL "background knowledge"
eR' <- makeSingleEq eR "background knowledge"
-- eL <= eR implies eR - eL >= 0
let e = addEq (amap negate eL') eR'
return ([],[e])
transformBKList :: [BackgroundKnowledge] -> StateT VarMap (Either String) (EqualityProblem,InequalityProblem)
transformBKList bk = mapM transformBK bk >>* foldl accumProblem ([],[])
-- | Turns a single expression into an equation-item. An error is given if the resulting
-- expression is anything complicated (for example, modulo or divide)
makeSingleEq :: A.Expression -> String -> StateT VarMap (Either String) EqualityConstraintEquation
makeSingleEq e desc = lift (flatten e) >>= makeEquation e [{-TODO-}] (error $ "Type is irrelevant for " ++ desc)
>>= getSingleAccessItem ("Modulo or Divide not allowed in " ++ desc)
-- | A helper function for joining two problems
accumProblem :: (EqualityProblem,InequalityProblem) -> (EqualityProblem,InequalityProblem) -> (EqualityProblem,InequalityProblem)
accumProblem (a,b) (c,d) = (a ++ c, b ++ d)
-- | Given a list of (written,read) expressions, an expression representing the upper array bound, returns either an error -- | Given a list of (written,read) expressions, an expression representing the upper array bound, returns either an error
-- (because the expressions can't be handled, typically) or a set of equalities, inequalities and mapping from -- (because the expressions can't be handled, typically) or a set of equalities, inequalities and mapping from
-- (unique, munged) variable name to variable-index in the equations. -- (unique, munged) variable name to variable-index in the equations.
@ -337,36 +369,21 @@ data ModuloCase =
-- squareAndPair. -- squareAndPair.
-- --
-- TODO probably want to take this into the PassM monad at some point, to use the Meta in the error message -- TODO probably want to take this into the PassM monad at some point, to use the Meta in the error message
makeEquations :: [BackgroundKnowledge] -> ParItems ([A.Expression],[A.Expression]) -> A.Expression -> makeEquations :: ParItems (BK, [A.Expression], [A.Expression]) -> A.Expression ->
Either String [(((A.Expression, [ModuloCase]), (A.Expression, [ModuloCase])), VarMap, (EqualityProblem, InequalityProblem))] Either String [(((A.Expression, [ModuloCase]), (A.Expression, [ModuloCase])), VarMap, (EqualityProblem, InequalityProblem))]
makeEquations otherInfo accesses bound makeEquations accesses bound
= do ((v,h,o,repVarIndexes),s) <- (flip runStateT) Map.empty $ = do ((v,h,repVarIndexes),s) <- (flip runStateT) Map.empty $
do (accesses',repVars) <- flip runStateT [] $ parItemToArrayAccessM mkEq accesses do (accesses',repVars) <- flip runStateT [] $ parItemToArrayAccessM mkEq accesses
high <- makeSingleEq bound "upper bound" high <- makeSingleEq bound "upper bound"
other <- mapM transformBK otherInfo return (accesses', high, nub repVars)
let other' = foldl accumProblem ([],[]) other return $ squareAndPair lookupBK (\(x,y,_) -> (x,y)) repVarIndexes s v (amap (const 0) h, addConstant (-1) h)
return (accesses', high, other', nub repVars)
return $ squareAndPair o repVarIndexes s v (amap (const 0) h, addConstant (-1) h)
where where
-- | Transforms background knowledge into problems lookupBK :: (A.Expression, [ModuloCase], BK') -> [(EqualityProblem, InequalityProblem)]
-- TODO make sure only relevant background knowledge is used (somehow?) lookupBK (e,_,bk) = map (foldl accumProblem ([],[]) . map snd . filter (\(v,eq) -> v `elem` vs) . Map.toList) bk
-- TODO allow modulo in background knowledge where
transformBK :: BackgroundKnowledge -> StateT VarMap (Either String) (EqualityProblem,InequalityProblem) vs :: [Var]
transformBK (Equal eL eR) = do eL' <- makeSingleEq eL "background knowledge" vs = map Var $ listify (const True :: A.Variable -> Bool) e
eR' <- makeSingleEq eR "background knowledge"
let e = addEq eL' (amap negate eR')
return ([e],[])
transformBK (LessThanOrEqual eL eR)
= do eL' <- makeSingleEq eL "background knowledge"
eR' <- makeSingleEq eR "background knowledge"
-- eL <= eR implies eR - eL >= 0
let e = addEq (amap negate eL') eR'
return ([],[e])
-- | A helper function for joining two problems
accumProblem :: (EqualityProblem,InequalityProblem) -> (EqualityProblem,InequalityProblem) -> (EqualityProblem,InequalityProblem)
accumProblem (a,b) (c,d) = (a ++ c, b ++ d)
-- | A front-end to the setIndexVar' function -- | A front-end to the setIndexVar' function
setIndexVar :: A.Variable -> Int -> [FlattenedExp] -> [FlattenedExp] setIndexVar :: A.Variable -> Int -> [FlattenedExp] -> [FlattenedExp]
@ -387,66 +404,15 @@ makeEquations otherInfo accesses bound
bottom' = Set.map (setIndexVar' tv ti) bottom bottom' = Set.map (setIndexVar' tv ti) bottom
setIndexVar' _ _ e = e setIndexVar' _ _ e = e
-- | Turns a single expression into an equation-item. An error is given if the resulting
-- expression is anything complicated (for example, modulo or divide)
makeSingleEq :: A.Expression -> String -> StateT VarMap (Either String) EqualityConstraintEquation
makeSingleEq e desc = lift (flatten e) >>= makeEquation e (error $ "Type is irrelevant for " ++ desc)
>>= getSingleAccessItem ("Modulo or Divide not allowed in " ++ desc)
-- | A helper function that takes a list of replicated variables and lower and upper bounds, then
-- looks to add the bounds to any array accesses that feature the replicated variable in either
-- its plain or primed version (the bounds are left plain or primed appropriately).
makeEquationWithPossibleRepBounds :: [(A.Variable, EqualityConstraintEquation, EqualityConstraintEquation)] ->
ArrayAccess label -> StateT (VarMap) (Either String) (ArrayAccess label)
makeEquationWithPossibleRepBounds [] item = return item
makeEquationWithPossibleRepBounds ((v,lower,upper):vars) item
-- We fold over the variables, altering the items one at a time via mapM:
= do item' <- makeEquationWithPossibleRepBounds vars item
flip addPossibleRepBound' (v,0,lower,upper) item' >>=
flip addPossibleRepBound' (v,1,lower,upper)
-- | Applies addPossibleRepBound everywhere in an ArrayAccess
addPossibleRepBound' :: ArrayAccess label ->
(A.Variable, Int, EqualityConstraintEquation, EqualityConstraintEquation) ->
StateT (VarMap) (Either String) (ArrayAccess label)
addPossibleRepBound' (Group accesses) v = sequence [addPossibleRepBound acc v >>* (\acc' -> (l,t,acc')) | (l,t,acc) <- accesses ] >>* Group
addPossibleRepBound' (Replicated acc0 acc1) v
= do acc0' <- mapM (flip addPossibleRepBound' v) acc0
acc1' <- mapM (flip addPossibleRepBound' v) acc1
return $ Replicated acc0' acc1'
-- | Adds a replicated bound if any of the item, equalities or inequalities feature
-- the variable in question
addPossibleRepBound :: (EqualityConstraintEquation, EqualityProblem, InequalityProblem) ->
(A.Variable, Int, EqualityConstraintEquation, EqualityConstraintEquation) ->
StateT (VarMap) (Either String) (EqualityConstraintEquation, EqualityProblem, InequalityProblem)
addPossibleRepBound (item,eq,ineq) (var,index,lower,upper)
= do vindex <- varIndex (Scale 1 $ (A.ExprVariable emptyMeta var, index))
let boundEqs = if elemPresent vindex item || any (elemPresent vindex) eq || any (elemPresent vindex) ineq
then [add (vindex,1) $ amap negate lower,add (vindex,-1) upper]
else []
return (item,eq,ineq ++ boundEqs)
where
elemPresent index item = arrayLookupWithDefault 0 item index /= 0
-- | A function to add an amount to the specified index, without the possibility of
-- screwing up the array by adding a number that is beyond its current size (in that
-- case, the array is resized appropriately)
add :: (CoeffIndex, Integer) -> Array CoeffIndex Integer -> Array CoeffIndex Integer
add (ind,val) a = (makeArraySize (newMin, newMax) 0 a) // [(ind, (arrayLookupWithDefault 0 a ind) + val)]
where
newMin = minimum [fst $ bounds a, ind]
newMax = maximum [snd $ bounds a, ind]
-- | Given a list of replicators (marked enabled\/disabled by a flag), the writes and reads, -- | Given a list of replicators (marked enabled\/disabled by a flag), the writes and reads,
-- turns them into a single list of accesses with all the relevant information. The writes and reads -- turns them into a single list of accesses with all the relevant information. The writes and reads
-- can be grouped together because they are differentiated by the ArrayAccessType in the result -- can be grouped together because they are differentiated by the ArrayAccessType in the result
mkEq :: [((A.Name, A.Replicator), Bool)] -> mkEq :: [((A.Name, A.Replicator), Bool)] ->
([A.Expression], [A.Expression]) -> (BK, [A.Expression], [A.Expression]) ->
StateT [(CoeffIndex, CoeffIndex)] StateT [(CoeffIndex, CoeffIndex)]
(StateT VarMap (Either String)) (StateT VarMap (Either String))
[((A.Expression, [ModuloCase]), ArrayAccessType, (EqualityConstraintEquation, EqualityProblem, InequalityProblem))] [((A.Expression, [ModuloCase], BK'), ArrayAccessType, (EqualityConstraintEquation, EqualityProblem, InequalityProblem))]
mkEq reps (ws,rs) = do repVarEqs <- mapM (liftF makeRepVarEq) reps mkEq reps (bk, ws, rs) = do repVarEqs <- mapM (liftF makeRepVarEq) reps
concatMapM (mkEq' repVarEqs) (ws' ++ rs') concatMapM (mkEq' repVarEqs) (ws' ++ rs')
where where
ws' = zip (repeat AAWrite) ws ws' = zip (repeat AAWrite) ws
@ -462,11 +428,11 @@ makeEquations otherInfo accesses bound
(ArrayAccessType, A.Expression) -> (ArrayAccessType, A.Expression) ->
StateT [(CoeffIndex,CoeffIndex)] StateT [(CoeffIndex,CoeffIndex)]
(StateT VarMap (Either String)) (StateT VarMap (Either String))
[((A.Expression, [ModuloCase]), ArrayAccessType, (EqualityConstraintEquation, EqualityProblem, InequalityProblem))] [((A.Expression, [ModuloCase], BK'), ArrayAccessType, (EqualityConstraintEquation, EqualityProblem, InequalityProblem))]
mkEq' repVarEqs (aat, e) mkEq' repVarEqs (aat, e)
= do f <- lift . lift $ flatten e = do f <- lift . lift $ flatten e
f' <- foldM mirrorFlaggedVars f reps f' <- foldM mirrorFlaggedVars f reps
g <- lift $ makeEquationWithPossibleRepBounds repVarEqs =<< makeEquation e aat f' g <- lift $ makeEquation e bk aat f'
case g of case g of
Group g' -> return g' Group g' -> return g'
_ -> throwError "Replicated group found unexpectedly" _ -> throwError "Replicated group found unexpectedly"
@ -589,16 +555,22 @@ flatten e = return [Scale 1 (e,0)]
-- will produce both "i = i' + 1" and "i + 1 = i'" so there is no need -- will produce both "i = i' + 1" and "i + 1 = i'" so there is no need
-- to vary the inequality itself. -- to vary the inequality itself.
squareAndPair :: squareAndPair ::
(EqualityProblem, InequalityProblem) -> (label -> [(EqualityProblem, InequalityProblem)]) ->
(label -> labelStripped) ->
[(CoeffIndex, CoeffIndex)] -> [(CoeffIndex, CoeffIndex)] ->
VarMap -> VarMap ->
[ArrayAccess label] -> [ArrayAccess label] ->
(EqualityConstraintEquation, EqualityConstraintEquation) -> (EqualityConstraintEquation, EqualityConstraintEquation) ->
[((label, label), VarMap, (EqualityProblem, InequalityProblem))] [((labelStripped, labelStripped), VarMap, (EqualityProblem, InequalityProblem))]
squareAndPair (bkEq, bkIneq) repVars s v lh squareAndPair lookupBK strip repVars s v lh
= [(labels, s,squareEquations (bkEq ++ eq, bkIneq ++ ineq ++ concat (applyAll (eq,ineq) (map addExtra repVars)))) = [(transformPair strip strip labels, s,squareEquations (bkEqA ++ bkEqB ++
eq, bkIneqA ++ bkIneqB ++ ineq ++ concat (applyAll (eq,ineq) (map addExtra repVars))))
| (labels, eq,ineq) <- pairEqsAndBounds v lh | (labels, eq,ineq) <- pairEqsAndBounds v lh
,and (map (primeImpliesPlain (eq,ineq)) repVars) ,and (map (primeImpliesPlain (eq,ineq)) repVars)
,((bkEqA, bkIneqA), (bkEqB, bkIneqB)) <-
case product2 (lookupBK (fst labels), lookupBK (snd labels)) of
[] -> [(([],[]),([],[]))] -- No BK
xs -> xs
] ]
where where
itemPresent :: CoeffIndex -> [Array CoeffIndex Integer] -> Bool itemPresent :: CoeffIndex -> [Array CoeffIndex Integer] -> Bool
@ -708,11 +680,13 @@ getIneqs (low, high) = concatMap getLH
-- | Given an expression, forms equations (and accompanying additional equation-sets) and returns it -- | Given an expression, forms equations (and accompanying additional equation-sets) and returns it
makeEquation :: label -> ArrayAccessType -> [FlattenedExp] -> StateT VarMap (Either String) (ArrayAccess (label,[ModuloCase])) makeEquation :: label -> BK -> ArrayAccessType -> [FlattenedExp] -> StateT VarMap (Either String) (ArrayAccess (label,[ModuloCase],
makeEquation l t summedItems BK'))
makeEquation l bk t summedItems
= do eqs <- process summedItems = do eqs <- process summedItems
bk' <- mapM (mapMapM transformBKList) bk
let eqs' = map (transformQuad id mapToArray (map mapToArray) (map mapToArray)) eqs :: [([ModuloCase], EqualityConstraintEquation, EqualityProblem, InequalityProblem)] let eqs' = map (transformQuad id mapToArray (map mapToArray) (map mapToArray)) eqs :: [([ModuloCase], EqualityConstraintEquation, EqualityProblem, InequalityProblem)]
return $ Group [((l,c),t,(e0,e1,e2)) | (c,e0,e1,e2) <- eqs'] return $ Group [((l,c,bk'),t,(e0,e1,e2)) | (c,e0,e1,e2) <- eqs']
where where
process :: [FlattenedExp] -> StateT VarMap (Either String) [([ModuloCase], Map.Map Int Integer,[Map.Map Int Integer], [Map.Map Int Integer])] process :: [FlattenedExp] -> StateT VarMap (Either String) [([ModuloCase], Map.Map Int Integer,[Map.Map Int Integer], [Map.Map Int Integer])]
process = foldM makeEquation' empty process = foldM makeEquation' empty

View File

@ -452,8 +452,8 @@ testMakeEquations = TestLabel "testMakeEquations" $ TestList
| otherwise = [((m,[]),(n',[])) | n' <- [(m + 1) .. n]] ++ labelNums (m + 1) n | otherwise = [((m,[]),(n',[])) | n' <- [(m + 1) .. n]] ++ labelNums (m + 1) n
makeParItems :: [A.Expression] -> ParItems ([A.Expression],[A.Expression]) makeParItems :: [A.Expression] -> ParItems (BK, [A.Expression],[A.Expression])
makeParItems es = ParItems $ map (\e -> SeqItems [([e],[])]) es makeParItems es = ParItems $ map (\e -> SeqItems [([],[e],[])]) es
lookup :: [A.Expression] -> (Int, a) -> (A.Expression, a) lookup :: [A.Expression] -> (Int, a) -> (A.Expression, a)
lookup es (n,b) = (es !! n, b) lookup es (n,b) = (es !! n, b)
@ -462,13 +462,13 @@ testMakeEquations = TestLabel "testMakeEquations" $ TestList
test' (ind, problems, exprs, upperBound) = test' (ind, problems, exprs, upperBound) =
TestCase $ assertEquivalentProblems ("testMakeEquations " ++ show ind) TestCase $ assertEquivalentProblems ("testMakeEquations " ++ show ind)
(map (\((a0,a1),b,c,d) -> ((lookup exprs a0, lookup exprs a1), b, makeConsistent c d)) problems) (map (\((a0,a1),b,c,d) -> ((lookup exprs a0, lookup exprs a1), b, makeConsistent c d)) problems)
=<< (checkRight $ makeEquations [] (makeParItems exprs) upperBound) =<< (checkRight $ makeEquations (makeParItems exprs) upperBound)
testRep' :: (Integer,[(((Int,[ModuloCase]), (Int,[ModuloCase])), VarMap,[HandyEq],[HandyIneq])],(String, A.Expression, A.Expression),[A.Expression],A.Expression) -> Test testRep' :: (Integer,[(((Int,[ModuloCase]), (Int,[ModuloCase])), VarMap,[HandyEq],[HandyIneq])],(String, A.Expression, A.Expression),[A.Expression],A.Expression) -> Test
testRep' (ind, problems, (repName, repFrom, repFor), exprs, upperBound) = testRep' (ind, problems, (repName, repFrom, repFor), exprs, upperBound) =
TestCase $ assertEquivalentProblems ("testMakeEquations " ++ show ind) TestCase $ assertEquivalentProblems ("testMakeEquations " ++ show ind)
(map (\((a0,a1),b,c,d) -> ((lookup exprs a0, lookup exprs a1), b, makeConsistent c d)) problems) (map (\((a0,a1),b,c,d) -> ((lookup exprs a0, lookup exprs a1), b, makeConsistent c d)) problems)
=<< (checkRight $ makeEquations [] (RepParItem (simpleName "i", A.For emptyMeta repFrom repFor) $ makeParItems exprs) upperBound) =<< (checkRight $ makeEquations (RepParItem (simpleName "i", A.For emptyMeta repFrom repFor) $ makeParItems exprs) upperBound)
pairLatterTwo (l,a,b,c) = (l,a,(b,c)) pairLatterTwo (l,a,b,c) = (l,a,(b,c))
@ -524,9 +524,9 @@ testMakeEquations = TestLabel "testMakeEquations" $ TestList
testMakeEquation :: TestMonad m r => ([(((A.Expression, [ModuloCase]), (A.Expression, [ModuloCase])), VarMap,[HandyEq],[HandyIneq])],ParItems [A.Expression],A.Expression) -> m () testMakeEquation :: TestMonad m r => ([(((A.Expression, [ModuloCase]), (A.Expression, [ModuloCase])), VarMap,[HandyEq],[HandyIneq])],ParItems [A.Expression],A.Expression) -> m ()
testMakeEquation (problems, exprs, upperBound) = testMakeEquation (problems, exprs, upperBound) =
assertEquivalentProblems "" assertEquivalentProblems ""
(map (\(x,y,z) -> (x, y, uncurry makeConsistent z)) $ map pairLatterTwo problems) =<< (checkRight $ makeEquations [] (transformParItems pairWithEmpty exprs) upperBound) (map (\(x,y,z) -> (x, y, uncurry makeConsistent z)) $ map pairLatterTwo problems) =<< (checkRight $ makeEquations (transformParItems pairWithEmpty exprs) upperBound)
where where
pairWithEmpty a = (a,[]) pairWithEmpty a = ([],a,[])
pairLatterTwo (l,a,b,c) = (l,a,(b,c)) pairLatterTwo (l,a,b,c) = (l,a,(b,c))
-- TODO add background knowledge -- TODO add background knowledge

View File

@ -49,12 +49,26 @@ usageCheckPass t = do g' <- buildFlowGraph labelUsageFunctions t
(g, roots) <- case g' of (g, roots) <- case g' of
Left err -> dieP (findMeta t) err Left err -> dieP (findMeta t) err
Right (g,rs,_) -> return (g,rs) Right (g,rs,_) -> return (g,rs)
checkPar nodeRep (joinCheckParFunctions checkArrayUsage checkPlainVarUsage) g reach <- case mapM (findReachDef g) roots >>* foldl Map.union
Map.empty of
Left err -> dieP emptyMeta $ "findReachDef: " ++
err
Right g -> return g
checkPar (nodeRep . snd)
(joinCheckParFunctions
checkArrayUsage
(checkPlainVarUsage . transformPair id (fmap snd)))
$ nmap (addBK reach g) g
checkParAssignUsage t checkParAssignUsage t
checkProcCallArgsUsage t checkProcCallArgsUsage t
mapM_ (checkInitVar (findMeta t) g) roots mapM_ (checkInitVar (findMeta t) g) roots
return t return t
addBK :: Map.Map Node (Map.Map Var (Set.Set (Maybe A.Expression))) -> FlowGraph PassM UsageLabel -> FNode
PassM UsageLabel -> FNode PassM (BK, UsageLabel)
addBK _ _ = fmap ((,) []) --TODO
filterPlain :: Set.Set Var -> Set.Set Var filterPlain :: Set.Set Var -> Set.Set Var
filterPlain = Set.filter plain filterPlain = Set.filter plain
where where
@ -210,7 +224,7 @@ checkParAssignUsage = mapM_ checkParAssign . listify isParAssign
checkParAssign :: A.Process -> m () checkParAssign :: A.Process -> m ()
checkParAssign (A.Assign m vs _) checkParAssign (A.Assign m vs _)
= do checkPlainVarUsage (m, mockedupParItems) = do checkPlainVarUsage (m, mockedupParItems)
checkArrayUsage (m, mockedupParItems) checkArrayUsage (m, fmap ((,) []) mockedupParItems) -- TODO add BK properly
where where
mockedupParItems :: ParItems UsageLabel mockedupParItems :: ParItems UsageLabel
mockedupParItems = ParItems [SeqItems [Usage Nothing Nothing $ processVarW v mockedupParItems = ParItems [SeqItems [Usage Nothing Nothing $ processVarW v
@ -232,4 +246,4 @@ checkProcCallArgsUsage = mapM_ checkArgs . listify isProcCall
let mockedupParItems = ParItems [SeqItems [Usage Nothing Nothing v] let mockedupParItems = ParItems [SeqItems [Usage Nothing Nothing v]
| v <- vars] | v <- vars]
checkPlainVarUsage (m, mockedupParItems) checkPlainVarUsage (m, mockedupParItems)
checkArrayUsage (m, mockedupParItems) checkArrayUsage (m, fmap ((,) []) mockedupParItems)