Provide combinators for generic traversals.

The types get hairier, but the code is much simpler!

I've left {check,apply}DepthM{,2} there for now, but reimplemented them in
terms of the new combinators.

Fixes #58.
This commit is contained in:
Adam Sampson 2008-04-08 14:41:25 +00:00
parent e460032c30
commit 3da2ad1385
2 changed files with 45 additions and 127 deletions

View File

@ -617,10 +617,17 @@ inSubscriptedContext m body
-- | Infer types. -- | Infer types.
inferTypes :: Data t => t -> PassM t inferTypes :: Data t => t -> PassM t
inferTypes = applyExplicitM10 doExpression doDimension doSubscript inferTypes = applyX $ baseX
doArrayConstr doReplicator doAlternative `extX` doExpression
doInputMode doSpecification doProcess `extX` doDimension
doVariable `extX` doSubscript
`extX` doArrayConstr
`extX` doReplicator
`extX` doAlternative
`extX` doInputMode
`extX` doSpecification
`extX` doProcess
`extX` doVariable
where where
doExpression :: ExplicitTrans A.Expression doExpression :: ExplicitTrans A.Expression
doExpression descend outer doExpression descend outer

View File

@ -20,7 +20,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module Traversal ( module Traversal (
ExplicitTrans, Transform, Check ExplicitTrans, Transform, Check
, transformToExplicitDepth, checkToTransform , transformToExplicitDepth, checkToTransform
, applyExplicitM, applyExplicitM2, applyExplicitM9, applyExplicitM10 , baseX, extX, extD, extC, applyX
, applyDepthM, applyDepthM2 , applyDepthM, applyDepthM2
, checkDepthM , checkDepthM
) where ) where
@ -52,140 +52,51 @@ transformToExplicitDepth f descend x = descend x >>= f
checkToTransform :: Data t => Check t -> Transform t checkToTransform :: Data t => Check t -> Transform t
checkToTransform f x = f x >> return x checkToTransform f x = f x >> return x
-- | Apply an explicit transformation. -- | A set of generic transformations.
applyExplicitM :: forall t1 s. (Data t1, Data s) => type InfoX = ([TypeKey],
ExplicitTrans t1 -> s -> PassM s (forall dgt. Data dgt => dgt -> PassM dgt)
applyExplicitM f1 = doGeneric `extM` (doSpecific f1) -> (forall t1. Data t1 => t1 -> PassM t1)
-> (forall t2. Data t2 => t2 -> PassM t2))
-- | An empty set of transformations.
baseX :: InfoX
baseX = ([], (\doGeneric t -> t))
-- | Add an 'ExplicitTrans' to a set.
extX :: forall t. Data t => InfoX -> ExplicitTrans t -> InfoX
extX (tks, g) f = ((typeKey (undefined :: t)) : tks,
(\doGeneric t -> (g doGeneric t) `extM` (f doGeneric)))
-- | Add a 'Transform' to a set, to be applied depth-first.
extD :: forall t. Data t => InfoX -> Transform t -> InfoX
extD info f = extX info (transformToExplicitDepth f)
-- | Add a 'Check' to a set, to be applied depth-first.
extC :: forall t. Data t => InfoX -> Check t -> InfoX
extC info f = extD info (checkToTransform f)
-- | Apply a set of transformations.
applyX :: Data s => InfoX -> s -> PassM s
applyX info@(tks, g) = g doGeneric doGeneric
where where
typeSet :: [TypeKey]
typeSet = [typeKey (undefined :: t1)]
doGeneric :: Data t => t -> PassM t doGeneric :: Data t => t -> PassM t
doGeneric = gmapMFor typeSet (applyExplicitM f1) doGeneric = gmapMFor tks (applyX info)
doSpecific :: Data t => ExplicitTrans t -> t -> PassM t
doSpecific f x = f doGeneric x
-- | Apply two explicit transformations.
applyExplicitM2 :: forall t1 t2 s. (Data t1, Data t2, Data s) =>
ExplicitTrans t1 -> ExplicitTrans t2 -> s -> PassM s
applyExplicitM2 f1 f2 = doGeneric `extM` (doSpecific f1)
`extM` (doSpecific f2)
where
typeSet :: [TypeKey]
typeSet = [ typeKey (undefined :: t1)
, typeKey (undefined :: t2)
]
doGeneric :: Data t => t -> PassM t
doGeneric = gmapMFor typeSet (applyExplicitM2 f1 f2)
doSpecific :: Data t => ExplicitTrans t -> t -> PassM t
doSpecific f x = f doGeneric x
-- | Apply nine explicit transformations (!).
applyExplicitM9 :: forall t1 t2 t3 t4 t5 t6 t7 t8 t9 s.
(Data t1, Data t2, Data t3, Data t4, Data t5, Data t6,
Data t7, Data t8, Data t9, Data s) =>
ExplicitTrans t1
-> ExplicitTrans t2
-> ExplicitTrans t3
-> ExplicitTrans t4
-> ExplicitTrans t5
-> ExplicitTrans t6
-> ExplicitTrans t7
-> ExplicitTrans t8
-> ExplicitTrans t9
-> s -> PassM s
applyExplicitM9 f1 f2 f3 f4 f5 f6 f7 f8 f9
= doGeneric `extM` (doSpecific f1)
`extM` (doSpecific f2)
`extM` (doSpecific f3)
`extM` (doSpecific f4)
`extM` (doSpecific f5)
`extM` (doSpecific f6)
`extM` (doSpecific f7)
`extM` (doSpecific f8)
`extM` (doSpecific f9)
where
typeSet :: [TypeKey]
typeSet = [ typeKey (undefined :: t1)
, typeKey (undefined :: t2)
, typeKey (undefined :: t3)
, typeKey (undefined :: t4)
, typeKey (undefined :: t5)
, typeKey (undefined :: t6)
, typeKey (undefined :: t7)
, typeKey (undefined :: t8)
, typeKey (undefined :: t9)
]
doGeneric :: Data t => t -> PassM t
doGeneric = gmapMFor typeSet (applyExplicitM9 f1 f2 f3 f4 f5 f6 f7 f8 f9)
doSpecific :: Data t => ExplicitTrans t -> t -> PassM t
doSpecific f x = f doGeneric x
-- | Apply ten explicit transformations.
applyExplicitM10 :: forall t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 s.
(Data t1, Data t2, Data t3, Data t4, Data t5, Data t6,
Data t7, Data t8, Data t9, Data t10, Data s) =>
ExplicitTrans t1
-> ExplicitTrans t2
-> ExplicitTrans t3
-> ExplicitTrans t4
-> ExplicitTrans t5
-> ExplicitTrans t6
-> ExplicitTrans t7
-> ExplicitTrans t8
-> ExplicitTrans t9
-> ExplicitTrans t10
-> s -> PassM s
applyExplicitM10 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10
= doGeneric `extM` (doSpecific f1)
`extM` (doSpecific f2)
`extM` (doSpecific f3)
`extM` (doSpecific f4)
`extM` (doSpecific f5)
`extM` (doSpecific f6)
`extM` (doSpecific f7)
`extM` (doSpecific f8)
`extM` (doSpecific f9)
`extM` (doSpecific f10)
where
typeSet :: [TypeKey]
typeSet = [ typeKey (undefined :: t1)
, typeKey (undefined :: t2)
, typeKey (undefined :: t3)
, typeKey (undefined :: t4)
, typeKey (undefined :: t5)
, typeKey (undefined :: t6)
, typeKey (undefined :: t7)
, typeKey (undefined :: t8)
, typeKey (undefined :: t9)
, typeKey (undefined :: t10)
]
doGeneric :: Data t => t -> PassM t
doGeneric = gmapMFor typeSet (applyExplicitM10 f1 f2 f3 f4 f5
f6 f7 f8 f9 f10)
doSpecific :: Data t => ExplicitTrans t -> t -> PassM t
doSpecific f x = f doGeneric x
-- | Apply a transformation, recursing depth-first. -- | Apply a transformation, recursing depth-first.
applyDepthM :: forall t1 s. (Data t1, Data s) => applyDepthM :: forall t1 s. (Data t1, Data s) =>
Transform t1 -> s -> PassM s Transform t1 -> s -> PassM s
applyDepthM f = applyExplicitM (transformToExplicitDepth f) applyDepthM f1
= applyX $ baseX `extD` f1
-- | Apply two transformations, recursing depth-first. -- | Apply two transformations, recursing depth-first.
applyDepthM2 :: forall t1 t2 s. (Data t1, Data t2, Data s) => applyDepthM2 :: forall t1 t2 s. (Data t1, Data t2, Data s) =>
Transform t1 -> Transform t2 -> s -> PassM s Transform t1 -> Transform t2 -> s -> PassM s
applyDepthM2 f1 f2 = applyExplicitM2 (transformToExplicitDepth f1) applyDepthM2 f1 f2
(transformToExplicitDepth f2) = applyX $ baseX `extD` f1 `extD` f2
-- | Apply a check, recursing depth-first. -- | Apply a check, recursing depth-first.
checkDepthM :: forall t1 s. (Data t1, Data s) => checkDepthM :: forall t1 s. (Data t1, Data s) =>
Check t1 -> s -> PassM s Check t1 -> s -> PassM s
checkDepthM f = applyDepthM (checkToTransform f) checkDepthM f1
= applyX $ baseX `extC` f1