Converted addDirections to the Polyplate traversals, and fixed inferTypes to work in Polyplate (more merging from trunk)

This commit is contained in:
Neil Brown 2009-02-11 12:17:28 +00:00
parent a72b01ff02
commit 9294febd6f

View File

@ -24,6 +24,7 @@ import Control.Monad.Reader
import Control.Monad.State import Control.Monad.State
import Data.Function (on) import Data.Function (on)
import Data.Generics import Data.Generics
import Data.IORef
import Data.List import Data.List
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Maybe import Data.Maybe
@ -569,10 +570,10 @@ inSubscriptedContext m body
--}}} --}}}
addDirections :: Pass addDirections :: PassOn2 A.Process A.Alternative
addDirections = occamOnlyPass "Add direction specifiers to inputs and outputs" addDirections = occamOnlyPass "Add direction specifiers to inputs and outputs"
[] [] [] []
(applyDepthM2 doProcess doAlternative) (applyBottomUpM2 doProcess doAlternative)
where where
doProcess :: Transform A.Process doProcess :: Transform A.Process
doProcess (A.Output m v os) doProcess (A.Output m v os)
@ -639,14 +640,13 @@ inferAllocMobile _ _ e = return e
-- I can't put this in the where clause of inferTypes, so it has to be out -- I can't put this in the where clause of inferTypes, so it has to be out
-- here. It should be the type of ops inside the inferTypes function below. -- here. It should be the type of ops inside the inferTypes function below.
type InferTypeOps type InferTypeOps
= BaseOp = ExtOpMSP BaseOp
`ExtOpMP` A.Expression `ExtOpMP` A.Expression
`ExtOpMP` A.Dimension `ExtOpMP` A.Dimension
`ExtOpMP` A.Subscript `ExtOpMP` A.Subscript
`ExtOpMP` A.Replicator `ExtOpMP` A.Replicator
`ExtOpMP` A.Alternative `ExtOpMP` A.Alternative
`ExtOpMP` A.InputMode `ExtOpMP` A.InputMode
`ExtOpMP` A.Specification
`ExtOpMP` A.Process `ExtOpMP` A.Process
`ExtOpMP` A.Variable `ExtOpMP` A.Variable
@ -824,22 +824,6 @@ inferTypes = occamOnlyPass "Infer types"
inTypeContext (Just ct) (recurse sv) >>* A.InputCase m inTypeContext (Just ct) (recurse sv) >>* A.InputCase m
doInputMode _ im = inTypeContext (Just A.Int) $ descend im doInputMode _ im = inTypeContext (Just A.Int) $ descend im
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 :: Data a => Transform (A.Structured a) doStructured :: Data a => Transform (A.Structured a)
doStructured (A.Spec mspec s@(A.Specification m n st) body) doStructured (A.Spec mspec s@(A.Specification m n st) body)
= do (st', wrap) <- runReaderT (doSpecType n st) body = do (st', wrap) <- runReaderT (doSpecType n st) body
@ -848,9 +832,7 @@ inferTypes = occamOnlyPass "Infer types"
wrap (recurse body) >>* A.Spec mspec (A.Specification m n st') wrap (recurse body) >>* A.Spec mspec (A.Specification m n st')
doStructured s = descend s doStructured s = descend s
-- The second parameter is a modifier (wrapper) for the descent into the body doSpecType :: Data a => A.Name -> A.SpecType -> ReaderT (A.Structured a) PassM A.SpecType
doSpecType :: Data a => A.Name -> A.SpecType -> ReaderT (A.Structured a) PassM
(A.SpecType, PassM (A.Structured a) -> PassM (A.Structured a))
doSpecType n st doSpecType n st
= case st of = case st of
A.Place _ _ -> lift $ inTypeContext (Just A.Int) $ descend st >>* addId A.Place _ _ -> lift $ inTypeContext (Just A.Int) $ descend st >>* addId
@ -999,18 +981,48 @@ inferTypes = occamOnlyPass "Infer types"
= do el' <- doExpressionList ts el = do el' <- doExpressionList ts el
return $ A.Only m el' return $ A.Only m el'
findDir :: Data a => A.Name -> a -> PassM [A.Direction] -- findDir only really needs to descend operating on Variables
findDir n = flip execStateT [] . makeRecurseM ops -- But since this is called by doStructured, that would require doStructured
-- to have an extra constraint that the Structured supports descent into
-- Variables. But that constraint, in turn, is not satisfied when we build
-- our ops using extOpMS. Rather than fix all the constraints, I've decided
-- to adopt a slightly sneaky approach, and build a set of ops for findDir
-- with the same type as the one for infer types (thus the constraints
-- don't change), but where everything apart from the Variable operation
-- is a call to descend.
--
-- Also, to fit with the normal ops, we must do so in the PassM monad.
-- Normally we would do this pass in a StateT monad, but to slip inside
-- PassM, I've used an IORef instead.
findDir :: ( PolyplateM a InferTypeOps () PassM
, PolyplateM a () InferTypeOps PassM
) => A.Name -> a -> PassM [A.Direction]
findDir n x
= do r <- liftIO $ newIORef []
makeRecurseM (ops r) x
liftIO $ readIORef r
where where
ops = baseOp `extOpM` doVariable ops :: IORef [A.Direction] -> InferTypeOps
ops r = baseOp
`extOpMS` (ops r, descend)
`extOpM` descend
`extOpM` descend
`extOpM` descend
`extOpM` descend
`extOpM` descend
`extOpM` descend
`extOpM` descend
`extOpM` (doVariable r)
-- This will cover everything, since we will have inferred the direction -- This will cover everything, since we will have inferred the direction
-- specifiers before applying this function. -- specifiers before applying this function.
doVariable :: A.Variable -> StateT [A.Direction] PassM A.Variable doVariable :: IORef [A.Direction] -> A.Variable -> PassM A.Variable
doVariable v@(A.DirectedVariable _ dir (A.Variable _ n')) | n == n' doVariable r v@(A.DirectedVariable _ dir (A.Variable _ n')) | n == n'
= modify (dir:) >> return v = liftIO $ modifyIORef r (dir:) >> return v
doVariable v = makeDescend ops v doVariable r v@(A.DirectedVariable _ dir
(A.SubscriptedVariable _ _ (A.Variable _ n'))) | n == n'
= liftIO $ modifyIORef r (dir:) >> return v
doVariable r v = makeDescendM (ops r) v
doProcess :: Transform A.Process doProcess :: Transform A.Process
doProcess p doProcess p