Moved all the remaining pass information to be with the passes themselves, and adjusted the tests accordingly
All the passes now have their information (name, pre-requisites and post- properties) stored at the point where the pass is declared, which means the pass lists are just a simple list of pass functions. The main consequence of this change was that the tests had to be changed. Now, instead of taking a "pass applied to data" item (type: PassM b), they take both the pass (type: Pass) and source data (type: b), and apply them later. This was the decision that involved the simplest changes to the existing tests (simply unbracketing the application of the pass to the source). I also had to include a few old-style versions though (testPass', testPassShouldFail') for where the functions were being used to test things that weren't actually passes (mainly StructureOccam). Fixes #48
This commit is contained in:
parent
6f6538ed57
commit
ba66cce89f
|
@ -17,7 +17,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
-}
|
||||
|
||||
-- | Passes associated with the backends
|
||||
module BackendPasses where
|
||||
module BackendPasses (addSizesActualParameters, addSizesFormalParameters, declareSizesArray, simplifySlices, squashArrays, transformWaitFor) where
|
||||
|
||||
import Control.Monad.State
|
||||
import Data.Generics
|
||||
|
@ -35,18 +35,21 @@ import Types
|
|||
import Utils
|
||||
|
||||
squashArrays :: [Pass]
|
||||
squashArrays = makePassesDep
|
||||
[ ("Simplify array slices", simplifySlices, prereq, [Prop.slicesSimplified])
|
||||
, ("Declare array-size arrays", declareSizesArray, prereq ++ [Prop.slicesSimplified,
|
||||
Prop.arrayConstructorsRemoved], [Prop.arraySizesDeclared])
|
||||
, ("Add array-size arrays to PROC headers", addSizesFormalParameters, prereq ++ [Prop.arraySizesDeclared], [])
|
||||
, ("Add array-size arrays to PROC calls", addSizesActualParameters, prereq ++ [Prop.arraySizesDeclared], [])
|
||||
squashArrays =
|
||||
[ simplifySlices
|
||||
, declareSizesArray
|
||||
, addSizesFormalParameters
|
||||
, addSizesActualParameters
|
||||
]
|
||||
where
|
||||
prereq = Prop.agg_namesDone ++ Prop.agg_typesDone ++ Prop.agg_functionsGone ++ [Prop.subscriptsPulledUp, Prop.arrayLiteralsExpanded]
|
||||
|
||||
transformWaitFor :: PassType
|
||||
transformWaitFor = applyDepthM doAlt
|
||||
prereq :: [Property]
|
||||
prereq = Prop.agg_namesDone ++ Prop.agg_typesDone ++ Prop.agg_functionsGone ++ [Prop.subscriptsPulledUp, Prop.arrayLiteralsExpanded]
|
||||
|
||||
transformWaitFor :: Pass
|
||||
transformWaitFor = cOnlyPass "Transform wait for guards into wait until guards"
|
||||
[]
|
||||
[Prop.waitForRemoved]
|
||||
$ applyDepthM doAlt
|
||||
where
|
||||
doAlt :: A.Process -> PassM A.Process
|
||||
doAlt a@(A.Alt m pri s)
|
||||
|
@ -79,8 +82,11 @@ append_sizes n = n {A.nameName = A.nameName n ++ "_sizes"}
|
|||
|
||||
-- | Declares a _sizes array for every array, statically sized or dynamically sized.
|
||||
-- For each record type it declares a _sizes array too.
|
||||
declareSizesArray :: PassType
|
||||
declareSizesArray = applyDepthSM doStructured
|
||||
declareSizesArray :: Pass
|
||||
declareSizesArray = occamOnlyPass "Declare array-size arrays"
|
||||
(prereq ++ [Prop.slicesSimplified, Prop.arrayConstructorsRemoved])
|
||||
[Prop.arraySizesDeclared]
|
||||
$ applyDepthSM doStructured
|
||||
where
|
||||
defineSizesName :: Meta -> A.Name -> A.SpecType -> PassM ()
|
||||
defineSizesName m n spec
|
||||
|
@ -229,8 +235,11 @@ declareSizesArray = applyDepthSM doStructured
|
|||
|
||||
-- | A pass for adding _sizes parameters to PROC arguments
|
||||
-- TODO in future, only add _sizes for variable-sized parameters
|
||||
addSizesFormalParameters :: PassType
|
||||
addSizesFormalParameters = applyDepthM doSpecification
|
||||
addSizesFormalParameters :: Pass
|
||||
addSizesFormalParameters = occamOnlyPass "Add array-size arrays to PROC headers"
|
||||
(prereq ++ [Prop.arraySizesDeclared])
|
||||
[]
|
||||
$ applyDepthM doSpecification
|
||||
where
|
||||
doSpecification :: A.Specification -> PassM A.Specification
|
||||
doSpecification (A.Specification m n (A.Proc m' sm args body))
|
||||
|
@ -263,8 +272,11 @@ addSizesFormalParameters = applyDepthM doSpecification
|
|||
return (f : rest, new)
|
||||
|
||||
-- | A pass for adding _sizes parameters to actuals in PROC calls
|
||||
addSizesActualParameters :: PassType
|
||||
addSizesActualParameters = applyDepthM doProcess
|
||||
addSizesActualParameters :: Pass
|
||||
addSizesActualParameters = occamOnlyPass "Add array-size arrays to PROC calls"
|
||||
(prereq ++ [Prop.arraySizesDeclared])
|
||||
[]
|
||||
$ applyDepthM doProcess
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.ProcCall m n params) = concatMapM transformActual params >>* A.ProcCall m n
|
||||
|
@ -289,8 +301,11 @@ addSizesActualParameters = applyDepthM doProcess
|
|||
transformActualVariable a _ = return [a]
|
||||
|
||||
-- | Transforms all slices into the FromFor form.
|
||||
simplifySlices :: PassType
|
||||
simplifySlices = applyDepthM doVariable
|
||||
simplifySlices :: Pass
|
||||
simplifySlices = occamOnlyPass "Simplify array slices"
|
||||
prereq
|
||||
[Prop.slicesSimplified]
|
||||
$ applyDepthM doVariable
|
||||
where
|
||||
doVariable :: A.Variable -> PassM A.Variable
|
||||
doVariable (A.SubscriptedVariable m (A.SubscriptFor m' check for) v)
|
||||
|
|
|
@ -61,13 +61,13 @@ mGetTime v = mInput (mVariable timerName) (mInputTimerRead $ mInVariable v)
|
|||
|
||||
-- | Test WaitUntil guard (should be unchanged)
|
||||
testTransformWaitFor0 :: Test
|
||||
testTransformWaitFor0 = TestCase $ testPass "testTransformWaitFor0" orig (transformWaitFor orig) (return ())
|
||||
testTransformWaitFor0 = TestCase $ testPass "testTransformWaitFor0" orig transformWaitFor orig (return ())
|
||||
where
|
||||
orig = A.Alt m True $ A.Only m $ waitUntil (exprVariable "t") (A.Skip m)
|
||||
|
||||
-- | Test pulling out a single WaitFor:
|
||||
testTransformWaitFor1 :: Test
|
||||
testTransformWaitFor1 = TestCase $ testPass "testTransformWaitFor1" exp (transformWaitFor orig) (return ())
|
||||
testTransformWaitFor1 = TestCase $ testPass "testTransformWaitFor1" exp transformWaitFor orig (return ())
|
||||
where
|
||||
orig = A.Alt m True $ A.Only m $ waitFor (exprVariable "t") (A.Skip m)
|
||||
exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName $ A.Declaration m A.Time) $
|
||||
|
@ -83,7 +83,7 @@ testTransformWaitFor1 = TestCase $ testPass "testTransformWaitFor1" exp (transfo
|
|||
|
||||
-- | Test pulling out two WaitFors:
|
||||
testTransformWaitFor2 :: Test
|
||||
testTransformWaitFor2 = TestCase $ testPass "testTransformWaitFor2" exp (transformWaitFor orig) (return ())
|
||||
testTransformWaitFor2 = TestCase $ testPass "testTransformWaitFor2" exp transformWaitFor orig (return ())
|
||||
where
|
||||
orig = A.Alt m True $ A.Several m [A.Only m $ waitFor (exprVariable "t0") (A.Skip m),
|
||||
A.Only m $ waitFor (exprVariable "t1") (A.Skip m)]
|
||||
|
@ -108,7 +108,7 @@ testTransformWaitFor2 = TestCase $ testPass "testTransformWaitFor2" exp (transfo
|
|||
|
||||
-- | Test pulling out a single WaitFor with an expression:
|
||||
testTransformWaitFor3 :: Test
|
||||
testTransformWaitFor3 = TestCase $ testPass "testTransformWaitFor3" exp (transformWaitFor orig) (return ())
|
||||
testTransformWaitFor3 = TestCase $ testPass "testTransformWaitFor3" exp transformWaitFor orig (return ())
|
||||
where
|
||||
orig = A.Alt m True $ A.Only m $ waitFor (A.Dyadic m A.Plus (exprVariable "t0") (exprVariable "t1")) (A.Skip m)
|
||||
exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName $ A.Declaration m A.Time) $
|
||||
|
@ -125,7 +125,7 @@ testTransformWaitFor3 = TestCase $ testPass "testTransformWaitFor3" exp (transfo
|
|||
|
||||
-- | Test pulling out a single WaitFor with some slight nesting in the ALT:
|
||||
testTransformWaitFor4 :: Test
|
||||
testTransformWaitFor4 = TestCase $ testPass "testTransformWaitFor4" exp (transformWaitFor orig) (return ())
|
||||
testTransformWaitFor4 = TestCase $ testPass "testTransformWaitFor4" exp transformWaitFor orig (return ())
|
||||
where
|
||||
orig = A.Alt m True $ A.Several m [A.Only m $ waitFor (exprVariable "t") (A.Skip m)]
|
||||
exp = tag2 A.Seq DontCare $ mSpecP (tag3 A.Specification DontCare varName $ A.Declaration m A.Time) $
|
||||
|
@ -142,7 +142,7 @@ testTransformWaitFor4 = TestCase $ testPass "testTransformWaitFor4" exp (transfo
|
|||
|
||||
-- | Test pulling out two WaitFors that use the same variable:
|
||||
testTransformWaitFor5 :: Test
|
||||
testTransformWaitFor5 = TestCase $ testPass "testTransformWaitFor5" exp (transformWaitFor orig) (return ())
|
||||
testTransformWaitFor5 = TestCase $ testPass "testTransformWaitFor5" exp transformWaitFor orig (return ())
|
||||
where
|
||||
orig = A.Alt m True $ A.Several m [A.Only m $ waitFor (exprVariable "t") (A.Skip m),
|
||||
A.Only m $ waitFor (exprVariable "t") (A.Skip m)]
|
||||
|
@ -313,7 +313,7 @@ qcTestDeclareSizes =
|
|||
term = A.Only emptyMeta ()
|
||||
|
||||
test :: TestMonad m r => Int -> A.Structured () -> A.Structured () -> State CompState () -> (CompState -> m ()) -> m ()
|
||||
test n exp inp st chk = testPassWithStateCheck label exp (declareSizesArray inp) st chk
|
||||
test n exp inp st chk = testPassWithStateCheck label exp declareSizesArray inp st chk
|
||||
where
|
||||
label = "testDeclareSizes " ++ show n
|
||||
|
||||
|
@ -354,7 +354,7 @@ qcTestSizeParameters =
|
|||
testActual :: TestMonad m r => [A.Type] -> m ()
|
||||
testActual ts = testPassWithStateCheck "qcTestSizeParameters Actual"
|
||||
(procCall "p" argsWithSizes)
|
||||
(addSizesActualParameters $ procCall "p" args)
|
||||
addSizesActualParameters (procCall "p" args)
|
||||
(do recordProcDef args
|
||||
recordProcFormals args)
|
||||
(const $ return ())
|
||||
|
@ -369,7 +369,7 @@ qcTestSizeParameters =
|
|||
testFormal :: TestMonad m r => [A.Type] -> m ()
|
||||
testFormal ts = testPassWithStateCheck "qcTestSizeParameters Formal"
|
||||
(wrapSpec "p" $ makeProcDef argsWithSizes)
|
||||
(addSizesFormalParameters $ wrapSpec "p" $ makeProcDef args)
|
||||
addSizesFormalParameters (wrapSpec "p" $ makeProcDef args)
|
||||
(do recordProcDef args
|
||||
recordProcFormals args)
|
||||
(\x -> do checkProcDef argsWithSizes x
|
||||
|
|
|
@ -62,9 +62,7 @@ import Utils
|
|||
|
||||
--{{{ passes related to C generation
|
||||
genCPasses :: [Pass]
|
||||
genCPasses = makePassesDep' ((== BackendC) . csBackend)
|
||||
[ ("Transform wait for guards into wait until guards", transformWaitFor, [], [Prop.waitForRemoved])
|
||||
]
|
||||
genCPasses = [transformWaitFor]
|
||||
--}}}
|
||||
|
||||
cPreReq :: [Property]
|
||||
|
|
|
@ -90,12 +90,13 @@ cppgenOps = cgenOps {
|
|||
--}}}
|
||||
|
||||
genCPPCSPPasses :: [Pass]
|
||||
genCPPCSPPasses = makePassesDep' ((== BackendCPPCSP) . csBackend)
|
||||
[ ("Transform channels to ANY", chansToAny, [Prop.processTypesChecked], [Prop.allChansToAnyOrProtocol])
|
||||
]
|
||||
genCPPCSPPasses = [chansToAny]
|
||||
|
||||
chansToAny :: PassType
|
||||
chansToAny x = do st <- get
|
||||
chansToAny :: Pass
|
||||
chansToAny = cppOnlyPass "Transform channels to ANY"
|
||||
[Prop.processTypesChecked]
|
||||
[Prop.allChansToAnyOrProtocol]
|
||||
$ \x -> do st <- get
|
||||
case csFrontend st of
|
||||
FrontendOccam ->
|
||||
do chansToAnyInCompState
|
||||
|
|
|
@ -955,10 +955,6 @@ assertEquivalentProblems title exp act
|
|||
sortProblem :: [(EqualityProblem, InequalityProblem)] -> [(EqualityProblem, InequalityProblem)]
|
||||
sortProblem = sort
|
||||
|
||||
checkRight :: (Show a, TestMonad m r) => Either a b -> m b
|
||||
checkRight (Left err) = testFailure ("Not Right: " ++ show err) >> return undefined
|
||||
checkRight (Right x) = return x
|
||||
|
||||
-- QuickCheck tests for Omega Test:
|
||||
-- The idea is to begin with a random list of integers, representing answers.
|
||||
-- Combine this with a randomly generated matrix of coefficients for equalities
|
||||
|
|
|
@ -109,7 +109,7 @@ testGetVarProc = TestList (map doTest tests)
|
|||
-- TestUtils.
|
||||
doTest :: (Int,[Var],[Var],[Var],A.Process) -> Test
|
||||
doTest (index, r, w, u, proc)
|
||||
= TestCase $ do result <- runPass (getVarProc proc) startState
|
||||
= TestCase $ do result <- runPass' (getVarProc proc) startState
|
||||
case result of
|
||||
(_, Left err) ->
|
||||
testFailure $ name ++ " failed: " ++ show err
|
||||
|
|
|
@ -38,7 +38,6 @@ If they are not equal, it shows them (using 'show') with the given message prefi
|
|||
|
||||
module TestUtils where
|
||||
|
||||
import Control.Monad.Error
|
||||
import Control.Monad.State
|
||||
import Control.Monad.Writer
|
||||
import Data.Generics
|
||||
|
@ -54,7 +53,6 @@ import Metadata (emptyMeta)
|
|||
import Pass
|
||||
import Pattern
|
||||
import PrettyShow
|
||||
import TagAST
|
||||
import TestFramework
|
||||
import TreeUtils
|
||||
import Types
|
||||
|
@ -447,8 +445,8 @@ checkTempVarTypes testName vars is = mapM_ (checkTempVarType testName is) vars
|
|||
Nothing -> liftIO $ assertFailure (testName ++ ": spec does not have identifiable type for key \"" ++ key ++ "\": " ++ show (A.ndSpecType nd))
|
||||
) state
|
||||
|
||||
assertEither :: (Eq a, Show a) => String -> a -> Either String a -> Assertion
|
||||
assertEither testName exp = assertEqual testName (Right exp)
|
||||
assertEither :: (Eq a, Eq e, Show a, Show e, TestMonad m r) => String -> a -> Either e a -> m ()
|
||||
assertEither testName exp = testEqual testName (Right exp)
|
||||
|
||||
assertEitherFail :: String -> Either String a -> Assertion
|
||||
assertEitherFail testName result
|
||||
|
@ -456,6 +454,10 @@ assertEitherFail testName result
|
|||
Left _ -> return ()
|
||||
Right _ -> assertFailure $ testName ++ "; test expected to fail but passed"
|
||||
|
||||
checkRight :: (Show a, TestMonad m r) => Either a b -> m b
|
||||
checkRight (Left err) = testFailure ("Not Right: " ++ show err) >> return undefined
|
||||
checkRight (Right x) = return x
|
||||
|
||||
--}}}
|
||||
--{{{ canned tests
|
||||
|
||||
|
@ -466,12 +468,13 @@ testPassGetItems ::
|
|||
(Data a, Data b, TestMonad m r) =>
|
||||
String -- ^ The message\/test name to prefix on failure.
|
||||
-> a -- ^ The expected outcome of the pass. Will be used as a 'Pattern', to find the named items in the result of the pass.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass
|
||||
-> b
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> m (CompState, Either (m ()) Items) -- ^ Returns the state, along with either an 'Assertion' (if the pass fails) or the 'Items' (if the pass succeeds).
|
||||
testPassGetItems testName expected actualPass startStateTrans =
|
||||
testPassGetItems testName expected actualPass src startStateTrans =
|
||||
--passResult :: Either String b
|
||||
do passResult <- runPass actualPass startState
|
||||
do passResult <- runPass actualPass src startState
|
||||
case passResult of
|
||||
(st, Left (_, err)) -> return (st, Left $ testFailure (prefixErr $ "pass actually failed: " ++ err))
|
||||
(st, Right resultItem) -> return (st, transformEither (mapM_ (testFailure . prefixErr)) (id) $ getMatchedItems expected resultItem)
|
||||
|
@ -484,35 +487,52 @@ testPassGetItems testName expected actualPass startStateTrans =
|
|||
|
||||
|
||||
-- | Runs a given AST pass and returns the subsequent state, along with either an error or the result. This function is primarily intended for internal use by this module.
|
||||
runPass :: TestMonad m r =>
|
||||
PassM b -- ^ The actual pass.
|
||||
runPass :: (Data b, TestMonad m r) =>
|
||||
Pass -> b -- ^ The actual pass.
|
||||
-> CompState -- ^ The state to use to run the pass.
|
||||
-> m (CompState, Either ErrorReport b) -- ^ The resultant state, and either an error or the successful outcome of the pass.
|
||||
runPass actualPass startState = liftM (\(x,y,_) -> (y,x)) $
|
||||
runIO (runPassM startState actualPass)
|
||||
runPass actualPass src startState = liftM (\(x,y,_) -> (y,x)) $
|
||||
runIO (runPassM startState $ passCode actualPass src)
|
||||
|
||||
runPass' :: TestMonad m r =>
|
||||
PassM b -> CompState -> m (CompState, Either ErrorReport b)
|
||||
runPass' actualPass startState
|
||||
= runIO (runPassM startState actualPass) >>* \(x,y,_) -> (y,x)
|
||||
|
||||
-- | A test that runs a given AST pass and checks that it succeeds.
|
||||
testPass ::
|
||||
(Data a, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> a -- ^ The expected value. Can either be an actual AST, or a 'Pattern' to match an AST.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass -- ^ The actual pass.
|
||||
-> b -- ^ The source for the actual pass
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> m ()
|
||||
--If Items are returned by testPassGetItems we return () [i.e. give an empty assertion], otherwise give back the assertion:
|
||||
testPass w x y z = join $ liftM (either (id) (\x -> return ())) $ (liftM snd) $ (testPassGetItems w x y z)
|
||||
testPass w x x' y z = join $ testPassGetItems w x x' y z >>* (either id (const $ return ()) . snd)
|
||||
|
||||
testPass' ::
|
||||
(Data a, Show a, Eq a, Data b, TestMonad m r) =>
|
||||
String -> a -> PassM b -> State CompState () -> m ()
|
||||
testPass' name exp act st
|
||||
= runPass' act (execState st emptyState)
|
||||
>>= \x -> case snd x of
|
||||
Left err -> testFailure $ name ++ " expected to pass but failed: " ++
|
||||
show err
|
||||
Right x' -> testPatternMatch name exp x'
|
||||
|
||||
-- | A test that runs a given AST pass and checks that it succeeds, and performs an additional check on the result
|
||||
testPassWithCheck ::
|
||||
(Data a, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> a -- ^ The expected value. Can either be an actual AST, or a 'Pattern' to match an AST.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass -- ^ The actual pass.
|
||||
-> b -- ^ The source for the actual pass
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> (b -> m ())
|
||||
-> m ()
|
||||
testPassWithCheck testName expected actualPass startStateTrans checkFunc =
|
||||
do passResult <- runPass actualPass (execState startStateTrans emptyState)
|
||||
testPassWithCheck testName expected actualPass src startStateTrans checkFunc =
|
||||
do passResult <- runPass actualPass src (execState startStateTrans emptyState)
|
||||
case snd passResult of
|
||||
Left (_,err) -> testFailure (testName ++ "; pass actually failed: " ++ err)
|
||||
Right result -> (testPatternMatch testName expected result) >> (checkFunc result)
|
||||
|
@ -522,12 +542,13 @@ testPassWithItemsCheck ::
|
|||
(Data a, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> a -- ^ The expected value. Can either be an actual AST, or a 'Pattern' to match an AST.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass -- ^ The actual pass.
|
||||
-> b -- ^ The source for the actual pass
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> (Items -> m ()) -- ^ A function to check the 'Items' once the pass succeeds.
|
||||
-> m ()
|
||||
testPassWithItemsCheck testName expected actualPass startStateTrans checkFunc =
|
||||
((liftM snd) (testPassGetItems testName expected actualPass startStateTrans))
|
||||
testPassWithItemsCheck testName expected actualPass src startStateTrans checkFunc =
|
||||
((liftM snd) (testPassGetItems testName expected actualPass src startStateTrans))
|
||||
>>= (\res ->
|
||||
case res of
|
||||
Left assert -> assert
|
||||
|
@ -539,12 +560,13 @@ testPassWithStateCheck ::
|
|||
(Data a, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> a -- ^ The expected value. Can either be an actual AST, or a 'Pattern' to match an AST.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass -- ^ The actual pass.
|
||||
-> b -- ^ The source for the actual pass
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> (CompState -> m ()) -- ^ A function to check the 'CompState' once the pass succeeds.
|
||||
-> m ()
|
||||
testPassWithStateCheck testName expected actualPass startStateTrans checkFunc =
|
||||
(testPassGetItems testName expected actualPass startStateTrans)
|
||||
testPassWithStateCheck testName expected actualPass src startStateTrans checkFunc =
|
||||
(testPassGetItems testName expected actualPass src startStateTrans)
|
||||
>>= (\x ->
|
||||
case x of
|
||||
(_,Left assert) -> assert
|
||||
|
@ -556,12 +578,13 @@ testPassWithItemsStateCheck ::
|
|||
(Data a, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> a -- ^ The expected value. Can either be an actual AST, or a 'Pattern' to match an AST.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass -- ^ The actual pass.
|
||||
-> b -- ^ The source for the actual pass
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> ((Items,CompState) -> m ()) -- ^ A function to check the 'Items' and 'CompState' once the pass succeeds.
|
||||
-> m ()
|
||||
testPassWithItemsStateCheck testName expected actualPass startStateTrans checkFunc =
|
||||
(testPassGetItems testName expected actualPass startStateTrans)
|
||||
testPassWithItemsStateCheck testName expected actualPass src startStateTrans checkFunc =
|
||||
(testPassGetItems testName expected actualPass src startStateTrans)
|
||||
>>= (\x ->
|
||||
case x of
|
||||
(_,Left assert) -> assert
|
||||
|
@ -572,15 +595,29 @@ testPassWithItemsStateCheck testName expected actualPass startStateTrans checkFu
|
|||
testPassShouldFail ::
|
||||
(Show b, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> Pass -- ^ The actual pass.
|
||||
-> b -- ^ The source for the actual pass
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> m ()
|
||||
testPassShouldFail testName actualPass startStateTrans =
|
||||
do ret <- runPass actualPass (execState startStateTrans emptyState)
|
||||
testPassShouldFail testName actualPass src startStateTrans =
|
||||
do ret <- runPass actualPass src (execState startStateTrans emptyState)
|
||||
case ret of
|
||||
(_,Left err) -> return ()
|
||||
(state, Right output) -> testFailure $ testName ++ " pass succeeded when expected to fail; output: " ++ pshow output
|
||||
|
||||
testPassShouldFail' ::
|
||||
(Show b, Data b, TestMonad m r) =>
|
||||
String -- ^ The test name.
|
||||
-> PassM b -- ^ The actual pass.
|
||||
-> (State CompState ()) -- ^ A function to transform a 'CompState'. Will be used on the 'emptyState' to get the initial state for the pass.
|
||||
-> m ()
|
||||
testPassShouldFail' testName actualPass startStateTrans =
|
||||
do ret <- runPass' actualPass (execState startStateTrans emptyState)
|
||||
case ret of
|
||||
(_,Left err) -> return ()
|
||||
(state, Right output) -> testFailure $ testName ++ " pass succeeded when expected to fail; output: " ++ pshow output
|
||||
|
||||
|
||||
--}}}
|
||||
--{{{ miscellaneous utilities
|
||||
|
||||
|
|
|
@ -36,34 +36,22 @@ import Types
|
|||
|
||||
-- | Occam-specific frontend passes.
|
||||
occamPasses :: [Pass]
|
||||
occamPasses = makePassesDep' ((== FrontendOccam) . csFrontend)
|
||||
[ ("Dummy occam pass", dummyOccamPass,
|
||||
[],
|
||||
Prop.agg_namesDone ++ [Prop.mainTagged])
|
||||
, ("Infer types", inferTypes,
|
||||
[],
|
||||
[Prop.inferredTypesRecorded])
|
||||
, ("Fold constants", foldConstants,
|
||||
[Prop.inferredTypesRecorded],
|
||||
[Prop.constantsFolded])
|
||||
, ("Fix the types of array constructors", fixConstructorTypes,
|
||||
[Prop.constantsFolded],
|
||||
[Prop.arrayConstructorTypesDone])
|
||||
, ("Check mandatory constants", checkConstants,
|
||||
[Prop.constantsFolded, Prop.arrayConstructorTypesDone],
|
||||
[Prop.constantsChecked])
|
||||
, ("Resolve ambiguities", resolveAmbiguities,
|
||||
[Prop.inferredTypesRecorded],
|
||||
[Prop.ambiguitiesResolved])
|
||||
, ("Check types", checkTypes,
|
||||
[Prop.inferredTypesRecorded, Prop.ambiguitiesResolved],
|
||||
[Prop.expressionTypesChecked, Prop.processTypesChecked,
|
||||
Prop.functionTypesChecked, Prop.retypesChecked])
|
||||
occamPasses =
|
||||
[ occamOnlyPass "Dummy occam pass" [] (Prop.agg_namesDone ++ [Prop.mainTagged]) return
|
||||
, inferTypes
|
||||
, foldConstants
|
||||
, fixConstructorTypes
|
||||
, checkConstants
|
||||
, resolveAmbiguities
|
||||
, checkTypes
|
||||
]
|
||||
|
||||
-- | Fixed the types of array constructors according to the replicator count
|
||||
fixConstructorTypes :: Data t => t -> PassM t
|
||||
fixConstructorTypes = applyDepthM doExpression
|
||||
fixConstructorTypes :: Pass
|
||||
fixConstructorTypes = occamOnlyPass "Fix the types of array constructors"
|
||||
[Prop.constantsFolded]
|
||||
[Prop.arrayConstructorTypesDone]
|
||||
$ applyDepthM doExpression
|
||||
where
|
||||
doExpression :: A.Expression -> PassM A.Expression
|
||||
doExpression (A.ExprConstr m (A.RepConstr m' _ rep expr))
|
||||
|
@ -74,8 +62,11 @@ fixConstructorTypes = applyDepthM doExpression
|
|||
doExpression e = return e
|
||||
|
||||
-- | Handle ambiguities in the occam syntax that the parser can't resolve.
|
||||
resolveAmbiguities :: Data t => t -> PassM t
|
||||
resolveAmbiguities = applyDepthM doExpressionList
|
||||
resolveAmbiguities :: Pass
|
||||
resolveAmbiguities = occamOnlyPass "Resolve ambiguities"
|
||||
[Prop.inferredTypesRecorded]
|
||||
[Prop.ambiguitiesResolved]
|
||||
$ applyDepthM doExpressionList
|
||||
where
|
||||
doExpressionList :: Transform A.ExpressionList
|
||||
-- A single function call inside an ExpressionList is actually a
|
||||
|
@ -85,8 +76,11 @@ resolveAmbiguities = applyDepthM doExpressionList
|
|||
doExpressionList e = return e
|
||||
|
||||
-- | Fold constant expressions.
|
||||
foldConstants :: Data t => t -> PassM t
|
||||
foldConstants = applyDepthM2 doExpression doSpecification
|
||||
foldConstants :: Pass
|
||||
foldConstants = occamOnlyPass "Fold constants"
|
||||
[Prop.inferredTypesRecorded]
|
||||
[Prop.constantsFolded]
|
||||
$ applyDepthM2 doExpression doSpecification
|
||||
where
|
||||
-- Try to fold all expressions we encounter. Since we've recursed into the
|
||||
-- expression first, this'll also fold subexpressions of non-constant
|
||||
|
@ -105,8 +99,11 @@ foldConstants = applyDepthM2 doExpression doSpecification
|
|||
return s
|
||||
|
||||
-- | Check that things that must be constant are.
|
||||
checkConstants :: Data t => t -> PassM t
|
||||
checkConstants = applyDepthM2 doDimension doOption
|
||||
checkConstants :: Pass
|
||||
checkConstants = occamOnlyPass "Check mandatory constants"
|
||||
[Prop.constantsFolded, Prop.arrayConstructorTypesDone]
|
||||
[Prop.constantsChecked]
|
||||
$ applyDepthM2 doDimension doOption
|
||||
where
|
||||
-- Check array dimensions are constant.
|
||||
doDimension :: A.Dimension -> PassM A.Dimension
|
||||
|
@ -125,7 +122,4 @@ checkConstants = applyDepthM2 doDimension doOption
|
|||
return o
|
||||
doOption o = return o
|
||||
|
||||
-- | A dummy pass for things that haven't been separated out into passes yet.
|
||||
dummyOccamPass :: Data t => t -> PassM t
|
||||
dummyOccamPass = return
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ testFoldConstants = TestList
|
|||
where
|
||||
test :: Data a => Int -> a -> a -> Test
|
||||
test n orig exp = TestCase $ testPass ("testFoldConstants" ++ show n)
|
||||
exp (OccamPasses.foldConstants orig)
|
||||
exp OccamPasses.foldConstants orig
|
||||
startState
|
||||
|
||||
testSame :: Int -> A.Expression -> Test
|
||||
|
@ -138,13 +138,13 @@ testCheckConstants = TestList
|
|||
testOK :: (Show a, Data a) => Int -> a -> Test
|
||||
testOK n orig
|
||||
= TestCase $ testPass ("testCheckConstants" ++ show n)
|
||||
orig (OccamPasses.checkConstants orig)
|
||||
orig OccamPasses.checkConstants orig
|
||||
(return ())
|
||||
|
||||
testFail :: (Show a, Data a) => Int -> a -> Test
|
||||
testFail n orig
|
||||
= TestCase $ testPassShouldFail ("testCheckConstants" ++ show n)
|
||||
(OccamPasses.checkConstants orig)
|
||||
OccamPasses.checkConstants orig
|
||||
(return ())
|
||||
|
||||
dim10 = A.Dimension $ intLiteral 10
|
||||
|
|
|
@ -30,6 +30,7 @@ import EvalConstants
|
|||
import Intrinsics
|
||||
import Metadata
|
||||
import Pass
|
||||
import qualified Properties as Prop
|
||||
import ShowCode
|
||||
import Traversal
|
||||
import Types
|
||||
|
@ -602,8 +603,11 @@ inSubscriptedContext m body
|
|||
--{{{ inferTypes
|
||||
|
||||
-- | Infer types.
|
||||
inferTypes :: PassType
|
||||
inferTypes = recurse
|
||||
inferTypes :: Pass
|
||||
inferTypes = occamOnlyPass "Infer types"
|
||||
[]
|
||||
[Prop.inferredTypesRecorded]
|
||||
$ recurse
|
||||
where
|
||||
ops :: Ops
|
||||
ops = baseOp
|
||||
|
@ -999,12 +1003,15 @@ inferTypes = recurse
|
|||
-- | Check the AST for type consistency.
|
||||
-- This is actually a series of smaller passes that check particular types
|
||||
-- inside the AST, but it doesn't really make sense to split it up.
|
||||
checkTypes :: PassType
|
||||
checkTypes t =
|
||||
checkVariables t >>=
|
||||
checkExpressions >>=
|
||||
checkSpecTypes >>=
|
||||
checkProcesses >>=
|
||||
checkTypes :: Pass
|
||||
checkTypes = occamOnlyPass "Check types"
|
||||
[Prop.inferredTypesRecorded, Prop.ambiguitiesResolved]
|
||||
[Prop.expressionTypesChecked, Prop.processTypesChecked,
|
||||
Prop.functionTypesChecked, Prop.retypesChecked]
|
||||
$ checkVariables >.>
|
||||
checkExpressions >.>
|
||||
checkSpecTypes >.>
|
||||
checkProcesses >.>
|
||||
checkReplicators
|
||||
|
||||
--{{{ checkVariables
|
||||
|
|
|
@ -513,13 +513,13 @@ testOccamTypes = TestList
|
|||
testOK :: (Show a, Data a) => Int -> a -> Test
|
||||
testOK n orig
|
||||
= TestCase $ testPass ("testOccamTypes" ++ show n)
|
||||
orig (OccamTypes.checkTypes orig)
|
||||
orig OccamTypes.checkTypes orig
|
||||
startState
|
||||
|
||||
testFail :: (Show a, Data a) => Int -> a -> Test
|
||||
testFail n orig
|
||||
= TestCase $ testPassShouldFail ("testOccamTypes" ++ show n)
|
||||
(OccamTypes.checkTypes orig)
|
||||
OccamTypes.checkTypes orig
|
||||
startState
|
||||
|
||||
--{{{ expression fragments
|
||||
|
|
|
@ -28,7 +28,7 @@ import TestUtils
|
|||
|
||||
-- | Test 'preprocessOccam' when we're expecting it to succeed.
|
||||
testPP :: Int -> [TokenType] -> [TokenType] -> Test
|
||||
testPP n itts etts = TestCase $ testPass ("testPP " ++ show n) (makeTokens etts) pass (return ())
|
||||
testPP n itts etts = TestCase $ testPass' ("testPP " ++ show n) (makeTokens etts) pass (return ())
|
||||
where
|
||||
makeTokens = zip (repeat emptyMeta)
|
||||
pass = preprocessOccam (makeTokens itts)
|
||||
|
@ -47,21 +47,21 @@ testPPCond n = testPPCondAfter n []
|
|||
|
||||
-- | Test 'preprocessOccam' when we're expecting it to fail.
|
||||
testPPFail :: Int -> [TokenType] -> Test
|
||||
testPPFail n itts = TestCase $ testPassShouldFail ("testPPFail " ++ show n) pass (return ())
|
||||
testPPFail n itts = TestCase $ testPassShouldFail' ("testPPFail " ++ show n) pass (return ())
|
||||
where
|
||||
makeTokens = zip (repeat emptyMeta)
|
||||
pass = preprocessOccam (makeTokens itts)
|
||||
|
||||
-- | Test 'expandIncludes' when we're expecting it to succeed.
|
||||
testEI :: Int -> [TokenType] -> [TokenType] -> Test
|
||||
testEI n itts etts = TestCase $ testPass ("testEI " ++ show n) (makeTokens etts) pass (return ())
|
||||
testEI n itts etts = TestCase $ testPass' ("testEI " ++ show n) (makeTokens etts) pass (return ())
|
||||
where
|
||||
makeTokens = zip (repeat emptyMeta)
|
||||
pass = expandIncludes (makeTokens itts)
|
||||
|
||||
-- | Test 'expandIncludes' when we're expecting it to fail.
|
||||
testEIFail :: Int -> [TokenType] -> Test
|
||||
testEIFail n itts = TestCase $ testPassShouldFail ("testEIFail " ++ show n) pass (return ())
|
||||
testEIFail n itts = TestCase $ testPassShouldFail' ("testEIFail " ++ show n) pass (return ())
|
||||
where
|
||||
makeTokens = zip (repeat emptyMeta)
|
||||
pass = expandIncludes (makeTokens itts)
|
||||
|
|
|
@ -40,7 +40,7 @@ import Types
|
|||
|
||||
-- | An ordered list of the Rain-specific passes to be run.
|
||||
rainPasses :: [Pass]
|
||||
rainPasses = let f = makePassesDep' ((== FrontendRain) . csFrontend) in
|
||||
rainPasses =
|
||||
[ excludeNonRainFeatures
|
||||
, rainOnlyPass "Dummy Rain pass" [] [Prop.retypesChecked] return
|
||||
, transformInt
|
||||
|
|
|
@ -39,12 +39,14 @@ import qualified AST as A
|
|||
import CompState
|
||||
import Errors
|
||||
import Metadata
|
||||
import Pass
|
||||
import Pattern
|
||||
import RainPasses
|
||||
import RainTypes
|
||||
import TagAST
|
||||
import TestUtils
|
||||
import TreeUtils
|
||||
import Utils
|
||||
|
||||
m :: Meta
|
||||
m = emptyMeta
|
||||
|
@ -65,7 +67,7 @@ makeRange b e = A.Dyadic emptyMeta A.Add (intLiteral 1)
|
|||
(A.Dyadic emptyMeta A.Subtr (intLiteral e) (intLiteral b))
|
||||
|
||||
testEachRangePass0 :: Test
|
||||
testEachRangePass0 = TestCase $ testPass "testEachRangePass0" exp (transformEachRange orig) (return ())
|
||||
testEachRangePass0 = TestCase $ testPass "testEachRangePass0" exp transformEachRange orig (return ())
|
||||
where
|
||||
orig = A.Par m A.PlainPar $ A.Rep m
|
||||
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m
|
||||
|
@ -76,7 +78,7 @@ testEachRangePass0 = TestCase $ testPass "testEachRangePass0" exp (transformEach
|
|||
(A.Only m (makeSimpleAssign "c" "x"))
|
||||
|
||||
testEachRangePass1 :: Test
|
||||
testEachRangePass1 = TestCase $ testPass "testEachRangePass1" exp (transformEachRange orig) (return ())
|
||||
testEachRangePass1 = TestCase $ testPass "testEachRangePass1" exp transformEachRange orig (return ())
|
||||
where
|
||||
orig = A.Par m A.PlainPar $ A.Rep m
|
||||
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m undefined
|
||||
|
@ -88,7 +90,7 @@ testEachRangePass1 = TestCase $ testPass "testEachRangePass1" exp (transformEach
|
|||
(A.Only m (makeSimpleAssign "c" "x"))
|
||||
|
||||
testEachRangePass2 :: Test
|
||||
testEachRangePass2 = TestCase $ testPass "testEachRangePass2" exp (transformEachRange orig) (return ())
|
||||
testEachRangePass2 = TestCase $ testPass "testEachRangePass2" exp transformEachRange orig (return ())
|
||||
where
|
||||
orig = A.Seq m $ A.Rep m
|
||||
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m undefined
|
||||
|
@ -99,7 +101,7 @@ testEachRangePass2 = TestCase $ testPass "testEachRangePass2" exp (transformEach
|
|||
(A.Only m (makeSimpleAssign "c" "x"))
|
||||
|
||||
testEachRangePass3 :: Test
|
||||
testEachRangePass3 = TestCase $ testPass "testEachRangePass3" exp (transformEachRange orig) (return ())
|
||||
testEachRangePass3 = TestCase $ testPass "testEachRangePass3" exp transformEachRange orig (return ())
|
||||
where
|
||||
orig = A.Seq m $ A.Rep m
|
||||
(A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m undefined
|
||||
|
@ -112,7 +114,7 @@ testEachRangePass3 = TestCase $ testPass "testEachRangePass3" exp (transformEach
|
|||
|
||||
-- | Test variable is made unique in a declaration:
|
||||
testUnique0 :: Test
|
||||
testUnique0 = TestCase $ testPassWithItemsStateCheck "testUnique0" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||
testUnique0 = TestCase $ testPassWithItemsStateCheck "testUnique0" exp uniquifyAndResolveVars orig (return ()) check
|
||||
where
|
||||
orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte) skipP
|
||||
exp = mSpecP (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte) skipP
|
||||
|
@ -124,7 +126,7 @@ testUnique0 = TestCase $ testPassWithItemsStateCheck "testUnique0" exp (uniquify
|
|||
|
||||
-- | Tests that two declarations of a variable with the same name are indeed made unique:
|
||||
testUnique1 :: Test
|
||||
testUnique1 = TestCase $ testPassWithItemsStateCheck "testUnique1" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||
testUnique1 = TestCase $ testPassWithItemsStateCheck "testUnique1" exp uniquifyAndResolveVars orig (return ()) check
|
||||
where
|
||||
orig = A.Several m [A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte ) skipP,
|
||||
A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Int64 ) skipP]
|
||||
|
@ -143,7 +145,7 @@ testUnique1 = TestCase $ testPassWithItemsStateCheck "testUnique1" exp (uniquify
|
|||
|
||||
-- | Tests that the unique pass does resolve the variables that are in scope
|
||||
testUnique2 :: Test
|
||||
testUnique2 = TestCase $ testPassWithItemsStateCheck "testUnique2" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||
testUnique2 = TestCase $ testPassWithItemsStateCheck "testUnique2" exp uniquifyAndResolveVars orig (return ()) check
|
||||
where
|
||||
orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte ) (A.Only m $ makeSimpleAssign "c" "d")
|
||||
exp = mSpecP (tag3 A.Specification DontCare ("newc"@@DontCare) $ A.Declaration m A.Byte )
|
||||
|
@ -153,7 +155,7 @@ testUnique2 = TestCase $ testPassWithItemsStateCheck "testUnique2" exp (uniquify
|
|||
|
||||
|
||||
testUnique2b :: Test
|
||||
testUnique2b = TestCase $ testPassWithItemsStateCheck "testUnique2b" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||
testUnique2b = TestCase $ testPassWithItemsStateCheck "testUnique2b" exp uniquifyAndResolveVars orig (return ()) check
|
||||
where
|
||||
orig = A.Spec m (A.Specification m (simpleName "c") $ A.Declaration m A.Byte ) $
|
||||
A.Several m [(A.Only m $ makeSimpleAssign "c" "d"),(A.Only m $ makeSimpleAssign "c" "e")]
|
||||
|
@ -168,7 +170,7 @@ testUnique2b = TestCase $ testPassWithItemsStateCheck "testUnique2b" exp (uniqui
|
|||
|
||||
-- | Tests that proc names are recorded, but not made unique (because they might be exported), and not resolved either
|
||||
testUnique3 :: Test
|
||||
testUnique3 = TestCase $ testPassWithItemsStateCheck "testUnique3" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||
testUnique3 = TestCase $ testPassWithItemsStateCheck "testUnique3" exp uniquifyAndResolveVars orig (return ()) check
|
||||
where
|
||||
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
|
||||
|
@ -177,7 +179,7 @@ testUnique3 = TestCase $ testPassWithItemsStateCheck "testUnique3" exp (uniquify
|
|||
|
||||
-- | Tests that parameters are uniquified and resolved:
|
||||
testUnique4 :: Test
|
||||
testUnique4 = TestCase $ testPassWithItemsStateCheck "testUnique4" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||
testUnique4 = TestCase $ testPassWithItemsStateCheck "testUnique4" exp uniquifyAndResolveVars orig (return ()) check
|
||||
where
|
||||
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 $ exprVariable "c"]) (skipP)
|
||||
|
@ -207,7 +209,7 @@ testUnique4 = TestCase $ testPassWithItemsStateCheck "testUnique4" exp (uniquify
|
|||
|
||||
-- | checks that c's type is recorded in: ***each (c : "hello") {}
|
||||
testRecordInfNames0 :: Test
|
||||
testRecordInfNames0 = TestCase $ testPassWithStateCheck "testRecordInfNames0" exp (recordInfNameTypes orig) (return ()) check
|
||||
testRecordInfNames0 = TestCase $ testPassWithStateCheck "testRecordInfNames0" exp recordInfNameTypes orig (return ()) check
|
||||
where
|
||||
orig = (A.Rep m (A.ForEach m (simpleName "c") (makeLiteralStringRain "hello")) skipP)
|
||||
exp = orig
|
||||
|
@ -217,7 +219,7 @@ testRecordInfNames0 = TestCase $ testPassWithStateCheck "testRecordInfNames0" ex
|
|||
|
||||
-- | checks that c's type is recorded in: ***each (c : str) {}, where str is known to be of type string
|
||||
testRecordInfNames1 :: Test
|
||||
testRecordInfNames1 = TestCase $ testPassWithStateCheck "testRecordInfNames1" exp (recordInfNameTypes orig) (startState') check
|
||||
testRecordInfNames1 = TestCase $ testPassWithStateCheck "testRecordInfNames1" exp recordInfNameTypes orig (startState') check
|
||||
where
|
||||
startState' :: State CompState ()
|
||||
startState' = do defineName (simpleName "str") $ simpleDef "str" (A.Declaration m (A.List A.Byte) )
|
||||
|
@ -229,7 +231,7 @@ testRecordInfNames1 = TestCase $ testPassWithStateCheck "testRecordInfNames1" ex
|
|||
|
||||
-- | checks that c's and d's type are recorded in: ***each (c : multi) { seqeach (d : c) {} } where multi is known to be of type [string]
|
||||
testRecordInfNames2 :: Test
|
||||
testRecordInfNames2 = TestCase $ testPassWithStateCheck "testRecordInfNames2" exp (recordInfNameTypes orig) (startState') check
|
||||
testRecordInfNames2 = TestCase $ testPassWithStateCheck "testRecordInfNames2" exp recordInfNameTypes orig (startState') check
|
||||
where
|
||||
startState' :: State CompState ()
|
||||
startState' = do defineName (simpleName "multi") $ simpleDef "multi" (A.Declaration m (A.List $ A.List A.Byte) )
|
||||
|
@ -246,8 +248,8 @@ testRecordInfNames2 = TestCase $ testPassWithStateCheck "testRecordInfNames2" ex
|
|||
"d") A.Abbrev A.Unplaced)
|
||||
|
||||
--Easy way to string two passes together; creates a pass-like function that applies the left-hand pass then the right-hand pass. Associative.
|
||||
(>>>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
|
||||
(>>>) f0 f1 x = (f0 x) >>= f1
|
||||
(>>>) :: Pass -> Pass -> Pass
|
||||
(>>>) f0 f1 = Pass {passCode = passCode f1 <.< passCode f0}
|
||||
|
||||
--Normally, process names in Rain are not mangled. And this should be fine in all cases - but not for the main process (which would
|
||||
--result in a function called main. Therefore we must mangle main. Ideally into a nonce, but for now into ____main
|
||||
|
@ -255,7 +257,7 @@ testRecordInfNames2 = TestCase $ testPassWithStateCheck "testRecordInfNames2" ex
|
|||
--TODO check recursive main function works
|
||||
|
||||
testFindMain0 :: Test
|
||||
testFindMain0 = TestCase $ testPassWithItemsStateCheck "testFindMain0" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
|
||||
testFindMain0 = TestCase $ testPassWithItemsStateCheck "testFindMain0" exp (uniquifyAndResolveVars >>> findMain) orig (return ()) check
|
||||
where
|
||||
orig = A.Spec m (A.Specification m (A.Name m "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m [] :: A.AST
|
||||
exp = mSpecAST (tag3 A.Specification DontCare (tag2 A.Name DontCare ("main"@@DontCare)) $
|
||||
|
@ -268,13 +270,13 @@ testFindMain0 = TestCase $ testPassWithItemsStateCheck "testFindMain0" exp ((uni
|
|||
(tag6 A.NameDef DontCare mainName "main" DontCare A.Original A.Unplaced)
|
||||
|
||||
testFindMain1 :: Test
|
||||
testFindMain1 = TestCase $ testPassWithStateCheck "testFindMain1" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
|
||||
testFindMain1 = TestCase $ testPassWithStateCheck "testFindMain1" orig (uniquifyAndResolveVars >>> findMain) orig (return ()) check
|
||||
where
|
||||
orig = A.Spec m (A.Specification m (A.Name m "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m ([] :: [A.AST])
|
||||
check state = assertEqual "testFindMain1" [] (csMainLocals state)
|
||||
|
||||
testFindMain2 :: Test
|
||||
testFindMain2 = TestCase $ testPassWithItemsStateCheck "testFindMain2" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
|
||||
testFindMain2 = TestCase $ testPassWithItemsStateCheck "testFindMain2" exp (uniquifyAndResolveVars >>> findMain) orig (return ()) check
|
||||
where
|
||||
inner = A.Spec m (A.Specification m (A.Name m "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
|
||||
A.Several m ([] :: [A.AST])
|
||||
|
@ -296,10 +298,10 @@ testParamPass ::
|
|||
|
||||
testParamPass testName formals params transParams
|
||||
= case transParams of
|
||||
Just act -> TestList [TestCase $ testPass (testName ++ "/process") (expProc act) (performTypeUnification origProc) startStateProc,
|
||||
TestCase $ testPass (testName ++ "/function") (expFunc act) (performTypeUnification origFunc) startStateFunc]
|
||||
Nothing -> TestList [TestCase $ testPassShouldFail (testName ++ "/process") (performTypeUnification origProc) startStateProc,
|
||||
TestCase $ testPassShouldFail (testName ++ "/function") (performTypeUnification origFunc) startStateFunc]
|
||||
Just act -> TestList [TestCase $ testPass (testName ++ "/process") (expProc act) performTypeUnification origProc startStateProc,
|
||||
TestCase $ testPass (testName ++ "/function") (expFunc act) performTypeUnification origFunc startStateFunc]
|
||||
Nothing -> TestList [TestCase $ testPassShouldFail (testName ++ "/process") performTypeUnification origProc startStateProc,
|
||||
TestCase $ testPassShouldFail (testName ++ "/function") performTypeUnification origFunc startStateFunc]
|
||||
where
|
||||
startStateProc :: State CompState ()
|
||||
startStateProc = do defineName (simpleName "x") $ simpleDefDecl "x" (A.UInt16)
|
||||
|
@ -378,8 +380,8 @@ testParamPass7 = testParamPass "testParamPass7"
|
|||
|
||||
-- | Test calling something that is not a process:
|
||||
testParamPass8 :: Test
|
||||
testParamPass8 = TestList [TestCase $ testPassShouldFail "testParamPass8/process" (performTypeUnification origProc) (startState'),
|
||||
TestCase $ testPassShouldFail "testParamPass8/function" (performTypeUnification origFunc) (startState')]
|
||||
testParamPass8 = TestList [TestCase $ testPassShouldFail "testParamPass8/process" performTypeUnification origProc (startState'),
|
||||
TestCase $ testPassShouldFail "testParamPass8/function" performTypeUnification origFunc (startState')]
|
||||
where
|
||||
startState' :: State CompState ()
|
||||
startState' = do defineName (simpleName "x") $ simpleDefDecl "x" (A.UInt16)
|
||||
|
@ -390,7 +392,7 @@ testParamPass8 = TestList [TestCase $ testPassShouldFail "testParamPass8/process
|
|||
|
||||
-- | Transform an example list
|
||||
testRangeRepPass0 :: Test
|
||||
testRangeRepPass0 = TestCase $ testPass "testRangeRepPass0" exp (transformRangeRep orig) (return())
|
||||
testRangeRepPass0 = TestCase $ testPass "testRangeRepPass0" exp transformRangeRep orig (return())
|
||||
where
|
||||
orig = A.ExprConstr m $ A.RangeConstr m A.Byte (intLiteral 0) (intLiteral 1)
|
||||
exp = tag2 A.ExprConstr DontCare $ mRepConstr A.Byte
|
||||
|
@ -399,9 +401,10 @@ testRangeRepPass0 = TestCase $ testPass "testRangeRepPass0" exp (transformRangeR
|
|||
|
||||
--TODO consider/test pulling up the definitions of variables involved in return statements in functions
|
||||
|
||||
{-
|
||||
-- | Test a fairly standard function:
|
||||
testCheckFunction0 :: Test
|
||||
testCheckFunction0 = TestCase $ testPass "testCheckFunction0" orig (checkFunction orig) (return ())
|
||||
testCheckFunction0 = TestCase $ testPass "testCheckFunction0" orig checkFunction orig (return ())
|
||||
where
|
||||
orig = A.Specification m (procName "id") $
|
||||
A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ Right
|
||||
|
@ -409,26 +412,26 @@ testCheckFunction0 = TestCase $ testPass "testCheckFunction0" orig (checkFunctio
|
|||
|
||||
-- | Test a function without a return as the final statement:
|
||||
testCheckFunction1 :: Test
|
||||
testCheckFunction1 = TestCase $ testPassShouldFail "testCheckunction1" (checkFunction orig) (return ())
|
||||
testCheckFunction1 = TestCase $ testPassShouldFail "testCheckFunction1" checkFunction orig (return ())
|
||||
where
|
||||
orig = A.Specification m (procName "brokenid") $
|
||||
A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $
|
||||
(Right $ A.Seq m $ A.Several m [])
|
||||
|
||||
-}
|
||||
testPullUpParDecl0 :: Test
|
||||
testPullUpParDecl0 = TestCase $ testPass "testPullUpParDecl0" orig (pullUpParDeclarations orig) (return ())
|
||||
testPullUpParDecl0 = TestCase $ testPass "testPullUpParDecl0" orig pullUpParDeclarations orig (return ())
|
||||
where
|
||||
orig = A.Par m A.PlainPar (A.Several m [])
|
||||
|
||||
testPullUpParDecl1 :: Test
|
||||
testPullUpParDecl1 = TestCase $ testPass "testPullUpParDecl1" exp (pullUpParDeclarations orig) (return ())
|
||||
testPullUpParDecl1 = TestCase $ testPass "testPullUpParDecl1" exp pullUpParDeclarations orig (return ())
|
||||
where
|
||||
orig = A.Par m A.PlainPar $
|
||||
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int) (A.Several m [])
|
||||
exp = A.Seq m $ A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int) (A.Only m $ A.Par m A.PlainPar $ A.Several m [])
|
||||
|
||||
testPullUpParDecl2 :: Test
|
||||
testPullUpParDecl2 = TestCase $ testPass "testPullUpParDecl2" exp (pullUpParDeclarations orig) (return ())
|
||||
testPullUpParDecl2 = TestCase $ testPass "testPullUpParDecl2" exp pullUpParDeclarations orig (return ())
|
||||
where
|
||||
orig = A.Par m A.PlainPar $
|
||||
A.Spec m (A.Specification m (simpleName "x") $ A.Declaration m A.Int) $
|
||||
|
@ -468,8 +471,8 @@ tests = TestLabel "RainPassesTest" $ TestList
|
|||
,testParamPass7
|
||||
,testParamPass8
|
||||
,testRangeRepPass0
|
||||
,testCheckFunction0
|
||||
,testCheckFunction1
|
||||
-- ,testCheckFunction0
|
||||
-- ,testCheckFunction1
|
||||
,testPullUpParDecl0
|
||||
,testPullUpParDecl1
|
||||
,testPullUpParDecl2
|
||||
|
|
|
@ -63,10 +63,10 @@ constantFoldTest = TestList
|
|||
two63 = 9223372036854775808
|
||||
|
||||
foldVar :: Int -> ExprHelper -> Test
|
||||
foldVar n e = TestCase $ testPass ("constantFoldTest " ++ show n) (buildExprPattern e) (constantFoldPass $ buildExpr e) state
|
||||
foldVar n e = TestCase $ testPass ("constantFoldTest " ++ show n) (buildExprPattern e) constantFoldPass (buildExpr e) state
|
||||
|
||||
foldCon :: Int -> ExprHelper -> ExprHelper -> Test
|
||||
foldCon n exp orig = TestCase $ testPass ("constantFoldTest " ++ show n) (buildExprPattern exp) (constantFoldPass $ buildExpr orig) state
|
||||
foldCon n exp orig = TestCase $ testPass ("constantFoldTest " ++ show n) (buildExprPattern exp) constantFoldPass (buildExpr orig) state
|
||||
|
||||
state :: State CompState ()
|
||||
state = defineVariable "x" A.Int64
|
||||
|
|
|
@ -30,13 +30,13 @@ import TreeUtils
|
|||
|
||||
-- | Test 'structureOccam' when we're expecting it to succeed.
|
||||
testS :: Int -> [Token] -> [Pattern] -> Test
|
||||
testS n its etts = TestCase $ testPass ("testS " ++ show n) ets (structureOccam its) (return ())
|
||||
testS n its etts = TestCase $ testPass' ("testS " ++ show n) ets (structureOccam its) (return ())
|
||||
where
|
||||
ets = zip (repeat DontCare) etts
|
||||
|
||||
-- | Test 'structureOccam' when we're expecting it to fail.
|
||||
testSFail :: Int -> [Token] -> Test
|
||||
testSFail n its = TestCase $ testPassShouldFail ("testSFail " ++ show n) (structureOccam its) (return ())
|
||||
testSFail n its = TestCase $ testPassShouldFail' ("testSFail " ++ show n) (structureOccam its) (return ())
|
||||
|
||||
--{{{ 0xxx simple stuff
|
||||
testSimple :: Test
|
||||
|
|
|
@ -105,13 +105,6 @@ runPassM cs pass = liftM flatten $ flip runStateT [] $ flip runStateT cs $ runEr
|
|||
flatten :: ((a, b),c) -> (a, b, c)
|
||||
flatten ((x, y), z) = (x, y, z)
|
||||
|
||||
|
||||
makePassesDep :: [(String, forall t. Data t => t -> PassM t, [Property], [Property])] -> [Pass]
|
||||
makePassesDep = map (\(s, p, pre, post) -> Pass p s (Set.fromList pre) (Set.fromList post) (const True))
|
||||
|
||||
makePassesDep' :: (CompState -> Bool) -> [(String, forall t. Data t => t -> PassM t, [Property], [Property])] -> [Pass]
|
||||
makePassesDep' f = map (\(s, p, pre, post) -> Pass p s (Set.fromList pre) (Set.fromList post) f)
|
||||
|
||||
enablePassesWhen :: (CompState -> Bool) -> [Pass] -> [Pass]
|
||||
enablePassesWhen f = map (\p -> p
|
||||
{passEnabled = \c -> f c && (passEnabled p c)})
|
||||
|
@ -158,7 +151,6 @@ pass name pre post code
|
|||
,passEnabled = const True
|
||||
}
|
||||
|
||||
|
||||
-- | Compose a list of passes into a single pass by running them in the order given.
|
||||
runPasses :: [Pass] -> (A.AST -> PassM A.AST)
|
||||
runPasses [] ast = return ast
|
||||
|
|
|
@ -48,10 +48,13 @@ commonPasses :: CompState -> [Pass]
|
|||
commonPasses opts = concat $
|
||||
-- Rain does simplifyTypes separately:
|
||||
[ enablePassesWhen ((== FrontendOccam) . csFrontend) simplifyTypes
|
||||
, makePassesDep' csUsageChecking [("Usage checking", passOnlyOnAST "usageCheckPass"
|
||||
$ runPassR usageCheckPass, Prop.agg_namesDone, [Prop.parUsageChecked])]
|
||||
, enablePassesWhen csUsageChecking
|
||||
[pass "Usage checking" Prop.agg_namesDone [Prop.parUsageChecked]
|
||||
$ passOnlyOnAST "usageCheckPass" $ runPassR usageCheckPass]
|
||||
-- If usage checking is turned off, the pass list will break unless we insert this dummy item:
|
||||
, makePassesDep' (not . csUsageChecking) [("Usage checking turned OFF", return, Prop.agg_namesDone, [Prop.parUsageChecked])]
|
||||
, enablePassesWhen (not . csUsageChecking)
|
||||
[pass "Usage checking turned OFF" Prop.agg_namesDone [Prop.parUsageChecked]
|
||||
return]
|
||||
, simplifyComms
|
||||
, simplifyExprs
|
||||
, simplifyProcs
|
||||
|
|
|
@ -74,7 +74,7 @@ singleParamSpecExp body = tag4 A.Proc DontCare A.PlainSpec [tag3 A.Formal A.ValA
|
|||
|
||||
-- | Tests a function with a single return, and a single parameter.
|
||||
testFunctionsToProcs0 :: Test
|
||||
testFunctionsToProcs0 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs0" exp (functionsToProcs orig) (return ()) check
|
||||
testFunctionsToProcs0 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs0" exp functionsToProcs orig (return ()) check
|
||||
where
|
||||
orig = singleParamFunc valof0
|
||||
exp = tag3 A.Specification DontCare (simpleName "foo") procSpec
|
||||
|
@ -91,7 +91,7 @@ testFunctionsToProcs0 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
|
|||
|
||||
-- | Tests a function with multiple returns, and multiple parameters.
|
||||
testFunctionsToProcs1 :: Test
|
||||
testFunctionsToProcs1 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs1 A" exp (functionsToProcs orig) (return ()) check
|
||||
testFunctionsToProcs1 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs1 A" exp functionsToProcs orig (return ()) check
|
||||
where
|
||||
orig = A.Specification m (simpleName "foo") (A.Function m A.PlainSpec [A.Int,A.Real32]
|
||||
[A.Formal A.ValAbbrev A.Byte (simpleName "param0"),A.Formal A.Abbrev A.Real32 (simpleName "param1")] (Left $ valofTwo "param0" "param1"))
|
||||
|
@ -121,7 +121,7 @@ testFunctionsToProcs1 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
|
|||
-- Currently I have chosen to put DontCare for the body of the function as stored in the NameDef.
|
||||
-- This behaviour is not too important, and may change at a later date.
|
||||
testFunctionsToProcs2 :: Test
|
||||
testFunctionsToProcs2 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs2 A" exp (functionsToProcs orig) (return ()) check
|
||||
testFunctionsToProcs2 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs2 A" exp functionsToProcs orig (return ()) check
|
||||
where
|
||||
orig = A.Specification m (simpleName "fooOuter") (A.Function m A.PlainSpec [A.Int] [A.Formal A.ValAbbrev A.Byte (simpleName "paramOuter0")] $ Left $
|
||||
A.Spec m (singleParamFunc valof0) valof0)
|
||||
|
@ -152,7 +152,7 @@ testFunctionsToProcs2 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
|
|||
|
||||
-- | Tests a function with a single return, and a single parameter, with a Process body
|
||||
testFunctionsToProcs3 :: Test
|
||||
testFunctionsToProcs3 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs3" exp (functionsToProcs orig) (return ()) check
|
||||
testFunctionsToProcs3 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs3" exp functionsToProcs orig (return ()) check
|
||||
where
|
||||
orig = singleParamFuncProc $ A.Seq m $ A.Only m $ A.Assign m [variable "foo"] $ A.ExpressionList m [intLiteral 0]
|
||||
exp = tag3 A.Specification DontCare (simpleName "foo") procSpec
|
||||
|
@ -169,7 +169,7 @@ testFunctionsToProcs3 = TestCase $ testPassWithItemsStateCheck "testFunctionsToP
|
|||
|
||||
-- | Tests a function with multiple returns, and multiple parameters.
|
||||
testFunctionsToProcs4 :: Test
|
||||
testFunctionsToProcs4 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs4 A" exp (functionsToProcs orig) (return ()) check
|
||||
testFunctionsToProcs4 = TestCase $ testPassWithItemsStateCheck "testFunctionsToProcs4 A" exp functionsToProcs orig (return ()) check
|
||||
where
|
||||
orig = A.Specification m (simpleName "foo") (A.Function m A.PlainSpec [A.Int,A.Real32]
|
||||
[A.Formal A.ValAbbrev A.Byte (simpleName "param0"),A.Formal A.Abbrev A.Real32 (simpleName "param1")] $
|
||||
|
@ -202,7 +202,7 @@ 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
|
||||
testTransformConstr0 :: Test
|
||||
testTransformConstr0 = TestCase $ testPass "transformConstr0" exp (transformConstr orig) startState
|
||||
testTransformConstr0 = TestCase $ testPass "transformConstr0" exp transformConstr orig startState
|
||||
where
|
||||
startState :: State CompState ()
|
||||
startState = defineConst "x" A.Int (intLiteral 42)
|
||||
|
@ -242,7 +242,7 @@ testOutExprs = TestList
|
|||
(mOnlyP $ tag3 A.Output emptyMeta chan
|
||||
[tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var" DontCare)))])
|
||||
)
|
||||
(outExprs $
|
||||
outExprs (
|
||||
A.Output emptyMeta chan [outXM 1]
|
||||
)
|
||||
(defineName (xName) $ simpleDefDecl "x" A.Int)
|
||||
|
@ -254,7 +254,7 @@ testOutExprs = TestList
|
|||
(mOnlyP $ tag3 A.Output emptyMeta chan
|
||||
[outX])
|
||||
)
|
||||
(outExprs $
|
||||
outExprs (
|
||||
A.Output emptyMeta chan [outX]
|
||||
)
|
||||
(return ())
|
||||
|
@ -269,7 +269,7 @@ testOutExprs = TestList
|
|||
]
|
||||
)
|
||||
)
|
||||
(outExprs $
|
||||
outExprs (
|
||||
A.Output emptyMeta chan [outXM 1,outX,A.OutExpression emptyMeta $ intLiteral 2]
|
||||
)
|
||||
(defineName (xName) $ simpleDefDecl "x" A.Byte)
|
||||
|
@ -285,7 +285,7 @@ testOutExprs = TestList
|
|||
]
|
||||
)
|
||||
)
|
||||
(outExprs $
|
||||
outExprs (
|
||||
A.Output emptyMeta chan [A.OutCounted emptyMeta (eXM 1) (exprVariable "x")]
|
||||
)
|
||||
(defineName (xName) $ simpleDefDecl "x" A.Byte)
|
||||
|
@ -297,7 +297,7 @@ testOutExprs = TestList
|
|||
(mOnlyP $ tag4 A.OutputCase emptyMeta chan (simpleName "foo")
|
||||
[tag2 A.OutExpression emptyMeta (tag2 A.ExprVariable DontCare (tag2 A.Variable DontCare (Named "temp_var" DontCare)))])
|
||||
)
|
||||
(outExprs $
|
||||
outExprs (
|
||||
A.OutputCase emptyMeta chan (simpleName "foo") [outXM 1]
|
||||
)
|
||||
(defineName (xName) $ simpleDefDecl "x" A.Int)
|
||||
|
@ -309,7 +309,7 @@ testOutExprs = TestList
|
|||
(tag2 A.Seq DontCare $
|
||||
(mOnlyP $ A.OutputCase emptyMeta chan (simpleName "foo") [])
|
||||
)
|
||||
(outExprs $
|
||||
outExprs (
|
||||
A.OutputCase emptyMeta chan (simpleName "foo") []
|
||||
)
|
||||
(return ())
|
||||
|
@ -354,7 +354,7 @@ testInputCase = TestList
|
|||
mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 0] p0
|
||||
]
|
||||
)
|
||||
(transformInputCase $
|
||||
transformInputCase (
|
||||
A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0
|
||||
)
|
||||
(defineMyProtocol >> defineC)
|
||||
|
@ -402,7 +402,7 @@ testInputCase = TestList
|
|||
]
|
||||
]
|
||||
)
|
||||
(transformInputCase $
|
||||
transformInputCase (
|
||||
A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Several emptyMeta
|
||||
[A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0
|
||||
,A.Only emptyMeta $ A.Variant emptyMeta c1 [A.InVariable emptyMeta z] p1
|
||||
|
@ -460,7 +460,7 @@ testInputCase = TestList
|
|||
]
|
||||
]
|
||||
)
|
||||
(transformInputCase $
|
||||
transformInputCase (
|
||||
A.Input emptyMeta c $ A.InputCase emptyMeta $ A.Several emptyMeta
|
||||
[A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0
|
||||
,specInt "z" $ A.Only emptyMeta $ A.Variant emptyMeta c1 [A.InVariable emptyMeta z] p1
|
||||
|
@ -494,7 +494,7 @@ testInputCase = TestList
|
|||
tag3 A.Case DontCare (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare (Named "tag" DontCare)) $
|
||||
mOnlyO $ tag3 A.Option DontCare [intLiteralPattern 0] p0
|
||||
)
|
||||
(transformInputCase $
|
||||
transformInputCase (
|
||||
A.Alt emptyMeta False $ A.Only emptyMeta $ A.Alternative emptyMeta (A.True emptyMeta) c
|
||||
(A.InputCase emptyMeta $ A.Only emptyMeta $ A.Variant emptyMeta a0 [] p0)
|
||||
(A.Skip emptyMeta)
|
||||
|
@ -529,30 +529,30 @@ testTransformProtocolInput = TestList
|
|||
[
|
||||
TestCase $ testPass "testTransformProtocolInput0"
|
||||
(seqItems [ii0])
|
||||
(transformProtocolInput $ seqItems [ii0])
|
||||
transformProtocolInput (seqItems [ii0])
|
||||
(return ())
|
||||
,TestCase $ testPass "testTransformProtocolInput1"
|
||||
(A.Seq emptyMeta $ A.Several emptyMeta $ map onlySingle [ii0, ii1, ii2])
|
||||
(transformProtocolInput $ seqItems [ii0, ii1, ii2])
|
||||
transformProtocolInput (seqItems [ii0, ii1, ii2])
|
||||
(return ())
|
||||
|
||||
,TestCase $ testPass "testTransformProtocolInput2"
|
||||
(A.Alt emptyMeta False $ onlySingleAlt ii0)
|
||||
(transformProtocolInput $ A.Alt emptyMeta False $ onlySingleAlt ii0)
|
||||
transformProtocolInput (A.Alt emptyMeta False $ onlySingleAlt ii0)
|
||||
(return ())
|
||||
|
||||
,TestCase $ testPass "testTransformProtocolInput3"
|
||||
(A.Alt emptyMeta True $ A.Only emptyMeta $ A.Alternative emptyMeta (A.True
|
||||
emptyMeta) (variable "c") (A.InputSimple emptyMeta [ii0]) $
|
||||
A.Seq emptyMeta $ A.Several emptyMeta $ onlySingle ii1 : [A.Only emptyMeta $ A.Skip emptyMeta])
|
||||
(transformProtocolInput $ A.Alt emptyMeta True $ A.Only emptyMeta $ altItems [ii0, ii1])
|
||||
transformProtocolInput (A.Alt emptyMeta True $ A.Only emptyMeta $ altItems [ii0, ii1])
|
||||
(return ())
|
||||
|
||||
,TestCase $ testPass "testTransformProtocolInput4"
|
||||
(A.Alt emptyMeta False $ A.Only emptyMeta $ A.Alternative emptyMeta (A.True
|
||||
emptyMeta) (variable "c") (A.InputSimple emptyMeta [ii0]) $
|
||||
A.Seq emptyMeta $ A.Several emptyMeta $ map onlySingle [ii1,ii2] ++ [A.Only emptyMeta $ A.Skip emptyMeta])
|
||||
(transformProtocolInput $ A.Alt emptyMeta False $ A.Only emptyMeta $ altItems [ii0, ii1, ii2])
|
||||
transformProtocolInput (A.Alt emptyMeta False $ A.Only emptyMeta $ altItems [ii0, ii1, ii2])
|
||||
(return ())
|
||||
]
|
||||
where
|
||||
|
@ -581,7 +581,7 @@ testPullRepCounts = TestList
|
|||
A.Spec emptyMeta (A.Specification emptyMeta (simpleName "nonce") (A.IsExpr emptyMeta A.ValAbbrev A.Int $ intLiteral 6)) $
|
||||
A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (exprVariable "nonce")) $ A.Several emptyMeta [])
|
||||
|
||||
(pullRepCounts $ A.Seq emptyMeta $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 6)) $ A.Several emptyMeta [])
|
||||
pullRepCounts (A.Seq emptyMeta $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 6)) $ A.Several emptyMeta [])
|
||||
(return ())
|
||||
|
||||
,TestCase $ testPass "testPullRepCounts 6"
|
||||
|
@ -591,7 +591,7 @@ testPullRepCounts = TestList
|
|||
A.Spec emptyMeta (A.Specification emptyMeta (simpleName "nonce2") (A.IsExpr emptyMeta A.ValAbbrev A.Int $ intLiteral 8)) $
|
||||
A.Rep emptyMeta (A.For emptyMeta (simpleName "j") (intLiteral 0) (exprVariable "nonce2")) $ A.Several emptyMeta [])
|
||||
|
||||
(pullRepCounts $ A.Seq emptyMeta $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 6)) $
|
||||
pullRepCounts (A.Seq emptyMeta $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 6)) $
|
||||
A.Rep emptyMeta (A.For emptyMeta (simpleName "j") (intLiteral 0) (intLiteral 8)) $ A.Several emptyMeta [])
|
||||
(return ())
|
||||
]
|
||||
|
@ -600,7 +600,7 @@ testPullRepCounts = TestList
|
|||
testUnchanged n f = TestCase $ testPass
|
||||
("testPullRepCounts/testUnchanged " ++ show n)
|
||||
code
|
||||
(pullRepCounts code)
|
||||
pullRepCounts code
|
||||
(return ())
|
||||
where
|
||||
code = (f $ A.Rep emptyMeta (A.For emptyMeta (simpleName "i") (intLiteral 0) (intLiteral 5)) $ A.Several emptyMeta [])
|
||||
|
|
|
@ -32,14 +32,17 @@ import Types
|
|||
import Utils
|
||||
|
||||
simplifyComms :: [Pass]
|
||||
simplifyComms = makePassesDep
|
||||
[ ("Define temporary variables for outputting expressions", outExprs, Prop.agg_namesDone ++ Prop.agg_typesDone, [Prop.outExpressionRemoved])
|
||||
,("Transform ? CASE statements/guards into plain CASE", transformInputCase, Prop.agg_namesDone ++ Prop.agg_typesDone, [Prop.inputCaseRemoved])
|
||||
,("Flatten sequential protocol inputs into multiple inputs", transformProtocolInput, Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.inputCaseRemoved], [Prop.seqInputsFlattened])
|
||||
simplifyComms =
|
||||
[ outExprs
|
||||
,transformInputCase
|
||||
,transformProtocolInput
|
||||
]
|
||||
|
||||
outExprs :: PassType
|
||||
outExprs = applyDepthM doProcess
|
||||
outExprs :: Pass
|
||||
outExprs = pass "Define temporary variables for outputting expressions"
|
||||
(Prop.agg_namesDone ++ Prop.agg_typesDone)
|
||||
[Prop.outExpressionRemoved]
|
||||
$ applyDepthM doProcess
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.Output m c ois)
|
||||
|
@ -130,8 +133,11 @@ ALT
|
|||
-- process D
|
||||
-}
|
||||
|
||||
transformInputCase :: PassType
|
||||
transformInputCase = applyDepthM doProcess
|
||||
transformInputCase :: Pass
|
||||
transformInputCase = pass "Transform ? CASE statements/guards into plain CASE"
|
||||
(Prop.agg_namesDone ++ Prop.agg_typesDone)
|
||||
[Prop.inputCaseRemoved]
|
||||
$ applyDepthM doProcess
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.Input m v (A.InputCase m' s))
|
||||
|
@ -174,8 +180,11 @@ transformInputCase = applyDepthM doProcess
|
|||
-- Leave other guards untouched.
|
||||
doAlternative m a = return $ A.Only m a
|
||||
|
||||
transformProtocolInput :: PassType
|
||||
transformProtocolInput = applyDepthM2 doProcess doAlternative
|
||||
transformProtocolInput :: Pass
|
||||
transformProtocolInput = pass "Flatten sequential protocol inputs into multiple inputs"
|
||||
(Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.inputCaseRemoved])
|
||||
[Prop.seqInputsFlattened]
|
||||
$ applyDepthM2 doProcess doAlternative
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.Input m v (A.InputSimple m' iis@(_:_:_)))
|
||||
|
|
|
@ -36,21 +36,22 @@ import Types
|
|||
import Utils
|
||||
|
||||
simplifyExprs :: [Pass]
|
||||
simplifyExprs = makePassesDep
|
||||
[ ("Convert FUNCTIONs to PROCs", functionsToProcs, Prop.agg_namesDone ++ [Prop.expressionTypesChecked, Prop.parUsageChecked,
|
||||
Prop.functionTypesChecked], [Prop.functionsRemoved])
|
||||
, ("Convert AFTER to MINUS", removeAfter, [Prop.expressionTypesChecked], [Prop.afterRemoved])
|
||||
, ("Expand array literals", expandArrayLiterals, [Prop.expressionTypesChecked, Prop.processTypesChecked], [Prop.arrayLiteralsExpanded])
|
||||
, ("Pull up replicator counts for SEQs", pullRepCounts, Prop.agg_namesDone ++ Prop.agg_typesDone, [])
|
||||
, ("Pull up definitions", pullUp False, Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.functionsRemoved, Prop.seqInputsFlattened], [Prop.functionCallsRemoved, Prop.subscriptsPulledUp])
|
||||
, ("Transform array constructors into initialisation code", transformConstr, Prop.agg_namesDone ++ Prop.agg_typesDone
|
||||
++ [Prop.subscriptsPulledUp], [Prop.arrayConstructorsRemoved])
|
||||
simplifyExprs =
|
||||
[ functionsToProcs
|
||||
, removeAfter
|
||||
, expandArrayLiterals
|
||||
, pullRepCounts
|
||||
, pullUp False
|
||||
, transformConstr
|
||||
]
|
||||
-- ++ makePassesDep' ((== BackendCPPCSP) . csBackend) [("Pull up definitions (C++)", pullUp True, Prop.agg_namesDone ++ [Prop.expressionTypesChecked, Prop.functionsRemoved, Prop.processTypesChecked,Prop.seqInputsFlattened], [Prop.functionCallsRemoved, Prop.subscriptsPulledUp])]
|
||||
|
||||
-- | Convert FUNCTION declarations to PROCs.
|
||||
functionsToProcs :: PassType
|
||||
functionsToProcs = applyDepthM doSpecification
|
||||
functionsToProcs :: Pass
|
||||
functionsToProcs = pass "Convert FUNCTIONs to PROCs"
|
||||
(Prop.agg_namesDone ++ [Prop.expressionTypesChecked, Prop.parUsageChecked,
|
||||
Prop.functionTypesChecked])
|
||||
[Prop.functionsRemoved]
|
||||
$ applyDepthM doSpecification
|
||||
where
|
||||
doSpecification :: A.Specification -> PassM A.Specification
|
||||
doSpecification (A.Specification m n (A.Function mf sm rts fs evp))
|
||||
|
@ -98,8 +99,11 @@ functionsToProcs = applyDepthM doSpecification
|
|||
|
||||
-- | Convert AFTER expressions to the equivalent using MINUS (which is how the
|
||||
-- occam 3 manual defines AFTER).
|
||||
removeAfter :: PassType
|
||||
removeAfter = applyDepthM doExpression
|
||||
removeAfter :: Pass
|
||||
removeAfter = pass "Convert AFTER to MINUS"
|
||||
[Prop.expressionTypesChecked]
|
||||
[Prop.afterRemoved]
|
||||
$ applyDepthM doExpression
|
||||
where
|
||||
doExpression :: A.Expression -> PassM A.Expression
|
||||
doExpression (A.Dyadic m A.After a b)
|
||||
|
@ -114,8 +118,11 @@ removeAfter = applyDepthM doExpression
|
|||
|
||||
-- | For array literals that include other arrays, burst them into their
|
||||
-- elements.
|
||||
expandArrayLiterals :: PassType
|
||||
expandArrayLiterals = applyDepthM doArrayElem
|
||||
expandArrayLiterals :: Pass
|
||||
expandArrayLiterals = pass "Expand array literals"
|
||||
[Prop.expressionTypesChecked, Prop.processTypesChecked]
|
||||
[Prop.arrayLiteralsExpanded]
|
||||
$ applyDepthM doArrayElem
|
||||
where
|
||||
doArrayElem :: A.ArrayElem -> PassM A.ArrayElem
|
||||
doArrayElem ae@(A.ArrayElemExpr e)
|
||||
|
@ -148,8 +155,11 @@ expandArrayLiterals = applyDepthM doArrayElem
|
|||
-- Therefore, we only need to pull up the counts for sequential replicators
|
||||
--
|
||||
-- TODO for simplification, we could avoid pulling up replication counts that are known to be constants
|
||||
pullRepCounts :: PassType
|
||||
pullRepCounts = applyDepthM doProcess
|
||||
pullRepCounts :: Pass
|
||||
pullRepCounts = pass "Pull up replicator counts for SEQs"
|
||||
(Prop.agg_namesDone ++ Prop.agg_typesDone)
|
||||
[]
|
||||
$ applyDepthM doProcess
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.Seq m s) = pullRepCountSeq s >>* A.Seq m
|
||||
|
@ -174,8 +184,11 @@ pullRepCounts = applyDepthM doProcess
|
|||
= do s' <- pullRepCountSeq s
|
||||
return $ A.Rep m rep s'
|
||||
|
||||
transformConstr :: PassType
|
||||
transformConstr = applyDepthSM doStructured
|
||||
transformConstr :: Pass
|
||||
transformConstr = pass "Transform array constructors into initialisation code"
|
||||
(Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.subscriptsPulledUp])
|
||||
[Prop.arrayConstructorsRemoved]
|
||||
$ applyDepthSM doStructured
|
||||
where
|
||||
-- For arrays, this takes a constructor expression:
|
||||
-- VAL type name IS [i = rep | expr]:
|
||||
|
@ -245,8 +258,11 @@ transformConstr = applyDepthSM doStructured
|
|||
|
||||
-- | Find things that need to be moved up to their enclosing Structured, and do
|
||||
-- so.
|
||||
pullUp :: Bool -> PassType
|
||||
pullUp pullUpArraysInsideRecords = recurse
|
||||
pullUp :: Bool -> Pass
|
||||
pullUp pullUpArraysInsideRecords = pass "Pull up definitions"
|
||||
(Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.functionsRemoved, Prop.seqInputsFlattened])
|
||||
[Prop.functionCallsRemoved, Prop.subscriptsPulledUp]
|
||||
recurse
|
||||
where
|
||||
ops :: Ops
|
||||
ops = baseOp
|
||||
|
|
|
@ -32,15 +32,18 @@ import Traversal
|
|||
import Types
|
||||
|
||||
simplifyProcs :: [Pass]
|
||||
simplifyProcs = makePassesDep
|
||||
[ ("Wrap PAR subprocesses in PROCs", parsToProcs, [Prop.parUsageChecked], [Prop.parsWrapped])
|
||||
, ("Remove parallel assignment", removeParAssign, [Prop.parUsageChecked, Prop.functionsRemoved, Prop.functionCallsRemoved], [Prop.assignParRemoved])
|
||||
, ("Flatten assignment", flattenAssign, Prop.agg_typesDone ++ [Prop.assignParRemoved], [Prop.assignFlattened])
|
||||
simplifyProcs =
|
||||
[ parsToProcs
|
||||
, removeParAssign
|
||||
, flattenAssign
|
||||
]
|
||||
|
||||
-- | Wrap the subprocesses of PARs in no-arg PROCs.
|
||||
parsToProcs :: PassType
|
||||
parsToProcs = applyDepthM doProcess
|
||||
parsToProcs :: Pass
|
||||
parsToProcs = pass "Wrap PAR subprocesses in PROCs"
|
||||
[Prop.parUsageChecked]
|
||||
[Prop.parsWrapped]
|
||||
$ applyDepthM doProcess
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.Par m pm s)
|
||||
|
@ -58,8 +61,11 @@ parsToProcs = applyDepthM doProcess
|
|||
return $ A.Spec m s (A.Only m (A.ProcCall m n []))
|
||||
|
||||
-- | Turn parallel assignment into multiple single assignments through temporaries.
|
||||
removeParAssign :: PassType
|
||||
removeParAssign = applyDepthM doProcess
|
||||
removeParAssign :: Pass
|
||||
removeParAssign = pass "Remove parallel assignment"
|
||||
[Prop.parUsageChecked, Prop.functionsRemoved, Prop.functionCallsRemoved]
|
||||
[Prop.assignParRemoved]
|
||||
$ applyDepthM doProcess
|
||||
where
|
||||
doProcess :: A.Process -> PassM A.Process
|
||||
doProcess (A.Assign m vs@(_:_:_) (A.ExpressionList _ es))
|
||||
|
@ -72,8 +78,11 @@ removeParAssign = applyDepthM doProcess
|
|||
doProcess p = return p
|
||||
|
||||
-- | Turn assignment of arrays and records into multiple assignments.
|
||||
flattenAssign :: PassType
|
||||
flattenAssign = makeRecurse ops
|
||||
flattenAssign :: Pass
|
||||
flattenAssign = pass "Flatten assignment"
|
||||
(Prop.agg_typesDone ++ [Prop.assignParRemoved])
|
||||
[Prop.assignFlattened]
|
||||
$ makeRecurse ops
|
||||
where
|
||||
ops :: Ops
|
||||
ops = extOpD (extOpSD baseOp ops doStructured) ops doProcess
|
||||
|
|
|
@ -37,9 +37,9 @@ import Traversal
|
|||
import Types
|
||||
|
||||
unnest :: [Pass]
|
||||
unnest = makePassesDep
|
||||
[ ("Convert free names to arguments", removeFreeNames, [Prop.mainTagged, Prop.parsWrapped, Prop.functionCallsRemoved], [Prop.freeNamesToArgs])
|
||||
, ("Pull nested definitions to top level", removeNesting, [Prop.freeNamesToArgs], [Prop.nestedPulled])
|
||||
unnest =
|
||||
[ removeFreeNames
|
||||
, removeNesting
|
||||
]
|
||||
|
||||
type NameMap = Map.Map String A.Name
|
||||
|
@ -94,8 +94,11 @@ replaceNames map v = runIdentity $ applyDepthM doName v
|
|||
doName n = return $ Map.findWithDefault n (A.nameName n) smap
|
||||
|
||||
-- | Turn free names in PROCs into arguments.
|
||||
removeFreeNames :: PassType
|
||||
removeFreeNames = applyDepthM2 doSpecification doProcess
|
||||
removeFreeNames :: Pass
|
||||
removeFreeNames = pass "Convert free names to arguments"
|
||||
[Prop.mainTagged, Prop.parsWrapped, Prop.functionCallsRemoved]
|
||||
[Prop.freeNamesToArgs]
|
||||
$ applyDepthM2 doSpecification doProcess
|
||||
where
|
||||
doSpecification :: A.Specification -> PassM A.Specification
|
||||
doSpecification spec = case spec of
|
||||
|
@ -181,8 +184,11 @@ removeFreeNames = applyDepthM2 doSpecification doProcess
|
|||
doProcess p = return p
|
||||
|
||||
-- | Pull nested declarations to the top level.
|
||||
removeNesting :: Data t => Transform t
|
||||
removeNesting = passOnlyOnAST "removeNesting" $ \s ->
|
||||
removeNesting :: Pass
|
||||
removeNesting = pass "Pull nested definitions to top level"
|
||||
[Prop.freeNamesToArgs]
|
||||
[Prop.nestedPulled]
|
||||
$ passOnlyOnAST "removeNesting" $ \s ->
|
||||
do pushPullContext
|
||||
s' <- (makeRecurse ops) s >>= applyPulled
|
||||
popPullContext
|
||||
|
|
Loading…
Reference in New Issue
Block a user