descript-lang-0.2.0.0: src/Descript/BasicInj/Traverse.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
-- | Abstracts traversals over source ASTs.
module Descript.BasicInj.Traverse
( module Descript.BasicInj.Traverse.Termed
, TTerm
, Traversal (..)
, Fold (..)
, Mapping (..)
, travTerm
, foldTerm
, mapTerm
) where
import Descript.BasicInj.Traverse.Termed
import Descript.BasicInj.Traverse.Term (TTerm)
import qualified Descript.BasicInj.Traverse.Term as T
import qualified Descript.BasicInj.Data.Value.Reg as Reg
import qualified Descript.BasicInj.Data.Value.In as In
import qualified Descript.BasicInj.Data.Value.Out as Out
import Descript.BasicInj.Data
import Data.Functor.Identity
import Control.Monad ((<=<))
import Control.Monad.Trans.Writer.Strict
import Prelude hiding (mod)
newtype FoldTrav a = FoldTrav a
newtype MappingTrav a = MappingTrav a
class (Monad (Eff f)) => Traversal f where
type Eff f :: * -> *
type TAnn f :: *
tonTerm :: TTerm t -> f -> t (TAnn f) -> Eff f (t (TAnn f))
tonTerm _ _ = pure
class (Monoid (Res f)) => Fold f where
type Res f :: *
type FAnn f :: *
fonTerm :: TTerm t -> f -> t (FAnn f) -> Res f
fonTerm _ _ = mempty
class Mapping f where
type MAnn f :: *
monTerm :: TTerm t -> f -> t (MAnn f) -> t (MAnn f)
monTerm _ _ = id
instance (Fold f) => Traversal (FoldTrav f) where
type Eff (FoldTrav f) = Writer (Res f)
type TAnn (FoldTrav f) = FAnn f
tonTerm term (FoldTrav t) x = x <$ tell (fonTerm term t x)
instance (Mapping f) => Traversal (MappingTrav f) where
type Eff (MappingTrav f) = Identity
type TAnn (MappingTrav f) = MAnn f
tonTerm term (MappingTrav t) = Identity . monTerm term t
travTerm :: (Traversal f) => TTerm t -> f -> t (TAnn f) -> Eff f (t (TAnn f))
travTerm term t = travSubTerm term t <=< tonTerm term t
foldTerm :: (Fold f) => TTerm t -> f -> t (FAnn f) -> Res f
foldTerm term t = execWriter . travTerm term (FoldTrav t)
mapTerm :: (Mapping f) => TTerm t -> f -> t (MAnn f) -> t (MAnn f)
mapTerm term t = runIdentity . travTerm term (MappingTrav t)
travSubTerm :: (Traversal f) => TTerm t -> f -> t (TAnn f) -> Eff f (t (TAnn f))
travSubTerm T.Source t (SourceModule mod)
= SourceModule <$> travTerm T.BModule t mod
travSubTerm T.Source t (SourceProgram prog)
= SourceProgram <$> travTerm T.Program t prog
travSubTerm T.Program t (Program ann mod query')
= Program ann <$> travTerm T.BModule t mod <*> travTerm T.Query t query'
travSubTerm T.BModule t (BModule ann ictx amod)
= BModule ann <$> travTerm T.ImportCtx t ictx <*> travTerm T.AModule t amod
travSubTerm T.AModule t (AModule ann recordCtx' reduceCtx')
= AModule ann
<$> travTerm T.RecordCtx t recordCtx'
<*> travTerm T.ReduceCtx t reduceCtx'
travSubTerm T.ImportCtx t (ImportCtx ann mdecl idecls)
= ImportCtx ann
<$> travTerm T.ModuleDecl t mdecl
<*> traverse (travTerm T.ImportDecl t) idecls
travSubTerm T.RecordCtx t (RecordCtx ann records)
= RecordCtx ann <$> traverse (travTerm T.RecordDecl t) records
travSubTerm T.ReduceCtx t (ReduceCtx ann topCtx lowCtxs)
= ReduceCtx ann
<$> travTerm T.PhaseCtx t topCtx
<*> traverse (travTerm T.PhaseCtx t) lowCtxs
travSubTerm T.PhaseCtx t (PhaseCtx ann reducers)
= PhaseCtx ann <$> traverse (travTerm T.Reducer t) reducers
travSubTerm T.Query t (Query ann val) = Query ann <$> travTerm T.RegValue t val
travSubTerm T.ModuleDecl t (ModuleDecl ann path)
= ModuleDecl ann <$> travTerm T.ModulePath t path
travSubTerm T.ImportDecl t (ImportDecl ann path isrcs idsts)
= ImportDecl ann
<$> travTerm T.ModulePath t path
<*> traverse (travTerm T.ImportRecord t) isrcs
<*> traverse (travTerm T.ImportRecord t) idsts
travSubTerm T.RecordDecl t (RecordDecl ann recordType)
= RecordDecl ann <$> travTerm T.RecordType t recordType
travSubTerm T.Reducer t (Reducer ann input' output')
= Reducer ann <$> travTerm T.Input t input' <*> travTerm T.Output t output'
travSubTerm T.ModulePath t (ModulePath ann xs)
= ModulePath ann <$> traverse (travTerm T.ModulePathElem t) xs
travSubTerm T.ImportRecord t (ImportRecord ann from to)
= ImportRecord ann
<$> travTerm T.RecordHead t from
<*> travTerm T.RecordHead t to
travSubTerm T.RecordType t (RecordType ann head' properties')
= RecordType ann
<$> travTerm T.RecordHead t head'
<*> traverse (travTerm T.PropertyKey t) properties'
travSubTerm T.RegValue t (Value ann parts)
= travTerm T.GenValue t
=<< Value ann <$> traverse (travTerm T.RegPart t) parts
travSubTerm T.Input t (Value ann parts)
= travTerm T.GenValue t
=<< Value ann <$> traverse (travTerm T.InPart t) parts
travSubTerm T.Output t (Value ann parts)
= travTerm T.GenValue t
=<< Value ann <$> traverse (travTerm T.OutPart t) parts
travSubTerm T.GenValue _ x = pure x
travSubTerm T.RegPart t (Reg.PartPrim prim)
= Reg.PartPrim <$> travTerm T.Prim t prim
travSubTerm T.RegPart t (Reg.PartRecord record)
= Reg.PartRecord <$> travTerm T.RegRecord t record
travSubTerm T.InPart t (In.PartPrim prim)
= In.PartPrim <$> travTerm T.Prim t prim
travSubTerm T.InPart t (In.PartPrimType primType)
= In.PartPrimType <$> travTerm T.PrimType t primType
travSubTerm T.InPart t (In.PartRecord record)
= In.PartRecord <$> travTerm T.InRecord t record
travSubTerm T.OutPart t (Out.PartPrim prim)
= Out.PartPrim <$> travTerm T.Prim t prim
travSubTerm T.OutPart t (Out.PartRecord record)
= Out.PartRecord <$> travTerm T.OutRecord t record
travSubTerm T.OutPart t (Out.PartPropPath path)
= Out.PartPropPath <$> travTerm T.PropPath t path
travSubTerm T.OutPart t (Out.PartInjApp app)
= Out.PartInjApp <$> travTerm T.InjApp t app
travSubTerm T.Prim _ x = pure x
travSubTerm T.PrimType _ x = pure x
travSubTerm T.RegRecord t (Record ann head' properties')
= travTerm T.GenRecord t
=<< Record ann head' <$> traverse (travTerm T.RegProperty t) properties'
travSubTerm T.InRecord t (Record ann head' properties')
= travTerm T.GenRecord t
=<< Record ann head' <$> traverse (travTerm T.InProperty t) properties'
travSubTerm T.OutRecord t (Record ann head' properties')
= travTerm T.GenRecord t
=<< Record ann head' <$> traverse (travTerm T.OutProperty t) properties'
travSubTerm T.GenRecord t (Record ann head' properties')
= Record ann <$> travTerm T.RecordHead t head' <*> pure properties'
travSubTerm T.RegProperty t (Property ann key val)
= Property ann
<$> travTerm T.PropertyKey t key
<*> travTerm T.RegValue t val
travSubTerm T.InProperty t (Property ann key val)
= Property ann
<$> travTerm T.PropertyKey t key
<*> In.traverseOptVal (travTerm T.Input t) val
travSubTerm T.OutProperty t (Property ann key val)
= Property ann
<$> travTerm T.PropertyKey t key
<*> travTerm T.Output t val
travSubTerm T.GenProperty _ x = pure x
travSubTerm T.PropPath t (PropPath ann elems)
= PropPath ann <$> traverse (travTerm T.PathElem t) elems
travSubTerm T.PathElem t (PathElem ann propKey' headKey')
= PathElem ann
<$> travTerm T.PropertyKey t propKey'
<*> travTerm T.RecordHead t headKey'
travSubTerm T.InjApp t (Out.InjApp ann funcId' params')
= Out.InjApp ann funcId'
<$> traverse (Out.traverseInjParamVal $ travTerm T.Output t) params'
travSubTerm T.ModulePathElem _ x = pure x
travSubTerm T.RecordHead _ x = pure x
travSubTerm T.PropertyKey _ x = pure x