--
-- (c) Susumu Katayama
--
\begin{code}
module MagicHaskeller.DebMT where
import MagicHaskeller.Types as Types
import MagicHaskeller.TyConLib
import Control.Monad
import Control.Monad.Search.Combinatorial
import MagicHaskeller.PriorSubsts
import Data.Array
import MagicHaskeller.T10((!?))
import Data.List(genericIndex)
import System.IO.Unsafe(unsafeInterleaveIO)
type Possibility e = (Bag e, Subst, TyVar)
data MapType a
= MT {
tvMT :: [a],
tcMT :: [a],
genMT :: [a],
taMT :: MapType (MapType a),
funMT :: MapType (MapType a)
}
lookupMT :: MapType a -> Type -> a
lookupMT mt (TV tv) = tvMT mt `genericIndex` tv
lookupMT mt (TC tc) | tc < 0 = genMT mt `genericIndex` (1tc)
| otherwise = tcMT mt `genericIndex` tc
lookupMT mt (TA t0 t1) = lookupMT (lookupMT (taMT mt) t0) t1
lookupMT mt (t0:->t1) = lookupMT (lookupMT (funMT mt) t0) t1
retrieve :: Decoder -> Subst -> Subst
retrieve deco sub = [ (decodeVar deco i, decode deco ty) | (i, ty) <- sub ]
decode :: Decoder -> Type -> Type
decode deco t = mapTV (decodeVar deco) t
decodeVar (Dec tvs margin) tv = case tvs !? tv of Nothing -> tv+margin
Just ntv -> ntv
encode :: Type -> TyVar -> (Type, Decoder)
encode = Types.normalizeVarIDs
mkMT :: TyConLib -> (Type->a) -> MapType a
mkMT tcl f = mkMT' tcl 0 f
mkMT' :: TyConLib -> Kind -> (Type->a) -> MapType a
mkMT' tcl k f = MT tvTree tcTree genTree taTree funTree where
tcs = snd tcl ! k
tvTree = [ f (TV i) | i <- [0..] ]
tcTree = [ f (TC i) | i <- [0..] ]
genTree = [ f (TC i) | i <- [1,2..] ]
taTree = mkMT' tcl (k+1) (\t0 -> mkMT tcl (\t1 -> f (TA t0 t1)))
funTree = if k==0 then mkMT tcl (\t0 -> mkMT tcl (\t1 -> f (t0 :-> t1))) else error "mkMT': the kind of functions must always be *"
mkMTIO :: TyConLib -> (Type -> IO a) -> IO (MapType a)
mkMTIO tcl f = mkMTIO' tcl 0 f
mkMTIO' :: TyConLib -> Kind -> (Type -> IO a) -> IO (MapType a)
mkMTIO' tcl k f = unsafeInterleaveIO $ liftM5 MT tvTree tcTree genTree taTree funTree where
tcs = snd tcl ! k
lazyf = unsafeInterleaveIO . f
tvTree = interleaveActions $ map (f . TV) [0..]
tcTree = interleaveActions $ map (f . TC) [0..]
genTree = interleaveActions $ map (f . TC) [1,2..]
taTree = mkMTIO' tcl (k+1) (\t0 -> mkMTIO tcl (\t1 -> lazyf (TA t0 t1)))
funTree = mkMTIO tcl $ if k==0 then (\t0 -> mkMTIO tcl (\t1 -> lazyf (t0 :-> t1))) else error "mkMTIO': the kind of functions must always be *"
interleaveActions :: [IO a] -> IO [a]
interleaveActions = foldr (\x xs -> unsafeInterleaveIO (Control.Monad.liftM2 (:) x xs)) (return []) . map unsafeInterleaveIO
\end{code}