{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverlappingInstances #-}
module Control.Search.Memo where
import Control.Monatron.Monatron hiding (Abort, L, state, cont)
import Control.Monatron.Zipper hiding (i,r)
import Control.Monatron.IdT
import Control.Monatron.MonadInfo
import Data.List (sort, nub, sortBy)
import Data.Maybe (fromJust)
import Data.Map (Map)
import qualified Data.Map as Map
import Control.Search.Language
import Control.Search.GeneratorInfo
import Control.Search.SStateT
data MemoKey = MemoKey { memoFn :: String, memoInfo :: Maybe Info, memoStack :: Maybe String, memoExtra :: Maybe (Map Int String), memoStatement :: Maybe Statement, memoParams :: [String] }
deriving (Eq, Ord)
data MemoValue = MemoValue { memoId :: Int, memoCode :: Statement, memoUsed :: Int, memoFields :: [(String,String)] }
data MemoInfo = MemoInfo { memoMap :: Map MemoKey MemoValue
, memoCount :: Int
, memoRead :: Map Int String
}
initMemoInfo = MemoInfo { memoMap = Map.empty
, memoCount = 0
, memoRead = Map.empty
}
newtype MemoT m a = MemoT { unMemoT :: SStateT MemoInfo m a }
deriving (MonadT,StateM MemoInfo,FMonadT)
instance MonadInfoT MemoT where
tminfo x = miInc "MemoT" (minfo $ runMemoT x)
runMemoT m = do (Tup2 a s) <- runSStateT initMemoInfo (unMemoT m)
return (a, sortBy (\(ka,va) (kb,vb) -> compare (memoId va) (memoId vb)) $ Map.toList (memoMap s)
)
class Monad m => MemoM m where
getMemo :: m MemoInfo
setMemo :: MemoInfo -> m ()
instance Monad m => MemoM (MemoT m) where
getMemo = MemoT $ get
setMemo = MemoT . put
instance (MemoM m, FMonadT t) => MemoM (t m) where
getMemo = lift $ getMemo
setMemo = lift . setMemo