content: 
  -- | General purpose tree walking boilerplate.
  module DDC.Core.Flow.Transform.TransformUpX
          ( TransformUpMX(..)
          , transformUpX
          , transformUpX'
  
            -- * Via the Simple AST
          , transformSimpleUpMX
          , transformSimpleUpX
          , transformSimpleUpX')
  where
  import DDC.Core.Exp.Annot
  import DDC.Core.Transform.TransformUpX  
  import DDC.Core.Flow.Transform.Annotate
  import DDC.Core.Flow.Transform.Deannotate
  import Data.Functor.Identity
  import DDC.Core.Env.EnvX                        (EnvX)
  import qualified DDC.Core.Flow.Exp.Simple.Exp   as S
  import qualified DDC.Core.Env.EnvX              as EnvX
  
  
  -- Simple ---------------------------------------------------------------------
  -- | Like `transformUpMX`, but the worker takes the Simple version of the AST.
  --
  --   * To avoid repeated conversions between the different versions of the AST,
  --     the worker should return `Nothing` if the provided expression is unchanged.
  transformSimpleUpMX 
          :: (Ord n, TransformUpMX m c, Monad m)
          => (EnvX n -> S.Exp a n -> m (Maybe (S.Exp a n)))
                          -- ^ The worker function is given the current
                          --     kind and type environments.
          -> EnvX n       -- ^ Initial type environment.
          -> c a n        -- ^ Transform thing thing.
          -> m (c a n)
  
  transformSimpleUpMX f env0 xx0
   = let  
          f' env xx
           = do   let a    = annotOfExp xx
                  let sxx  = deannotate (const Nothing) xx
                  msxx'    <- f env sxx
                  case msxx' of
                       Nothing   -> return $ xx
                       Just sxx' -> return $ annotate a sxx'
  
     in   transformUpMX f' env0 xx0
  
  
  -- | Like `transformUpX`, but the worker takes the Simple version of the AST.
  --
  --   * To avoid repeated conversions between the different versions of the AST,
  --     the worker should return `Nothing` if the provided expression is unchanged.
  transformSimpleUpX
          :: forall (c :: * -> * -> *) a n
          .  (Ord n, TransformUpMX Identity c)
          => (EnvX n -> S.Exp a n -> Maybe (S.Exp a n))
                          -- ^ The worker function is given the current
                          --     kind and type environments.
          -> EnvX n       -- ^ Initial type environment.
          -> c a n        -- ^ Transform this thing.
          -> c a n
  
  transformSimpleUpX f env xx
          = runIdentity 
          $ transformSimpleUpMX 
                  (\env' x -> return (f env' x)) env xx
  
  
  -- | Like `transformUpX'`, but the worker takes the Simple version of the AST.
  --
  --   * To avoid repeated conversions between the different versions of the AST,
  --     the worker should return `Nothing` if the provided expression is unchanged.
  transformSimpleUpX'
          :: forall (c :: * -> * -> *) a n
          .  (Ord n, TransformUpMX Identity c)
          => (S.Exp a n -> Maybe (S.Exp a n))
                          -- ^ The worker function is given the current
                          --      kind and type environments.
          -> c a n        -- ^ Transform this thing.
          -> c a n
  
  transformSimpleUpX' f xx
          = transformSimpleUpX (\_ -> f) EnvX.empty xx
  
  