Rain: added a pass to turn range constructors into the more general array constructor form

This commit is contained in:
Neil Brown 2007-09-01 14:40:50 +00:00
parent 0392036322
commit 4fadab442d
2 changed files with 43 additions and 0 deletions

View File

@ -440,6 +440,22 @@ testParamPass8 = testPassShouldFail "testParamPass6" (matchParamPass orig) (star
--TODO test passing in channel ends
-- | Transform an example list
testRangeRepPass0 :: Test
testRangeRepPass0 = 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 (Named "repIndex" DontCare) (intLiteral 0) (intLiteral 2))
(tag2 A.ExprVariable DontCare $ tag2 A.Variable DontCare $ Named "repIndex" DontCare)
-- | Lists with negative counts should be turned into an empty literal list
testRangeRepPass1 :: Test
testRangeRepPass1 = testPass "testRangeRepPass1" exp (transformRangeRep orig) (return())
where
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 []
---Returns the list of tests:
tests :: Test
tests = TestList
@ -472,6 +488,8 @@ tests = TestList
,testParamPass6
,testParamPass7
,testParamPass8
,testRangeRepPass0
,testRangeRepPass1
]

View File

@ -45,6 +45,8 @@ rainPasses =
--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
,("Convert simple Rain range constructors into more general array constructors",transformRangeRep)
--must be done after transformEachRange
]
-- | A pass that transforms all instances of 'A.Int' into 'A.Int64'
@ -255,3 +257,26 @@ transformEach = everywhereM (mkM transformEach')
s
return (spec (A.Rep m newRep s'))
transformEach' s = return s
-- | 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')
where
transformRangeRep' :: A.Expression -> PassM A.Expression
transformRangeRep' (A.ExprConstr _ (A.RangeConstr m (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"
where
transformRangeRep'' :: Meta -> Integer -> Integer -> PassM A.Expression
transformRangeRep'' m begin end
= if (end < begin)
then return $ A.Literal m (A.Array [A.Dimension 0] A.Int) $ A.ArrayLiteral m []
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
(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