Fixed many of the modules to use the new Polyplate-based Traversal system

This commit is contained in:
Neil Brown 2008-12-02 18:06:10 +00:00
parent a3bcb32937
commit 890e7ea9a6
6 changed files with 91 additions and 58 deletions

View File

@ -363,6 +363,28 @@ abbrevModeOfSpec s
A.RetypesExpr _ am _ _ -> am A.RetypesExpr _ am _ _ -> am
_ -> A.Original _ -> A.Original
-- | Resolve a datatype into its underlying type -- i.e. if it's a named data
-- type, then return the underlying real type. This will recurse.
underlyingType :: forall m. (CSMR m, Die m) => Meta -> A.Type -> m A.Type
underlyingType m = applyDepthM doType
where
doType :: A.Type -> m A.Type
-- This is fairly subtle: after resolving a user type, we have to recurse
-- on the resulting type.
doType t@(A.UserDataType _) = resolveUserType m t >>= underlyingType m
doType t = return t
-- | Like underlyingType, but only do the "outer layer": if you give this a
-- user type that's an array of user types, then you'll get back an array of
-- user types.
resolveUserType :: (CSMR m, Die m) => Meta -> A.Type -> m A.Type
resolveUserType m (A.UserDataType n)
= do st <- specTypeOfName n
case st of
A.DataType _ t -> resolveUserType m t
_ -> dieP m $ "Not a type name: " ++ show n
resolveUserType _ t = return t
-- | Add array dimensions to a type; if it's already an array it'll just add -- | Add array dimensions to a type; if it's already an array it'll just add
-- the new dimensions to the existing array. -- the new dimensions to the existing array.
addDimensions :: [A.Dimension] -> A.Type -> A.Type addDimensions :: [A.Dimension] -> A.Type -> A.Type

View File

@ -16,11 +16,13 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. with this program. If not, see <http://www.gnu.org/licenses/>.
-} -}
-- | Traversal strategies over the AST and other data types. -- | Traversal strategies over the AST and other data types. This is now mainly
-- a collection of extra Tock-specific utilities that go on top of Polyplate
module Traversal ( module Traversal (
TransformM, Transform TransformM, Transform, TransformStructured
, CheckM, Check , CheckM, Check
, ExtOpMP, ExtOpMS, ExtOpMSP, extOpMS , ExtOpMP, ExtOpMS, ExtOpMSP, extOpMS
, applyBottomUpMS
, module Data.Generics.Polyplate , module Data.Generics.Polyplate
, module Data.Generics.Polyplate.Schemes , module Data.Generics.Polyplate.Schemes
) where ) where
@ -95,3 +97,13 @@ extOpMS ops (_, f)
`extOpM` (f :: A.Structured A.Alternative -> m (A.Structured A.Alternative)) `extOpM` (f :: A.Structured A.Alternative -> m (A.Structured A.Alternative))
`extOpM` (f :: A.Structured () -> m (A.Structured ())) `extOpM` (f :: A.Structured () -> m (A.Structured ()))
applyBottomUpMS :: (PolyplateM t (ExtOpMSP BaseOp) () PassM) =>
(forall a. (Data a, PolyplateM (A.Structured a) () (ExtOpMSP BaseOp) PassM) =>
(A.Structured a -> PassM (A.Structured a)))
-> t -> PassM t
applyBottomUpMS f = makeRecurseM ops
where
ops = baseOp `extOpMS` (ops, makeBottomUpM ops f)
type TransformStructured ops
= (PolyplateM (A.Structured t) () ops PassM, Data t) => Transform (A.Structured t)

View File

@ -31,18 +31,18 @@ import Traversal
import Types import Types
import Utils import Utils
simplifyComms :: [Pass] simplifyComms :: [Pass A.AST]
simplifyComms = simplifyComms =
[ outExprs [ outExprs
, transformInputCase , transformInputCase
, transformProtocolInput , transformProtocolInput
] ]
outExprs :: Pass outExprs :: PassOn A.Process
outExprs = pass "Define temporary variables for outputting expressions" outExprs = pass "Define temporary variables for outputting expressions"
(Prop.agg_namesDone ++ Prop.agg_typesDone) (Prop.agg_namesDone ++ Prop.agg_typesDone)
[Prop.outExpressionRemoved] [Prop.outExpressionRemoved]
(applyDepthM doProcess) (applyBottomUpM doProcess)
where where
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Output m c ois) doProcess (A.Output m c ois)
@ -135,11 +135,11 @@ ALT
-- process D -- process D
-} -}
transformInputCase :: Pass transformInputCase :: PassOn A.Process
transformInputCase = pass "Transform ? CASE statements/guards into plain CASE" transformInputCase = pass "Transform ? CASE statements/guards into plain CASE"
(Prop.agg_namesDone ++ Prop.agg_typesDone) (Prop.agg_namesDone ++ Prop.agg_typesDone)
[Prop.inputCaseRemoved] [Prop.inputCaseRemoved]
(applyDepthM doProcess) (applyBottomUpM doProcess)
where where
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Input m v (A.InputCase m' s)) doProcess (A.Input m v (A.InputCase m' s))
@ -182,11 +182,11 @@ transformInputCase = pass "Transform ? CASE statements/guards into plain CASE"
-- Leave other guards untouched. -- Leave other guards untouched.
doAlternative m a = return $ A.Only m a doAlternative m a = return $ A.Only m a
transformProtocolInput :: Pass transformProtocolInput :: PassOn2 A.Process A.Alternative
transformProtocolInput = pass "Flatten sequential protocol inputs into multiple inputs" transformProtocolInput = pass "Flatten sequential protocol inputs into multiple inputs"
(Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.inputCaseRemoved]) (Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.inputCaseRemoved])
[Prop.seqInputsFlattened] [Prop.seqInputsFlattened]
(applyDepthM2 doProcess doAlternative) (applyBottomUpM2 doProcess doAlternative)
where where
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Input m v (A.InputSimple m' iis@(_:_:_))) doProcess (A.Input m v (A.InputSimple m' iis@(_:_:_)))

View File

@ -35,7 +35,7 @@ import Traversal
import Types import Types
import Utils import Utils
simplifyExprs :: [Pass] simplifyExprs :: [Pass A.AST]
simplifyExprs = simplifyExprs =
[ functionsToProcs [ functionsToProcs
, removeAfter , removeAfter
@ -51,7 +51,7 @@ builtInOperatorFunction = (`elem` occamBuiltInOperatorFunctions) . A.nameName
-- | Convert FUNCTION declarations to PROCs. -- | Convert FUNCTION declarations to PROCs.
functionsToProcs :: Pass functionsToProcs :: PassOn A.Specification
functionsToProcs = pass "Convert FUNCTIONs to PROCs" functionsToProcs = pass "Convert FUNCTIONs to PROCs"
(Prop.agg_namesDone ++ [Prop.expressionTypesChecked, Prop.parUsageChecked, (Prop.agg_namesDone ++ [Prop.expressionTypesChecked, Prop.parUsageChecked,
Prop.functionTypesChecked]) Prop.functionTypesChecked])
@ -106,11 +106,11 @@ functionsToProcs = pass "Convert FUNCTIONs to PROCs"
-- | Convert AFTER expressions to the equivalent using MINUS (which is how the -- | Convert AFTER expressions to the equivalent using MINUS (which is how the
-- occam 3 manual defines AFTER). -- occam 3 manual defines AFTER).
removeAfter :: Pass removeAfter :: PassOn A.Expression
removeAfter = pass "Convert AFTER to MINUS" removeAfter = pass "Convert AFTER to MINUS"
[Prop.expressionTypesChecked] [Prop.expressionTypesChecked]
[Prop.afterRemoved] [Prop.afterRemoved]
(applyDepthM2 doExpression doExpressionList) (applyDepthM doExpression)
where where
doFunctionCall :: (Meta -> A.Name -> [A.Expression] -> a) doFunctionCall :: (Meta -> A.Name -> [A.Expression] -> a)
-> Meta -> A.Name -> [A.Expression] -> PassM a -> Meta -> A.Name -> [A.Expression] -> PassM a
@ -145,11 +145,11 @@ removeAfter = pass "Convert AFTER to MINUS"
-- | For array literals that include other arrays, burst them into their -- | For array literals that include other arrays, burst them into their
-- elements. -- elements.
expandArrayLiterals :: Pass expandArrayLiterals :: PassOn A.ArrayElem
expandArrayLiterals = pass "Expand array literals" expandArrayLiterals = pass "Expand array literals"
[Prop.expressionTypesChecked, Prop.processTypesChecked] [Prop.expressionTypesChecked, Prop.processTypesChecked]
[Prop.arrayLiteralsExpanded] [Prop.arrayLiteralsExpanded]
(applyDepthM doArrayElem) (applyBottomUpM doArrayElem)
where where
doArrayElem :: A.Structured A.Expression -> PassM (A.Structured A.Expression) doArrayElem :: A.Structured A.Expression -> PassM (A.Structured A.Expression)
doArrayElem ae@(A.Only _ e) doArrayElem ae@(A.Only _ e)
@ -189,13 +189,14 @@ expandArrayLiterals = pass "Expand array literals"
-- Therefore, we only need to pull up the counts for SEQ, PAR and ALT -- Therefore, we only need to pull up the counts for SEQ, PAR and ALT
-- --
-- TODO for simplification, we could avoid pulling up replication counts that are known to be constants -- TODO for simplification, we could avoid pulling up replication counts that are known to be constants
--
-- TODO we should also pull up the step counts
pullRepCounts :: Pass pullRepCounts :: Pass
pullRepCounts = pass "Pull up replicator counts for SEQs, PARs and ALTs" pullRepCounts = pass "Pull up replicator counts for SEQs, PARs and ALTs"
(Prop.agg_namesDone ++ Prop.agg_typesDone) (Prop.agg_namesDone ++ Prop.agg_typesDone)
[] []
(applyDepthM pullRepCountProc) (applyDepthM2
(pullRepCount :: A.Structured A.Process -> PassM (A.Structured A.Process))
(pullRepCount :: A.Structured A.Alternative -> PassM (A.Structured A.Alternative))
)
where where
pullRepCountStr :: Data a => Bool -> A.Structured a pullRepCountStr :: Data a => Bool -> A.Structured a
-> StateT (A.Structured A.Process -> A.Structured A.Process) -> StateT (A.Structured A.Process -> A.Structured A.Process)
@ -221,11 +222,11 @@ pullRepCounts = pass "Pull up replicator counts for SEQs, PARs and ALTs"
return $ A.Seq m $ spec $ A.Only m $ A.Par m p body' return $ A.Seq m $ spec $ A.Only m $ A.Par m p body'
pullRepCountProc p = return p pullRepCountProc p = return p
transformConstr :: Pass transformConstr :: PassOnOps (ExtOpMSP BaseOp)
transformConstr = pass "Transform array constructors into initialisation code" transformConstr = pass "Transform array constructors into initialisation code"
(Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.subscriptsPulledUp]) (Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.subscriptsPulledUp])
[Prop.arrayConstructorsRemoved] [Prop.arrayConstructorsRemoved]
(applyDepthSM doStructured) (applyBottomUpMS doStructured)
where where
-- For arrays, this takes a constructor expression: -- For arrays, this takes a constructor expression:
-- VAL type name IS [i = rep | expr]: -- VAL type name IS [i = rep | expr]:
@ -329,19 +330,26 @@ transformConstr = pass "Transform array constructors into initialisation code"
doStructured s = return s doStructured s = return s
type PullUpOps = ExtOpMSP BaseOp
`ExtOpMP` A.Process
`ExtOpMP` A.Specification
`ExtOpMP` A.LiteralRepr
`ExtOpMP` A.Expression
`ExtOpMP` A.Variable
`ExtOpMP` A.ExpressionList
-- | Find things that need to be moved up to their enclosing Structured, and do -- | Find things that need to be moved up to their enclosing Structured, and do
-- so. -- so.
pullUp :: Bool -> Pass pullUp :: Bool -> PassOnOps PullUpOps
pullUp pullUpArraysInsideRecords = pass "Pull up definitions" pullUp pullUpArraysInsideRecords = pass "Pull up definitions"
(Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.functionsRemoved, Prop.seqInputsFlattened]) (Prop.agg_namesDone ++ Prop.agg_typesDone ++ [Prop.functionsRemoved, Prop.seqInputsFlattened])
[Prop.functionCallsRemoved, Prop.subscriptsPulledUp] [Prop.functionCallsRemoved, Prop.subscriptsPulledUp]
recurse recurse
where where
ops :: Ops ops :: PullUpOps
ops = baseOp ops = baseOp
`extOpS` doStructured `extOpS` doStructured
`extOp` doProcess `extOp` doProcess
`extOp` doRepArray
`extOp` doSpecification `extOp` doSpecification
`extOp` doLiteralRepr `extOp` doLiteralRepr
`extOp` doExpression `extOp` doExpression
@ -354,7 +362,7 @@ pullUp pullUpArraysInsideRecords = pass "Pull up definitions"
-- | When we encounter a Structured, create a new pulled items state, -- | When we encounter a Structured, create a new pulled items state,
-- recurse over it, then apply whatever pulled items we found to it. -- recurse over it, then apply whatever pulled items we found to it.
doStructured :: Data a => A.Structured a -> PassM (A.Structured a) doStructured :: TransformStructured PullUpOps
doStructured s doStructured s
= do pushPullContext = do pushPullContext
-- Recurse over the body, then apply the pulled items to it -- Recurse over the body, then apply the pulled items to it

View File

@ -34,7 +34,7 @@ import Traversal
import Types import Types
import Utils import Utils
simplifyProcs :: [Pass] simplifyProcs :: [Pass A.AST]
simplifyProcs = simplifyProcs =
[ parsToProcs [ parsToProcs
, removeParAssign , removeParAssign
@ -42,11 +42,11 @@ simplifyProcs =
] ]
-- | Wrap the subprocesses of PARs in no-arg PROCs. -- | Wrap the subprocesses of PARs in no-arg PROCs.
parsToProcs :: Pass parsToProcs :: PassOn A.Process
parsToProcs = pass "Wrap PAR subprocesses in PROCs" parsToProcs = pass "Wrap PAR subprocesses in PROCs"
[Prop.parUsageChecked] [Prop.parUsageChecked]
[Prop.parsWrapped] [Prop.parsWrapped]
(applyDepthM doProcess) (applyBottomUpM doProcess)
where where
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Par m pm s) doProcess (A.Par m pm s)
@ -64,11 +64,11 @@ parsToProcs = pass "Wrap PAR subprocesses in PROCs"
return $ A.Spec m s (A.Only m (A.ProcCall m n [])) return $ A.Spec m s (A.Only m (A.ProcCall m n []))
-- | Turn parallel assignment into multiple single assignments through temporaries. -- | Turn parallel assignment into multiple single assignments through temporaries.
removeParAssign :: Pass removeParAssign :: PassOn A.Process
removeParAssign = pass "Remove parallel assignment" removeParAssign = pass "Remove parallel assignment"
[Prop.parUsageChecked, Prop.functionsRemoved, Prop.functionCallsRemoved] [Prop.parUsageChecked, Prop.functionsRemoved, Prop.functionCallsRemoved]
[Prop.assignParRemoved] [Prop.assignParRemoved]
(applyDepthM doProcess) (applyBottomUpM doProcess)
where where
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Assign m vs@(_:_:_) (A.ExpressionList _ es)) doProcess (A.Assign m vs@(_:_:_) (A.ExpressionList _ es))
@ -81,14 +81,14 @@ removeParAssign = pass "Remove parallel assignment"
doProcess p = return p doProcess p = return p
-- | Turn assignment of arrays and records into multiple assignments. -- | Turn assignment of arrays and records into multiple assignments.
flattenAssign :: Pass flattenAssign :: PassOnOps (ExtOpMSP BaseOp `ExtOpMP` A.Process)
flattenAssign = pass "Flatten assignment" flattenAssign = pass "Flatten assignment"
(Prop.agg_typesDone ++ [Prop.assignParRemoved]) (Prop.agg_typesDone ++ [Prop.assignParRemoved])
[Prop.assignFlattened] [Prop.assignFlattened]
(makeRecurse ops) (makeRecurseM ops)
where where
ops :: Ops ops = baseOp `extOpMS` (ops, makeBottomUpM ops doStructured)
ops = extOpD (extOpSD baseOp ops doStructured) ops doProcess `extOpM` makeBottomUpM ops doProcess
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Assign m [v] (A.ExpressionList m' [e])) doProcess (A.Assign m [v] (A.ExpressionList m' [e]))

View File

@ -37,7 +37,7 @@ import Traversal
import Types import Types
import Utils import Utils
unnest :: [Pass] unnest :: [Pass A.AST]
unnest = unnest =
[ removeFreeNames [ removeFreeNames
, removeNesting , removeNesting
@ -77,22 +77,12 @@ freeNamesIn = doGeneric
doSpecType st = doGeneric st doSpecType st = doGeneric st
-- | Replace names. -- | Replace names.
-- replaceNames :: Data t => [(A.Name, A.Name)] -> t -> t
-- This has to have extra cleverness due to a really nasty bug. Array types can replaceNames map v = runIdentity $ applyDepthM doName v
-- have expressions as dimensions, and those expressions can contain free names
-- which are being replaced. This is fine, but when that happens we need to update
-- CompState so that the type has the replaced name, not the old name.
replaceNames :: Data t => [(A.Name, A.Name)] -> t -> PassM t
replaceNames map v = recurse v
where where
smap = Map.fromList [(A.nameName f, t) | (f, t) <- map] smap = Map.fromList [(A.nameName f, t) | (f, t) <- map]
ops :: Ops doName :: A.Name -> Identity A.Name
ops = baseOp `extOp` doName `extOp` doSpecification
recurse :: Data a => Transform a
recurse = makeRecurse ops
doName :: Transform A.Name
doName n = return $ Map.findWithDefault n (A.nameName n) smap doName n = return $ Map.findWithDefault n (A.nameName n) smap
doSpecification :: Transform A.Specification doSpecification :: Transform A.Specification
@ -107,11 +97,11 @@ replaceNames map v = recurse v
return $ A.Specification m n' sp' return $ A.Specification m n' sp'
-- | Turn free names in PROCs into arguments. -- | Turn free names in PROCs into arguments.
removeFreeNames :: Pass removeFreeNames :: PassOn2 A.Specification A.Process
removeFreeNames = pass "Convert free names to arguments" removeFreeNames = pass "Convert free names to arguments"
[Prop.mainTagged, Prop.parsWrapped, Prop.functionCallsRemoved] [Prop.mainTagged, Prop.parsWrapped, Prop.functionCallsRemoved]
[Prop.freeNamesToArgs] [Prop.freeNamesToArgs]
(applyDepthM2 doSpecification doProcess) (applyBottomUpM2 doSpecification doProcess)
where where
doSpecification :: A.Specification -> PassM A.Specification doSpecification :: A.Specification -> PassM A.Specification
doSpecification spec = case spec of doSpecification spec = case spec of
@ -196,25 +186,26 @@ removeFreeNames = pass "Convert free names to arguments"
doProcess p = return p doProcess p = return p
-- | Pull nested declarations to the top level. -- | Pull nested declarations to the top level.
removeNesting :: Pass removeNesting :: PassASTOnOps (ExtOpMSP BaseOp)
removeNesting = pass "Pull nested definitions to top level" removeNesting = pass "Pull nested definitions to top level"
[Prop.freeNamesToArgs] [Prop.freeNamesToArgs]
[Prop.nestedPulled] [Prop.nestedPulled]
(passOnlyOnAST "removeNesting" $ \s -> (passOnlyOnAST "removeNesting" $ \s ->
do pushPullContext do pushPullContext
s' <- recurse s >>= applyPulled s' <- (makeRecurse ops) s >>= applyPulled
popPullContext popPullContext
return s') return s')
where where
ops :: Ops ops :: ExtOpMSP BaseOp
ops = baseOp `extOpS` doStructured ops = baseOp `extOpMS` (ops, doStructured)
recurse :: Recurse
recurse = makeRecurse ops
descend :: Descend
descend = makeDescend ops
doStructured :: Data t => Transform (A.Structured t) recurse :: RecurseM PassM (ExtOpMSP BaseOp)
recurse = makeRecurseM ops
descend :: DescendM PassM (ExtOpMSP BaseOp)
descend = makeDescendM ops
doStructured :: TransformStructured (ExtOpMSP BaseOp)
doStructured s@(A.Spec m spec subS) doStructured s@(A.Spec m spec subS)
= do spec'@(A.Specification _ n st) <- recurse spec = do spec'@(A.Specification _ n st) <- recurse spec
isConst <- isConstantName n isConst <- isConstantName n