Changed the A.Structured type to be parameterised

This patch is actually an amalgam of multiple (already large) patches.  Those patches conflicted (parameterised Structured vs. changes to usage checking and FlowGraph) and encountered a nasty bug in darcs 1 involving exponential time (see http://wiki.darcs.net/DarcsWiki/ConflictsFAQ for more details).  Reasoning that half an hour (of 100% CPU use) was too long to apply patches, I opted to re-record the parameterised Structured changes as this new large patch.  Here are the commit messages originally used for the patches (which, as mentioned, were already large patches):

A gigantic patch switching all the non-test modules over to using parameterised A.Structured
Changed the FlowGraph module again to handle any sort of Structured you want to pass to it (mainly for testing)
A further gigantic patch changing all the tests to work with the new parameterised Structured
Fixed a nasty bug involving functions being named incorrectly inside transformInputCase
Added a hand-written instance of Data for Structured that allows us to use ext1M properly
Fixed a few warnings in the code
This commit is contained in:
Neil Brown 2008-02-05 19:40:27 +00:00
parent 6c4e7ee713
commit acd57d74de
33 changed files with 828 additions and 642 deletions

View File

@ -47,13 +47,13 @@ genHeader = [
-- | Here's the idea for easily building a compare function. Go through in ascending order. -- | Here's the idea for easily building a compare function. Go through in ascending order.
-- Match A vs A in detail. For A vs _ give LT, and for _ vs A give GT. Then repeat for B, C, etc -- Match A vs A in detail. For A vs _ give LT, and for _ vs A give GT. Then repeat for B, C, etc
-- But for the last item, do not give the LT and GT matches! -- But for the last item, do not give the LT and GT matches!
ordFor :: forall a. (Data a, Typeable a) => a -> [String] ordFor' :: forall a. (Data a, Typeable a) => String -> a -> [String]
ordFor x = process $ map processConstr $ dataTypeConstrs $ dataTypeOf x ordFor' typeName x = process $ map processConstr $ dataTypeConstrs $ dataTypeOf x
where where
process :: [(String, String, String, [String])] -> [String] process :: [(String, String, String, [String])] -> [String]
process [] = [] process [] = []
process items = process items =
["instance Ord " ++ (dataTypeName $ dataTypeOf x) ++ " where"] ["instance Ord " ++ typeName ++ " where"]
++ concat [ [ " compare (" ++ name ++ headL ++ ") (" ++ name ++ headR ++ ") = " ++ ++ concat [ [ " compare (" ++ name ++ headL ++ ") (" ++ name ++ headR ++ ") = " ++
--Shortcut: --Shortcut:
if null comparisons then "EQ" else if null comparisons then "EQ" else
@ -100,13 +100,21 @@ items = concat
,ordFor (u :: A.Replicator) ,ordFor (u :: A.Replicator)
,ordFor (u :: A.Specification) ,ordFor (u :: A.Specification)
,ordFor (u :: A.SpecType) ,ordFor (u :: A.SpecType)
,ordFor (u :: A.Structured) --TODO define a new function for doing a parameterised Ord
,ordFor' "(AST.Structured AST.Process)" (u :: A.Structured A.Process)
,ordFor' "(AST.Structured AST.Choice)" (u :: A.Structured A.Choice)
,ordFor' "(AST.Structured AST.Option)" (u :: A.Structured A.Option)
,ordFor' "(AST.Structured AST.Alternative)" (u :: A.Structured A.Alternative)
,ordFor' "(AST.Structured AST.Variant)" (u :: A.Structured A.Variant)
,ordFor' "(AST.Structured AST.ExpressionList)" (u :: A.Structured A.ExpressionList)
,ordFor (u :: A.Subscript) ,ordFor (u :: A.Subscript)
,ordFor (u :: A.Type) ,ordFor (u :: A.Type)
,ordFor (u :: A.Variable) ,ordFor (u :: A.Variable)
,ordFor (u :: A.Variant) ,ordFor (u :: A.Variant)
] ]
where where
ordFor x = ordFor' (dataTypeName $ dataTypeOf x) x
u = undefined u = undefined
joinLines :: [String] -> String joinLines :: [String] -> String

View File

@ -23,6 +23,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module GenTagAST where module GenTagAST where
import Data.Generics import Data.Generics
import Data.List (intersperse)
import qualified AST as A import qualified AST as A
@ -36,7 +37,9 @@ genHeader = [
,"module TagAST where" ,"module TagAST where"
,"import Data.Generics" ,"import Data.Generics"
,"" ,""
,"import qualified AST"
,"import qualified AST as A" ,"import qualified AST as A"
,"import qualified Metadata"
,"import Pattern" ,"import Pattern"
,"import TreeUtils" ,"import TreeUtils"
-- Could probably auto-generate these, too: -- Could probably auto-generate these, too:
@ -47,6 +50,13 @@ genHeader = [
,"type F4 = (Data a0, Data a1, Data a2, Data a3) => a0 -> a1 -> a2 -> a3 -> Pattern" ,"type F4 = (Data a0, Data a1, Data a2, Data a3) => a0 -> a1 -> a2 -> a3 -> Pattern"
,"type F5 = (Data a0, Data a1, Data a2, Data a3, Data a4) => a0 -> a1 -> a2 -> a3 -> a4 -> Pattern" ,"type F5 = (Data a0, Data a1, Data a2, Data a3, Data a4) => a0 -> a1 -> a2 -> a3 -> a4 -> Pattern"
,"type F6 = (Data a0, Data a1, Data a2, Data a3, Data a4, Data a5) => a0 -> a1 -> a2 -> a3 -> a4 -> a5 -> Pattern" ,"type F6 = (Data a0, Data a1, Data a2, Data a3, Data a4, Data a5) => a0 -> a1 -> a2 -> a3 -> a4 -> a5 -> Pattern"
,"type F0' a = Pattern"
,"type F1' a0 = a0 -> Pattern"
,"type F2' a1 = (Data a0) => a0 -> a1 -> Pattern"
,"type F3' a2 = (Data a0, Data a1) => a0 -> a1 -> a2 -> Pattern"
,"type F4' a3 = (Data a0, Data a1, Data a2) => a0 -> a1 -> a2 -> a3 -> Pattern"
,"type F5' a4 = (Data a0, Data a1, Data a2, Data a3) => a0 -> a1 -> a2 -> a3 -> a4 -> Pattern"
,"type F6' a5 = (Data a0, Data a1, Data a2, Data a3, Data a4) => a0 -> a1 -> a2 -> a3 -> a4 -> a5 -> Pattern"
,"" ,""
] ]
@ -60,6 +70,25 @@ genItem (num, name)
n = show num n = show num
mname = "m" ++ name mname = "m" ++ name
genItem' :: String -> String -> (Int, String, [String]) -> [String]
genItem' suffix typeName (num, name, paramTypes)
= [mname ++ "' :: F" ++ n ++ typeSuffix
,mname ++ "' = tag" ++ n ++ " (A." ++ name ++ " :: " ++ params ++ ")"
,mname ++ " :: F" ++ show (num - 1) ++ typeSuffix
,mname ++ " = " ++ mname ++ "' DontCare"]
where
-- typeSuffix = "' (" ++ typeName ++ ")"
typeSuffix = ""
params = concat $ intersperse " -> " $
[case p of
"AST.Structured" -> typeName
"[AST.Structured]" -> "[" ++ typeName ++ "]"
_ -> p | p <- paramTypes] ++ [typeName]
n = show num
mname = "m" ++ name ++ suffix
consFor :: forall a. Data a => a -> [(Int, String)] consFor :: forall a. Data a => a -> [(Int, String)]
consFor x = map consFor' (dataTypeConstrs $ dataTypeOf x) consFor x = map consFor' (dataTypeConstrs $ dataTypeOf x)
where where
@ -68,6 +97,26 @@ consFor x = map consFor' (dataTypeConstrs $ dataTypeOf x)
consFor' :: Constr -> (Int, String) consFor' :: Constr -> (Int, String)
consFor' con = (length (gmapQ (const undefined) (fromConstr con :: a)), showConstr con) consFor' con = (length (gmapQ (const undefined) (fromConstr con :: a)), showConstr con)
consParamsFor :: forall a. Data a => a -> [(Int, String, [String])]
consParamsFor x = map consParamsFor' (dataTypeConstrs $ dataTypeOf x)
where
-- The way I work out how many arguments a constructor takes is crazy, but
-- I can't see a better way given the Data.Generics API
consParamsFor' :: Constr -> (Int, String, [String])
consParamsFor' con = (length cons, showConstr con, cons)
where
cons :: [String]
cons = gmapQ showDataType (fromConstr con :: a)
-- Hack to handle various types:
showDataType :: Data b => b -> String
showDataType y = case n of
"Prelude.[]" -> "[" ++ (dataTypeName $ dataTypeOf x) ++ "]"
"Prelude.()" -> "()"
_ -> n
where
n = dataTypeName $ dataTypeOf y
items :: [(Int, String)] items :: [(Int, String)]
items = concat items = concat
[consFor (u :: A.Actual) [consFor (u :: A.Actual)
@ -87,7 +136,6 @@ items = concat
,consFor (u :: A.Replicator) ,consFor (u :: A.Replicator)
,consFor (u :: A.Specification) ,consFor (u :: A.Specification)
,consFor (u :: A.SpecType) ,consFor (u :: A.SpecType)
,consFor (u :: A.Structured)
,consFor (u :: A.Subscript) ,consFor (u :: A.Subscript)
,consFor (u :: A.Type) ,consFor (u :: A.Type)
,consFor (u :: A.Variable) ,consFor (u :: A.Variable)
@ -96,6 +144,18 @@ items = concat
where where
u = undefined u = undefined
struct :: [String]
struct = concat
[concatMap (genItem' "P" "A.Structured A.Process") $ consParamsFor (undefined :: A.Structured A.Process)
,concatMap (genItem' "O" "A.Structured A.Option") $ consParamsFor (undefined :: A.Structured A.Option)
,concatMap (genItem' "C" "A.Structured A.Choice") $ consParamsFor (undefined :: A.Structured A.Choice)
,concatMap (genItem' "V" "A.Structured A.Variant") $ consParamsFor (undefined :: A.Structured A.Variant)
,concatMap (genItem' "A" "A.Structured A.Alternative") $ consParamsFor (undefined :: A.Structured A.Alternative)
,concatMap (genItem' "EL" "A.Structured A.ExpressionList") $ consParamsFor (undefined :: A.Structured A.ExpressionList)
,concatMap (genItem' "AST" "A.Structured ()") $ consParamsFor (undefined :: A.Structured ())
]
filterInvalid :: [(Int, a)] -> [(Int, a)] filterInvalid :: [(Int, a)] -> [(Int, a)]
filterInvalid = filter (\(n,_) -> n > 0) filterInvalid = filter (\(n,_) -> n > 0)
@ -103,4 +163,4 @@ joinLines :: [String] -> String
joinLines xs = concat [x ++ "\n" | x <- xs] joinLines xs = concat [x ++ "\n" | x <- xs]
main :: IO () main :: IO ()
main = putStr $ joinLines $ genHeader ++ concatMap genItem (filterInvalid items) main = putStr $ joinLines $ genHeader ++ concatMap genItem (filterInvalid items) ++ struct

View File

@ -261,10 +261,13 @@ compile mode fn outHandle
do procs <- findAllProcesses do procs <- findAllProcesses
let fs :: Data t => t -> PassM String let fs :: Data t => t -> PassM String
fs = ((liftM $ (take 20) . (filter ((/=) '\"'))) . pshowCode) fs = ((liftM $ (take 20) . (filter ((/=) '\"'))) . pshowCode)
-- TODO fix this mode
{-
let labelFuncs = mkLabelFuncsGeneric fs let labelFuncs = mkLabelFuncsGeneric fs
graphs <- mapM graphs <- mapM
((liftM $ either (const Nothing) Just) . (buildFlowGraph labelFuncs) ) ((liftM $ either (const Nothing) Just) . (buildFlowGraph labelFuncs) )
(map (A.OnlyP emptyMeta) (snd $ unzip $ procs)) (map (A.Only emptyMeta) (snd $ unzip $ procs))
-- We need this line to enforce the type of the mAlter monad (Identity) -- We need this line to enforce the type of the mAlter monad (Identity)
-- since it is never used. Then we used graphsTyped (rather than graphs) -- since it is never used. Then we used graphsTyped (rather than graphs)
@ -273,7 +276,8 @@ compile mode fn outHandle
let (graphsTyped :: [Maybe (FlowGraph Identity String)]) = map (transformMaybe fst) graphs let (graphsTyped :: [Maybe (FlowGraph Identity String)]) = map (transformMaybe fst) graphs
--TODO output each process to a separate file, rather than just taking the first: --TODO output each process to a separate file, rather than just taking the first:
return $ head $ map makeFlowGraphInstr (catMaybes graphsTyped) return $ head $ map makeFlowGraphInstr (catMaybes graphsTyped)
-}
return ""
ModeCompile -> ModeCompile ->
do progress "Passes:" do progress "Passes:"

View File

@ -35,12 +35,12 @@ identifyParProcs = everywhereM (mkM doProcess)
doProcess p@(A.Par _ _ s) = findProcs s >> return p doProcess p@(A.Par _ _ s) = findProcs s >> return p
doProcess p = return p doProcess p = return p
findProcs :: A.Structured -> PassM () findProcs :: A.Structured A.Process -> PassM ()
findProcs (A.Rep _ _ s) = findProcs s findProcs (A.Rep _ _ s) = findProcs s
findProcs (A.Spec _ _ s) = findProcs s findProcs (A.Spec _ _ s) = findProcs s
findProcs (A.ProcThen _ _ s) = findProcs s findProcs (A.ProcThen _ _ s) = findProcs s
findProcs (A.Several _ ss) = sequence_ $ map findProcs ss findProcs (A.Several _ ss) = sequence_ $ map findProcs ss
findProcs (A.OnlyP _ (A.ProcCall _ n _)) findProcs (A.Only _ (A.ProcCall _ n _))
= modify (\cs -> cs { csParProcs = Set.insert n (csParProcs cs) }) = modify (\cs -> cs { csParProcs = Set.insert n (csParProcs cs) })
transformWaitFor :: Data t => t -> PassM t transformWaitFor :: Data t => t -> PassM t
@ -51,20 +51,20 @@ transformWaitFor = everywhereM (mkM doAlt)
= do (a',(specs,code)) <- runStateT (everywhereM (mkM doWaitFor) a) ([],[]) = do (a',(specs,code)) <- runStateT (everywhereM (mkM doWaitFor) a) ([],[])
if (null specs && null code) if (null specs && null code)
then return a then return a
else return $ A.Seq m $ foldr addSpec (A.Several m (code ++ [A.OnlyP m a'])) specs else return $ A.Seq m $ foldr addSpec (A.Several m (code ++ [A.Only m a'])) specs
doAlt p = return p doAlt p = return p
addSpec :: (A.Structured -> A.Structured) -> A.Structured -> A.Structured addSpec :: Data a => (A.Structured a -> A.Structured a) -> A.Structured a -> A.Structured a
addSpec spec inner = spec inner addSpec spec inner = spec inner
doWaitFor :: A.Alternative -> StateT ([A.Structured -> A.Structured], [A.Structured]) PassM A.Alternative doWaitFor :: A.Alternative -> StateT ([A.Structured A.Process -> A.Structured A.Process], [A.Structured A.Process]) PassM A.Alternative
doWaitFor a@(A.AlternativeWait m A.WaitFor e p) doWaitFor a@(A.AlternativeWait m A.WaitFor e p)
= do (specs, init) <- get = do (specs, init) <- get
id <- lift $ makeNonce "waitFor" id <- lift $ makeNonce "waitFor"
let n = (A.Name m A.VariableName id) let n = (A.Name m A.VariableName id)
let var = A.Variable m n let var = A.Variable m n
put (specs ++ [A.Spec m (A.Specification m n (A.Declaration m A.Time Nothing))], put (specs ++ [A.Spec m (A.Specification m n (A.Declaration m A.Time Nothing))],
init ++ [A.OnlyP m $ A.GetTime m var, A.OnlyP m $ A.Assign m [var] $ A.ExpressionList m [A.Dyadic m A.Plus (A.ExprVariable m var) e]]) init ++ [A.Only m $ A.GetTime m var, A.Only m $ A.Assign m [var] $ A.ExpressionList m [A.Dyadic m A.Plus (A.ExprVariable m var) e]])
return $ A.AlternativeWait m A.WaitUntil (A.ExprVariable m var) p return $ A.AlternativeWait m A.WaitUntil (A.ExprVariable m var) p
doWaitFor a = return a doWaitFor a = return a

View File

@ -27,6 +27,7 @@ import Test.HUnit hiding (State)
import qualified AST as A import qualified AST as A
import BackendPasses import BackendPasses
import Pattern import Pattern
import TagAST
import TestUtils import TestUtils
import TreeUtils import TreeUtils
@ -34,19 +35,19 @@ import TreeUtils
testTransformWaitFor0 :: Test testTransformWaitFor0 :: Test
testTransformWaitFor0 = TestCase $ testPass "testTransformWaitFor0" orig (transformWaitFor orig) (return ()) testTransformWaitFor0 = TestCase $ testPass "testTransformWaitFor0" orig (transformWaitFor orig) (return ())
where where
orig = A.Alt m True $ A.OnlyA m $ A.AlternativeWait m A.WaitUntil (exprVariable "t") (A.Skip m) orig = A.Alt m True $ A.Only m $ A.AlternativeWait m A.WaitUntil (exprVariable "t") (A.Skip m)
-- | Test pulling out a single WaitFor: -- | Test pulling out a single WaitFor:
testTransformWaitFor1 :: Test testTransformWaitFor1 :: Test
testTransformWaitFor1 = TestCase $ testPass "testTransformWaitFor1" exp (transformWaitFor orig) (return ()) testTransformWaitFor1 = TestCase $ testPass "testTransformWaitFor1" exp (transformWaitFor orig) (return ())
where where
orig = A.Alt m True $ A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m) orig = A.Alt m True $ A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m)
exp = tag2 A.Seq DontCare $ tag3 A.Spec DontCare (tag3 A.Specification DontCare varName $ A.Declaration m A.Time Nothing) $ exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName $ A.Declaration m A.Time Nothing) $
tag2 A.Several DontCare mSeveralP
[ [
tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var mOnlyP $ tag2 A.GetTime DontCare var
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar (exprVariablePattern "t")] ,mOnlyP $ tag3 A.Assign DontCare [var] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar (exprVariablePattern "t")]
,tag2 A.OnlyP DontCare $ tag3 A.Alt DontCare True $ tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar (A.Skip m) ,mOnlyP $ tag3 A.Alt DontCare True $ mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar (A.Skip m)
] ]
varName = (tag3 A.Name DontCare A.VariableName $ Named "nowt" DontCare) varName = (tag3 A.Name DontCare A.VariableName $ Named "nowt" DontCare)
var = tag2 A.Variable DontCare varName var = tag2 A.Variable DontCare varName
@ -56,19 +57,19 @@ testTransformWaitFor1 = TestCase $ testPass "testTransformWaitFor1" exp (transfo
testTransformWaitFor2 :: Test testTransformWaitFor2 :: Test
testTransformWaitFor2 = TestCase $ testPass "testTransformWaitFor2" exp (transformWaitFor orig) (return ()) testTransformWaitFor2 = TestCase $ testPass "testTransformWaitFor2" exp (transformWaitFor orig) (return ())
where where
orig = A.Alt m True $ A.Several m [A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t0") (A.Skip m), orig = A.Alt m True $ A.Several m [A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t0") (A.Skip m),
A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t1") (A.Skip m)] A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t1") (A.Skip m)]
exp = tag2 A.Seq DontCare $ tag3 A.Spec DontCare (tag3 A.Specification DontCare varName0 $ A.Declaration m A.Time Nothing) $ exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName0 $ A.Declaration m A.Time Nothing) $
tag3 A.Spec DontCare (tag3 A.Specification DontCare varName1 $ A.Declaration m A.Time Nothing) $ mSpecP (tag3 A.Specification DontCare varName1 $ A.Declaration m A.Time Nothing) $
tag2 A.Several DontCare mSeveralP
[ [
tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var0 mOnlyP $ tag2 A.GetTime DontCare var0
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var0] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar0 (exprVariablePattern "t0")] ,mOnlyP $ tag3 A.Assign DontCare [var0] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar0 (exprVariablePattern "t0")]
,tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var1 ,mOnlyP $ tag2 A.GetTime DontCare var1
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var1] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar1 (exprVariablePattern "t1")] ,mOnlyP $ tag3 A.Assign DontCare [var1] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar1 (exprVariablePattern "t1")]
,tag2 A.OnlyP DontCare $ tag3 A.Alt DontCare True $ tag2 A.Several DontCare ,mOnlyP $ tag3 A.Alt DontCare True $ mSeveralA
[tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar0 (A.Skip m) [mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar0 (A.Skip m)
,tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar1 (A.Skip m)] ,mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar1 (A.Skip m)]
] ]
varName0 = (tag3 A.Name DontCare A.VariableName $ Named "nowt0" DontCare) varName0 = (tag3 A.Name DontCare A.VariableName $ Named "nowt0" DontCare)
var0 = tag2 A.Variable DontCare varName0 var0 = tag2 A.Variable DontCare varName0
@ -81,14 +82,14 @@ testTransformWaitFor2 = TestCase $ testPass "testTransformWaitFor2" exp (transfo
testTransformWaitFor3 :: Test testTransformWaitFor3 :: Test
testTransformWaitFor3 = TestCase $ testPass "testTransformWaitFor3" exp (transformWaitFor orig) (return ()) testTransformWaitFor3 = TestCase $ testPass "testTransformWaitFor3" exp (transformWaitFor orig) (return ())
where where
orig = A.Alt m True $ A.OnlyA m $ A.AlternativeWait m A.WaitFor (A.Dyadic m A.Plus (exprVariable "t0") (exprVariable "t1")) (A.Skip m) orig = A.Alt m True $ A.Only m $ A.AlternativeWait m A.WaitFor (A.Dyadic m A.Plus (exprVariable "t0") (exprVariable "t1")) (A.Skip m)
exp = tag2 A.Seq DontCare $ tag3 A.Spec DontCare (tag3 A.Specification DontCare varName $ A.Declaration m A.Time Nothing) $ exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName $ A.Declaration m A.Time Nothing) $
tag2 A.Several DontCare mSeveralP
[ [
tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var mOnlyP $ tag2 A.GetTime DontCare var
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar ,mOnlyP $ tag3 A.Assign DontCare [var] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar
(A.Dyadic m A.Plus (exprVariable "t0") (exprVariable "t1"))] (A.Dyadic m A.Plus (exprVariable "t0") (exprVariable "t1"))]
,tag2 A.OnlyP DontCare $ tag3 A.Alt DontCare True $ tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar (A.Skip m) ,mOnlyP $ tag3 A.Alt DontCare True $ mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar (A.Skip m)
] ]
varName = (tag3 A.Name DontCare A.VariableName $ Named "nowt" DontCare) varName = (tag3 A.Name DontCare A.VariableName $ Named "nowt" DontCare)
var = tag2 A.Variable DontCare varName var = tag2 A.Variable DontCare varName
@ -98,14 +99,14 @@ testTransformWaitFor3 = TestCase $ testPass "testTransformWaitFor3" exp (transfo
testTransformWaitFor4 :: Test testTransformWaitFor4 :: Test
testTransformWaitFor4 = TestCase $ testPass "testTransformWaitFor4" exp (transformWaitFor orig) (return ()) testTransformWaitFor4 = TestCase $ testPass "testTransformWaitFor4" exp (transformWaitFor orig) (return ())
where where
orig = A.Alt m True $ A.Several m [A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m)] orig = A.Alt m True $ A.Several m [A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m)]
exp = tag2 A.Seq DontCare $ tag3 A.Spec DontCare (tag3 A.Specification DontCare varName $ A.Declaration m A.Time Nothing) $ exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName $ A.Declaration m A.Time Nothing) $
tag2 A.Several DontCare mSeveralP
[ [
tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var mOnlyP $ tag2 A.GetTime DontCare var
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar (exprVariablePattern "t")] ,mOnlyP $ tag3 A.Assign DontCare [var] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar (exprVariablePattern "t")]
,tag2 A.OnlyP DontCare $ tag3 A.Alt DontCare True $ tag2 A.Several DontCare ,mOnlyP $ tag3 A.Alt DontCare True $ mSeveralA
[tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar (A.Skip m)] [mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar (A.Skip m)]
] ]
varName = (tag3 A.Name DontCare A.VariableName $ Named "nowt" DontCare) varName = (tag3 A.Name DontCare A.VariableName $ Named "nowt" DontCare)
var = tag2 A.Variable DontCare varName var = tag2 A.Variable DontCare varName
@ -115,19 +116,19 @@ testTransformWaitFor4 = TestCase $ testPass "testTransformWaitFor4" exp (transfo
testTransformWaitFor5 :: Test testTransformWaitFor5 :: Test
testTransformWaitFor5 = TestCase $ testPass "testTransformWaitFor5" exp (transformWaitFor orig) (return ()) testTransformWaitFor5 = TestCase $ testPass "testTransformWaitFor5" exp (transformWaitFor orig) (return ())
where where
orig = A.Alt m True $ A.Several m [A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m), orig = A.Alt m True $ A.Several m [A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m),
A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m)] A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t") (A.Skip m)]
exp = tag2 A.Seq DontCare $ tag3 A.Spec DontCare (tag3 A.Specification DontCare varName0 $ A.Declaration m A.Time Nothing) $ exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName0 $ A.Declaration m A.Time Nothing) $
tag3 A.Spec DontCare (tag3 A.Specification DontCare varName1 $ A.Declaration m A.Time Nothing) $ mSpecP (tag3 A.Specification DontCare varName1 $ A.Declaration m A.Time Nothing) $
tag2 A.Several DontCare mSeveralP
[ [
tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var0 mOnlyP $ tag2 A.GetTime DontCare var0
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var0] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar0 (exprVariablePattern "t")] ,mOnlyP $ tag3 A.Assign DontCare [var0] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar0 (exprVariablePattern "t")]
,tag2 A.OnlyP DontCare $ tag2 A.GetTime DontCare var1 ,mOnlyP $ tag2 A.GetTime DontCare var1
,tag2 A.OnlyP DontCare $ tag3 A.Assign DontCare [var1] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar1 (exprVariablePattern "t")] ,mOnlyP $ tag3 A.Assign DontCare [var1] $ tag2 A.ExpressionList DontCare [tag4 A.Dyadic DontCare A.Plus evar1 (exprVariablePattern "t")]
,tag2 A.OnlyP DontCare $ tag3 A.Alt DontCare True $ tag2 A.Several DontCare ,mOnlyP $ tag3 A.Alt DontCare True $ mSeveralA
[tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar0 (A.Skip m) [mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar0 (A.Skip m)
,tag2 A.OnlyA DontCare $ tag4 A.AlternativeWait DontCare A.WaitUntil evar1 (A.Skip m)] ,mOnlyA $ tag4 A.AlternativeWait DontCare A.WaitUntil evar1 (A.Skip m)]
] ]
varName0 = (tag3 A.Name DontCare A.VariableName $ Named "nowt0" DontCare) varName0 = (tag3 A.Name DontCare A.VariableName $ Named "nowt0" DontCare)
var0 = tag2 A.Variable DontCare varName0 var0 = tag2 A.Variable DontCare varName0

View File

@ -74,7 +74,7 @@ data GenOps = GenOps {
-- | Generates the list of actual parameters to a function\/proc. -- | Generates the list of actual parameters to a function\/proc.
genActuals :: GenOps -> [A.Actual] -> CGen (), genActuals :: GenOps -> [A.Actual] -> CGen (),
genAllocMobile :: GenOps -> Meta -> A.Type -> Maybe A.Expression -> CGen(), genAllocMobile :: GenOps -> Meta -> A.Type -> Maybe A.Expression -> CGen(),
genAlt :: GenOps -> Bool -> A.Structured -> CGen (), genAlt :: GenOps -> Bool -> A.Structured A.Alternative -> CGen (),
-- | Generates the given array element expressions as a flattened (one-dimensional) list of literals -- | Generates the given array element expressions as a flattened (one-dimensional) list of literals
genArrayLiteralElems :: GenOps -> [A.ArrayElem] -> CGen (), genArrayLiteralElems :: GenOps -> [A.ArrayElem] -> CGen (),
-- | Declares a constant array for the sizes (dimensions) of a C array. -- | Declares a constant array for the sizes (dimensions) of a C array.
@ -93,7 +93,7 @@ data GenOps = GenOps {
-- wheter or not one free dimension is allowed (True <=> allowed). -- wheter or not one free dimension is allowed (True <=> allowed).
genBytesIn :: GenOps -> Meta -> A.Type -> Either Bool A.Variable -> CGen (), genBytesIn :: GenOps -> Meta -> A.Type -> Either Bool A.Variable -> CGen (),
-- | Generates a case statement over the given expression with the structured as the body. -- | Generates a case statement over the given expression with the structured as the body.
genCase :: GenOps -> Meta -> A.Expression -> A.Structured -> CGen (), genCase :: GenOps -> Meta -> A.Expression -> A.Structured A.Option -> CGen (),
genCheckedConversion :: GenOps -> Meta -> A.Type -> A.Type -> CGen () -> CGen (), genCheckedConversion :: GenOps -> Meta -> A.Type -> A.Type -> CGen () -> CGen (),
genClearMobile :: GenOps -> Meta -> A.Variable -> CGen (), genClearMobile :: GenOps -> Meta -> A.Variable -> CGen (),
genConversion :: GenOps -> Meta -> A.ConversionMode -> A.Type -> A.Expression -> CGen (), genConversion :: GenOps -> Meta -> A.ConversionMode -> A.Type -> A.Expression -> CGen (),
@ -115,7 +115,7 @@ data GenOps = GenOps {
-- | Gets the current time into the given variable -- | Gets the current time into the given variable
genGetTime :: GenOps -> Meta -> A.Variable -> CGen (), genGetTime :: GenOps -> Meta -> A.Variable -> CGen (),
-- | Generates an IF statement (which can have replicators, specifications and such things inside it). -- | Generates an IF statement (which can have replicators, specifications and such things inside it).
genIf :: GenOps -> Meta -> A.Structured -> CGen (), genIf :: GenOps -> Meta -> A.Structured A.Choice -> CGen (),
genInput :: GenOps -> A.Variable -> A.InputMode -> CGen (), genInput :: GenOps -> A.Variable -> A.InputMode -> CGen (),
genInputItem :: GenOps -> A.Variable -> A.InputItem -> CGen (), genInputItem :: GenOps -> A.Variable -> A.InputItem -> CGen (),
genIntrinsicFunction :: GenOps -> Meta -> String -> [A.Expression] -> CGen (), genIntrinsicFunction :: GenOps -> Meta -> String -> [A.Expression] -> CGen (),
@ -133,7 +133,7 @@ data GenOps = GenOps {
genOutputItem :: GenOps -> A.Variable -> A.OutputItem -> CGen (), genOutputItem :: GenOps -> A.Variable -> A.OutputItem -> CGen (),
-- | Generates a loop that maps over every element in a (potentially multi-dimensional) array -- | Generates a loop that maps over every element in a (potentially multi-dimensional) array
genOverArray :: GenOps -> Meta -> A.Variable -> (SubscripterFunction -> Maybe (CGen ())) -> CGen (), genOverArray :: GenOps -> Meta -> A.Variable -> (SubscripterFunction -> Maybe (CGen ())) -> CGen (),
genPar :: GenOps -> A.ParMode -> A.Structured -> CGen (), genPar :: GenOps -> A.ParMode -> A.Structured A.Process -> CGen (),
genProcCall :: GenOps -> A.Name -> [A.Actual] -> CGen (), genProcCall :: GenOps -> A.Name -> [A.Actual] -> CGen (),
genProcess :: GenOps -> A.Process -> CGen (), genProcess :: GenOps -> A.Process -> CGen (),
-- | Generates a replicator loop, given the replicator and body -- | Generates a replicator loop, given the replicator and body
@ -141,7 +141,7 @@ data GenOps = GenOps {
-- | Generates the three bits of a for loop (e.g. "int i=0;i<10;i++" for the given replicator -- | Generates the three bits of a for loop (e.g. "int i=0;i<10;i++" for the given replicator
genReplicatorLoop :: GenOps -> A.Replicator -> CGen (), genReplicatorLoop :: GenOps -> A.Replicator -> CGen (),
genRetypeSizes :: GenOps -> Meta -> A.Type -> A.Name -> A.Type -> A.Variable -> CGen (), genRetypeSizes :: GenOps -> Meta -> A.Type -> A.Name -> A.Type -> A.Variable -> CGen (),
genSeq :: GenOps -> A.Structured -> CGen (), genSeq :: GenOps -> A.Structured A.Process -> CGen (),
genSimpleDyadic :: GenOps -> String -> A.Expression -> A.Expression -> CGen (), genSimpleDyadic :: GenOps -> String -> A.Expression -> A.Expression -> CGen (),
genSimpleMonadic :: GenOps -> String -> A.Expression -> CGen (), genSimpleMonadic :: GenOps -> String -> A.Expression -> CGen (),
genSizeSuffix :: GenOps -> String -> CGen (), genSizeSuffix :: GenOps -> String -> CGen (),
@ -150,11 +150,11 @@ data GenOps = GenOps {
genSpecMode :: GenOps -> A.SpecMode -> CGen (), genSpecMode :: GenOps -> A.SpecMode -> CGen (),
-- | Generates a STOP process that uses the given Meta tag and message as its printed message. -- | Generates a STOP process that uses the given Meta tag and message as its printed message.
genStop :: GenOps -> Meta -> String -> CGen (), genStop :: GenOps -> Meta -> String -> CGen (),
genStructured :: GenOps -> A.Structured -> (A.Structured -> CGen ()) -> CGen (), genStructured :: forall a. Data a => GenOps -> A.Structured a -> (Meta -> a -> CGen ()) -> CGen (),
genTLPChannel :: GenOps -> TLPChannel -> CGen (), genTLPChannel :: GenOps -> TLPChannel -> CGen (),
genTimerRead :: GenOps -> A.Variable -> A.Variable -> CGen (), genTimerRead :: GenOps -> A.Variable -> A.Variable -> CGen (),
genTimerWait :: GenOps -> A.Expression -> CGen (), genTimerWait :: GenOps -> A.Expression -> CGen (),
genTopLevel :: GenOps -> A.Structured -> CGen (), genTopLevel :: GenOps -> A.AST -> CGen (),
-- | Generates the type as it might be used in a cast expression -- | Generates the type as it might be used in a cast expression
genType :: GenOps -> A.Type -> CGen (), genType :: GenOps -> A.Type -> CGen (),
genTypeSymbol :: GenOps -> String -> A.Type -> CGen (), genTypeSymbol :: GenOps -> String -> A.Type -> CGen (),
@ -263,12 +263,12 @@ cgenOps = GenOps {
--}}} --}}}
--{{{ top-level --{{{ top-level
generate :: GenOps -> A.Structured -> PassM String generate :: GenOps -> A.AST -> PassM String
generate ops ast generate ops ast
= do (a, out) <- runWriterT (call genTopLevel ops ast) = do (a, out) <- runWriterT (call genTopLevel ops ast)
return $ concat out return $ concat out
generateC :: A.Structured -> PassM String generateC :: A.AST -> PassM String
generateC = generate cgenOps generateC = generate cgenOps
cgenTLPChannel :: GenOps -> TLPChannel -> CGen () cgenTLPChannel :: GenOps -> TLPChannel -> CGen ()
@ -276,14 +276,14 @@ cgenTLPChannel _ TLPIn = tell ["in"]
cgenTLPChannel _ TLPOut = tell ["out"] cgenTLPChannel _ TLPOut = tell ["out"]
cgenTLPChannel _ TLPError = tell ["err"] cgenTLPChannel _ TLPError = tell ["err"]
cgenTopLevel :: GenOps -> A.Structured -> CGen () cgenTopLevel :: GenOps -> A.AST -> CGen ()
cgenTopLevel ops s cgenTopLevel ops s
= do tell ["#include <tock_support.h>\n"] = do tell ["#include <tock_support.h>\n"]
cs <- get cs <- get
tell ["extern int " ++ nameString n ++ "_stack_size;\n" tell ["extern int " ++ nameString n ++ "_stack_size;\n"
| n <- Set.toList $ csParProcs cs] | n <- Set.toList $ csParProcs cs]
sequence_ $ map (call genForwardDeclaration ops) (listify (const True :: A.Specification -> Bool) s) sequence_ $ map (call genForwardDeclaration ops) (listify (const True :: A.Specification -> Bool) s)
call genStructured ops s (\s -> tell ["\n#error Invalid top-level item: ",show s]) call genStructured ops s (\m _ -> tell ["\n#error Invalid top-level item: ", show m])
(name, chans) <- tlpInterface (name, chans) <- tlpInterface
tell ["void tock_main (Process *me, Channel *in, Channel *out, Channel *err) {\n"] tell ["void tock_main (Process *me, Channel *in, Channel *out, Channel *err) {\n"]
genName name genName name
@ -347,12 +347,12 @@ cgenOverArray ops m var func
Nothing -> return () Nothing -> return ()
-- | Generate code for one of the Structured types. -- | Generate code for one of the Structured types.
cgenStructured :: GenOps -> A.Structured -> (A.Structured -> CGen ()) -> CGen () cgenStructured :: Data a => GenOps -> A.Structured a -> (Meta -> a -> CGen ()) -> CGen ()
cgenStructured ops (A.Rep _ rep s) def = call genReplicator ops rep (call genStructured ops s def) cgenStructured ops (A.Rep _ rep s) def = call genReplicator ops rep (call genStructured ops s def)
cgenStructured ops (A.Spec _ spec s) def = call genSpec ops spec (call genStructured ops s def) cgenStructured ops (A.Spec _ spec s) def = call genSpec ops spec (call genStructured ops s def)
cgenStructured ops (A.ProcThen _ p s) def = call genProcess ops p >> call genStructured ops s def cgenStructured ops (A.ProcThen _ p s) def = call genProcess ops p >> call genStructured ops s def
cgenStructured ops (A.Several _ ss) def = sequence_ [call genStructured ops s def | s <- ss] cgenStructured ops (A.Several _ ss) def = sequence_ [call genStructured ops s def | s <- ss]
cgenStructured _ s def = def s cgenStructured ops (A.Only m s) def = def m s
--}}} --}}}
@ -1618,13 +1618,13 @@ cgenStop ops m s
tell [",\"", s, "\");"] tell [",\"", s, "\");"]
--}}} --}}}
--{{{ seq --{{{ seq
cgenSeq :: GenOps -> A.Structured -> CGen () cgenSeq :: GenOps -> A.Structured A.Process -> CGen ()
cgenSeq ops s = call genStructured ops s doP cgenSeq ops s = call genStructured ops s doP
where where
doP (A.OnlyP _ p) = call genProcess ops p doP _ p = call genProcess ops p
--}}} --}}}
--{{{ if --{{{ if
cgenIf :: GenOps -> Meta -> A.Structured -> CGen () cgenIf :: GenOps -> Meta -> A.Structured A.Choice -> CGen ()
cgenIf ops m s cgenIf ops m s
= do label <- makeNonce "if_end" = do label <- makeNonce "if_end"
tell ["/*",label,"*/"] tell ["/*",label,"*/"]
@ -1632,10 +1632,10 @@ cgenIf ops m s
call genStop ops m "no choice matched in IF process" call genStop ops m "no choice matched in IF process"
tell [label, ":;"] tell [label, ":;"]
where where
genIfBody :: String -> A.Structured -> CGen () genIfBody :: String -> A.Structured A.Choice -> CGen ()
genIfBody label s = call genStructured ops s doC genIfBody label s = call genStructured ops s doC
where where
doC (A.OnlyC m (A.Choice m' e p)) doC m (A.Choice m' e p)
= do tell ["if("] = do tell ["if("]
call genExpression ops e call genExpression ops e
tell ["){"] tell ["){"]
@ -1644,7 +1644,7 @@ cgenIf ops m s
tell ["}"] tell ["}"]
--}}} --}}}
--{{{ case --{{{ case
cgenCase :: GenOps -> Meta -> A.Expression -> A.Structured -> CGen () cgenCase :: GenOps -> Meta -> A.Expression -> A.Structured A.Option -> CGen ()
cgenCase ops m e s cgenCase ops m e s
= do tell ["switch("] = do tell ["switch("]
call genExpression ops e call genExpression ops e
@ -1655,17 +1655,17 @@ cgenCase ops m e s
call genStop ops m "no option matched in CASE process" call genStop ops m "no option matched in CASE process"
tell ["}"] tell ["}"]
where where
genCaseBody :: CGen () -> A.Structured -> CGen Bool genCaseBody :: CGen () -> A.Structured A.Option -> CGen Bool
genCaseBody coll (A.Spec _ spec s) genCaseBody coll (A.Spec _ spec s)
= genCaseBody (call genSpec ops spec coll) s = genCaseBody (call genSpec ops spec coll) s
genCaseBody coll (A.OnlyO _ (A.Option _ es p)) genCaseBody coll (A.Only _ (A.Option _ es p))
= do sequence_ [tell ["case "] >> call genExpression ops e >> tell [":"] | e <- es] = do sequence_ [tell ["case "] >> call genExpression ops e >> tell [":"] | e <- es]
tell ["{"] tell ["{"]
coll coll
call genProcess ops p call genProcess ops p
tell ["}break;"] tell ["}break;"]
return False return False
genCaseBody coll (A.OnlyO _ (A.Else _ p)) genCaseBody coll (A.Only _ (A.Else _ p))
= do tell ["default:"] = do tell ["default:"]
tell ["{"] tell ["{"]
coll coll
@ -1686,7 +1686,7 @@ cgenWhile ops e p
tell ["}"] tell ["}"]
--}}} --}}}
--{{{ par --{{{ par
cgenPar :: GenOps -> A.ParMode -> A.Structured -> CGen () cgenPar :: GenOps -> A.ParMode -> A.Structured A.Process -> CGen ()
cgenPar ops pm s cgenPar ops pm s
= do (size, _, _) <- constantFold $ addOne (sizeOfStructured s) = do (size, _, _) <- constantFold $ addOne (sizeOfStructured s)
pids <- makeNonce "pids" pids <- makeNonce "pids"
@ -1711,13 +1711,13 @@ cgenPar ops pm s
tell [index, " = 0;\n"] tell [index, " = 0;\n"]
call genStructured ops s (freeP pids index) call genStructured ops s (freeP pids index)
where where
createP pids pris index (A.OnlyP _ p) createP pids pris index _ p
= do when (pm == A.PriPar) $ = do when (pm == A.PriPar) $
tell [pris, "[", index, "] = ", index, ";\n"] tell [pris, "[", index, "] = ", index, ";\n"]
tell [pids, "[", index, "++] = "] tell [pids, "[", index, "++] = "]
genProcAlloc p genProcAlloc p
tell [";\n"] tell [";\n"]
freeP pids index (A.OnlyP _ _) freeP pids index _ _
= do tell ["ProcAllocClean (", pids, "[", index, "++]);\n"] = do tell ["ProcAllocClean (", pids, "[", index, "++]);\n"]
genProcAlloc :: A.Process -> CGen () genProcAlloc :: A.Process -> CGen ()
@ -1731,7 +1731,7 @@ cgenPar ops pm s
genProcAlloc p = call genMissing ops $ "genProcAlloc " ++ show p genProcAlloc p = call genMissing ops $ "genProcAlloc " ++ show p
--}}} --}}}
--{{{ alt --{{{ alt
cgenAlt :: GenOps -> Bool -> A.Structured -> CGen () cgenAlt :: GenOps -> Bool -> A.Structured A.Alternative -> CGen ()
cgenAlt ops isPri s cgenAlt ops isPri s
= do tell ["AltStart ();\n"] = do tell ["AltStart ();\n"]
tell ["{\n"] tell ["{\n"]
@ -1753,10 +1753,10 @@ cgenAlt ops isPri s
tell ["}\n"] tell ["}\n"]
tell [label, ":\n;\n"] tell [label, ":\n;\n"]
where where
genAltEnable :: A.Structured -> CGen () genAltEnable :: A.Structured A.Alternative -> CGen ()
genAltEnable s = call genStructured ops s doA genAltEnable s = call genStructured ops s doA
where where
doA (A.OnlyA _ alt) doA _ alt
= case alt of = case alt of
A.Alternative _ c im _ -> doIn c im A.Alternative _ c im _ -> doIn c im
A.AlternativeCond _ e c im _ -> withIf ops e $ doIn c im A.AlternativeCond _ e c im _ -> withIf ops e $ doIn c im
@ -1779,10 +1779,10 @@ cgenAlt ops isPri s
call genVariable ops c call genVariable ops c
tell [");\n"] tell [");\n"]
genAltDisable :: String -> A.Structured -> CGen () genAltDisable :: String -> A.Structured A.Alternative -> CGen ()
genAltDisable id s = call genStructured ops s doA genAltDisable id s = call genStructured ops s doA
where where
doA (A.OnlyA _ alt) doA _ alt
= case alt of = case alt of
A.Alternative _ c im _ -> doIn c im A.Alternative _ c im _ -> doIn c im
A.AlternativeCond _ e c im _ -> withIf ops e $ doIn c im A.AlternativeCond _ e c im _ -> withIf ops e $ doIn c im
@ -1803,10 +1803,10 @@ cgenAlt ops isPri s
call genVariable ops c call genVariable ops c
tell [");\n"] tell [");\n"]
genAltProcesses :: String -> String -> String -> A.Structured -> CGen () genAltProcesses :: String -> String -> String -> A.Structured A.Alternative -> CGen ()
genAltProcesses id fired label s = call genStructured ops s doA genAltProcesses id fired label s = call genStructured ops s doA
where where
doA (A.OnlyA _ alt) doA _ alt
= case alt of = case alt of
A.Alternative _ c im p -> doIn c im p A.Alternative _ c im p -> doIn c im p
A.AlternativeCond _ e c im p -> withIf ops e $ doIn c im p A.AlternativeCond _ e c im p -> withIf ops e $ doIn c im p

View File

@ -158,16 +158,16 @@ chansToAny x = do st <- get
--{{{ top-level --{{{ top-level
-- | Transforms the given AST into a pass that generates C++ code. -- | Transforms the given AST into a pass that generates C++ code.
generateCPPCSP :: A.Structured -> PassM String generateCPPCSP :: A.AST -> PassM String
generateCPPCSP = generate cppgenOps generateCPPCSP = generate cppgenOps
-- | Generates the top-level code for an AST. -- | Generates the top-level code for an AST.
cppgenTopLevel :: GenOps -> A.Structured -> CGen () cppgenTopLevel :: GenOps -> A.AST -> CGen ()
cppgenTopLevel ops s cppgenTopLevel ops s
= do tell ["#include <tock_support_cppcsp.h>\n"] = do tell ["#include <tock_support_cppcsp.h>\n"]
--In future, these declarations could be moved to a header file: --In future, these declarations could be moved to a header file:
sequence_ $ map (call genForwardDeclaration ops) (listify (const True :: A.Specification -> Bool) s) sequence_ $ map (call genForwardDeclaration ops) (listify (const True :: A.Specification -> Bool) s)
call genStructured ops s (\s -> tell ["\n#error Invalid top-level item: ",show s]) call genStructured ops s (\m _ -> tell ["\n#error Invalid top-level item: ",show m])
(name, chans) <- tlpInterface (name, chans) <- tlpInterface
tell ["int main (int argc, char** argv) { csp::Start_CPPCSP();"] tell ["int main (int argc, char** argv) { csp::Start_CPPCSP();"]
(chanType,writer) <- (chanType,writer) <-
@ -409,16 +409,16 @@ cppgenOutputCase ops c tag ois
-- | We use the process wrappers here, in order to execute the functions in parallel. -- | We use the process wrappers here, in order to execute the functions in parallel.
--We use forking instead of Run\/InParallelOneThread, because it is easier to use forking with replication. --We use forking instead of Run\/InParallelOneThread, because it is easier to use forking with replication.
cppgenPar :: GenOps -> A.ParMode -> A.Structured -> CGen () cppgenPar :: GenOps -> A.ParMode -> A.Structured A.Process -> CGen ()
cppgenPar ops _ s cppgenPar ops _ s
= do forking <- makeNonce "forking" = do forking <- makeNonce "forking"
tell ["{ csp::ScopedForking ",forking," ; "] tell ["{ csp::ScopedForking ",forking," ; "]
call genStructured ops s (genPar' forking) call genStructured ops s (genPar' forking)
tell [" }"] tell [" }"]
where where
genPar' :: String -> A.Structured -> CGen () genPar' :: String -> Meta -> A.Process -> CGen ()
genPar' forking (A.OnlyP _ p) genPar' forking _ p
= case p of = case p of
A.ProcCall _ n as -> A.ProcCall _ n as ->
do tell [forking," .forkInThisThread(new proc_"] do tell [forking," .forkInThisThread(new proc_"]
genName n genName n
@ -430,7 +430,7 @@ cppgenPar ops _ s
-- | Changed to use C++CSP's Alternative class: -- | Changed to use C++CSP's Alternative class:
cppgenAlt :: GenOps -> Bool -> A.Structured -> CGen () cppgenAlt :: GenOps -> Bool -> A.Structured A.Alternative -> CGen ()
cppgenAlt ops _ s cppgenAlt ops _ s
= do guards <- makeNonce "alt_guards" = do guards <- makeNonce "alt_guards"
tell ["std::list< csp::Guard* > ", guards, " ; "] tell ["std::list< csp::Guard* > ", guards, " ; "]
@ -449,10 +449,10 @@ cppgenAlt ops _ s
tell [label, ":\n;\n"] tell [label, ":\n;\n"]
where where
--This function is like the enable function in GenerateC, but this one merely builds a list of guards. It does not do anything other than add to the guard list --This function is like the enable function in GenerateC, but this one merely builds a list of guards. It does not do anything other than add to the guard list
initAltGuards :: String -> A.Structured -> CGen () initAltGuards :: String -> A.Structured A.Alternative -> CGen ()
initAltGuards guardList s = call genStructured ops s doA initAltGuards guardList s = call genStructured ops s doA
where where
doA (A.OnlyA _ alt) doA _ alt
= case alt of = case alt of
A.Alternative _ c im _ -> doIn c im A.Alternative _ c im _ -> doIn c im
A.AlternativeCond _ e c im _ -> withIf ops e $ doIn c im A.AlternativeCond _ e c im _ -> withIf ops e $ doIn c im
@ -475,10 +475,10 @@ cppgenAlt ops _ s
-- This is the same as GenerateC for now -- but it's not really reusable -- This is the same as GenerateC for now -- but it's not really reusable
-- because it's so closely tied to how ALT is implemented in the backend. -- because it's so closely tied to how ALT is implemented in the backend.
genAltProcesses :: String -> String -> String -> A.Structured -> CGen () genAltProcesses :: String -> String -> String -> A.Structured A.Alternative -> CGen ()
genAltProcesses id fired label s = call genStructured ops s doA genAltProcesses id fired label s = call genStructured ops s doA
where where
doA (A.OnlyA _ alt) doA _ alt
= case alt of = case alt of
A.Alternative _ c im p -> doIn c im p A.Alternative _ c im p -> doIn c im p
A.AlternativeCond _ e c im p -> withIf ops e $ doIn c im p A.AlternativeCond _ e c im p -> withIf ops e $ doIn c im p
@ -1047,7 +1047,7 @@ cppgenUnfoldedVariable ops m var
--{{{ if --{{{ if
-- | Changed to throw a nonce-exception class instead of the goto, because C++ doesn't allow gotos to cross class initialisations (such as arrays) -- | Changed to throw a nonce-exception class instead of the goto, because C++ doesn't allow gotos to cross class initialisations (such as arrays)
cppgenIf :: GenOps -> Meta -> A.Structured -> CGen () cppgenIf :: GenOps -> Meta -> A.Structured A.Choice -> CGen ()
cppgenIf ops m s cppgenIf ops m s
= do ifExc <- makeNonce "if_exc" = do ifExc <- makeNonce "if_exc"
tell ["class ",ifExc, "{};try{"] tell ["class ",ifExc, "{};try{"]
@ -1055,10 +1055,10 @@ cppgenIf ops m s
call genStop ops m "no choice matched in IF process" call genStop ops m "no choice matched in IF process"
tell ["}catch(",ifExc,"){}"] tell ["}catch(",ifExc,"){}"]
where where
genIfBody :: String -> A.Structured -> CGen () genIfBody :: String -> A.Structured A.Choice -> CGen ()
genIfBody ifExc s = call genStructured ops s doC genIfBody ifExc s = call genStructured ops s doC
where where
doC (A.OnlyC m (A.Choice m' e p)) doC m (A.Choice m' e p)
= do tell ["if("] = do tell ["if("]
call genExpression ops e call genExpression ops e
tell ["){"] tell ["){"]

View File

@ -34,6 +34,7 @@ module GenerateCTest (tests) where
import Control.Monad.Error import Control.Monad.Error
import Control.Monad.State import Control.Monad.State
import Control.Monad.Writer import Control.Monad.Writer
import Data.Generics
import Data.List (isInfixOf, intersperse) import Data.List (isInfixOf, intersperse)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Test.HUnit hiding (State) import Test.HUnit hiding (State)
@ -833,21 +834,22 @@ testCase :: Test
testCase = TestList testCase = TestList
[ [
testBothSame "testCase 0" "switch($){default:^}" ((tcall3 genCase emptyMeta e (A.Several emptyMeta [])) . over) testBothSame "testCase 0" "switch($){default:^}" ((tcall3 genCase emptyMeta e (A.Several emptyMeta [])) . over)
,testBothSame "testCase 1" "switch($){default:{@}break;}" ((tcall3 genCase emptyMeta e (A.OnlyO emptyMeta $ A.Else emptyMeta p)) . over) ,testBothSame "testCase 1" "switch($){default:{@}break;}" ((tcall3 genCase emptyMeta e (A.Only emptyMeta $ A.Else emptyMeta p)) . over)
,testBothSame "testCase 2" "switch($){default:{#@}break;}" ((tcall3 genCase emptyMeta e (spec $ A.OnlyO emptyMeta $ A.Else emptyMeta p)) . over) ,testBothSame "testCase 2" "switch($){default:{#@}break;}" ((tcall3 genCase emptyMeta e (spec $ A.Only emptyMeta $ A.Else emptyMeta p)) . over)
,testBothSame "testCase 10" "switch($){case $:{@}break;default:^}" ((tcall3 genCase emptyMeta e (A.OnlyO emptyMeta $ A.Option emptyMeta [intLiteral 0] p)) . over) ,testBothSame "testCase 10" "switch($){case $:{@}break;default:^}" ((tcall3 genCase emptyMeta e (A.Only emptyMeta $ A.Option emptyMeta [intLiteral 0] p)) . over)
,testBothSame "testCase 20" "switch($){case $:case $:{#@}break;default:{@}break;case $:{@}break;}" ((tcall3 genCase emptyMeta e $ A.Several emptyMeta ,testBothSame "testCase 20" "switch($){case $:case $:{#@}break;default:{@}break;case $:{@}break;}" ((tcall3 genCase emptyMeta e $ A.Several emptyMeta
[spec $ A.OnlyO emptyMeta $ A.Option emptyMeta [e, e] p [spec $ A.Only emptyMeta $ A.Option emptyMeta [e, e] p
,A.OnlyO emptyMeta $ A.Else emptyMeta p ,A.Only emptyMeta $ A.Else emptyMeta p
,A.OnlyO emptyMeta $ A.Option emptyMeta [e] p] ,A.Only emptyMeta $ A.Option emptyMeta [e] p]
) . over) ) . over)
] ]
where where
--The expression and process won't be used so we can use what we like: --The expression and process won't be used so we can use what we like:
e = A.True emptyMeta e = A.True emptyMeta
p = A.Skip emptyMeta p = A.Skip emptyMeta
spec :: Data a => A.Structured a -> A.Structured a
spec = A.Spec emptyMeta undefined spec = A.Spec emptyMeta undefined
over ops = ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash} over ops = ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash}
@ -872,7 +874,7 @@ testIf = TestList
((tcall2 genIf emptyMeta (A.Several emptyMeta [])) . over) ((tcall2 genIf emptyMeta (A.Several emptyMeta [])) . over)
,testBothR "testIf 1" "/\\*([[:alnum:]_]+)\\*/if\\(\\$\\)\\{@goto \\1;\\}\\^\\1:;" ,testBothR "testIf 1" "/\\*([[:alnum:]_]+)\\*/if\\(\\$\\)\\{@goto \\1;\\}\\^\\1:;"
"class ([[:alnum:]_]+)\\{\\};try\\{if\\(\\$\\)\\{@throw \\1\\(\\);\\}\\^\\}catch\\(\\1\\)\\{\\}" "class ([[:alnum:]_]+)\\{\\};try\\{if\\(\\$\\)\\{@throw \\1\\(\\);\\}\\^\\}catch\\(\\1\\)\\{\\}"
((tcall2 genIf emptyMeta (A.OnlyC emptyMeta $ A.Choice emptyMeta e p)) . over) ((tcall2 genIf emptyMeta (A.Only emptyMeta $ A.Choice emptyMeta e p)) . over)
] ]
where where
e :: A.Expression e :: A.Expression

View File

@ -31,7 +31,6 @@ import CompState
import Errors import Errors
import Metadata import Metadata
import Omega import Omega
import Pass
import ShowCode import ShowCode
import Types import Types
import UsageCheckUtils import UsageCheckUtils
@ -98,7 +97,11 @@ checkArrayUsage (m,p) = mapM_ (checkIndexes m) $ Map.toList $
cx <- showCode lx cx <- showCode lx
cy <- showCode ly cy <- showCode ly
prob <- formatProblem varMapping problem prob <- formatProblem varMapping problem
debug $ "Found solution for problem: " ++ prob -- debug $ "Found solution for problem: " ++ prob
-- liftIO $ putStrLn $ "Succeeded on problem: " ++ prob
-- allProbs <- concatMapM (\(_,_,p) -> formatProblem varMapping p >>* (++ "\n#\n")) problems
-- svm <- mapM showFlattenedExp $ Map.keys varMapping
-- liftIO $ putStrLn $ "All problems: " ++ allProbs ++ "\n" ++ (concat $ intersperse " ; " $ svm)
dieP m $ "Indexes of array \"" ++ userArrName ++ "\" " dieP m $ "Indexes of array \"" ++ userArrName ++ "\" "
++ "(\"" ++ cx ++ "\" and \"" ++ cy ++ "\") could overlap" ++ "(\"" ++ cx ++ "\" and \"" ++ cy ++ "\") could overlap"
++ if sol /= "" then " when: " ++ sol else "" ++ if sol /= "" then " when: " ++ sol else ""
@ -149,7 +152,7 @@ checkArrayUsage (m,p) = mapM_ (checkIndexes m) $ Map.toList $
showFlattenedExp :: FlattenedExp -> m String showFlattenedExp :: FlattenedExp -> m String
showFlattenedExp (Const n) = return $ show n showFlattenedExp (Const n) = return $ show n
showFlattenedExp (Scale n ((A.Variable _ vn),vi)) showFlattenedExp (Scale n ((A.Variable _ vn),vi))
= do vn' <- getRealName vn >>* (++ replicate vi '\'') = do vn' <- getRealName vn >>* (++ replicate vi '@')
case n of case n of
1 -> return vn' 1 -> return vn'
-1 -> return $ "-" ++ vn' -1 -> return $ "-" ++ vn'
@ -175,8 +178,6 @@ data FlattenedExp
| Modulo (Set.Set FlattenedExp) (Set.Set FlattenedExp) | Modulo (Set.Set FlattenedExp) (Set.Set FlattenedExp)
| Divide (Set.Set FlattenedExp) (Set.Set FlattenedExp) | Divide (Set.Set FlattenedExp) (Set.Set FlattenedExp)
--TODO change the A.Variable to Var, and automatically derive Eq and Ord
instance Eq FlattenedExp where instance Eq FlattenedExp where
a == b = EQ == compare a b a == b = EQ == compare a b

View File

@ -162,11 +162,11 @@ checkInitVar m graph startNode
-- 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 UsageLabel) -> (Node, ExSet Var) readNode :: (Node, FNode m UsageLabel) -> (Node, ExSet Var)
readNode (n, Node (_,ul,_)) = (n,NormalSet $ readVars $ nodeVars ul) readNode (n, nd) = (n,NormalSet $ readVars $ nodeVars $ getNodeData nd)
-- Gets all variables written-to in a particular node -- Gets all variables written-to in a particular node
writeNode :: FNode m UsageLabel -> ExSet Var writeNode :: FNode m UsageLabel -> ExSet Var
writeNode (Node (_,ul,_)) = NormalSet $ writtenVars $ nodeVars ul writeNode nd = NormalSet $ writtenVars $ nodeVars $ getNodeData nd
-- Nothing is treated as if were the set of all possible variables: -- Nothing is treated as if were the set of all possible variables:
nodeFunction :: (Node, EdgeLabel) -> ExSet Var -> Maybe (ExSet Var) -> ExSet Var nodeFunction :: (Node, EdgeLabel) -> ExSet Var -> Maybe (ExSet Var) -> ExSet Var
@ -185,7 +185,7 @@ checkInitVar m graph startNode
getMeta :: Node -> Meta getMeta :: Node -> Meta
getMeta n = case lab graph n of getMeta n = case lab graph n of
Just (Node (m,_,_)) -> m Just nd -> getNodeMeta nd
_ -> emptyMeta _ -> emptyMeta
checkInitVar' :: Map.Map Node (ExSet Var) -> (Node, ExSet Var) -> m () checkInitVar' :: Map.Map Node (ExSet Var) -> (Node, ExSet Var) -> m ()

View File

@ -143,11 +143,11 @@ testParUsageCheck = TestList (map doTest tests)
buildTestFlowGraph :: [(Int, [Var], [Var])] -> [(Int, Int, EdgeLabel)] -> Int -> Int -> String -> FlowGraph Identity UsageLabel buildTestFlowGraph :: [(Int, [Var], [Var])] -> [(Int, Int, EdgeLabel)] -> Int -> Int -> String -> FlowGraph Identity UsageLabel
buildTestFlowGraph ns es start end v buildTestFlowGraph ns es start end v
= mkGraph = mkGraph
([(-1,Node (emptyMeta,Usage Nothing (Just $ ScopeIn False v) emptyVars, undefined)),(-2,Node (emptyMeta,Usage Nothing (Just $ ScopeOut v) emptyVars, undefined))] ++ (map transNode ns)) ([(-1,makeTestNode emptyMeta $ Usage Nothing (Just $ ScopeIn False v) emptyVars),(-2,makeTestNode emptyMeta $ Usage Nothing (Just $ ScopeOut v) emptyVars)] ++ (map transNode ns))
([(-1,start,ESeq),(end,-2,ESeq)] ++ es) ([(-1,start,ESeq),(end,-2,ESeq)] ++ es)
where where
transNode :: (Int, [Var], [Var]) -> (Int, FNode Identity UsageLabel) transNode :: (Int, [Var], [Var]) -> (Int, FNode Identity UsageLabel)
transNode (n,r,w) = (n,Node (emptyMeta, (Usage Nothing Nothing $ vars r w []), undefined)) transNode (n,r,w) = (n,makeTestNode emptyMeta (Usage Nothing Nothing $ vars r w []))
testInitVar :: Test testInitVar :: Test

View File

@ -57,7 +57,7 @@ checkPar getRep f g = mapM f =<< allParItems
prevR :: Maybe (Maybe A.Replicator) prevR :: Maybe (Maybe A.Replicator)
prevR = liftM fst $ Map.lookup n mp prevR = liftM fst $ Map.lookup n mp
r :: Maybe (Maybe A.Replicator) r :: Maybe (Maybe A.Replicator)
r = lab g s >>* (getRep . (\(Node (_,l,_)) -> l)) r = lab g s >>* (getRep . getNodeData)
tagStartParEdge :: (Node,Node,EdgeLabel) -> Maybe (Node,Node,Int) tagStartParEdge :: (Node,Node,EdgeLabel) -> Maybe (Node,Node,Int)
tagStartParEdge (s,e,EStartPar n) = Just (s,e,n) tagStartParEdge (s,e,EStartPar n) = Just (s,e,n)
@ -71,7 +71,7 @@ checkPar getRep f g = mapM f =<< allParItems
[] -> fail "No edges in list of PAR edges" [] -> fail "No edges in list of PAR edges"
[n] -> case lab g n of [n] -> case lab g n of
Nothing -> fail "Label not found for node at start of PAR" Nothing -> fail "Label not found for node at start of PAR"
Just (Node (m,_,_)) -> return m Just nd -> return $ getNodeMeta nd
_ -> fail "PAR edges did not all start at the same node" _ -> fail "PAR edges did not all start at the same node"
where where
distinctItems = nub $ map fst ns distinctItems = nub $ map fst ns
@ -118,7 +118,7 @@ checkPar getRep f g = mapM f =<< allParItems
(Nothing, g') -> customDFS vs g' (Nothing, g') -> customDFS vs g'
labelItem :: Context (FNode m a) EdgeLabel -> a labelItem :: Context (FNode m a) EdgeLabel -> a
labelItem c = let (Node (_,x,_)) = lab' c in x labelItem = getNodeData . lab'
customSucc :: Context (FNode m a) EdgeLabel -> [Node] customSucc :: Context (FNode m a) EdgeLabel -> [Node]
customSucc c = [n | (n,e) <- lsuc' c, e /= endEdge] customSucc c = [n | (n,e) <- lsuc' c, e /= endEdge]
@ -144,10 +144,10 @@ findReachDef graph startNode
readInNode' n v _ = readInNode v (lab graph n) readInNode' n v _ = readInNode v (lab graph n)
readInNode :: Var -> Maybe (FNode m UsageLabel) -> Bool readInNode :: Var -> Maybe (FNode m UsageLabel) -> Bool
readInNode v (Just (Node (_,ul,_))) = (Set.member v . readVars . nodeVars) ul readInNode v (Just nd) = (Set.member v . readVars . nodeVars) (getNodeData nd)
writeNode :: FNode m UsageLabel -> Set.Set Var writeNode :: FNode m UsageLabel -> Set.Set Var
writeNode (Node (_,ul,_)) = writtenVars $ nodeVars ul writeNode nd = writtenVars $ nodeVars $ getNodeData nd
-- | A confusiing function used by processNode. It takes a node and node label, and uses -- | A confusiing function used by processNode. It takes a node and node label, and uses
-- these to form a multi-map modifier function that replaces all node-sources for variables -- these to form a multi-map modifier function that replaces all node-sources for variables

View File

@ -368,25 +368,60 @@ data Variant = Variant Meta Name [InputItem] Process
-- | This represents something that can contain local replicators and specifications. -- | This represents something that can contain local replicators and specifications.
-- (This ought to be a parametric type, @Structured Variant@ etc., but doing so -- (This ought to be a parametric type, @Structured Variant@ etc., but doing so
-- makes using generic functions across it hard.) -- makes using generic functions across it hard.)
data Structured = data Data a => Structured a =
Rep Meta Replicator Structured Rep Meta Replicator (Structured a)
| Spec Meta Specification Structured | Spec Meta Specification (Structured a)
| ProcThen Meta Process Structured | ProcThen Meta Process (Structured a)
| OnlyV Meta Variant -- ^ Variant (@CASE@) input process | Only Meta a
| OnlyC Meta Choice -- ^ @IF@ process | Several Meta [Structured a]
| OnlyO Meta Option -- ^ @CASE@ process deriving (Show, Eq, Typeable)
| OnlyA Meta Alternative -- ^ @ALT@ process
| OnlyP Meta Process -- ^ @SEQ@, @PAR@ -- The Data instance for Structured is tricky. Because it is a parameterised class we
| OnlyEL Meta ExpressionList -- ^ @VALOF@ -- need to change the dataCast1 function from the default declaration; something
| Several Meta [Structured] -- that leaving GHC to handle deriving (Data) will not achieve. Therefore we have no
deriving (Show, Eq, Typeable, Data) -- choice but to provide our own instance long-hand here:
_struct_RepConstr = mkConstr _struct_DataType "Rep" [] Prefix
_struct_SpecConstr = mkConstr _struct_DataType "Spec" [] Prefix
_struct_ProcThenConstr= mkConstr _struct_DataType "ProcThen" [] Prefix
_struct_OnlyConstr = mkConstr _struct_DataType "Only" [] Prefix
_struct_SeveralConstr = mkConstr _struct_DataType "Several" [] Prefix
_struct_DataType = mkDataType "AST.Structured"
[_struct_RepConstr
,_struct_SpecConstr
,_struct_ProcThenConstr
,_struct_OnlyConstr
,_struct_SeveralConstr
]
instance Data a => Data (Structured a) where
gfoldl f z (Rep m r s) = z Rep `f` m `f` r `f` s
gfoldl f z (Spec m sp str) = z Spec `f` m `f` sp `f` str
gfoldl f z (ProcThen m p s) = z ProcThen `f` m `f` p `f` s
gfoldl f z (Only m x) = z Only `f` m `f` x
gfoldl f z (Several m ss) = z Several `f` m `f` ss
toConstr (Rep {}) = _struct_RepConstr
toConstr (Spec {}) = _struct_SpecConstr
toConstr (ProcThen {}) = _struct_ProcThenConstr
toConstr (Only {}) = _struct_OnlyConstr
toConstr (Several {}) = _struct_SeveralConstr
gunfold k z c = case constrIndex c of
1 -> (k . k . k) (z Rep)
2 -> (k . k . k) (z Spec)
3 -> (k . k . k) (z ProcThen)
4 -> (k . k) (z Only)
5 -> (k . k) (z Several)
_ -> error "gunfold"
dataTypeOf _ = _struct_DataType
dataCast1 f = gcast1 f
-- | The mode in which an input operates. -- | The mode in which an input operates.
data InputMode = data InputMode =
-- | A plain input from a channel. -- | A plain input from a channel.
InputSimple Meta [InputItem] InputSimple Meta [InputItem]
-- | A variant input from a channel. -- | A variant input from a channel.
| InputCase Meta Structured | InputCase Meta (Structured Variant)
-- | Read the value of a timer. -- | Read the value of a timer.
| InputTimerRead Meta InputItem | InputTimerRead Meta InputItem
-- | Wait for a particular time to go past on a timer. -- | Wait for a particular time to go past on a timer.
@ -437,7 +472,7 @@ data SpecType =
-- | Declare a @PROC@. -- | Declare a @PROC@.
| Proc Meta SpecMode [Formal] Process | Proc Meta SpecMode [Formal] Process
-- | Declare a @FUNCTION@. -- | Declare a @FUNCTION@.
| Function Meta SpecMode [Type] [Formal] Structured | Function Meta SpecMode [Type] [Formal] (Structured ExpressionList)
-- | Declare a retyping abbreviation of a variable. -- | Declare a retyping abbreviation of a variable.
| Retypes Meta AbbrevMode Type Variable | Retypes Meta AbbrevMode Type Variable
-- | Declare a retyping abbreviation of an expression. -- | Declare a retyping abbreviation of an expression.
@ -491,16 +526,16 @@ data Process =
| ClearMobile Meta Variable | ClearMobile Meta Variable
| Skip Meta | Skip Meta
| Stop Meta | Stop Meta
| Seq Meta Structured | Seq Meta (Structured Process)
| If Meta Structured | If Meta (Structured Choice)
| Case Meta Expression Structured | Case Meta Expression (Structured Option)
| While Meta Expression Process | While Meta Expression Process
| Par Meta ParMode Structured | Par Meta ParMode (Structured Process)
-- | A @PROCESSOR@ process. -- | A @PROCESSOR@ process.
-- The occam2.1 syntax says this is just a process, although it shouldn't be -- The occam2.1 syntax says this is just a process, although it shouldn't be
-- legal outside a @PLACED PAR@. -- legal outside a @PLACED PAR@.
| Processor Meta Expression Process | Processor Meta Expression Process
| Alt Meta Bool Structured | Alt Meta Bool (Structured Alternative)
| ProcCall Meta Name [Actual] | ProcCall Meta Name [Actual]
-- | A call of a built-in @PROC@. -- | A call of a built-in @PROC@.
-- This may go away in the future, since which @PROC@s are intrinsics depends -- This may go away in the future, since which @PROC@s are intrinsics depends
@ -508,3 +543,4 @@ data Process =
| IntrinsicProcCall Meta String [Actual] | IntrinsicProcCall Meta String [Actual]
deriving (Show, Eq, Typeable, Data) deriving (Show, Eq, Typeable, Data)
type AST = Structured ()

View File

@ -99,11 +99,13 @@ testCheckTreeForConstr = TestList
,doTest (1,A.Int,[con0 A.Int],[ADI A.Int]) ,doTest (1,A.Int,[con0 A.Int],[ADI A.Int])
,doTest (100, A.True emptyMeta, [con1 A.True],[ADI $ A.True emptyMeta]) ,doTest (100, A.True emptyMeta, [con1 A.True],[ADI $ A.True emptyMeta])
,doTest (200, A.Seq emptyMeta $ A.Several emptyMeta [A.OnlyP emptyMeta $ A.Skip emptyMeta], [con1 A.Skip], [ADI $ A.Skip emptyMeta]) ,doTest (200, A.Seq emptyMeta $ A.Several emptyMeta [A.Only emptyMeta $ A.Skip emptyMeta], [con1 A.Skip], [ADI $ A.Skip emptyMeta])
,doTest (201, A.Seq emptyMeta $ A.Several emptyMeta [A.OnlyP emptyMeta $ A.Skip emptyMeta], [con2 A.Several], [ADI $ A.Several emptyMeta [A.OnlyP emptyMeta $ A.Skip emptyMeta]]) ,doTest (201, A.Seq emptyMeta $ A.Several emptyMeta [A.Only emptyMeta $ A.Skip emptyMeta],
,doTest (202, A.Seq emptyMeta $ A.Several emptyMeta [A.OnlyP emptyMeta $ A.Skip emptyMeta], [con0 A.Int], []) [con2 (A.Several :: Meta -> [A.Structured A.Process] -> A.Structured A.Process)],
,doTest (203, A.Seq emptyMeta $ A.Several emptyMeta [A.OnlyP emptyMeta $ A.Skip emptyMeta], [con2 A.OnlyP, con1 A.Skip], [ADI $ A.Several emptyMeta [A.Only emptyMeta $ A.Skip emptyMeta]])
[ADI $ A.OnlyP emptyMeta $ A.Skip emptyMeta, ADI $ A.Skip emptyMeta]) ,doTest (202, A.Seq emptyMeta $ A.Several emptyMeta [A.Only emptyMeta $ A.Skip emptyMeta], [con0 A.Int], [])
,doTest (203, A.Seq emptyMeta $ A.Several emptyMeta [A.Only emptyMeta $ A.Skip emptyMeta], [con2 (A.Only :: Meta -> A.Process -> A.Structured A.Process), con1 A.Skip],
[ADI $ A.Only emptyMeta $ A.Skip emptyMeta, ADI $ A.Skip emptyMeta])
] ]
where where
doTest :: Data a => (Int, a, [Constr], [AnyDataItem]) -> Test doTest :: Data a => (Int, a, [Constr], [AnyDataItem]) -> Test

View File

@ -75,14 +75,13 @@ data CompState = CompState {
-- Set by passes -- Set by passes
csNonceCounter :: Int, csNonceCounter :: Int,
csFunctionReturns :: Map String [A.Type], csFunctionReturns :: Map String [A.Type],
csPulledItems :: [[A.Structured -> A.Structured]], csPulledItems :: [[PulledItem]],
csAdditionalArgs :: Map String [A.Actual], csAdditionalArgs :: Map String [A.Actual],
csParProcs :: Set A.Name csParProcs :: Set A.Name
} }
deriving (Data, Typeable) deriving (Data, Typeable)
instance Show (A.Structured -> A.Structured) where type PulledItem = (Meta, Either A.Specification A.Process) -- Either Spec or ProcThen
show p = "(function on Structured)"
emptyState :: CompState emptyState :: CompState
emptyState = CompState { emptyState = CompState {
@ -155,7 +154,7 @@ popPullContext :: CSM m => m ()
popPullContext = modify (\ps -> ps { csPulledItems = tail $ csPulledItems ps }) popPullContext = modify (\ps -> ps { csPulledItems = tail $ csPulledItems ps })
-- | Add a pulled item to the collection. -- | Add a pulled item to the collection.
addPulled :: CSM m => (A.Structured -> A.Structured) -> m () addPulled :: CSM m => PulledItem -> m ()
addPulled item addPulled item
= modify (\ps -> case csPulledItems ps of = modify (\ps -> case csPulledItems ps of
(l:ls) -> ps { csPulledItems = (item:l):ls }) (l:ls) -> ps { csPulledItems = (item:l):ls })
@ -169,12 +168,17 @@ havePulled
_ -> return True _ -> return True
-- | Apply pulled items to a Structured. -- | Apply pulled items to a Structured.
applyPulled :: CSM m => A.Structured -> m A.Structured applyPulled :: (CSM m, Data a) => A.Structured a -> m (A.Structured a)
applyPulled ast applyPulled ast
= do ps <- get = do ps <- get
case csPulledItems ps of case csPulledItems ps of
(l:ls) -> do put $ ps { csPulledItems = [] : ls } (l:ls) -> do put $ ps { csPulledItems = [] : ls }
return $ foldl (\p f -> f p) ast l return $ foldl (\p f -> apply f p) ast l
where
apply :: Data a => PulledItem -> A.Structured a -> A.Structured a
apply (m, Left spec) = A.Spec m spec
apply (m, Right proc) = A.ProcThen m proc
--}}} --}}}
--{{{ type contexts --{{{ type contexts

View File

@ -41,7 +41,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
-- * If statements, on the other hand, have to be chained together. Each expression is connected -- * If statements, on the other hand, have to be chained together. Each expression is connected
-- to its body, but also to the next expression. There is no link between the last expression -- to its body, but also to the next expression. There is no link between the last expression
-- and the end of the if; if statements behave like STOP if nothing is matched. -- and the end of the if; if statements behave like STOP if nothing is matched.
module FlowGraph (AlterAST(..), EdgeLabel(..), FNode(..), FlowGraph, GraphLabelFuncs(..), buildFlowGraph, joinLabelFuncs, makeFlowGraphInstr, mkLabelFuncsConst, mkLabelFuncsGeneric) where module FlowGraph (AlterAST(..), EdgeLabel(..), FNode, FlowGraph, FlowGraph', GraphLabelFuncs(..), buildFlowGraph, getNodeData, getNodeFunc, getNodeMeta, joinLabelFuncs, makeFlowGraphInstr, makeTestNode, mkLabelFuncsConst, mkLabelFuncsGeneric) where
import Control.Monad.Error import Control.Monad.Error
import Control.Monad.State import Control.Monad.State
@ -70,47 +70,51 @@ data OuterType = ONone | OSeq | OPar Int (Node, Node) | OCase (Node,Node) | OIf
-- | A type used to build up tree-modifying functions. When given an inner modification function, -- | A type used to build up tree-modifying functions. When given an inner modification function,
-- it returns a modification function for the whole tree. The functions are monadic, to -- it returns a modification function for the whole tree. The functions are monadic, to
-- provide flexibility; you can always use the Identity monad. -- provide flexibility; you can always use the Identity monad.
type ASTModifier m inner = (inner -> m inner) -> (A.Structured -> m A.Structured) type ASTModifier m inner structType = (inner -> m inner) -> (A.Structured structType -> m (A.Structured structType))
-- | An operator for combining ASTModifier functions as you walk the tree. -- | An operator for combining ASTModifier functions as you walk the tree.
-- While its implementation is simple, it adds clarity to the code. -- While its implementation is simple, it adds clarity to the code.
(@->) :: ASTModifier m outer -> ((inner -> m inner) -> (outer -> m outer)) -> ASTModifier m inner (@->) :: ASTModifier m outer b -> ((inner -> m inner) -> (outer -> m outer)) -> ASTModifier m inner b
(@->) = (.) (@->) = (.)
-- | A choice of AST altering functions built on ASTModifier. -- | A choice of AST altering functions built on ASTModifier.
data AlterAST m = data AlterAST m structType =
AlterProcess (ASTModifier m A.Process) AlterProcess (ASTModifier m A.Process structType)
|AlterArguments (ASTModifier m [A.Formal]) |AlterArguments (ASTModifier m [A.Formal] structType)
|AlterExpression (ASTModifier m A.Expression) |AlterExpression (ASTModifier m A.Expression structType)
|AlterExpressionList (ASTModifier m A.ExpressionList) |AlterExpressionList (ASTModifier m A.ExpressionList structType)
|AlterReplicator (ASTModifier m A.Replicator) |AlterReplicator (ASTModifier m A.Replicator structType)
|AlterSpec (ASTModifier m A.Specification) |AlterSpec (ASTModifier m A.Specification structType)
|AlterNothing |AlterNothing
data Monad m => FNode' m a b = Node (Meta, a, AlterAST m b)
-- | The label for a node. A Meta tag, a custom label, and a function -- | The label for a node. A Meta tag, a custom label, and a function
-- for altering the part of the AST that this node came from -- for altering the part of the AST that this node came from
data Monad m => FNode m a = Node (Meta, a, AlterAST m) type FNode m a = FNode' m a ()
--type FEdge = (Node, EdgeLabel, Node) --type FEdge = (Node, EdgeLabel, Node)
instance (Monad m, Show a) => Show (FNode m a) where instance (Monad m, Show a) => Show (FNode' m a b) where
show (Node (m,x,_)) = (filter ((/=) '\"')) $ show m ++ ":" ++ show x show (Node (m,x,_)) = (filter ((/=) '\"')) $ show m ++ ":" ++ show x
type FlowGraph' m a b = Gr (FNode' m a b) EdgeLabel
-- | The main FlowGraph type. The m parameter is the monad -- | The main FlowGraph type. The m parameter is the monad
-- in which alterations to the AST (based on the FlowGraph) -- in which alterations to the AST (based on the FlowGraph)
-- must occur. The a parameter is the type of the node labels. -- must occur. The a parameter is the type of the node labels.
type FlowGraph m a = Gr (FNode m a) EdgeLabel type FlowGraph m a = FlowGraph' m a ()
-- | A list of nodes and edges. Used for building up the graph. -- | A list of nodes and edges. Used for building up the graph.
type NodesEdges m a = ([LNode (FNode m a)],[LEdge EdgeLabel]) type NodesEdges m a b = ([LNode (FNode' m a b)],[LEdge EdgeLabel])
-- | The state carried around when building up the graph. In order they are: -- | The state carried around when building up the graph. In order they are:
-- * The next node identifier -- * The next node identifier
-- * The next identifier for a PAR item (for the EStartPar/EEndPar edges) -- * The next identifier for a PAR item (for the EStartPar/EEndPar edges)
-- * The list of nodes and edges to put into the graph -- * The list of nodes and edges to put into the graph
-- * The list of root nodes thus far (those with no links to them) -- * The list of root nodes thus far (those with no links to them)
type GraphMakerState mAlter a = (Node, Int, NodesEdges mAlter a, [Node]) type GraphMakerState mAlter a b = (Node, Int, NodesEdges mAlter a b, [Node])
type GraphMaker mLabel mAlter a b = ErrorT String (StateT (GraphMakerState mAlter a) mLabel) b type GraphMaker mLabel mAlter a b c = ErrorT String (StateT (GraphMakerState mAlter a b) mLabel) c
-- | The GraphLabelFuncs type. These are a group of functions -- | The GraphLabelFuncs type. These are a group of functions
-- used to provide labels for different elements of AST. -- used to provide labels for different elements of AST.
@ -130,6 +134,18 @@ data Monad m => GraphLabelFuncs m label = GLF {
,labelScopeOut :: A.Specification -> m label ,labelScopeOut :: A.Specification -> m label
} }
getNodeMeta :: Monad m => FNode' m a b -> Meta
getNodeMeta (Node (m,_,_)) = m
getNodeData :: Monad m => FNode' m a b -> a
getNodeData (Node (_,d,_)) = d
getNodeFunc :: Monad m => FNode' m a b -> AlterAST m b
getNodeFunc (Node (_,_,f)) = f
makeTestNode :: Monad m => Meta -> a -> FNode m a
makeTestNode m d = Node (m,d,undefined)
-- | Builds the instructions to send to GraphViz -- | Builds the instructions to send to GraphViz
makeFlowGraphInstr :: (Monad m, Show a) => FlowGraph m a -> String makeFlowGraphInstr :: (Monad m, Show a) => FlowGraph m a -> String
makeFlowGraphInstr = graphviz' makeFlowGraphInstr = graphviz'
@ -167,12 +183,12 @@ mkLabelFuncsGeneric f = GLF f f f f f f f f
-- the parameters, only in the result. The mLabel monad is the monad in -- the parameters, only in the result. The mLabel monad is the monad in
-- which the labelling must be done; hence the flow-graph is returned inside -- which the labelling must be done; hence the flow-graph is returned inside
-- the label monad. -- the label monad.
buildFlowGraph :: forall mLabel mAlter label. (Monad mLabel, Monad mAlter) => buildFlowGraph :: forall mLabel mAlter label structType. (Monad mLabel, Monad mAlter, Data structType) =>
GraphLabelFuncs mLabel label -> GraphLabelFuncs mLabel label ->
A.Structured -> A.Structured structType ->
mLabel (Either String (FlowGraph mAlter label, [Node])) mLabel (Either String (FlowGraph' mAlter label structType, [Node]))
buildFlowGraph funcs s buildFlowGraph funcs s
= do res <- runStateT (runErrorT $ buildStructured ONone s id) (0, 0, ([],[]), []) = do res <- runStateT (runErrorT $ buildStructured (\_ _ _ -> throwError "Did not expect outer-most node to exist in AST") ONone s id) (0, 0, ([],[]), [])
return $ case res of return $ case res of
(Left err,_) -> Left err (Left err,_) -> Left err
(Right (Left {}),(_,_,(nodes, edges),roots)) -> Right (mkGraph nodes edges, roots) (Right (Left {}),(_,_,(nodes, edges),roots)) -> Right (mkGraph nodes edges, roots)
@ -183,16 +199,16 @@ buildFlowGraph funcs s
run :: (GraphLabelFuncs mLabel label -> (b -> mLabel label)) -> b -> mLabel label run :: (GraphLabelFuncs mLabel label -> (b -> mLabel label)) -> b -> mLabel label
run func = func funcs run func = func funcs
addNode :: (Meta, label, AlterAST mAlter) -> GraphMaker mLabel mAlter label Node addNode :: (Meta, label, AlterAST mAlter structType) -> GraphMaker mLabel mAlter label structType Node
addNode x = do (n,pi,(nodes, edges), rs) <- get addNode x = do (n,pi,(nodes, edges), rs) <- get
put (n+1, pi,((n, Node x):nodes, edges), rs) put (n+1, pi,((n, Node x):nodes, edges), rs)
return n return n
denoteRootNode :: Node -> GraphMaker mLabel mAlter label () denoteRootNode :: Node -> GraphMaker mLabel mAlter label structType ()
denoteRootNode root = do (n, pi, nes, roots) <- get denoteRootNode root = do (n, pi, nes, roots) <- get
put (n, pi, nes, root : roots) put (n, pi, nes, root : roots)
addEdge :: EdgeLabel -> Node -> Node -> GraphMaker mLabel mAlter label () addEdge :: EdgeLabel -> Node -> Node -> GraphMaker mLabel mAlter label structType ()
addEdge label start end = do (n, pi, (nodes, edges), rs) <- get addEdge label start end = do (n, pi, (nodes, edges), rs) <- get
-- Edges should only be added after the nodes, so -- Edges should only be added after the nodes, so
-- for safety here we can check that the nodes exist: -- for safety here we can check that the nodes exist:
@ -202,25 +218,25 @@ buildFlowGraph funcs s
-- It is important for the flow-graph tests that the Meta tag passed in is the same as the -- It is important for the flow-graph tests that the Meta tag passed in is the same as the
-- result of calling findMeta on the third parameter -- result of calling findMeta on the third parameter
addNode' :: Meta -> (GraphLabelFuncs mLabel label -> (b -> mLabel label)) -> b -> AlterAST mAlter -> GraphMaker mLabel mAlter label Node addNode' :: Meta -> (GraphLabelFuncs mLabel label -> (b -> mLabel label)) -> b -> AlterAST mAlter structType -> GraphMaker mLabel mAlter label structType Node
addNode' m f t r = do val <- (lift . lift) (run f t) addNode' m f t r = do val <- (lift . lift) (run f t)
addNode (m, val, r) addNode (m, val, r)
addNodeExpression :: Meta -> A.Expression -> (ASTModifier mAlter A.Expression) -> GraphMaker mLabel mAlter label Node addNodeExpression :: Meta -> A.Expression -> (ASTModifier mAlter A.Expression structType) -> GraphMaker mLabel mAlter label structType Node
addNodeExpression m e r = addNode' m labelExpression e (AlterExpression r) addNodeExpression m e r = addNode' m labelExpression e (AlterExpression r)
addNodeExpressionList :: Meta -> A.ExpressionList -> (ASTModifier mAlter A.ExpressionList) -> GraphMaker mLabel mAlter label Node addNodeExpressionList :: Meta -> A.ExpressionList -> (ASTModifier mAlter A.ExpressionList structType) -> GraphMaker mLabel mAlter label structType Node
addNodeExpressionList m e r = addNode' m labelExpressionList e (AlterExpressionList r) addNodeExpressionList m e r = addNode' m labelExpressionList e (AlterExpressionList r)
addDummyNode :: Meta -> GraphMaker mLabel mAlter label Node addDummyNode :: Meta -> GraphMaker mLabel mAlter label structType Node
addDummyNode m = addNode' m labelDummy m AlterNothing addDummyNode m = addNode' m labelDummy m AlterNothing
getNextParEdgeId :: GraphMaker mLabel mAlter label Int getNextParEdgeId :: GraphMaker mLabel mAlter label structType Int
getNextParEdgeId = do (a, pi, b, c) <- get getNextParEdgeId = do (a, pi, b, c) <- get
put (a, pi + 1, b, c) put (a, pi + 1, b, c)
return pi return pi
addParEdges :: Int -> (Node,Node) -> [(Node,Node)] -> GraphMaker mLabel mAlter label () addParEdges :: Int -> (Node,Node) -> [(Node,Node)] -> GraphMaker mLabel mAlter label structType ()
addParEdges usePI (s,e) pairs addParEdges usePI (s,e) pairs
= do (n,pi,(nodes,edges),rs) <- get = do (n,pi,(nodes,edges),rs) <- get
put (n,pi,(nodes,edges ++ (concatMap (parEdge usePI) pairs)),rs) put (n,pi,(nodes,edges ++ (concatMap (parEdge usePI) pairs)),rs)
@ -240,14 +256,14 @@ buildFlowGraph funcs s
x' <- f x x' <- f x
return (pre ++ [x'] ++ suf) return (pre ++ [x'] ++ suf)
mapMR :: forall inner. ASTModifier mAlter [inner] -> (inner -> ASTModifier mAlter inner -> GraphMaker mLabel mAlter label (Node,Node)) -> [inner] -> GraphMaker mLabel mAlter label [(Node,Node)] mapMR :: forall inner. ASTModifier mAlter [inner] structType -> (inner -> ASTModifier mAlter inner structType -> GraphMaker mLabel mAlter label structType (Node,Node)) -> [inner] -> GraphMaker mLabel mAlter label structType [(Node,Node)]
mapMR outerRoute func xs = mapM funcAndRoute (zip [0..] xs) mapMR outerRoute func xs = mapM funcAndRoute (zip [0..] xs)
where where
funcAndRoute :: (Int, inner) -> GraphMaker mLabel mAlter label (Node,Node) funcAndRoute :: (Int, inner) -> GraphMaker mLabel mAlter label structType (Node,Node)
funcAndRoute (ind,x) = func x (outerRoute @-> routeList ind) funcAndRoute (ind,x) = func x (outerRoute @-> routeList ind)
mapMRE :: forall inner. ASTModifier mAlter [inner] -> (inner -> ASTModifier mAlter inner -> GraphMaker mLabel mAlter label (Either Bool (Node,Node))) -> [inner] -> GraphMaker mLabel mAlter label (Either Bool [(Node,Node)]) mapMRE :: forall inner. ASTModifier mAlter [inner] structType -> (inner -> ASTModifier mAlter inner structType -> GraphMaker mLabel mAlter label structType (Either Bool (Node,Node))) -> [inner] -> GraphMaker mLabel mAlter label structType (Either Bool [(Node,Node)])
mapMRE outerRoute func xs = mapM funcAndRoute (zip [0..] xs) >>* foldl foldEither (Left False) mapMRE outerRoute func xs = mapM funcAndRoute (zip [0..] xs) >>* foldl foldEither (Left False)
where where
foldEither :: Either Bool [(Node,Node)] -> Either Bool (Node,Node) -> Either Bool [(Node,Node)] foldEither :: Either Bool [(Node,Node)] -> Either Bool (Node,Node) -> Either Bool [(Node,Node)]
@ -256,7 +272,7 @@ buildFlowGraph funcs s
foldEither (Left hadNode) (Left hadNode') = Left $ hadNode || hadNode' foldEither (Left hadNode) (Left hadNode') = Left $ hadNode || hadNode'
foldEither (Right ns) (Right n) = Right (ns ++ [n]) foldEither (Right ns) (Right n) = Right (ns ++ [n])
funcAndRoute :: (Int, inner) -> GraphMaker mLabel mAlter label (Either Bool (Node,Node)) funcAndRoute :: (Int, inner) -> GraphMaker mLabel mAlter label structType (Either Bool (Node,Node))
funcAndRoute (ind,x) = func x (outerRoute @-> routeList ind) funcAndRoute (ind,x) = func x (outerRoute @-> routeList ind)
@ -264,67 +280,49 @@ buildFlowGraph funcs s
nonEmpty (Left hadNodes) = hadNodes nonEmpty (Left hadNodes) = hadNodes
nonEmpty (Right nodes) = not (null nodes) nonEmpty (Right nodes) = not (null nodes)
joinPairs :: Meta -> [(Node, Node)] -> GraphMaker mLabel mAlter label (Node, Node) joinPairs :: Meta -> [(Node, Node)] -> GraphMaker mLabel mAlter label structType (Node, Node)
joinPairs m [] = addDummyNode m >>* mkPair joinPairs m [] = addDummyNode m >>* mkPair
joinPairs m nodes = do sequence_ $ mapPairs (\(_,s) (e,_) -> addEdge ESeq s e) nodes joinPairs m nodes = do sequence_ $ mapPairs (\(_,s) (e,_) -> addEdge ESeq s e) nodes
return (fst (head nodes), snd (last nodes)) return (fst (head nodes), snd (last nodes))
buildStructuredP = buildStructured (\_ r p -> buildProcess p r)
buildStructuredC = buildStructured buildOnlyChoice
buildStructuredO = buildStructured buildOnlyOption
-- Returns a pair of beginning-node, end-node -- Returns a pair of beginning-node, end-node
-- Bool indicates emptiness (False = empty, True = there was something) -- Bool indicates emptiness (False = empty, True = there was something)
buildStructured :: OuterType -> A.Structured -> ASTModifier mAlter A.Structured -> GraphMaker mLabel mAlter label (Either Bool (Node, Node)) buildStructured :: forall a. Data a => (OuterType -> ASTModifier mAlter a structType -> a -> GraphMaker mLabel mAlter label structType (Node, Node)) ->
buildStructured outer (A.Several m ss) route OuterType -> A.Structured a -> ASTModifier mAlter (A.Structured a) structType -> GraphMaker mLabel mAlter label structType (Either Bool (Node, Node))
buildStructured f outer (A.Several m ss) route
= do case outer of = do case outer of
ONone -> -- If there is no context, they should be left as disconnected graphs. ONone -> -- If there is no context, they should be left as disconnected graphs.
do nodes <- mapMRE decompSeveral (buildStructured outer) ss do nodes <- mapMRE decompSeveral (buildStructured f outer) ss
return $ Left $ nonEmpty nodes return $ Left $ nonEmpty nodes
OSeq -> do nodes <- mapMRE decompSeveral (buildStructured outer) ss OSeq -> do nodes <- mapMRE decompSeveral (buildStructured f outer) ss
case nodes of case nodes of
Left hadNodes -> return $ Left hadNodes Left hadNodes -> return $ Left hadNodes
Right nodes' -> joinPairs m nodes' >>* Right Right nodes' -> joinPairs m nodes' >>* Right
OPar pId (nStart, nEnd) -> OPar pId (nStart, nEnd) ->
do nodes <- mapMRE decompSeveral (buildStructured outer) ss do nodes <- mapMRE decompSeveral (buildStructured f outer) ss
addParEdges pId (nStart, nEnd) $ either (const []) id nodes addParEdges pId (nStart, nEnd) $ either (const []) id nodes
return $ Left $ nonEmpty nodes return $ Left $ nonEmpty nodes
--Because the conditions in If statements are chained together, we --Because the conditions in If statements are chained together, we
--must fold the specs, not map them independently --must fold the specs, not map them independently
OIf prev end -> foldM foldIf (prev,end) (zip [0..] ss) >>* Right OIf prev end -> foldM foldIf (prev,end) (zip [0..] ss) >>* Right
where where
foldIf :: (Node,Node) -> (Int,A.Structured) -> GraphMaker mLabel mAlter label (Node, Node) foldIf :: (Node,Node) -> (Int,A.Structured a) -> GraphMaker mLabel mAlter label structType (Node, Node)
foldIf (prev,end) (ind,s) = do nodes <- buildStructured (OIf prev end) s $ decompSeveral @-> (routeList ind) foldIf (prev,end) (ind,s) = do nodes <- buildStructured f (OIf prev end) s $ decompSeveral @-> (routeList ind)
case nodes of case nodes of
Left {} -> return (prev,end) Left {} -> return (prev,end)
Right (prev',_) -> return (prev', end) Right (prev',_) -> return (prev', end)
_ -> do nodes <- mapMRE decompSeveral (buildStructured outer) ss _ -> do nodes <- mapMRE decompSeveral (buildStructured f outer) ss
return $ Left $ nonEmpty nodes return $ Left $ nonEmpty nodes
where where
decompSeveral :: ASTModifier mAlter [A.Structured] decompSeveral :: ASTModifier mAlter [A.Structured a] structType
decompSeveral = route22 route A.Several decompSeveral = route22 route A.Several
buildStructured _ (A.OnlyP _ p) route = buildProcess p (route22 route A.OnlyP) >>* Right buildStructured f outer (A.Spec m spec str) route
buildStructured outer (A.OnlyC _ (A.Choice m exp p)) route
= do nexp <- addNodeExpression (findMeta exp) exp $ route @-> (\f (A.OnlyC m (A.Choice m' exp p)) -> do {exp' <- f exp; return (A.OnlyC m (A.Choice m' exp' p))})
(nbodys, nbodye) <- buildProcess p $ route @-> (\f (A.OnlyC m (A.Choice m' exp p)) -> f p >>* ((A.OnlyC m) . (A.Choice m' exp)))
addEdge ESeq nexp nbodys
case outer of
OIf cPrev cEnd ->
do addEdge ESeq cPrev nexp
addEdge ESeq nbodye cEnd
_ -> throwError "Choice found outside IF statement"
return $ Right (nexp,nbodye)
buildStructured outer (A.OnlyO _ opt) route
= do (s,e) <-
case opt of
(A.Option m es p) -> do
buildProcess p $ route @-> (\f (A.OnlyO m (A.Option m2 es p)) -> f p >>* ((A.OnlyO m) . (A.Option m2 es)))
(A.Else _ p) -> buildProcess p $ route @-> (\f (A.OnlyO m (A.Else m2 p)) -> f p >>* ((A.OnlyO m) . (A.Else m2)))
case outer of
OCase (cStart, cEnd) ->
do addEdge ESeq cStart s
addEdge ESeq e cEnd
_ -> throwError "Option found outside CASE statement"
return $ Right (s,e)
buildStructured outer (A.Spec m spec str) route
= do n <- addNode' (findMeta spec) labelScopeIn spec (AlterSpec $ route23 route A.Spec) = do n <- addNode' (findMeta spec) labelScopeIn spec (AlterSpec $ route23 route A.Spec)
n' <- addNode' (findMeta spec) labelScopeOut spec (AlterSpec $ route23 route A.Spec) n' <- addNode' (findMeta spec) labelScopeOut spec (AlterSpec $ route23 route A.Spec)
@ -342,18 +340,18 @@ buildFlowGraph funcs s
outer' <- case outer of outer' <- case outer of
OPar {} -> getNextParEdgeId >>* flip OPar (n,n') OPar {} -> getNextParEdgeId >>* flip OPar (n,n')
_ -> return outer _ -> return outer
nodes <- buildStructured outer' str (route33 route A.Spec) nodes <- buildStructured f outer' str (route33 route A.Spec)
case nodes of case nodes of
Left False -> do addEdge ESeq n n' Left False -> do addEdge ESeq n n'
Left True -> return () Left True -> return ()
Right (s,e) -> do addEdge ESeq n s Right (s,e) -> do addEdge ESeq n s
addEdge ESeq e n' addEdge ESeq e n'
return $ Right (n,n') return $ Right (n,n')
buildStructured outer (A.Rep m rep str) route buildStructured f outer (A.Rep m rep str) route
= do let alter = AlterReplicator $ route23 route A.Rep = do let alter = AlterReplicator $ route23 route A.Rep
case outer of case outer of
OSeq -> do n <- addNode' (findMeta rep) labelReplicator rep alter OSeq -> do n <- addNode' (findMeta rep) labelReplicator rep alter
nodes <- buildStructured outer str (route33 route A.Rep) nodes <- buildStructured f outer str (route33 route A.Rep)
case nodes of case nodes of
Right (s,e) -> Right (s,e) ->
do addEdge ESeq n s do addEdge ESeq n s
@ -365,7 +363,7 @@ buildFlowGraph funcs s
do s <- addNode' (findMeta rep) labelReplicator rep alter do s <- addNode' (findMeta rep) labelReplicator rep alter
e <- addDummyNode m e <- addDummyNode m
pId <- getNextParEdgeId pId <- getNextParEdgeId
nodes <- buildStructured (OPar pId (s,e)) str (route33 route A.Rep) nodes <- buildStructured f (OPar pId (s,e)) str (route33 route A.Rep)
case nodes of case nodes of
Left False -> addEdge ESeq s e Left False -> addEdge ESeq s e
Left True -> return () Left True -> return ()
@ -374,25 +372,55 @@ buildFlowGraph funcs s
return $ Right (s,e) return $ Right (s,e)
_ -> throwError $ "Cannot have replicators inside context: " ++ show outer _ -> throwError $ "Cannot have replicators inside context: " ++ show outer
buildStructured _ s _ = return $ Left False buildStructured f outer (A.Only _ o) route = f outer (route22 route A.Only) o >>* Right
buildStructured _ _ s _ = return $ Left False
addNewSubProcFunc :: Meta -> [A.Formal] -> Either (A.Process, ASTModifier mAlter A.Process) (A.Structured, ASTModifier mAlter A.Structured) -> buildOnlyChoice outer route (A.Choice m exp p)
ASTModifier mAlter [A.Formal] -> GraphMaker mLabel mAlter label () = do nexp <- addNodeExpression (findMeta exp) exp $ route23 route A.Choice
(nbodys, nbodye) <- buildProcess p $ route33 route A.Choice
addEdge ESeq nexp nbodys
case outer of
OIf cPrev cEnd ->
do addEdge ESeq cPrev nexp
addEdge ESeq nbodye cEnd
_ -> throwError "Choice found outside IF statement"
return (nexp,nbodye)
buildOnlyOption outer route opt
= do (s,e) <-
case opt of
(A.Option m es p) -> do
nexpNodes <- mapMR (route23 route A.Option) (\e r -> addNodeExpression (findMeta e) e r >>* mkPair) es
(nexps, nexpe) <- joinPairs m nexpNodes
(nbodys, nbodye) <- buildProcess p $ route33 route A.Option
addEdge ESeq nexpe nbodys
return (nexps,nbodye)
(A.Else _ p) -> buildProcess p $ route22 route A.Else
case outer of
OCase (cStart, cEnd) ->
do addEdge ESeq cStart s
addEdge ESeq e cEnd
_ -> throwError "Option found outside CASE statement"
return (s,e)
addNewSubProcFunc :: Meta -> [A.Formal] -> Either (A.Process, ASTModifier mAlter A.Process structType) (A.Structured A.ExpressionList, ASTModifier mAlter (A.Structured A.ExpressionList) structType) ->
ASTModifier mAlter [A.Formal] structType -> GraphMaker mLabel mAlter label structType ()
addNewSubProcFunc m args body argsRoute addNewSubProcFunc m args body argsRoute
= do root <- addNode' m labelStartNode (m, args) (AlterArguments argsRoute) = do root <- addNode' m labelStartNode (m, args) (AlterArguments argsRoute)
denoteRootNode root denoteRootNode root
bodyNode <- case body of bodyNode <- case body of
Left (p,route) -> buildProcess p route >>* fst Left (p,route) -> buildProcess p route >>* fst
Right (s,route) -> Right (s,route) ->
do s <- buildStructured ONone s route do s <- buildStructured (buildEL m) ONone s route
case s of case s of
Left {} -> throwError $ show m ++ " Expected VALOF or specification at top-level of function when building flow-graph" Left {} -> throwError $ show m ++ " Expected VALOF or specification at top-level of function when building flow-graph"
Right (n,_) -> return n Right (n,_) -> return n
addEdge ESeq root bodyNode addEdge ESeq root bodyNode
where
buildEL m _ r el = addNodeExpressionList m el r >>* mkPair
buildProcess :: A.Process -> ASTModifier mAlter A.Process -> GraphMaker mLabel mAlter label (Node, Node) buildProcess :: A.Process -> ASTModifier mAlter A.Process structType -> GraphMaker mLabel mAlter label structType (Node, Node)
buildProcess (A.Seq m s) route buildProcess (A.Seq m s) route
= do s <- buildStructured OSeq s (route22 route A.Seq) = do s <- buildStructuredP OSeq s (route22 route A.Seq)
case s of case s of
Left True -> throwError $ show m ++ " SEQ had non-joined up body when building flow-graph" Left True -> throwError $ show m ++ " SEQ had non-joined up body when building flow-graph"
Left False -> do n <- addDummyNode m Left False -> do n <- addDummyNode m
@ -402,7 +430,7 @@ buildFlowGraph funcs s
= do nStart <- addDummyNode m = do nStart <- addDummyNode m
nEnd <- addDummyNode m nEnd <- addDummyNode m
pId <- getNextParEdgeId pId <- getNextParEdgeId
nodes <- buildStructured (OPar pId (nStart, nEnd)) s (route33 route A.Par) nodes <- buildStructuredP (OPar pId (nStart, nEnd)) s (route33 route A.Par)
case nodes of case nodes of
Left False -> do addEdge ESeq nStart nEnd -- no processes in PAR, join start and end with simple ESeq link Left False -> do addEdge ESeq nStart nEnd -- no processes in PAR, join start and end with simple ESeq link
Left True -> return () -- already wired up Left True -> return () -- already wired up
@ -419,12 +447,12 @@ buildFlowGraph funcs s
buildProcess (A.Case m e s) route buildProcess (A.Case m e s) route
= do nStart <- addNodeExpression (findMeta e) e (route23 route A.Case) = do nStart <- addNodeExpression (findMeta e) e (route23 route A.Case)
nEnd <- addDummyNode m nEnd <- addDummyNode m
buildStructured (OCase (nStart,nEnd)) s (route33 route A.Case) buildStructuredO (OCase (nStart,nEnd)) s (route33 route A.Case)
return (nStart, nEnd) return (nStart, nEnd)
buildProcess (A.If m s) route buildProcess (A.If m s) route
= do nStart <- addDummyNode m = do nStart <- addDummyNode m
nEnd <- addDummyNode m nEnd <- addDummyNode m
buildStructured (OIf nStart nEnd) s (route22 route A.If) buildStructuredC (OIf nStart nEnd) s (route22 route A.If)
return (nStart, nEnd) return (nStart, nEnd)
buildProcess p route = addNode' (findMeta p) labelProcess p (AlterProcess route) >>* mkPair buildProcess p route = addNode' (findMeta p) labelProcess p (AlterProcess route) >>* mkPair
@ -453,27 +481,27 @@ decomp55 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3
(a0 -> a1 -> a2 -> a3 -> a4 -> a) -> (a4 -> m a4) -> (a -> m a) (a0 -> a1 -> a2 -> a3 -> a4 -> a) -> (a4 -> m a4) -> (a -> m a)
decomp55 con f4 = decomp5 con return return return return f4 decomp55 con f4 = decomp5 con return return return return f4
route22 :: (Monad m, Data a, Typeable a0, Typeable a1) => ASTModifier m a -> (a0 -> a1 -> a) -> ASTModifier m a1 route22 :: (Monad m, Data a, Typeable a0, Typeable a1) => ASTModifier m a b -> (a0 -> a1 -> a) -> ASTModifier m a1 b
route22 route con = route @-> (decomp22 con) route22 route con = route @-> (decomp22 con)
route23 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2) => ASTModifier m a -> (a0 -> a1 -> a2 -> a) -> ASTModifier m a1 route23 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2) => ASTModifier m a b -> (a0 -> a1 -> a2 -> a) -> ASTModifier m a1 b
route23 route con = route @-> (decomp23 con) route23 route con = route @-> (decomp23 con)
route33 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2) => ASTModifier m a -> (a0 -> a1 -> a2 -> a) -> ASTModifier m a2 route33 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2) => ASTModifier m a b -> (a0 -> a1 -> a2 -> a) -> ASTModifier m a2 b
route33 route con = route @-> (decomp33 con) route33 route con = route @-> (decomp33 con)
route34 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3) => route34 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3) =>
ASTModifier m a -> (a0 -> a1 -> a2 -> a3 -> a) -> ASTModifier m a2 ASTModifier m a b -> (a0 -> a1 -> a2 -> a3 -> a) -> ASTModifier m a2 b
route34 route con = route @-> (decomp34 con) route34 route con = route @-> (decomp34 con)
route44 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3) => route44 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3) =>
ASTModifier m a -> (a0 -> a1 -> a2 -> a3 -> a) -> ASTModifier m a3 ASTModifier m a b -> (a0 -> a1 -> a2 -> a3 -> a) -> ASTModifier m a3 b
route44 route con = route @-> (decomp44 con) route44 route con = route @-> (decomp44 con)
route45 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3, Typeable a4) => route45 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3, Typeable a4) =>
ASTModifier m a -> (a0 -> a1 -> a2 -> a3 -> a4 -> a) -> ASTModifier m a3 ASTModifier m a b -> (a0 -> a1 -> a2 -> a3 -> a4 -> a) -> ASTModifier m a3 b
route45 route con = route @-> (decomp45 con) route45 route con = route @-> (decomp45 con)
route55 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3, Typeable a4) => route55 :: (Monad m, Data a, Typeable a0, Typeable a1, Typeable a2, Typeable a3, Typeable a4) =>
ASTModifier m a -> (a0 -> a1 -> a2 -> a3 -> a4 -> a) -> ASTModifier m a4 ASTModifier m a b -> (a0 -> a1 -> a2 -> a3 -> a4 -> a) -> ASTModifier m a4 b
route55 route con = route @-> (decomp55 con) route55 route con = route @-> (decomp55 con)

View File

@ -105,27 +105,27 @@ nextId' inc t
-- for being isomorphic, based on the meta-tag node labels (node E in the expected list is -- for being isomorphic, based on the meta-tag node labels (node E in the expected list is
-- isomorphic to node A in the actual list if their meta tags are the same). -- isomorphic to node A in the actual list if their meta tags are the same).
testGraph :: String -> [(Int, Meta)] -> [Int] -> [(Int, Int, EdgeLabel)] -> A.Process -> Test testGraph :: String -> [(Int, Meta)] -> [Int] -> [(Int, Int, EdgeLabel)] -> A.Process -> Test
testGraph testName nodes roots edges proc = testGraph' testName nodes roots edges (A.OnlyP emptyMeta proc) testGraph testName nodes roots edges proc = testGraph' testName nodes roots edges (A.Only emptyMeta proc)
--TODO test root nodes too --TODO test root nodes too
testGraph' :: String -> [(Int, Meta)] -> [Int] -> [(Int, Int, EdgeLabel)] -> A.Structured -> Test testGraph' :: String -> [(Int, Meta)] -> [Int] -> [(Int, Int, EdgeLabel)] -> A.Structured A.Process -> Test
testGraph' testName nodes roots edges code testGraph' testName nodes roots edges code
= TestCase $ = TestCase $
case evalState (buildFlowGraph testOps code) Map.empty of case evalState (buildFlowGraph testOps code) Map.empty of
Left err -> assertFailure (testName ++ " graph building failed: " ++ err) Left err -> assertFailure (testName ++ " graph building failed: " ++ err)
Right gr -> checkGraphEquality (nodes, roots, edges) (gr :: (FlowGraph Identity Int, [Node])) Right gr -> checkGraphEquality (nodes, roots, edges) (gr :: (FlowGraph' Identity Int A.Process, [Node]))
where where
-- Checks two graphs are equal by creating a node mapping from the expected graph to the real map (checkNodeEquality), -- Checks two graphs are equal by creating a node mapping from the expected graph to the real map (checkNodeEquality),
-- then mapping the edges across (transformEdge) and checking everything is right (in checkGraphEquality) -- then mapping the edges across (transformEdge) and checking everything is right (in checkGraphEquality)
deNode :: Monad m => FNode m a -> (Meta, a) -- deNode :: Monad m => FNode' m a b -> (Meta, a)
deNode (Node (x,y,_)) = (x,y) deNode nd = (getNodeMeta nd, getNodeData nd)
testOps :: GraphLabelFuncs (State (Map.Map Meta Int)) Int testOps :: GraphLabelFuncs (State (Map.Map Meta Int)) Int
testOps = GLF nextId nextId nextId nextId nextId nextId (nextId' 100) (nextId' 100) testOps = GLF nextId nextId nextId nextId nextId nextId (nextId' 100) (nextId' 100)
checkGraphEquality :: (Graph g, Show b, Ord b, Monad m) => ([(Int, Meta)], [Int], [(Int, Int, b)]) -> (g (FNode m Int) b, [Int]) -> Assertion checkGraphEquality :: (Data a, Monad m) => ([(Int, Meta)], [Int], [(Int, Int, EdgeLabel)]) -> (FlowGraph' m Int a, [Int]) -> Assertion
checkGraphEquality (nodes, roots, edges) (g, actRoots) checkGraphEquality (nodes, roots, edges) (g, actRoots)
= do let (remainingNodes, nodeLookup, ass) = foldl checkNodeEquality (Map.fromList (map revPair nodes),Map.empty, return ()) (map (transformPair id deNode) $ labNodes g) = do let (remainingNodes, nodeLookup, ass) = foldl checkNodeEquality (Map.fromList (map revPair nodes),Map.empty, return ()) (map (transformPair id deNode) $ labNodes g)
ass ass
@ -162,74 +162,74 @@ testSeq :: Test
testSeq = TestLabel "testSeq" $ TestList testSeq = TestLabel "testSeq" $ TestList
[ [
testSeq' 0 [(0,m0)] [] (A.Several m1 []) testSeq' 0 [(0,m0)] [] (A.Several m1 [])
,testSeq' 1 [(0,m2)] [] (A.OnlyP m1 sm2) ,testSeq' 1 [(0,m2)] [] (A.Only m1 sm2)
,testSeq' 2 [(0,m3)] [] (A.Several m1 [A.OnlyP m2 sm3]) ,testSeq' 2 [(0,m3)] [] (A.Several m1 [A.Only m2 sm3])
,testSeq' 3 [(0,m3),(1,m5)] [(0,1,ESeq)] (A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5]) ,testSeq' 3 [(0,m3),(1,m5)] [(0,1,ESeq)] (A.Several m1 [A.Only m2 sm3,A.Only m4 sm5])
,testSeq' 4 [(0,m3),(1,m5),(2,m7)] [(0,1,ESeq),(1,2,ESeq)] (A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5,A.OnlyP m6 sm7]) ,testSeq' 4 [(0,m3),(1,m5),(2,m7)] [(0,1,ESeq),(1,2,ESeq)] (A.Several m1 [A.Only m2 sm3,A.Only m4 sm5,A.Only m6 sm7])
,testSeq' 5 [(0,m3),(1,m5)] [(0,1,ESeq)] (A.Several m1 [A.Several m1 [A.OnlyP m2 sm3],A.Several m1 [A.OnlyP m4 sm5]]) ,testSeq' 5 [(0,m3),(1,m5)] [(0,1,ESeq)] (A.Several m1 [A.Several m1 [A.Only m2 sm3],A.Several m1 [A.Only m4 sm5]])
,testSeq' 6 [(0,m3),(1,m5),(2,m7),(3,m9)] [(0,1,ESeq),(1,2,ESeq),(2,3,ESeq)] ,testSeq' 6 [(0,m3),(1,m5),(2,m7),(3,m9)] [(0,1,ESeq),(1,2,ESeq),(2,3,ESeq)]
(A.Several m1 [A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5,A.OnlyP m6 sm7], A.OnlyP m8 sm9]) (A.Several m1 [A.Several m1 [A.Only m2 sm3,A.Only m4 sm5,A.Only m6 sm7], A.Only m8 sm9])
,testSeq' 10 [(0,m1),(1,m4),(100,sub m1 100)] [(0,1,ESeq),(1,100,ESeq)] (A.Spec mU (someSpec m1) $ A.OnlyP m3 sm4) ,testSeq' 10 [(0,m1),(1,m4),(100,sub m1 100)] [(0,1,ESeq),(1,100,ESeq)] (A.Spec mU (someSpec m1) $ A.Only m3 sm4)
,testSeq'' 11 ,testSeq'' 11
[(1,m1),(3,m4),(5,m5),(7,m7),(9,m10),(101,sub m1 100),(105,sub m5 100),(107,sub m7 100)] [1] [(1,m1),(3,m4),(5,m5),(7,m7),(9,m10),(101,sub m1 100),(105,sub m5 100),(107,sub m7 100)] [1]
[(1,3,ESeq),(3,101,ESeq),(101,5,ESeq),(5,7,ESeq),(7,9,ESeq),(9,107,ESeq),(107,105,ESeq)] [(1,3,ESeq),(3,101,ESeq),(101,5,ESeq),(5,7,ESeq),(7,9,ESeq),(9,107,ESeq),(107,105,ESeq)]
(A.Several m11 [A.Spec mU (someSpec m1) $ A.OnlyP m3 sm4,A.Spec mU (someSpec m5) $ A.Spec mU (someSpec m7) $ A.OnlyP m9 sm10]) (A.Several m11 [A.Spec mU (someSpec m1) $ A.Only m3 sm4,A.Spec mU (someSpec m5) $ A.Spec mU (someSpec m7) $ A.Only m9 sm10])
,testSeq' 12 [(0,m1),(100,sub m1 100)] [(0,100,ESeq)] (A.Spec mU (someSpec m1) $ A.Several m4 []) ,testSeq' 12 [(0,m1),(100,sub m1 100)] [(0,100,ESeq)] (A.Spec mU (someSpec m1) $ A.Several m4 [])
-- Replicated SEQ: -- Replicated SEQ:
,testSeq' 100 [(0,m10), (1,m3), (2,m5)] [(0,1,ESeq), (1,2,ESeq), (2,0,ESeq)] ,testSeq' 100 [(0,m10), (1,m3), (2,m5)] [(0,1,ESeq), (1,2,ESeq), (2,0,ESeq)]
(A.Rep m10 (A.For m10 undefined undefined undefined) $ A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5]) (A.Rep m10 (A.For m10 undefined undefined undefined) $ A.Several m1 [A.Only m2 sm3,A.Only m4 sm5])
,testSeq'' 101 [(0,m8), (1,m3), (2,m5),(3,m9),(4,m11)] [3] [(3,0,ESeq),(0,1,ESeq), (1,2,ESeq), (2,0,ESeq),(0,4,ESeq)] ,testSeq'' 101 [(0,m8), (1,m3), (2,m5),(3,m9),(4,m11)] [3] [(3,0,ESeq),(0,1,ESeq), (1,2,ESeq), (2,0,ESeq),(0,4,ESeq)]
(A.OnlyP mU $ A.Seq m6 $ A.Several m7 (A.Only mU $ A.Seq m6 $ A.Several m7
[A.OnlyP mU sm9 [A.Only mU sm9
,(A.Rep m8 (A.For m8 undefined undefined undefined) $ A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5]) ,(A.Rep m8 (A.For m8 undefined undefined undefined) $ A.Several m1 [A.Only m2 sm3,A.Only m4 sm5])
,A.OnlyP mU sm11]) ,A.Only mU sm11])
,testSeq' 102 [(0,m10)] [(0,0,ESeq)] ,testSeq' 102 [(0,m10)] [(0,0,ESeq)]
(A.Rep m10 (A.For m10 undefined undefined undefined) $ A.Several mU []) (A.Rep m10 (A.For m10 undefined undefined undefined) $ A.Several mU [])
,testSeq' 103 [(1,m10), (0,m1), (2,m2)] [(0,1,ESeq),(1,1,ESeq),(1,2,ESeq)] ,testSeq' 103 [(1,m10), (0,m1), (2,m2)] [(0,1,ESeq),(1,1,ESeq),(1,2,ESeq)]
(A.Several mU [A.OnlyP mU sm1, (A.Rep m10 (A.For m10 undefined undefined undefined) $ A.Several mU []), A.OnlyP mU sm2]) (A.Several mU [A.Only mU sm1, (A.Rep m10 (A.For m10 undefined undefined undefined) $ A.Several mU []), A.Only mU sm2])
] ]
where where
testSeq' :: Int -> [(Int, Meta)] -> [(Int, Int, EdgeLabel)] -> A.Structured -> Test testSeq' :: Int -> [(Int, Meta)] -> [(Int, Int, EdgeLabel)] -> A.Structured A.Process -> Test
testSeq' n a b s = testSeq'' n a [0] b s testSeq' n a b s = testSeq'' n a [0] b s
testSeq'' :: Int -> [(Int, Meta)] -> [Int] -> [(Int, Int, EdgeLabel)] -> A.Structured -> Test testSeq'' :: Int -> [(Int, Meta)] -> [Int] -> [(Int, Int, EdgeLabel)] -> A.Structured A.Process -> Test
testSeq'' n a r b s = testGraph ("testSeq " ++ show n) a r b (A.Seq m0 s) testSeq'' n a r b s = testGraph ("testSeq " ++ show n) a r b (A.Seq m0 s)
testPar :: Test testPar :: Test
testPar = TestLabel "testPar" $ TestList testPar = TestLabel "testPar" $ TestList
[ [
testPar' 0 [] [(0,99,ESeq)] (A.Several m1 []) testPar' 0 [] [(0,99,ESeq)] (A.Several m1 [])
,testPar' 1 [(1,m2)] [(0,1,EStartPar 0), (1,99,EEndPar 0)] (A.OnlyP m1 sm2) ,testPar' 1 [(1,m2)] [(0,1,EStartPar 0), (1,99,EEndPar 0)] (A.Only m1 sm2)
,testPar' 2 [(1,m3)] [(0,1,EStartPar 0), (1,99,EEndPar 0)] (A.Several m1 [A.OnlyP m2 sm3]) ,testPar' 2 [(1,m3)] [(0,1,EStartPar 0), (1,99,EEndPar 0)] (A.Several m1 [A.Only m2 sm3])
,testPar' 3 [(1, m3), (2, m5)] ,testPar' 3 [(1, m3), (2, m5)]
[(0,1,EStartPar 0),(1,99,EEndPar 0), (0,2,EStartPar 0), (2,99,EEndPar 0)] [(0,1,EStartPar 0),(1,99,EEndPar 0), (0,2,EStartPar 0), (2,99,EEndPar 0)]
(A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5]) (A.Several m1 [A.Only m2 sm3,A.Only m4 sm5])
,testPar' 4 [(3,m3),(5,m5),(7,m7)] ,testPar' 4 [(3,m3),(5,m5),(7,m7)]
[(0,3,EStartPar 0),(3,99,EEndPar 0),(0,5,EStartPar 0),(5,99,EEndPar 0),(0,7,EStartPar 0),(7,99,EEndPar 0)] [(0,3,EStartPar 0),(3,99,EEndPar 0),(0,5,EStartPar 0),(5,99,EEndPar 0),(0,7,EStartPar 0),(7,99,EEndPar 0)]
(A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5,A.OnlyP m6 sm7]) (A.Several m1 [A.Only m2 sm3,A.Only m4 sm5,A.Only m6 sm7])
,testPar' 5 [(1, m3), (2, m5)] ,testPar' 5 [(1, m3), (2, m5)]
[(0,1,EStartPar 0),(1,99,EEndPar 0), (0,2,EStartPar 0), (2,99,EEndPar 0)] [(0,1,EStartPar 0),(1,99,EEndPar 0), (0,2,EStartPar 0), (2,99,EEndPar 0)]
(A.Several mU [A.Several mU [A.OnlyP m2 sm3],A.Several mU [A.OnlyP m4 sm5]]) (A.Several mU [A.Several mU [A.Only m2 sm3],A.Several mU [A.Only m4 sm5]])
,testPar' 6 [(3,m3),(5,m5),(7,m7),(9,m9)] ,testPar' 6 [(3,m3),(5,m5),(7,m7),(9,m9)]
[(0,3,EStartPar 0), (0,5,EStartPar 0), (0,7,EStartPar 0), (0,9,EStartPar 0) [(0,3,EStartPar 0), (0,5,EStartPar 0), (0,7,EStartPar 0), (0,9,EStartPar 0)
,(3,99,EEndPar 0), (5,99,EEndPar 0), (7,99,EEndPar 0), (9,99,EEndPar 0)] ,(3,99,EEndPar 0), (5,99,EEndPar 0), (7,99,EEndPar 0), (9,99,EEndPar 0)]
(A.Several m1 [A.Several m10 [A.OnlyP m2 sm3,A.OnlyP m4 sm5,A.OnlyP m6 sm7], A.OnlyP m8 sm9]) (A.Several m1 [A.Several m10 [A.Only m2 sm3,A.Only m4 sm5,A.Only m6 sm7], A.Only m8 sm9])
,testPar' 10 [(1, m3), (2, m5), (6, m6),(106,sub m6 100)] ,testPar' 10 [(1, m3), (2, m5), (6, m6),(106,sub m6 100)]
[(0,6,EStartPar 0),(6,1,ESeq),(1,106,ESeq),(106,99,EEndPar 0), (0,2,EStartPar 0), (2,99,EEndPar 0)] [(0,6,EStartPar 0),(6,1,ESeq),(1,106,ESeq),(106,99,EEndPar 0), (0,2,EStartPar 0), (2,99,EEndPar 0)]
(A.Several m1 [A.Spec mU (someSpec m6) $ A.OnlyP m2 sm3,A.OnlyP m4 sm5]) (A.Several m1 [A.Spec mU (someSpec m6) $ A.Only m2 sm3,A.Only m4 sm5])
,testPar' 11 [(1, m3), (2, m5), (3,m7), (6, m6),(106,sub m6 100)] ,testPar' 11 [(1, m3), (2, m5), (3,m7), (6, m6),(106,sub m6 100)]
[(0,6,EStartPar 0),(6,1,EStartPar 1),(6,2,EStartPar 1),(1,106,EEndPar 1),(2,106,EEndPar 1) [(0,6,EStartPar 0),(6,1,EStartPar 1),(6,2,EStartPar 1),(1,106,EEndPar 1),(2,106,EEndPar 1)
,(106,99,EEndPar 0), (0,3,EStartPar 0), (3,99,EEndPar 0)] ,(106,99,EEndPar 0), (0,3,EStartPar 0), (3,99,EEndPar 0)]
(A.Several m1 [A.Spec mU (someSpec m6) $ A.Several mU [A.OnlyP mU sm3, A.OnlyP mU sm5], A.OnlyP mU sm7]) (A.Several m1 [A.Spec mU (someSpec m6) $ A.Several mU [A.Only mU sm3, A.Only mU sm5], A.Only mU sm7])
,testPar' 20 [(1,m1),(100,sub m1 100)] [(0,1,EStartPar 0),(1,100,ESeq),(100,99,EEndPar 0)] (A.Spec mU (someSpec m1) $ A.Several m4 []) ,testPar' 20 [(1,m1),(100,sub m1 100)] [(0,1,EStartPar 0),(1,100,ESeq),(100,99,EEndPar 0)] (A.Spec mU (someSpec m1) $ A.Several m4 [])
@ -240,7 +240,7 @@ testPar = TestLabel "testPar" $ TestList
,testPar' 100 [(1,m6), (2,m3), (3,m5), (4, sub m6 1)] ,testPar' 100 [(1,m6), (2,m3), (3,m5), (4, sub m6 1)]
[(0,1,EStartPar 0), (1,2,EStartPar 1), (2,4,EEndPar 1), (1,3,EStartPar 1), (3,4,EEndPar 1), (4,99,EEndPar 0)] [(0,1,EStartPar 0), (1,2,EStartPar 1), (2,4,EEndPar 1), (1,3,EStartPar 1), (3,4,EEndPar 1), (4,99,EEndPar 0)]
(A.Rep m6 (A.For m6 undefined undefined undefined) $ A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5]) (A.Rep m6 (A.For m6 undefined undefined undefined) $ A.Several m1 [A.Only m2 sm3,A.Only m4 sm5])
,testPar' 101 [(1,m1), (2,m2), (3,m3), (11,sub m1 1), (4,m4), (5,m5), (6,m6), (7,m7), (15, sub m5 1)] ,testPar' 101 [(1,m1), (2,m2), (3,m3), (11,sub m1 1), (4,m4), (5,m5), (6,m6), (7,m7), (15, sub m5 1)]
-- The links in the main PAR: -- The links in the main PAR:
@ -251,16 +251,16 @@ testPar = TestLabel "testPar" $ TestList
,(5,6,EStartPar 2), (6,15,EEndPar 2), (5,7,EStartPar 2), (7,15,EEndPar 2)] ,(5,6,EStartPar 2), (6,15,EEndPar 2), (5,7,EStartPar 2), (7,15,EEndPar 2)]
(A.Several mU (A.Several mU
[(A.Rep m1 (A.For m1 undefined undefined undefined) $ A.Several mU [A.OnlyP mU sm2,A.OnlyP mU sm3]) [(A.Rep m1 (A.For m1 undefined undefined undefined) $ A.Several mU [A.Only mU sm2,A.Only mU sm3])
,A.OnlyP mU sm4 ,A.Only mU sm4
,(A.Rep m5 (A.For m5 undefined undefined undefined) $ A.Several mU [A.OnlyP mU sm6,A.OnlyP mU sm7])]) ,(A.Rep m5 (A.For m5 undefined undefined undefined) $ A.Several mU [A.Only mU sm6,A.Only mU sm7])])
,testPar' 102 [(1,m6), (4, sub m6 1)] ,testPar' 102 [(1,m6), (4, sub m6 1)]
[(0,1,EStartPar 0), (1,4,ESeq), (4,99,EEndPar 0)] [(0,1,EStartPar 0), (1,4,ESeq), (4,99,EEndPar 0)]
(A.Rep m6 (A.For m6 undefined undefined undefined) $ A.Several mU []) (A.Rep m6 (A.For m6 undefined undefined undefined) $ A.Several mU [])
] ]
where where
testPar' :: Int -> [(Int, Meta)] -> [(Int, Int, EdgeLabel)] -> A.Structured -> Test testPar' :: Int -> [(Int, Meta)] -> [(Int, Int, EdgeLabel)] -> A.Structured A.Process -> Test
testPar' n a b s = testGraph ("testPar " ++ show n) (a ++ [(0,m0), (99,sub m0 1)]) [0] b (A.Par m0 A.PlainPar s) testPar' n a b s = testGraph ("testPar " ++ show n) (a ++ [(0,m0), (99,sub m0 1)]) [0] b (A.Par m0 A.PlainPar s)
testWhile :: Test testWhile :: Test
@ -268,11 +268,11 @@ testWhile = TestLabel "testWhile" $ TestList
[ [
testGraph "testWhile 0" [(0,m0), (1,m1)] [0] [(0,1,ESeq), (1,0,ESeq)] (A.While mU (A.True m0) sm1) testGraph "testWhile 0" [(0,m0), (1,m1)] [0] [(0,1,ESeq), (1,0,ESeq)] (A.While mU (A.True m0) sm1)
,testGraph "testWhile 1" [(2,m2), (3, m3), (5, m5)] [2] [(2,3,ESeq), (3,2,ESeq), (2,5,ESeq)] ,testGraph "testWhile 1" [(2,m2), (3, m3), (5, m5)] [2] [(2,3,ESeq), (3,2,ESeq), (2,5,ESeq)]
(A.Seq m0 $ A.Several m1 [A.OnlyP m9 $ A.While mU (A.True m2) sm3,A.OnlyP m4 sm5]) (A.Seq m0 $ A.Several m1 [A.Only m9 $ A.While mU (A.True m2) sm3,A.Only m4 sm5])
,testGraph "testWhile 2" [(2,m2), (3, m3), (5, m5), (7, m7)] [7] [(7,2,ESeq), (2,3,ESeq), (3,2,ESeq), (2,5,ESeq)] ,testGraph "testWhile 2" [(2,m2), (3, m3), (5, m5), (7, m7)] [7] [(7,2,ESeq), (2,3,ESeq), (3,2,ESeq), (2,5,ESeq)]
(A.Seq m0 $ A.Several m1 [A.OnlyP m6 sm7,A.OnlyP m9 $ A.While mU (A.True m2) sm3,A.OnlyP m4 sm5]) (A.Seq m0 $ A.Several m1 [A.Only m6 sm7,A.Only m9 $ A.While mU (A.True m2) sm3,A.Only m4 sm5])
,testGraph "testWhile 3" [(2,m2), (3, m3), (5, m5), (7, m7), (9, m9)] [7] [(7,2,ESeq), (2,3,ESeq), (3,9,ESeq), (9,2,ESeq), (2,5,ESeq)] ,testGraph "testWhile 3" [(2,m2), (3, m3), (5, m5), (7, m7), (9, m9)] [7] [(7,2,ESeq), (2,3,ESeq), (3,9,ESeq), (9,2,ESeq), (2,5,ESeq)]
(A.Seq m0 $ A.Several m1 [A.OnlyP m6 sm7,A.OnlyP mU $ A.While mU (A.True m2) $ A.Seq mU $ A.Several mU [A.OnlyP mU sm3,A.OnlyP mU sm9],A.OnlyP m4 sm5]) (A.Seq m0 $ A.Several m1 [A.Only m6 sm7,A.Only mU $ A.While mU (A.True m2) $ A.Seq mU $ A.Several mU [A.Only mU sm3,A.Only mU sm9],A.Only m4 sm5])
] ]
testCase :: Test testCase :: Test
@ -290,8 +290,8 @@ testCase = TestLabel "testCase" $ TestList
--TODO test case statements that have specs --TODO test case statements that have specs
] ]
where where
cases :: Meta -> [A.Option] -> A.Structured cases :: Meta -> [A.Option] -> A.Structured A.Option
cases m = (A.Several m) . (map (A.OnlyO mU)) cases m = (A.Several m) . (map (A.Only mU))
testIf :: Test testIf :: Test
testIf = TestLabel "testIf" $ TestList testIf = TestLabel "testIf" $ TestList
@ -306,8 +306,8 @@ testIf = TestLabel "testIf" $ TestList
(A.If m0 $ ifs mU [(A.True m2, sm3), (A.True m4, sm5), (A.True m6, sm7)]) (A.If m0 $ ifs mU [(A.True m2, sm3), (A.True m4, sm5), (A.True m6, sm7)])
] ]
where where
ifs :: Meta -> [(A.Expression, A.Process)] -> A.Structured ifs :: Meta -> [(A.Expression, A.Process)] -> A.Structured A.Choice
ifs m = (A.Several m) . (map (\(e,p) -> A.OnlyC mU $ A.Choice (findMeta e) e p)) ifs m = (A.Several m) . (map (\(e,p) -> A.Only mU $ A.Choice (findMeta e) e p))
testProcFuncSpec :: Test testProcFuncSpec :: Test
testProcFuncSpec = TestLabel "testProcFuncSpec" $ TestList testProcFuncSpec = TestLabel "testProcFuncSpec" $ TestList
@ -318,16 +318,16 @@ testProcFuncSpec = TestLabel "testProcFuncSpec" $ TestList
-- Single spec of process (with body with SEQ SKIP SKIP): -- Single spec of process (with body with SEQ SKIP SKIP):
,testGraph' "testProcFuncSpec 1" [(0, m3),(1,m6),(2,sub m6 100),(4,m5), (9,m9)] [1,9] ([(1,2,ESeq)] ++ [(9,0,ESeq), (0,4,ESeq)]) ,testGraph' "testProcFuncSpec 1" [(0, m3),(1,m6),(2,sub m6 100),(4,m5), (9,m9)] [1,9] ([(1,2,ESeq)] ++ [(9,0,ESeq), (0,4,ESeq)])
(A.Spec mU (A.Specification m6 undefined $ A.Proc m9 undefined undefined $ (A.Spec mU (A.Specification m6 undefined $ A.Proc m9 undefined undefined $
A.Seq m0 $ A.Several m1 [A.OnlyP m2 sm3,A.OnlyP m4 sm5] A.Seq m0 $ A.Several m1 [A.Only m2 sm3,A.Only m4 sm5]
) $ A.Several mU []) ) $ A.Several mU [])
-- Nested spec of process (with bodies with SEQ SKIP SKIP): -- Nested spec of process (with bodies with SEQ SKIP SKIP):
,testGraph' "testProcFuncSpec 2" [(0,m6),(1,sub m6 100),(3,m2),(4,m3),(5,m4),(6,m5),(7,m7),(8,sub m7 100), (10,m10), (11, m11)] [0,10,11] ,testGraph' "testProcFuncSpec 2" [(0,m6),(1,sub m6 100),(3,m2),(4,m3),(5,m4),(6,m5),(7,m7),(8,sub m7 100), (10,m10), (11, m11)] [0,10,11]
([(0,7,ESeq), (7,8,ESeq), (8,1,ESeq)] ++ [(10,3,ESeq), (3,4,ESeq)] ++ [(11,5,ESeq), (5,6,ESeq)]) ([(0,7,ESeq), (7,8,ESeq), (8,1,ESeq)] ++ [(10,3,ESeq), (3,4,ESeq)] ++ [(11,5,ESeq), (5,6,ESeq)])
(A.Spec mU (A.Specification m6 undefined $ A.Proc m10 undefined undefined $ (A.Spec mU (A.Specification m6 undefined $ A.Proc m10 undefined undefined $
A.Seq mU $ A.Several mU [A.OnlyP mU sm2,A.OnlyP mU sm3] A.Seq mU $ A.Several mU [A.Only mU sm2,A.Only mU sm3]
) $ ) $
A.Spec mU (A.Specification m7 undefined $ A.Proc m11 undefined undefined $ A.Spec mU (A.Specification m7 undefined $ A.Proc m11 undefined undefined $
A.Seq mU $ A.Several mU [A.OnlyP mU sm4,A.OnlyP mU sm5] A.Seq mU $ A.Several mU [A.Only mU sm4,A.Only mU sm5]
) )
$ A.Several mU []) $ A.Several mU [])
] ]
@ -528,27 +528,6 @@ sub3 x = x-3
-- (such as for A.Alternative) you need to take account of this in its parent items, and bump -- (such as for A.Alternative) you need to take account of this in its parent items, and bump
-- up the required size for them accordingly. -- up the required size for them accordingly.
-- | A type that indicates which of the OnlyX items are allowed in a given A.Structured.
-- This is to avoid generating, for example, A.If with A.OnlyA things inside them.
data OnlyAllowed = OA {
onlyP :: Bool
,onlyO :: Bool
,onlyC :: Bool
,onlyA :: Bool
}
nothing = OA False False False False
justP = nothing {onlyP = True}
justO = nothing {onlyO = True}
justC = nothing {onlyC = True}
justA = nothing {onlyA = True}
-- | Slightly cheaty way of easily masking out items:
cond :: Bool -> (Int, a) -> (Int, a)
cond True = id
cond False = const (1000000, undefined)
-- | Generates a simple expression (A.True m). -- | Generates a simple expression (A.True m).
genExpression :: GenL A.Expression genExpression :: GenL A.Expression
genExpression = nextIdT >>* makeMeta' >>= genElem1 A.True genExpression = nextIdT >>* makeMeta' >>= genElem1 A.True
@ -564,6 +543,9 @@ genAlternative n = nextIdT >>* makeMeta' >>= \m -> (flip oneofLS) n
(3, genElem3 A.AlternativeSkip m genExpression . genProcess . sub2) (3, genElem3 A.AlternativeSkip m genExpression . genProcess . sub2)
] ]
genAlternative' :: (Int, Int -> GenL A.Alternative)
genAlternative' = (3, genAlternative)
-- | Generates a A.Specification. -- | Generates a A.Specification.
genSpecification :: GenL A.Specification genSpecification :: GenL A.Specification
genSpecification = nextIdT >>* makeMeta' >>= \m -> genElem3 A.Specification m (comb0 $ simpleName "x") genSpecType genSpecification = nextIdT >>* makeMeta' >>= \m -> genElem3 A.Specification m (comb0 $ simpleName "x") genSpecType
@ -577,27 +559,48 @@ genSpecification = nextIdT >>* makeMeta' >>= \m -> genElem3 A.Specification m (c
--TODO proc and function declaration --TODO proc and function declaration
] ]
genChoice :: Int -> GenL A.Choice
genChoice n = nextIdT >>* makeMeta' >>= \m -> (comb2 (\e p -> A.Choice emptyMeta e p) genExpression . genProcess . sub2) n
genChoice' :: (Int, Int -> GenL A.Choice)
genChoice' = (3, genChoice)
genOption :: Int -> GenL A.Option
genOption = comb1 (A.Else emptyMeta) . genProcess . sub1
genOption' :: (Int, Int -> GenL A.Option)
genOption' = (1, genOption)
genReplicator :: GenL A.Replicator genReplicator :: GenL A.Replicator
genReplicator = nextIdT >>* makeMeta' >>= \m -> genElem4 A.For m (comb0 $ simpleName "i") genExpression genExpression genReplicator = nextIdT >>* makeMeta' >>= \m -> genElem4 A.For m (comb0 $ simpleName "i") genExpression genExpression
-- | Generates a A.Structured, obeying the given OnlyAllowed structure. class ReplicatorAnnotation a where
genStructured :: OnlyAllowed -> Int -> GenL A.Structured replicatorItem :: (Int, Int -> GenL a) -> Maybe (Int, Int -> GenL (A.Structured a))
genStructured allowed n = nextIdT >>* makeMeta' >>= \m -> (flip oneofLS) n
[ replicatorItem' x = (4, genElem3 A.Rep m genReplicator . genStructured x . sub3)
cond (onlyP allowed) (2,genElem2 A.OnlyP m . genProcess . sub1 )
,cond (onlyO allowed) (2,comb1 (A.OnlyO emptyMeta . A.Else emptyMeta) . genProcess . sub1 )
,cond (onlyC allowed) (3,comb2 (\e p -> A.OnlyC emptyMeta $ A.Choice emptyMeta e p) genExpression . genProcess . sub2)
,cond (onlyA allowed) (4,genElem2 A.OnlyA m . genAlternative . sub1 )
--Replicators are allowed in ALTs, IFs, SEQs and PARs: --Replicators are allowed in ALTs, IFs, SEQs and PARs:
instance ReplicatorAnnotation A.Process where replicatorItem = Just . replicatorItem'
,cond (onlyP allowed || onlyC allowed || onlyA allowed) instance ReplicatorAnnotation A.Alternative where replicatorItem = Just . replicatorItem'
(4, genElem3 A.Rep m genReplicator . genStructured allowed . sub3) instance ReplicatorAnnotation A.Choice where replicatorItem = Just . replicatorItem'
instance ReplicatorAnnotation A.Option where replicatorItem = const Nothing
-- | Generates a A.Structured, obeying the given OnlyAllowed structure.
genStructured :: (Data a, ReplicatorAnnotation a) => (Int, Int -> GenL a) -> Int -> GenL (A.Structured a)
genStructured (no,genOnly) n = nextIdT >>* makeMeta' >>= \m -> (flip oneofLS) n
([{-
cond (onlyP allowed) (2,genElem2 A.Only m . genProcess . sub1 )
,cond (onlyO allowed) (2,comb1 (A.Only emptyMeta . A.Else emptyMeta) . genProcess . sub1 )
,cond (onlyC allowed) (3,comb2 (\e p -> A.Only emptyMeta $ A.Choice emptyMeta e p) genExpression . genProcess . sub2)
,cond (onlyA allowed) (4,genElem2 A.Only m . genAlternative . sub1 )
-}
(no - 1, genElem2 A.Only m . genOnly . sub1)
-- Specs currently don't work with Case statements TODO -- Specs currently don't work with Case statements TODO
,cond (not $ onlyO allowed) (3,genElem3 A.Spec m genSpecification . genStructured allowed . sub2 ) ,(3,genElem3 A.Spec m genSpecification . genStructured (no, genOnly) . sub2 )
,(1,genElem2 A.Several m . genList (genStructured allowed) . sub1) ,(1,genElem2 A.Several m . genList (genStructured (no, genOnly)) . sub1)
] ] ++ maybeToList (replicatorItem (no,genOnly)) )
-- | Generates a A.Process. -- | Generates a A.Process.
genProcess :: Int -> GenL A.Process genProcess :: Int -> GenL A.Process
@ -605,32 +608,35 @@ genProcess n = nextIdT >>* makeMeta' >>= \m -> (flip oneofLS) n
[ [
(1,const $ genElem1 A.Skip m) (1,const $ genElem1 A.Skip m)
,(1,const $ genElem1 A.Stop m) ,(1,const $ genElem1 A.Stop m)
,(2,genElem2 A.Seq m . genStructured justP . sub1) ,(2,genElem2 A.Seq m . genStructured genProcess' . sub1)
,(2,genElem3 A.Par m (comb0 A.PlainPar) . genStructured justP . sub1) ,(2,genElem3 A.Par m (comb0 A.PlainPar) . genStructured genProcess' . sub1)
,(3,genElem3 A.While m genExpression . genProcess . sub2) ,(3,genElem3 A.While m genExpression . genProcess . sub2)
,(2,genElem2 A.If m . genStructured justC . sub1) ,(2,genElem2 A.If m . genStructured genChoice' . sub1)
,(3,genElem3 A.Case m genExpression . genStructured justO . sub2) ,(3,genElem3 A.Case m genExpression . genStructured genOption' . sub2)
,(2,const $ genElem3 A.Assign m (comb0 [variable "x"]) genExpressionList) ,(2,const $ genElem3 A.Assign m (comb0 [variable "x"]) genExpressionList)
,(1,const $ genElem2 A.GetTime m (comb0 $ variable "x")) ,(1,const $ genElem2 A.GetTime m (comb0 $ variable "x"))
,(1,const $ genElem3 A.Wait m (comb0 A.WaitFor) genExpression) ,(1,const $ genElem3 A.Wait m (comb0 A.WaitFor) genExpression)
,(2,genElem3 A.Alt m (comb0 True) . genStructured justA . sub1) ,(2,genElem3 A.Alt m (comb0 True) . genStructured genAlternative' . sub1)
] ]
genProcess' :: (Int, Int -> GenL A.Process)
genProcess' = (1, genProcess)
-- | Generates a flow-graph from the given AST. -- | Generates a flow-graph from the given AST.
-- TODO put this in proper error monad -- TODO put this in proper error monad
genGraph :: A.Structured -> FlowGraph Identity () genGraph :: Data a => A.Structured a -> FlowGraph' Identity () a
genGraph s = either (\e -> error $ "QuickCheck graph did not build properly: " ++ e ++ ", from: " ++ pshow s) fst $ runIdentity $ buildFlowGraph funcs s genGraph s = either (\e -> error $ "QuickCheck graph did not build properly: " ++ e ++ ", from: " ++ pshow s) fst $ runIdentity $ buildFlowGraph funcs s
where where
funcs = mkLabelFuncsConst (return ()) funcs :: GraphLabelFuncs Identity ()
funcs = mkLabelFuncsConst (return ())
-- | Given a flow-graph, it returns a list of all the identity alteration functions, -- | Given a flow-graph, it returns a list of all the identity alteration functions,
-- for each node. Applying any, many or all of these functions to the source AST -- for each node. Applying any, many or all of these functions to the source AST
-- should leave it unchanged. -- should leave it unchanged.
pickFuncId :: Monad m => FlowGraph m () -> [A.Structured -> m A.Structured] pickFuncId :: (Data a, Monad m) => FlowGraph' m () a -> [A.Structured a -> m (A.Structured a)]
pickFuncId g = map (applyFunc . getFunc) (labNodes g) pickFuncId g = map (applyFunc . getFunc) (labNodes g)
where where
getFunc (_,Node (_,_,f)) = f getFunc (_,n) = getNodeFunc n
applyFunc (AlterProcess f) = f return applyFunc (AlterProcess f) = f return
applyFunc (AlterExpression f) = f return applyFunc (AlterExpression f) = f return
@ -641,10 +647,10 @@ pickFuncId g = map (applyFunc . getFunc) (labNodes g)
-- | Given a flow-graph, it returns a list of the meta-tag replacement alteration functions, -- | Given a flow-graph, it returns a list of the meta-tag replacement alteration functions,
-- for each meta-tag (i.e. each node). -- for each meta-tag (i.e. each node).
pickFuncRep :: Monad m => FlowGraph m () -> Map.Map Meta (A.Structured -> m A.Structured) pickFuncRep :: (Data a, Monad m) => FlowGraph' m () a -> Map.Map Meta (A.Structured a -> m (A.Structured a))
pickFuncRep gr = Map.fromList $ map (helpApplyFunc . getMetaFunc) (labNodes gr) pickFuncRep gr = Map.fromList $ map (helpApplyFunc . getMetaFunc) (labNodes gr)
where where
getMetaFunc (_,Node (m,_,f)) = (m,f) getMetaFunc (_,n) = (getNodeMeta n,getNodeFunc n)
helpApplyFunc (m,f) = (m, applyFunc (m,f)) helpApplyFunc (m,f) = (m, applyFunc (m,f))
@ -687,26 +693,26 @@ testModify =
prop_Id :: QC (A.Process, Map.Map [Meta] A.Process) -> Result prop_Id :: QC (A.Process, Map.Map [Meta] A.Process) -> Result
prop_Id (QC (g,_)) = collectAll $ (flip map) (map (foldFuncsM) $ powerset $ pickFuncId $ genGraph g') $ \f -> runIdentity (f g') *==* g' prop_Id (QC (g,_)) = collectAll $ (flip map) (map (foldFuncsM) $ powerset $ pickFuncId $ genGraph g') $ \f -> runIdentity (f g') *==* g'
where where
g' = A.OnlyP emptyMeta g g' = A.Only emptyMeta g
-- | Checks that applying any set (from the powerset of replacement functions) of replacement functions -- | Checks that applying any set (from the powerset of replacement functions) of replacement functions
-- produces the expected result. -- produces the expected result.
prop_Rep :: QC (A.Process, Map.Map [Meta] A.Process) -> Result prop_Rep :: QC (A.Process, Map.Map [Meta] A.Process) -> Result
prop_Rep (QC (g,rest)) = collectAll $ (flip map) (helper $ pickFuncRep $ genGraph g') $ prop_Rep (QC (g,rest)) = collectAll $ (flip map) (helper $ pickFuncRep $ genGraph g') $
\(funcs,ms) -> Just (runIdentity (applyMetas ms funcs g')) *==* (Map.lookup ms rest >>* A.OnlyP emptyMeta) \(funcs,ms) -> Just (runIdentity (applyMetas ms funcs g')) *==* (Map.lookup ms rest >>* A.Only emptyMeta)
where where
g' = A.OnlyP emptyMeta g g' = A.Only emptyMeta g
-- | This tests our genNumsToTotal function, which is itself a test generator; nasty! -- | This tests our genNumsToTotal function, which is itself a test generator; nasty!
prop_gennums :: Int -> Result prop_gennums :: Int -> Result
prop_gennums n = generate 0 (mkStdGen 0) (genNumsToTotal n >>* sum) *==* n prop_gennums n = generate 0 (mkStdGen 0) (genNumsToTotal n >>* sum) *==* n
-- | Repeatedly pairs the map with each element of the powerset of its keys -- | Repeatedly pairs the map with each element of the powerset of its keys
helper :: Monad m => Map.Map Meta (A.Structured -> m A.Structured) -> [(Map.Map Meta (A.Structured -> m A.Structured), [Meta])] helper :: Monad m => Map.Map Meta (A.Structured a -> m (A.Structured a)) -> [(Map.Map Meta (A.Structured a -> m (A.Structured a)), [Meta])]
helper fs = zip (repeat fs) (powerset $ Map.keys fs) helper fs = zip (repeat fs) (powerset $ Map.keys fs)
-- | Applies the functions associated with the given meta tags -- | Applies the functions associated with the given meta tags
applyMetas :: Monad m => [Meta] -> Map.Map Meta (A.Structured -> m A.Structured) -> (A.Structured -> m A.Structured) applyMetas :: Monad m => [Meta] -> Map.Map Meta (A.Structured a -> m (A.Structured a)) -> (A.Structured a -> m (A.Structured a))
applyMetas ms funcs = foldFuncsM $ concatMap (\m -> Map.lookup m funcs) ms applyMetas ms funcs = foldFuncsM $ concatMap (\m -> Map.lookup m funcs) ms

View File

@ -39,7 +39,7 @@ instance Die PassM where
dieReport = throwError dieReport = throwError
-- | The type of an AST-mangling pass. -- | The type of an AST-mangling pass.
type Pass = A.Structured -> PassM A.Structured type Pass = A.AST -> PassM A.AST
-- | Compose a list of passes into a single pass. -- | Compose a list of passes into a single pass.
runPasses :: [(String, Pass)] -> Pass runPasses :: [(String, Pass)] -> Pass
@ -105,3 +105,6 @@ excludeConstr cons x
= if null items then return x else dieInternal (Nothing, "Excluded item still remains in source tree: " ++ (show $ head items) ++ " tree is: " ++ pshow x) = if null items then return x else dieInternal (Nothing, "Excluded item still remains in source tree: " ++ (show $ head items) ++ " tree is: " ++ pshow x)
where where
items = checkTreeForConstr cons x items = checkTreeForConstr cons x
mk1M :: (Monad m, Data a, Typeable1 t) => (forall d . Data d => t d -> m (t d)) -> a -> m a
mk1M = ext1M return

View File

@ -134,15 +134,16 @@ doPattern p@(Match c ps) =
items = map doPattern ps items = map doPattern ps
folded = foldPatternList p folded = foldPatternList p
doAny :: (forall a. Typeable a => (a -> Doc) -> (a -> Doc)) -> GenericQ Doc doAny :: (forall a. Data a => (a -> Doc) -> (a -> Doc)) -> GenericQ Doc
doAny extFunc = extFunc ( doAny extFunc = extFunc (
(doGeneral anyFunc) `ext1Q` (doList anyFunc) `extQ` doString `extQ` doMeta `extQ` doPattern (doGeneral anyFunc) `ext1Q` (doList anyFunc) `extQ` doString `extQ` doMeta `extQ` doPattern
`extQ` (doMap anyFunc :: Map.Map String String -> Doc) `extQ` (doMap anyFunc :: Map.Map String String -> Doc)
`extQ` (doMap anyFunc :: Map.Map String A.NameDef -> Doc) `extQ` (doMap anyFunc :: Map.Map String A.NameDef -> Doc)
`extQ` (doMap anyFunc :: Map.Map String [A.Type] -> Doc) `extQ` (doMap anyFunc :: Map.Map String [A.Type] -> Doc)
`extQ` (doMap anyFunc :: Map.Map String [A.Actual] -> Doc) `extQ` (doMap anyFunc :: Map.Map String [A.Actual] -> Doc)
`extQ` (doSet anyFunc :: Set.Set String -> Doc) -- `extQ` (doSet anyFunc :: Set.Set String -> Doc)
`extQ` (doSet anyFunc :: Set.Set A.Name -> Doc) -- `extQ` (doSet anyFunc :: Set.Set A.Name -> Doc)
`ext1Q` (doSet anyFunc)
) )
where where
anyFunc :: GenericQ Doc anyFunc :: GenericQ Doc
@ -159,7 +160,7 @@ pshowCode c = do st <- get
FrontendOccam -> return $ render $ (extOccam $ doAny extOccam) c FrontendOccam -> return $ render $ (extOccam $ doAny extOccam) c
FrontendRain -> return $ render $ (extRain $ doAny extRain) c FrontendRain -> return $ render $ (extRain $ doAny extRain) c
where where
extOccam :: forall a. Typeable a => (a -> Doc) -> (a -> Doc) extOccam :: forall a. (Data a, Typeable a) => (a -> Doc) -> (a -> Doc)
extOccam f = extCode f showOccam extOccam f = extCode f showOccam
extRain :: forall a. Typeable a => (a -> Doc) -> (a -> Doc) extRain :: forall a. (Data a, Typeable a) => (a -> Doc) -> (a -> Doc)
extRain f = extCode f showRain extRain f = extCode f showRain

View File

@ -390,7 +390,7 @@ instance ShowOccam A.Specification where
+>> occamOutdent +>> occamOutdent
+>> (showOccamLine colon) +>> (showOccamLine colon)
--TODO use the specmode --TODO use the specmode
showOccamM (A.Specification _ n (A.Function _ sm retTypes params el@(A.OnlyEL {}))) showOccamM (A.Specification _ n (A.Function _ sm retTypes params el@(A.Only {})))
= showOccamLine $ = showOccamLine $
showWithCommas retTypes +>> (return " FUNCTION ") +>> showName n +>> return "(" +>> showWithCommas params +>> return ")" showWithCommas retTypes +>> (return " FUNCTION ") +>> showName n +>> return "(" +>> showWithCommas params +>> return ")"
+>> return " IS " +>> showOccamM el +>> colon +>> return " IS " +>> showOccamM el +>> colon
@ -461,17 +461,12 @@ instance ShowOccam A.Option where
showOccamM (A.Option _ es p) = showOccamLine (showAll $ intersperse (return " , ") $ map showOccamM es) +>> occamBlock (showOccamM p) showOccamM (A.Option _ es p) = showOccamLine (showAll $ intersperse (return " , ") $ map showOccamM es) +>> occamBlock (showOccamM p)
showOccamM (A.Else _ p) = showOccamLine (return "ELSE") +>> occamBlock (showOccamM p) showOccamM (A.Else _ p) = showOccamLine (return "ELSE") +>> occamBlock (showOccamM p)
instance ShowOccam A.Structured where instance (Data a, ShowOccam a) => ShowOccam (A.Structured a) where
showOccamM (A.Spec _ spec str) = showOccamM spec +>> showOccamM str showOccamM (A.Spec _ spec str) = showOccamM spec +>> showOccamM str
showOccamM (A.Rep _ rep str) showOccamM (A.Rep _ rep str)
= do item <- currentContext = do item <- currentContext
(showOccamLine (return (item ++ " ") +>> showOccamM rep)) +>> occamIndent +>> showOccamM str +>> occamOutdent (showOccamLine (return (item ++ " ") +>> showOccamM rep)) +>> occamIndent +>> showOccamM str +>> occamOutdent
showOccamM (A.OnlyP _ p) = showOccamM p showOccamM (A.Only _ p) = showOccamM p
showOccamM (A.OnlyEL _ el) = showOccamM el
showOccamM (A.OnlyA _ a) = showOccamM a
showOccamM (A.OnlyV _ v) = showOccamM v
showOccamM (A.OnlyC _ c) = showOccamM c
showOccamM (A.OnlyO _ o) = showOccamM o
showOccamM (A.Several _ ss) = showAll $ map showOccamM ss showOccamM (A.Several _ ss) = showAll $ map showOccamM ss
showOccamM (A.ProcThen _ p str) = showOccamLine (return "VALOF") +>> occamBlock (showOccamM p +>> showOccamLine (return "RESULT " +>> showOccamM str)) showOccamM (A.ProcThen _ p str) = showOccamLine (return "VALOF") +>> occamBlock (showOccamM p +>> showOccamLine (return "RESULT " +>> showOccamM str))
@ -485,7 +480,7 @@ instance ShowOccam A.ExpressionList where
showOccamM (A.ExpressionList _ es) = showWithCommas es showOccamM (A.ExpressionList _ es) = showWithCommas es
--TODO functioncalllist --TODO functioncalllist
outer :: String -> A.Structured -> OccamWriter String outer :: (Data a, ShowOccam a) => String -> A.Structured a -> OccamWriter String
outer keyword (A.Rep _ rep str) = showOccamLine (return keyword +>> showOccamM rep) +>> beginStr keyword +>> showOccamM str +>> endStr outer keyword (A.Rep _ rep str) = showOccamLine (return keyword +>> showOccamM rep) +>> beginStr keyword +>> showOccamM str +>> endStr
outer keyword str = doStr keyword (showOccamM str) outer keyword str = doStr keyword (showOccamM str)
@ -523,7 +518,7 @@ instance ShowRain a where
-- ShowOccam\/ShowRain implementation. But since to add a type to the ShowOccam\/ShowRain -- ShowOccam\/ShowRain implementation. But since to add a type to the ShowOccam\/ShowRain
-- classes you have to provide a specific instance above anyway, I don't think that adding -- classes you have to provide a specific instance above anyway, I don't think that adding
-- one more line while you're at it is too bad. -- one more line while you're at it is too bad.
extCode :: Typeable b => (b -> Doc) -> (forall a. (ShowOccam a, ShowRain a) => a -> String) -> (b -> Doc) extCode :: (Data b, Typeable b) => (b -> Doc) -> (forall a. (ShowOccam a, ShowRain a) => a -> String) -> (b -> Doc)
extCode q f = q extCode q f = q
`extQ` (text . (f :: A.DyadicOp -> String)) `extQ` (text . (f :: A.DyadicOp -> String))
`extQ` (text . (f :: A.Expression -> String)) `extQ` (text . (f :: A.Expression -> String))
@ -533,9 +528,10 @@ extCode q f = q
`extQ` (text . (f :: A.Process -> String)) `extQ` (text . (f :: A.Process -> String))
`extQ` (text . (f :: A.Replicator -> String)) `extQ` (text . (f :: A.Replicator -> String))
`extQ` (text . (f :: A.Specification -> String)) `extQ` (text . (f :: A.Specification -> String))
`extQ` (text . (f :: A.Structured -> String))
`extQ` (text . (f :: A.Type -> String)) `extQ` (text . (f :: A.Type -> String))
`extQ` (text . (f :: A.Variable -> String)) `extQ` (text . (f :: A.Variable -> String))
--TODO
-- `ext1Q` (text . (f :: (Data c, ShowOccam c) => A.Structured c -> String))
(+>>) :: State s [a] -> State s [a] -> State s [a] (+>>) :: State s [a] -> State s [a] -> State s [a]
(+>>) x y = do x' <- x (+>>) x y = do x' <- x

View File

@ -223,15 +223,15 @@ makeSimpleAssignPattern lhs rhs = stopCaringPattern emptyMeta $ mkPattern $ make
-- | Turns a list of 'A.Process' into a 'A.Seq' with those processes in order, with empty meta tags. -- | Turns a list of 'A.Process' into a 'A.Seq' with those processes in order, with empty meta tags.
makeSeq :: [A.Process] -> A.Process makeSeq :: [A.Process] -> A.Process
makeSeq procList = A.Seq emptyMeta $ A.Several emptyMeta (map (\x -> A.OnlyP emptyMeta x) procList) makeSeq procList = A.Seq emptyMeta $ A.Several emptyMeta (map (A.Only emptyMeta) procList)
-- | Turns a list of 'A.Process' into a 'A.Par' with those processes in order (with type 'A.PlainPar'), with empty meta tags. -- | Turns a list of 'A.Process' into a 'A.Par' with those processes in order (with type 'A.PlainPar'), with empty meta tags.
makePar :: [A.Process] -> A.Process makePar :: [A.Process] -> A.Process
makePar procList = A.Par emptyMeta A.PlainPar $ A.Several emptyMeta (map (\x -> A.OnlyP emptyMeta x) procList) makePar procList = A.Par emptyMeta A.PlainPar $ A.Several emptyMeta (map (A.Only emptyMeta) procList)
-- | Wraps the given process in a replicated 'A.Par' of the form PAR i = 0 FOR 3. -- | Wraps the given process in a replicated 'A.Par' of the form PAR i = 0 FOR 3.
makeRepPar :: A.Process -> A.Process makeRepPar :: A.Process -> A.Process
makeRepPar proc = A.Par emptyMeta A.PlainPar $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 3)) (A.OnlyP emptyMeta proc) makeRepPar proc = A.Par emptyMeta A.PlainPar $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 3)) (A.Only emptyMeta proc)
-- | Creates an assignment to the given 'A.Variable' from the given 'A.Expression.' -- | Creates an assignment to the given 'A.Variable' from the given 'A.Expression.'
makeAssign :: A.Variable -> A.Expression -> A.Process makeAssign :: A.Variable -> A.Expression -> A.Process

View File

@ -572,7 +572,7 @@ sizeOfReplicator :: A.Replicator -> A.Expression
sizeOfReplicator (A.For _ _ _ count) = count sizeOfReplicator (A.For _ _ _ count) = count
-- | Get the number of items in a Structured as an expression. -- | Get the number of items in a Structured as an expression.
sizeOfStructured :: A.Structured -> A.Expression sizeOfStructured :: Data a => A.Structured a -> A.Expression
sizeOfStructured (A.Rep m rep s) sizeOfStructured (A.Rep m rep s)
= A.Dyadic m A.Times (sizeOfReplicator rep) (sizeOfStructured s) = A.Dyadic m A.Times (sizeOfReplicator rep) (sizeOfStructured s)
sizeOfStructured (A.Spec _ _ s) = sizeOfStructured s sizeOfStructured (A.Spec _ _ s) = sizeOfStructured s

View File

@ -1339,7 +1339,7 @@ definition
(rs, sm) <- tryVV (sepBy1 dataType sComma) (specMode sFUNCTION) (rs, sm) <- tryVV (sepBy1 dataType sComma) (specMode sFUNCTION)
n <- newFunctionName n <- newFunctionName
fs <- formalList fs <- formalList
do { sIS; fs' <- scopeInFormals fs; el <- expressionList rs; scopeOutFormals fs'; sColon; eol; return $ A.Specification m n $ A.Function m sm rs fs' (A.OnlyEL m el) } do { sIS; fs' <- scopeInFormals fs; el <- expressionList rs; scopeOutFormals fs'; sColon; eol; return $ A.Specification m n $ A.Function m sm rs fs' (A.Only m el) }
<|> do { eol; indent; fs' <- scopeInFormals fs; vp <- valueProcess rs; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Function m sm rs fs' vp } <|> do { eol; indent; fs' <- scopeInFormals fs; vp <- valueProcess rs; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Function m sm rs fs' vp }
<|> retypesAbbrev <|> retypesAbbrev
<?> "definition" <?> "definition"
@ -1476,7 +1476,7 @@ formalVariableType
return (A.Abbrev, s) return (A.Abbrev, s)
<?> "formal variable type" <?> "formal variable type"
valueProcess :: [A.Type] -> OccParser A.Structured valueProcess :: [A.Type] -> OccParser (A.Structured A.ExpressionList)
valueProcess rs valueProcess rs
= do m <- md = do m <- md
sVALOF sVALOF
@ -1487,7 +1487,7 @@ valueProcess rs
el <- expressionList rs el <- expressionList rs
eol eol
outdent outdent
return $ A.ProcThen m p (A.OnlyEL m el) return $ A.ProcThen m p (A.Only m el)
<|> handleSpecs specification (valueProcess rs) A.Spec <|> handleSpecs specification (valueProcess rs) A.Spec
<?> "value process" <?> "value process"
--}}} --}}}
@ -1536,7 +1536,7 @@ process
<|> procInstance <|> procInstance
<|> intrinsicProc <|> intrinsicProc
<|> handleSpecs (allocation <|> specification) process <|> handleSpecs (allocation <|> specification) process
(\m s p -> A.Seq m (A.Spec m s (A.OnlyP m p))) (\m s p -> A.Seq m (A.Spec m s (A.Only m p)))
<?> "process" <?> "process"
--{{{ assignment (:=) --{{{ assignment (:=)
@ -1585,7 +1585,7 @@ channelInput
do sCASE do sCASE
tl <- taggedList nts tl <- taggedList nts
eol eol
return (c, A.InputCase m (A.OnlyV m (tl (A.Skip m)))) return (c, A.InputCase m (A.Only m (tl (A.Skip m))))
<?> "channel input" <?> "channel input"
timerInput :: OccParser (A.Variable, A.InputMode) timerInput :: OccParser (A.Variable, A.InputMode)
@ -1641,7 +1641,7 @@ caseInput
return $ A.Input m c (A.InputCase m (A.Several m vs)) return $ A.Input m c (A.InputCase m (A.Several m vs))
<?> "case input" <?> "case input"
variant :: [(A.Name, [A.Type])] -> OccParser A.Structured variant :: [(A.Name, [A.Type])] -> OccParser (A.Structured A.Variant)
variant nts variant nts
= do m <- md = do m <- md
tl <- taggedList nts tl <- taggedList nts
@ -1649,7 +1649,7 @@ variant nts
indent indent
p <- process p <- process
outdent outdent
return $ A.OnlyV m (tl p) return $ A.Only m (tl p)
<|> handleSpecs specification (variant nts) A.Spec <|> handleSpecs specification (variant nts) A.Spec
<?> "variant" <?> "variant"
--}}} --}}}
@ -1710,8 +1710,8 @@ seqProcess :: OccParser A.Process
seqProcess seqProcess
= do m <- md = do m <- md
sSEQ sSEQ
do { eol; ps <- maybeIndentedList m "empty SEQ" process; return $ A.Seq m (A.Several m (map (A.OnlyP m) ps)) } do { eol; ps <- maybeIndentedList m "empty SEQ" process; return $ A.Seq m (A.Several m (map (A.Only m) ps)) }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.Seq m (A.Rep m r' (A.OnlyP m p)) } <|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.Seq m (A.Rep m r' (A.Only m p)) }
<?> "SEQ process" <?> "SEQ process"
--}}} --}}}
--{{{ IF --{{{ IF
@ -1722,7 +1722,7 @@ ifProcess
return $ A.If m c return $ A.If m c
<?> "IF process" <?> "IF process"
conditional :: OccParser A.Structured conditional :: OccParser (A.Structured A.Choice)
conditional conditional
= do m <- md = do m <- md
sIF sIF
@ -1730,14 +1730,14 @@ conditional
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; c <- ifChoice; scopeOutRep r'; outdent; return $ A.Rep m r' c } <|> do { r <- replicator; eol; indent; r' <- scopeInRep r; c <- ifChoice; scopeOutRep r'; outdent; return $ A.Rep m r' c }
<?> "conditional" <?> "conditional"
ifChoice :: OccParser A.Structured ifChoice :: OccParser (A.Structured A.Choice)
ifChoice ifChoice
= guardedChoice = guardedChoice
<|> conditional <|> conditional
<|> handleSpecs specification ifChoice A.Spec <|> handleSpecs specification ifChoice A.Spec
<?> "choice" <?> "choice"
guardedChoice :: OccParser A.Structured guardedChoice :: OccParser (A.Structured A.Choice)
guardedChoice guardedChoice
= do m <- md = do m <- md
b <- booleanExpr b <- booleanExpr
@ -1745,7 +1745,7 @@ guardedChoice
indent indent
p <- process p <- process
outdent outdent
return $ A.OnlyC m (A.Choice m b p) return $ A.Only m (A.Choice m b p)
<?> "guarded choice" <?> "guarded choice"
--}}} --}}}
--{{{ CASE --{{{ CASE
@ -1762,21 +1762,21 @@ caseProcess
return $ A.Case m sel (A.Several m os) return $ A.Case m sel (A.Several m os)
<?> "CASE process" <?> "CASE process"
caseOption :: A.Type -> OccParser A.Structured caseOption :: A.Type -> OccParser (A.Structured A.Option)
caseOption t caseOption t
= do m <- md = do m <- md
ces <- tryVX (sepBy (constExprOfType t) sComma) eol ces <- tryVX (sepBy (constExprOfType t) sComma) eol
indent indent
p <- process p <- process
outdent outdent
return $ A.OnlyO m (A.Option m ces p) return $ A.Only m (A.Option m ces p)
<|> do m <- md <|> do m <- md
sELSE sELSE
eol eol
indent indent
p <- process p <- process
outdent outdent
return $ A.OnlyO m (A.Else m p) return $ A.Only m (A.Else m p)
<|> handleSpecs specification (caseOption t) A.Spec <|> handleSpecs specification (caseOption t) A.Spec
<?> "option" <?> "option"
--}}} --}}}
@ -1798,8 +1798,8 @@ parallel :: OccParser A.Process
parallel parallel
= do m <- md = do m <- md
isPri <- parKeyword isPri <- parKeyword
do { eol; ps <- maybeIndentedList m "empty PAR" process; return $ A.Par m isPri (A.Several m (map (A.OnlyP m) ps)) } do { eol; ps <- maybeIndentedList m "empty PAR" process; return $ A.Par m isPri (A.Several m (map (A.Only m) ps)) }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.Par m isPri (A.Rep m r' (A.OnlyP m p)) } <|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.Par m isPri (A.Rep m r' (A.Only m p)) }
<|> processor <|> processor
<?> "PAR process" <?> "PAR process"
@ -1830,7 +1830,7 @@ altProcess
return $ A.Alt m isPri a return $ A.Alt m isPri a
<?> "ALT process" <?> "ALT process"
alternation :: OccParser (Bool, A.Structured) alternation :: OccParser (Bool, A.Structured A.Alternative)
alternation alternation
= do m <- md = do m <- md
isPri <- altKeyword isPri <- altKeyword
@ -1846,7 +1846,7 @@ altKeyword
-- The reason the CASE guards end up here is because they have to be handled -- The reason the CASE guards end up here is because they have to be handled
-- specially: you can't tell until parsing the guts of the CASE what the processes -- specially: you can't tell until parsing the guts of the CASE what the processes
-- are. -- are.
alternative :: OccParser A.Structured alternative :: OccParser (A.Structured A.Alternative)
alternative alternative
-- FIXME: Check we don't have PRI ALT inside ALT. -- FIXME: Check we don't have PRI ALT inside ALT.
= do (isPri, a) <- alternation = do (isPri, a) <- alternation
@ -1857,24 +1857,24 @@ alternative
(b, c) <- tryVXVXX booleanExpr sAmp channel sQuest (sCASE >> eol) (b, c) <- tryVXVXX booleanExpr sAmp channel sQuest (sCASE >> eol)
nts <- caseInputItems c nts <- caseInputItems c
vs <- maybeIndentedList m "empty ? CASE" (variant nts) vs <- maybeIndentedList m "empty ? CASE" (variant nts)
return $ A.OnlyA m (A.AlternativeCond m b c (A.InputCase m $ A.Several m vs) (A.Skip m)) return $ A.Only m (A.AlternativeCond m b c (A.InputCase m $ A.Several m vs) (A.Skip m))
<|> do m <- md <|> do m <- md
c <- tryVXX channel sQuest (sCASE >> eol) c <- tryVXX channel sQuest (sCASE >> eol)
nts <- caseInputItems c nts <- caseInputItems c
vs <- maybeIndentedList m "empty ? CASE" (variant nts) vs <- maybeIndentedList m "empty ? CASE" (variant nts)
return $ A.OnlyA m (A.Alternative m c (A.InputCase m $ A.Several m vs) (A.Skip m)) return $ A.Only m (A.Alternative m c (A.InputCase m $ A.Several m vs) (A.Skip m))
<|> guardedAlternative <|> guardedAlternative
<|> handleSpecs specification alternative A.Spec <|> handleSpecs specification alternative A.Spec
<?> "alternative" <?> "alternative"
guardedAlternative :: OccParser A.Structured guardedAlternative :: OccParser (A.Structured A.Alternative)
guardedAlternative guardedAlternative
= do m <- md = do m <- md
makeAlt <- guard makeAlt <- guard
indent indent
p <- process p <- process
outdent outdent
return $ A.OnlyA m (makeAlt p) return $ A.Only m (makeAlt p)
<?> "guarded alternative" <?> "guarded alternative"
guard :: OccParser (A.Process -> A.Alternative) guard :: OccParser (A.Process -> A.Alternative)
@ -1943,7 +1943,7 @@ intrinsicProc
--}}} --}}}
--{{{ top-level forms --{{{ top-level forms
topLevelItem :: OccParser A.Structured topLevelItem :: OccParser A.AST
topLevelItem = handleSpecs (allocation <|> specification) topLevelItem topLevelItem = handleSpecs (allocation <|> specification) topLevelItem
(\m s inner -> A.Spec m s inner) (\m s inner -> A.Spec m s inner)
<|> do m <- md <|> do m <- md
@ -1959,7 +1959,7 @@ topLevelItem = handleSpecs (allocation <|> specification) topLevelItem
-- A source file is really a series of specifications, but the later ones need to -- A source file is really a series of specifications, but the later ones need to
-- have the earlier ones in scope, so we can't parse them separately. -- have the earlier ones in scope, so we can't parse them separately.
-- Instead, we nest the specifications -- Instead, we nest the specifications
sourceFile :: OccParser (A.Structured, CompState) sourceFile :: OccParser (A.AST, CompState)
sourceFile sourceFile
= do p <- topLevelItem = do p <- topLevelItem
s <- getState s <- getState
@ -1976,7 +1976,7 @@ runTockParser toks prod cs
Right r -> return r Right r -> return r
-- | Parse an occam program. -- | Parse an occam program.
parseOccamProgram :: [Token] -> PassM A.Structured parseOccamProgram :: [Token] -> PassM A.AST
parseOccamProgram toks parseOccamProgram toks
= do cs <- get = do cs <- get
(p, cs') <- runTockParser toks sourceFile cs (p, cs') <- runTockParser toks sourceFile cs

View File

@ -21,6 +21,7 @@ module ParseRain where
import Control.Monad (liftM) import Control.Monad (liftM)
import Control.Monad.State (MonadState, liftIO, get, put) import Control.Monad.State (MonadState, liftIO, get, put)
import Data.Generics
import Data.List import Data.List
import Data.Maybe import Data.Maybe
import qualified IO import qualified IO
@ -243,22 +244,22 @@ expression
data InnerBlockLineState = Decls | NoMoreDecls | Mixed deriving (Eq) data InnerBlockLineState = Decls | NoMoreDecls | Mixed deriving (Eq)
innerBlock :: Bool -> RainParser A.Structured innerBlock :: Bool -> RainParser (A.Structured A.Process)
innerBlock declsMustBeFirst = do m <- sLeftC innerBlock declsMustBeFirst = do m <- sLeftC
lines <- linesToEnd (if declsMustBeFirst then Decls else Mixed) lines <- linesToEnd (if declsMustBeFirst then Decls else Mixed)
case lines of case lines of
Left single -> return single Left single -> return single
Right lines -> return $ A.Several m lines Right lines -> return $ A.Several m lines
where where
wrapProc :: A.Process -> A.Structured wrapProc :: A.Process -> A.Structured A.Process
wrapProc x = A.OnlyP (findMeta x) x wrapProc x = A.Only (findMeta x) x
makeList :: Either A.Structured [A.Structured] -> [A.Structured] makeList :: Either (A.Structured A.Process) [A.Structured A.Process] -> [A.Structured A.Process]
makeList (Left s) = [s] makeList (Left s) = [s]
makeList (Right ss) = ss makeList (Right ss) = ss
--Returns either a single line (which means the immediate next line is a declaration) or a list of remaining lines --Returns either a single line (which means the immediate next line is a declaration) or a list of remaining lines
linesToEnd :: InnerBlockLineState -> RainParser (Either A.Structured [A.Structured]) linesToEnd :: InnerBlockLineState -> RainParser (Either (A.Structured A.Process) [A.Structured A.Process])
linesToEnd state linesToEnd state
= (if state /= NoMoreDecls then = (if state /= NoMoreDecls then
do (m,decl) <- declaration do (m,decl) <- declaration
@ -270,8 +271,10 @@ innerBlock declsMustBeFirst = do m <- sLeftC
<|> do {st <- statement ; rest <- linesToEnd nextState ; return $ Right $ (wrapProc st) : (makeList rest)} <|> do {st <- statement ; rest <- linesToEnd nextState ; return $ Right $ (wrapProc st) : (makeList rest)}
--Although return is technically a statement, we parse it here because it can only occur inside a block, --Although return is technically a statement, we parse it here because it can only occur inside a block,
--and we don't want to wrap it in an A.OnlyP: --and we don't want to wrap it in an A.OnlyP:
{- TODO parse return again
<|> do {m <- sReturn ; exp <- expression ; sSemiColon ; rest <- linesToEnd nextState ; <|> do {m <- sReturn ; exp <- expression ; sSemiColon ; rest <- linesToEnd nextState ;
return $ Right $ (A.OnlyEL m $ A.ExpressionList (findMeta exp) [exp]) : (makeList rest)} return $ Right $ (A.OnlyEL m $ A.ExpressionList (findMeta exp) [exp]) : (makeList rest)}
-}
<|> do {sRightC ; return $ Right []} <|> do {sRightC ; return $ Right []}
<?> "statement, declaration, or end of block" <?> "statement, declaration, or end of block"
where where
@ -298,9 +301,9 @@ assignOp
each :: RainParser A.Process each :: RainParser A.Process
each = do { m <- sPareach ; sLeftR ; n <- name ; sColon ; exp <- expression ; sRightR ; st <- block ; each = do { m <- sPareach ; sLeftR ; n <- name ; sColon ; exp <- expression ; sRightR ; st <- block ;
return $ A.Par m A.PlainPar $ A.Rep m (A.ForEach m n exp) $ A.OnlyP m st } return $ A.Par m A.PlainPar $ A.Rep m (A.ForEach m n exp) $ A.Only m st }
<|> do { m <- sSeqeach ; sLeftR ; n <- name ; sColon ; exp <- expression ; sRightR ; st <- block ; <|> do { m <- sSeqeach ; sLeftR ; n <- name ; sColon ; exp <- expression ; sRightR ; st <- block ;
return $ A.Seq m $ A.Rep m (A.ForEach m n exp) $ A.OnlyP m st } return $ A.Seq m $ A.Rep m (A.ForEach m n exp) $ A.Only m st }
comm :: Bool -> RainParser A.Process comm :: Bool -> RainParser A.Process
comm isAlt comm isAlt
@ -321,18 +324,18 @@ alt = do {m <- sPri ; sAlt ; m' <- sLeftC ; cases <- many altCase ; optElseCase
singleton :: RainParser a -> RainParser [a] singleton :: RainParser a -> RainParser [a]
singleton p = do {a <- p ; return [a]} singleton p = do {a <- p ; return [a]}
altCase :: RainParser A.Structured altCase :: RainParser (A.Structured A.Alternative)
altCase = do input <- comm True altCase = do input <- comm True
case input of case input of
A.Input m lv im -> do { body <- block ; return $ A.OnlyA m $ A.Alternative m lv im body } A.Input m lv im -> do { body <- block ; return $ A.Only m $ A.Alternative m lv im body }
_ -> dieP (findMeta input) $ "communication type not supported in an alt: \"" ++ show input ++ "\"" _ -> dieP (findMeta input) $ "communication type not supported in an alt: \"" ++ show input ++ "\""
<|> do (m, wm, e) <- waitStatement True <|> do (m, wm, e) <- waitStatement True
body <- block body <- block
return $ A.OnlyA m $ A.AlternativeWait m wm e body return $ A.Only m $ A.AlternativeWait m wm e body
elseCase :: RainParser A.Structured elseCase :: RainParser (A.Structured A.Alternative)
elseCase = do m <- sElse elseCase = do m <- sElse
body <- block body <- block
return $ A.OnlyA m $ A.AlternativeSkip m (A.True m) body return $ A.Only m $ A.AlternativeSkip m (A.True m) body
tuple :: RainParser [A.Expression] tuple :: RainParser [A.Expression]
tuple = do { sLeftR ; items <- expression `sepBy` sComma ; sRightR ; return items } tuple = do { sLeftR ; items <- expression `sepBy` sComma ; sRightR ; return items }
@ -363,8 +366,8 @@ statement :: RainParser A.Process
statement statement
= do { m <- sWhile ; sLeftR ; exp <- expression ; sRightR ; st <- block ; return $ A.While m exp st} = do { m <- sWhile ; sLeftR ; exp <- expression ; sRightR ; st <- block ; return $ A.While m exp st}
<|> do { m <- sIf ; sLeftR ; exp <- expression ; sRightR ; st <- block ; <|> do { m <- sIf ; sLeftR ; exp <- expression ; sRightR ; st <- block ;
option (A.If m $ A.Several m [A.OnlyC m (A.Choice m exp st), A.OnlyC m (A.Choice m (A.True m) (A.Skip m))]) option (A.If m $ A.Several m [A.Only m (A.Choice m exp st), A.Only m (A.Choice m (A.True m) (A.Skip m))])
(do {sElse ; elSt <- block ; return (A.If m $ A.Several m [A.OnlyC m (A.Choice m exp st), A.OnlyC m (A.Choice m (A.True m) elSt)])}) (do {sElse ; elSt <- block ; return (A.If m $ A.Several m [A.Only m (A.Choice m exp st), A.Only m (A.Choice m (A.True m) elSt)])})
} }
<|> block <|> block
<|> each <|> each
@ -389,41 +392,41 @@ tupleDef = do {sLeftR ; tm <- sepBy tupleDefMember sComma ; sRightR ; return tm}
tupleDefMember :: RainParser (A.Name,A.Type) tupleDefMember :: RainParser (A.Name,A.Type)
tupleDefMember = do {t <- dataType ; sColon ; n <- name ; return (n,t)} tupleDefMember = do {t <- dataType ; sColon ; n <- name ; return (n,t)}
declaration :: RainParser (Meta,A.Structured -> A.Structured) declaration :: Data a => RainParser (Meta, A.Structured a -> A.Structured a)
declaration = try $ do {t <- dataType; sColon ; ns <- name `sepBy1` sComma ; sSemiColon ; declaration = try $ do {t <- dataType; sColon ; ns <- name `sepBy1` sComma ; sSemiColon ;
return (findMeta t, \x -> foldr (foldSpec t) x ns) } return (findMeta t, \x -> foldr (foldSpec t) x ns) }
where where
foldSpec :: A.Type -> A.Name -> (A.Structured -> A.Structured) foldSpec :: Data a => A.Type -> A.Name -> (A.Structured a -> A.Structured a)
foldSpec t n = A.Spec (findMeta t) $ A.Specification (findMeta t) n $ A.Declaration (findMeta t) t Nothing foldSpec t n = A.Spec (findMeta t) $ A.Specification (findMeta t) n $ A.Declaration (findMeta t) t Nothing
terminator :: A.Structured terminator :: Data a => A.Structured a
terminator = A.Several emptyMeta [] terminator = A.Several emptyMeta []
processDecl :: RainParser A.Structured processDecl :: RainParser A.AST
processDecl = do {m <- sProcess ; procName <- name ; params <- tupleDef ; body <- block ; processDecl = do {m <- sProcess ; procName <- name ; params <- tupleDef ; body <- block ;
return $ A.Spec m return $ A.Spec m
(A.Specification m procName (A.Proc m A.PlainSpec (formaliseTuple params) body)) (A.Specification m procName (A.Proc m A.PlainSpec (formaliseTuple params) body))
terminator} terminator}
functionDecl :: RainParser A.Structured functionDecl :: RainParser A.AST
functionDecl = do {m <- sFunction ; retType <- dataType ; sColon ; funcName <- name ; params <- tupleDef ; body <- block ; functionDecl = do {m <- sFunction ; retType <- dataType ; sColon ; funcName <- name ; params <- tupleDef ; body <- block ;
return $ A.Spec m return {- $ A.Spec m TODO handle functions again
(A.Specification m funcName (A.Function m A.PlainSpec [retType] (formaliseTuple params) (A.OnlyP (findMeta body) body))) (A.Specification m funcName (A.Function m A.PlainSpec [retType] (formaliseTuple params) (A.Only (findMeta body) body))) -}
terminator} terminator}
topLevelDecl :: RainParser A.Structured topLevelDecl :: RainParser A.AST
topLevelDecl = do decls <- many (processDecl <|> functionDecl <?> "process or function declaration") topLevelDecl = do decls <- many (processDecl <|> functionDecl <?> "process or function declaration")
eof eof
return $ A.Several emptyMeta decls return $ A.Several emptyMeta decls
rainSourceFile :: RainParser (A.Structured, CompState) rainSourceFile :: RainParser (A.AST, CompState)
rainSourceFile rainSourceFile
= do p <- topLevelDecl = do p <- topLevelDecl
s <- getState s <- getState
return (p, s) return (p, s)
-- | Load and parse a Rain source file. -- | Load and parse a Rain source file.
parseRainProgram :: String -> PassM A.Structured parseRainProgram :: String -> PassM A.AST
parseRainProgram filename parseRainProgram filename
= do source <- liftIO $ readFile filename = do source <- liftIO $ readFile filename
lexOut <- liftIO $ L.runLexer filename source lexOut <- liftIO $ L.runLexer filename source

View File

@ -90,9 +90,12 @@ testParseFail (text,prod)
Right result -> assertFailure ("Test was expected to fail:\n***BEGIN CODE***\n" ++ text ++ "\n*** END CODE ***\n") Right result -> assertFailure ("Test was expected to fail:\n***BEGIN CODE***\n" ++ text ++ "\n*** END CODE ***\n")
where parser = do { p <- prod ; eof ; return p} where parser = do { p <- prod ; eof ; return p}
emptySeveral :: A.Structured emptySeveral :: Data a => A.Structured a
emptySeveral = A.Several m [] emptySeveral = A.Several m []
emptySeveralAST :: A.AST
emptySeveralAST = emptySeveral
-- | A handy synonym for the empty block -- | A handy synonym for the empty block
emptyBlock :: A.Process emptyBlock :: A.Process
emptyBlock = A.Seq m emptySeveral emptyBlock = A.Seq m emptySeveral
@ -266,8 +269,8 @@ testRange =
makeIf :: [(A.Expression,A.Process)] -> A.Process makeIf :: [(A.Expression,A.Process)] -> A.Process
makeIf list = A.If m $ A.Several m (map makeChoice list) makeIf list = A.If m $ A.Several m (map makeChoice list)
where where
makeChoice :: (A.Expression,A.Process) -> A.Structured makeChoice :: (A.Expression,A.Process) -> A.Structured A.Choice
makeChoice (exp,proc) = A.OnlyC m $ A.Choice m exp proc makeChoice (exp,proc) = A.Only m $ A.Choice m exp proc
dyExp :: A.DyadicOp -> A.Variable -> A.Variable -> A.Expression dyExp :: A.DyadicOp -> A.Variable -> A.Variable -> A.Expression
dyExp op v0 v1 = A.Dyadic m op (A.ExprVariable m v0) (A.ExprVariable m v1) dyExp op v0 v1 = A.Dyadic m op (A.ExprVariable m v0) (A.ExprVariable m v1)
@ -355,19 +358,19 @@ testPar =
[ [
passPar (0, "par { }", A.Par m A.PlainPar $ A.Several m [] ) passPar (0, "par { }", A.Par m A.PlainPar $ A.Several m [] )
,passPar (1, "par { {} {} }", A.Par m A.PlainPar $ A.Several m [A.OnlyP m emptyBlock, A.OnlyP m emptyBlock] ) ,passPar (1, "par { {} {} }", A.Par m A.PlainPar $ A.Several m [A.Only m emptyBlock, A.Only m emptyBlock] )
--Rain only allows declarations at the beginning of a par block: --Rain only allows declarations at the beginning of a par block:
,passPar (2, "par {int:x; {} }", A.Par m A.PlainPar $ ,passPar (2, "par {int:x; {} }", A.Par m A.PlainPar $
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) $
A.Several m [A.OnlyP m $ A.Seq m $ A.Several m []] ) A.Several m [A.Only m $ A.Seq m $ A.Several m []] )
,passPar (3, "par {uint16:x; uint32:y; {} }", A.Par m A.PlainPar $ ,passPar (3, "par {uint16:x; uint32:y; {} }", A.Par m A.PlainPar $
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.UInt16 Nothing) $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.UInt16 Nothing) $
A.Spec m (A.Specification m (simpleName "y") $ A.Declaration m A.UInt32 Nothing) $ A.Spec m (A.Specification m (simpleName "y") $ A.Declaration m A.UInt32 Nothing) $
A.Several m [A.OnlyP m $ A.Seq m $ A.Several m []] ) A.Several m [A.Only m $ A.Seq m $ A.Several m []] )
,fail ("par { {} int: x; }",RP.statement) ,fail ("par { {} int: x; }",RP.statement)
] ]
@ -376,26 +379,26 @@ testPar =
passPar (ind, input, exp) = pass (input,RP.statement, assertPatternMatch ("testPar " ++ show ind) (pat exp)) passPar (ind, input, exp) = pass (input,RP.statement, assertPatternMatch ("testPar " ++ show ind) (pat exp))
-- | Test innerBlock, particularly with declarations mixed with statements: -- | Test innerBlock, particularly with declarations mixed with statements:
testBlock :: [ParseTest A.Structured] testBlock :: [ParseTest (A.Structured A.Process)]
testBlock = testBlock =
[ [
passBlock (0, "{ a = b; }", False, A.Several m [A.OnlyP m $ makeSimpleAssign "a" "b"]) passBlock (0, "{ a = b; }", False, A.Several m [A.Only m $ makeSimpleAssign "a" "b"])
,passBlock (1, "{ a = b; b = c; }", False, ,passBlock (1, "{ a = b; b = c; }", False,
A.Several m [A.OnlyP m $ makeSimpleAssign "a" "b",A.OnlyP m $ makeSimpleAssign "b" "c"]) A.Several m [A.Only m $ makeSimpleAssign "a" "b",A.Only m $ makeSimpleAssign "b" "c"])
,passBlock (2, "{ uint8: x; a = b; }", False, ,passBlock (2, "{ uint8: x; a = b; }", False,
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Byte noInit) $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Byte noInit) $
A.Several m [A.OnlyP m $ makeSimpleAssign "a" "b"]) A.Several m [A.Only m $ makeSimpleAssign "a" "b"])
,passBlock (3, "{ uint8: x; a = b; b = c; }", False, ,passBlock (3, "{ uint8: x; a = b; b = c; }", False,
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Byte noInit) $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Byte noInit) $
A.Several m [A.OnlyP m $ makeSimpleAssign "a" "b",A.OnlyP m $ makeSimpleAssign "b" "c"]) A.Several m [A.Only m $ makeSimpleAssign "a" "b",A.Only m $ makeSimpleAssign "b" "c"])
,passBlock (4, "{ b = c; uint8: x; a = b; }", False, ,passBlock (4, "{ b = c; uint8: x; a = b; }", False,
A.Several m [A.OnlyP m $ makeSimpleAssign "b" "c", A.Several m [A.Only m $ makeSimpleAssign "b" "c",
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Byte noInit) $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Byte noInit) $
A.Several m [A.OnlyP m $ makeSimpleAssign "a" "b"] A.Several m [A.Only m $ makeSimpleAssign "a" "b"]
]) ])
,passBlock (5, "{ uint8: x; }", False, ,passBlock (5, "{ uint8: x; }", False,
@ -404,7 +407,7 @@ testBlock =
,fail("{b}",RP.innerBlock False) ,fail("{b}",RP.innerBlock False)
] ]
where where
passBlock :: (Int, String, Bool, A.Structured) -> ParseTest A.Structured passBlock :: (Int, String, Bool, A.Structured A.Process) -> ParseTest (A.Structured A.Process)
passBlock (ind, input, b, exp) = pass (input, RP.innerBlock b, assertPatternMatch ("testBlock " ++ show ind) (pat exp)) passBlock (ind, input, b, exp) = pass (input, RP.innerBlock b, assertPatternMatch ("testBlock " ++ show ind) (pat exp))
testEach :: [ParseTest A.Process] testEach :: [ParseTest A.Process]
@ -412,13 +415,13 @@ testEach =
[ [
pass ("seqeach (c : \"1\") par {c = 7;}", RP.statement, pass ("seqeach (c : \"1\") par {c = 7;}", RP.statement,
assertPatternMatch "Each Test 0" (pat $ A.Seq m $ A.Rep m (A.ForEach m (simpleName "c") (makeLiteralStringRain "1")) $ assertPatternMatch "Each Test 0" (pat $ A.Seq m $ A.Rep m (A.ForEach m (simpleName "c") (makeLiteralStringRain "1")) $
A.OnlyP m $ makePar [(makeAssign (variable "c") (A.Literal m A.Int (A.IntLiteral m "7")))] )) A.Only m $ makePar [(makeAssign (variable "c") (A.Literal m A.Int (A.IntLiteral m "7")))] ))
,pass ("pareach (c : \"345\") {c = 1; c = 2;}", RP.statement, ,pass ("pareach (c : \"345\") {c = 1; c = 2;}", RP.statement,
assertPatternMatch "Each Test 1" $ pat $ A.Par m A.PlainPar $ A.Rep m (A.ForEach m (simpleName "c") (makeLiteralStringRain "345")) $ assertPatternMatch "Each Test 1" $ pat $ A.Par m A.PlainPar $ A.Rep m (A.ForEach m (simpleName "c") (makeLiteralStringRain "345")) $
A.OnlyP m $ makeSeq[(makeAssign (variable "c") (A.Literal m A.Int (A.IntLiteral m "1"))),(makeAssign (variable "c") (A.Literal m A.Int (A.IntLiteral m "2")))] ) A.Only m $ makeSeq[(makeAssign (variable "c") (A.Literal m A.Int (A.IntLiteral m "1"))),(makeAssign (variable "c") (A.Literal m A.Int (A.IntLiteral m "2")))] )
] ]
testTopLevelDecl :: [ParseTest A.Structured] testTopLevelDecl :: [ParseTest A.AST]
testTopLevelDecl = testTopLevelDecl =
[ [
passTop (0, "process noargs() {}", passTop (0, "process noargs() {}",
@ -447,22 +450,24 @@ testTopLevelDecl =
, fail ("process foo (int: x)", RP.topLevelDecl) , fail ("process foo (int: x)", RP.topLevelDecl)
, fail ("process foo (int x) {}", RP.topLevelDecl) , fail ("process foo (int x) {}", RP.topLevelDecl)
{- TODO get functions going again
,passTop (100, "function uint8: cons() {}", ,passTop (100, "function uint8: cons() {}",
[A.Spec m (A.Specification m (simpleName "cons") $ A.Function m A.PlainSpec [A.Byte] [] $ A.OnlyP m emptyBlock) emptySeveral]) [A.Spec m (A.Specification m (simpleName "cons") $ A.Function m A.PlainSpec [A.Byte] [] $ A.Only m emptyBlock) emptySeveral])
,passTop (101, "function uint8: f(uint8: x) {}", ,passTop (101, "function uint8: f(uint8: x) {}",
[A.Spec m (A.Specification m (simpleName "f") $ [A.Spec m (A.Specification m (simpleName "f") $
A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ A.OnlyP m emptyBlock) A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ A.Only m emptyBlock)
emptySeveral]) emptySeveral])
,passTop (102, "function uint8: id(uint8: x) {return x;}", ,passTop (102, "function uint8: id(uint8: x) {return x;}",
[A.Spec m (A.Specification m (simpleName "id") $ [A.Spec m (A.Specification m (simpleName "id") $
A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $
A.OnlyP m $ A.Seq m $ A.Several m [A.OnlyEL m $ A.ExpressionList m [exprVariable "x"]]) A.Only m $ A.Seq m $ A.Several m [A.Only m $ A.ExpressionList m [exprVariable "x"]])
emptySeveral]) emptySeveral])
-}
] ]
where where
passTop :: (Int, String, [A.Structured]) -> ParseTest A.Structured passTop :: (Int, String, [A.AST]) -> ParseTest A.AST
passTop (ind, input, exp) = pass (input, RP.topLevelDecl, assertPatternMatch ("testTopLevelDecl " ++ show ind) $ pat $ A.Several m exp) passTop (ind, input, exp) = pass (input, RP.topLevelDecl, assertPatternMatch ("testTopLevelDecl " ++ show ind) $ pat $ A.Several m exp)
nonShared :: A.ChanAttributes nonShared :: A.ChanAttributes
@ -507,7 +512,10 @@ testDataType =
,pass ("timer",RP.dataType,assertEqual "testDataType 301" $ A.UserDataType $ typeName "timer") ,pass ("timer",RP.dataType,assertEqual "testDataType 301" $ A.UserDataType $ typeName "timer")
] ]
testDecl :: [ParseTest (Meta, A.Structured -> A.Structured)] instance Data a => Show (A.Structured a -> A.Structured a) where
show _ = "<function over Structured"
testDecl :: [ParseTest (Meta, A.AST -> A.AST)]
testDecl = testDecl =
[ [
passd ("bool: b;",0,pat $ A.Specification m (simpleName "b") $ A.Declaration m A.Bool noInit) passd ("bool: b;",0,pat $ A.Specification m (simpleName "b") $ A.Declaration m A.Bool noInit)
@ -530,15 +538,17 @@ testDecl =
,fail ("bool: b0 b1;",RP.declaration) ,fail ("bool: b0 b1;",RP.declaration)
] ]
where where
passd :: (String,Int,Pattern) -> ParseTest (Meta, A.Structured -> A.Structured) specAST = (A.Spec :: Meta -> A.Specification -> A.AST -> A.AST)
passd :: (String,Int,Pattern) -> ParseTest (Meta, A.AST -> A.AST)
passd (code,index,exp) = pass(code,RP.declaration,check ("testDecl " ++ (show index)) exp) passd (code,index,exp) = pass(code,RP.declaration,check ("testDecl " ++ (show index)) exp)
check :: String -> Pattern -> (Meta, A.Structured -> A.Structured) -> Assertion check :: String -> Pattern -> (Meta, A.AST -> A.AST) -> Assertion
check msg spec (_,act) = assertPatternMatch msg (tag3 A.Spec DontCare spec $ emptySeveral) (act $ emptySeveral) check msg spec (_,act) = assertPatternMatch msg (tag3 specAST DontCare spec $ emptySeveralAST) (act $ emptySeveralAST)
passd2 :: (String,Int,Pattern,Pattern) -> ParseTest (Meta, A.Structured -> A.Structured) passd2 :: (String,Int,Pattern,Pattern) -> ParseTest (Meta, A.AST -> A.AST)
passd2 (code,index,expOuter,expInner) = pass(code,RP.declaration,check2 ("testDecl " ++ (show index)) expOuter expInner) passd2 (code,index,expOuter,expInner) = pass(code,RP.declaration,check2 ("testDecl " ++ (show index)) expOuter expInner)
check2 :: String -> Pattern -> Pattern -> (Meta, A.Structured -> A.Structured) -> Assertion check2 :: String -> Pattern -> Pattern -> (Meta, A.AST -> A.AST) -> Assertion
check2 msg specOuter specInner (_,act) = assertPatternMatch msg (tag3 A.Spec DontCare specOuter $ tag3 A.Spec DontCare specInner $ A.Several m []) (act $ A.Several m []) check2 msg specOuter specInner (_,act) = assertPatternMatch msg (tag3 specAST DontCare specOuter $ tag3 specAST DontCare specInner $ emptySeveralAST) (act $ emptySeveralAST)
testComm :: [ParseTest A.Process] testComm :: [ParseTest A.Process]
testComm = testComm =
@ -571,26 +581,26 @@ testAlt :: [ParseTest A.Process]
testAlt = testAlt =
[ [
passAlt (0, "pri alt {}", A.Alt m True $ A.Several m []) passAlt (0, "pri alt {}", A.Alt m True $ A.Several m [])
,passAlt (1, "pri alt { c ? x {} }", A.Alt m True $ A.Several m [A.OnlyA m $ A.Alternative m ,passAlt (1, "pri alt { c ? x {} }", A.Alt m True $ A.Several m [A.Only m $ A.Alternative m
(variable "c") (A.InputSimple m [A.InVariable m (variable "x")]) emptyBlock]) (variable "c") (A.InputSimple m [A.InVariable m (variable "x")]) emptyBlock])
,passAlt (2, "pri alt { c ? x {} d ? y {} }", A.Alt m True $ A.Several m [ ,passAlt (2, "pri alt { c ? x {} d ? y {} }", A.Alt m True $ A.Several m [
A.OnlyA m $ A.Alternative m (variable "c") (A.InputSimple m [A.InVariable m (variable "x")]) emptyBlock A.Only m $ A.Alternative m (variable "c") (A.InputSimple m [A.InVariable m (variable "x")]) emptyBlock
,A.OnlyA m $ A.Alternative m (variable "d") (A.InputSimple m [A.InVariable m (variable "y")]) emptyBlock]) ,A.Only m $ A.Alternative m (variable "d") (A.InputSimple m [A.InVariable m (variable "y")]) emptyBlock])
--Fairly nonsensical, but valid: --Fairly nonsensical, but valid:
,passAlt (3, "pri alt { else {} }", A.Alt m True $ A.Several m [ ,passAlt (3, "pri alt { else {} }", A.Alt m True $ A.Several m [
A.OnlyA m $ A.AlternativeSkip m (A.True m) emptyBlock]) A.Only m $ A.AlternativeSkip m (A.True m) emptyBlock])
,passAlt (4, "pri alt { c ? x {} else {} }", A.Alt m True $ A.Several m [ ,passAlt (4, "pri alt { c ? x {} else {} }", A.Alt m True $ A.Several m [
A.OnlyA m $ A.Alternative m (variable "c") (A.InputSimple m [A.InVariable m (variable "x")]) emptyBlock A.Only m $ A.Alternative m (variable "c") (A.InputSimple m [A.InVariable m (variable "x")]) emptyBlock
,A.OnlyA m $ A.AlternativeSkip m (A.True m) emptyBlock]) ,A.Only m $ A.AlternativeSkip m (A.True m) emptyBlock])
,passAlt (100, "pri alt { wait for t {} }", A.Alt m True $ A.Several m [ ,passAlt (100, "pri alt { wait for t {} }", A.Alt m True $ A.Several m [
A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t") emptyBlock]) A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t") emptyBlock])
,passAlt (101, "pri alt { wait for t {} wait until t {} }", A.Alt m True $ A.Several m [ ,passAlt (101, "pri alt { wait for t {} wait until t {} }", A.Alt m True $ A.Several m [
A.OnlyA m $ A.AlternativeWait m A.WaitFor (exprVariable "t") emptyBlock A.Only m $ A.AlternativeWait m A.WaitFor (exprVariable "t") emptyBlock
,A.OnlyA m $ A.AlternativeWait m A.WaitUntil (exprVariable "t") emptyBlock]) ,A.Only m $ A.AlternativeWait m A.WaitUntil (exprVariable "t") emptyBlock])
,passAlt (102, "pri alt { wait until t + t {} else {} }", A.Alt m True $ A.Several m [ ,passAlt (102, "pri alt { wait until t + t {} else {} }", A.Alt m True $ A.Several m [
A.OnlyA m $ A.AlternativeWait m A.WaitUntil (buildExpr $ Dy (Var "t") A.Plus (Var "t")) emptyBlock A.Only m $ A.AlternativeWait m A.WaitUntil (buildExpr $ Dy (Var "t") A.Plus (Var "t")) emptyBlock
,A.OnlyA m $ A.AlternativeSkip m (A.True m) emptyBlock]) ,A.Only m $ A.AlternativeSkip m (A.True m) emptyBlock])

View File

@ -86,9 +86,9 @@ transformInt = everywhereM (mkM transformInt')
-- This may seem like three passes in one, but if you try to separate them out, it just ends up -- This may seem like three passes in one, but if you try to separate them out, it just ends up
-- with more confusion and more code. -- with more confusion and more code.
uniquifyAndResolveVars :: Data t => t -> PassM t uniquifyAndResolveVars :: Data t => t -> PassM t
uniquifyAndResolveVars = everywhereM (mkM uniquifyAndResolveVars') uniquifyAndResolveVars = everywhereM (mk1M uniquifyAndResolveVars')
where where
uniquifyAndResolveVars' :: A.Structured -> PassM A.Structured uniquifyAndResolveVars' :: Data a => A.Structured a -> PassM (A.Structured a)
--Variable declarations: --Variable declarations:
uniquifyAndResolveVars' (A.Spec m (A.Specification m' n decl@(A.Declaration {})) scope) uniquifyAndResolveVars' (A.Spec m (A.Specification m' n decl@(A.Declaration {})) scope)
@ -164,9 +164,9 @@ checkIntegral _ = Nothing
-- | Transforms seqeach\/pareach loops over things like [0..99] into SEQ i = 0 FOR 100 loops -- | Transforms seqeach\/pareach loops over things like [0..99] into SEQ i = 0 FOR 100 loops
transformEachRange :: Data t => t -> PassM t transformEachRange :: Data t => t -> PassM t
transformEachRange = everywhereM (mkM transformEachRange') transformEachRange = everywhereM (mk1M transformEachRange')
where where
transformEachRange' :: A.Structured -> PassM A.Structured transformEachRange' :: forall a. Data a => A.Structured a -> PassM (A.Structured a)
transformEachRange' s@(A.Rep m _ _) transformEachRange' s@(A.Rep m _ _)
= case getMatchedItems patt s of = case getMatchedItems patt s of
Left _ -> return s --Doesn't match, return the original Left _ -> return s --Doesn't match, return the original
@ -183,7 +183,8 @@ transformEachRange = everywhereM (mkM transformEachRange')
) body ) body
else dieP eachMeta "Items in range constructor (x..y) are not integer literals" else dieP eachMeta "Items in range constructor (x..y) are not integer literals"
where where
patt = tag3 A.Rep (Named "repMeta" DontCare) ( patt :: Pattern
patt = tag3 (A.Rep :: Meta -> A.Replicator -> A.Structured a -> A.Structured a) (Named "repMeta" DontCare) (
tag3 A.ForEach (Named "eachMeta" DontCare) (Named "loopVar" DontCare) $ tag3 A.ForEach (Named "eachMeta" DontCare) (Named "loopVar" DontCare) $
tag2 A.ExprConstr DontCare $ tag2 A.ExprConstr DontCare $
tag3 A.RangeConstr DontCare (tag3 A.Literal DontCare DontCare $ Named "begin" DontCare) tag3 A.RangeConstr DontCare (tag3 A.Literal DontCare DontCare $ Named "begin" DontCare)
@ -197,9 +198,9 @@ transformEachRange = everywhereM (mkM transformEachRange')
-- | A pass that changes all the 'A.ForEach' replicators in the AST into 'A.For' replicators. -- | A pass that changes all the 'A.ForEach' replicators in the AST into 'A.For' replicators.
transformEach :: Data t => t -> PassM t transformEach :: Data t => t -> PassM t
transformEach = everywhereM (mkM transformEach') transformEach = everywhereM (mk1M transformEach')
where where
transformEach' :: A.Structured -> PassM A.Structured transformEach' :: Data a => A.Structured a -> PassM (A.Structured a)
transformEach' (A.Rep m (A.ForEach m' loopVar loopExp) s) transformEach' (A.Rep m (A.ForEach m' loopVar loopExp) s)
= do (spec,var,am) <- case loopExp of = do (spec,var,am) <- case loopExp of
(A.ExprVariable _ v) -> return (id,v,A.Abbrev) (A.ExprVariable _ v) -> return (id,v,A.Abbrev)
@ -246,12 +247,12 @@ transformRangeRep = everywhereM (mkM transformRangeRep')
transformRangeRep' s = return s transformRangeRep' s = return s
transformFunction :: Data t => t -> PassM t transformFunction :: Data t => t -> PassM t
transformFunction = everywhereM (mkM transformFunction') transformFunction = return {- TODO handle functions again everywhereM (mkM transformFunction')
where where
transformFunction' :: A.SpecType -> PassM A.SpecType transformFunction' :: A.SpecType -> PassM A.SpecType
transformFunction' (A.Function m specMode types params body) transformFunction' (A.Function m specMode types params body)
= case body of = case body of
(A.OnlyP _ (A.Seq m' (A.Several m'' statements))) -> (A.Only _ (A.Seq m' (A.Several m'' statements))) ->
if (null statements) if (null statements)
then dieP m "Functions must not have empty bodies" then dieP m "Functions must not have empty bodies"
else case (last statements) of else case (last statements) of
@ -262,6 +263,7 @@ transformFunction = everywhereM (mkM transformFunction')
_ -> dieP m "Functions must have a return statement as their last statement" _ -> dieP m "Functions must have a return statement as their last statement"
_ -> dieP m "Functions must have seq[uential] bodies" _ -> dieP m "Functions must have seq[uential] bodies"
transformFunction' s = return s transformFunction' s = return s
-}
pullUpParDeclarations :: Data t => t -> PassM t pullUpParDeclarations :: Data t => t -> PassM t
pullUpParDeclarations = everywhereM (mkM pullUpParDeclarations') pullUpParDeclarations = everywhereM (mkM pullUpParDeclarations')
@ -269,11 +271,11 @@ pullUpParDeclarations = everywhereM (mkM pullUpParDeclarations')
pullUpParDeclarations' :: A.Process -> PassM A.Process pullUpParDeclarations' :: A.Process -> PassM A.Process
pullUpParDeclarations' p@(A.Par m mode inside) pullUpParDeclarations' p@(A.Par m mode inside)
= case chaseSpecs inside of = case chaseSpecs inside of
Just (specs, innerCode) -> return $ A.Seq m $ specs $ A.OnlyP m $ A.Par m mode innerCode Just (specs, innerCode) -> return $ A.Seq m $ specs $ A.Only m $ A.Par m mode innerCode
Nothing -> return p Nothing -> return p
pullUpParDeclarations' p = return p pullUpParDeclarations' p = return p
chaseSpecs :: A.Structured -> Maybe (A.Structured -> A.Structured, A.Structured) chaseSpecs :: A.Structured A.Process -> Maybe (A.Structured A.Process -> A.Structured A.Process, A.Structured A.Process)
chaseSpecs (A.Spec m spec inner) chaseSpecs (A.Spec m spec inner)
= case chaseSpecs inner of = case chaseSpecs inner of
Nothing -> Just (A.Spec m spec,inner) Nothing -> Just (A.Spec m spec,inner)

View File

@ -45,9 +45,9 @@ import TagAST
import TestUtils import TestUtils
import TreeUtils import TreeUtils
-- | A helper function that returns a simple A.Structured item (A.OnlyP m $ A.Skip m). -- | A helper function that returns a simple A.Structured A.Process item (A.Only m $ A.Skip m).
skipP :: A.Structured skipP :: A.Structured A.Process
skipP = A.OnlyP m (A.Skip m) skipP = A.Only m (A.Skip m)
-- | A function that tries to cast a given value into the return type, and dies (using "dieInternal") -- | A function that tries to cast a given value into the return type, and dies (using "dieInternal")
-- if the cast isn't valid. -- if the cast isn't valid.
@ -65,16 +65,16 @@ testEachPass0 = TestCase $ testPassWithItemsStateCheck "testEachPass0" exp (tran
orig = A.Seq m orig = A.Seq m
(A.Rep m (A.Rep m
(A.ForEach m (simpleName "c") (makeLiteralStringRain "1")) (A.ForEach m (simpleName "c") (makeLiteralStringRain "1"))
(A.OnlyP m (makeAssign (variable "c") (intLiteral 7))) (A.Only m (makeAssign (variable "c") (intLiteral 7)))
) )
exp = mSeq exp = mSeq
(mSpec (mSpecP
(mSpecification listVarName (mSpecification listVarName
(mIsExpr A.ValAbbrev (A.List A.Byte) (makeLiteralStringRain "1")) (mIsExpr A.ValAbbrev (A.List A.Byte) (makeLiteralStringRain "1"))
) )
(mRep (mRepP
(mFor indexVar (intLiteral 0) (tag2 A.SizeVariable DontCare listVar)) (mFor indexVar (intLiteral 0) (tag2 A.SizeVariable DontCare listVar))
(mSpec (mSpecP
(mSpecification (simpleName "c") (mSpecification (simpleName "c")
--ValAbbrev because we are abbreviating an expression: --ValAbbrev because we are abbreviating an expression:
(mIs A.ValAbbrev A.Byte (mIs A.ValAbbrev A.Byte
@ -84,7 +84,7 @@ testEachPass0 = TestCase $ testPassWithItemsStateCheck "testEachPass0" exp (tran
) )
) )
) )
(A.OnlyP m (makeAssign (variable "c") (intLiteral 7))) (A.Only m (makeAssign (variable "c") (intLiteral 7)))
) )
) )
) )
@ -114,12 +114,12 @@ testEachPass1 = TestCase $ testPassWithItemsStateCheck "testEachPass0" exp (tran
orig = A.Par m A.PlainPar orig = A.Par m A.PlainPar
(A.Rep m (A.Rep m
(A.ForEach m (simpleName "c") (A.ExprVariable m (variable "d"))) (A.ForEach m (simpleName "c") (A.ExprVariable m (variable "d")))
(A.OnlyP m (makeAssign (variable "c") (intLiteral 7))) (A.Only m (makeAssign (variable "c") (intLiteral 7)))
) )
exp = tag3 A.Par DontCare A.PlainPar exp = tag3 A.Par DontCare A.PlainPar
(tag3 A.Rep DontCare (mRepP
(tag4 A.For DontCare indexVar (intLiteral 0) (tag2 A.SizeVariable DontCare (variable "d"))) (tag4 A.For DontCare indexVar (intLiteral 0) (tag2 A.SizeVariable DontCare (variable "d")))
(tag3 A.Spec DontCare (mSpecP
(tag3 A.Specification DontCare (simpleName "c") (tag3 A.Specification DontCare (simpleName "c")
(tag4 A.Is DontCare A.Abbrev A.Byte (tag4 A.Is DontCare A.Abbrev A.Byte
(tag3 A.SubscriptedVariable DontCare (tag3 A.SubscriptedVariable DontCare
@ -128,7 +128,7 @@ testEachPass1 = TestCase $ testPassWithItemsStateCheck "testEachPass0" exp (tran
) )
) )
) )
(A.OnlyP m (makeAssign (variable "c") (intLiteral 7))) (A.Only m (makeAssign (variable "c") (intLiteral 7)))
) )
) )
indexVar = Named "indexVar" DontCare indexVar = Named "indexVar" DontCare
@ -145,40 +145,40 @@ testEachRangePass0 = TestCase $ testPass "testEachRangePass0" exp (transformEach
where where
orig = A.Par m A.PlainPar $ A.Rep m orig = A.Par m A.PlainPar $ A.Rep m
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral 0) (intLiteral 9)))) (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral 0) (intLiteral 9))))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
exp = A.Par m A.PlainPar $ A.Rep m exp = A.Par m A.PlainPar $ A.Rep m
(A.For m (simpleName "x") (intLiteral 0) (intLiteral 10)) (A.For m (simpleName "x") (intLiteral 0) (intLiteral 10))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
testEachRangePass1 :: Test testEachRangePass1 :: Test
testEachRangePass1 = TestCase $ testPass "testEachRangePass1" exp (transformEachRange orig) (return ()) testEachRangePass1 = TestCase $ testPass "testEachRangePass1" exp (transformEachRange orig) (return ())
where where
orig = A.Par m A.PlainPar $ A.Rep m orig = A.Par m A.PlainPar $ A.Rep m
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral (-5)) (intLiteral (-2))))) (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral (-5)) (intLiteral (-2)))))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
exp = A.Par m A.PlainPar $ A.Rep m exp = A.Par m A.PlainPar $ A.Rep m
(A.For m (simpleName "x") (intLiteral (-5)) (intLiteral 4)) (A.For m (simpleName "x") (intLiteral (-5)) (intLiteral 4))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
testEachRangePass2 :: Test testEachRangePass2 :: Test
testEachRangePass2 = TestCase $ testPass "testEachRangePass2" exp (transformEachRange orig) (return ()) testEachRangePass2 = TestCase $ testPass "testEachRangePass2" exp (transformEachRange orig) (return ())
where where
orig = A.Seq m $ A.Rep m orig = A.Seq m $ A.Rep m
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral 6) (intLiteral 6)))) (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral 6) (intLiteral 6))))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
exp = A.Seq m $ A.Rep m exp = A.Seq m $ A.Rep m
(A.For m (simpleName "x") (intLiteral 6) (intLiteral 1)) (A.For m (simpleName "x") (intLiteral 6) (intLiteral 1))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
testEachRangePass3 :: Test testEachRangePass3 :: Test
testEachRangePass3 = TestCase $ testPass "testEachRangePass3" exp (transformEachRange orig) (return ()) testEachRangePass3 = TestCase $ testPass "testEachRangePass3" exp (transformEachRange orig) (return ())
where where
orig = A.Seq m $ A.Rep m orig = A.Seq m $ A.Rep m
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral 6) (intLiteral 0)))) (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m (intLiteral 6) (intLiteral 0))))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
exp = A.Seq m $ A.Rep m exp = A.Seq m $ A.Rep m
(A.For m (simpleName "x") (intLiteral 6) (intLiteral (-5))) (A.For m (simpleName "x") (intLiteral 6) (intLiteral (-5)))
(A.OnlyP m (makeSimpleAssign "c" "x")) (A.Only m (makeSimpleAssign "c" "x"))
-- | Test variable is made unique in a declaration: -- | Test variable is made unique in a declaration:
@ -186,7 +186,7 @@ testUnique0 :: Test
testUnique0 = TestCase $ testPassWithItemsStateCheck "testUnique0" exp (uniquifyAndResolveVars orig) (return ()) check testUnique0 = TestCase $ testPassWithItemsStateCheck "testUnique0" exp (uniquifyAndResolveVars orig) (return ()) check
where where
orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) skipP orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) skipP
exp = tag3 A.Spec DontCare (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte Nothing) skipP exp = mSpecP (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte Nothing) skipP
check (items,state) check (items,state)
= do newcName <- castAssertADI (Map.lookup "newc" items) = do newcName <- castAssertADI (Map.lookup "newc" items)
assertNotEqual "testUnique0: Variable was not made unique" "c" (A.nameName newcName) assertNotEqual "testUnique0: Variable was not made unique" "c" (A.nameName newcName)
@ -199,8 +199,8 @@ testUnique1 = TestCase $ testPassWithItemsStateCheck "testUnique1" exp (uniquify
where where
orig = A.Several m [A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) skipP, orig = A.Several m [A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) skipP,
A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Int64 Nothing) skipP] A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Int64 Nothing) skipP]
exp = tag2 A.Several m [tag3 A.Spec DontCare (tag3 A.Specification DontCare ("newc0"@@DontCare) $ A.Declaration m A.Byte Nothing) skipP, exp = mSeveralP [mSpecP (tag3 A.Specification DontCare ("newc0"@@DontCare) $ A.Declaration m A.Byte Nothing) skipP,
tag3 A.Spec DontCare (tag3 A.Specification DontCare ("newc1"@@DontCare) $ A.Declaration m A.Int64 Nothing) skipP] mSpecP (tag3 A.Specification DontCare ("newc1"@@DontCare) $ A.Declaration m A.Int64 Nothing) skipP]
check (items,state) check (items,state)
= do newc0Name <- castAssertADI (Map.lookup "newc0" items) = do newc0Name <- castAssertADI (Map.lookup "newc0" items)
newc1Name <- castAssertADI (Map.lookup "newc1" items) newc1Name <- castAssertADI (Map.lookup "newc1" items)
@ -216,9 +216,9 @@ testUnique1 = TestCase $ testPassWithItemsStateCheck "testUnique1" exp (uniquify
testUnique2 :: Test testUnique2 :: Test
testUnique2 = TestCase $ testPassWithItemsStateCheck "testUnique2" exp (uniquifyAndResolveVars orig) (return ()) check testUnique2 = TestCase $ testPassWithItemsStateCheck "testUnique2" exp (uniquifyAndResolveVars orig) (return ()) check
where where
orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) (A.OnlyP m $ makeSimpleAssign "c" "d") orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) (A.Only m $ makeSimpleAssign "c" "d")
exp = tag3 A.Spec DontCare (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte Nothing) exp = mSpecP (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte Nothing)
(tag2 A.OnlyP m $ tag3 A.Assign DontCare [tag2 A.Variable DontCare ("newc"@@DontCare)] (tag2 A.ExpressionList DontCare [(exprVariable "d")])) (mOnlyP' m $ tag3 A.Assign DontCare [tag2 A.Variable DontCare ("newc"@@DontCare)] (tag2 A.ExpressionList DontCare [(exprVariable "d")]))
check (items,state) = do newcName <- castAssertADI (Map.lookup "newc" items) check (items,state) = do newcName <- castAssertADI (Map.lookup "newc" items)
assertNotEqual "testUnique2: Variable was not made unique" "c" (A.nameName newcName) assertNotEqual "testUnique2: Variable was not made unique" "c" (A.nameName newcName)
@ -227,11 +227,11 @@ testUnique2b :: Test
testUnique2b = TestCase $ testPassWithItemsStateCheck "testUnique2b" exp (uniquifyAndResolveVars orig) (return ()) check testUnique2b = TestCase $ testPassWithItemsStateCheck "testUnique2b" exp (uniquifyAndResolveVars orig) (return ()) check
where where
orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) $ orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte Nothing) $
A.Several m [(A.OnlyP m $ makeSimpleAssign "c" "d"),(A.OnlyP m $ makeSimpleAssign "c" "e")] A.Several m [(A.Only m $ makeSimpleAssign "c" "d"),(A.Only m $ makeSimpleAssign "c" "e")]
exp = tag3 A.Spec DontCare (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte Nothing) $ exp = mSpecP (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte Nothing) $
tag2 A.Several DontCare [ mSeveralP [
(tag2 A.OnlyP m $ tag3 A.Assign DontCare [tag2 A.Variable DontCare ("newc"@@DontCare)] (tag2 A.ExpressionList DontCare [(exprVariable "d")])) (mOnlyP' m $ tag3 A.Assign DontCare [tag2 A.Variable DontCare ("newc"@@DontCare)] (tag2 A.ExpressionList DontCare [(exprVariable "d")]))
,(tag2 A.OnlyP m $ tag3 A.Assign DontCare [tag2 A.Variable DontCare ("newc"@@DontCare)] (tag2 A.ExpressionList DontCare [(exprVariable "e")])) ,(mOnlyP' m $ tag3 A.Assign DontCare [tag2 A.Variable DontCare ("newc"@@DontCare)] (tag2 A.ExpressionList DontCare [(exprVariable "e")]))
] ]
check (items,state) = do newcName <- castAssertADI (Map.lookup "newc" items) check (items,state) = do newcName <- castAssertADI (Map.lookup "newc" items)
assertNotEqual "testUnique2: Variable was not made unique" "c" (A.nameName newcName) assertNotEqual "testUnique2: Variable was not made unique" "c" (A.nameName newcName)
@ -241,7 +241,7 @@ testUnique2b = TestCase $ testPassWithItemsStateCheck "testUnique2b" exp (uniqui
testUnique3 :: Test testUnique3 :: Test
testUnique3 = TestCase $ testPassWithItemsStateCheck "testUnique3" exp (uniquifyAndResolveVars orig) (return ()) check testUnique3 = TestCase $ testPassWithItemsStateCheck "testUnique3" exp (uniquifyAndResolveVars orig) (return ()) check
where where
orig = A.Spec m (A.Specification m (procName "foo") $ A.Proc m A.PlainSpec [] $ A.Skip m) (A.OnlyP m $ A.ProcCall m (procName "foo") []) orig = A.Spec m (A.Specification m (procName "foo") $ A.Proc m A.PlainSpec [] $ A.Skip m) (A.Only m $ A.ProcCall m (procName "foo") [])
exp = orig exp = orig
check (items,state) = assertVarDef "testUnique3: Variable was not recorded" state "foo" check (items,state) = assertVarDef "testUnique3: Variable was not recorded" state "foo"
(tag7 A.NameDef DontCare "foo" "foo" A.ProcName (A.Proc m A.PlainSpec [] $ A.Skip m) A.Original A.Unplaced) (tag7 A.NameDef DontCare "foo" "foo" A.ProcName (A.Proc m A.PlainSpec [] $ A.Skip m) A.Original A.Unplaced)
@ -252,7 +252,7 @@ testUnique4 = TestCase $ testPassWithItemsStateCheck "testUnique4" exp (uniquify
where where
orig = A.Spec m (A.Specification m (procName "foo") $ A.Proc m A.PlainSpec [A.Formal A.ValAbbrev A.Byte $ simpleName "c"] $ orig = A.Spec m (A.Specification m (procName "foo") $ A.Proc m A.PlainSpec [A.Formal A.ValAbbrev A.Byte $ simpleName "c"] $
A.ProcCall m (procName "foo") [A.ActualExpression A.Byte $ exprVariable "c"]) (skipP) A.ProcCall m (procName "foo") [A.ActualExpression A.Byte $ exprVariable "c"]) (skipP)
exp = tag3 A.Spec DontCare exp = mSpecP
(tag3 A.Specification DontCare (procNamePattern "foo") $ tag4 A.Proc DontCare A.PlainSpec (tag3 A.Specification DontCare (procNamePattern "foo") $ tag4 A.Proc DontCare A.PlainSpec
[tag3 A.Formal A.ValAbbrev A.Byte newc] [tag3 A.Formal A.ValAbbrev A.Byte newc]
(bodyPattern newc) (bodyPattern newc)
@ -302,7 +302,7 @@ testRecordInfNames2 = TestCase $ testPassWithStateCheck "testRecordInfNames2" ex
startState' :: State CompState () startState' :: State CompState ()
startState' = do defineName (simpleName "multi") $ simpleDef "multi" (A.Declaration m (A.List $ A.List A.Byte) Nothing) startState' = do defineName (simpleName "multi") $ simpleDef "multi" (A.Declaration m (A.List $ A.List A.Byte) Nothing)
orig = A.Rep m (A.ForEach m (simpleName "c") (exprVariable "multi")) $ orig = A.Rep m (A.ForEach m (simpleName "c") (exprVariable "multi")) $
A.OnlyP m $ A.Seq m $ A.Rep m (A.ForEach m (simpleName "d") (exprVariable "c")) skipP A.Only m $ A.Seq m $ A.Rep m (A.ForEach m (simpleName "d") (exprVariable "c")) skipP
exp = orig exp = orig
check state = do assertVarDef "testRecordInfNames2" state "c" check state = do assertVarDef "testRecordInfNames2" state "c"
(tag7 A.NameDef DontCare "c" "c" A.VariableName (A.Declaration m (A.List A.Byte) Nothing) A.Original A.Unplaced) (tag7 A.NameDef DontCare "c" "c" A.VariableName (A.Declaration m (A.List A.Byte) Nothing) A.Original A.Unplaced)
@ -327,9 +327,9 @@ testRecordInfNames3 = TestCase $ testPassShouldFail "testRecordInfNames3" (recor
testFindMain0 :: Test testFindMain0 :: Test
testFindMain0 = TestCase $ testPassWithItemsStateCheck "testFindMain0" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check testFindMain0 = TestCase $ testPassWithItemsStateCheck "testFindMain0" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
where where
orig = A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m [] orig = A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m [] :: A.AST
exp = tag3 A.Spec DontCare (tag3 A.Specification DontCare (tag3 A.Name DontCare A.ProcName ("main"@@DontCare)) $ exp = mSpecAST (tag3 A.Specification DontCare (tag3 A.Name DontCare A.ProcName ("main"@@DontCare)) $
tag4 A.Proc DontCare A.PlainSpec ([] :: [A.Formal]) (tag1 A.Skip DontCare)) $ tag2 A.Several DontCare ([] :: [A.Structured]) tag4 A.Proc DontCare A.PlainSpec ([] :: [A.Formal]) (tag1 A.Skip DontCare)) $ mSeveralAST ([] :: [A.AST])
check (items,state) check (items,state)
= do mainName <- castAssertADI (Map.lookup "main" items) = do mainName <- castAssertADI (Map.lookup "main" items)
assertNotEqual "testFindMain0 A" "main" mainName assertNotEqual "testFindMain0 A" "main" mainName
@ -340,17 +340,17 @@ testFindMain0 = TestCase $ testPassWithItemsStateCheck "testFindMain0" exp ((uni
testFindMain1 :: Test testFindMain1 :: Test
testFindMain1 = TestCase $ testPassWithStateCheck "testFindMain1" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check testFindMain1 = TestCase $ testPassWithStateCheck "testFindMain1" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
where where
orig = A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m [] orig = A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m ([] :: [A.AST])
check state = assertEqual "testFindMain1" [] (csMainLocals state) check state = assertEqual "testFindMain1" [] (csMainLocals state)
testFindMain2 :: Test testFindMain2 :: Test
testFindMain2 = TestCase $ testPassWithItemsStateCheck "testFindMain2" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check testFindMain2 = TestCase $ testPassWithItemsStateCheck "testFindMain2" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
where where
inner = A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ inner = A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Several m [] A.Several m ([] :: [A.AST])
orig = A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) inner orig = A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) inner
exp = tag3 A.Spec DontCare (tag3 A.Specification DontCare (tag3 A.Name DontCare A.ProcName ("main"@@DontCare)) $ exp = mSpecAST (tag3 A.Specification DontCare (tag3 A.Name DontCare A.ProcName ("main"@@DontCare)) $
tag4 A.Proc DontCare A.PlainSpec ([] :: [A.Formal]) (tag1 A.Skip DontCare)) (stopCaringPattern m $ mkPattern inner) tag4 A.Proc DontCare A.PlainSpec ([] :: [A.Formal]) (tag1 A.Skip DontCare)) (stopCaringPattern m $ mkPattern inner)
check (items,state) check (items,state)
= do mainName <- castAssertADI (Map.lookup "main" items) = do mainName <- castAssertADI (Map.lookup "main" items)
@ -380,7 +380,7 @@ testParamPass testName formals params transParams
startStateFunc = do defineName (simpleName "x") $ simpleDefDecl "x" (A.UInt16) startStateFunc = do defineName (simpleName "x") $ simpleDefDecl "x" (A.UInt16)
case formals of case formals of
Nothing -> return () Nothing -> return ()
Just formals' -> defineName (funcName "foo") $ simpleDef "foo" $ A.Function m A.PlainSpec [A.Byte] formals' (A.OnlyP m $ A.Skip m) Just formals' -> defineName (funcName "foo") $ simpleDef "foo" $ A.Function m A.PlainSpec [A.Byte] formals' (A.Only m $ A.ExpressionList m [])
origProc = A.ProcCall m (procName "foo") params origProc = A.ProcCall m (procName "foo") params
expProc ps = A.ProcCall m (procName "foo") ps expProc ps = A.ProcCall m (procName "foo") ps
origFunc = A.FunctionCall m (funcName "foo") (deActualise params) origFunc = A.FunctionCall m (funcName "foo") (deActualise params)
@ -474,17 +474,18 @@ testRangeRepPass1 = TestCase $ testPassShouldFail "testRangeRepPass1" (transform
--TODO consider/test pulling up the definitions of variables involved in return statements in functions --TODO consider/test pulling up the definitions of variables involved in return statements in functions
{-
-- | Test a fairly standard function: -- | Test a fairly standard function:
testTransformFunction0 :: Test testTransformFunction0 :: Test
testTransformFunction0 = TestCase $ testPass "testTransformFunction0" exp (transformFunction orig) (return ()) testTransformFunction0 = TestCase $ testPass "testTransformFunction0" exp (transformFunction orig) (return ())
where where
orig = A.Specification m (procName "id") $ orig = A.Specification m (procName "id") $
A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $
(A.OnlyP m $ A.Seq m $ A.Several m [A.OnlyEL m $ A.ExpressionList m [exprVariable "x"]]) (A.Only m $ A.Seq m $ A.Several m [A.Only m $ A.ExpressionList m [exprVariable "x"]])
exp = tag3 A.Specification DontCare (procNamePattern "id") $ exp = tag3 A.Specification DontCare (procNamePattern "id") $
tag5 A.Function DontCare A.PlainSpec [A.Byte] [tag3 A.Formal A.ValAbbrev A.Byte (simpleNamePattern "x")] $ tag5 A.Function DontCare A.PlainSpec [A.Byte] [tag3 A.Formal A.ValAbbrev A.Byte (simpleNamePattern "x")] $
tag3 A.ProcThen DontCare (tag2 A.Seq DontCare $ tag2 A.Several DontCare ([] :: [A.Structured])) $ tag3 A.ProcThen DontCare (tag2 A.Seq DontCare $ mSeveralP DontCare []) $
tag2 A.OnlyEL DontCare $ tag2 A.ExpressionList DontCare [exprVariablePattern "x"] mOnlyEL $ tag2 A.ExpressionList DontCare [exprVariablePattern "x"]
-- | Test a function without a return as the final statement: -- | Test a function without a return as the final statement:
testTransformFunction1 :: Test testTransformFunction1 :: Test
@ -492,8 +493,8 @@ testTransformFunction1 = TestCase $ testPassShouldFail "testTransformFunction1"
where where
orig = A.Specification m (procName "brokenid") $ orig = A.Specification m (procName "brokenid") $
A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $
(A.OnlyP m $ A.Seq m $ A.Several m []) (A.Only m $ A.Seq m $ A.Several m [])
-}
testPullUpParDecl0 :: Test testPullUpParDecl0 :: Test
testPullUpParDecl0 = TestCase $ testPass "testPullUpParDecl0" orig (pullUpParDeclarations orig) (return ()) testPullUpParDecl0 = TestCase $ testPass "testPullUpParDecl0" orig (pullUpParDeclarations orig) (return ())
where where
@ -504,7 +505,7 @@ testPullUpParDecl1 = TestCase $ testPass "testPullUpParDecl1" exp (pullUpParDecl
where where
orig = A.Par m A.PlainPar $ orig = A.Par m A.PlainPar $
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) (A.Several m []) A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) (A.Several m [])
exp = A.Seq m $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) (A.OnlyP m $ A.Par m A.PlainPar $ A.Several m []) exp = A.Seq m $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) (A.Only m $ A.Par m A.PlainPar $ A.Several m [])
testPullUpParDecl2 :: Test testPullUpParDecl2 :: Test
testPullUpParDecl2 = TestCase $ testPass "testPullUpParDecl2" exp (pullUpParDeclarations orig) (return ()) testPullUpParDecl2 = TestCase $ testPass "testPullUpParDecl2" exp (pullUpParDeclarations orig) (return ())
@ -515,7 +516,7 @@ testPullUpParDecl2 = TestCase $ testPass "testPullUpParDecl2" exp (pullUpParDecl
(A.Several m []) (A.Several m [])
exp = A.Seq m $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing) exp = A.Seq m $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int Nothing)
$ A.Spec m (A.Specification m (simpleName "y") $ A.Declaration m A.Byte Nothing) $ A.Spec m (A.Specification m (simpleName "y") $ A.Declaration m A.Byte Nothing)
(A.OnlyP m $ A.Par m A.PlainPar $ A.Several m []) (A.Only m $ A.Par m A.PlainPar $ A.Several m [])
---Returns the list of tests: ---Returns the list of tests:
tests :: Test tests :: Test
@ -551,8 +552,9 @@ tests = TestLabel "RainPassesTest" $ TestList
,testParamPass8 ,testParamPass8
,testRangeRepPass0 ,testRangeRepPass0
,testRangeRepPass1 ,testRangeRepPass1
,testTransformFunction0 -- TODO get functions working again
,testTransformFunction1 -- ,testTransformFunction0
-- ,testTransformFunction1
,testPullUpParDecl0 ,testPullUpParDecl0
,testPullUpParDecl1 ,testPullUpParDecl1
,testPullUpParDecl2 ,testPullUpParDecl2

View File

@ -287,8 +287,8 @@ checkExpressionTest = TestList
passWhileIf n exp src = TestList passWhileIf n exp src = TestList
[ [
TestCase $ testPass ("checkExpressionTest/if " ++ show n) TestCase $ testPass ("checkExpressionTest/if " ++ show n)
(mIf $ tag2 A.OnlyC DontCare $ tag3 A.Choice DontCare (buildExprPattern exp) (tag1 A.Skip DontCare)) (mIf $ mOnlyC $ tag3 A.Choice DontCare (buildExprPattern exp) (tag1 A.Skip DontCare))
(checkConditionalTypes $ A.If m $ A.OnlyC m $ A.Choice m (buildExpr src) (A.Skip m)) (checkConditionalTypes $ A.If m $ A.Only m $ A.Choice m (buildExpr src) (A.Skip m))
state state
,TestCase $ testPass ("checkExpressionTest/while " ++ show n) ,TestCase $ testPass ("checkExpressionTest/while " ++ show n)
(mWhile (buildExprPattern exp) (tag1 A.Skip DontCare)) (mWhile (buildExprPattern exp) (tag1 A.Skip DontCare))
@ -300,7 +300,7 @@ checkExpressionTest = TestList
failWhileIf n src = TestList failWhileIf n src = TestList
[ [
TestCase $ testPassShouldFail ("checkExpressionTest/if " ++ show n) TestCase $ testPassShouldFail ("checkExpressionTest/if " ++ show n)
(checkConditionalTypes $ A.If m $ A.OnlyC m $ A.Choice m (buildExpr src) (A.Skip m)) (checkConditionalTypes $ A.If m $ A.Only m $ A.Choice m (buildExpr src) (A.Skip m))
state state
,TestCase $ testPassShouldFail ("checkExpressionTest/while " ++ show n) ,TestCase $ testPassShouldFail ("checkExpressionTest/while " ++ show n)
(checkConditionalTypes $ A.While m (buildExpr src) (A.Skip m)) (checkConditionalTypes $ A.While m (buildExpr src) (A.Skip m))
@ -325,7 +325,7 @@ checkExpressionTest = TestList
then TestCase $ testPass ("testCheckCommTypesIn " ++ show n) (mkPattern st) (checkCommTypes st) state then TestCase $ testPass ("testCheckCommTypesIn " ++ show n) (mkPattern st) (checkCommTypes st) state
else TestCase $ testPassShouldFail ("testCheckCommTypesIn " ++ show n) (checkCommTypes st) state else TestCase $ testPassShouldFail ("testCheckCommTypesIn " ++ show n) (checkCommTypes st) state
where where
st = A.Alt m True $ A.OnlyA m $ A.Alternative m chanVar (A.InputSimple m [A.InVariable m destVar]) $ A.Skip m st = A.Alt m True $ A.Only m $ A.Alternative m chanVar (A.InputSimple m [A.InVariable m destVar]) $ A.Skip m
--Automatically tests checking inputs and outputs for various combinations of channel type and direction --Automatically tests checking inputs and outputs for various combinations of channel type and direction
testAllCheckCommTypes :: Int -> Test testAllCheckCommTypes :: Int -> Test

View File

@ -30,6 +30,7 @@ import Metadata
import Pattern import Pattern
import SimplifyComms import SimplifyComms
import SimplifyExprs import SimplifyExprs
import TagAST
import TestUtils import TestUtils
import TreeUtils import TreeUtils
@ -38,12 +39,12 @@ noInit :: Maybe A.Expression
noInit = Nothing noInit = Nothing
-- | An expression list containing a single value of 0. -- | An expression list containing a single value of 0.
valof0 :: A.Structured valof0 :: A.Structured A.ExpressionList
valof0 = A.OnlyEL m $ A.ExpressionList m [intLiteral 0] valof0 = A.Only m $ A.ExpressionList m [intLiteral 0]
-- | An expression list containing variables with the two given names. -- | An expression list containing variables with the two given names.
valofTwo :: String -> String -> A.Structured valofTwo :: String -> String -> A.Structured A.ExpressionList
valofTwo a b = A.OnlyEL m $ A.ExpressionList m [exprVariable a,exprVariable b] valofTwo a b = A.Only m $ A.ExpressionList m [exprVariable a,exprVariable b]
-- | Looks up an item from the Items, and attempts to cast it. Fails (via assertions) if -- | Looks up an item from the Items, and attempts to cast it. Fails (via assertions) if
-- either the item is not found, or if the cast is invalid. -- either the item is not found, or if the cast is invalid.
@ -56,13 +57,12 @@ assertGetItemCast k kv
Nothing -> (assertFailure $ "Wrong type when casting in assertGetItemCast for key: " ++ k) >> return (undefined) Nothing -> (assertFailure $ "Wrong type when casting in assertGetItemCast for key: " ++ k) >> return (undefined)
-- | Given a body, returns a function spec: -- | Given a body, returns a function spec:
singleParamFunc :: A.Structured-> A.Specification singleParamFunc :: A.Structured A.ExpressionList -> A.Specification
singleParamFunc body = A.Specification m (simpleName "foo") (A.Function m A.PlainSpec [A.Int] [A.Formal A.ValAbbrev A.Byte (simpleName "param0")] body) singleParamFunc body = A.Specification m (simpleName "foo") (A.Function m A.PlainSpec [A.Int] [A.Formal A.ValAbbrev A.Byte (simpleName "param0")] body)
-- | Returns the expected body of the single parameter process (when the function had valof0 as a body) -- | Returns the expected body of the single parameter process (when the function had valof0 as a body)
singleParamBodyExp :: Pattern -- ^ to match: A.Process singleParamBodyExp :: Pattern -- ^ to match: A.Process
singleParamBodyExp = tag2 A.Seq DontCare $ singleParamBodyExp = tag2 A.Seq DontCare $ mOnlyP $
tag2 A.OnlyP DontCare $
tag3 A.Assign DontCare [tag2 A.Variable DontCare (Named "ret0" DontCare)] $ tag2 A.ExpressionList DontCare [intLiteral 0] tag3 A.Assign DontCare [tag2 A.Variable DontCare (Named "ret0" DontCare)] $ tag2 A.ExpressionList DontCare [intLiteral 0]
-- | Returns the expected specification type of the single parameter process -- | Returns the expected specification type of the single parameter process
@ -98,7 +98,7 @@ testFunctionsToProcs1 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
tag3 A.Formal A.Abbrev A.Int (Named "ret0" DontCare), tag3 A.Formal A.Abbrev A.Int (Named "ret0" DontCare),
tag3 A.Formal A.Abbrev A.Real32 (Named "ret1" DontCare)] $ tag3 A.Formal A.Abbrev A.Real32 (Named "ret1" DontCare)] $
tag2 A.Seq DontCare $ tag2 A.Seq DontCare $
tag2 A.OnlyP DontCare $ mOnlyP $
tag3 A.Assign DontCare [tag2 A.Variable DontCare (Named "ret0" DontCare),tag2 A.Variable DontCare (Named "ret1" DontCare)] $ tag3 A.Assign DontCare [tag2 A.Variable DontCare (Named "ret0" DontCare),tag2 A.Variable DontCare (Named "ret1" DontCare)] $
tag2 A.ExpressionList DontCare [exprVariable "param0",exprVariable "param1"] tag2 A.ExpressionList DontCare [exprVariable "param0",exprVariable "param1"]
--check return parameters were defined: --check return parameters were defined:
@ -126,8 +126,8 @@ testFunctionsToProcs2 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
procHeader body = tag4 A.Proc DontCare A.PlainSpec [tag3 A.Formal A.ValAbbrev A.Byte (simpleName "paramOuter0"), tag3 A.Formal A.Abbrev A.Int (Named "retOuter0" DontCare)] body procHeader body = tag4 A.Proc DontCare A.PlainSpec [tag3 A.Formal A.ValAbbrev A.Byte (simpleName "paramOuter0"), tag3 A.Formal A.Abbrev A.Int (Named "retOuter0" DontCare)] body
procBodyOuter = procHeader $ procBodyOuter = procHeader $
tag2 A.Seq DontCare $ tag2 A.Seq DontCare $
tag3 A.Spec DontCare (tag3 A.Specification DontCare (simpleName "foo") (singleParamSpecExp singleParamBodyExp)) $ mSpecP (tag3 A.Specification DontCare (simpleName "foo") (singleParamSpecExp singleParamBodyExp)) $
tag2 A.OnlyP DontCare $ mOnlyP $
tag3 A.Assign DontCare [tag2 A.Variable DontCare (Named "retOuter0" DontCare)] $ tag2 A.ExpressionList DontCare [intLiteral 0] tag3 A.Assign DontCare [tag2 A.Variable DontCare (Named "retOuter0" DontCare)] $ tag2 A.ExpressionList DontCare [intLiteral 0]
@ -147,8 +147,8 @@ testFunctionsToProcs2 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
assertEqual "testFunctionsToProcs2 F" (Just [A.Int]) (Map.lookup "foo" (csFunctionReturns state)) assertEqual "testFunctionsToProcs2 F" (Just [A.Int]) (Map.lookup "foo" (csFunctionReturns state))
assertEqual "testFunctionsToProcs2 G" (Just [A.Int]) (Map.lookup "fooOuter" (csFunctionReturns state)) assertEqual "testFunctionsToProcs2 G" (Just [A.Int]) (Map.lookup "fooOuter" (csFunctionReturns state))
skipP :: A.Structured skipP :: A.Structured A.Process
skipP = A.OnlyP m (A.Skip m) skipP = A.Only m (A.Skip m)
-- | Tests that a simple constructor (with no expression, nor function call) gets converted into the appropriate initialisation code -- | Tests that a simple constructor (with no expression, nor function call) gets converted into the appropriate initialisation code
testTransformConstr0 :: Test testTransformConstr0 :: Test
@ -161,10 +161,10 @@ testTransformConstr0 = TestCase $ testPass "transformConstr0" exp (transformCons
exp' = A.Spec m (A.Specification m (simpleName "arr") (A.Declaration m (A.Array [A.Dimension 10] A.Int) Nothing)) $ exp' = A.Spec m (A.Specification m (simpleName "arr") (A.Declaration m (A.Array [A.Dimension 10] A.Int) Nothing)) $
A.ProcThen m A.ProcThen m
(A.Seq m $ A.Spec m (A.Specification m (simpleName "i") (A.Declaration m A.Int Nothing)) $ (A.Seq m $ A.Spec m (A.Specification m (simpleName "i") (A.Declaration m A.Int Nothing)) $
A.Several m [A.OnlyP m $ A.Assign m [variable "i"] $ A.ExpressionList m [intLiteral 0], A.Several m [A.Only m $ A.Assign m [variable "i"] $ A.ExpressionList m [intLiteral 0],
A.Rep m (A.For m (simpleName "x") (intLiteral 0) (intLiteral 10)) $ A.OnlyP m $ A.Seq m $ A.Several m A.Rep m (A.For m (simpleName "x") (intLiteral 0) (intLiteral 10)) $ A.Only m $ A.Seq m $ A.Several m
[A.OnlyP m $ A.Assign m [A.SubscriptedVariable m (A.Subscript m $ exprVariable "i") (variable "arr")] $ A.ExpressionList m [exprVariable "x"], [A.Only m $ A.Assign m [A.SubscriptedVariable m (A.Subscript m $ exprVariable "i") (variable "arr")] $ A.ExpressionList m [exprVariable "x"],
A.OnlyP m $ A.Assign m [variable "i"] $ A.ExpressionList m [A.Dyadic m A.Plus (exprVariable "i") (intLiteral 1)]] A.Only m $ A.Assign m [variable "i"] $ A.ExpressionList m [A.Dyadic m A.Plus (exprVariable "i") (intLiteral 1)]]
] ]
) )
skipP skipP
@ -176,7 +176,7 @@ testOutExprs = TestList
-- Test outputting from an expression: -- Test outputting from an expression:
TestCase $ testPassWithItemsStateCheck "testOutExprs 0" TestCase $ testPassWithItemsStateCheck "testOutExprs 0"
(tag2 A.Seq DontCare $ (abbr "temp_var" A.Int (eXM 1)) (tag2 A.Seq DontCare $ (abbr "temp_var" A.Int (eXM 1))
(tag2 A.OnlyP DontCare $ tag3 A.Output emptyMeta chan (mOnlyP $ tag3 A.Output emptyMeta chan
[tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var" DontCare)))]) [tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var" DontCare)))])
) )
(outExprs $ (outExprs $
@ -188,7 +188,7 @@ testOutExprs = TestList
-- Test outputting from a variable already: -- Test outputting from a variable already:
,TestCase $ testPass "testOutExprs 1" ,TestCase $ testPass "testOutExprs 1"
(tag2 A.Seq DontCare $ (tag2 A.Seq DontCare $
(tag2 A.OnlyP DontCare $ tag3 A.Output emptyMeta chan (mOnlyP $ tag3 A.Output emptyMeta chan
[outX]) [outX])
) )
(outExprs $ (outExprs $
@ -199,7 +199,7 @@ testOutExprs = TestList
-- Test outputting from multiple output items: -- Test outputting from multiple output items:
,TestCase $ testPassWithItemsStateCheck "testOutExprs 2" ,TestCase $ testPassWithItemsStateCheck "testOutExprs 2"
(tag2 A.Seq DontCare $ (abbr "temp_var0" A.Byte (eXM 1)) $ (abbr "temp_var1" A.Int (intLiteral 2)) (tag2 A.Seq DontCare $ (abbr "temp_var0" A.Byte (eXM 1)) $ (abbr "temp_var1" A.Int (intLiteral 2))
(tag2 A.OnlyP DontCare $ tag3 A.Output emptyMeta chan (mOnlyP $ tag3 A.Output emptyMeta chan
[tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var0" DontCare))) [tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var0" DontCare)))
,mkPattern outX ,mkPattern outX
,tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var1" DontCare))) ,tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var1" DontCare)))
@ -215,7 +215,7 @@ testOutExprs = TestList
-- Test an OutCounted -- Test an OutCounted
,TestCase $ testPassWithItemsStateCheck "testOutExprs 3" ,TestCase $ testPassWithItemsStateCheck "testOutExprs 3"
(tag2 A.Seq DontCare $ (abbr "temp_var" A.Byte (eXM 1)) (tag2 A.Seq DontCare $ (abbr "temp_var" A.Byte (eXM 1))
(tag2 A.OnlyP DontCare $ tag3 A.Output emptyMeta chan (mOnlyP $ tag3 A.Output emptyMeta chan
[tag3 A.OutCounted emptyMeta [tag3 A.OutCounted emptyMeta
(tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var0" DontCare))) (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var0" DontCare)))
(exprVariable "x") (exprVariable "x")
@ -231,7 +231,7 @@ testOutExprs = TestList
-- Test that OutputCase is also processed: -- Test that OutputCase is also processed:
,TestCase $ testPassWithItemsStateCheck "testOutExprs 4" ,TestCase $ testPassWithItemsStateCheck "testOutExprs 4"
(tag2 A.Seq DontCare $ (abbr "temp_var" A.Int (eXM 1)) (tag2 A.Seq DontCare $ (abbr "temp_var" A.Int (eXM 1))
(tag2 A.OnlyP DontCare $ tag4 A.OutputCase emptyMeta chan (simpleName "foo") (mOnlyP $ tag4 A.OutputCase emptyMeta chan (simpleName "foo")
[tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var" DontCare)))]) [tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var" DontCare)))])
) )
(outExprs $ (outExprs $
@ -244,7 +244,7 @@ testOutExprs = TestList
,TestCase $ testPass "testOutExprs 5" ,TestCase $ testPass "testOutExprs 5"
(tag2 A.Seq DontCare $ (tag2 A.Seq DontCare $
(tag2 A.OnlyP DontCare $ A.OutputCase emptyMeta chan (simpleName "foo") []) (mOnlyP $ A.OutputCase emptyMeta chan (simpleName "foo") [])
) )
(outExprs $ (outExprs $
A.OutputCase emptyMeta chan (simpleName "foo") [] A.OutputCase emptyMeta chan (simpleName "foo") []
@ -257,7 +257,7 @@ testOutExprs = TestList
outXM n = A.OutExpression emptyMeta $ eXM n outXM n = A.OutExpression emptyMeta $ eXM n
eXM n = buildExpr $ Dy (Var "x") A.Minus (Lit $ intLiteral n) eXM n = buildExpr $ Dy (Var "x") A.Minus (Lit $ intLiteral n)
abbr key t e = tag3 A.Spec DontCare abbr key t e = mSpecP
(tag3 A.Specification DontCare (Named key DontCare) $ tag4 A.IsExpr DontCare A.ValAbbrev t e) (tag3 A.Specification DontCare (Named key DontCare) $ tag4 A.IsExpr DontCare A.ValAbbrev t e)
chan = variable "c" chan = variable "c"
@ -284,15 +284,15 @@ testInputCase = TestList
-} -}
TestCase $ testPass "testInputCase 0" TestCase $ testPass "testInputCase 0"
(tag2 A.Seq DontCare $ (tag2 A.Seq DontCare $
tag3 A.Spec DontCare (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $ mSpecP (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $
tag2 A.Several DontCare mSeveralP
[tag2 A.OnlyP DontCare $ tag3 A.Input DontCare c $ tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)] [mOnlyP $ tag3 A.Input DontCare c $ tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)]
,tag2 A.OnlyP DontCare $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $ ,mOnlyP $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $
tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 0] p0 mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 0] p0
] ]
) )
(transformInputCase $ (transformInputCase $
A.Input emptyMeta c $ A.InputCase emptyMeta $ A.OnlyV emptyMeta $ A.Variant emptyMeta a0 [] p0 A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0
) )
(defineMyProtocol >> defineC) (defineMyProtocol >> defineC)
@ -325,25 +325,25 @@ testInputCase = TestList
-} -}
,TestCase $ testPass "testInputCase 1" ,TestCase $ testPass "testInputCase 1"
(tag2 A.Seq DontCare $ (tag2 A.Seq DontCare $
tag3 A.Spec DontCare (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $ mSpecP (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $
tag2 A.Several DontCare mSeveralP
[tag2 A.OnlyP DontCare $ tag3 A.Input DontCare c $ tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)] [mOnlyP $ tag3 A.Input DontCare c $ tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)]
,tag2 A.OnlyP DontCare $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $ tag2 A.Several emptyMeta ,mOnlyP $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $ mSeveralO
[tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 0] p0 [mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 0] p0
,tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 2] $ ,mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 2] $
tag2 A.Seq DontCare $ tag2 A.Several DontCare tag2 A.Seq DontCare $ mSeveralP
[tag2 A.OnlyP DontCare $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta z],tag2 A.OnlyP DontCare p1] [mOnlyP $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta z],mOnlyP p1]
,tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 1] $ ,mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 1] $
tag2 A.Seq DontCare $ tag2 A.Several DontCare tag2 A.Seq DontCare $ mSeveralP
[tag2 A.OnlyP DontCare $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta x,A.InVariable emptyMeta y],tag2 A.OnlyP DontCare p2] [mOnlyP $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta x,A.InVariable emptyMeta y],mOnlyP p2]
] ]
] ]
) )
(transformInputCase $ (transformInputCase $
A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Several emptyMeta A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Several emptyMeta
[A.OnlyV emptyMeta $ A.Variant emptyMeta a0 [] p0 [A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0
,A.OnlyV emptyMeta $ A.Variant emptyMeta c1 [A.InVariable emptyMeta z] p1 ,A.Only emptyMeta $ A.Variant emptyMeta c1 [A.InVariable emptyMeta z] p1
,A.OnlyV emptyMeta $ A.Variant emptyMeta b2 [A.InVariable emptyMeta x,A.InVariable emptyMeta y] p2 ,A.Only emptyMeta $ A.Variant emptyMeta b2 [A.InVariable emptyMeta x,A.InVariable emptyMeta y] p2
] ]
) )
(defineMyProtocol >> defineC) (defineMyProtocol >> defineC)
@ -383,25 +383,25 @@ testInputCase = TestList
-} -}
,TestCase $ testPass "testInputCase 2" ,TestCase $ testPass "testInputCase 2"
(tag2 A.Seq DontCare $ (tag2 A.Seq DontCare $
tag3 A.Spec DontCare (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $ mSpecP (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $
tag2 A.Several DontCare mSeveralP
[tag2 A.OnlyP DontCare $ tag3 A.Input DontCare c $ tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)] [mOnlyP $ tag3 A.Input DontCare c $ tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)]
,tag2 A.OnlyP DontCare $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $ tag2 A.Several emptyMeta ,mOnlyP $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $ mSeveralO
[tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 0] p0 [mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 0] p0
,specIntPatt "z" $ tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 2] $ ,specIntPatt "z" $ mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 2] $
tag2 A.Seq DontCare $ tag2 A.Several DontCare tag2 A.Seq DontCare $ mSeveralP
[tag2 A.OnlyP DontCare $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta z],tag2 A.OnlyP DontCare p1] [mOnlyP $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta z],mOnlyP p1]
,specIntPatt "x" $ specIntPatt "y" $ tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 1] $ ,specIntPatt "x" $ specIntPatt "y" $ mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 1] $
tag2 A.Seq DontCare $ tag2 A.Several DontCare tag2 A.Seq DontCare $ mSeveralP
[tag2 A.OnlyP DontCare $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta x,A.InVariable emptyMeta y],tag2 A.OnlyP DontCare p2] [mOnlyP $ A.Input emptyMeta c $ A.InputSimple emptyMeta [A.InVariable emptyMeta x,A.InVariable emptyMeta y],mOnlyP p2]
] ]
] ]
) )
(transformInputCase $ (transformInputCase $
A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Several emptyMeta A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Several emptyMeta
[A.OnlyV emptyMeta $ A.Variant emptyMeta a0 [] p0 [A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0
,specInt "z" $ A.OnlyV emptyMeta $ A.Variant emptyMeta c1 [A.InVariable emptyMeta z] p1 ,specInt "z" $ A.Only emptyMeta $ A.Variant emptyMeta c1 [A.InVariable emptyMeta z] p1
,specInt "x" $ specInt "y" $ A.OnlyV emptyMeta $ A.Variant emptyMeta b2 [A.InVariable emptyMeta x,A.InVariable emptyMeta y] p2 ,specInt "x" $ specInt "y" $ A.Only emptyMeta $ A.Variant emptyMeta b2 [A.InVariable emptyMeta x,A.InVariable emptyMeta y] p2
] ]
) )
(defineMyProtocol >> defineC) (defineMyProtocol >> defineC)
@ -425,15 +425,15 @@ testInputCase = TestList
-} -}
,TestCase $ testPass "testInputCase 100" ,TestCase $ testPass "testInputCase 100"
(tag3 A.Alt DontCare False $ (tag3 A.Alt DontCare False $
tag3 A.Spec DontCare (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $ mSpecA (tag3 A.Specification DontCare (Named "tag" DontCare) $ tag3 A.Declaration DontCare A.Int noInit) $
tag2 A.OnlyA DontCare $ tag4 A.Alternative DontCare c mOnlyA $ tag4 A.Alternative DontCare c
(tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)]) $ (tag2 A.InputSimple DontCare [tag2 A.InVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)]) $
tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $ tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $
tag2 A.OnlyO DontCare $ tag3 A.Option DontCare [intLiteralPattern 0] p0 mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 0] p0
) )
(transformInputCase $ (transformInputCase $
A.Alt emptyMeta False $ A.OnlyA emptyMeta $ A.Alternative emptyMeta c A.Alt emptyMeta False $ A.Only emptyMeta $ A.Alternative emptyMeta c
(A.InputCase emptyMeta $ A.OnlyV emptyMeta $ A.Variant emptyMeta a0 [] p0) (A.InputCase emptyMeta $ A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0)
(A.Skip emptyMeta) (A.Skip emptyMeta)
) )
(defineMyProtocol >> defineC) (defineMyProtocol >> defineC)
@ -459,7 +459,7 @@ testInputCase = TestList
defineC = defineName (simpleName "c") $ simpleDefDecl "c" (A.Chan A.DirUnknown (A.ChanAttributes False False) (A.UserProtocol $ simpleName "prot")) defineC = defineName (simpleName "c") $ simpleDefDecl "c" (A.Chan A.DirUnknown (A.ChanAttributes False False) (A.UserProtocol $ simpleName "prot"))
specInt s = A.Spec emptyMeta (A.Specification emptyMeta (simpleName s) $ A.Declaration emptyMeta A.Int Nothing) specInt s = A.Spec emptyMeta (A.Specification emptyMeta (simpleName s) $ A.Declaration emptyMeta A.Int Nothing)
specIntPatt s = tag3 A.Spec emptyMeta (A.Specification emptyMeta (simpleName s) $ A.Declaration emptyMeta A.Int Nothing) specIntPatt s = mSpecA' emptyMeta (A.Specification emptyMeta (simpleName s) $ A.Declaration emptyMeta A.Int Nothing)
--Returns the list of tests: --Returns the list of tests:
tests :: Test tests :: Test

View File

@ -49,27 +49,27 @@ outExprs = doGeneric `extM` doProcess
doProcess (A.Output m c ois) doProcess (A.Output m c ois)
= do (ois', specs) <- mapAndUnzipM changeItem ois = do (ois', specs) <- mapAndUnzipM changeItem ois
let foldedSpec = foldFuncs specs let foldedSpec = foldFuncs specs
return $ A.Seq m (foldedSpec $ A.OnlyP m $ A.Output m c ois') return $ A.Seq m (foldedSpec $ A.Only m $ A.Output m c ois')
doProcess (A.OutputCase m c tag ois) doProcess (A.OutputCase m c tag ois)
= do (ois', specs) <- mapAndUnzipM changeItem ois = do (ois', specs) <- mapAndUnzipM changeItem ois
let foldedSpec = foldFuncs specs let foldedSpec = foldFuncs specs
return $ A.Seq m (foldedSpec $ A.OnlyP m $ A.OutputCase m c tag ois') return $ A.Seq m (foldedSpec $ A.Only m $ A.OutputCase m c tag ois')
doProcess p = doGeneric p doProcess p = doGeneric p
changeItem :: A.OutputItem -> PassM (A.OutputItem, A.Structured -> A.Structured) changeItem :: A.OutputItem -> PassM (A.OutputItem, A.Structured A.Process -> A.Structured A.Process)
changeItem (A.OutExpression m e) = do (e', spec) <- transExpr m e changeItem (A.OutExpression m e) = do (e', spec) <- transExpr m e
return (A.OutExpression m e', spec) return (A.OutExpression m e', spec)
changeItem (A.OutCounted m ce ae) = do (ce', ceSpec) <- transExpr m ce changeItem (A.OutCounted m ce ae) = do (ce', ceSpec) <- transExpr m ce
(ae', aeSpec) <- transExpr m ae (ae', aeSpec) <- transExpr m ae
return (A.OutCounted m ce' ae', ceSpec . aeSpec) return (A.OutCounted m ce' ae', ceSpec . aeSpec)
transExpr :: Meta -> A.Expression -> PassM (A.Expression, A.Structured -> A.Structured) transExpr :: Meta -> A.Expression -> PassM (A.Expression, A.Structured A.Process -> A.Structured A.Process)
-- If it's already an output direct from a variable, no need to change it: -- If it's already an output direct from a variable, no need to change it:
transExpr _ e@(A.ExprVariable {}) = return (e, id) transExpr _ e@(A.ExprVariable {}) = return (e, id)
transExpr m e = do (nm, spec) <- abbrevExpr m e transExpr m e = do (nm, spec) <- abbrevExpr m e
return (A.ExprVariable m $ A.Variable m nm, spec) return (A.ExprVariable m $ A.Variable m nm, spec)
abbrevExpr :: Meta -> A.Expression -> PassM (A.Name, A.Structured -> A.Structured) abbrevExpr :: Meta -> A.Expression -> PassM (A.Name, A.Structured A.Process -> A.Structured A.Process)
abbrevExpr m e = do t <- typeOfExpression e abbrevExpr m e = do t <- typeOfExpression e
specification@(A.Specification _ nm _) <- defineNonce m "output_var" (A.IsExpr m A.ValAbbrev t e) A.VariableName A.ValAbbrev specification@(A.Specification _ nm _) <- defineNonce m "output_var" (A.IsExpr m A.ValAbbrev t e) A.VariableName A.ValAbbrev
return (nm, A.Spec m specification) return (nm, A.Spec m specification)
@ -143,56 +143,73 @@ transformInputCase = doGeneric `extM` doProcess
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Input m v (A.InputCase m' s)) doProcess (A.Input m v (A.InputCase m' s))
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int Nothing) A.VariableName A.Original = do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int Nothing) A.VariableName A.Original
s' <- doStructured v s s' <- doStructuredV v s
return $ A.Seq m $ A.Spec m' spec $ A.Several m' return $ A.Seq m $ A.Spec m' spec $ A.Several m'
[A.OnlyP m $ A.Input m v (A.InputSimple m [A.InVariable m (A.Variable m n)]) [A.Only m $ A.Input m v (A.InputSimple m [A.InVariable m (A.Variable m n)])
,A.OnlyP m' $ A.Case m' (A.ExprVariable m $ A.Variable m n) s'] ,A.Only m' $ A.Case m' (A.ExprVariable m $ A.Variable m n) s']
doProcess (A.Alt m pri s) doProcess (A.Alt m pri s)
= do s' <- doStructured undefined s = do s' <- doStructuredA s
return (A.Alt m pri s') return (A.Alt m pri s')
doProcess p = doGeneric p doProcess p = doGeneric p
doStructured :: A.Variable -> A.Structured -> PassM A.Structured -- Can't easily use generics here as we're switching from one type of Structured to another
doStructuredV :: A.Variable -> A.Structured A.Variant -> PassM (A.Structured A.Option)
-- These entries all just burrow deeper into the structured: -- These entries all just burrow deeper into the structured:
doStructured v (A.ProcThen m p s) doStructuredV v (A.ProcThen m p s)
= do s' <- doStructured v s = do s' <- doStructuredV v s
p' <- doProcess p p' <- doProcess p
return (A.ProcThen m p' s') return (A.ProcThen m p' s')
doStructured v (A.Spec m sp st) doStructuredV v (A.Spec m sp st)
= do st' <- doStructured v st = do st' <- doStructuredV v st
return (A.Spec m sp st') return (A.Spec m sp st')
doStructured v (A.Several m ss) doStructuredV v (A.Several m ss)
= do ss' <- mapM (doStructured v) ss = do ss' <- mapM (doStructuredV v) ss
return (A.Several m ss') return (A.Several m ss')
doStructured v (A.Rep m rep s) doStructuredV v (A.Rep m rep s)
= do s' <- doStructured v s = do s' <- doStructuredV v s
return (A.Rep m rep s') return (A.Rep m rep s')
-- Transform variant options: -- Transform variant options:
doStructured chanVar (A.OnlyV m (A.Variant m' n iis p)) doStructuredV chanVar (A.Only m (A.Variant m' n iis p))
= do (Right items) <- protocolItems chanVar = do (Right items) <- protocolItems chanVar
let (Just idx) = elemIndex n (fst $ unzip items) let (Just idx) = elemIndex n (fst $ unzip items)
p' <- doProcess p p' <- doProcess p
return $ A.OnlyO m $ A.Option m' [makeConstant m' idx] $ return $ A.Only m $ A.Option m' [makeConstant m' idx] $
if (length iis == 0) if (length iis == 0)
then p' then p'
else A.Seq m' $ A.Several m' else A.Seq m' $ A.Several m'
[A.OnlyP m' $ A.Input m' chanVar (A.InputSimple m' iis) [A.Only m' $ A.Input m' chanVar (A.InputSimple m' iis)
,A.OnlyP (findMeta p') p'] ,A.Only (findMeta p') p']
doStructuredA :: A.Structured A.Alternative -> PassM (A.Structured A.Alternative)
-- TODO use generics instead of this boilerplate, but don't omit the doProcess call in ProcThen!
doStructuredA (A.ProcThen m p s)
= do s' <- doStructuredA s
p' <- doProcess p
return (A.ProcThen m p' s')
doStructuredA (A.Spec m sp st)
= do st' <- doStructuredA st
return (A.Spec m sp st')
doStructuredA (A.Several m ss)
= do ss' <- mapM doStructuredA ss
return (A.Several m ss')
doStructuredA (A.Rep m rep s)
= do s' <- doStructuredA s
return (A.Rep m rep s')
-- Transform alt guards: -- Transform alt guards:
-- The processes that are the body of input-case guards are always skip, so we can discard them: -- The processes that are the body of input-case guards are always skip, so we can discard them:
doStructured _ (A.OnlyA m (A.Alternative m' v (A.InputCase m'' s) _)) doStructuredA (A.Only m (A.Alternative m' v (A.InputCase m'' s) _))
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int Nothing) A.VariableName A.Original = do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int Nothing) A.VariableName A.Original
s' <- doStructured v s s' <- doStructuredV v s
return $ A.Spec m' spec $ A.OnlyA m $ return $ A.Spec m' spec $ A.Only m $
A.Alternative m' v (A.InputSimple m [A.InVariable m (A.Variable m n)]) $ A.Alternative m' v (A.InputSimple m [A.InVariable m (A.Variable m n)]) $
A.Case m'' (A.ExprVariable m'' $ A.Variable m n) s' A.Case m'' (A.ExprVariable m'' $ A.Variable m n) s'
doStructured _ (A.OnlyA m (A.AlternativeCond m' e v (A.InputCase m'' s) _)) doStructuredA (A.Only m (A.AlternativeCond m' e v (A.InputCase m'' s) _))
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int Nothing) A.VariableName A.Original = do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int Nothing) A.VariableName A.Original
s' <- doStructured v s s' <- doStructuredV v s
return $ A.Spec m' spec $ A.OnlyA m $ return $ A.Spec m' spec $ A.Only m $
A.AlternativeCond m' e v (A.InputSimple m [A.InVariable m (A.Variable m n)]) $ A.AlternativeCond m' e v (A.InputSimple m [A.InVariable m (A.Variable m n)]) $
A.Case m'' (A.ExprVariable m'' $ A.Variable m n) s' A.Case m'' (A.ExprVariable m'' $ A.Variable m n) s'
-- Leave other guards untouched: -- Leave other guards (and parts of Structured) untouched:
doStructured _ a@(A.OnlyA {}) = return a doStructuredA s = return s

View File

@ -74,10 +74,10 @@ functionsToProcs = doGeneric `extM` doSpecification
doGeneric spec doGeneric spec
doSpecification s = doGeneric s doSpecification s = doGeneric s
vpToSeq :: A.Structured -> [A.Variable] -> A.Structured vpToSeq :: A.Structured A.ExpressionList -> [A.Variable] -> A.Structured A.Process
vpToSeq (A.Spec m spec s) vs = A.Spec m spec (vpToSeq s vs) vpToSeq (A.Spec m spec s) vs = A.Spec m spec (vpToSeq s vs)
vpToSeq (A.ProcThen m p s) vs = A.ProcThen m p (vpToSeq s vs) vpToSeq (A.ProcThen m p s) vs = A.ProcThen m p (vpToSeq s vs)
vpToSeq (A.OnlyEL m el) vs = A.OnlyP m $ A.Assign m vs el vpToSeq (A.Only m el) vs = A.Only m $ A.Assign m vs el
-- | Convert AFTER expressions to the equivalent using MINUS (which is how the -- | Convert AFTER expressions to the equivalent using MINUS (which is how the
-- occam 3 manual defines AFTER). -- occam 3 manual defines AFTER).
@ -121,23 +121,23 @@ expandArrayLiterals = doGeneric `extM` doArrayElem
where m = findMeta e where m = findMeta e
transformConstr :: Data t => t -> PassM t transformConstr :: Data t => t -> PassM t
transformConstr = doGeneric `extM` doStructured transformConstr = doGeneric `ext1M` doStructured
where where
doGeneric :: Data t => t -> PassM t doGeneric :: Data t => t -> PassM t
doGeneric = makeGeneric transformConstr doGeneric = makeGeneric transformConstr
doStructured :: A.Structured -> PassM A.Structured doStructured :: Data a => A.Structured a -> PassM (A.Structured a)
doStructured (A.Spec m (A.Specification m' n (A.IsExpr _ _ t (A.ExprConstr m'' (A.RepConstr _ rep exp)))) scope) doStructured (A.Spec m (A.Specification m' n (A.IsExpr _ _ t (A.ExprConstr m'' (A.RepConstr _ rep exp)))) scope)
= do indexVarSpec@(A.Specification _ indexVar _) <- makeNonceVariable "array_constr_index" m'' A.Int A.VariableName A.Original = do indexVarSpec@(A.Specification _ indexVar _) <- makeNonceVariable "array_constr_index" m'' A.Int A.VariableName A.Original
scope' <- doGeneric scope scope' <- doGeneric scope
return $ A.Spec m (A.Specification m' n (A.Declaration m' t Nothing)) $ A.ProcThen m'' return $ A.Spec m (A.Specification m' n (A.Declaration m' t Nothing)) $ A.ProcThen m''
(A.Seq m'' $ A.Spec m'' (indexVarSpec) $ A.Several m'' [ (A.Seq m'' $ A.Spec m'' (indexVarSpec) $ A.Several m'' [
A.OnlyP m'' $ A.Assign m'' [A.Variable m'' indexVar] $ A.ExpressionList m'' [A.Literal m'' A.Int $ A.IntLiteral m'' "0"], A.Only m'' $ A.Assign m'' [A.Variable m'' indexVar] $ A.ExpressionList m'' [A.Literal m'' A.Int $ A.IntLiteral m'' "0"],
A.Rep m'' rep $ A.OnlyP m'' $ A.Seq m'' $ A.Several m'' A.Rep m'' rep $ A.Only m'' $ A.Seq m'' $ A.Several m''
[A.OnlyP m'' $ A.Assign m'' [A.Only m'' $ A.Assign m''
[A.SubscriptedVariable m'' (A.Subscript m'' $ A.ExprVariable m'' $ A.Variable m'' indexVar) $ A.Variable m'' n] [A.SubscriptedVariable m'' (A.Subscript m'' $ A.ExprVariable m'' $ A.Variable m'' indexVar) $ A.Variable m'' n]
$ A.ExpressionList m'' [exp] $ A.ExpressionList m'' [exp]
,A.OnlyP m'' $ A.Assign m'' [A.Variable m'' indexVar] $ A.ExpressionList m'' [A.Dyadic m'' A.Plus ,A.Only m'' $ A.Assign m'' [A.Variable m'' indexVar] $ A.ExpressionList m'' [A.Dyadic m'' A.Plus
(A.ExprVariable m'' $ A.Variable m'' indexVar) (A.ExprVariable m'' $ A.Variable m'' indexVar)
(A.Literal m'' A.Int $ A.IntLiteral m'' "1")] (A.Literal m'' A.Int $ A.IntLiteral m'' "1")]
] ]
@ -149,7 +149,7 @@ transformConstr = doGeneric `extM` doStructured
-- so. -- so.
pullUp :: Data t => t -> PassM t pullUp :: Data t => t -> PassM t
pullUp = doGeneric pullUp = doGeneric
`extM` doStructured `ext1M` doStructured
`extM` doProcess `extM` doProcess
`extM` doSpecification `extM` doSpecification
`extM` doLiteralRepr `extM` doLiteralRepr
@ -162,7 +162,7 @@ pullUp = doGeneric
-- | When we encounter a Structured, create a new pulled items state, -- | When we encounter a Structured, create a new pulled items state,
-- recurse over it, then apply whatever pulled items we found to it. -- recurse over it, then apply whatever pulled items we found to it.
doStructured :: A.Structured -> PassM A.Structured doStructured :: Data a => A.Structured a -> PassM (A.Structured a)
doStructured s doStructured s
= do pushPullContext = do pushPullContext
-- Recurse over the body, then apply the pulled items to it -- Recurse over the body, then apply the pulled items to it
@ -179,7 +179,7 @@ pullUp = doGeneric
p' <- doGeneric p p' <- doGeneric p
pulled <- havePulled pulled <- havePulled
p'' <- if pulled p'' <- if pulled
then liftM (A.Seq emptyMeta) $ applyPulled (A.OnlyP emptyMeta p') then liftM (A.Seq emptyMeta) $ applyPulled (A.Only emptyMeta p')
else return p' else return p'
popPullContext popPullContext
return p'' return p''
@ -199,7 +199,7 @@ pullUp = doGeneric
= do e' <- doExpression e = do e' <- doExpression e
fromT <- typeOfExpression e' fromT <- typeOfExpression e'
spec@(A.Specification _ n' _) <- makeNonceIsExpr "retypes_expr" m' fromT e' spec@(A.Specification _ n' _) <- makeNonceIsExpr "retypes_expr" m' fromT e'
addPulled $ A.Spec m' spec addPulled $ (m', Left spec)
return $ A.Specification m n (A.Retypes m' am toT (A.Variable m' n')) return $ A.Specification m n (A.Retypes m' am toT (A.Variable m' n'))
doSpecification s = doGeneric s doSpecification s = doGeneric s
@ -231,7 +231,7 @@ pullUp = doGeneric
pull t e pull t e
= do let m = findMeta e = do let m = findMeta e
spec@(A.Specification _ n _) <- makeNonceIsExpr "array_expr" m t e spec@(A.Specification _ n _) <- makeNonceIsExpr "array_expr" m t e
addPulled $ A.Spec m spec addPulled $ (m, Left spec)
return $ A.ExprVariable m (A.Variable m n) return $ A.ExprVariable m (A.Variable m n)
-- | Pull any variable subscript that results in an array. -- | Pull any variable subscript that results in an array.
@ -244,7 +244,7 @@ pullUp = doGeneric
do origAM <- abbrevModeOfVariable v' do origAM <- abbrevModeOfVariable v'
let am = makeAbbrevAM origAM let am = makeAbbrevAM origAM
spec@(A.Specification _ n _) <- makeNonceIs "array_slice" m t am v' spec@(A.Specification _ n _) <- makeNonceIs "array_slice" m t am v'
addPulled $ A.Spec m spec addPulled $ (m, Left spec)
return $ A.Variable m n return $ A.Variable m n
_ -> return v' _ -> return v'
doVariable v = doGeneric v doVariable v = doGeneric v
@ -258,12 +258,12 @@ pullUp = doGeneric
ps <- get ps <- get
rts <- Map.lookup (A.nameName n) (csFunctionReturns ps) rts <- Map.lookup (A.nameName n) (csFunctionReturns ps)
specs <- sequence [makeNonceVariable "return_actual" m t A.VariableName A.Original | t <- rts] specs <- sequence [makeNonceVariable "return_actual" m t A.VariableName A.Original | t <- rts]
sequence_ [addPulled $ A.Spec m spec | spec <- specs] sequence_ [addPulled $ (m, Left spec) | spec <- specs]
let names = [n | A.Specification _ n _ <- specs] let names = [n | A.Specification _ n _ <- specs]
let vars = [A.Variable m n | n <- names] let vars = [A.Variable m n | n <- names]
let call = A.ProcCall m n ([A.ActualExpression t e | (t, e) <- zip ets es'] ++ [A.ActualVariable A.Abbrev t v | (t, v) <- zip rts vars]) let call = A.ProcCall m n ([A.ActualExpression t e | (t, e) <- zip ets es'] ++ [A.ActualVariable A.Abbrev t v | (t, v) <- zip rts vars])
addPulled $ A.ProcThen m call addPulled $ (m, Right call)
return vars return vars
@ -278,7 +278,7 @@ pullUp = doGeneric
s' <- pullUp s s' <- pullUp s
t <- typeOfExpression e' t <- typeOfExpression e'
spec@(A.Specification _ n _) <- makeNonceIsExpr "subscripted_expr" m t e' spec@(A.Specification _ n _) <- makeNonceIsExpr "subscripted_expr" m t e'
addPulled $ A.Spec m spec addPulled $ (m, Left spec)
return $ A.ExprVariable m (A.SubscriptedVariable m s' (A.Variable m n)) return $ A.ExprVariable m (A.SubscriptedVariable m s' (A.Variable m n))
doExpression' e = doGeneric e doExpression' e = doGeneric e

View File

@ -52,7 +52,7 @@ parsToProcs = doGeneric `extM` doProcess
doProcess p = doGeneric p doProcess p = doGeneric p
-- FIXME This should be generic and in Pass. -- FIXME This should be generic and in Pass.
doStructured :: A.Structured -> PassM A.Structured doStructured :: A.Structured A.Process -> PassM (A.Structured A.Process)
doStructured (A.Rep m r s) doStructured (A.Rep m r s)
= do r' <- parsToProcs r = do r' <- parsToProcs r
s' <- doStructured s s' <- doStructured s
@ -65,10 +65,10 @@ parsToProcs = doGeneric `extM` doProcess
= do p' <- parsToProcs p = do p' <- parsToProcs p
s' <- doStructured s s' <- doStructured s
return $ A.ProcThen m p' s' return $ A.ProcThen m p' s'
doStructured (A.OnlyP m p) doStructured (A.Only m p)
= do p' <- parsToProcs p = do p' <- parsToProcs p
s@(A.Specification _ n _) <- makeNonceProc m p' s@(A.Specification _ n _) <- makeNonceProc m p'
return $ A.Spec m s (A.OnlyP m (A.ProcCall m n [])) return $ A.Spec m s (A.Only m (A.ProcCall m n []))
doStructured (A.Several m ss) doStructured (A.Several m ss)
= liftM (A.Several m) $ mapM doStructured ss = liftM (A.Several m) $ mapM doStructured ss
@ -86,7 +86,7 @@ removeParAssign = doGeneric `extM` doProcess
let temps = [A.Variable m n | A.Specification _ n _ <- specs] let temps = [A.Variable m n | A.Specification _ n _ <- specs]
let first = [A.Assign m [v] (A.ExpressionList m [e]) | (v, e) <- zip temps es] let first = [A.Assign m [v] (A.ExpressionList m [e]) | (v, e) <- zip temps es]
let second = [A.Assign m [v] (A.ExpressionList m [A.ExprVariable m v']) | (v, v') <- zip vs temps] let second = [A.Assign m [v] (A.ExpressionList m [A.ExprVariable m v']) | (v, v') <- zip vs temps]
return $ A.Seq m $ foldl (\s spec -> A.Spec m spec s) (A.Several m (map (A.OnlyP m) (first ++ second))) specs return $ A.Seq m $ foldl (\s spec -> A.Spec m spec s) (A.Several m (map (A.Only m) (first ++ second))) specs
doProcess p = doGeneric p doProcess p = doGeneric p
-- | Turn assignment of arrays and records into multiple assignments. -- | Turn assignment of arrays and records into multiple assignments.
@ -134,7 +134,7 @@ flattenAssign = doGeneric `extM` doProcess
(A.SubscriptedVariable m sub destV) m' (A.SubscriptedVariable m sub destV) m'
(A.ExprVariable m' (A.ExprVariable m'
(A.SubscriptedVariable m' sub srcV)) (A.SubscriptedVariable m' sub srcV))
return $ A.Rep m rep $ A.OnlyP m inner return $ A.Rep m rep $ A.Only m inner
A.Record _ -> A.Record _ ->
-- Record assignments become a sequence of -- Record assignments become a sequence of
-- assignments, one for each field. -- assignments, one for each field.
@ -147,7 +147,7 @@ flattenAssign = doGeneric `extM` doProcess
(A.ExprVariable m' (A.ExprVariable m'
(A.SubscriptedVariable m' sub srcV)) (A.SubscriptedVariable m' sub srcV))
| (fName, fType) <- fs] | (fName, fType) <- fs]
return $ A.Several m $ map (A.OnlyP m) assigns return $ A.Several m $ map (A.Only m) assigns
return $ A.Seq m $ A.Spec m src $ A.Spec m dest body return $ A.Seq m $ A.Spec m src $ A.Spec m dest body

View File

@ -47,7 +47,7 @@ freeNamesIn :: Data t => t -> NameMap
freeNamesIn = doGeneric freeNamesIn = doGeneric
`extQ` (ignore :: String -> NameMap) `extQ` (ignore :: String -> NameMap)
`extQ` (ignore :: Meta -> NameMap) `extQ` (ignore :: Meta -> NameMap)
`extQ` doName `extQ` doStructured `extQ` doSpecType `extQ` doName `ext1Q` doStructured `extQ` doSpecType
where where
doGeneric :: Data t => t -> NameMap doGeneric :: Data t => t -> NameMap
doGeneric n = Map.unions $ gmapQ freeNamesIn n doGeneric n = Map.unions $ gmapQ freeNamesIn n
@ -58,7 +58,7 @@ freeNamesIn = doGeneric
doName :: A.Name -> NameMap doName :: A.Name -> NameMap
doName n = Map.singleton (A.nameName n) n doName n = Map.singleton (A.nameName n) n
doStructured :: A.Structured -> NameMap doStructured :: Data a => A.Structured a -> NameMap
doStructured (A.Rep _ rep s) = doRep rep s doStructured (A.Rep _ rep s) = doRep rep s
doStructured (A.Spec _ spec s) = doSpec spec s doStructured (A.Spec _ spec s) = doSpec spec s
doStructured s = doGeneric s doStructured s = doGeneric s
@ -171,7 +171,7 @@ removeFreeNames = doGeneric `extM` doSpecification `extM` doProcess
doProcess p = doGeneric p doProcess p = doGeneric p
-- | Pull nested declarations to the top level. -- | Pull nested declarations to the top level.
removeNesting :: A.Structured -> PassM A.Structured removeNesting :: forall a. Data a => A.Structured a -> PassM (A.Structured a)
removeNesting p removeNesting p
= do pushPullContext = do pushPullContext
p' <- pullSpecs p p' <- pullSpecs p
@ -185,13 +185,13 @@ removeNesting p
doGeneric :: Data t => t -> PassM t doGeneric :: Data t => t -> PassM t
doGeneric = makeGeneric pullSpecs doGeneric = makeGeneric pullSpecs
doStructured :: A.Structured -> PassM A.Structured doStructured :: A.Structured a -> PassM (A.Structured a)
doStructured s@(A.Spec m spec@(A.Specification _ n st) subS) doStructured s@(A.Spec m spec@(A.Specification _ n st) subS)
= do isConst <- isConstantName n = do isConst <- isConstantName n
if isConst || canPull st then if isConst || canPull st then
do debug $ "removeNesting: pulling up " ++ show n do debug $ "removeNesting: pulling up " ++ show n
spec' <- doGeneric spec spec' <- doGeneric spec
addPulled $ A.Spec m spec' addPulled $ (m, Left spec')
doStructured subS doStructured subS
else doGeneric s else doGeneric s
doStructured s = doGeneric s doStructured s = doGeneric s