module UHC.Light.Compiler.CoreRun.Run.Val
( module System.IO
, module Data.IORef
, module Data.Int, module Data.Word
, module GHC.Ptr
, RCxt (..)
, mkRCxt, mkRCxtSl, rcxtCloneWithNewFrame
, RVal (..)
, mkTuple, mkUnit
, RValV, RValMV
, RValCxt (..), emptyRValCxt
, rvalTrEnterLam
, mustReturn, needNotReturn, rvalRetEvl, rvalPrimargEvl
, rcxtUpdDatatypes
, HpPtr, nullPtr, isNullPtr, newHeap, Heap (..)
, heapGetM, heapGetM', heapAllocM, heapAllocAsPtrM, heapUpdM, heapSetM, heapSetM'
, RValEnv (..), newRValEnv
, renvResolveModNames
, renvTopFramePtrM, renvTopFramePtrAndFrameM, renvTopFrameM
, dumpEnvM'
, RValT
, HSMarshall (..)
, vecReverseForM_
, mvecAllocInit, mvecAlloc, mvecFillFromV, mvecReverseFillFromV, mvecFillFromMV, mvecAllocFillFromV, mvecAppend, mvecToList
, mvecReverseForM_
, ptr2valM, ref2valM
, updTopFrameM
, renvFrStkPush1, renvFrStkReversePushMV
, renvFrStkPop1, renvFrStkPopMV, renvFrStkReversePopMV, renvFrStkReversePopInMV
, rsemTr''
, rcxtTraceOnS )
where
import UHC.Light.Compiler.Base.HsName.Builtin
import UHC.Light.Compiler.Base.Common
import UHC.Light.Compiler.Error
import UHC.Light.Compiler.Base.Trace
import UHC.Light.Compiler.CoreRun
import UHC.Light.Compiler.CoreRun.Run
import UHC.Light.Compiler.CoreRun.Pretty
import UHC.Util.Pretty as PP
import UHC.Util.Utils
import UHC.Util.Lens
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 System.IO
import System.IO.Unsafe
import Data.IORef
import Data.Int
import Data.Word
import Data.Bits
import qualified Data.ByteString.Char8 as BSC8
import GHC.Ptr (Ptr (..))
import GHC.Exts (Addr#)
import GHC.Generics
import Control.Applicative
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Maybe
data RCxt
= RCxt
{ rcxtMdRef :: !(IORef HpPtr)
, rcxtSlRef :: !(IORef HpPtr)
}
instance Show RCxt where
show _ = "RCxt"
mkRCxt :: HpPtr -> HpPtr -> IO RCxt
mkRCxt m f = liftM2 RCxt (newIORef m) (newIORef f)
mkRCxtSl :: HpPtr -> IO RCxt
mkRCxtSl = mkRCxt 0
rcxtCloneWithNewFrame :: HpPtr -> RCxt -> IO RCxt
rcxtCloneWithNewFrame f cx = do
f' <- newIORef f
return $ cx {rcxtSlRef = f'}
data RVal
=
RVal_Lit
{ rvalSExp :: !SExp
}
| RVal_Char !Char
| RVal_Int !Int
| RVal_Int8 !Int8
| RVal_Int16 !Int16
| RVal_Int32 !Int32
| RVal_Int64 !Int64
| RVal_Word !Word
| RVal_Word8 !Word8
| RVal_Word16 !Word16
| RVal_Word32 !Word32
| RVal_Word64 !Word64
| RVal_Integer !Integer
| RVal_Float !Float
| RVal_Double !Double
| RVal_PackedString !BSC8.ByteString
| RVal_Lam
{ rvalMbNm :: !(Maybe HsName)
, rvalBody :: !Exp
, rvalCx :: !RCxt
}
| RVal_Thunk
{ rvalMbNm :: !(Maybe HsName)
, rvalBody :: !Exp
, rvalCx :: !RCxt
}
| RVal_NodeMV
{ rvalTag :: !Int
, rvalNdMVals :: !RValMV
}
| RVal_App
{ rvalFun :: !RVal
, rvalArgs :: !RValMV
}
| RVal_Frame
{ rvalRef2Nm :: Ref2Nm
, rvalCx :: !RCxt
, rvalFrVals :: !RValMV
, rvalFrSP :: !(IORef Int)
}
| RVal_Module
{ rvalModNm :: HsName
, rvalModImpsV :: !(CRArray Int)
, rvalFrRef :: !(IORef HpPtr)
}
| 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_Int8 v -> dfltpp $ show v
RVal_Int16 v -> dfltpp $ show v
RVal_Int32 v -> dfltpp $ show v
RVal_Int64 v -> dfltpp $ show v
RVal_Word v -> dfltpp $ show v
RVal_Word8 v -> dfltpp $ show v
RVal_Word16 v -> dfltpp $ show v
RVal_Word32 v -> dfltpp $ show v
RVal_Word64 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 mn b _ -> dfltpp b
RVal_Thunk mn e _ -> return $ ppBrackets e
RVal_NodeMV 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 PP.empty) (\v -> ppRVal' lkptr v >>= \vpp -> return $ " -> " >|< vpp)
return $ "*" >|< p >|< vpp
RVal_Fwd p -> return $ "f*" >|< p
RVal_Frame _ rcx vs spref -> do
sl <- readIORef (rcxtSlRef rcx)
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, "sz=" >|< MV.length vs, "sp=" >|< sp])
>-< vlist vlpp
RVal_Module nm _ frref -> do
fr <- readIORef frref
return $ ppBracketsCommas ["mod=" >|< nm, "fr=" >|< fr]
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 $ crarrayFromList vs) >>= rsemNode 0 >>= rsemPush
mkUnit :: (RunSem RValCxt RValEnv RVal m a) => RValT m a
mkUnit = mkTuple []
type RValV = CRArray RVal
type RValMV = CRMArray RVal
data RValCxt
= RValCxt
{ rcxtInRet :: !Bool
, rcxtCallCxt :: [Maybe HsName]
, rcxtDatatypeMp :: RValDatatypeMp
, _rcxtTraceOnS :: !(Set.Set TraceOn)
}
deriving (Show, Typeable)
emptyRValCxt :: RValCxt
emptyRValCxt = RValCxt True [] m Set.empty
where m = rvalDatatypeMpUnions1
[ Map.singleton n (emptyRValDataconstrInfo {rdciNm2Tg = Map.singleton n 0, rdciTg2Nm = crarrayFromList [n]})
| tuparity <- [2..15], let n = "(" ++ replicate (tuparity1) ',' ++ ")"
]
rvalTrEnterLam :: RunSem RValCxt RValEnv RVal m x => Maybe HsName -> RValT m a -> RValT m a
rvalTrEnterLam s = local (\r -> r {rcxtCallCxt = s : rcxtCallCxt r})
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
rcxtUpdDatatypes :: RunSem RValCxt RValEnv RVal m x => [Mod] -> RValT m RValCxt
rcxtUpdDatatypes mods = do
cx@(RValCxt {rcxtDatatypeMp=m}) <- ask
let cx' = cx {rcxtDatatypeMp = rvalDatatypeMpUnions1 $ m : map rvalDatatypeMpFromMod mods}
return cx'
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
, renvGlobalsMV=globals
, renvModulesMV=modules
}) <- 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_Module {rvalFrRef=frref} -> modifyIORefM frref copyp
RVal_Frame {rvalCx=rcx, rvalFrVals=vs, rvalFrSP=spref}
-> copycx rcx >> readIORef spref >>= \sp -> mvecForM_' 0 sp vs copyv
RVal_NodeMV {rvalNdMVals=vs} -> mvecForM_ vs copyv
RVal_App {rvalFun=f, rvalArgs=as} -> copyv f >> mvecForM_ as copyv
RVal_Thunk {rvalCx=rcx} -> copycx rcx
RVal_Lam {rvalCx=rcx} -> copycx rcx
_ -> return ()
copycx cx = do
case cx of
RCxt mref slref -> modifyIORefM mref copyp >> modifyIORefM slref copyp
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
mvecLoop 0 (MV.length modules) (\v i -> MV.read v i >>= copyp >>= MV.write v i) modules
mvecLoop 0 (MV.length globals) (\v i -> MV.read v i >>= copyp >>= MV.write v i) globals
copyv curV
readIORef rootStkRef >>= mapM_ (mapM_ copyv)
readIORef greyref >>= follow offNew >>= \p -> writeIORef hpFrRef (p offNew)
return $ env { 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
type RValDataconstrInfoNm2Tg = Map.Map String Int
type RValDataconstrInfoTg2Nm = CRArray String
data RValDataconstrInfo
= RValDataconstrInfo
{ rdciNm2Tg :: RValDataconstrInfoNm2Tg
, rdciTg2Nm :: RValDataconstrInfoTg2Nm
, rdciMods :: [HsName]
}
deriving Show
emptyRValDataconstrInfo = RValDataconstrInfo Map.empty emptyCRArray []
type RValDatatypeMp
= Map.Map
String
RValDataconstrInfo
rvalDatatypeMpUnion :: RValDatatypeMp -> RValDatatypeMp -> RValDatatypeMp
rvalDatatypeMpUnion = Map.unionWith (\l r -> l {rdciMods = rdciMods l ++ rdciMods r})
rvalDatatypeMpUnions1 :: [RValDatatypeMp] -> RValDatatypeMp
rvalDatatypeMpUnions1 = foldr1 rvalDatatypeMpUnion
rvalDatatypeMpFromMod :: Mod -> RValDatatypeMp
rvalDatatypeMpFromMod (Mod_Mod {metas_Mod_Mod=metas})
= Map.fromList
[ ( show tn'
, emptyRValDataconstrInfo
{ rdciNm2Tg = Map.fromList cts
, rdciTg2Nm = crarrayFromList $ map fst $ sortOnLazy snd cts
, rdciMods = mods
})
| Meta_Data {tyNm_Meta_Data=tn, dataCons_Meta_Data=constrs} <- metas
, let cts = assocLMapKey show $ candtg constrs
(tn',mods) = splitTN tn
]
where candtg cs = [ (cn,t) | DataCon_Con {conNm_DataCon_Con=cn, tagNr_DataCon_Con=t} <- cs ]
splitTN n = (hsnQualified n, maybe [] (:[]) $ hsnQualifier n)
type RValFrame = HpPtr
type RValModule = HpPtr
type RValStack = [RValFrame]
data RValEnv
= RValEnv
{ renvModulesMV :: !(CRMArray RValModule)
, renvGlobalsMV :: !(CRMArray RValFrame)
, renvStack :: !(IORef RValStack)
, renvTopFrame :: !(IORef RValFrame)
, renvHeap :: !Heap
, renvDoTrace :: !Bool
, renvDoTraceExt :: !Bool
, renvGcRootStack :: !(IORef [[RVal]])
}
newRValEnv :: Int -> IO RValEnv
newRValEnv hpSz = do
st <- newIORef []
tp <- newIORef nullPtr
hp <- newHeap hpSz
rtst <- newIORef []
md <- MV.new 0
gl <- MV.new 0
return $ RValEnv md gl st tp hp False False rtst
renvResolveModNames :: (RunSem RValCxt RValEnv RVal m x) => Int -> [HsName] -> RValT m [Int]
renvResolveModNames upb nms = do
env@(RValEnv {renvModulesMV=ms, renvHeap=hp}) <- get
let lkup n nm | n > upb = err $ "No module entry for: " ++ show nm
| otherwise = (liftIO $ MV.read ms n >>= heapGetM'' hp) >>= \(RVal_Module {rvalModNm=nm'}) -> if nm == nm' then return n else lkup (n+1) nm
forM nms $ \nm -> do
i <- lkup 0 nm
rsemTr'' TraceOn_RunMod $ "renvResolveModNames" >#< nm >#< "->" >#< i
return i
renvTopFramePtrM :: (RunSem RValCxt RValEnv RVal m x) => RValT m HpPtr
renvTopFramePtrM = do
(RValEnv {renvTopFrame=tf}) <- get
liftIO $ readIORef tf
renvTopFramePtrAndFrameM :: (RunSem RValCxt RValEnv RVal m x) => RValT m (HpPtr,RVal)
renvTopFramePtrAndFrameM = do
frp <- renvTopFramePtrM
fr <- heapGetM frp
return (frp,fr)
renvTopFrameM :: (RunSem RValCxt RValEnv RVal m x) => RValT m RVal
renvTopFrameM = renvTopFramePtrM >>= heapGetM
renvAllFrameM' :: (RunSem RValCxt RValEnv RVal m x) => RValT m (Maybe HpPtr,[HpPtr])
renvAllFrameM' = do
topfrp <- renvTopFramePtrM
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) => (TraceOn -> Bool) -> RValT m [PP_Doc]
dumpPpEnvM' onTr = do
stkfrs <- renvAllFrameM
env <- get
callcxt <- asks rcxtCallCxt
let hp = renvHeap env
stkfrspp <- forM stkfrs $ dumpFrameMinimal hp
hpfr <- liftIO $ readIORef (hpFree hp)
needRet <- asks rcxtInRet
let dash = "===================="
header1 = dash >-< "rcxtInRet=" >|< needRet
header2 = ppCurly $ "Heap =" >|< hpfr >|< "/" >|< MV.length (hpVals hp) >|< ", CallCxt=" >|< ppBracketsCommas callcxt >|< ", Stack=" >|< ppBracketsCommas stkfrspp
footer1 = dash
hpPP <- if onTr TraceOn_RunHeap then dumpHeap hp hpfr else return []
mdPP <- if onTr TraceOn_RunMod then dumpModulesMV hp (renvModulesMV env) else return []
glPP <- if onTr TraceOn_RunGlobals then dumpGlobalsMV hp (renvGlobalsMV env) else return []
frPP <- if onTr TraceOn_RunFrames then ((forM stkfrs $ dumpFrame hp) >>= \fs -> return [pp "====== Frames ======", indent 2 $ vlist fs]) else return []
let extensivePP = hpPP ++ glPP ++ mdPP ++ frPP
headerOrFooter = if null extensivePP then [] else [pp dash]
return $
headerOrFooter ++
(if onTr TraceOn_RunFrame then [header2] else []) ++
extensivePP ++
headerOrFooter
where
dumpFrameMinimal hp fp = do
fr@(RVal_Frame {rvalFrVals=vs, rvalFrSP=spref}) <- heapGetM fp
sp <- liftIO $ readIORef spref
return [fp >|< (ppParens $ sp >|< "/" >|< MV.length vs)]
dumpModule hp fp = do
md <- heapGetM fp
liftIO $ ppRValWithHp hp md
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)
dumpModulesMV hp mods = do
pps <- liftIO (mvecToList mods) >>= \l -> forM l $ dumpModule hp
return [pp "====== Modules ======", indent 2 (vlist pps)]
dumpGlobalsMV hp glbls = do
pps <- liftIO (mvecToList glbls) >>= \l -> forM l $ dumpFrame hp
return [pp "====== Globals ======", indent 2 (vlist pps)]
dumpHeap hp@(Heap {hpFirst=off}) hpfr = do
pps <- ppa off hp hpfr (hpVals hp)
return [pp "======= 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) => RValT m ()
dumpEnvM' = do
tons <- rsemTraceOnS
dumpPpEnvM' (`Set.member` tons) >>= \ps -> liftIO $ forM_ ps putPPLn >> hFlush stdout
type RValT m a = RunT' RValCxt RValEnv RVal m a
class HSMarshall hs where
hsMarshall :: (RunSem RValCxt RValEnv RVal m a) => (RVal -> RValT m a) -> RVal -> RValT m hs
default hsMarshall :: (Generic hs, GHSMarshall (Rep hs), RunSem RValCxt RValEnv RVal m a) => (RVal -> RValT m a) -> RVal -> RValT m hs
hsMarshall evl v = to <$> ghsMarshall evl v
hsUnmarshall :: (RunSem RValCxt RValEnv RVal m a) => hs -> RValT m a
default hsUnmarshall :: (Generic hs, GHSMarshall (Rep hs), RunSem RValCxt RValEnv RVal m a) => hs -> RValT m a
hsUnmarshall = ghsUnmarshall . from
instance HSMarshall Int where
hsMarshall _ (RVal_Int v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Int:" >#< v
hsUnmarshall v = rsemPush $ RVal_Int v
instance HSMarshall Int8 where
hsMarshall _ (RVal_Int8 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Int8:" >#< v
hsUnmarshall v = rsemPush $ RVal_Int8 v
instance HSMarshall Int16 where
hsMarshall _ (RVal_Int16 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Int16:" >#< v
hsUnmarshall v = rsemPush $ RVal_Int16 v
instance HSMarshall Int32 where
hsMarshall _ (RVal_Int32 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Int32:" >#< v
hsUnmarshall v = rsemPush $ RVal_Int32 v
instance HSMarshall Int64 where
hsMarshall _ (RVal_Int64 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Int64:" >#< v
hsUnmarshall v = rsemPush $ RVal_Int64 v
instance HSMarshall Word where
hsMarshall _ (RVal_Word v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Word:" >#< v
hsUnmarshall v = rsemPush $ RVal_Word v
instance HSMarshall Word8 where
hsMarshall _ (RVal_Word8 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Word8:" >#< v
hsUnmarshall v = rsemPush $ RVal_Word8 v
instance HSMarshall Word16 where
hsMarshall _ (RVal_Word16 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Word16:" >#< v
hsUnmarshall v = rsemPush $ RVal_Word16 v
instance HSMarshall Word32 where
hsMarshall _ (RVal_Word32 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Word32:" >#< v
hsUnmarshall v = rsemPush $ RVal_Word32 v
instance HSMarshall Word64 where
hsMarshall _ (RVal_Word64 v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Word64:" >#< v
hsUnmarshall v = rsemPush $ RVal_Word64 v
instance HSMarshall Integer where
hsMarshall _ (RVal_Integer v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Integer:" >#< v
hsUnmarshall v = rsemPush $ RVal_Integer v
instance HSMarshall Float where
hsMarshall _ (RVal_Float v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Float:" >#< v
hsUnmarshall v = rsemPush $ RVal_Float v
instance HSMarshall Double where
hsMarshall _ (RVal_Double v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Double:" >#< v
hsUnmarshall v = rsemPush $ RVal_Double v
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 Handle where
hsMarshall _ (RHsV_Handle v) = return v
hsMarshall _ v = err $ "CoreRun.Run.Val.HSMarshall Handle:" >#< v
hsUnmarshall v = rsemPush $ RHsV_Handle v
instance HSMarshall Bool
instance HSMarshall x => HSMarshall [x]
class GHSMarshall hs where
ghsMarshall :: (RunSem RValCxt RValEnv RVal m a) => (RVal -> RValT m a) -> RVal -> RValT m (hs x)
ghsUnmarshall :: (RunSem RValCxt RValEnv RVal m a) => hs x -> RValT m a
instance (Datatype d, MarshallSum hs) => GHSMarshall (D1 d hs) where
ghsMarshall evl v = do
dtmp <- asks rcxtDatatypeMp
let nm = datatypeName (undefined :: t d hs p)
case Map.lookup nm dtmp of
Nothing -> err $ "Marshall to HS lacks datatype info, datatype=" ++ nm
Just (RValDataconstrInfo {rdciMods=mods@(_:_:_)}) ->
err $ "Marshall to HS datatype info in multiple modules, datatype=" ++ nm ++ ", mods=" ++ show mods
Just (RValDataconstrInfo {rdciTg2Nm=tg2con}) -> do
r <- sumExtrTagged evl tg2con v
maybe (err $ "sumExtrTagged") (return . M1) r
ghsUnmarshall (M1 x) = do
dtmp <- asks rcxtDatatypeMp
let nm = datatypeName (undefined :: t d hs p)
case Map.lookup nm dtmp of
Nothing -> err $ "Marshall from HS lacks datatype info, datatype=" ++ nm
Just (RValDataconstrInfo {rdciMods=mods@(_:_:_)}) ->
err $ "Marshall from HS datatype info in multiple modules, datatype=" ++ nm ++ ", mods=" ++ show mods
Just (RValDataconstrInfo {rdciNm2Tg=con2tg}) ->
sumFillTagged con2tg x
class MarshallSum hs where
sumFillTagged
:: (RunSem RValCxt RValEnv RVal m a)
=> RValDataconstrInfoNm2Tg
-> hs x
-> RValT m a
sumExtrTagged
:: (RunSem RValCxt RValEnv RVal m a)
=> (RVal -> RValT m a)
-> RValDataconstrInfoTg2Nm
-> RVal
-> RValT m (Maybe (hs x))
instance ( MarshallProduct hs, ProductSize hs, Constructor c ) => MarshallSum (C1 c hs) where
sumFillTagged con2tg (M1 x) = do
v <- liftIO $ MV.unsafeNew len
productFillMVec v 0 len x
let nm = conName (undefined :: t c hs p)
mt = Map.lookup nm con2tg
when (isNothing mt) $ err $ "Marshall from HS lacks constructor info, constructor=" ++ nm
rsemNode (fromJust mt) v >>= rsemPush
where
len = (unTagged2 :: Tagged2 hs Int -> Int) productSize
tag = Map.findWithDefault 0 (conName (undefined :: t c hs p)) con2tg
sumExtrTagged evl tg2con v@(RVal_NodeMV {rvalTag=t, rvalNdMVals=mv})
| t >= V.length tg2con = err $ "Marshall to HS illegal tag value, con=" ++ nmc ++ ", tag=" ++ show t
| nmc == nmt = (Just . M1) <$> productExtrMVec evl mv 0 len
| otherwise = return $ Nothing
where
len = (unTagged2 :: Tagged2 hs Int -> Int) productSize
nmc = conName (undefined :: t c hs p)
nmt = tg2con V.! t
instance ( MarshallSum a, MarshallSum b ) => MarshallSum (a :+: b) where
sumFillTagged con2tg (L1 x) = sumFillTagged con2tg x
sumFillTagged con2tg (R1 x) = sumFillTagged con2tg x
sumExtrTagged evl tg2con v = do
l <- sumExtrTagged evl tg2con v
case l of
Just l' -> return $ fmap L1 l
_ -> fmap R1 <$> sumExtrTagged evl tg2con v
class MarshallProduct hs where
productFillMVec
:: (RunSem RValCxt RValEnv RVal m a)
=> CRMArray RVal
-> Int
-> Int
-> hs x
-> RValT m ()
productExtrMVec
:: (RunSem RValCxt RValEnv RVal m a)
=> (RVal -> RValT m a)
-> CRMArray RVal
-> Int
-> Int
-> RValT m (hs x)
instance (MarshallProduct a, MarshallProduct b) => MarshallProduct (a :*: b) where
productFillMVec mv ix len (a :*: b) = do
productFillMVec mv ix lenL a
productFillMVec mv ixR lenR b
where
lenL = len `unsafeShiftR` 1
ixR = ix + lenL
lenR = len lenL
productExtrMVec evl mv ix len =
(:*:) <$> productExtrMVec evl mv ix lenL
<*> productExtrMVec evl mv ixR lenR
where
lenL = len `unsafeShiftR` 1
ixR = ix + lenL
lenR = len lenL
instance MarshallProduct hs => MarshallProduct (S1 s hs) where
productFillMVec mv ix l (M1 x) = productFillMVec mv ix l x
productExtrMVec evl mv ix l = M1 <$> productExtrMVec evl mv ix l
instance HSMarshall x => MarshallProduct (K1 i x) where
productFillMVec mv ix _ (K1 x) = do
x' <- rsemPop =<< hsUnmarshall x
liftIO $ MV.unsafeWrite mv ix x'
productExtrMVec evl mv ix _ = do
v <- (liftIO $ MV.read mv ix) >>= evl >>= rsemPop
K1 <$> hsMarshall evl v
instance MarshallProduct U1 where
productFillMVec mv ix _ U1 = return ()
productExtrMVec evl mv ix _ = return U1
newtype Tagged s b = Tagged {unTagged :: b}
newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}
class ProductSize f where
productSize :: Tagged2 f Int
instance (ProductSize a, ProductSize b) => ProductSize (a :*: b) where
productSize = Tagged2 $ unTagged2 (productSize :: Tagged2 a Int) +
unTagged2 (productSize :: Tagged2 b Int)
instance ProductSize (S1 s a) where
productSize = Tagged2 1
instance ProductSize U1 where
productSize = Tagged2 0
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
mvecReverseFillFromV :: PrimMonad m => Int -> MV.MVector (PrimState m) a -> CRArray a -> m ()
mvecReverseFillFromV lwb toarr frarr = forM_ (craReverseAssocs' 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@(RValEnv {renvHeap=hp, renvModulesMV=mods}) <- get
v <- case r of
RRef_Glb m e -> do
RVal_Frame {rvalFrVals=frvals} <- heapGetM =<< liftIO (MV.read (renvGlobalsMV env) m)
liftIO $ MV.read frvals e
RRef_Imp m e -> do
RVal_Frame {rvalCx=RCxt {rcxtMdRef=mdref}} <- renvTopFrameM
liftIO $ do
RVal_Module {rvalModImpsV=imps} <- heapGetM'' hp =<< readIORef mdref
RVal_Module {rvalFrRef=frref} <- heapGetM'' hp =<< MV.read mods (imps V.! m)
RVal_Frame {rvalFrVals=frvals} <- heapGetM'' hp =<< readIORef frref
MV.read frvals e
RRef_Mod e -> do
RVal_Frame {rvalCx=RCxt {rcxtMdRef=mdref}} <- renvTopFrameM
liftIO $ do
RVal_Module {rvalFrRef=frref} <- heapGetM'' hp =<< readIORef mdref
RVal_Frame {rvalFrVals=frvals} <- heapGetM'' hp =<< readIORef frref
MV.read frvals e
RRef_LDf ld o -> do
topfr <- renvTopFrameM
access ld topfr
where
access 0 (RVal_Frame {rvalFrVals=vs}) =
liftIO $ MV.read vs o
access ld (RVal_Frame {rvalCx=rcx}) = do
sl <- liftIO $ readIORef (rcxtSlRef rcx)
fr <- heapGetM sl
access (ld1) fr
access _ v =
err $ "CoreRun.Run.Val.ref2valM.RRef_LDf.access:" >#< r >#< "in" >#< v
RRef_Fld r e -> do
v <- ptr2valM =<< ref2valM r
case v of
RVal_NodeMV _ vs -> liftIO $ MV.read vs e
_ -> err $ "CoreRun.Run.Val.ref2valM.RRef_Fld:" >#< e >#< "in" >#< v
RRef_Tag r -> do
v <- ptr2valM =<< ref2valM r
case v of
RVal_NodeMV t _ -> return $ RVal_Int t
_ -> err $ "CoreRun.Run.Val.ref2valM.RRef_Tag:" >#< v
_ -> err $ "CoreRun.Run.Val.ref2valM.r:" >#< r
return v
updTopFrameM :: (RunSem RValCxt RValEnv RVal m x) => (RVal -> RValT m RVal) -> RValT m ()
updTopFrameM f = renvTopFramePtrM >>= 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))
renvFrStkPushV :: RunSem RValCxt RValEnv RVal m x => RValV -> RValT m ()
renvFrStkPushV = renvFrStkPush' (\sp frvs vs -> mvecFillFromV sp frvs vs >> return (sp + V.length vs))
renvFrStkReversePushV :: RunSem RValCxt RValEnv RVal m x => RValV -> RValT m ()
renvFrStkReversePushV = renvFrStkPush' (\sp frvs vs -> mvecReverseFillFromV sp frvs vs >> return (sp + V.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) => TraceOn -> msg -> RValT m ()
rsemTr'' ton msg = do
tons <- rsemTraceOnS
dump <- dumpPpEnvM' (`Set.member` tons)
trOnPP (\t -> t `Set.member` tons) ton $ [pp msg] ++ dump
mkLabel ''RValCxt