{-# LANGUAGE Rank2Types, FlexibleContexts, ImplicitParams, GADTs, TypeOperators #-}---------------------------------------------------------------------------------- |-- Module : Data.Comp.Automata-- Copyright : (c) 2010-2012 Patrick Bahr-- License : BSD3-- Maintainer : Patrick Bahr <paba@diku.dk>-- Stability : experimental-- Portability : non-portable (GHC Extensions)---- This module defines stateful term homomorphisms. This (slightly-- oxymoronic) notion extends per se stateless term homomorphisms with-- a state that is maintained separately by a bottom-up or top-down-- state transformation. Additionally, this module also provides-- combinators to run state transformations themselves.-- -- Like regular term homomorphisms also stateful homomorphisms (as-- well as transducers) can be lifted to annotated signatures-- (cf. Data.Comp.Annotation").----------------------------------------------------------------------------------moduleData.Comp.Automata(-- * Stateful Term HomomorphismsQHom,below,above-- ** Bottom-Up State Propagation,upTrans,runUpHom,runUpHomSt-- ** Top-Down State Propagation,downTrans,runDownHom-- ** Bidirectional State Propagation,runQHom-- * Deterministic Bottom-Up Tree Transducers,UpTrans,runUpTrans,compUpTrans,compUpTransHom,compHomUpTrans,compUpTransSig,compSigUpTrans,compAlgUpTrans-- * Deterministic Bottom-Up Tree State Transformations-- ** Monolithic State,UpState,tagUpState,runUpState,prodUpState-- ** Modular State,DUpState,dUpState,upState,runDUpState,prodDUpState,(<*>)-- * Deterministic Top-Down Tree Transducers,DownTrans,runDownTrans,compDownTrans,compDownTransSig,compSigDownTrans,compDownTransHom,compHomDownTrans-- * Deterministic Top-Down Tree State Transformations-- ** Monolithic State,DownState,tagDownState,prodDownState-- ** Modular State,DDownState,dDownState,downState,prodDDownState,(>*<)-- * Bidirectional Tree State Transformations,runDState-- * Operators for Finite Mappings,(&),(|->),o-- * Product State Spaces,moduleData.Comp.Automata.Product)whereimportData.Comp.NumberimportData.Comp.Automata.ProductimportData.Comp.TermimportData.Comp.AlgebraimportData.Map(Map)importqualifiedData.MapasMap-- The following are operators to specify finite mappings.infix1|->infixr0&-- | left-biased union of two mappings.(&)::Ordk=>Mapkv->Mapkv->Mapkv(&)=Map.union-- | This operator constructs a singleton mapping.(|->)::k->a->Mapka(|->)=Map.singleton-- | This is the empty mapping.o::Mapkao=Map.empty-- | This function provides access to components of the states from-- "below".below::(?below::a->q,p:<q)=>a->pbelow=pr.?below-- | This function provides access to components of the state from-- "above"above::(?above::q,p:<q)=>pabove=pr?above-- | Turns the explicit parameters @?above@ and @?below@ into explicit-- ones.explicit::((?above::q,?below::a->q)=>b)->q->(a->q)->bexplicitxabbe=xwhere?above=ab;?below=be-- | This type represents stateful term homomorphisms. Stateful term-- homomorphisms have access to a state that is provided (separately)-- by a bottom-up or top-down state transformation function (or both).typeQHomfqg=foralla.(?below::a->q,?above::q)=>fa->Contextga-- -- | This type represents (pure, i.e. stateless) homomorphism by-- -- universally quantifying over the state type.-- type PHom f g = forall q . QHom f q g-- -- | This combinator runs a stateless homomorphism. (use-- -- 'Data.Comp.Algebra.appHom' instead).-- runPHom :: forall f g . (Functor f, Functor g) => PHom f g -> CxtFun f g-- runPHom hom = run where-- run :: CxtFun f g-- run (Hole x) = Hole x-- run (Term t) = appCxt (explicit () (const ()) hom (fmap run t))-- | This type represents transition functions of deterministic-- bottom-up tree transducers (DUTTs).typeUpTransfqg=foralla.f(q,a)->(q,Contextga)-- | This function transforms a DUTT transition function into an-- algebra.upAlg::(Functorg)=>UpTransfqg->Algf(q,Termg)upAlgtrans=fmapappCxt.trans-- | This function runs the given DUTT on the given term.runUpTrans::(Functorf,Functorg)=>UpTransfqg->Termf->TermgrunUpTranstrans=snd.runUpTransSttrans-- | This function is a variant of 'runUpTrans' that additionally-- returns the final state of the run.runUpTransSt::(Functorf,Functorg)=>UpTransfqg->Termf->(q,Termg)runUpTransSt=cata.upAlg-- | This function generalises 'runUpTrans' to contexts. Therefore,-- additionally, a transition function for the holes is needed.runUpTrans'::(Functorf,Functorg)=>UpTransfqg->Contextf(q,a)->(q,Contextga)runUpTrans'trans=runwhererun(Hole(q,a))=(q,Holea)run(Termt)=fmapappCxt$trans$fmaprunt-- | This function composes two DUTTs. (see TATA, Theorem 6.4.5)compUpTrans::(Functorf,Functorg,Functorh)=>UpTransgph->UpTransfqg->UpTransf(q,p)hcompUpTranst2t1x=((q1,q2),c2)where(q1,c1)=t1$fmap(\((q1,q2),a)->(q1,(q2,a)))x(q2,c2)=runUpTrans't2c1-- | This function composes a DUTT with an algebra.compAlgUpTrans::(Functorg)=>Algga->UpTransfqg->Algf(q,a)compAlgUpTransalgtrans=fmap(cata'alg).trans-- | This combinator composes a DUTT followed by a signature function.compSigUpTrans::(Functorg)=>SigFungh->UpTransfqg->UpTransfqhcompSigUpTranssigtransx=(q,appSigFunsigx')where(q,x')=transx-- | This combinator composes a signature function followed by a DUTT.compUpTransSig::UpTransgqh->SigFunfg->UpTransfqhcompUpTransSigtranssig=trans.sig-- | This combinator composes a DUTT followed by a homomorphism.compHomUpTrans::(Functorg,Functorh)=>Homgh->UpTransfqg->UpTransfqhcompHomUpTranshomtransx=(q,appHomhomx')where(q,x')=transx-- | This combinator composes a homomorphism followed by a DUTT.compUpTransHom::(Functorg,Functorh)=>UpTransgqh->Homfg->UpTransfqhcompUpTransHomtranshomx=runUpTrans'trans.hom$x-- | This type represents transition functions of deterministic-- bottom-up tree acceptors (DUTAs).typeUpStatefq=Algfq-- | Changes the state space of the DUTA using the given isomorphism.tagUpState::(Functorf)=>(q->p)->(p->q)->UpStatefq->UpStatefptagUpStateios=i.s.fmapo-- | This combinator runs the given DUTA on a term returning the final-- state of the run.runUpState::(Functorf)=>UpStatefq->Termf->qrunUpState=cata-- | This function combines the product DUTA of the two given DUTAs.prodUpState::Functorf=>UpStatefp->UpStatefq->UpStatef(p,q)prodUpStatespsqt=(p,q)wherep=sp$fmapfsttq=sq$fmapsndt-- | This function constructs a DUTT from a given stateful term-- homomorphism with the state propagated by the given DUTA.upTrans::(Functorf,Functorg)=>UpStatefq->QHomfqg->UpTransfqgupTransstft=(q,c)whereq=st$fmapfsttc=fmapsnd$explicitfqfstt-- | This function applies a given stateful term homomorphism with-- a state space propagated by the given DUTA to a term.runUpHom::(Functorf,Functorg)=>UpStatefq->QHomfqg->Termf->TermgrunUpHomsthom=snd.runUpHomStsthom-- | This is a variant of 'runUpHom' that also returns the final state-- of the run.runUpHomSt::(Functorf,Functorg)=>UpStatefq->QHomfqg->Termf->(q,Termg)runUpHomStalgh=runUpTransSt(upTransalgh)-- | This type represents transition functions of generalised-- deterministic bottom-up tree acceptors (GDUTAs) which have access-- to an extended state space.typeDUpStatefpq=foralla.(?below::a->p,?above::p,q:<p)=>fa->q-- | This combinator turns an arbitrary DUTA into a GDUTA.dUpState::Functorf=>UpStatefq->DUpStatefpqdUpStatef=f.fmapbelow-- | This combinator turns a GDUTA with the smallest possible state-- space into a DUTA.upState::DUpStatefqq->UpStatefqupStatefs=reswhereres=explicitfresids-- | This combinator runs a GDUTA on a term.runDUpState::Functorf=>DUpStatefqq->Termf->qrunDUpState=runUpState.upState-- | This combinator constructs the product of two GDUTA.prodDUpState::(p:<c,q:<c)=>DUpStatefcp->DUpStatefcq->DUpStatefc(p,q)prodDUpStatespsqt=(spt,sqt)(<*>)::(p:<c,q:<c)=>DUpStatefcp->DUpStatefcq->DUpStatefc(p,q)(<*>)=prodDUpState-- | This type represents transition functions of deterministic-- top-down tree transducers (DDTTs).typeDownTransfqg=foralla.(q,fa)->Contextg(q,a)-- | Thsis function runs the given DDTT on the given tree.runDownTrans::(Functorf,Functorg)=>DownTransfqg->q->Cxthfa->CxthgarunDownTranstrqt=run(q,t)whererun(q,Termt)=appCxt$fmaprun$tr(q,t)run(_,Holea)=Holea-- | This function runs the given DDTT on the given tree.runDownTrans'::(Functorf,Functorg)=>DownTransfqg->q->Cxthfa->Cxthg(q,a)runDownTrans'trqt=run(q,t)whererun(q,Termt)=appCxt$fmaprun$tr(q,t)run(q,Holea)=Hole(q,a)-- | This function composes two DDTTs. (see Z. Fulop, H. Vogler-- /Syntax-Directed Semantics/, Theorem 3.39)compDownTrans::(Functorf,Functorg,Functorh)=>DownTransgph->DownTransfqg->DownTransf(q,p)hcompDownTranst2t1((q,p),t)=fmap(\(p,(q,a))->((q,p),a))$runDownTrans't2p(t1(q,t))-- | This function composes a signature function after a DDTT.compSigDownTrans::(Functorg)=>SigFungh->DownTransfqg->DownTransfqhcompSigDownTranssigtrans=appSigFunsig.trans-- | This function composes a DDTT after a function.compDownTransSig::DownTransgqh->SigFunfg->DownTransfqhcompDownTransSigtranshom(q,t)=trans(q,homt)-- | This function composes a homomorphism after a DDTT.compHomDownTrans::(Functorg,Functorh)=>Homgh->DownTransfqg->DownTransfqhcompHomDownTranshomtrans=appHomhom.trans-- | This function composes a DDTT after a homomorphism.compDownTransHom::(Functorg,Functorh)=>DownTransgqh->Homfg->DownTransfqhcompDownTransHomtranshom(q,t)=runDownTrans'transq(homt)-- | This type represents transition functions of deterministic-- top-down tree acceptors (DDTAs).typeDownStatefq=foralla.Orda=>(q,fa)->Mapaq-- | Changes the state space of the DDTA using the given isomorphism.tagDownState::(q->p)->(p->q)->DownStatefq->DownStatefptagDownStateiot(q,s)=fmapi$t(oq,s)-- | This function constructs the product DDTA of the given two DDTAs.prodDownState::DownStatefp->DownStatefq->DownStatef(p,q)prodDownStatespsq((p,q),t)=prodMappq(sp(p,t))(sq(q,t))-- | This type is needed to construct the product of two DDTAs.dataProdStatepq=LStatep|RStateq|BStatepq-- | This function constructs the pointwise product of two maps each-- with a default value.prodMap::(Ordi)=>p->q->Mapip->Mapiq->Mapi(p,q)prodMappqmpmq=Map.mapfinal$Map.unionWithcombinepsqswhereps=Map.mapLStatempqs=Map.mapRStatemqcombine(LStatep)(RStateq)=BStatepqcombine(RStateq)(LStatep)=BStatepqcombine__=error"unexpected merging"final(LStatep)=(p,q)final(RStateq)=(p,q)final(BStatepq)=(p,q)-- | Apply the given state mapping to the given functorial value by-- adding the state to the corresponding index if it is in the map and-- otherwise adding the provided default state.appMap::Traversablef=>(foralli.Ordi=>fi->Mapiq)->q->fb->f(q,b)appMapqmapqs=fmapqfuns'wheres'=numbersqfunk@(Numbered(_,a))=(Map.findWithDefaultqk(qmaps'),a)-- | This function constructs a DDTT from a given stateful term---- homomorphism with the state propagated by the given DDTA.downTrans::Traversablef=>DownStatefq->QHomfqg->DownTransfqgdownTransstf(q,s)=explicitfqfst(appMap(currystq)qs)-- | This function applies a given stateful term homomorphism with a-- state space propagated by the given DDTA to a term.runDownHom::(Traversablef,Functorg)=>DownStatefq->QHomfqg->q->Termf->TermgrunDownHomsth=runDownTrans(downTranssth)-- | This type represents transition functions of generalised-- deterministic top-down tree acceptors (GDDTAs) which have access-- to an extended state space.typeDDownStatefpq=foralli.(Ordi,?below::i->p,?above::p,q:<p)=>fi->Mapiq-- | This combinator turns an arbitrary DDTA into a GDDTA.dDownState::DownStatefq->DDownStatefpqdDownStateft=f(above,t)-- | This combinator turns a GDDTA with the smallest possible state-- space into a DDTA.downState::DDownStatefqq->DownStatefqdownStatef(q,s)=reswhereres=explicitfqbelsbelk=Map.findWithDefaultqkres-- | This combinator constructs the product of two dependant top-down-- state transformations.prodDDownState::(p:<c,q:<c)=>DDownStatefcp->DDownStatefcq->DDownStatefc(p,q)prodDDownStatespsqt=prodMapaboveabove(spt)(sqt)-- | This is a synonym for 'prodDDownState'.(>*<)::(p:<c,q:<c,Functorf)=>DDownStatefcp->DDownStatefcq->DDownStatefc(p,q)(>*<)=prodDDownState-- | This combinator combines a bottom-up and a top-down state-- transformations. Both state transformations can depend mutually-- recursive on each other.runDState::Traversablef=>DUpStatef(u,d)u->DDownStatef(u,d)d->d->Termf->urunDStateupdownd(Termt)=uwheret'=fmapbel$numbertbel(Numbered(i,s))=letd'=Map.findWithDefaultd(Numbered(i,undefined))minNumbered(i,(runDStateupdownd's,d'))m=explicitdown(u,d)unNumberedt'u=explicitup(u,d)unNumberedt'-- | This combinator runs a stateful term homomorphisms with a state-- space produced both on a bottom-up and a top-down state-- transformation.runQHom::(Traversablef,Functorg)=>DUpStatef(u,d)u->DDownStatef(u,d)d->QHomf(u,d)g->d->Termf->(u,Termg)runQHomupdowntransd(Termt)=(u,t'')wheret'=fmapbel$numbertbel(Numbered(i,s))=letd'=Map.findWithDefaultd(Numbered(i,undefined))m(u',s')=runQHomupdowntransd'sinNumbered(i,((u',d'),s'))m=explicitdown(u,d)(fst.unNumbered)t'u=explicitup(u,d)(fst.unNumbered)t't''=appCxt$fmap(snd.unNumbered)$explicittrans(u,d)(fst.unNumbered)t'