From fa405e7e46eb20cc1ad49694a166273661dfae0c Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Sun, 2 Sep 2007 16:50:12 +0000 Subject: [PATCH] Rain: added a pass to transform functions into the occam form --- RainPassTest.hs | 23 +++++++++++++++++++++++ RainPasses.hs | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/RainPassTest.hs b/RainPassTest.hs index e4dc7eb..c70c952 100644 --- a/RainPassTest.hs +++ b/RainPassTest.hs @@ -472,6 +472,27 @@ testRangeRepPass1 = testPass "testRangeRepPass1" exp (transformRangeRep orig) (r orig = A.ExprConstr m $ A.RangeConstr m (intLiteral 1) (intLiteral 0) exp = A.Literal m (A.Array [A.Dimension 0] A.Int) $ A.ArrayLiteral m [] +--TODO consider/test pulling up the definitions of variables involved in return statements in functions + +-- | Test a fairly standard function: +testTransformFunction0 :: Test +testTransformFunction0 = testPass "testTransformFunction0" exp (transformFunction orig) (return ()) + where + orig = A.Specification m (procName "id") $ + 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"]]) + exp = tag3 A.Specification DontCare (procNamePattern "id") $ + 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])) $ + tag2 A.OnlyEL DontCare $ tag2 A.ExpressionList DontCare [exprVariablePattern "x"] + +-- | Test a function without a return as the final statement: +testTransformFunction1 :: Test +testTransformFunction1 = testPassShouldFail "testTransformFunction1" (transformFunction orig) (return ()) + where + orig = A.Specification m (procName "brokenid") $ + A.Function m A.PlainSpec [A.Byte] [A.Formal A.ValAbbrev A.Byte (simpleName "x")] $ + (A.OnlyP m $ A.Seq m $ A.Several m []) ---Returns the list of tests: tests :: Test @@ -507,6 +528,8 @@ tests = TestList ,testParamPass8 ,testRangeRepPass0 ,testRangeRepPass1 + ,testTransformFunction0 + ,testTransformFunction1 ] diff --git a/RainPasses.hs b/RainPasses.hs index e24075c..a9ad197 100644 --- a/RainPasses.hs +++ b/RainPasses.hs @@ -47,6 +47,8 @@ rainPasses = --depends on uniquifyAndResolveVars and recordInfNameTypes, and should be done after transformEachRange ,("Convert simple Rain range constructors into more general array constructors",transformRangeRep) --must be done after transformEachRange + ,("Transform Rain functions into the occam form",transformFunction) + --must be done after transformEach, depends on uniquifyAndResolveVars and recordInfNameTypes ] -- | A pass that transforms all instances of 'A.Int' into 'A.Int64' @@ -301,3 +303,21 @@ transformRangeRep = everywhereM (mkM transformRangeRep') (A.Literal m A.Int (A.IntLiteral m $ show count)) ) (A.ExprVariable m $ A.Variable m rep) transformRangeRep' s = return s + +transformFunction :: Data t => t -> PassM t +transformFunction = everywhereM (mkM transformFunction') + where + transformFunction' :: A.SpecType -> PassM A.SpecType + transformFunction' (A.Function m specMode types params body) + = case body of + (A.OnlyP _ (A.Seq m' (A.Several m'' statements))) -> + if (null statements) + then dieP m "Functions must not have empty bodies" + else case (last statements) of + ret@(A.OnlyEL {}) -> return $ + (A.Function m specMode types params + (A.ProcThen m' (A.Seq m' (A.Several m'' (init statements))) ret) + ) + _ -> dieP m "Functions must have a return statement as their last statement" + _ -> dieP m "Functions must have seq[uential] bodies" + transformFunction' s = return s