diff --git a/Makefile.am b/Makefile.am
index d282dcc..39bbfb7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -106,7 +106,7 @@ modulesdir=$(TOCKMODDIR)
tockincdir=$(TOCKINCDIR)
tocklibdir=$(TOCKLIBDIR)
-config/Paths.hs: config/Paths.hs.in
+config/Paths.hs: config/Paths.hs.in Makefile
@sed -e 's,@@pkgincludedir@@,$(pkgincludedir),g' config/Paths.hs.in \
| sed -e 's,@@tockdir@@,$(TOCKDIR),g' \
| sed -e 's,@@tockmoddir@@,$(TOCKMODDIR),g' \
@@ -114,10 +114,7 @@ config/Paths.hs: config/Paths.hs.in
| sed -e 's,@@tocklibdir@@,$(TOCKLIBDIR),g' >config/Paths.hs
data/NavAST.hs: GenNavAST$(EXEEXT)
- ./GenNavAST$(EXEEXT) data/NavAST.hs data/NavASTSpine.hs
-
-data/NavASTSpine.hs: GenNavAST$(EXEEXT)
- ./GenNavAST$(EXEEXT) data/NavAST.hs data/NavASTSpine.hs
+ ./GenNavAST$(EXEEXT) data/NavAST.hs
data/OrdAST.hs: GenOrdAST$(EXEEXT)
./GenOrdAST$(EXEEXT) > data/OrdAST.hs
@@ -130,7 +127,6 @@ config_sources += config/Paths.hs
config_sources += config/TypeSizes.hs
BUILT_SOURCES = data/NavAST.hs
-BUILT_SOURCES += data/NavASTSpine.hs
BUILT_SOURCES += data/OrdAST.hs
BUILT_SOURCES += data/TagAST.hs
BUILT_SOURCES += frontends/LexOccam.hs
@@ -233,7 +229,7 @@ tocktest_SOURCES += transformations/PassTest.hs
tocktest_SOURCES += transformations/SimplifyAbbrevsTest.hs
tocktest_SOURCES += transformations/SimplifyTypesTest.hs
-pregen_sources = data/AST.hs data/CompState.hs
+pregen_sources = data/AST.hs data/CompState.hs config/Paths.hs
pregen_sources += pregen/PregenUtils.hs
pregen_sources += polyplate/Data/Generics/Polyplate/GenInstances.hs
diff --git a/backends/GenerateC.hs b/backends/GenerateC.hs
index 0465f7c..905ad29 100644
--- a/backends/GenerateC.hs
+++ b/backends/GenerateC.hs
@@ -182,11 +182,11 @@ cgenTopLevel headerName s
= A.nameName n `elem` (csOriginalTopLevelProcs cs)
tellToHeader $ sequence_ $ map (call genForwardDeclaration)
- (listifyDepth isTopLevelSpec s)
+ (listifyTopDown isTopLevelSpec s)
-- Things like lifted wrapper_procs we still need to forward-declare,
-- but we do it in the C file, not in the header:
sequence_ $ map (call genForwardDeclaration)
- (listifyDepth (not . isTopLevelSpec) s)
+ (listifyTopDown (not . isTopLevelSpec) s)
tell ["#include \"", dropPath headerName, "\"\n"]
diff --git a/backends/GenerateCPPCSP.hs b/backends/GenerateCPPCSP.hs
index 2917af0..d7038d0 100644
--- a/backends/GenerateCPPCSP.hs
+++ b/backends/GenerateCPPCSP.hs
@@ -144,11 +144,11 @@ cppgenTopLevel headerName s
= A.nameName n `elem` (csOriginalTopLevelProcs cs)
tellToHeader $ sequence_ $ map (call genForwardDeclaration)
- (listifyDepth isTopLevelSpec s)
+ (listifyTopDown isTopLevelSpec s)
-- Things like lifted wrapper_procs we still need to forward-declare,
-- but we do it in the C file, not in the header:
sequence_ $ map (call genForwardDeclaration)
- (listifyDepth (\sp@(A.Specification _ n _)
+ (listifyTopDown (\sp@(A.Specification _ n _)
-> not (isTopLevelSpec sp)
&& A.nameName n `notElem` map fst (csExternals cs)) s)
diff --git a/checks/Check.hs b/checks/Check.hs
index 19b4666..df9bad4 100644
--- a/checks/Check.hs
+++ b/checks/Check.hs
@@ -107,12 +107,12 @@ followBK = map followBK'
next = Set.fromList $ map Var $ concatMap allVarsInBK bk
allVarsInBK :: BackgroundKnowledge -> [A.Variable]
-allVarsInBK (Equal a b) = listifyDepth (const True) a
- ++ listifyDepth (const True) b
-allVarsInBK (LessThanOrEqual a b) = listifyDepth (const True) a
- ++ listifyDepth (const True) b
-allVarsInBK (RepBoundsIncl v a b) = v : (listifyDepth (const True) a
- ++ listifyDepth (const True) b)
+allVarsInBK (Equal a b) = listifyTopDown (const True) a
+ ++ listifyTopDown (const True) b
+allVarsInBK (LessThanOrEqual a b) = listifyTopDown (const True) a
+ ++ listifyTopDown (const True) b
+allVarsInBK (RepBoundsIncl v a b) = v : (listifyTopDown (const True) a
+ ++ listifyTopDown (const True) b)
data And a = And [a]
data Or a = Or [a]
diff --git a/checks/UsageCheckAlgorithms.hs b/checks/UsageCheckAlgorithms.hs
index 67f1219..cb0ee46 100644
--- a/checks/UsageCheckAlgorithms.hs
+++ b/checks/UsageCheckAlgorithms.hs
@@ -204,7 +204,7 @@ findConstraints graph startNode
processNode (n, e) nodeVal curAgg = case fmap getNodeData $ lab graph n of
Just u ->
let overlapsWithWritten e = not $ null $ intersect
- (listifyDepth (const True) $ snd e)
+ (listifyTopDown (const True) $ snd e)
[v | Var v <- Map.keys $ writtenVars $ nodeVars u]
valFilt = filter (not . overlapsWithWritten) $
nub $ nodeVal ++ (case e of
diff --git a/frontends/OccamTypes.hs b/frontends/OccamTypes.hs
index 941fd74..578211c 100644
--- a/frontends/OccamTypes.hs
+++ b/frontends/OccamTypes.hs
@@ -1307,10 +1307,14 @@ inferTypes = occamOnlyPass "Infer types"
-- This is actually a series of smaller passes that check particular types
-- inside the AST, but it doesn't really make sense to split it up.
checkTypes ::
- (PolyplateSpine t (OneOpQ (PassM ()) A.Variable) () (PassM ())
- ,PolyplateSpine t (OneOpQ (PassM ()) A.Expression) () (PassM ())
- ,PolyplateSpine t (OneOpQ (PassM ()) A.SpecType) () (PassM ())
- ,PolyplateSpine t (OneOpQ (PassM ()) A.Process) () (PassM ())
+ (PolyplateM t (OneOpM PassM A.Variable) () PassM
+ ,PolyplateM t (OneOpM PassM A.Expression) () PassM
+ ,PolyplateM t (OneOpM PassM A.SpecType) () PassM
+ ,PolyplateM t (OneOpM PassM A.Process) () PassM
+ ,PolyplateM t () (OneOpM PassM A.Variable) PassM
+ ,PolyplateM t () (OneOpM PassM A.Expression) PassM
+ ,PolyplateM t () (OneOpM PassM A.SpecType) PassM
+ ,PolyplateM t () (OneOpM PassM A.Process) PassM
) => Pass t
checkTypes = occamOnlyPass "Check types"
[Prop.inferredTypesRecorded, Prop.ambiguitiesResolved]
@@ -1326,8 +1330,8 @@ checkTypes = occamOnlyPass "Check types"
--{{{ checkVariables
-checkVariables :: PlainCheckOn A.Variable
-checkVariables = checkDepthM doVariable
+checkVariables :: PassTypeOn A.Variable
+checkVariables x = checkDepthM doVariable x >> return x
where
doVariable :: Check A.Variable
doVariable (A.SubscriptedVariable m s v)
@@ -1357,8 +1361,8 @@ checkVariables = checkDepthM doVariable
--}}}
--{{{ checkExpressions
-checkExpressions :: PlainCheckOn A.Expression
-checkExpressions = checkDepthM doExpression
+checkExpressions :: PassTypeOn A.Expression
+checkExpressions x = checkDepthM doExpression x >> return x
where
doExpression :: Check A.Expression
doExpression (A.MostPos m t) = checkNumeric m t
@@ -1409,8 +1413,8 @@ checkExpressions = checkDepthM doExpression
--}}}
--{{{ checkSpecTypes
-checkSpecTypes :: PlainCheckOn A.SpecType
-checkSpecTypes = checkDepthM doSpecType
+checkSpecTypes :: PassTypeOn A.SpecType
+checkSpecTypes x = checkDepthM doSpecType x >> return x
where
doSpecType :: Check A.SpecType
doSpecType (A.Place _ e) = checkExpressionInt e
@@ -1532,8 +1536,8 @@ checkSpecTypes = checkDepthM doSpecType
--}}}
--{{{ checkProcesses
-checkProcesses :: PlainCheckOn A.Process
-checkProcesses = checkDepthM doProcess
+checkProcesses :: PassTypeOn A.Process
+checkProcesses x = checkDepthM doProcess x >> return x
where
doProcess :: Check A.Process
doProcess (A.Assign m vs el)
diff --git a/frontends/OccamTypesTest.hs b/frontends/OccamTypesTest.hs
index 0a950af..fc46888 100644
--- a/frontends/OccamTypesTest.hs
+++ b/frontends/OccamTypesTest.hs
@@ -502,20 +502,28 @@ testOccamTypes = TestList
--}}}
]
where
- testOK :: (PolyplateSpine a (OneOpQ (PassM ()) A.Variable) () (PassM ())
- ,PolyplateSpine a (OneOpQ (PassM ()) A.Expression) () (PassM ())
- ,PolyplateSpine a (OneOpQ (PassM ()) A.SpecType) () (PassM ())
- ,PolyplateSpine a (OneOpQ (PassM ()) A.Process) () (PassM ())
+ testOK :: (PolyplateM a (OneOpM PassM A.Variable) () PassM
+ ,PolyplateM a (OneOpM PassM A.Expression) () PassM
+ ,PolyplateM a (OneOpM PassM A.SpecType) () PassM
+ ,PolyplateM a (OneOpM PassM A.Process) () PassM
+ ,PolyplateM a () (OneOpM PassM A.Variable) PassM
+ ,PolyplateM a () (OneOpM PassM A.Expression) PassM
+ ,PolyplateM a () (OneOpM PassM A.SpecType) PassM
+ ,PolyplateM a () (OneOpM PassM A.Process) PassM
,Show a, Data a) => Int -> a -> Test
testOK n orig
= TestCase $ testPass ("testOccamTypes " ++ show n)
orig OccamTypes.checkTypes orig
startState
- testFail :: (PolyplateSpine a (OneOpQ (PassM ()) A.Variable) () (PassM ())
- ,PolyplateSpine a (OneOpQ (PassM ()) A.Expression) () (PassM ())
- ,PolyplateSpine a (OneOpQ (PassM ()) A.SpecType) () (PassM ())
- ,PolyplateSpine a (OneOpQ (PassM ()) A.Process) () (PassM ())
+ testFail :: (PolyplateM a (OneOpM PassM A.Variable) () PassM
+ ,PolyplateM a (OneOpM PassM A.Expression) () PassM
+ ,PolyplateM a (OneOpM PassM A.SpecType) () PassM
+ ,PolyplateM a (OneOpM PassM A.Process) () PassM
+ ,PolyplateM a () (OneOpM PassM A.Variable) PassM
+ ,PolyplateM a () (OneOpM PassM A.Expression) PassM
+ ,PolyplateM a () (OneOpM PassM A.SpecType) PassM
+ ,PolyplateM a () (OneOpM PassM A.Process) PassM
,Show a, Data a) => Int -> a -> Test
testFail n orig
= TestCase $ testPassShouldFail ("testOccamTypes " ++ show n)
diff --git a/frontends/RainTypes.hs b/frontends/RainTypes.hs
index 11d62f7..61dbb98 100644
--- a/frontends/RainTypes.hs
+++ b/frontends/RainTypes.hs
@@ -61,11 +61,11 @@ type RainTypeM = StateT RainTypeState PassM
type RainTypePassType = forall t. t -> StateT RainTypeState PassM t
-type RainTypeCheckOn a = forall t. PolyplateSpine t (OneOpQ (RainTypeM ()) a) ()
- (RainTypeM ()) => t -> RainTypeM ()
+type RainTypeCheckOn a = forall t. PolyplateM t (OneOpM RainTypeM a) () RainTypeM
+ => t -> RainTypeM ()
type RainTypeCheckOn2 a b = forall t.
- (PolyplateSpine t (TwoOpQ (RainTypeM ()) a b) () (RainTypeM ())
+ (PolyplateM t (TwoOpM RainTypeM a b) () RainTypeM
) => t -> RainTypeM ()
@@ -128,12 +128,12 @@ markUnify x y
performTypeUnification ::
-- | A shorthand for prerequisites when you need to spell them out:
- (PolyplateSpine t (OneOpQ (RainTypeM ()) A.Specification) () (RainTypeM ())
- ,PolyplateSpine t (OneOpQ (RainTypeM ()) A.Process) () (RainTypeM ())
- ,PolyplateSpine t (OneOpQ (RainTypeM ()) A.Expression) () (RainTypeM ())
- ,PolyplateSpine t (TwoOpQ (RainTypeM ()) A.Process A.Expression) () (RainTypeM ())
- ,PolyplateSpine t (TwoOpQ (RainTypeM ()) A.Process A.Choice) () (RainTypeM ())
- ,PolyplateSpine t (TwoOpQ (RainTypeM ()) A.Process A.Alternative) () (RainTypeM ())
+ (PolyplateM t (OneOpM RainTypeM A.Specification) () RainTypeM
+ ,PolyplateM t (OneOpM RainTypeM A.Process) () RainTypeM
+ ,PolyplateM t (OneOpM RainTypeM A.Expression) () RainTypeM
+ ,PolyplateM t (TwoOpM RainTypeM A.Process A.Expression) () RainTypeM
+ ,PolyplateM t (TwoOpM RainTypeM A.Process A.Choice) () RainTypeM
+ ,PolyplateM t (TwoOpM RainTypeM A.Process A.Alternative) () RainTypeM
,PolyplateM t () (OneOpM PassM A.Type) PassM
,PolyplateM t (OneOpM PassM A.Type) () PassM
) => Pass t
diff --git a/pass/Pass.hs b/pass/Pass.hs
index dc6a621..0be4ac3 100644
--- a/pass/Pass.hs
+++ b/pass/Pass.hs
@@ -61,12 +61,6 @@ type PassOnOpsM m ops
type PassOnOps ops = PassOnOpsM PassM ops
-type CheckOnOps ops
- = (PolyplateSpine t ops () (PassM ())) => Pass t
-
-type PlainCheckOnOps ops
- = (PolyplateSpine t ops () (PassM ())) => t -> PassM ()
-
type PassASTOnOps ops
= (PolyplateM A.AST ops () PassM, PolyplateM A.AST () ops PassM) => Pass A.AST
@@ -76,8 +70,6 @@ type PassTypeOnOps ops
type PassOn t = PassOnOps (OneOpM PassM t)
type PassOn2 s t = PassOnOps (TwoOpM PassM s t)
type PassTypeOn t = PassTypeOnOps (OneOpM PassM t)
-type CheckOn t = CheckOnOps (OneOpQ (PassM ()) t)
-type PlainCheckOn t = PlainCheckOnOps (OneOpQ (PassM ()) t)
-- | A description of an AST-mangling pass.
data Pass t = Pass {
diff --git a/pass/Traversal.hs b/pass/Traversal.hs
index 68eac0e..50c1480 100644
--- a/pass/Traversal.hs
+++ b/pass/Traversal.hs
@@ -22,7 +22,6 @@ module Traversal (
TransformM, Transform, TransformStructured, TransformStructured', TransformStructuredM'
, CheckM, Check
, ExtOpMP, ExtOpMS, ExtOpMSP, extOpMS, PassOnStruct, PassASTOnStruct
- , ExtOpQS, extOpQS
, applyBottomUpMS, ASTStructured
, module Data.Generics.Polyplate
, module Data.Generics.Polyplate.Schemes
@@ -36,7 +35,6 @@ import Data.Generics.Polyplate.Schemes
import qualified AST as A
import NavAST()
-import NavASTSpine()
import Pass
-- | A transformation for a single 'Data' type.
@@ -71,52 +69,36 @@ type PassASTOnStruct = PassASTOnOps (ExtOpMSP BaseOp)
class (PolyplateM (A.Structured a) () opsM m
,PolyplateM (A.Structured a) opsM () m
- ,PolyplateSpine (A.Structured a) opsQ () r
- ,PolyplateSpine (A.Structured a) () opsQ r
,Data a
,Monad m
) => ASTStructured a opsM m opsQ r
instance (PolyplateM (A.Structured ()) () opsM m
,PolyplateM (A.Structured ()) opsM () m
- ,PolyplateSpine (A.Structured ()) opsQ () r
- ,PolyplateSpine (A.Structured ()) () opsQ r
,Monad m) => ASTStructured () opsM m opsQ r
instance (PolyplateM (A.Structured A.Alternative) () opsM m
,PolyplateM (A.Structured A.Alternative) opsM () m
- ,PolyplateSpine (A.Structured A.Alternative) opsQ () r
- ,PolyplateSpine (A.Structured A.Alternative) () opsQ r
,Monad m) => ASTStructured A.Alternative opsM m opsQ r
instance (PolyplateM (A.Structured A.Choice) () opsM m
,PolyplateM (A.Structured A.Choice) opsM () m
- ,PolyplateSpine (A.Structured A.Choice) opsQ () r
- ,PolyplateSpine (A.Structured A.Choice) () opsQ r
,Monad m) => ASTStructured A.Choice opsM m opsQ r
instance (PolyplateM (A.Structured A.ExpressionList) () opsM m
,PolyplateM (A.Structured A.ExpressionList) opsM () m
- ,PolyplateSpine (A.Structured A.ExpressionList) opsQ () r
- ,PolyplateSpine (A.Structured A.ExpressionList) () opsQ r
,Monad m) => ASTStructured A.ExpressionList opsM m opsQ r
instance (PolyplateM (A.Structured A.Option) () opsM m
,PolyplateM (A.Structured A.Option) opsM () m
- ,PolyplateSpine (A.Structured A.Option) opsQ () r
- ,PolyplateSpine (A.Structured A.Option) () opsQ r
,Monad m) => ASTStructured A.Option opsM m opsQ r
instance (PolyplateM (A.Structured A.Process) () opsM m
,PolyplateM (A.Structured A.Process) opsM () m
- ,PolyplateSpine (A.Structured A.Process) opsQ () r
- ,PolyplateSpine (A.Structured A.Process) () opsQ r
,Monad m) => ASTStructured A.Process opsM m opsQ r
instance (PolyplateM (A.Structured A.Variant) () opsM m
,PolyplateM (A.Structured A.Variant) opsM () m
- ,PolyplateSpine (A.Structured A.Variant) opsQ () r
- ,PolyplateSpine (A.Structured A.Variant) () opsQ r
,Monad m) => ASTStructured A.Variant opsM m opsQ r
@@ -150,47 +132,6 @@ extOpMS ops (_, f)
`extOpM` (f :: A.Structured A.Alternative -> m (A.Structured A.Alternative))
`extOpM` (f :: A.Structured () -> m (A.Structured ()))
-type ExtOpQS r opT =
- (A.Structured () -> r,
- (A.Structured A.Alternative -> r,
- (A.Structured A.Choice -> r,
- (A.Structured A.ExpressionList -> r,
- (A.Structured A.Option -> r,
- (A.Structured A.Process -> r,
- (A.Structured A.Variant -> r,
- opT)))))))
-
-extOpQS :: forall m opT op0T r.
- (PolyplateSpine (A.Structured ()) () op0T r,
- PolyplateSpine (A.Structured A.Alternative) () op0T r,
- PolyplateSpine (A.Structured A.Choice) () op0T r,
- PolyplateSpine (A.Structured A.ExpressionList) () op0T r,
- PolyplateSpine (A.Structured A.Option) () op0T r,
- PolyplateSpine (A.Structured A.Process) () op0T r,
- PolyplateSpine (A.Structured A.Variant) () op0T r,
- PolyplateSpine (A.Structured ()) op0T () r,
- PolyplateSpine (A.Structured A.Alternative) op0T () r,
- PolyplateSpine (A.Structured A.Choice) op0T () r,
- PolyplateSpine (A.Structured A.ExpressionList) op0T () r,
- PolyplateSpine (A.Structured A.Option) op0T () r,
- PolyplateSpine (A.Structured A.Process) op0T () r,
- PolyplateSpine (A.Structured A.Variant) op0T () r) =>
- opT ->
- -- Pairing the next two arguments allows us to apply this function infix:
- (op0T, -- just a type witness
- forall t. ASTStructured t () PassM op0T r => A.Structured t -> r) ->
- ExtOpQS r opT
-extOpQS ops (_, f)
- = ops
- `extOpQ` (f :: A.Structured A.Variant -> r)
- `extOpQ` (f :: A.Structured A.Process -> r)
- `extOpQ` (f :: A.Structured A.Option -> r)
- `extOpQ` (f :: A.Structured A.ExpressionList -> r)
- `extOpQ` (f :: A.Structured A.Choice -> r)
- `extOpQ` (f :: A.Structured A.Alternative -> r)
- `extOpQ` (f :: A.Structured () -> r)
-
-
applyBottomUpMS :: (PolyplateM t (ExtOpMSP BaseOp) () PassM) =>
(forall a. (Data a, PolyplateM (A.Structured a) () (ExtOpMSP BaseOp) PassM) =>
(A.Structured a -> PassM (A.Structured a)))
diff --git a/polyplate/Data/Generics/Polyplate.hs b/polyplate/Data/Generics/Polyplate.hs
index 2941914..f25ab60 100644
--- a/polyplate/Data/Generics/Polyplate.hs
+++ b/polyplate/Data/Generics/Polyplate.hs
@@ -124,14 +124,13 @@ with this program. If not, see .
--
-- TODO include an example with routes
module Data.Generics.Polyplate (PolyplateMRoute(..), PolyplateM(..), Polyplate(..),
- PolyplateSpine(..), {-FullSpine(..),-} transformSpine, {-transformSpineFull,-} trimTree,
makeRecurseM, RecurseM, makeRecurse, Recurse,
makeDescendM, DescendM, makeDescend, Descend,
-- makeRecurseQ, RecurseQ,
-- makeDescendQ, DescendQ,
BaseOp, baseOp,
- ExtOpM, extOpM, ExtOpMRoute, extOpMRoute, ExtOp, extOp, OneOpM, OneOp, TwoOpM, TwoOp,
- ExtOpQ, extOpQ, OneOpQ, TwoOpQ) where
+ ExtOpM, extOpM, ExtOpMRoute, extOpMRoute, ExtOp, extOp, OneOpM, OneOp, TwoOpM, TwoOp
+ ) where
import Control.Monad.Identity
import Data.Maybe
@@ -232,77 +231,6 @@ instance (Monad m
fakeRoute :: t -> Route t ()
fakeRoute = const $ error "transformM"
- -- List of use cases for the Polyplate type-class, to try to decide best on its
- -- necessary functions:
- --
- -- 1. To perform a monadic modification on specific types in the ops across a
- -- whole structure.
- -- 2. As #1, but non-monadic (use Identity monad to adapt the above)
- -- 3. To perform a query across the whole tree that returns a rose-tree that reflects
- -- the (spine-view) structure of the data.
- -- 4. As #3, but to return a flattened list (use flatten to adapt the above)
- -- 5. To perform a monadic modification that also uses modification wrappers,
- -- (a more general case of #1)
- --
- -- So I think there are two classes needed:
- --
- -- 1. One to apply monadic transformations that takes routes (covers #5, #2, #1)
- --
- -- 2. One to apply tree-based queries that transform a whole data structure into
- -- its tree spine-view, with optional methods for flattening into a depth-first
- -- or breadth-first order.
-
--- | A class for transforming a data structure into its spine-view rose tree based
--- on query functions.
---
--- The first parameter is the item being processed. The fourth parameter is the
--- return type of the query functions, which is used in the returned tree.
---
--- The second and third parameters are the usual ops sets, but of the form:
---
--- > (s -> a, (t -> a, ()))
-class PolyplateSpine t o o' a where
- -- | You are unlikely to need to use this function directly at all. See 'transformSpine'
- -- or 'applyQuery' and 'listifyDepth' (and friends).
- --
- -- The third parameter, which transformSpine passes as Nothing, is the value
- -- to be used for the current node. Because this value is set somewhere in the
- -- middle of the ops set, not necessarily at the end, this must be passed along
- -- the sideways calls (while processing the first ops set).
- transformSpineSparse :: o -> o' -> Maybe a -> t -> Tree (Maybe a)
-
-transformSpine :: PolyplateSpine t o o' a => o -> o' -> t -> Tree (Maybe a)
-transformSpine o o' = transformSpineSparse o o' Nothing
-
-{-
--- | Used at the type-level by this library to force a full traversal of a data
--- structure. You are unlikely to need to use this directly.
-data FullSpine a = FullSpine a
--- TODO make this work
-
-transformSpineFull :: (ConvertSpineOpsToFull a o co, ConvertSpineOpsToFull a o' co',
- PolyplateSpine t co co' a) =>
- a -> o -> o' -> t -> Tree a
-transformSpineFull def o o' x
- = fmap fromJust' $
- transformSpineSparse
- (convertSpineOpsToFull def o)
- (convertSpineOpsToFull def o')
- Nothing x
- where
- fromJust' (Just x) = x
- fromJust' _ = error "transformSpineFull: internal error"
--}
-
--- | A function for pruning rose trees of maybe values. All trees where the node
--- value (and the node value of all its children) is Nothing are discarded (Nothing
--- is returned).
-trimTree :: Tree (Maybe a) -> Maybe (Tree (Maybe a))
-trimTree tr | isNothing (rootLabel tr) && null trimmedChildren = Nothing
- | otherwise = Just (Node (rootLabel tr) trimmedChildren)
- where
- trimmedChildren = mapMaybe trimTree (subForest tr)
-
-- | A non-monadic equivalent of PolyplateM. All ops sets are of the form:
--
-- > (a -> a, (b -> b, ()))
@@ -383,11 +311,6 @@ type ExtOpMRoute m opT t outer = ((t, Route t outer) -> m t, opT)
-- for use with the 'Polyplate' class.
type ExtOp opT t = (t -> t, opT)
--- | The type that extends a query-ops set to be applied to the given type (t).
--- Not to be mixed with modification operations. This is for use with the 'PolyplateSpine'
--- class.
-type ExtOpQ a opQ t = (t -> a, opQ)
-
-- | The function that extends an ops set (opT) in the given monad (m) to be applied to
-- the given type (t). You cannot mix monadic and non-monadic operations in the
-- same list. This is for use with the 'PolyplateM' class.
@@ -406,26 +329,15 @@ extOpMRoute ops f = (f, ops)
extOp :: opT -> (t -> t) -> ExtOp opT t
extOp ops f = (f, ops)
--- | The function that extends a query-ops set to be applied to the given type (t).
--- Not to be mixed with modification operations. This is for use with the 'PolyplateSpine'
--- class.
-extOpQ :: opQ -> (t -> a) -> ExtOpQ a opQ t
-extOpQ ops f = (f, ops)
-
-
-- | A handy synonym for a monadic ops set with only one item, to use with 'PolyplateM'.
type OneOpM m t = ExtOpM m BaseOp t
-- | A handy synonym for an ops set with only one item, to use with 'Polyplate'.
type OneOp t = ExtOp BaseOp t
--- | A handy synonym for a query ops set with only one item, to use with 'PolyplateSpine'.
-type OneOpQ a t = ExtOpQ a BaseOp t
-- | A handy synonym for a monadic ops set with only two items, to use with 'PolyplateM'.
type TwoOpM m s t = ExtOpM m (ExtOpM m BaseOp s) t
-- | A handy synonym for an ops set with only two items, to use with 'Polyplate'.
type TwoOp s t = ExtOp (ExtOp BaseOp s) t
--- | A handy synonym for a monadic ops set with only two items, to use with 'PolyplateSpine'.
-type TwoOpQ a s t = ExtOpQ a (ExtOpQ a BaseOp s) t
-- {{{ Various type-level programming ops conversions:
diff --git a/polyplate/Data/Generics/Polyplate/GenInstances.hs b/polyplate/Data/Generics/Polyplate/GenInstances.hs
index c763ba3..3b4cc44 100644
--- a/polyplate/Data/Generics/Polyplate/GenInstances.hs
+++ b/polyplate/Data/Generics/Polyplate/GenInstances.hs
@@ -38,7 +38,7 @@ with this program. If not, see .
module Data.Generics.Polyplate.GenInstances
(GenOverlappedOption(..), GenClassOption(..),
GenInstance, genInstance, genMapInstance, genSetInstance, genInstances,
- writeInstances, writeInstancesTo, writeInstancesToSep) where
+ writeInstances, writeInstancesTo) where
import Control.Monad.State
import Data.Char
@@ -440,231 +440,31 @@ instancesFrom genOverlapped genClass boxes w
-- This is covered by one big overlapping instance:
| otherwise = (False,[],[])
--- | Instances for a particular data type (i.e. where that data type is the
--- first argument to 'Polyplate').
-spineInstancesFrom :: forall t. Data t => GenOverlappedOption -> GenClassOption -> [Witness] -> t -> IO [String]
--- This method is similar to instancesFrom in terms of general behaviour, but still
--- different enough that very little code could be shared, so it's clearer to pull
--- it out to its own method:
-spineInstancesFrom genOverlapped genClass boxes w
- = do (specialProcessChildren, containedTypes) <-
- case find (== Plain (DataBox w)) boxes of
- Just (Detailed _ containedTypes _ doChildrenSpine) ->
- -- It's a special case, use the detailed info:
- do eachContained <- sequence [findTypesIn' c | DataBox c <- containedTypes]
- return (Just (containedTypes, doChildrenSpine), foldl Map.union Map.empty eachContained)
- -- It's a normal case, use findTypesIn' directly:
- _ -> do ts <- findTypesIn' w
- return (Nothing, ts)
- containedKeys <- liftM Set.fromList
- (sequence [typeKey c | DataBox c <- map witness $ justBoxes containedTypes])
- wKey <- typeKey w
- otherInsts <- sequence [do ck <- typeKey c
- return (otherInst wKey containedKeys c ck)
- | DataBox c <- map witness boxes]
- return $ baseInst specialProcessChildren ++ concat otherInsts
- where
- wName = show $ typeOf w
- wMunged = mungeName wName
- wDType = dataTypeOf w
- wCtrs = if isAlgType wDType then dataTypeConstrs wDType else []
-
- -- The module prefix of this type, so we can use it in constructor names.
- modPrefix
- = if '.' `elem` (takeWhile (\c -> isAlphaNum c || c == '.') wName)
- then takeWhile (/= '.') wName ++ "."
- else ""
-
- ctrArgs ctr
- = gmapQ DataBox (fromConstr ctr :: t)
- ctrArgTypes types
- = [show $ typeOf w | DataBox w <- types]
-
- -- Given the context (a list of instance requirements), the left-hand ops,
- -- the right-hand ops, and a list of lines for the body of the class, generates
- -- an instance.
- --
- -- For GenOneClass this will be an instance of PolyplateM.
- --
- -- For GenClassPerType this will be an instance of PolyplateMFoo (or whatever)
- --
- -- For GenSlowDelegate this will be an instance of PolyplateM', with the first
- -- and last arguments swapped.
- genInst :: [String] -> String -> String -> [String] -> [String]
- genInst context ops0 ops1 body
- = ["instance (" ++ concat (intersperse ", " context) ++ ") =>"
- ," " ++ contextSameType ops0 ops1 ++ " where"
- ] ++ map (" " ++) body
-
- -- Generates the name of an instance for the same type with the given two ops
- -- sets. The class name will be the same as genInst.
- contextSameType :: String -> String -> String
- contextSameType ops0 ops1 = case genClass of
- GenOneClass -> "PolyplateSpine (" ++ wName ++ ") " ++ ops0 ++ " " ++ ops1 ++ " a"
- GenClassPerType -> "PolyplateSpine" ++ wMunged ++" " ++ ops0 ++ " " ++ ops1 ++ " a"
- GenSlowDelegate -> "PolyplateSpine' a " ++ ops0 ++ " " ++ ops1 ++ " (" ++ wName ++ ")"
-
- -- Generates the name of an instance for a different type (for processing children).
- -- This will be PolyplateM or PolyplateM'.
- contextNewType :: String -> String -> String -> String
- contextNewType cName ops0 ops1 = case genClass of
- GenOneClass -> "PolyplateSpine (" ++ cName ++ ") " ++ ops0 ++ " " ++ ops1 ++ " a"
- GenClassPerType -> "PolyplateSpine (" ++ cName ++ ") " ++ ops0 ++ " " ++ ops1 ++ " a"
- GenSlowDelegate -> "PolyplateSpine' a " ++ ops0 ++ " " ++ ops1 ++ " (" ++ cName ++ ")"
-
-
- -- The function to define in the body, and also to use for processing the same
- -- type.
- funcSameType :: String
- funcSameType = case genClass of
- GenClassPerType -> "transformSpineSparse" ++ wMunged
- GenOneClass -> "transformSpineSparse"
- GenSlowDelegate -> "transformSpineSparse'"
-
- -- The function to use for processing other types
- funcNewType :: String
- funcNewType = case genClass of
- GenClassPerType -> "transformSpineSparse"
- GenOneClass -> "transformSpineSparse"
- GenSlowDelegate -> "transformSpineSparse'"
-
- -- | An instance that describes what to do when we have no transformations
- -- left to apply. You can pass it an override for the case of processing children
- -- (and the types that make up the children).
- baseInst :: Maybe ([DataBox], (String, String) -> [String]) -> [String]
- baseInst mdoChildren
- = concat
- [genInst context "()" "(f, ops)" $
- maybe
- (if isAlgType wDType
- -- An algebraic type: apply to each child if we're following.
- then (concatMap constrCase wCtrs)
- -- A primitive (or non-represented) type: just return it.
- else [funcSameType ++ " () _ _ _ = Node Nothing []"])
- (\(_,f) -> f (funcSameType, funcNewType)) mdoChildren
- ,genInst [] "()" "()" [funcSameType ++ " () () q _ = Node q []"]
- --,genInst (contextNewType "(FullSpine a)" "()") "(FullSpine a)" "()" [funcSameType ++ " () () v = return v"]
- ,if genOverlapped == GenWithoutOverlapped then [] else
- genInst
- [ contextSameType "r" "ops" ]
- "(b -> a, r)" "ops"
- [funcSameType ++ " (_, rest) ops = " ++ funcSameType ++ " rest ops"]
- ,if genClass == GenClassPerType
- then ["class PolyplateSpine" ++ wMunged ++ " o o' a where"
- ," " ++ funcSameType ++ " :: o -> o' -> Maybe a -> (" ++ wName ++
- ") -> Tree (Maybe a)"
- ,""
- ,"instance (" ++ contextSameType "o0" "o1" ++ ") =>"
- ," PolyplateSpine (" ++ wName ++ ") o0 o1 a where"
- ," transformSpineSparse = " ++ funcSameType
- ]
- else []
- ]
- where
- -- | Class context for 'baseInst'.
- -- We need an instance of Polyplate for each of the types directly contained within
- -- this type, so we can recurse into them.
- context :: [String]
- context
- = [ contextNewType argType "(f,ops)" "()"
- | argType <- nub $ sort $ concatMap ctrArgTypes $
- maybe (map ctrArgs wCtrs) ((:[]) . fst) mdoChildren]
-
- -- | A 'transformM' case for a particular constructor of this (algebraic)
- -- data type: pull the value apart, apply 'transformM' to each part of it,
- -- then stick it back together.
- constrCase :: Constr -> [String]
- constrCase ctr
- = [ funcSameType ++ " () " ++ (if argNums == [] then "_" else "ops") ++
- " q (" ++ ctrInput ++ ")"
- , " = Node q $ mapMaybe trimTree ["
- ] ++
- intersperse
- " ,"
- [ " " ++ funcNewType ++ " ops () Nothing a" ++ show i
- | i <- argNums] ++
- [ " ]"
- ]
- where
- argNums = [0 .. ((length $ ctrArgs ctr) - 1)]
- ctrS = show ctr
- ctrName = modPrefix ++ ctrS
- makeCtr vs = ctrName ++ concatMap (" " ++) vs
- ctrInput = makeCtr ["a" ++ show i | i <- argNums]
- ctrResult = makeCtr ["r" ++ show i | i <- argNums]
-
-
- -- | An instance that describes how to apply -- or not apply -- a
- -- transformation.
- otherInst :: Data s => Int -> Set.Set Int -> s -> Int -> [String]
- otherInst wKey containedKeys c cKey
- = if not shouldGen then [] else
- genInst context
- ("((" ++ cName ++ ") -> a, r)")
- "ops"
- impl
- where
- cName = show $ typeOf c
- (shouldGen, context, impl)
- -- This type might contain the type that the transformation acts
- -- upon
- | cKey `Set.member` containedKeys
- = (True
- ,[contextSameType "r" ("((" ++ cName ++ ") -> a, ops)")]
- ,[if wKey == cKey
- then funcSameType ++ " (f, rest) ops _ v = "
- ++ funcSameType ++ " rest (f, ops) (Just (f v)) v"
- else funcSameType ++ " (f, rest) ops = " ++ funcSameType ++ " rest (f, ops)"])
- -- This type can't contain the transformed type; just move on to the
- -- next transformation.
- | genOverlapped == GenWithoutOverlapped
- = (True
- ,[contextSameType "r" "ops"]
- ,[funcSameType ++ " (_, rest) ops = " ++ funcSameType ++ " rest ops"])
- -- This is covered by one big overlapping instance:
- | otherwise = (False,[],[])
-
-
-
-- | Generates all the given instances (eliminating any duplicates)
-- with the given options. The return is a pair of a list of instances of PolyplateMRoute,
-- and a list of instances of PolyplateSpine
genInstances :: GenOverlappedOption -> GenClassOption -> [GenInstance] ->
- IO ([String], [String])
+ IO [String]
genInstances op1 op2 insts
= do typeMap <- flip execStateT Map.empty (sequence [g | GenInstance g <- insts])
- let (inst, spineInst) = unzip [
- (instancesFrom op1 op2 (justBoxes typeMap) w
- ,spineInstancesFrom op1 op2 (justBoxes typeMap) w)
- | DataBox w <- map witness $ justBoxes typeMap]
+ let inst = [instancesFrom op1 op2 (justBoxes typeMap) w
+ | DataBox w <- map witness $ justBoxes typeMap]
inst' <- sequence inst
- spineInst' <- sequence spineInst
- return (concat inst', concat spineInst')
+ return $ concat inst'
-- | Generates the instances according to the options and writes it to stdout with
-- the given header (the header is a list of lines without newline characters).
writeInstances :: GenOverlappedOption -> GenClassOption -> [GenInstance] -> [String] -> IO ()
writeInstances op1 op2 inst header
- = do (instLines, spineInstLines) <- genInstances op1 op2 inst
- putStr (unlines (header ++ instLines ++ spineInstLines))
-
--- | Generates the instances according to the options and writes the PolyplateMRoute
--- instances with the first header (the header is a list of lines without newline characters)
--- to the first filename, and the PolyplateSpine instances with the second header
--- to the second filename.
-writeInstancesToSep :: GenOverlappedOption -> GenClassOption -> [GenInstance] -> ([String],
- [String]) -> (FilePath, FilePath) -> IO ()
-writeInstancesToSep op1 op2 inst (header1, header2) (fileName1, fileName2)
- = do (instLines, spineInstLines) <- genInstances op1 op2 inst
- writeFile fileName1 (unlines (header1 ++ instLines))
- writeFile fileName2 (unlines (header2 ++ spineInstLines))
+ = do instLines <- genInstances op1 op2 inst
+ putStr (unlines (header ++ instLines))
-- | Generates the instances according to the options and writes it to a file with
-- the given header (the header is a list of lines without newline characters).
writeInstancesTo :: GenOverlappedOption -> GenClassOption -> [GenInstance] -> [String]
-> FilePath -> IO ()
writeInstancesTo op1 op2 inst header fileName
- = do (instLines, spineInstLines) <- genInstances op1 op2 inst
- writeFile fileName (unlines (header ++ instLines ++ spineInstLines))
+ = do instLines <- genInstances op1 op2 inst
+ writeFile fileName (unlines (header ++ instLines))
--{{{ Various SYB-based functions that we don't export, for discovering contained types:
diff --git a/polyplate/Data/Generics/Polyplate/Schemes.hs b/polyplate/Data/Generics/Polyplate/Schemes.hs
index e2e7c35..ac9f489 100644
--- a/polyplate/Data/Generics/Polyplate/Schemes.hs
+++ b/polyplate/Data/Generics/Polyplate/Schemes.hs
@@ -19,8 +19,7 @@ with this program. If not, see .
module Data.Generics.Polyplate.Schemes where
-import Data.Maybe
-import Data.Tree
+import Control.Monad.State
import Data.Generics.Polyplate
import Data.Generics.Polyplate.Route
@@ -81,52 +80,17 @@ makeCheckM ops f v
descend = makeDescend ops
-}
--- * Query functions that return rose-trees of results
-
--- | Given a query function that turns all items of type \"s\" into results of
--- type \"a\", applies the function to every instance of \"s\" inside a larger
--- structure of type \"t\", and gives the resulting values of type \"a\" back in
--- a rose-tree. A node in the tree will be generated for every constructor in
--- the larger item (of type \"t\"). If the constructor was of type \"s\", the
--- corresponding tree node will contain Just (the result of the query function).
--- If the constructor was any other type, the corresponding tree node will contain
--- Nothing.
---
--- Also note that the result is trimmed. If a particular sub-tree has no items
--- of the target type, instead of getting a whole sub-tree with Nothing values,
--- you will get one node (at the top of the sub-tree) with a Nothing value. This
--- is to make the traversal more efficient, in terms of time and space.
-applyQuery :: PolyplateSpine t (OneOpQ a s) () a => (s -> a) -> t -> Tree (Maybe a)
-applyQuery qf = transformSpine ops ()
- where
- ops = baseOp `extOpQ` qf
-
--- | As 'applyQuery', but takes two query functions that act on different types
--- (\"sA\" and \"sB\") but return the same result type (\"a\").
-applyQuery2 :: PolyplateSpine t (TwoOpQ a sA sB) () a => (sA -> a) -> (sB -> a) -> t -> Tree (Maybe a)
-applyQuery2 qfA qfB = transformSpine ops ()
- where
- ops = baseOp `extOpQ` qfA `extOpQ` qfB
-
-- * Listify functions that return lists of items that satisfy given criteria
-- | Given a function that examines a type \"s\" and gives an answer (True to include
-- the item in the list, False to drop it), finds all items of type \"s\" in some
-- larger item (of type \"t\") that satisfy this function, listed in depth-first
-- order.
-listifyDepth :: PolyplateSpine t (OneOpQ (Maybe s) s) () (Maybe s) => (s -> Bool) -> t -> [s]
-listifyDepth qf = catMaybes . flatten . fmap (fromMaybe Nothing) . transformSpine ops ()
+listifyTopDown :: (PolyplateM t (OneOpM (State [s]) s) () (State [s])
+ ,PolyplateM s () (OneOpM (State [s]) s) (State [s])) => (s -> Bool) -> t -> [s]
+listifyTopDown qf = flip execState [] . applyBottomUpM qf'
where
- qf' x = if qf x then Just x else Nothing
- ops = baseOp `extOpQ` qf'
-
--- | As 'listifyDepth', but the returned list is in breadth-first order.
-listifyBreadth :: PolyplateSpine t (OneOpQ (Maybe s) s) () (Maybe s) => (s -> Bool) -> t -> [s]
-listifyBreadth qf = catMaybes . (concat . levels) . fmap (fromMaybe Nothing) . transformSpine ops ()
- where
- qf' x = if qf x then Just x else Nothing
- ops = baseOp `extOpQ` qf'
-
+ qf' x = if qf x then modify (x:) >> return x else return x
-- * Check functions to apply monadic checks throughout a data structure
@@ -136,23 +100,19 @@ listifyBreadth qf = catMaybes . (concat . levels) . fmap (fromMaybe Nothing) . t
--
-- This can be used, for example, to perform checks on items in an error monad,
-- or to accumulate information in a state monad.
-checkDepthM :: (Monad m, PolyplateSpine t (OneOpQ (m ()) s) () (m ())) => (s -> m ()) -> t -> m ()
-checkDepthM f = sequence_ . catMaybes . flatten . applyQuery f
+checkDepthM :: (Monad m, PolyplateM t (OneOpM m s) () m
+ , PolyplateM s () (OneOpM m s) m) => (s -> m ()) -> t -> m ()
+checkDepthM f x = applyBottomUpM (\x -> f x >> return x) x >> return ()
-- | As 'checkDepthM', but takes two functions (one operating on type \"r\", the
-- other on type \"s\").
-checkDepthM2 :: (Monad m, PolyplateSpine t (TwoOpQ (m ()) r s) () (m ())) =>
+checkDepthM2 :: (Monad m, PolyplateM t (TwoOpM m r s) () m
+ , PolyplateM r () (TwoOpM m r s) m
+ , PolyplateM s () (TwoOpM m r s) m
+ ) =>
(r -> m ()) -> (s -> m ()) -> t -> m ()
-checkDepthM2 f g = sequence_ . catMaybes . flatten . applyQuery2 f g
-
--- | As 'checkDepthM', but applies the checks in breadth-first order.
-checkBreadthM :: (Monad m, PolyplateSpine t (OneOpQ (m ()) s) () (m ())) => (s -> m ()) -> t -> m ()
-checkBreadthM f = sequence_ . catMaybes . concat . levels . applyQuery f
-
--- | As 'checkDepthM2', but applies the checks in breadth-first order.
-checkBreadthM2 :: (Monad m, PolyplateSpine t (TwoOpQ (m ()) r s) () (m ())) =>
- (r -> m ()) -> (s -> m ()) -> t -> m ()
-checkBreadthM2 f g = sequence_ . catMaybes . concat . levels . applyQuery2 f g
+checkDepthM2 f g x = applyBottomUpM2 (\x -> f x >> return x)
+ (\y -> g y >> return y) x >> return ()
-- * Functions to easily apply transformations throughout a data structure
diff --git a/pregen/GenNavAST.hs b/pregen/GenNavAST.hs
index 08bf12f..435c1db 100644
--- a/pregen/GenNavAST.hs
+++ b/pregen/GenNavAST.hs
@@ -31,8 +31,8 @@ import qualified Errors
main :: IO ()
main = do
- [instFileName, spineInstFileName] <- getArgs
- writeInstancesToSep GenWithOverlapped GenClassPerType
+ [instFileName] <- getArgs
+ writeInstancesTo GenWithOverlapped GenOneClass
[ genInstance (undefined :: AST.AST)
, genInstance (undefined :: CompState.CompState)
-- All the maps that are in CompState:
@@ -48,8 +48,8 @@ main = do
, genSetInstance (undefined :: AST.Name)
, genSetInstance (undefined :: CompState.NameAttr)
]
- (header False (findModuleName instFileName), header True (findModuleName spineInstFileName))
- (instFileName, spineInstFileName)
+ (header False (findModuleName instFileName))
+ instFileName
where
findModuleName moduleFileName
| not (".hs" `isSuffixOf` moduleFileName)
diff --git a/transformations/SimplifyAbbrevs.hs b/transformations/SimplifyAbbrevs.hs
index fece9c6..096d046 100644
--- a/transformations/SimplifyAbbrevs.hs
+++ b/transformations/SimplifyAbbrevs.hs
@@ -263,7 +263,7 @@ abbrevCheckPass
checkNotWritten (A.Variable m n) "VAL-abbreviated variable % written-to inside the scope of the abbreviation"
sequence_ [checkNotWritten v
"Abbreviated variable % used inside the scope of the abbreviation"
- | A.ExprVariable _ v <- listifyDepth (const True) e]
+ | A.ExprVariable _ v <- listifyTopDown (const True) e]
pop
return s
doStructured s = descend s
@@ -288,7 +288,7 @@ abbrevCheckPass
checkAbbreved v@(A.Variable {}) msg = checkNone v msg
checkAbbreved v@(A.DirectedVariable {}) msg = checkNone v msg
checkAbbreved (A.SubscriptedVariable _ sub v) msg
- = sequence_ [checkNotWritten subV msg | subV <- listifyDepth (const True) sub]
+ = sequence_ [checkNotWritten subV msg | subV <- listifyTopDown (const True) sub]
checkNone :: A.Variable -> String -> StateT [Map.Map Var Bool] PassM ()
checkNone v msg