module MagicHaskeller.MemoToFiles where
import System.IO
import System.Directory(doesFileExist, createDirectoryIfMissing)
import MagicHaskeller.ShortString
import Data.ByteString.Char8 as C
import Data.ByteString.Lazy.Char8 as LC
import Control.Monad.Search.Combinatorial
import MagicHaskeller.DebMT
import MagicHaskeller.Types
import MagicHaskeller.PriorSubsts
import Data.Monoid
import Data.Ix
freezePS :: Search m => Type -> PriorSubsts m (Bag e) -> m (Possibility e)
freezePS ty ps
= let mxty = maxVarID ty
in mergesortDepthWithBy (\(xs,k,i) (ys,_,_) -> (xs `mappend` ys, k, i)) (\(_,k,_) (_,l,_) -> k `compare` l) $ fps mxty ps
fps :: Search m => TyVar -> PriorSubsts m es -> m (es,[(TyVar, Type)],TyVar)
fps mxty (PS f) = do (exprs, sub, m) <- f emptySubst (mxty+1)
return (exprs, filterSubst sub mxty, m)
where filterSubst :: Subst -> TyVar -> [(TyVar, Type)]
filterSubst sub mx = [ t | t@(i,_) <- sub, inRange (0,mx) i ]
memoPSRTIO :: ShortString b =>
MemoCond
-> MapType (Matrix (Possibility b))
-> (Type -> PriorSubsts (RecompT IO) [b])
-> Type -> PriorSubsts (RecompT IO) [b]
memoPSRTIO policy mt f t = PS $ \subst mx ->
let (tn, decoder) = encode t mx
in (fmap (\ (exprs, sub, m) -> (exprs, retrieve decoder sub `plusSubst` subst, mx+m)) $ (memoRTIO policy (\ty depth -> return $ unMx (lookupMT mt ty) !! depth) (\u -> freezePS u (f u)) tn))
memoRTIO :: ShortString b =>
MemoCond
-> (Type -> Int -> IO [b])
-> (Type -> RecompT IO b)
-> Type -> RecompT IO b
memoRTIO policy lor f t = RcT $ memoer policy lor (\ty -> unRcT (f ty)) t
memoer :: ShortString b =>
MemoCond
-> (Type -> Int -> IO [b])
-> (Type -> Int -> IO [b])
-> Type -> Int -> IO [b]
memoer policy lor f ty depth
= do memotype <- policy ty depth
case memotype of Recompute -> compute
Ram -> lor ty depth
Disk fp | Prelude.length filepath < 250 -> do
createDirectoryIfMissing True directory
memoToFile readBriefly showBriefly filepath compute
| otherwise -> compute
where
directory = fp++shows depth "/"
filepath = directory ++ show ty
where compute = f ty depth
data MemoType = Recompute
| Ram
| Disk FilePath
type MemoCond = Type -> Int -> IO MemoType
memoToFile :: (C.ByteString -> Maybe a)
-> (a -> LC.ByteString)
-> FilePath
-> IO a
-> IO a
memoToFile parser printer filepath compute
= let write = do result <- compute
LC.writeFile filepath (printer result)
return result
in do there <- doesFileExist filepath
if there then do cs <- C.readFile filepath
case parser cs of Just x -> return x
_ -> do
System.IO.hPutStrLn stderr ("File " ++ filepath ++ " was broken.")
write
else write