-- Please, see the file LICENSE for copyright and license information.
% -----------------------------------------------------------------------------
% $Id: FuseFace.lhs,v 1.32 2006/06/21 17:04:41 fdomin Exp $
%
% Se presenta aqui la interfaz del tipo HyloT que representa hilomorfimos de
% cualquier tipo.
%
% -----------------------------------------------------------------------------
> module HFusion.Internal.FuseFace(
> fusionar,
> fusionarTau,
> fusionarSigma,
> getCata,
> getAna,
> HyloT,
> showHT,
> deriveHylo,
> inline,
> getConstantArgCount,
> getNames,
> renameHT,
> WrapHT(..),WrapHA(..)
> )
> where
> import HFusion.Internal.HyloRep
> import HFusion.Internal.Parsing.HyloContext
> import qualified HFusion.Internal.FunctorRep as F
> import qualified HFusion.Internal.Inline as I
> import Control.Monad.Error(throwError,catchError)
> import Control.Monad.Trans(lift)
> import Control.Monad.State(get)
> import List((\\))
> import HFusion.Internal.RenVars
> import HFusion.Internal.Utils
> import HFusion.Internal.Messages
import Debug.Trace
sss s v = trace (s++": "++show v) v
> data HyloT = HTp (HA Phii)
> | HTi (HA InF)
> | HTt (HA Tau)
> showHT :: HyloT -> VarGenState String
> showHT h = do i<-get;return$ foldHT (show' i False) (show' i False) (show' i True) h
> where show' i t h=foldHA (show'' i t) (show'' i t) (show'' i t) h
> show'' i t hss@(h:hs) = (names ++)$ concat $ (I.showHylo t i h :) $
> map ("\n------------------------------\n"++)$ map (I.showHylo t i) hs
> where names=tuple (map getName hss)
> tuple [] = "()"
> tuple (n:ns) = '(': show n ++ concat (map ((',':).show) ns) ++ ") =\n"
> show'' _ t _ = ""
> data HA a = HAp [Hylo a Psi]
> | HAs [Hylo a Sigma]
> | HAo [Hylo a OutF]
> foldHT :: (HA Phii->b)->(HA InF->b)->(HA Tau->b)->HyloT->b
> foldHT f1 f2 f3 (HTp a) = f1 a
> foldHT f1 f2 f3 (HTi a) = f2 a
> foldHT f1 f2 f3 (HTt a) = f3 a
> foldHA :: ([Hylo a Psi]->b)->([Hylo a OutF]->b)->([Hylo a Sigma]->b)->HA a->b
> foldHA f1 f2 f3 (HAp a) = f1 a
> foldHA f1 f2 f3 (HAo a) = f2 a
> foldHA f1 f2 f3 (HAs a) = f3 a
> class WrapHA ca where
> wrapHA :: [Hylo a ca] -> HA a
> instance WrapHA Psi where
> wrapHA h = HAp h
> instance WrapHA OutF where
> wrapHA h = HAo h
> instance WrapHA Sigma where
> wrapHA h = HAs h
> class WrapHT a where
> wrapHT :: HA a -> HyloT
> instance WrapHT Term where
> wrapHT = HTp
> instance WrapHT InF where
> wrapHT = HTi
> instance WrapHT Tau where
> wrapHT = HTt
> getNames :: HyloT -> [Variable]
> getNames = foldHT gn gn gn
> where gn = foldHA (map getName) (map getName) (map getName)
> getConstantArgCount :: HyloT -> Int
> getConstantArgCount = length . foldHT gn gn gn
> where gn = head . foldHA (map (getConstantArgs.getContext)) (map (getConstantArgs.getContext)) (map (getConstantArgs.getContext))
> getRecArgCount :: HyloT -> Int -> Int
> getRecArgCount h i = foldHT gn gn gn h
> where gn = (!!i) . foldHA (map getRecArgs) (map getRecArgs) (map getRecArgs)
> getRecArgs = (\(bvs,_,_)->length bvs) . getCoalgebra
> getConstantArgPos :: HyloT -> Maybe [Int]
> getConstantArgPos = foldHT gn gn gn
> where gn = head . foldHA (map (getCntArgPos.getContext)) (map (getCntArgPos.getContext)) (map (getCntArgPos.getContext))
> renameHT :: HyloT -> HyloT -> FusionState (HyloT,HyloT)
> renameHT h1 h2 = foldHT (renh1 h2) (renh1 h2) (renh1 h2) h1
> where renh1 h2 h1 = foldHA (ren h2) (ren h2) (ren h2) h1
> ren h2 h1 = foldHT (renh2 h1) (renh2 h1) (renh2 h1) h2
> renh2 h1 h2 = foldHA (ren' h1) (ren' h1) (ren' h1) h2
> ren' [h1] [h2] = do (h1',h2')<-lift (renameVariables h1 h2 [])
> return (wrapHT.wrapHA$ [h1'],wrapHT.wrapHA$ [h2'])
> ren' _ _ = error "Mutual recursion not handled."
> deriveHylo :: [Def] -> FusionState HyloT
> deriveHylo dfs = let (ctxs,vs,ts)=unzip3$ map (\(ctx,Defvalue v t)-> (ctx,v,t))$ extractContext$ dfs
> in buildHylo vs ts >>= (return.wrapHT.wrapHA.zipWith setContext ctxs)
> fusionar :: [Variable] -> HyloT -> Int -> Int -> HyloT -> Int -> FusionState (Int,HyloT)
> fusionar names h1 ih1 ia' h2 ih2 =
>
> do h1' <- lift (inline h1) >>= deriveHylo
> h2' <- lift (inline h2) >>= deriveHylo
> fusionar' names h1' ih1 (ia h1' ih1) h2' ih2
> where ia'' = maybe (ia'getConstantArgCount h1) (length.([0..ia'1]\\))$ getConstantArgPos h1
> ia h1 ih1 = max 0 (min (getRecArgCount h1 ih11) ia'')
> fusionar' :: [Variable] -> HyloT -> Int -> Int -> HyloT -> Int -> FusionState (Int,HyloT)
> fusionar' names h1 ih1 ia h2 ih2 = foldHT (fuseh1 h2) (fuseh1 h2) (fuseh1 h2) h1
> where
> fuseh1 h2 h1 = foldHA (fusePsi h2) (fuseCata h2) (fuseSigma h2) h1
> errorTau _ = throwError NotTau
> fuseCata h2 h1 = foldHT (fuseCataHylo h1) (fuseCataAna h1) errorTau h2
> fusePsi h2 h1 = foldHT (fusePsiPhii h1) (fuseHyloAna h1) errorTau h2
> fuseSigma h2 h1 = foldHT (fuseSigmaPhii h1) (fuseSigmaAna h1) errorTau h2
> fuseCataHylo h1 h2 = let f h2 i2 = fusionarOutF names h1 ih1 h2 i2
> in foldHA f f f h2 ih2
> fuseCataAna h1 h2 = let f h2 i2 = F.fusionarSimple h1 ih1 h2 i2 >>= wrapHylos
> in foldHA f f f h2 ih2
> fusePsiPhii h1 h2 = let f h1=fusionarAmbos names h1 ih1 ia
> in foldHA (f h1) (f h1) (f h1) h2 ih2
> fuseHyloAna h1 h2 = let f h1=fusionarInF names h1 ih1 ia
> in foldHA (f h1) (f h1) (f h1) h2 ih2
> fuseSigmaAna h1 h2 = let f h1 h2=F.fusionarSigma h1 ih1 ia h2 ih2 >>= wrapHylos
> in foldHA (f h1) (f h1) (f h1) h2
> fuseSigmaPhii h1 h2 = let f h1 h2 = do h2' <- mapM (F.getAna h2) h2
> F.fusionarSigma h1 ih1 ia h2' ih2>>=wrapHylos
> in foldHA (f h1) (f h1) (f h1) h2
> wrapHylos (m,h) = do vs<-sequence $ replicate (length hlength names) (lift (getFreshVar "v"))
> return (m,wrapHT.wrapHA.zipWith setName (names++vs)$ h)
> fusionarTau :: [Variable] -> HyloT -> Int -> HyloT -> Int -> FusionState (Int,HyloT)
> fusionarTau names h1 ih1 h2 ih2 = foldHT (fuseh1 h2) (fuseh1 h2) (fuseh1 h2) h1
> where
> fuseh1 h2 h1 = foldHA errorh1 (fuseCata h2) errorh1 h1
> errorh1 _ = throwError (Msg first_Hylo_Not_OutF_Form)
> errorh2 _ = throwError (Msg second_Hylo_Not_Phi_Form)
> fuseCata h2 h1 = foldHT (fuseCataHylo h1) errorh2 errorh2 h2
> fuseCataHylo h1 h2 = let f h1 h2=do res<-lift$ F.fusionarTau h1 ih1 h2 ih2;wrapHylos res
> in foldHA (f h1) (f h1) (f h1) h2
> wrapHylos (m,h) = do vs<-sequence $ replicate (length hlength names) (lift$ getFreshVar "v")
> return (m,wrapHT.wrapHA.zipWith setName (names++vs)$ h)
> fusionarSigma :: [Variable] -> HyloT -> Int -> Int -> HyloT -> Int -> FusionState (Int,HyloT)
> fusionarSigma names h1 ih1 ia h2 ih2 = foldHT (fuseh1 h2) (fuseh1 h2) (fuseh1 h2) h1
> where
> fuseh1 h2 h1 = foldHA (fuseAna h2) errorh1 (fuseSigma h2) h1
> errorh1 _ = throwError (Msg first_Hylo_Not_Psi_Form)
> errorh2 _ = throwError (Msg second_Hylo_Not_InF_Form)
> fuseAna h2 h1 = foldHT errorh2 (fuseHyloAna h1) errorh2 h2
> fuseSigma h2 h1 = foldHT errorh2 (fuseSigmaAna h1) errorh2 h2
> fuseSigmaAna h1 h2 = let f h1 = F.fusionarSigma h1 ih1 ia
> in wrapHylos$ foldHA (f h1) (f h1) (f h1) h2 ih2
> fuseHyloAna h1 h2 = let f h1 h2 ih2 = do h1'<-F.psiToSigma h1
> F.fusionarSigma h1' ih1 ia h2 ih2
> in wrapHylos$ foldHA (f h1) (f h1) (f h1) h2 ih2
> wrapHylos res = do (m,h)<-res
> vs<-sequence $ replicate (length hlength names) (lift$ getFreshVar "v")
> return (m,wrapHT.wrapHA.zipWith setName (names++vs)$ h)
> getCata :: HyloT -> FusionState HyloT
> getCata h = foldHT f f f h
> where f h=foldHA f' (return.wrapHT.wrapHA) (\_->throwError NotInF) h
> f' h = do h'<-mapM (F.getCata h) h
> return.wrapHT.wrapHA$ h'
> getAna :: HyloT -> FusionState HyloT
> getAna h = foldHT f (return.wrapHT) (\_->throwError NotInF) h
> where f h=foldHA f' f' f' h
> f' h = do h'<-mapM (F.getAna h) h
> return.wrapHT.wrapHA$ h'
> wrapHylos :: (WrapHT a,WrapHA b) => [Variable] -> Int -> [Hylo a b] -> FusionState (Int,HyloT)
> wrapHylos names m h = do vs<-sequence $ replicate (length hlength names) (lift$ getFreshVar "v")
> return (m,wrapHT.wrapHA.zipWith setName (names++vs)$ h)
fusionarAmbos :: (WrapHT a,WrapHA b,HasComponents b,WrapTau a,Vars a, AlphaConvertible a,VarsB b, AlphaConvertible b, Vars b) =>
[Variable] -> [Hylo a Psi] -> Int -> Int -> [Hylo Phii b] -> Int -> FusionState (Int,HyloT)
> fusionarAmbos names h1 ih1 ia h2 ih2 = catchError (mapM (F.getCata h1) h1 >>= okCata) badCata
> where
> okCata h1' = catchError (mapM (F.getAna h2) h2 >>= okcataana h1') (okCataBadAna h1')
> badCata _ = catchError (mapM (F.getAna h2) h2 >>= badCataOkAna ) badCataBadAna
> okcataana h1' h2'= catchError (do h1''<-F.psiToSigma h1
> res<-F.fusionarSigma h1'' ih1 ia h2' ih2
> oksigma h1' h2' res)
> (badsigma h1' h2')
> oksigma h1' h2' (m3,hh3) =
> do (m1,hh1)<-F.fusionarSimple h1' ih1 h2' ih2
> (m2,hh2)<-lift$ F.fusionarTau h1' ih1 h2 ih2
> if m1>=m2
> then if m1>=m3 then wrapHylos names m1 hh1
> else wrapHylos names m3 hh3
> else if m2>=m3 then wrapHylos names m2 hh2
> else wrapHylos names m3 hh3
> okCataBadAna h1' _ = do (m2,hh2)<-lift (F.fusionarTau h1' ih1 h2 ih2); wrapHylos names m2 hh2
> badCataOkAna h2' = do h1''<-F.psiToSigma h1
> (m3,hh3)<-F.fusionarSigma h1'' ih1 ia h2' ih2; wrapHylos names m3 hh3
> badCataBadAna _ = throwError (Msg couldnt_Fuse_Hylos)
> badsigma h1' h2' _ = do (m1,hh1)<-F.fusionarSimple h1' ih1 h2' ih2
> (m2,hh2)<-lift$ F.fusionarTau h1' ih1 h2 ih2
> if m1>=m2
> then wrapHylos names m1 hh1
> else wrapHylos names m2 hh2
> fusionarOutF :: (WrapHT a,WrapHA b,HasComponents b,TermWrappable a, WrapTau a,Vars b, AlphaConvertible b, VarsB b,VarsB a,Vars a, AlphaConvertible a) =>
> [Variable] -> [Hylo a OutF] -> Int -> [Hylo Phii b] -> Int -> FusionState (Int,HyloT)
> fusionarOutF names h1 ih1 h2 ih2 = catchError (mapM (F.getAna h2) h2 >>= okcataana) okCataBadAna
> where
> okcataana h2'= do (m1,hh1)<-F.fusionarSimple h1 ih1 h2' ih2
> (m2,hh2)<-lift$ F.fusionarTau h1 ih1 h2 ih2
> if m1>=m2
> then wrapHylos names m1 hh1
> else wrapHylos names m2 hh2
> okCataBadAna _ = do (m2,hh2)<-lift$ F.fusionarTau h1 ih1 h2 ih2; wrapHylos names m2 hh2
fusionarInF :: (WrapHT a,WrapHA b,HasComponents b,WrapTau a,AlphaConvertible a, Vars a,Vars b, AlphaConvertible b, VarsB b) =>
[Variable] -> [Hylo a Psi] -> Int -> Int -> [Hylo InF b] -> Int -> FusionState (Int,HyloT)
> fusionarInF names h1 ih1 ia h2 ih2 = catchError (mapM (F.getCata h1) h1 >>= okCata) badCata
> where
> okCata h1' = catchError (do h1''<-F.psiToSigma h1
> res<-F.fusionarSigma h1'' ih1 ia h2 ih2
> oksigma h1' res)
> (badsigma h1')
> oksigma h1' (m2,hh2)=
> do (m1,hh1)<-F.fusionarSimple h1' ih1 h2 ih2
> if m1>=m2
> then wrapHylos names m1 hh1
> else wrapHylos names m2 hh2
> badCata _ = catchError (do h1''<- F.psiToSigma h1
> (m3,hh3)<-F.fusionarSigma h1'' ih1 ia h2 ih2
> wrapHylos names m3 hh3)
> error
> badsigma h1' _ = do (m3,hh3)<-F.fusionarSimple h1' ih1 h2 ih2; wrapHylos names m3 hh3
> error _ = throwError (Msg couldnt_Fuse_Hylos)
===================================================================================================================================
inline
===================================================================================================================================
> inline :: HyloT -> VarGenState [Def]
> inline hylo =
> foldHT f f f hylo
> where f h = foldHA g g g h
> g h = do dfs<-mapM (I.inline h) h
> return (mergeContext (zip (map getContext h) dfs))
inline :: HyloT -> VarGenState [Def]
inline hylo =
foldHT (trace "phi" f) (trace "inf" f) (trace "tau" f) hylo
where f h = foldHA (trace "psi" g) (trace "outF" g) (trace "sigma" g) h
g h = do dfs<-mapM (I.inline h) h
return (mergeContext (zip (map getContext h) dfs))