diff --git a/Makefile.am b/Makefile.am
index 929e322..7cbad0f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,7 @@ CLEANFILES = $(BUILT_SOURCES)
tock_SOURCES_hs = transformations/SimplifyExprs.hs transformations/SimplifyTypes.hs
tock_SOURCES_hs += transformations/Unnest.hs transformations/RainUsageCheck.hs transformations/SimplifyProcs.hs
tock_SOURCES_hs += transformations/SimplifyComms.hs transformations/ArrayUsageCheck.hs
-tock_SOURCES_hs += transformations/Omega.hs
+tock_SOURCES_hs += transformations/Omega.hs transformations/UsageCheck.hs
tock_SOURCES_hs += frontends/PreprocessOccam.hs frontends/ParseRain.hs frontends/StructureOccam.hs
tock_SOURCES_hs += frontends/ParseOccam.hs frontends/RainTypes.hs frontends/RainPasses.hs frontends/ParseUtils.hs
tock_SOURCES_hs += common/Pass.hs common/TreeUtils.hs common/Intrinsics.hs common/EvalLiterals.hs
diff --git a/common/PassList.hs b/common/PassList.hs
index a4b2e6f..6d06a81 100644
--- a/common/PassList.hs
+++ b/common/PassList.hs
@@ -36,7 +36,7 @@ commonPasses opts =
[ ("Simplify types", simplifyTypes)
, ("Simplify expressions", simplifyExprs)
]
- ++ (if csUsageChecking opts then [("Check array usage", checkArrayUsage)] else []) ++
+ ++ (if csUsageChecking opts then [("Usage checks", usageCheckPass)] else []) ++
[
("Simplify processes", simplifyProcs)
, ("Flatten nested declarations", unnest)
diff --git a/transformations/ArrayUsageCheck.hs b/transformations/ArrayUsageCheck.hs
index f70337b..6225ad4 100644
--- a/transformations/ArrayUsageCheck.hs
+++ b/transformations/ArrayUsageCheck.hs
@@ -16,12 +16,12 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see .
-}
-module ArrayUsageCheck (checkArrayUsage, FlattenedExp(..), makeEquations, makeReplicatedEquations, VarMap) where
+module ArrayUsageCheck (checkArrayUsage, FlattenedExp(..), makeEquations, makeReplicatedEquations, usageCheckPass, VarMap) where
import Control.Monad.Error
import Control.Monad.State
import Data.Array.IArray
-import Data.Generics hiding (GT)
+import Data.Graph.Inductive
import Data.List
import qualified Data.Map as Map
import Data.Maybe
@@ -35,25 +35,52 @@ import Metadata
import Omega
import Pass
import Types
+import UsageCheck
import Utils
+usageCheckPass :: Pass
+usageCheckPass t = do g' <- buildFlowGraph labelFunctions t
+ g <- case g' of
+ Left err -> die err
+ Right g -> return g
+ checkArrayUsage g undefined -- TODO do we need a start node?
+ return t
+
+
-- TODO we should probably calculate this from the CFG
-checkArrayUsage :: Data a => a -> PassM a
-checkArrayUsage tree = (mapM_ checkPar $ listify (const True) tree) >> return tree
+checkArrayUsage :: forall m. (Die m, CSM m) => FlowGraph m (Maybe Decl, Vars) -> Node -> m ()
+checkArrayUsage graph startNode = sequence_ $ checkPar checkArrayUsage' graph startNode
where
- -- TODO this doesn't actually check that the uses are in parallel;
- -- they might be in sequence within the parallel!
- checkPar :: A.Process -> PassM ()
- checkPar (A.Par m _ p) = mapM_ (checkIndexes m) $ Map.toList $ Map.fromListWith (++) $ mapMaybe groupArrayIndexes $ listify (const True) p
- checkPar _ = return ()
+ -- TODO take proper account of replication!
+ flatten :: ParItems a -> [a]
+ flatten (ParItem x) = [x]
+ flatten (ParItems xs) = concatMap flatten xs
+ flatten (RepParItem _ x) = flatten x --TODO
+
+ checkArrayUsage' :: (Meta, ParItems (Maybe Decl, Vars)) -> m ()
+ checkArrayUsage' (m,p) = mapM_ (checkIndexes m) $ Map.toList $
+ foldl (Map.unionWith (\(a,b) (c,d) -> (a ++ c, b ++ d))) Map.empty $ map (groupArrayIndexes . snd) $ flatten p
- groupArrayIndexes :: A.Variable -> Maybe (String,[A.Expression])
- -- TODO this is quite hacky:
- groupArrayIndexes (A.SubscriptedVariable _ (A.Subscript _ e) (A.Variable _ n))
- = Just (A.nameName n, [e])
- groupArrayIndexes _ = Nothing
+ -- Returns (array name, list of written-to indexes, list of read-from indexes)
+ groupArrayIndexes :: Vars -> Map.Map String ([A.Expression], [A.Expression])
+ groupArrayIndexes vs = zipMap join (makeList (writtenVars vs)) (makeList (readVars vs))
+ where
+ join :: Maybe [a] -> Maybe [a] -> Maybe ([a],[a])
+ join x y = Just (maybe [] id x, maybe [] id y)
+
+ makeList :: Set.Set Var -> Map.Map String [A.Expression]
+ makeList = Set.fold (maybe id (uncurry $ Map.insertWith (++)) . getArrayIndex) Map.empty
+
+-- sortAndGroupBy :: (a -> a -> Ordering) -> [a] -> [[a]]
+-- sortAndGroupBy f = groupBy ((== EQ) . f) . sortBy f
+
+ -- TODO this is quite hacky:
+ getArrayIndex :: Var -> Maybe (String, [A.Expression])
+ getArrayIndex (Var (A.SubscriptedVariable _ (A.Subscript _ e) (A.Variable _ n)))
+ = Just (A.nameName n, [e])
+ getArrayIndex _ = Nothing
- checkIndexes :: Meta -> (String,[A.Expression]) -> PassM ()
+ checkIndexes :: Meta -> (String,([A.Expression],[A.Expression])) -> m ()
checkIndexes m (arrName, indexes)
= do userArrName <- getRealName (A.Name undefined undefined arrName)
arrType <- typeOfName (A.Name undefined undefined arrName)
@@ -73,7 +100,7 @@ checkArrayUsage tree = (mapM_ checkPar $ listify (const True) tree) >> return tr
((varMapping,vm):_) -> do sol <- formatSolution varMapping (getCounterEqs vm)
dieP m $ "Overlapping indexes of array \"" ++ userArrName ++ "\" when: " ++ sol
- formatSolution :: VarMap -> Map.Map CoeffIndex Integer -> PassM String
+ formatSolution :: VarMap -> Map.Map CoeffIndex Integer -> m String
formatSolution varToIndex indexToConst = do names <- mapM valOfVar $ Map.assocs varToIndex
return $ concat $ intersperse " , " $ catMaybes names
where
@@ -83,10 +110,10 @@ checkArrayUsage tree = (mapM_ checkPar $ listify (const True) tree) >> return tr
return $ Just $ varExp' ++ " = " ++ show val
-- TODO this is surely defined elsewhere already?
- getRealName :: A.Name -> PassM String
+ getRealName :: A.Name -> m String
getRealName n = lookupName n >>* A.ndOrigName
- showFlattenedExp :: FlattenedExp -> PassM String
+ showFlattenedExp :: FlattenedExp -> m String
showFlattenedExp (Const n) = return $ show n
showFlattenedExp (Scale n ((A.Variable _ vn),vi))
= do vn' <- getRealName vn >>* (\s -> if vi == 0 then s else s ++ replicate vi '\'' )
@@ -105,7 +132,7 @@ checkArrayUsage tree = (mapM_ checkPar $ listify (const True) tree) >> return tr
bottom' <- showFlattenedExpSet bottom
return $ "(" ++ top' ++ " / " ++ bottom' ++ ")"
- showFlattenedExpSet :: Set.Set FlattenedExp -> PassM String
+ showFlattenedExpSet :: Set.Set FlattenedExp -> m String
showFlattenedExpSet s = liftM concat $ sequence $ intersperse (return " + ") $ map showFlattenedExp $ Set.toList s
-- | A type for inside makeEquations:
@@ -148,10 +175,12 @@ onlyConst _ = Nothing
-- Each item in the left branch can be paired with each other, and each item in the left branch can
-- be paired with all other items.
data ArrayAccess =
- Single (EqualityConstraintEquation,EqualityProblem,InequalityProblem)
- | Group [(EqualityConstraintEquation,EqualityProblem,InequalityProblem)]
+ Single (ArrayAccessType, (EqualityConstraintEquation, EqualityProblem, InequalityProblem))
+ | Group [(ArrayAccessType, (EqualityConstraintEquation, EqualityProblem, InequalityProblem))]
| Replicated [ArrayAccess] [ArrayAccess]
+data ArrayAccessType = AAWrite | AARead
+
makeExpSet :: [FlattenedExp] -> Either String (Set.Set FlattenedExp)
makeExpSet = foldM makeExpSet' Set.empty
where
@@ -185,8 +214,8 @@ makeExpSet = foldM makeExpSet' Set.empty
type VarMap = Map.Map FlattenedExp Int
--- | Given a list of (replicated variable, start, count), a list of parallel array accesses, the length of the array,
--- returns the problems
+-- | Given a list of (replicated variable, start, count), a list of (written,read) parallel array accesses,
+-- the length of the array, returns the problems.
--
-- The general strategy is as follows.
-- For every array index (here termed an "access"), we transform it into
@@ -205,25 +234,34 @@ type VarMap = Map.Map FlattenedExp Int
--
-- The remainder of the work (correctly pairing equations) is done by
-- squareAndPair.
-makeReplicatedEquations :: [(A.Variable, A.Expression, A.Expression)] -> [A.Expression] -> A.Expression ->
+makeReplicatedEquations :: [(A.Variable, A.Expression, A.Expression)] -> ([A.Expression],[A.Expression]) -> A.Expression ->
Either String [(VarMap, (EqualityProblem, InequalityProblem))]
makeReplicatedEquations repVars accesses bound
- = do flattenedAccesses <- mapM flatten accesses
- let flattenedAccessesMirror = concatMap (\(v,_,_) -> map (setIndexVar v 1) flattenedAccesses) repVars
+ = do flattenedAccesses <- applyPairM (mapM flatten) accesses
+ let flattenedAccessesMirror = applyPair concat $ unzip $ map (\(v,_,_) -> applyPair (map (setIndexVar v 1)) flattenedAccesses) repVars
bound' <- flatten bound
((v,h,repVars',repVarIndexes),s) <- (flip runStateT) Map.empty $
do repVars' <- mapM (\(v,s,c) ->
- do s' <- lift (flatten s) >>= makeEquation >>= getSingleAccessItem "Modulo or Divide not allowed in replication start"
- c' <- lift (flatten c) >>= makeEquation >>= getSingleAccessItem "Modulo or Divide not allowed in replication count"
+ do s' <- lift (flatten s) >>= makeEquation (error "Type is irrelevant for replication count")
+ >>= getSingleAccessItem "Modulo or Divide not allowed in replication start"
+ c' <- lift (flatten c) >>= makeEquation (error "Type is irrelevant for replication count")
+ >>= getSingleAccessItem "Modulo or Divide not allowed in replication count"
return (v,s',c')) repVars
- accesses' <- mapM (makeEquationWithPossibleRepBounds repVars' <.< makeEquation) flattenedAccesses
- accesses'' <- mapM (makeEquationWithPossibleRepBounds repVars' <.< makeEquation) flattenedAccessesMirror
- high <- makeEquation bound' >>= getSingleAccessItem "Multiple possible upper bounds not supported"
+ accesses' <- mapM (makeEquationWithPossibleRepBounds repVars') =<< makeEquationsWR flattenedAccesses
+ accesses'' <- mapM (makeEquationWithPossibleRepBounds repVars') =<< makeEquationsWR flattenedAccessesMirror
+ high <- makeEquation (error "Type is irrelevant for uppper bound") bound'
+ >>= getSingleAccessItem "Multiple possible upper bounds not supported"
repVarIndexes <- mapM (\(v,_,_) -> seqPair (varIndex (Scale 1 (v,0)), varIndex (Scale 1 (v,1)))) repVars
return (Replicated accesses' accesses'',high, repVars',repVarIndexes)
return $ squareAndPair repVarIndexes s [v] (amap (const 0) h, addConstant (-1) h)
where
+ makeEquationsWR :: ([[FlattenedExp]],[[FlattenedExp]]) -> StateT (VarMap) (Either String) [ArrayAccess]
+ makeEquationsWR (w,r) = do w' <- mapM (makeEquation AAWrite) w
+ r' <- mapM (makeEquation AARead) r
+ return (w' ++ r')
+
+
setIndexVar :: A.Variable -> Int -> [FlattenedExp] -> [FlattenedExp]
setIndexVar tv ti es = case mapAccumL (setIndexVar' tv ti) False es of
(_, es') -> es'
@@ -246,12 +284,12 @@ makeReplicatedEquations repVars accesses bound
addPossibleRepBound' :: ArrayAccess ->
(A.Variable, Int, EqualityConstraintEquation, EqualityConstraintEquation) ->
StateT (VarMap) (Either String) ArrayAccess
- addPossibleRepBound' (Group accesses) v = mapM (flip addPossibleRepBound v) accesses >>* Group
+ addPossibleRepBound' (Group accesses) v = mapM (seqPair . transformPair return (flip addPossibleRepBound v)) accesses >>* Group
addPossibleRepBound' (Replicated acc0 acc1) v
= do acc0' <- mapM (flip addPossibleRepBound' v) acc0
acc1' <- mapM (flip addPossibleRepBound' v) acc1
return $ Replicated acc0' acc1'
- addPossibleRepBound' (Single acc) v = addPossibleRepBound acc v >>* Single
+ addPossibleRepBound' (Single (t,acc)) v = addPossibleRepBound acc v >>* (\x -> Single (t,x))
addPossibleRepBound :: (EqualityConstraintEquation, EqualityProblem, InequalityProblem) ->
(A.Variable, Int, EqualityConstraintEquation, EqualityConstraintEquation) ->
@@ -289,7 +327,7 @@ flatten (A.Dyadic m op lhs rhs) | op == A.Add = combine' (flatten lhs) (flatte
| otherwise = throwError ("Unhandleable operator found in expression: " ++ show op)
where
-- liftM2L :: (Ord a, Ord b, Monad m) => (Set.Set a -> Set.Set b -> c) -> m [a] -> m [b] -> m [c]
- liftM2L f x y = liftM (:[]) $ liftM2 f (x >>= makeExpSet) (y >>= makeExpSet)
+ liftM2L f x y = liftM singleton $ liftM2 f (x >>= makeExpSet) (y >>= makeExpSet)
--TODO we need to handle lots more different expression types in future.
@@ -392,42 +430,48 @@ squareAndPair repVars s v lh
-- prime >= plain + 1 (prime - plain - 1 >= 0)
extraIneq = [simpleArray [(prime,1), (plain,-1), (0, -1)]]
+{-
getSingles :: String -> [ArrayAccess] -> Either String [(EqualityConstraintEquation, EqualityProblem, InequalityProblem)]
getSingles err = mapM getSingle
where
getSingle (Single acc) = return acc
getSingle _ = throwError err
+-}
getSingleAccessItem :: MonadTrans m => String -> ArrayAccess -> m (Either String) EqualityConstraintEquation
-getSingleAccessItem _ (Single (acc,_,_)) = lift $ return acc
+getSingleAccessItem _ (Single (_,(acc,_,_))) = lift $ return acc
getSingleAccessItem err _ = lift $ throwError err
+{-
getSingleAccess :: MonadTrans m => String -> ArrayAccess -> m (Either String) (EqualityConstraintEquation, EqualityProblem, InequalityProblem)
getSingleAccess _ (Single acc) = lift $ return acc
getSingleAccess err _ = lift $ throwError err
+-}
-- | Odd helper function for getting/asserting the first item of a triple from a singleton list inside a monad transformer (!)
getSingleItem :: MonadTrans m => String -> [(a,b,c)] -> m (Either String) a
getSingleItem _ [(item,_,_)] = lift $ return item
getSingleItem err _ = lift $ throwError err
--- | Given a list of 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
-- (unique, munged) variable name to variable-index in the equations.
-- TODO probably want to take this into the PassM monad at some point, to use the Meta in the error message
-- TODO allow "background knowledge" in the form of other equalities and inequalities
-makeEquations :: [A.Expression] -> A.Expression -> Either String [(VarMap, (EqualityProblem, InequalityProblem))]
-makeEquations es high = makeEquations' >>* uncurry3 (squareAndPair [])
+makeEquations :: ([A.Expression],[A.Expression]) -> A.Expression -> Either String [(VarMap, (EqualityProblem, InequalityProblem))]
+makeEquations (esW,esR) high = makeEquations' >>* uncurry3 (squareAndPair [])
where
-- | The body of makeEquations; returns the variable mapping, the list of (nx,ex) pairs and a pair
-- representing the upper and lower bounds of the array (inclusive).
makeEquations' :: Either String (VarMap, [ArrayAccess], (EqualityConstraintEquation, EqualityConstraintEquation))
makeEquations' = do ((v,h),s) <- (flip runStateT) Map.empty $
- do flattened <- lift (mapM flatten es)
- eqs <- mapM makeEquation flattened
- high' <- (lift $ flatten high) >>= makeEquation >>= getSingleAccessItem "Multiple possible upper bounds not supported"
- return (eqs,high')
+ do eqsW <- mapM (makeEquation AAWrite) =<< lift (mapM flatten esW)
+ eqsR <- mapM (makeEquation AARead) =<< lift (mapM flatten esR)
+ high' <- (lift $ flatten high) >>= makeEquation (error "Type irrelevant for upper bound")
+ >>= getSingleAccessItem "Multiple possible upper bounds not supported"
+ return (eqsW ++ eqsR,high')
return (s,v,(amap (const 0) h, addConstant (-1) h))
@@ -459,10 +503,10 @@ pairEqsAndBounds items bounds = (concatMap (uncurry pairEqs) . allPairs) items +
pairEqs :: ArrayAccess
-> ArrayAccess
-> [(EqualityProblem, InequalityProblem)]
- pairEqs (Single acc) (Single acc') = [pairEqs' acc acc']
- pairEqs (Single acc) (Group accs) = map (pairEqs' acc) accs
- pairEqs (Group accs) (Single acc) = map (pairEqs' acc) accs
- pairEqs (Group accs) (Group accs') = map (uncurry pairEqs') $ product2 (accs,accs')
+ pairEqs (Single acc) (Single acc') = maybeToList $ pairEqs' acc acc'
+ pairEqs (Single acc) (Group accs) = mapMaybe (pairEqs' acc) accs
+ pairEqs (Group accs) (Single acc) = mapMaybe (pairEqs' acc) accs
+ pairEqs (Group accs) (Group accs') = mapMaybe (uncurry pairEqs') $ product2 (accs,accs')
pairEqs (Replicated rA rB) acc
= concatMap (pairEqs acc) rA
pairEqs acc (Replicated rA rB)
@@ -473,10 +517,11 @@ pairEqsAndBounds items bounds = (concatMap (uncurry pairEqs) . allPairs) items +
pairRep (Replicated rA rB) = (concatMap (uncurry pairEqs) $ product2 (rA,rB)) ++ concatMap (uncurry pairEqs) (allPairs rA)
pairRep _ = []
- pairEqs' :: (EqualityConstraintEquation, EqualityProblem, InequalityProblem)
- -> (EqualityConstraintEquation, EqualityProblem, InequalityProblem)
- -> (EqualityProblem, InequalityProblem)
- pairEqs' (ex,eqX,ineqX) (ey,eqY,ineqY) = ([arrayZipWith' 0 (-) ex ey] ++ eqX ++ eqY, ineqX ++ ineqY ++ getIneqs bounds [ex,ey])
+ pairEqs' :: (ArrayAccessType,(EqualityConstraintEquation, EqualityProblem, InequalityProblem))
+ -> (ArrayAccessType,(EqualityConstraintEquation, EqualityProblem, InequalityProblem))
+ -> Maybe (EqualityProblem, InequalityProblem)
+ pairEqs' (AARead,_) (AARead,_) = Nothing
+ pairEqs' (_,(ex,eqX,ineqX)) (_,(ey,eqY,ineqY)) = Just ([arrayZipWith' 0 (-) ex ey] ++ eqX ++ eqY, ineqX ++ ineqY ++ getIneqs bounds [ex,ey])
-- | Given a (low,high) bound (typically: array dimensions), and a list of equations ex,
-- forms the possible inequalities:
@@ -494,14 +539,15 @@ getIneqs (low, high) = concatMap getLH
addEq = arrayZipWith' 0 (+)
-- | Given an expression, forms equations (and accompanying additional equation-sets) and returns it
-makeEquation :: [FlattenedExp] -> StateT (VarMap) (Either String) ArrayAccess
-makeEquation summedItems
+makeEquation :: ArrayAccessType -> [FlattenedExp] -> StateT VarMap (Either String) ArrayAccess
+makeEquation t summedItems
= do eqs <- process summedItems
let eqs' = map (transformTriple mapToArray (map mapToArray) (map mapToArray)) eqs
return $ case eqs' of
- [acc] -> Single acc
- _ -> Group eqs'
+ [acc] -> Single (t,acc)
+ _ -> Group $ zip (repeat t) eqs'
where
+ process :: [FlattenedExp] -> StateT VarMap (Either String) [(Map.Map Int Integer,[Map.Map Int Integer], [Map.Map Int Integer])]
process = foldM makeEquation' empty
makeEquation' :: [(Map.Map Int Integer,[Map.Map Int Integer], [Map.Map Int Integer])] -> FlattenedExp -> StateT (VarMap) (Either String) [(Map.Map Int Integer,[Map.Map Int Integer], [Map.Map Int Integer])]
diff --git a/transformations/ArrayUsageCheckTest.hs b/transformations/ArrayUsageCheckTest.hs
index 607208a..08fa9b6 100644
--- a/transformations/ArrayUsageCheckTest.hs
+++ b/transformations/ArrayUsageCheckTest.hs
@@ -361,13 +361,13 @@ testMakeEquations = TestList
test :: (Integer,[(VarMap,[HandyEq],[HandyIneq])],[A.Expression],A.Expression) -> Test
test (ind, problems, exprs, upperBound) =
TestCase $ assertEquivalentProblems ("testMakeEquations " ++ show ind)
- (map (transformPair id (uncurry makeConsistent)) $ map pairLatterTwo problems) =<< (checkRight $ makeEquations exprs upperBound)
+ (map (transformPair id (uncurry makeConsistent)) $ map pairLatterTwo problems) =<< (checkRight $ makeEquations (exprs,[]) upperBound)
testRep :: (Integer,[(VarMap,[HandyEq],[HandyIneq])],[(A.Variable, A.Expression, A.Expression)],[A.Expression],A.Expression) -> Test
testRep (ind, problems, reps, exprs, upperBound) =
TestCase $ assertEquivalentProblems ("testMakeEquations " ++ show ind)
(map (transformPair id (uncurry makeConsistent)) $ map pairLatterTwo problems)
- =<< (checkRight $ makeReplicatedEquations reps exprs upperBound)
+ =<< (checkRight $ makeReplicatedEquations reps (exprs,[]) upperBound)
pairLatterTwo (a,b,c) = (a,(b,c))
diff --git a/transformations/UsageCheck.hs b/transformations/UsageCheck.hs
new file mode 100644
index 0000000..1f93f12
--- /dev/null
+++ b/transformations/UsageCheck.hs
@@ -0,0 +1,54 @@
+{-
+Tock: a compiler for parallel languages
+Copyright (C) 2007 University of Kent
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see .
+-}
+
+module UsageCheck where
+
+import Data.Graph.Inductive
+import qualified Data.Set as Set
+
+import qualified AST as A
+import Errors
+import FlowGraph
+import Metadata
+
+
+newtype Var = Var A.Variable
+
+data Vars = Vars {
+ readVars :: Set.Set Var
+ ,writtenVars :: Set.Set Var
+ ,usedVars :: Set.Set Var -- for channels, barriers, etc
+}
+
+data Decl = ScopeIn String | ScopeOut String deriving (Show, Eq)
+
+data ParItems a
+ = ParItem a
+ | ParItems [ParItems a]
+ | RepParItem A.Replicator (ParItems a)
+
+-- | Given a function to check a list of graph labels, a flow graph
+-- and a starting node, returns a list of monadic actions (slightly
+-- more flexible than a monadic action giving a list) that will check
+-- all PAR items in the flow graph
+checkPar :: Monad m => ((Meta, ParItems a) -> m b) -> FlowGraph m a -> Node -> [m b]
+checkPar = undefined -- TODO
+--TODO is a start node actually necessary for checkPar?
+
+labelFunctions :: Die m => GraphLabelFuncs m (Maybe Decl, Vars)
+labelFunctions = undefined -- TODO