--
-- (c) Susumu Katayama
--
\begin{code}
module MagicHaskeller.ProgGen(ProgGen(PG), mkCL, ClassLib(..), mguPrograms) where
import MagicHaskeller.Types
import MagicHaskeller.TyConLib
import Control.Monad
import Data.Monoid
import MagicHaskeller.CoreLang
import Control.Monad.Search.Combinatorial
import MagicHaskeller.PriorSubsts
import Data.List(partition, sortBy, genericLength)
import Data.Ix(inRange)
import MagicHaskeller.ProgramGenerator
import MagicHaskeller.Options(Opt(..))
import MagicHaskeller.Classify
import MagicHaskeller.Instantiate
import MagicHaskeller.Expression
import MagicHaskeller.T10
import qualified Data.Map as Map
import MagicHaskeller.DebMT
import Debug.Trace
import Data.Monoid
import MagicHaskeller.MemoToFiles hiding (freezePS,fps)
traceTy _ = id
type BF = Recomp
type BFM = Matrix
fromMemo :: Search m => Matrix a -> m a
fromMemo = fromMx
toMemo :: Search m => m a -> Matrix a
toMemo = toMx
newtype ProgGen = PG (MemoDeb (ClassLib CoreExpr) CoreExpr)
newtype ClassLib e = CL (MemoDeb (ClassLib e) e)
type MemoTrie a = MapType (BFM (Possibility a))
lmt mt fty =
traceTy fty $
lookupMT mt fty
lookupFunsShared :: (Search m) => Generator m CoreExpr -> Generator m CoreExpr
lookupFunsShared behalf memodeb@(_,mt,_,cmn) avail reqret
= let annAvails = zip [0..] avail
in PS (\subst mx -> fromRc $ Rc $ \d ->concat [ let (tn, decoder) = encode (popArgs newavails reqret) mx in map (decodeVarsPos ixs) $ map (\ (exprs, sub, m) -> (exprs, retrieve decoder sub `plusSubst` subst, mx+m)) $ unMx (lmt mt tn) !! d | annAvs <- combs (d+1) annAvails, let (ixs, newavails) = unzip annAvs ] :: [Possibility CoreExpr])
lookupFunsPoly :: (Search m, Expression e) => Generator m e -> Generator m e
lookupFunsPoly behalf memodeb@(_,mt,_,cmn) avail reqret
= PS (\subst mx ->
let (tn, decoder) = encode (popArgs avail reqret) mx
in ifDepth (<= memodepth (opt cmn))
(fmap (\ (exprs, sub, m) -> (exprs, retrieve decoder sub `plusSubst` subst, mx+m)) $ fromMemo $ lmt mt tn)
(unPS (behalf memodeb avail reqret) subst mx) )
instance WithCommon ProgGen where
extractCommon (PG (_,_,_,cmn)) = cmn
instance ProgramGenerator ProgGen where
mkTrie cmn classes tces = mkTriePG cmn classes tces
unifyingPrograms ty (PG x@(_,_,_,cmn)) = fromRc $ fmap (toAnnExpr $ reducer cmn) $ catBags $ fmap (\ (es,_,_) -> es) $ unifyingPossibilities ty x
instance ProgramGeneratorIO ProgGen where
mkTrieIO cmn classes tces = return $ mkTriePG cmn classes tces
unifyingProgramsIO ty (PG x@(_,_,_,cmn)) = fmap (toAnnExpr $ reducer cmn) $ catBags $ fmap (\ (es,_,_) -> es) $ unifyingPossibilitiesIO ty x
unifyingPossibilities :: Search m => Type -> MemoDeb (ClassLib CoreExpr) CoreExpr -> m ([CoreExpr],Subst,TyVar)
unifyingPossibilities ty memodeb = unPS (mguProgs memodeb [] ty) emptySubst 0
unifyingPossibilitiesIO :: Type -> MemoDeb (ClassLib CoreExpr) CoreExpr -> RecompT IO ([CoreExpr],Subst,TyVar)
unifyingPossibilitiesIO ty memodeb = unPS (mguProgsIO memodeb [] ty) emptySubst 0
type MemoDeb c a = (c, MemoTrie a, ([[Prim]],[[Prim]]), Common)
mkTriePG :: Common -> [Typed [CoreExpr]] -> [[Typed [CoreExpr]]] -> ProgGen
mkTriePG cmn classes tces = let qtl = splitPrimss tces
trie = mkTrieMD (mkCL cmn classes) qtl cmn
in PG trie
mkCL :: Common -> [Typed [CoreExpr]] -> ClassLib CoreExpr
mkCL cmn classes = CL $ mkTrieMD undefined ([],[map annotateTCEs classes]) cmn
mkTrieMD :: ClassLib CoreExpr -> ([[Prim]],[[Prim]]) -> Common -> MemoDeb (ClassLib CoreExpr) CoreExpr
mkTrieMD cl qtl cmn
= let trie = mkMT (tcl cmn) (\ty -> fromRc (let (avail,t) = splitArgs ty in freezePS (length avail) ty (mguFuns memoDeb avail t )))
memoDeb = (cl,trie,qtl,cmn)
in memoDeb
freezePS :: Search m => Int -> Type -> PriorSubsts m (Bag CoreExpr) -> m (Possibility CoreExpr)
freezePS arity ty ps
= let mxty = maxVarID ty
in mergesortDepthWithBy (\(xs,k,i) (ys,_,_) -> (xs `mappend` ys, k, i)) (\(_,k,_) (_,l,_) -> k `compare` l) $ fps arity mxty ps
fps :: Search m => Int -> TyVar -> PriorSubsts m [CoreExpr] -> m ([CoreExpr],[(TyVar, Type)],TyVar)
fps arity mxty (PS f) = do
(exprs, sub, m) <- f emptySubst (mxty+1)
let es = filter (not . isAbsent arity) exprs
guard $ not $ length es `seq` null es
return (es, filterSubst sub mxty, m)
where filterSubst :: Subst -> TyVar -> [(TyVar, Type)]
filterSubst sub mx = [ t | t@(i,_) <- sub, inRange (0,mx) i ]
type Generator m e = MemoDeb (ClassLib e) e -> [Type] -> Type -> PriorSubsts m [e]
mguProgramsIO, mguProgsIO :: Generator (RecompT IO) CoreExpr
mguProgramsIO memodeb = applyDo (mguProgsIO memodeb)
mguProgsIO memodeb@(_,mt,_,cmn) = wind (>>= (return . fmap Lambda)) (\avail reqret -> reorganize (\newavail -> (\memodeb avail reqr -> memoPSRTIO (memoCond $ opt cmn)
mt
(\ty -> let (av,rr) = splitArgs ty in generateFuns mguProgramsIO memodeb av rr)
(popArgs avail reqr)) memodeb newavail reqret) avail)
mguPrograms, mguProgs :: (Search m) => Generator m CoreExpr
mguFuns :: (Search m) => Generator m CoreExpr
mguPrograms memodeb = applyDo (mguProgs memodeb)
mguProgs memodeb = wind (>>= (return . fmap (mapCE Lambda))) (lookupFunsShared mguFuns memodeb)
mguFuns memodeb = generateFuns mguPrograms memodeb
generateFuns :: (Search m) =>
Generator m CoreExpr
-> Generator m CoreExpr
generateFuns rec memodeb@(CL classLib, _mt, (primgen,primmono),cmn) avail reqret
= let clbehalf = mguPrograms classLib []
behalf = rec memodeb avail
lltbehalf = lookupListrie (opt cmn) rec memodeb avail
lenavails = genericLength avail
fe = filtExprs (guess $ opt cmn)
rg = if tv0 $ opt cmn then retGenTV0 else
if tv1 $ opt cmn then retGenTV1 else retGen
in fromAssumptions cmn lenavails behalf mguPS reqret avail `mplus` mapSum (rg cmn lenavails fe clbehalf lltbehalf behalf reqret) primgen `mplus` mapSum (retPrimMono cmn lenavails clbehalf lltbehalf behalf mguPS reqret) primmono
lookupListrie opt rec memodeb avail t
| guess opt = do args <- rec memodeb avail t
let args' = filter (not.isClosed.toCE) args
when (null args') mzero
return args'
| otherwise = do args <- rec memodeb avail t
let args' = filter (not.isConstrExpr.toCE) args
when (null args') mzero
return args'
\end{code}