module UHC.Light.Compiler.CoreRun.Run.Val
( module System.IO
, module Data.IORef
, module Data.Int, module Data.Word
, module GHC.Ptr
, RVal (..)
, mkTuple, mkUnit
, RValV, RValMV
, HSMarshall (..)
, HpPtr, nullPtr, isNullPtr, newHeap, Heap (..)
, heapGetM, heapGetM', heapAllocM, heapAllocAsPtrM, heapUpdM, heapSetM, heapSetM'
, RValCxt (..), emptyRValCxt
, mustReturn, needNotReturn, rvalRetEvl, rvalPrimargEvl
, vecReverseForM_
, mvecAllocInit, mvecAlloc, mvecFillFromV, mvecFillFromMV, mvecAllocFillFromV, mvecAppend, mvecToList
, mvecReverseForM_
, ptr2valM, ref2valM
, RValEnv (..), newRValEnv
, renvTopFrameM
, dumpEnvM
, updTopFrameM
, renvFrStkPush1, renvFrStkReversePushMV
, renvFrStkPop1, renvFrStkPopMV, renvFrStkReversePopMV, renvFrStkReversePopInMV
, rsemTr', rsemTr
, RValT )
where
import UHC.Light.Compiler.Base.HsName.Builtin
import UHC.Light.Compiler.Base.Common
import UHC.Light.Compiler.Error
import UHC.Light.Compiler.CoreRun
import UHC.Light.Compiler.CoreRun.Run
import UHC.Light.Compiler.CoreRun.Pretty
import UHC.Util.Pretty
import Control.Monad.Primitive
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
import qualified Data.Vector.Generic as GV
import Data.Data
import Data.Typeable
import System.IO
import System.IO.Unsafe
import Data.IORef
import Data.Int
import Data.Word
import qualified Data.ByteString.Char8 as BSC8
import GHC.Ptr (Ptr (..))
import GHC.Exts (Addr#)
data RVal
=
RVal_Lit
{ rvalSExp :: !SExp
}
| RVal_Char !Char
| RVal_Int !Int
| RVal_Int32 !Int32
| RVal_Integer !Integer
| RVal_Float !Float
| RVal_Double !Double
| RVal_PackedString !BSC8.ByteString
| RVal_Lam
{ rvalBody :: !Exp
, rvalSLRef :: !(IORef HpPtr)
}
| RVal_Thunk
{ rvalBody :: !Exp
, rvalSLRef :: !(IORef HpPtr)
}
| RVal_Node
{ rvalTag :: !Int
, rvalNdVals :: !RValMV
}
| RVal_App
{ rvalFun :: !RVal
, rvalArgs :: !RValMV
}
| RVal_Frame
{ rvalRef2Nm :: Ref2Nm
, rvalSLRef :: !(IORef HpPtr)
, rvalLev :: !Int
, rvalFrVals :: !RValMV
, rvalFrSP :: !(IORef Int)
}
| RVal_Ptr
{ rvalPtrRef :: !(IORef HpPtr)
}
| RVal_Fwd
{ rvalPtr :: !HpPtr
}
| RVal_BlackHole
| RVal_None
| RHsV_MutVar !(IORef RVal)
| RHsV_Handle !Handle
| RHsV_Addr Addr#
instance Show RVal where
show _ = "RVal"
ppRVal' :: (HpPtr -> IO (Maybe RVal)) -> RVal -> IO PP_Doc
ppRVal' lkptr rval = case rval of
RVal_Lit e -> dfltpp e
RVal_Char v -> dfltpp $ show v
RVal_Int v -> dfltpp v
RVal_Int32 v -> dfltpp $ show v
RVal_Integer v -> dfltpp v
RVal_Float v -> dfltpp v
RVal_Double v -> dfltpp $ show v
RVal_PackedString v -> dfltpp $ show v
RVal_Lam b slref -> dfltpp b
RVal_Thunk e slref -> return $ ppBrackets e
RVal_Node t vs -> do
vl <- mvecToList vs
return $ t >|< ppBracketsCommas vl
RVal_App f as -> dfltpp f
RVal_Ptr pref -> do
p <- readIORef pref
vpp <- lkptr p >>= maybe (return empty) (\v -> ppRVal' lkptr v >>= \vpp -> return $ " -> " >|< vpp)
return $ "*" >|< p >|< vpp
RVal_Fwd p -> return $ "f*" >|< p
RVal_Frame _ slref lv vs spref -> do
sl <- readIORef slref
sp <- readIORef spref
vl <- mvecToList vs
vlpp <- forM (zip [0..(sp1)] vl) $ \(i,v) -> ppRVal' lkptr v >>= \vpp -> return $ i >|< ":" >#< vpp
return $ (ppBracketsCommas $ ["sl=" >|< sl, "lev=" >|< lv, "sz=" >|< MV.length vs, "sp=" >|< sp])
>-< vlist vlpp
RVal_BlackHole -> dfltpp "Hole"
RVal_None -> dfltpp "None"
RHsV_MutVar v -> dfltpp "MutVar"
RHsV_Handle h -> dfltpp $ show h
RHsV_Addr p -> dfltpp $ show (Ptr p)
where
dfltpp :: PP x => x -> IO PP_Doc
dfltpp = return . pp
ppRValWithHp :: Heap -> RVal -> IO PP_Doc
ppRValWithHp hp = ppRVal' (\p -> heapGetM'' hp p >>= (return . Just))
ppRVal :: RVal -> IO PP_Doc
ppRVal = ppRVal' (\_ -> return Nothing)
instance PP RVal where
pp rval = unsafePerformIO (ppRVal rval)
mkTuple :: (RunSem RValCxt RValEnv RVal m a) => [RVal] -> RValT m a
mkTuple vs = liftIO (mvecAllocFillFromV $ mkCRArray vs) >>= rsemNode 0 >>= rsemPush
mkUnit :: (RunSem RValCxt RValEnv RVal m a) => RValT m a
mkUnit = mkTuple []
type RValV = CRArray RVal
type RValMV = CRMArray RVal
class HSMarshall hs where
hsMarshall :: (RunSem RValCxt RValEnv RVal m a) => (RVal -> RValT m a) -> RVal -> RValT m hs
hsUnmarshall :: (RunSem RValCxt RValEnv RVal m a) => hs -> RValT m a
instance HSMarshall Int where
hsMarshall _ (RVal_Int v) = return v
hsUnmarshall v = rsemPush $ RVal_Int v
instance HSMarshall Integer where
hsMarshall _ (RVal_Integer v) = return v
hsUnmarshall v = rsemPush $ RVal_Integer v
instance HSMarshall Bool where
hsMarshall _ (RVal_Node t _) = return $ t == tagBoolTrue
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Bool:" >#< v
hsUnmarshall b = liftIO (mvecAllocFillFromV emptyCRArray) >>= rsemNode (if b then tagBoolTrue else tagBoolFalse) >>= rsemPush
instance HSMarshall Char where
hsMarshall _ (RVal_Char v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Char:" >#< v
hsUnmarshall v = rsemPush $ RVal_Char v
instance HSMarshall (Ptr a) where
hsMarshall _ (RHsV_Addr v) = return $ Ptr v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall (Ptr a):" >#< v
hsUnmarshall (Ptr v) = rsemPush $ RHsV_Addr v
instance HSMarshall [RVal] where
hsMarshall evl (RVal_Node t as)
| t == tagListCons = liftIO (MV.read as 1) >>= evl >>= rsemPop >>= hsMarshall evl >>= \tl -> liftIO (MV.read as 0) >>= \hd -> return (hd : tl)
| otherwise = return []
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall [RVal]:" >#< v
hsUnmarshall [] = liftIO (mvecAllocFillFromV emptyCRArray) >>= rsemNode tagListNil >>= rsemPush
hsUnmarshall (h:t) = hsUnmarshall t >>= rsemPop >>= \t' -> (liftIO $ mvecAllocFillFromV $ mkCRArray [h, t']) >>= rsemNode tagListCons >>= rsemPush
instance HSMarshall x => HSMarshall [x] where
hsMarshall evl x = hsMarshall evl x >>= mapM (\v -> evl v >>= rsemPop >>= hsMarshall evl)
hsUnmarshall v = forM v (\e -> hsUnmarshall e >>= rsemPop) >>= hsUnmarshall
deriving instance Typeable IOMode
deriving instance Data IOMode
type HpPtr = Int
nullPtr :: HpPtr
nullPtr = 1
isNullPtr = (== nullPtr)
data Heap
= Heap
{ hpVals :: !RValMV
, hpFirst :: !HpPtr
, hpFree :: !(IORef HpPtr)
, hpSemispaceMultiplier :: !(IORef Rational)
}
newHeap :: Int -> IO Heap
newHeap sz = do
vs <- mvecAllocInit sz
fr <- newIORef 0
ml <- newIORef 1.5
return $ Heap vs 0 fr ml
heapGcM :: (RunSem RValCxt RValEnv RVal m x) => RVal -> RValT m RVal
heapGcM curV = do
env@(RValEnv {renvHeap=hp@(Heap {hpVals=vsOld, hpSemispaceMultiplier=mlRef, hpFirst=offOld, hpFree=hpFrRef}), renvGcRootStack=rootStkRef, renvTopFrame=topFrRef, renvStack=stkRef, renvGlobals=globals}) <- get
env' <- liftIO $ do
ml <- readIORef mlRef
let szOld = MV.length vsOld
szNew = (round $ fromIntegral szOld * ml) :: Int
offNew = offOld + szOld
lwbOld = offOld
upbOld = offNew
vsNew <- mvecAllocInit szNew
greyref <- newIORef offNew
let
copyp p
| p >= lwbOld && p < upbOld = do
let pOld = p
iOld = pOld offOld
v <- MV.read vsOld iOld
case v of
RVal_Fwd pNew -> do
return pNew
v -> do
pNew <- readIORef greyref
let iNew = pNew offNew
MV.write vsNew iNew v
MV.write vsOld iOld (RVal_Fwd pNew)
writeIORef greyref (pNew+1)
return pNew
| otherwise = do
return p
copypv v = do
case v of
RVal_Ptr pref -> modifyIORefM pref copyp
_ -> return ()
copyv v = do
case v of
RVal_Ptr pref -> modifyIORefM pref copyp
RVal_Frame {rvalSLRef=slref, rvalFrVals=vs, rvalFrSP=spref}
-> modifyIORefM slref copyp >> readIORef spref >>= \sp -> mvecForM_' 0 sp vs copyv
RVal_Node {rvalNdVals=vs} -> mvecForM_ vs copyv
RVal_App {rvalFun=f, rvalArgs=as} -> copyv f >> mvecForM_ as copyv
RVal_Thunk {rvalSLRef=slref} -> modifyIORefM slref copyp
RVal_Lam {rvalSLRef=slref} -> modifyIORefM slref copyp
_ -> return ()
follow pBlk pGry
| pBlk < pGry = MV.read vsNew (pBlkoffNew) >>= copyv >> follow (pBlk+1) pGry
| otherwise = do
pGry' <- readIORef greyref
if pBlk < pGry' then follow pBlk pGry' else return pBlk
modifyIORefM topFrRef copyp
modifyIORefM stkRef $ mapM copyp
globals' <- V.forM globals copyp
copyv curV
readIORef rootStkRef >>= mapM_ (mapM_ copyv)
readIORef greyref >>= follow offNew >>= \p -> writeIORef hpFrRef (p offNew)
return $ env {renvGlobals = globals', renvHeap = hp {hpVals=vsNew, hpFirst=offNew}}
put env'
return curV
heapAllocM :: (RunSem RValCxt RValEnv RVal m x) => RVal -> RValT m HpPtr
heapAllocM v = do
hp@(Heap {hpVals=vs, hpFirst=off, hpFree=fr}) <- gets renvHeap
p <- liftIO $ readIORef fr
if p >= MV.length vs
then heapGcM v >>= heapAllocM
else liftIO $ do
MV.write vs p v
writeIORef fr (p + 1)
return $ p + off
heapAllocAsPtrM :: (RunSem RValCxt RValEnv RVal m x) => RVal -> RValT m RVal
heapAllocAsPtrM v = do
p <- heapAllocM v
liftIO (newIORef p) >>= (return . RVal_Ptr)
heapGetM'' :: Heap -> HpPtr -> IO RVal
heapGetM'' hp@(Heap {hpVals=vs, hpFirst=off}) p = MV.read vs (p off)
heapGetM' :: (RunSem RValCxt RValEnv RVal m x) => Heap -> HpPtr -> RValT m RVal
heapGetM' hp p = liftIO $ heapGetM'' hp p
heapGetM :: (RunSem RValCxt RValEnv RVal m x) => HpPtr -> RValT m RVal
heapGetM p = do
hp <- gets renvHeap
heapGetM' hp p
heapSetM' :: (RunSem RValCxt RValEnv RVal m x) => Heap -> HpPtr -> RVal -> RValT m ()
heapSetM' hp@(Heap {hpVals=vs, hpFirst=off}) p v = liftIO $ MV.write vs (p off) v
heapSetM :: (RunSem RValCxt RValEnv RVal m x) => HpPtr -> RVal -> RValT m ()
heapSetM p v = do
hp <- gets renvHeap
heapSetM' hp p v
heapUpdM' :: (RunSem RValCxt RValEnv RVal m x) => Heap -> HpPtr -> (RVal -> RValT m RVal) -> RValT m ()
heapUpdM' hp@(Heap {hpVals=vs, hpFirst=off}) p f = do
let p' = p off
v <- liftIO $ MV.read vs p'
v' <- f v
liftIO $ MV.write vs p' v'
heapUpdM :: (RunSem RValCxt RValEnv RVal m x) => HpPtr -> (RVal -> RValT m RVal) -> RValT m ()
heapUpdM p f = do
hp <- gets renvHeap
heapUpdM' hp p f
data RValCxt
= RValCxt
{ rcxtInRet :: !Bool
}
emptyRValCxt :: RValCxt
emptyRValCxt = RValCxt True
mustReturn :: RunSem RValCxt RValEnv RVal m x => RValT m a -> RValT m a
mustReturn = local (\r -> r {rcxtInRet = True})
needNotReturn :: RunSem RValCxt RValEnv RVal m x => RValT m a -> RValT m a
needNotReturn = local (\r -> r {rcxtInRet = False})
rvalRetEvl :: RunSem RValCxt RValEnv RVal m x => RVal -> RValT m x
rvalRetEvl = mustReturn . rsemEvl
rvalPrimargEvl :: RunSem RValCxt RValEnv RVal m x => RVal -> RValT m x
rvalPrimargEvl x = rvalRetEvl x >>= rsemPop >>= rsemDeref
vecLoopReverse :: Monad m => Int -> Int -> (V.Vector a -> Int -> m b) -> V.Vector a -> m ()
vecLoopReverse l h m v = loop (h1)
where loop h | l <= h = m v h >> loop (h1)
| otherwise = return ()
vecReverseForM_ :: Monad m => V.Vector a -> (a -> m x) -> m ()
vecReverseForM_ v m = vecLoopReverse 0 (V.length v) (\_ i -> m (v V.! i)) v
mvecAllocWith :: PrimMonad m => Int -> a -> m (MV.MVector (PrimState m) a)
mvecAllocWith = MV.replicate
mvecAllocInit :: Int -> IO RValMV
mvecAllocInit sz = mvecAllocWith sz RVal_None
mvecAlloc :: PrimMonad m => Int -> m (MV.MVector (PrimState m) a)
mvecAlloc = MV.new
mvecLoop :: PrimMonad m => Int -> Int -> (MV.MVector (PrimState m) a -> Int -> m b) -> MV.MVector (PrimState m) a -> m (MV.MVector (PrimState m) a)
mvecLoop l h m v = loop l
where loop l | l < h = m v l >> loop (l+1)
| otherwise = return v
mvecLoopReverse :: PrimMonad m => Int -> Int -> (MV.MVector (PrimState m) a -> Int -> m b) -> MV.MVector (PrimState m) a -> m (MV.MVector (PrimState m) a)
mvecLoopReverse l h m v = loop (h1)
where loop h | l <= h = m v h >> loop (h1)
| otherwise = return v
mvecLoopReverseAccum :: PrimMonad m => acc -> Int -> Int -> (acc -> Int -> m acc) -> MV.MVector (PrimState m) a -> m acc
mvecLoopReverseAccum a l h m v = loop (h1) a
where loop h a | l <= h = m a h >>= loop (h1)
| otherwise = return a
mvecToList :: PrimMonad m => MV.MVector (PrimState m) a -> m [a]
mvecToList v = mvecLoopReverseAccum [] 0 (MV.length v) (\l i -> MV.read v i >>= \a -> return (a:l)) v
mvecFillFromV :: PrimMonad m => Int -> MV.MVector (PrimState m) a -> CRArray a -> m ()
mvecFillFromV lwb toarr frarr = forM_ (craAssocs' lwb frarr) $ \(i,e) -> MV.write toarr i e
mvecFillFromMV' :: PrimMonad m => Int -> Int -> Int -> MV.MVector (PrimState m) a -> MV.MVector (PrimState m) a -> m ()
mvecFillFromMV' lwbTo lwbFr sz toarr frarr = mvecLoop lwbFr (lwbFr+sz) (\v i -> MV.read v i >>= MV.write toarr (i+lwbDiff)) frarr >> return ()
where lwbDiff = lwbTo lwbFr
mvecReverseFillFromMV' :: PrimMonad m => Int -> Int -> Int -> MV.MVector (PrimState m) a -> MV.MVector (PrimState m) a -> m ()
mvecReverseFillFromMV' lwbTo lwbFr sz toarr frarr = mvecLoopReverse lwbFr (lwbFr+sz) (\v i -> MV.read v i >>= MV.write toarr (upbFr1 i + lwbTo)) frarr >> return ()
where lwbDiff = lwbTo lwbFr
upbFr1 = lwbFr + sz 1
mvecFillFromMV :: PrimMonad m => Int -> MV.MVector (PrimState m) a -> MV.MVector (PrimState m) a -> m ()
mvecFillFromMV lwb toarr frarr = mvecFillFromMV' lwb 0 (MV.length frarr) toarr frarr
mvecReverseFillFromMV :: PrimMonad m => Int -> MV.MVector (PrimState m) a -> MV.MVector (PrimState m) a -> m ()
mvecReverseFillFromMV lwb toarr frarr = mvecReverseFillFromMV' lwb 0 (MV.length frarr) toarr frarr
mvecAllocFillFromV :: PrimMonad m => CRArray a -> m (MV.MVector (PrimState m) a)
mvecAllocFillFromV frarr = mvecAlloc (V.length frarr) >>= \toarr -> mvecFillFromV 0 toarr frarr >> return toarr
mvecForM_' :: PrimMonad m => Int -> Int -> MV.MVector (PrimState m) a -> (a -> m b) -> m ()
mvecForM_' lwb upb v m = mvecLoop lwb upb (\v i -> MV.read v i >>= m) v >> return ()
mvecForM_ :: PrimMonad m => MV.MVector (PrimState m) a -> (a -> m b) -> m ()
mvecForM_ v m = mvecForM_' 0 (MV.length v) v m
mvecAppend :: PrimMonad m => MV.MVector (PrimState m) a -> MV.MVector (PrimState m) a -> m (MV.MVector (PrimState m) a)
mvecAppend v1 v2 =
mvecAlloc l12 >>= mvecLoop 0 l1 (\v i -> MV.read v1 i >>= MV.write v i) >>= mvecLoop l1 l12 (\v i -> MV.read v2 (il1) >>= MV.write v i)
where
l1 = MV.length v1
l2 = MV.length v2
l12 = l1 + l2
mvecReverseForM_ :: PrimMonad m => MV.MVector (PrimState m) a -> (a -> m x) -> m ()
mvecReverseForM_ v m = mvecLoopReverse 0 (MV.length v) (\v i -> MV.read v i >>= m) v >> return ()
ptr2valM :: (RunSem RValCxt RValEnv RVal m x) => RVal -> RValT m RVal
ptr2valM v = case v of
RVal_Ptr pref -> liftIO (readIORef pref) >>= heapGetM >>= \v' -> case v' of
RVal_Thunk {} -> return v
_ -> ptr2valM v'
_ -> return v
ref2valM :: (RunSem RValCxt RValEnv RVal m x) => RRef -> RValT m RVal
ref2valM r = do
env <- get
case r of
RRef_Glb m e -> do
modFrame <- heapGetM (renvGlobals env V.! m)
liftIO $ MV.read (rvalFrVals modFrame) e
RRef_Loc l o -> do
topfrp <- renvTopFrameM
topfr <- heapGetM topfrp
access topfr
where
access (RVal_Frame {rvalLev=frlev, rvalFrVals=vs}) | l == frlev = do
liftIO $ MV.read vs o
access (RVal_Frame {rvalLev=frlev, rvalSLRef=slref}) = do
sl <- liftIO $ readIORef slref
heapGetM sl >>= access
access v =
err $ "CoreRun.Run.Val.ref2valM.RRef_Loc.access:" >#< r >#< "in" >#< v
RRef_Fld r e -> do
v <- ptr2valM =<< ref2valM r
case v of
RVal_Node _ vs -> liftIO $ MV.read vs e
_ -> err $ "CoreRun.Run.Val.ref2valM.RRef_Fld:" >#< e >#< "in" >#< v
_ -> err $ "CoreRun.Run.Val.ref2valM.r:" >#< r
type RValFrame = HpPtr
type RValStack = [RValFrame]
data RValEnv
= RValEnv
{ renvGlobals :: !(CRArray RValFrame)
, renvStack :: !(IORef RValStack)
, renvTopFrame :: !(IORef RValFrame)
, renvHeap :: !Heap
, renvDoTrace :: !Bool
, renvGcRootStack :: !(IORef [[RVal]])
}
newRValEnv :: Int -> IO RValEnv
newRValEnv hpSz = do
st <- newIORef []
tp <- newIORef nullPtr
hp <- newHeap hpSz
rtst <- newIORef []
return $ RValEnv V.empty st tp hp False rtst
renvTopFrameM :: (RunSem RValCxt RValEnv RVal m x) => RValT m HpPtr
renvTopFrameM = do
(RValEnv {renvTopFrame=tf}) <- get
liftIO $ readIORef tf
renvAllFrameM' :: (RunSem RValCxt RValEnv RVal m x) => RValT m (Maybe HpPtr,[HpPtr])
renvAllFrameM' = do
topfrp <- renvTopFrameM
env <- get
st <- liftIO $ readIORef (renvStack env)
return (if isNullPtr topfrp then Nothing else Just topfrp, st)
renvAllFrameM :: (RunSem RValCxt RValEnv RVal m x) => RValT m [HpPtr]
renvAllFrameM = do
(mbtop,st) <- renvAllFrameM'
return $ maybe [] (:[]) mbtop ++ st
dumpPpEnvM :: (RunSem RValCxt RValEnv RVal m x) => Bool -> RValT m PP_Doc
dumpPpEnvM extensive = do
stkfrs <- renvAllFrameM
env <- get
let hp = renvHeap env
hpfr <- liftIO $ readIORef (hpFree hp)
needRet <- asks rcxtInRet
let dash = "===================="
header1 = dash >-< "rcxtInRet=" >|< needRet
header2 = ppCurly $ "Heap =" >|< hpfr >|< "/" >|< MV.length (hpVals hp) >|< ", Stack =" >|< ppBracketsCommas stkfrs
footer1 = dash
hpPP <- dumpHeap hp hpfr
glPP <- dumpGlobals hp (renvGlobals env)
frPPs <- forM stkfrs $ dumpFrame hp
if extensive
then return $ header1 >-< header2 >-< hpPP >-< glPP >-< "====== Frames ======" >-< (indent 2 $ vlist frPPs) >-< footer1
else return $ header2
where
dumpFrame hp fp = do
fr@(RVal_Frame {rvalFrVals=vs, rvalFrSP=spref}) <- heapGetM fp
sp <- liftIO $ readIORef spref
(liftIO $ ppRValWithHp hp fr) >>= \frpp -> return $ "Frame ptr=" >|< fp >|< " sp=" >|< sp >-< (indent 2 $ frpp)
dumpGlobals hp glbls = do
pps <- forM [0 .. V.length glbls 1] $ \i -> do
dumpFrame hp (glbls V.! i)
return $ "====== Globals ======" >-< indent 2 (vlist pps)
dumpHeap hp@(Heap {hpFirst=off}) hpfr = do
pps <- ppa off hp hpfr (hpVals hp)
return $ "======= Heap =======" >-< indent 2 (vlist pps)
ppb hp k v = (liftIO $ ppRValWithHp hp v) >>= \vpp -> return $ k >|< ":" >#< vpp
ppa off hp sz vs = forM [0 .. sz 1] $ \i -> liftIO (MV.read vs i) >>= ppb hp (i + off)
dumpEnvM :: (RunSem RValCxt RValEnv RVal m x) => Bool -> RValT m ()
dumpEnvM extensive = dumpPpEnvM extensive >>= \p -> liftIO $ putPPLn p >> hFlush stdout
updTopFrameM :: (RunSem RValCxt RValEnv RVal m x) => (RVal -> RValT m RVal) -> RValT m ()
updTopFrameM f = renvTopFrameM >>= flip heapUpdM f
renvFrStkPush' :: RunSem RValCxt RValEnv RVal m x => (Int -> RValMV -> v -> IO Int) -> v -> RValT m ()
renvFrStkPush' pushvOn v = do
(RValEnv {renvTopFrame=frref, renvHeap=hp}) <- get
liftIO $ do
(RVal_Frame {rvalFrVals=frvs, rvalFrSP=spref}) <- heapGetM'' hp =<< readIORef frref
sp <- readIORef spref
sp' <- pushvOn sp frvs v
writeIORef spref sp'
renvFrStkPush1 :: RunSem RValCxt RValEnv RVal m x => RVal -> RValT m ()
renvFrStkPush1 = renvFrStkPush' (\sp frvs v -> MV.write frvs sp v >> return (sp + 1))
renvFrStkPushMV :: RunSem RValCxt RValEnv RVal m x => RValMV -> RValT m ()
renvFrStkPushMV = renvFrStkPush' (\sp frvs vs -> mvecFillFromMV sp frvs vs >> return (sp + MV.length vs))
renvFrStkReversePushMV :: RunSem RValCxt RValEnv RVal m x => RValMV -> RValT m ()
renvFrStkReversePushMV = renvFrStkPush' (\sp frvs vs -> mvecReverseFillFromMV sp frvs vs >> return (sp + MV.length vs))
renvFrStkPop' :: RunSem RValCxt RValEnv RVal m x => (RValMV -> Int -> IO v) -> Int -> RValT m v
renvFrStkPop' popvFrom sz = do
(RValEnv {renvTopFrame=frref, renvHeap=hp}) <- get
liftIO $ do
(RVal_Frame {rvalFrVals=frvs, rvalFrSP=spref}) <- heapGetM'' hp =<< readIORef frref
sp <- readIORef spref
let sp' = sp sz
writeIORef spref sp'
popvFrom frvs sp'
renvFrStkPop :: RunSem RValCxt RValEnv RVal m x => Int -> RValT m ()
renvFrStkPop = renvFrStkPop' (\_ _ -> return ())
renvFrStkPop1 :: RunSem RValCxt RValEnv RVal m x => RValT m RVal
renvFrStkPop1 = renvFrStkPop' MV.read 1
renvFrStkPopInMV :: RunSem RValCxt RValEnv RVal m x => Int -> Int -> RValMV -> RValT m ()
renvFrStkPopInMV lwbTo sz vs = renvFrStkPop' (\frvs sp -> mvecFillFromMV' lwbTo sp sz vs frvs) sz
renvFrStkPopMV :: RunSem RValCxt RValEnv RVal m x => Int -> RValT m RValMV
renvFrStkPopMV sz = (liftIO $ mvecAlloc sz) >>= \vs -> renvFrStkPopInMV 0 sz vs >> return vs
renvFrStkReversePopInMV :: RunSem RValCxt RValEnv RVal m x => Int -> Int -> RValMV -> RValT m ()
renvFrStkReversePopInMV lwbTo sz vs = renvFrStkPop' (\frvs sp -> mvecReverseFillFromMV' lwbTo sp sz vs frvs) sz
renvFrStkReversePopMV :: RunSem RValCxt RValEnv RVal m x => Int -> RValT m RValMV
renvFrStkReversePopMV sz = (liftIO $ mvecAlloc sz) >>= \vs -> renvFrStkReversePopInMV 0 sz vs >> return vs
rsemTr' :: (PP msg, RunSem RValCxt RValEnv RVal m x) => Bool -> msg -> RValT m ()
rsemTr' dumpExtensive msg = whenM (gets renvDoTrace) $ do
liftIO $ putStrLn $ show $ pp msg
dumpEnvM dumpExtensive
liftIO $ hFlush stdout
rsemTr :: (PP msg, RunSem RValCxt RValEnv RVal m x) => msg -> RValT m ()
rsemTr = rsemTr' False
type RValT m a = RunT' RValCxt RValEnv RVal m a