Rain: added a pass that transforms ForEach replicators over simple ranges directly into For replicators
This commit is contained in:
parent
e655c1412a
commit
0392036322
|
@ -139,6 +139,47 @@ testEachPass1 = testPassWithItemsStateCheck "testEachPass0" exp (transformEach o
|
||||||
(simpleDefPattern (A.nameName indexVarName) A.Original (tag2 A.Declaration DontCare A.Int64))
|
(simpleDefPattern (A.nameName indexVarName) A.Original (tag2 A.Declaration DontCare A.Int64))
|
||||||
Nothing -> assertFailure "testEachPass1: Internal error, indexVar not found"
|
Nothing -> assertFailure "testEachPass1: Internal error, indexVar not found"
|
||||||
|
|
||||||
|
testEachRangePass0 :: Test
|
||||||
|
testEachRangePass0 = 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.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
exp = A.Par m A.PlainPar $ A.Rep m
|
||||||
|
(A.For m (simpleName "x") (intLiteral 0) (intLiteral 10))
|
||||||
|
(A.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
|
||||||
|
testEachRangePass1 :: Test
|
||||||
|
testEachRangePass1 = 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.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
exp = A.Par m A.PlainPar $ A.Rep m
|
||||||
|
(A.For m (simpleName "x") (intLiteral (-5)) (intLiteral 4))
|
||||||
|
(A.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
|
||||||
|
testEachRangePass2 :: Test
|
||||||
|
testEachRangePass2 = 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.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
exp = A.Seq m $ A.Rep m
|
||||||
|
(A.For m (simpleName "x") (intLiteral 6) (intLiteral 1))
|
||||||
|
(A.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
|
||||||
|
testEachRangePass3 :: Test
|
||||||
|
testEachRangePass3 = 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.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
exp = A.Seq m $ A.Rep m
|
||||||
|
(A.For m (simpleName "x") (intLiteral 6) (intLiteral (-5)))
|
||||||
|
(A.OnlyP m (makeSimpleAssign "c" "x"))
|
||||||
|
|
||||||
|
|
||||||
-- | Test variable is made unique in a declaration:
|
-- | Test variable is made unique in a declaration:
|
||||||
testUnique0 :: Test
|
testUnique0 :: Test
|
||||||
testUnique0 = testPassWithItemsStateCheck "testUnique0" exp (uniquifyAndResolveVars orig) (return ()) check
|
testUnique0 = testPassWithItemsStateCheck "testUnique0" exp (uniquifyAndResolveVars orig) (return ()) check
|
||||||
|
@ -405,6 +446,10 @@ tests = TestList
|
||||||
[
|
[
|
||||||
testEachPass0
|
testEachPass0
|
||||||
,testEachPass1
|
,testEachPass1
|
||||||
|
,testEachRangePass0
|
||||||
|
,testEachRangePass1
|
||||||
|
,testEachRangePass2
|
||||||
|
,testEachRangePass3
|
||||||
,testUnique0
|
,testUnique0
|
||||||
,testUnique1
|
,testUnique1
|
||||||
,testUnique2
|
,testUnique2
|
||||||
|
|
|
@ -24,11 +24,14 @@ import qualified AST as A
|
||||||
import Pass
|
import Pass
|
||||||
import Data.Generics
|
import Data.Generics
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
import Data.Maybe
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Types
|
import Types
|
||||||
import CompState
|
import CompState
|
||||||
import Errors
|
import Errors
|
||||||
import Metadata
|
import Metadata
|
||||||
|
import Pattern
|
||||||
|
import TreeUtil
|
||||||
|
|
||||||
-- | An ordered list of the Rain-specific passes to be run.
|
-- | An ordered list of the Rain-specific passes to be run.
|
||||||
rainPasses :: [(String,Pass)]
|
rainPasses :: [(String,Pass)]
|
||||||
|
@ -38,7 +41,10 @@ rainPasses =
|
||||||
,("Record inferred name types in dictionary",recordInfNameTypes) --depends on uniquifyAndResolveVars
|
,("Record inferred name types in dictionary",recordInfNameTypes) --depends on uniquifyAndResolveVars
|
||||||
,("Find and tag the main function",findMain) --depends on uniquifyAndResolveVars
|
,("Find and tag the main function",findMain) --depends on uniquifyAndResolveVars
|
||||||
,("Check parameters in process calls",matchParamPass) --depends on uniquifyAndResolveVars and recordInfNameTypes
|
,("Check parameters in process calls",matchParamPass) --depends on uniquifyAndResolveVars and recordInfNameTypes
|
||||||
,("Convert seqeach/pareach loops into classic replicated SEQ/PAR",transformEach) --depends on uniquifyAndResolveVars and recordInfNameTypes
|
,("Convert seqeach/pareach loops over ranges into simple replicated SEQ/PAR",transformEachRange)
|
||||||
|
--depends on uniquifyAndResolveVars and recordInfNameTypes
|
||||||
|
,("Convert seqeach/pareach loops into classic replicated SEQ/PAR",transformEach)
|
||||||
|
--depends on uniquifyAndResolveVars and recordInfNameTypes, and should be done after transformEachRange
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | A pass that transforms all instances of 'A.Int' into 'A.Int64'
|
-- | A pass that transforms all instances of 'A.Int' into 'A.Int64'
|
||||||
|
@ -184,6 +190,45 @@ matchParamPass = everywhereM (mkM matchParamPass')
|
||||||
else dieP (findMeta item) $ "Could not perform implicit cast from supplied type: " ++ (show from) ++
|
else dieP (findMeta item) $ "Could not perform implicit cast from supplied type: " ++ (show from) ++
|
||||||
" to expected type: " ++ (show to) ++ " for parameter (zero-based): " ++ (show index)
|
" to expected type: " ++ (show to) ++ " for parameter (zero-based): " ++ (show index)
|
||||||
|
|
||||||
|
checkIntegral :: A.LiteralRepr -> Maybe Integer
|
||||||
|
checkIntegral (A.IntLiteral _ s) = Just $ read s
|
||||||
|
checkIntegral (A.HexLiteral _ s) = Nothing -- TODO support hex literals
|
||||||
|
checkIntegral (A.ByteLiteral _ s) = Nothing -- TODO support char literals
|
||||||
|
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 (mkM transformEachRange')
|
||||||
|
where
|
||||||
|
transformEachRange' :: A.Structured -> PassM A.Structured
|
||||||
|
transformEachRange' s@(A.Rep {})
|
||||||
|
= 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
|
||||||
|
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
|
||||||
|
else dieP eachMeta "Items in range constructor (x..y) are not integer literals"
|
||||||
|
where
|
||||||
|
patt = tag3 A.Rep (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 -> die "Internal error in transformEachRange"
|
||||||
|
transformEachRange' s = return s
|
||||||
|
|
||||||
-- | 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 (mkM transformEach')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user