-- Please, see the file LICENSE for copyright and license information.
>
% -----------------------------------------------------------------------------
% Interfaces for manipulating hylomorphisms and its components.
% -----------------------------------------------------------------------------
> module HFusion.Internal.HyloFace(
> CHylo(..)
> , Algebra, Acomponent(..), Psi(..), Psii(..), Phii, OutF(..), InF(..), Etai(..), TupleTerm(..)
> , Tau(..), TauTerm(..), TermWrapper(..), Sigma(..), PatternS(..), WrappedCA(..)
> , ParaFunctor(..), EtaOp(..), HFunctor(..), HyloFunctor, Position, WrapTau(..)
> , unwrapA, foldTWM, foldTau, foldPF, foldPFM, foldTW, getRecIndex, mapStructure, getVars
> , getTerm, setTerm, getPosition, getPositions, rightCompose, leftCompose, compose
> , composeEta, idEta, expanded, mapTau, mapTW, mapTWacc, wrapA, isRec
> , runFusionState, FusionState, FusionError(..)
> , mapTWaccM, expandPositions, remapPositions, isIdEta, tupleterm
> , getTupletermsWithArgIndexes, makePosNR, OutFi(..)
> , CoalgebraTerm(..), HasComponents(..), Coalgebra, TermWrappable(..)
> , module HFusion.Internal.HsSyn
> ) where
>
> import HFusion.Internal.HsSyn
> import HFusion.Internal.Utils
> import HFusion.Internal.HsPretty
> import HFusion.Internal.Parsing.HyloContext
> import Data.List(find)
> import HFusion.Internal.Messages
> import Control.Monad.Error
> import Control.Monad.State
> import Language.Haskell.Syntax(SrcLoc(..))
>
>
> class CHylo hylo where
>
>
>
>
>
>
>
> buildHylo :: [Variable]
> -> [Term]
> -> FusionState [hylo Phii Psi]
>
>
>
> getAlgebra :: hylo a ca -> Algebra a
>
> setAlgebra :: Algebra a -> hylo b ca -> hylo a ca
>
> getEta :: hylo a ca -> Eta
>
> setEta :: Eta -> hylo a ca -> hylo a ca
>
> getCoalgebra :: hylo a ca -> Coalgebra ca
>
> setCoalgebra :: Coalgebra ca -> hylo a cb -> hylo a ca
>
> getContext :: hylo a ca -> Context
>
> setContext :: Context -> hylo a ca -> hylo a ca
>
> getName :: hylo a ca -> Variable
>
> setName :: Variable -> hylo a ca -> hylo a ca
>
> getFunctor :: hylo a ca -> HyloFunctor
>
> setFunctor :: HyloFunctor -> hylo a ca -> hylo a ca
>
>
>
> consHylo :: Algebra a -> [Etai] -> HyloFunctor -> Coalgebra ca -> hylo a ca
>
> type HyloFunctor = [HFunctor]
>
>
>
>
> type Algebra a = [Acomponent a]
>
>
>
> data Acomponent a = Acomp ([Boundvar],TermWrapper a)
>
> getVars :: Acomponent a -> [Boundvar]
> getVars (Acomp (vrs,_)) = vrs
>
> unwrapA :: Acomponent a -> TermWrapper a
> unwrapA (Acomp (_,a)) = a
>
> wrapA :: [Boundvar] -> TermWrapper a -> Acomponent a
> wrapA = curry Acomp
>
> type Phii = Term
>
>
>
>
>
>
> newtype InF = InF (Constructor,[Term])
>
>
> data Tau = Tauphi (Tau' Phii)
> | TauinF (Tau' InF)
> | Tautau (Tau' Tau)
> type Tau' a = TermWrapper (TauTerm (Acomponent a))
>
> class WrapTau a where
> wrapTau :: Tau' a -> Tau
> instance WrapTau Term where
> wrapTau = Tauphi
> instance WrapTau InF where
> wrapTau = TauinF
> instance WrapTau Tau where
> wrapTau = Tautau
>
> foldTau :: (Tau' Phii->b)->
> (Tau' InF->b)->
> (Tau' Tau->b)->Tau->b
> foldTau f1 _ _ (Tauphi t) = f1 t
> foldTau _ f2 _ (TauinF t) = f2 t
> foldTau _ _ f3 (Tautau t) = f3 t
>
> mapTau :: (Tau' Phii->Tau' Phii)->(Tau' InF->Tau' InF)->(Tau' Tau->Tau' Tau)->Tau->Tau
> mapTau f1 f2 f3 = foldTau (Tauphi .f1) (TauinF .f2) (Tautau .f3)
>
> data TauTerm a = Taucons Constructor [TauTerm a] a Etai
>
> | Tausimple Term
>
>
> | Taupair Term (TauTerm a)
>
>
>
>
> | Taucata (Term->Term) (TauTerm a)
>
>
>
>
> data TermWrapper a = TWcase Term [Pattern] [TermWrapper a]
>
>
>
> | TWeta (TermWrapper a) Etai
>
> | TWsimple a
>
> | TWacomp (Acomponent a)
>
> | TWbottom
>
>
> foldTW::(Term->[Pattern]->[b]->b)->(b->Etai->b)->(a->b)->(Acomponent a->b)->b->TermWrapper a->b
> foldTW f1 f2 f3 f4 f5 (TWcase t0 ps ts) = f1 t0 ps (map (foldTW f1 f2 f3 f4 f5) ts)
> foldTW f1 f2 f3 f4 f5 (TWeta a eta) = f2 (foldTW f1 f2 f3 f4 f5 a) eta
> foldTW _ _ f3 _ _ (TWsimple a) = f3 a
> foldTW _ _ _ f4 _ (TWacomp a) = f4 a
> foldTW _ _ _ _ f5 TWbottom = f5
>
> foldTWM :: Monad m => (Term->[Pattern]->[b]->m b)->(b->Etai->m b)->(a->m b)->(Acomponent a->m b)->m b->TermWrapper a->m b
> foldTWM f1 f2 f3 f4 f5 = foldTW (\t0 ps mbs->do bs<-sequence mbs; f1 t0 ps bs)
> (\mb eta->do b<-mb; f2 b eta)
> f3 f4 f5
>
> mapTW::(a->b)->TermWrapper a->TermWrapper b
> mapTW f = foldTW TWcase TWeta (TWsimple .f) (\a->TWacomp (wrapA (getVars a).mapTW f.unwrapA$ a)) TWbottom
>
> mapTWacc:: [Boundvar] -> ([Boundvar]->a->(c,TermWrapper b))->([c]->c)->c->TermWrapper a->(c,TermWrapper b)
> mapTWacc bvs f1 f2 f3 = foldTW (\t0 ps ->(\(cs',ts')->(f2 cs',TWcase t0 ps ts')).unzip)
> (\(c,tw) e-> (c,TWeta tw e))
> (f1 bvs)
> (\a->(\(c,tw)-> (c,TWacomp (wrapA (getVars a) tw))).mapTWacc (getVars a) f1 f2 f3.unwrapA$ a)
> (f3,TWbottom)
>
> mapTWaccM::Monad m => [Boundvar] -> ([Boundvar] -> a->m (c,TermWrapper b))->([c]->c)->c->TermWrapper a->m (c,TermWrapper b)
> mapTWaccM bvs f1 f2 f3 = foldTWM (\t0 ps ->(\(cs',ts')->return (f2 cs',TWcase t0 ps ts')).unzip)
> (\(c,tw) e-> return (c,TWeta tw e))
> (f1 bvs)
> (\a->do (c,tw)<-mapTWaccM (getVars a) f1 f2 f3.unwrapA$ a
> return (c,TWacomp (wrapA (getVars a) tw)))
> (return (f3,TWbottom))
Tipo para representar una coalgebra. Se da la variable de entrada el termino sobre el
case que divide en alternativas y las alternativas.
>
>
>
>
> type Coalgebra ca = ([Boundvar],[Term],ca)
>
>
> data WrappedCA = WCApsi (Coalgebra Psi)
> | WCAoutF (Coalgebra OutF)
> | WCAsigma (Coalgebra Sigma)
>
> class HasComponents a where
>
> getComponentTerms :: a -> [[TupleTerm]]
>
> renamePatternVars :: a -> VarGenState a
>
> wrapSigma :: Coalgebra a -> WrappedCA
>
>
>
> newtype Psi = Psi [Psii]
> deriving Show
> newtype Psii = Psii PsiiRep
> deriving Show
> type PsiiRep = ([Pattern],[TupleTerm])
>
>
>
> newtype OutF = OutF [OutFi]
>
>
>
> newtype OutFi = OutFc (Constructor,[Variable],[TupleTerm])
>
>
>
>
> newtype Sigma = Sigma ([Int],[[TupleTerm]],[[PatternS]],[Maybe [(Int,[Acomponent InF],[Etai],WrappedCA,Int->Term->Term)]])
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> data PatternS = PcaseS Variable Pattern PatternS
>
> | PcaseSana Int Variable Pattern PatternS
>
>
> | PcaseR Int Variable Constructor [Variable] [(PatternS,[Variable])]
>
>
>
>
>
>
> | Ppattern Variable Pattern
>
> | Pdone
>
> deriving (Show,Eq)
>
>
> type Eta = [Etai]
>
>
>
> newtype Etai = Etai ([EtaOp],[EtaOp])
>
> data EtaOp = EOid
>
> | EOgeneral [Boundvar] [Term]
>
> | EOsust [Variable] [Term] [Boundvar]
>
>
> | EOlet [Term] [Pattern] [Variable] [Term]
>
>
> leftCompose :: EtaOp -> Etai -> Etai
> leftCompose op e@(Etai (l,r)) = if isId op then e else Etai (op:l,r)
>
> rightCompose :: Etai -> EtaOp -> Etai
> rightCompose e@(Etai (l,r)) op = if isId op then e else Etai (l,op:r)
>
> compose :: Etai -> Etai -> Etai
> compose e1 (Etai ([],[])) = e1
> compose (Etai ([],[])) e2 = e2
> compose (Etai (l1,r1)) (Etai (l2,r2)) = Etai (l1++reverse r1,r2++reverse l2)
>
> composeEta :: Acomponent a -> Etai -> TermWrapper a
> composeEta a eta | isIdEta eta = TWacomp a
> | otherwise = TWeta (TWacomp a) eta
> infixl 3 `rightCompose`
> infixr 3 `leftCompose`
> infixr 2 `compose`
> infixr 2 `composeEta`
>
> idEta :: Etai
> idEta = Etai ([],[])
>
> isIdEta :: Etai -> Bool
> isIdEta (Etai ([],[])) = True
> isIdEta _ = False
> isId :: EtaOp -> Bool
> isId (EOsust [] _ _) = True
> isId (EOgeneral bv ts) = and (zipWith eq bv ts) && (length bv == length ts)
> where eq (Bvar bv) (Tvar v) = bv==v
> eq (Bvtuple _ bvs) (Ttuple _ ts) = and (zipWith eq bvs ts)
> eq (Bvar bv) (Ttuple _ [Tvar v]) = bv==v
> eq (Bvtuple _ [Bvar bv]) (Tvar v) = bv==v
> eq _ _ = False
> isId (EOlet [] _ _ _) = True
> isId EOid = True
> isId _ = False
>
>
> class CoalgebraTerm ca where
>
>
>
>
>
>
> getTerms :: ca -> [TupleTerm]
> setTerms :: [TupleTerm] -> ca -> ca
> getPatterns :: ca -> [Pattern]
>
> getPos :: ca -> Variable -> [Position]
> getPos ca v = map getPosition.filter (elem v.vars.getTerm).getTerms$ ca
>
>
> data TupleTerm = Tterm Term Position
> deriving (Eq,Show)
> type Position=Variable
> getPosition :: TupleTerm -> Position
> getPosition (Tterm _ p) = p
> getTerm :: TupleTerm -> Term
> getTerm (Tterm t _) = t
> setTerm :: Term -> TupleTerm -> TupleTerm
> setTerm t (Tterm _ p) = Tterm t p
>
>
> tupleterm :: Position -> Term -> TupleTerm
> tupleterm p t=Tterm t p
>
> getPositions :: [TupleTerm] -> Variable -> [Position]
> getPositions [] _ = []
> getPositions (tt:tts) v | elem v.vars.getTerm$ tt = getPosition tt:getPositions tts v
> | otherwise = getPositions tts v
>
>
> getTupletermsWithArgIndexes :: [TupleTerm] -> Variable -> [(TupleTerm,[Int])]
> getTupletermsWithArgIndexes [] _ = []
> getTupletermsWithArgIndexes (tt:tts) v =
> let tsi = filter (elem v.vars.fst)$ zip (termToRecList (getTerm tt)) [0..]
> in if null tsi then getTupletermsWithArgIndexes tts v
> else (tt,map snd tsi):getTupletermsWithArgIndexes tts v
> where termToRecList (Ttuple True ts) = ts
> termToRecList t = [t]
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> newtype HFunctor = HF [(Position,Int,ParaFunctor)]
> deriving Show
>
> data ParaFunctor = PFprod [ParaFunctor]
> | PFid Position
> | PFcnt Position
> deriving Show
>
> foldPF :: (Variable->b)->(Variable->b)->([b]->b)->ParaFunctor->b
> foldPF f1 _ _ (PFid v) = f1 v
> foldPF _ f2 _ (PFcnt v) = f2 v
> foldPF f1 f2 f3 (PFprod bvs) = f3 (map (foldPF f1 f2 f3) bvs)
>
> foldPFM :: Monad m => (Variable->m b)->(Variable->m b)->([b]->m b)->ParaFunctor->m b
> foldPFM f1 _ _ (PFid v) = f1 v
> foldPFM _ f2 _ (PFcnt v) = f2 v
> foldPFM f1 f2 f3 (PFprod bvs) = mapM (foldPFM f1 f2 f3) bvs >>= f3
> instance Vars ParaFunctor where
> vars = foldPF (:[]) (:[]) concat
>
>
>
> mapStructure :: Term -> Term -> ParaFunctor -> Term
> mapStructure f1 t2 = foldPF (const f1) (const t2) (Ttuple False)
>
> isRec :: HFunctor -> Position -> Bool
> isRec (HF vrs) p = any isR vrs
> where isR (p',_,bv) = p==p' && foldPF (const True) (const False) or bv || foldPF (==p) (const False) or bv
>
> getRecIndex :: HFunctor -> Position -> Maybe Int
> getRecIndex (HF vrs) p = fmap (\(_,i,_)->i)$ find (findPos p)$ vrs
> where findPos p (p',_,bv) = p==p' && foldPF (const True) (const False) or bv || foldPF (p==) (const False) or bv
>
> makePosNR :: [Position] -> HFunctor -> HFunctor
> makePosNR ps (HF vrs) = HF (mknr' ps vrs)
> where mknr' ps vrs = if any (\(v,_,_)->elem v ps) vrs
> then map (\t@(v,i,bv)-> if elem v ps then (v,i,foldPF PFcnt PFcnt PFprod bv) else t) vrs
> else mknr ps vrs
> mknr ps (h@(p,i,bv):vs) | any (flip elem ps) (vars bv) = (p,i,foldPF (mknrbv ps) PFcnt PFprod bv):vs
> | otherwise = h:mknr ps vs
> mknr _ [] = []
> mknrbv ps p | elem p ps = PFcnt p
> | otherwise = PFid p
>
>
> expandPositions :: [(ParaFunctor,Position)] -> HFunctor -> HFunctor
> expandPositions ps (HF vrs) = HF (map (exp ps) vrs)
> where exp ps (p,i,bv) = (p,i,foldPF (expbv ps) PFcnt PFprod bv)
> where expbv ps v = case find ((v==).snd) ps of
> Just (PFprod [],_) -> PFid v
> Just (pf,_) -> pf
> _ -> PFid v
>
> expanded :: HFunctor -> Position -> ParaFunctor
> expanded fnc@(HF vrs) p = case find (\(p',_,_)->p'==p) vrs of
> Just (_,_,PFprod []) -> PFcnt p
> Just (_,_,bv) -> bv
> _ | isRec fnc p -> PFid p
> | otherwise -> PFcnt p
>
> remapPositions :: [(Position,Int)] -> HFunctor -> HFunctor
> remapPositions idxs (HF vrs) =
> HF$ map (\o@(a,_,b)->maybe o (\i'->(a,i',b))$
> maybe (foldPF (flip lookup idxs) (const Nothing) findJust b) Just$
> lookup a idxs)
> vrs
> where findJust (Just a:_) = Just a
> findJust (_:as) = findJust as
> findJust _ = Nothing
===========================================================
Auxiliary definitions for fusion algorithms
===========================================================
>
>
> type FusionState a = ErrorT FusionError VarGenState a
>
>
>
> runFusionState :: VarGen -> FusionState a -> Either FusionError a
> runFusionState vg m = evalState (runErrorT m) vg
>
> data FusionError =
> NotSaturated Term
> | NotExpected Term
> | NotInF
> | NotOutF
> | NotTau
> | NotSigma
> | NotFound String
> | Msg String
> | ParserError SrcLoc String
> instance Error FusionError where
> noMsg = Msg "Generic message"
> strMsg = Msg
> instance Show FusionError where
> show (NotSaturated t) = not_Satured t
> show (NotExpected t) = not_Expected t
> show NotInF = not_InF_Term
> show NotOutF = not_OutF_Term
> show NotTau = right_Hylo_Not_Tau_Form
> show NotSigma = left_Hylo_Not_Sigma_Form
> show (NotFound s) = not_Found s
> show (Msg chrs) = error_Message chrs
> show (ParserError loc s) = showLoc loc ++ s
> where showLoc l = srcFilename l ++ "("++ show (srcLine l) ++ ","++ show (srcColumn l)++"): "
> class TermWrappable a where
> wrapTerm :: Term -> a
> instance TermWrappable Phii where
> wrapTerm = id
> instance TermWrappable InF where
> wrapTerm t = InF (" ",[t])
> instance TermWrappable Tau where
> wrapTerm t = wrapTau (TWsimple (Tausimple t::TauTerm (Acomponent Phii)))