diff --git a/frontends/RainPasses.hs b/frontends/RainPasses.hs index 48fe343..9d094fd 100644 --- a/frontends/RainPasses.hs +++ b/frontends/RainPasses.hs @@ -29,7 +29,6 @@ import CompState import Errors import Metadata import Pass -import Pattern import qualified Properties as Prop import RainTypes import TreeUtils @@ -58,7 +57,8 @@ rainPasses = makePassesDep' ((== FrontendRain) . csFrontend) ,("Check parameters in process calls", matchParamPass, typesDone, [Prop.processTypesChecked]) ,("Find and tag the main function", findMain, namesDone, [Prop.mainTagged]) - ,("Convert seqeach/pareach loops over ranges into simple replicated SEQ/PAR",transformEachRange, typesDone, [Prop.eachRangeTransformed]) + ,("Convert seqeach/pareach loops over ranges into simple replicated SEQ/PAR", + transformEachRange, typesDone ++ [Prop.constantsFolded], [Prop.eachRangeTransformed]) ,("Convert seqeach/pareach loops into classic replicated SEQ/PAR",transformEach, typesDone ++ [Prop.eachRangeTransformed], [Prop.eachTransformed]) ,("Convert simple Rain range constructors into more general array constructors",transformRangeRep, typesDone ++ [Prop.eachRangeTransformed], [Prop.rangeTransformed]) ,("Transform Rain functions into the occam form",checkFunction, typesDone ++ [Prop.eachTransformed], []) @@ -170,37 +170,22 @@ checkIntegral _ = Nothing -- | Transforms seqeach\/pareach loops over things like [0..99] into SEQ i = 0 FOR 100 loops transformEachRange :: Data t => t -> PassM t -transformEachRange = everywhereM (mk1M transformEachRange') +transformEachRange = doGeneric `ext1M` doStructured where - transformEachRange' :: forall a. Data a => A.Structured a -> PassM (A.Structured a) - transformEachRange' s@(A.Rep m _ _) - = case getMatchedItems patt s of - Left _ -> return s --Doesn't match, return the original - Right items -> - do repMeta <- castOrDie "repMeta" items - eachMeta <- castOrDie "eachMeta" items - loopVar <- castOrDie "loopVar" items - begin <- castOrDie "begin" items - end <- castOrDie "end" items - body <- castOrDie "body" items + doGeneric :: Data t => t -> PassM t + doGeneric = makeGeneric transformEachRange + + doStructured :: Data a => A.Structured a -> PassM (A.Structured a) + doStructured (A.Rep repMeta (A.ForEach eachMeta loopVar (A.ExprConstr + _ (A.RangeConstr _ _ (A.Literal _ _ begin) (A.Literal _ _ end)))) body) + = do body' <- doStructured body + -- TODO should probably not do mini-constant-folding here: if (isJust $ checkIntegral begin) && (isJust $ checkIntegral end) then return $ A.Rep repMeta (A.For eachMeta loopVar (A.Literal eachMeta A.Int begin) (A.Literal eachMeta A.Int $ A.IntLiteral eachMeta $ show ((fromJust $ checkIntegral end) - (fromJust $ checkIntegral begin) + 1)) - ) body + ) body' else dieP eachMeta "Items in range constructor (x..y) are not integer literals" - where - 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) $ - tag2 A.ExprConstr DontCare $ - tag3 A.RangeConstr DontCare (tag3 A.Literal DontCare DontCare $ Named "begin" DontCare) - (tag3 A.Literal DontCare DontCare $ Named "end" DontCare) - ) (Named "body" DontCare) - castOrDie :: (Typeable b) => String -> Items -> PassM b - castOrDie key items = case castADI (Map.lookup key items) of - Just y -> return y - Nothing -> dieP m "Internal error in transformEachRange" - transformEachRange' s = return s + doStructured s = doGeneric s -- | A pass that changes all the 'A.ForEach' replicators in the AST into 'A.For' replicators. transformEach :: Data t => t -> PassM t @@ -231,10 +216,13 @@ transformEach = everywhereM (mk1M transformEach') -- | A pass that changes all the Rain range constructor expressions into the more general array constructor expressions transformRangeRep :: Data t => t -> PassM t -transformRangeRep = everywhereM (mkM transformRangeRep') +transformRangeRep = doGeneric `extM` doExpression where - transformRangeRep' :: A.Expression -> PassM A.Expression - transformRangeRep' (A.ExprConstr _ (A.RangeConstr m (A.Literal _ _ beginLit) (A.Literal _ _ endLit))) + doGeneric :: Data t => t -> PassM t + doGeneric = makeGeneric transformRangeRep + + doExpression :: A.Expression -> PassM A.Expression + doExpression (A.ExprConstr _ (A.RangeConstr m t (A.Literal _ _ beginLit) (A.Literal _ _ endLit))) = if (isJust $ checkIntegral beginLit) && (isJust $ checkIntegral endLit) then transformRangeRep'' m (fromJust $ checkIntegral beginLit) (fromJust $ checkIntegral endLit) else dieP m "Items in range constructor (x..y) are not integer literals" @@ -245,12 +233,12 @@ transformRangeRep = everywhereM (mkM transformRangeRep') then dieP m $ "End of range is before beginning: " ++ show begin ++ " > " ++ show end else do A.Specification _ rep _ <- makeNonceVariable "rep_constr" m A.Int A.VariableName A.ValAbbrev let count = end - begin + 1 - return $ A.ExprConstr m $ A.RepConstr m + return $ A.ExprConstr m $ A.RepConstr m t (A.For m rep (A.Literal m A.Int (A.IntLiteral m $ show begin)) (A.Literal m A.Int (A.IntLiteral m $ show count)) ) (A.ExprVariable m $ A.Variable m rep) - transformRangeRep' s = return s + doExpression e = doGeneric e checkFunction :: Data t => t -> PassM t checkFunction = everywhereM (mkM checkFunction') diff --git a/frontends/RainPassesTest.hs b/frontends/RainPassesTest.hs index accf937..aee0250 100644 --- a/frontends/RainPassesTest.hs +++ b/frontends/RainPassesTest.hs @@ -148,7 +148,8 @@ testEachRangePass0 :: Test 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 (intLiteral 0) (intLiteral 9)))) + (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m + undefined (intLiteral 0) (intLiteral 9)))) (A.Only m (makeSimpleAssign "c" "x")) exp = A.Par m A.PlainPar $ A.Rep m (A.For m (simpleName "x") (intLiteral 0) (intLiteral 10)) @@ -158,7 +159,8 @@ testEachRangePass1 :: Test 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 (intLiteral (-5)) (intLiteral (-2))))) + (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m undefined + (intLiteral (-5)) (intLiteral (-2))))) (A.Only m (makeSimpleAssign "c" "x")) exp = A.Par m A.PlainPar $ A.Rep m (A.For m (simpleName "x") (intLiteral (-5)) (intLiteral 4)) @@ -168,7 +170,8 @@ testEachRangePass2 :: Test 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 (intLiteral 6) (intLiteral 6)))) + (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m undefined + (intLiteral 6) (intLiteral 6)))) (A.Only m (makeSimpleAssign "c" "x")) exp = A.Seq m $ A.Rep m (A.For m (simpleName "x") (intLiteral 6) (intLiteral 1)) @@ -178,7 +181,8 @@ testEachRangePass3 :: Test 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 (intLiteral 6) (intLiteral 0)))) + (A.ForEach m (simpleName "x") (A.ExprConstr m (A.RangeConstr m undefined + (intLiteral 6) (intLiteral 0)))) (A.Only m (makeSimpleAssign "c" "x")) exp = A.Seq m $ A.Rep m (A.For m (simpleName "x") (intLiteral 6) (intLiteral (-5))) @@ -466,15 +470,15 @@ testParamPass8 = TestList [TestCase $ testPassShouldFail "testParamPass8/process testRangeRepPass0 :: Test testRangeRepPass0 = TestCase $ testPass "testRangeRepPass0" exp (transformRangeRep orig) (return()) where - orig = A.ExprConstr m $ A.RangeConstr m (intLiteral 0) (intLiteral 1) - exp = tag2 A.ExprConstr DontCare $ tag3 A.RepConstr DontCare (tag4 A.For DontCare ("repIndex"@@DontCare) (intLiteral 0) (intLiteral 2)) + orig = A.ExprConstr m $ A.RangeConstr m A.Byte (intLiteral 0) (intLiteral 1) + exp = tag2 A.ExprConstr DontCare $ mRepConstr A.Byte (tag4 A.For DontCare ("repIndex"@@DontCare) (intLiteral 0) (intLiteral 2)) (tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare $ "repIndex"@@DontCare) -- | Lists with negative counts should give an error testRangeRepPass1 :: Test testRangeRepPass1 = TestCase $ testPassShouldFail "testRangeRepPass1" (transformRangeRep orig) (return()) where - orig = A.ExprConstr m $ A.RangeConstr m (intLiteral 1) (intLiteral 0) + orig = A.ExprConstr m $ A.RangeConstr m A.Byte (intLiteral 1) (intLiteral 0) --TODO consider/test pulling up the definitions of variables involved in return statements in functions diff --git a/transformations/PassTest.hs b/transformations/PassTest.hs index 8c7b612..6fae799 100644 --- a/transformations/PassTest.hs +++ b/transformations/PassTest.hs @@ -208,7 +208,7 @@ testTransformConstr0 = TestCase $ testPass "transformConstr0" exp (transformCons startState = defineConst "x" A.Int (intLiteral 42) orig = A.Spec m (A.Specification m (simpleName "arr") $ A.IsExpr m A.ValAbbrev (A.Array [dimension 10] A.Int) $ A.ExprConstr m $ - A.RepConstr m (A.For m (simpleName "x") (intLiteral 0) (intLiteral 10)) (exprVariable "x") + A.RepConstr m undefined (A.For m (simpleName "x") (intLiteral 0) (intLiteral 10)) (exprVariable "x") ) skipP exp = nameAndStopCaringPattern "indexVar" "i" $ mkPattern exp' exp' = A.Spec m (A.Specification m (simpleName "arr") (A.Declaration m (A.Array [dimension 10] A.Int))) $