-- -- (c) Susumu Katayama -- \begin{code} module MagicHaskeller.ClassLib(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.Classify import MagicHaskeller.Instantiate import MagicHaskeller.Expression import MagicHaskeller.T10 import MagicHaskeller.DebMT traceTy _ = id -- traceTy fty = trace ("lookup "++ show fty) type BF = Recomp -- type BF = DBound type BFM = Matrix -- type BFM = DBMemo fromMemo :: Search m => Matrix a -> m a fromMemo = fromMx toMemo :: Search m => m a -> Matrix a toMemo = toMx newtype ClassLib e = CL (MemoDeb e) type MemoTrie a = MapType (BFM (Possibility a)) lmt mt fty = traceTy fty $ lookupMT mt fty lookupFunsPoly :: (Search m, Expression e) => Generator m e -> Generator m e lookupFunsPoly behalf memodeb@(mt,_,cmn) reqret = PS (\subst mx -> let (tn, decoder) = encode 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 reqret) subst mx) ) -- 条件によって再計算したいときはuncommentすべし。メモりは食わないはずなので、常にmemoizeで問題ないはず。 type MemoDeb a = (MemoTrie a, [[Prim]], Common) mkCL :: Expression e => Common -> [Typed [CoreExpr]] -> ClassLib e mkCL cmn classes = CL $ mkTrieMD [map annotateTCEs classes] cmn mkTrieMD :: (Expression e) => [[Prim]] -> Common -> MemoDeb e mkTrieMD qtl cmn = let trie = mkMT (tcl cmn) (\ty -> fromRc (freezePS ty (mguFuns memoDeb ty))) memoDeb = (trie,qtl,cmn) in memoDeb -- moved from DebMT.lhs to avoid cyclic modules. freezePS :: (Search m, Expression e) => Type -> PriorSubsts m (Bag e) -> m (Possibility e) freezePS ty ps = let mxty = maxVarID ty -- `max` maximum (map maxVarID avail) in mergesortDepthWithBy (\(xs,k,i) (ys,_,_) -> (xs `mappend` ys, k, i)) (\(_,k,_) (_,l,_) -> k `compare` l) $ fps mxty ps fps :: (Search m, Expression e) => TyVar -> PriorSubsts m [e] -> m ([e],[(TyVar, Type)],TyVar) fps mxty (PS f) = do (es, sub, m) <- f emptySubst (mxty+1) 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 ] -- note that the assoc list is NOT sorted. type Generator m e = MemoDeb e -> Type -> PriorSubsts m [e] mguPrograms, mguFuns :: (Search m, Expression e) => Generator m e mguPrograms memodeb ty = do subst <- getSubst lookupFunsPoly mguFuns memodeb (apply subst ty) mguFuns memodeb = generateFuns mguPrograms memodeb -- MemoDebの型が違うと使えない. generateFuns :: (Search m, Expression e) => Generator m e -- ^ recursive call -> Generator m e generateFuns rec memodeb@(_mt, primmono,cmn) reqret = let clbehalf = error "generateFuns: cannot happen." behalf = rec memodeb lltbehalf = error "generateFuns: cannot happen." lenavails = 0 in mapSum (retPrimMono cmn lenavails clbehalf lltbehalf behalf mguPS reqret) primmono \end{code}