Subversion

ptable

[/] [Synthesis.hs] - Rev 8

Compare with Previous - Blame


{-# OPTIONS -fglasgow-exts #-}
-- | The synthesis part of the \"periodic table\".
module Synthesis where

import qualified Data.Map as Map
import Control.Monad
import Control.Monad.Error
import Language.Haskell.Pretty
import Language.Haskell.Syntax

import Language.Pointwise.Pretty

import Data.Transform.Type
import Data.Transform.RulesPF
import Dynamics

import PTable
import Analysis
import FunctorOf
import Matching
import PType
import Pf2Pw

-- | Combine two genes into a function that you can insert into the ptable.
-- Gives an identifier if there is already a definition of a function using
-- both genes or maybe a new function to insert (Nothing if the genes are incompatible).
combine :: IdGene -> IdGene -> String -> String -> PTable -> Either IdFunction (ErrorS Function)
combine idal idca fname fcom pt =
        case (lookupByGenes idal idca pt) of
           Right idf -> Left idf
           Left _  -> Right $ do
                compatible idal idca pt
                idfc <- getAlg idal pt >>= return . gfunctor
                return (Function fcom fname idfc idal idca)

mkDynHylo :: IdGene -> IdGene -> PTable -> ErrorS DynHylo
mkDynHylo idalg idcoalg pt = do
        alg <- getAlg idalg pt
        coalg <- getCoAlg idcoalg pt
        when (gfunctor alg /= gfunctor coalg) $ throwError $ "Algebra "++show idalg++" and co-algebra "++show idcoalg++" do not share the same functor"
        DynPF (fd `Func` fb) from <- return $ transf alg
        DynPF (fa `Func` fc) to <- return $ transf coalg
        DynPF (fb' `Func` b) galg <- return $ gene alg
        DynPF (a `Func` fa') gcoalg <- return $ gene coalg
        Eq <- teq fa' fa
        Eq <- teq fb' fb
        return $ DynHylo ((a `Func` b,fc,fd),COMP fb galg from,COMP fa to gcoalg)

mapff :: Type fa -> Type fb -> String -> Type (a -> b) -> PFctr -> Maybe DynPF
mapff fa fb name (a `Func` b) PId = do
        Eq <- teq fa a
        Eq <- teq fb b
        return $ DynPF (a `Func` b) (FUN name undefined)
mapff fa fb name (a `Func` b) (PK (PVar v)) = do
        Eq <- teq fa fb
        return $ DynPF (fa `Func` fb) ID
mapff fa fb name (a `Func` b) (PK pt) = do
        DynType t <- ptype2type pt
        Eq <- teq fa t
        Eq <- teq fb t
        return $ DynPF (t `Func` t) ID
mapff (fa `Either` ga) (fb `Either` gb) name (a `Func` b) (f ::+:: g) = do
	DynPF (fa' `Func` fb') ff <- mapff fa fb name (a `Func` b) f
        DynPF (ga' `Func` gb') gf <- mapff ga gb name (a `Func` b) g
        return $ DynPF ((fa' `Either` ga') `Func` (fb' `Either` gb')) (ff `SUM` gf)
mapff (fa `Prod` ga) (fb `Prod` gb) name (a `Func` b) (f ::*:: g) = do
	DynPF (fa' `Func` fb') ff <- mapff fa fb name (a `Func` b) f
        DynPF (ga' `Func` gb') gf <- mapff ga gb name (a `Func` b) g
        return $ DynPF ((fa' `Prod` ga') `Func` (fb' `Prod` gb')) (ff `PROD` gf)
mapff _ _ _ _ _ = mzero

{-- | Combine two genes into a pointfree hylomorphism
mkhylo :: IdGene -> IdGene -> PTable -> Maybe PF.Term
mkhylo idal idca pt =
     do	al <- Map.lookup idal (algebras pt)
        ca <- Map.lookup idca (coalgebras pt)
        guard (gfunctor al == gfunctor ca)		-- match the functors
        fc <- Map.lookup (gfunctor al) (functors pt)
        let res = Hylo (Mu (funct fc)) (gene al) (gene ca)
--	guard (isJust (PF.infer res))			 -- go hs-plugins
        return res
-}

-- | Expand a function definition as the corresponding pointfree term, by combining its genes.
expandPF :: Function -> PTable -> ErrorS DynPF
expandPF f pt = do
        DynHylo ((t, fa, fb), gc, ga) <- mkDynHylo (algebra f) (coalgebra f) pt
        pfc <- getFunctor (ffunctor f) pt >>= return . funct
        DynPF (fa' `Func` fb') ff <- liftMaybe $ mapff fa fb (fname f) t pfc
        Eq <- teq fa' fa
        Eq <- teq fb' fb
        return $ DynPF t (COMP fb gc (COMP fa ff ga))

-- | Expand a function by it's identifier.
expandPFById :: IdFunction -> PTable -> ErrorS DynPF
expandPFById idf pt =
     do fn <- Map.lookup idf (functions pt)
        expandPF fn pt

-- | Expand a function definition as the corresponding pointwise term, by combining its genes.
expandPW :: Function -> PTable -> ErrorS HsExp
expandPW f pt = do
        DynPF t pf <- expandPF f pt
        return $ pw2hs $ pf2pw pf

-- | Expand a function by it's identifier.
expandPWById :: IdFunction -> PTable -> ErrorS HsExp
expandPWById idf pt =
     do fn <- Map.lookup idf (functions pt)
        expandPW fn pt

Theme by Vikram Singh | Powered by WebSVN v1.61