Merged the latest set of changes from the trunk into the Polyplate branch

I also added the import list to all the Data.Generics imports in the tests (as I did for the other modules recently)
This commit is contained in:
Neil Brown 2009-04-10 20:38:29 +00:00
parent 8f767ff0d4
commit c8b724d2be
23 changed files with 169 additions and 71 deletions

View File

@ -233,7 +233,7 @@ tocktest_SOURCES += transformations/PassTest.hs
tocktest_SOURCES += transformations/SimplifyAbbrevsTest.hs
tocktest_SOURCES += transformations/SimplifyTypesTest.hs
pregen_sources = data/AST.hs
pregen_sources = data/AST.hs data/CompState.hs
pregen_sources += pregen/PregenUtils.hs
pregen_sources += polyplate/Data/Generics/Polyplate/GenInstances.hs

View File

@ -71,7 +71,96 @@ removeDirectionsForC
doVariable (A.DirectedVariable _ _ v) = v
doVariable v = v
transformWaitFor :: Pass
-- | Remove variable directions that are superfluous. This prevents confusing
-- later passes, where the user has written something like:
-- []CHAN INT da! IS ...:
-- foo(da!)
--
-- The second direction specifier is unneeded, and will confuse passes such as
-- those adding sizes parameters (which looks for plain variables, since directed
-- arrays should already have been pulled up).
removeUnneededDirections :: PassOn A.Variable
removeUnneededDirections
= occamOnlyPass "Remove unneeded variable directions"
prereq
[]
(applyBottomUpM doVariable)
where
doVariable :: Transform (A.Variable)
doVariable whole@(A.DirectedVariable m dir v)
= do t <- astTypeOf v
case t of
A.Chan {} -> return whole
A.Array _ (A.Chan {}) -> return whole
A.ChanEnd chanDir _ _ | dir == chanDir -> return v
A.Array _ (A.ChanEnd chanDir _ _) | dir == chanDir -> return v
_ -> diePC m $ formatCode "Direction applied to non-channel type: %" t
doVariable v = return v
type AllocMobileOps = ExtOpMSP BaseOp `ExtOpMP` A.Process
-- | Pulls up any initialisers for mobile allocations. I think, after all the
-- other passes have run, the only place these initialisers should be left is in
-- assignments (and maybe not even those?) and A.Is items.
pullAllocMobile :: PassOnOps AllocMobileOps
pullAllocMobile = cOnlyPass "Pull up mobile initialisers" [] [] recurse
where
ops :: AllocMobileOps
ops = baseOp `extOpMS` (ops, doStructured) `extOpM` doProcess
recurse :: RecurseM PassM AllocMobileOps
recurse = makeRecurseM ops
descend :: DescendM PassM AllocMobileOps
descend = makeDescendM ops
doProcess :: Transform A.Process
doProcess (A.Assign m [v] (A.ExpressionList me [A.AllocMobile ma t (Just e)]))
= return $ A.Seq m $ A.Several m $ map (A.Only m) $
[A.Assign m [v] $ A.ExpressionList me [A.AllocMobile ma t Nothing]
,A.Assign m [A.DerefVariable m v] $ A.ExpressionList me [e]
]
doProcess p = descend p
doStructured :: TransformStructured' AllocMobileOps
doStructured (A.Spec mspec (A.Specification mif n
(A.Is mis am t (A.ActualExpression (A.AllocMobile ma tm (Just e)))))
body)
= do body' <- recurse body
return $ A.Spec mspec (A.Specification mif n $
A.Is mis am t $ A.ActualExpression $ A.AllocMobile ma tm Nothing)
$ A.ProcThen ma
(A.Assign ma [A.DerefVariable mif $ A.Variable mif n] $ A.ExpressionList ma [e])
body'
doStructured s = descend s
-- | Turns any literals equivalent to a MOSTNEG back into a MOSTNEG
-- The reason for doing this is that C (and presumably C++) don't technically (according
-- to the standard) allow you to write INT_MIN directly as a constant. GCC certainly
-- warns about it. So this pass takes any MOSTNEG-equivalent values (that will have been
-- converted to constants in the constant folding earlier) and turns them back
-- into MOSTNEG, for which the C backend uses INT_MIN and similar, which avoid
-- this problem.
fixMinInt :: PassOn A.Expression
fixMinInt
= cOrCppOnlyPass "Turn any literals that are equal to MOSTNEG INT back into MOSTNEG INT"
prereq
[]
(applyBottomUpM doExpression)
where
doExpression :: Transform (A.Expression)
doExpression l@(A.Literal m t (A.IntLiteral m' s))
= do folded <- constantFold (A.MostNeg m t)
case folded of
(A.Literal _ _ (A.IntLiteral _ s'), _, _)
-> if (s == s')
then return $ A.MostNeg m t
else return l
_ -> return l -- This can happen as some literals retain the Infer
-- type which fails the constant folding
doExpression e = return e
transformWaitFor :: PassOn A.Process
transformWaitFor = cOnlyPass "Transform wait for guards into wait until guards"
[]
[Prop.waitForRemoved]

View File

@ -22,7 +22,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module BackendPassesTest (qcTests) where
import Control.Monad.State
import Data.Generics
import Data.Generics (Data)
import qualified Data.Map as Map
import Test.HUnit hiding (State)
import Test.QuickCheck

View File

@ -35,7 +35,7 @@ import Control.Monad.Error
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Writer hiding (tell)
import Data.Generics
import Data.Generics (Data)
import Data.List (isInfixOf, intersperse)
import Data.Maybe (fromMaybe)
import Test.HUnit hiding (State)

View File

@ -420,40 +420,14 @@ applyAccum _ ops = ops'
ops' :: ((t, Route t A.AST) -> StateT (AccumMap t) (RestartT CheckOptM) t, ops)
ops' = (accum, ops)
extF ::
(forall a. Data a => TransFuncS acc z a) ->
(forall c. Data c => TransFuncS acc z c)
extF = (`extMRAccS` (\(x,_) -> modify (accOneF x) >> return x))
accum xr = do x' <- transformMRoute () ops' xr
modify $ Map.insert (routeId $ snd xr) x'
return x'
applyAccum' :: (forall a. Data a => TransFuncAcc acc a) ->
(forall b. Data b => (b, Route b A.AST) -> StateT acc (RestartT CheckOptM) b)
applyAccum' f (x, route)
= do when (findMeta x /= emptyMeta) $ lift . lift . CheckOptM $ modify $ \d -> d {lastValidMeta = findMeta x}
(x', acc) <- lift $ flip runStateT accEmpty (gmapMForRoute typeSet (extF wrap) x)
r <- f' (x', route, acc)
modify (`accJoinF` acc)
return r
where
wrap (y, route') = applyAccum' f (y, route @-> route')
-- Keep applying the function while there is a Left return (which indicates
-- the value was replaced) until there is a Right return
f' (x, route, acc) = do
x' <- f (x, route, acc)
case x' of
Left y -> f' (y, route, foldl (flip accOneF) accEmpty (listify {-TODO-} (const True) y))
Right y -> return y
applyTopDown :: TypeSet -> (forall a. Data a => TransFunc a) ->
(forall b. Data b => (b, Route b A.AST) -> RestartT CheckOptM b)
applyTopDown typeSet f (x, route)
= do when (findMeta x /= emptyMeta) $ lift . CheckOptM $ modify $ \d -> d {lastValidMeta = findMeta x}
z <- f' (x, route)
gmapMForRoute typeSet (\(y, route') -> applyTopDown typeSet f (y, route @-> route')) z
where
-- Keep applying the function while there is a Left return (which indicates
-- the value was replaced) until there is a Right return
f' (x, route) = do
-- Keep applying the function while there is a Left return (which indicates
-- the value was replaced) until there is a Right return
keepApplying :: Monad m => ((t, Route t outer) -> m (Either t t)) -> ((t, Route t outer) -> m t)
keepApplying f (x, route) = do
x' <- f (x, route)
case x' of
Left y -> keepApplying f (y, route)

View File

@ -21,7 +21,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
-- | A module with tests for various miscellaneous things in the common directory.
module CommonTest (tests) where
import Data.Generics
import Data.Generics (Constr, Data, Typeable)
import Test.HUnit hiding (State)
import qualified AST as A

View File

@ -30,7 +30,7 @@ module OccamEDSL (ExpInp, ExpInpT,
becomes) where
import Control.Monad.State hiding (guard)
import Data.Generics
import Data.Generics (Data)
import qualified Data.Map as Map
import qualified Data.Set as Set
import Test.HUnit hiding (State)

View File

@ -21,7 +21,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module TestFramework where
import Control.Monad.Error
import Data.Generics
import Data.Generics (Data)
import System.IO.Unsafe
import Test.HUnit hiding (Testable)
import Test.QuickCheck hiding (check)

View File

@ -40,7 +40,7 @@ module TestUtils where
import Control.Monad.State
import Control.Monad.Writer
import Data.Generics
import Data.Generics (Data, Typeable)
import qualified Data.Map as Map
import System.Random
import Test.HUnit hiding (State,Testable)

View File

@ -23,7 +23,7 @@ import Control.Monad.Error
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Writer
import Data.Generics (Data, Typeable)
import Data.Generics (Data, Typeable, listify)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe
@ -496,6 +496,8 @@ instance FindMeta A.Name where
findMeta = A.nameMeta
-- Should stop being lazy, and put these as pattern matches:
--
-- TODO also, at least use Polyplate!
findMeta_Data :: Data a => a -> Meta
findMeta_Data = head . listify (const True)

View File

@ -21,7 +21,7 @@ module Metadata where
{-! global : Haskell2Xml !-}
import Data.Generics (Data, Typeable, listify)
import Data.Generics (Data, Typeable)
import Data.List
import Numeric
import Text.Printf

View File

@ -51,7 +51,8 @@ import Data.Graph.Inductive hiding (run)
import Data.Maybe
import qualified AST as A
import GenericUtils
import CompState
import Data.Generics.Polyplate.Route
import Metadata
import FlowUtils
import Utils

View File

@ -24,7 +24,7 @@ module FlowGraphTest (qcTests) where
import Control.Monad.Identity
import Control.Monad.State
import Data.Generics
import Data.Generics (Data)
import Data.Graph.Inductive
import Data.List
import qualified Data.Map as Map
@ -34,11 +34,14 @@ import Test.HUnit hiding (Node, State, Testable)
import Test.QuickCheck
import qualified AST as A
import CompState
import Data.Generics.Polyplate.Route
import FlowGraph
import Metadata
import PrettyShow
import TestFramework
import TestUtils
import Traversal
import Utils
-- | Makes a distinctive metatag for testing. The function is one-to-one.
@ -789,7 +792,7 @@ pickFuncRep gr = Map.fromList $ filter ((/= emptyMeta) . fst) $ map (helpApplyFu
applyFunc (m,AlterSpec f) = routeModify f (g m)
applyFunc (m,AlterNothing _) = return
g m = gmapM (mkM $ replaceM m (replaceMeta m))
g m = applyBottomUpM $ replaceM m (replaceMeta m)
-- | It is important to have these functions in the right ratio. The number of possible trees is

View File

@ -23,7 +23,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module OccamPassesTest (tests) where
import Control.Monad.State
import Data.Generics
import Data.Generics (Data)
import Test.HUnit hiding (State)
import qualified AST as A
@ -32,6 +32,8 @@ import Metadata
import qualified OccamPasses
import Pass
import TestUtils
import Traversal
import Types
m :: Meta
m = emptyMeta
@ -138,15 +140,15 @@ testCheckConstants = TestList
, testFail 33 (A.Option m [lit10, lit10, lit10, var] skip)
]
where
testOK :: (PolyplateM a (TwoOpM PassM A.Dimension A.Option) () PassM
,PolyplateM a () (TwoOpM PassM A.Dimension A.Option) PassM
testOK :: (PolyplateM a (TwoOpM PassM A.Type A.Option) () PassM
,PolyplateM a () (TwoOpM PassM A.Type A.Option) PassM
,Show a, Data a) => Int -> a -> Test
testOK n orig
= TestCase $ testPass ("testCheckConstants" ++ show n)
orig OccamPasses.checkConstants orig
(return ())
testFail :: (PolyplateM a (TwoOpM PassM A.Dimension A.Option) () PassM
,PolyplateM a () (TwoOpM PassM A.Dimension A.Option) PassM
testFail :: (PolyplateM a (TwoOpM PassM A.Type A.Option) () PassM
,PolyplateM a () (TwoOpM PassM A.Type A.Option) PassM
,Show a, Data a) => Int -> a -> Test
testFail n orig
= TestCase $ testPassShouldFail ("testCheckConstants" ++ show n)

View File

@ -648,6 +648,7 @@ type InferTypeOps
`ExtOpMP` A.Alternative
`ExtOpMP` A.Process
`ExtOpMP` A.Variable
`ExtOpMP` A.Variant
-- | Infer types.
inferTypes :: Pass A.AST
@ -658,16 +659,18 @@ inferTypes = occamOnlyPass "Infer types"
where
ops :: InferTypeOps
ops = baseOp
`extOp` doExpression
`extOp` doDimension
`extOp` doSubscript
`extOp` doArrayConstr
`extOp` doReplicator
`extOp` doAlternative
`extOp` doInputMode
`extOp` doSpecification
`extOp` doProcess
`extOp` doVariable
`extOpMS` (ops, doStructured)
`extOpM` doExpression
`extOpM` doDimension
`extOpM` doSubscript
`extOpM` doReplicator
`extOpM` doAlternative
`extOpM` doProcess
`extOpM` doVariable
`extOpM` doVariant
recurse :: RecurseM PassM InferTypeOps
recurse = makeRecurseM ops
descend :: DescendM PassM InferTypeOps
descend = makeDescendM ops
@ -834,7 +837,26 @@ inferTypes = occamOnlyPass "Infer types"
inTypeContext (Just ct) (recurse sv) >>* A.InputCase m
doInputMode _ im = inTypeContext (Just A.Int) $ descend im
doStructured :: Data a => Transform (A.Structured a)
doVariant :: Transform A.Variant
doVariant (A.Variant m n iis p)
= do ctx <- getTypeContext
ets <- case ctx of
Just x -> protocolItems m x
Nothing -> dieP m "Could not deduce protocol"
case ets of
Left {} -> dieP m "Simple protocol expected during input CASE"
Right ps -> case lookup n ps of
Nothing -> diePC m $ formatCode "Name % is not part of protocol %"
n (fromJust ctx)
Just ts -> do iis' <- sequence [inTypeContext (Just t) $ recurse ii
| (t, ii) <- zip ts iis]
p' <- recurse p
return $ A.Variant m n iis' p'
doStructured :: ( PolyplateM (A.Structured t) InferTypeOps () PassM
, PolyplateM (A.Structured t) () InferTypeOps PassM
, Data t) => Transform (A.Structured t)
doStructured (A.Spec mspec s@(A.Specification m n st) body)
= do (st', wrap) <- runReaderT (doSpecType n st) body
-- Update the definition of each name after we handle it.
@ -842,7 +864,11 @@ inferTypes = occamOnlyPass "Infer types"
wrap (recurse body) >>* A.Spec mspec (A.Specification m n st')
doStructured s = descend s
doSpecType :: Data a => A.Name -> A.SpecType -> ReaderT (A.Structured a) PassM A.SpecType
-- The second parameter is a modifier (wrapper) for the descent into the body
doSpecType :: ( PolyplateM (A.Structured t) InferTypeOps () PassM
, PolyplateM (A.Structured t) () InferTypeOps PassM
, Data t) => A.Name -> A.SpecType -> ReaderT (A.Structured t) PassM
(A.SpecType, PassM (A.Structured a) -> PassM (A.Structured a))
doSpecType n st
= case st of
A.Place _ _ -> lift $ inTypeContext (Just A.Int) $ descend st >>* addId
@ -1025,6 +1051,7 @@ inferTypes = occamOnlyPass "Infer types"
`extOpM` descend
`extOpM` descend
`extOpM` (doVariable r)
`extOpM` descend
descend :: DescendM PassM InferTypeOps
descend = makeDescendM ops

View File

@ -22,7 +22,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module OccamTypesTest (vioTests) where
import Control.Monad.State
import Data.Generics
import Data.Generics (Data)
import Test.HUnit hiding (State)
import qualified AST as A

View File

@ -35,7 +35,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
-- and then turn these into Patterns where any Meta tag that is "m" is ignored during the comparison.
module ParseRainTest (tests) where
import Data.Generics
import Data.Generics (Data)
import Prelude hiding (fail)
import Test.HUnit
import Text.ParserCombinators.Parsec (runParser,eof)

View File

@ -31,7 +31,7 @@ module RainPassesTest (tests) where
import Control.Monad.State
import Control.Monad.Identity
import Data.Generics
import Data.Generics (Data, Typeable)
import qualified Data.Map as Map
import Test.HUnit hiding (State)

View File

@ -19,7 +19,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module RainTypes (constantFoldPass, performTypeUnification) where
import Control.Monad.State
import Data.Generics (Data, showConstr, toConstr)
import Data.Generics (Data, showConstr, toConstr, Typeable)
import Data.List
import qualified Data.Map as Map
import Data.Maybe

View File

@ -22,7 +22,7 @@ module RainTypesTest (vioTests) where
import Control.Monad.State
import Control.Monad.Error
import Control.Monad.Writer
import Data.Generics
import Data.Generics (Data)
import qualified Data.Map as Map
import Test.HUnit hiding (State)

View File

@ -20,7 +20,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module PassTest (tests) where
import Control.Monad.State hiding (guard)
import Data.Generics
import Data.Generics (cast, Data, Typeable)
import qualified Data.Map as Map
import Test.HUnit hiding (State)

View File

@ -20,7 +20,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module SimplifyAbbrevsTest (tests) where
import Control.Monad.State
import Data.Generics
import Data.Generics (Data)
import Test.HUnit hiding (State)
import CompState

View File

@ -20,7 +20,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module SimplifyTypesTest (tests) where
import Control.Monad.State
import Data.Generics
import Data.Generics (Data)
import Test.HUnit hiding (State)
import CompState