module UHC.Light.Compiler.CoreRun.Run.Val.RunImplStk
( cmodRun )
where
import UHC.Light.Compiler.Base.HsName.Builtin
import UHC.Light.Compiler.Base.Common
import UHC.Light.Compiler.Opts
import UHC.Light.Compiler.Ty
import UHC.Light.Compiler.Error
import UHC.Light.Compiler.Gam
import UHC.Light.Compiler.Gam.DataGam
import UHC.Light.Compiler.CoreRun
import UHC.Light.Compiler.CoreRun.Run
import UHC.Light.Compiler.CoreRun.Run.Val
import UHC.Light.Compiler.CoreRun.Run.Val.Prim
import UHC.Light.Compiler.CoreRun.Pretty
import UHC.Util.Pretty
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
import qualified Data.ByteString.Char8 as BSC8
fillFrameM :: (RunSem RValCxt RValEnv RVal m RVal) => Int -> RValMV -> RVal -> RValT m ()
fillFrameM lwb as (RVal_Frame {rvalFrVals=frArr}) = do
liftIO $ mvecFillFromMV lwb frArr as
implStkAllocFrameM :: (RunSem RValCxt RValEnv RVal m RVal) => Ref2Nm -> HpPtr -> Int -> Int -> RValMV -> RValT m HpPtr
implStkAllocFrameM r2n sl lev sz as = do
a <- liftIO $ mvecAllocInit sz
slref <- liftIO $ newIORef sl
spref <- liftIO $ newIORef sz
let fr = RVal_Frame r2n slref lev a spref
fillFrameM 0 as fr
heapAllocM fr
implStkPushAllocFrameM :: (RunSem RValCxt RValEnv RVal m RVal) => Ref2Nm -> HpPtr -> Int -> Int -> RValMV -> RValT m ()
implStkPushAllocFrameM r2n sl lev sz as = do
p <- implStkAllocFrameM r2n sl lev sz as
(RValEnv {renvStack=st, renvTopFrame=tf}) <- get
liftIO $ do
t <- readIORef tf
unless (isNullPtr t) $ modifyIORef st (t:)
writeIORef tf p
implStkReplaceAllocFrameM :: (RunSem RValCxt RValEnv RVal m RVal) => Ref2Nm -> HpPtr -> Int -> Int -> RValMV -> RValT m ()
implStkReplaceAllocFrameM r2n sl lev sz as = do
p <- implStkAllocFrameM r2n sl lev sz as
(RValEnv {renvTopFrame=tf}) <- get
liftIO $ writeIORef tf p
implStkPopFrameM :: (RunSem RValCxt RValEnv RVal m RVal) => RValT m ()
implStkPopFrameM = do
(RValEnv {renvStack=st, renvTopFrame=tf}) <- get
liftIO $ do
stk <- readIORef st
case stk of
[] -> writeIORef tf nullPtr
(h:t) -> do
writeIORef tf h
writeIORef st t
cmodRun :: (RunSem RValCxt RValEnv RVal m RVal) => EHCOpts -> Mod -> RValT m RVal
cmodRun opts (Mod_Mod {body_Mod_Mod=e}) = do
v <- rsemExp e
return v
rvalImplStkAppLam :: RunSem RValCxt RValEnv RVal m RVal => HpPtr -> Exp -> RValMV -> (Int -> RValT m RVal) -> RValT m RVal
rvalImplStkAppLam sl f as failcont = do
case f of
Exp_Lam {lev_Exp_Lam=l, nrArgs_Exp_Lam=narg, stkDepth_Exp_Lam=sz, ref2nm_Exp_Lam=r2n, body_Exp_Lam=b}
| MV.length as == narg -> do
needRet <- asks rcxtInRet
if needRet
then do
implStkPushAllocFrameM r2n sl l sz as
v <- rsemExp b
implStkPopFrameM
return v
else do
implStkReplaceAllocFrameM r2n sl l sz as
mustReturn $ rsemExp b
| otherwise -> failcont narg
_ -> err $ "CoreRun.Run.Val.rvalImplStkAppLam:" >#< f
rvalImplStkApp :: RunSem RValCxt RValEnv RVal m RVal => RVal -> RValMV -> RValT m RVal
rvalImplStkApp f as = do
case f of
RVal_Lam {rvalSLRef=slref, rvalBody=b} -> do
sl <- liftIO $ readIORef slref
rvalImplStkAppLam sl b as $ \narg -> do
if MV.length as < narg
then do
return $ RVal_App f as
else do
ap <- rvalImplStkApp f (MV.take narg as)
rvalImplStkApp ap (MV.drop narg as)
RVal_App appf appas
| MV.length as > 0 -> do
(liftIO $ mvecAppend appas as) >>= rvalImplStkApp appf
_ -> err $ "CoreRun.Run.Val.rvalImplStkApp:" >#< f
rvalImplStkExp :: RunSem RValCxt RValEnv RVal m RVal => Exp -> RValT m RVal
rvalImplStkExp e = do
case e of
Exp_App f as -> do
f' <- rsemExp f
V.mapM rsemExp as >>= (liftIO . V.thaw) >>= rvalImplStkApp f'
Exp_Tup t as -> do
as' <- V.mapM rsemExp as >>= (liftIO . mvecAllocFillFromV)
rsemNode (ctagTag t) as'
Exp_Lam {nrArgs_Exp_Lam=na}
| na == 0 -> mk RVal_Thunk >>= heapAllocM >>= (liftIO . newIORef) >>= (return . RVal_Ptr)
| otherwise -> mk RVal_Lam
where mk rv = do
sl <- renvTopFrameM
slref <- liftIO $ newIORef sl
return $ rv e slref
Exp_Let {firstOff_Exp_Let=fillFrom, ref2nm_Exp_Let=r2n, binds_Exp_Let=bs, body_Exp_Let=b} -> do
bs' <- (liftIO . V.thaw) =<< V.forM bs rsemExp
fr <- renvTopFrameM >>= heapGetM
fillFrameM fillFrom bs' fr
rsemExp b
Exp_Case e as -> do
(RVal_Node {rvalTag=tg}) <- rsemSExp e
rsemAlt $ as V.! tg
Exp_Force e -> rsemExp e >>= rsemPop >>= rsemEvl
Exp_Ret e -> mustReturn $ rsemExp e
Exp_RetCase _ e -> rsemExp e
Exp_Tail e -> needNotReturn $ rsemExp e
Exp_SExp se -> rsemSExp se
Exp_FFI pr as -> V.mapM rsemExp as >>= rsemPrim pr
e -> err $ "CoreRun.Run.Val.RunExplStk.rvalImplStkExp:" >#< e
instance
( Monad m, MonadIO m, Functor m
) => RunSem RValCxt RValEnv RVal m RVal
where
rsemInitial = do
s <- liftIO $ newRValEnv 100000
return (emptyRValCxt, s, undefined)
rsemSetup opts modImpL mod = do
let modAllL = mod : modImpL
ms <- liftIO $ MV.new (maximum (map moduleNr_Mod_Mod modAllL) + 1)
forM_ modAllL $ \(Mod_Mod {ref2nm_Mod_Mod=r2n, moduleNr_Mod_Mod=nr, binds_Mod_Mod=bs}) -> do
bs' <- (liftIO . V.thaw) =<< V.forM bs rsemExp
p <- implStkAllocFrameM r2n nullPtr 0 (MV.length bs') bs'
liftIO $ MV.write ms nr p
ms' <- liftIO $ V.freeze ms
modify $ \env -> env {renvGlobals = ms'}
rsemSetTrace $ CoreOpt_RunTrace `elem` ehcOptCoreOpts opts
rsemSetTrace doTrace = modify $ \env ->
env {renvDoTrace = doTrace}
rsemExp = rvalImplStkExp
rsemSExp se = do
case se of
SExp_Int v -> rsemPush $ RVal_Int v
SExp_Char v -> rsemPush $ RVal_Char v
SExp_Var r -> do v <- ref2valM r
rsemPush v
SExp_String v -> rsemPush $ RVal_PackedString $ BSC8.pack v
_ -> rsemPush (RVal_Lit se)
rsemEvl v = case v of
RVal_Ptr {rvalPtrRef=pref} -> liftIO (readIORef pref) >>= evlPtr
RVal_BlackHole -> err $ "CoreRun.Run.Val.rsemEvl.RVal_BlackHole:" >#< "Black hole"
_ -> return v
where
evlPtr p = do
hp <- gets renvHeap
v <- heapGetM' hp p
v' <- case v of
RVal_Thunk {rvalSLRef=slref, rvalBody=e} -> do
sl <- liftIO $ readIORef slref
heapSetM' hp p RVal_BlackHole
v' <- liftIO (mvecAlloc 0) >>= \v -> rvalImplStkAppLam sl e v $ \_ -> err $ "CoreRun.Run.Val.rsemEvl.RVal_Thunk:" >#< e
heapSetM' hp p v'
return v'
RVal_Ptr {rvalPtrRef=pref} -> do
v' <- evlPtr =<< liftIO (readIORef pref)
heapSetM' hp p v'
return v'
v -> return v
return v'
rsemDeref v = do
v' <- ptr2valM v
return v'
rsemPrim = rvalPrim
rsemPush = return
rsemPop = return
rsemNode t vs = return $ RVal_Node t vs