use ExceptT transformer to clarify interpreter code
This commit is contained in:
@@ -50,6 +50,8 @@ import Data.Bits (
|
|||||||
countTrailingZeros
|
countTrailingZeros
|
||||||
)
|
)
|
||||||
import Numeric.IEEE (IEEE, copySign, minNum, maxNum, identicalIEEE)
|
import Numeric.IEEE (IEEE, copySign, minNum, maxNum, identicalIEEE)
|
||||||
|
import Control.Monad.Except (ExceptT, runExceptT, throwError)
|
||||||
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
|
||||||
import Debug.Trace as Debug
|
import Debug.Trace as Debug
|
||||||
|
|
||||||
@@ -484,28 +486,26 @@ allocMems mems = Vector.fromList <$> mapM allocMem mems
|
|||||||
memory
|
memory
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize :: ModuleInstance -> Module -> Store -> IO (Either String Store)
|
type Initialize = ExceptT String IO
|
||||||
|
|
||||||
|
initialize :: ModuleInstance -> Module -> Store -> Initialize Store
|
||||||
initialize inst Module {elems, datas, start} store = do
|
initialize inst Module {elems, datas, start} store = do
|
||||||
checkedMems <- Monad.foldM checkData (Right store) datas
|
checkedMems <- Monad.foldM checkData store datas
|
||||||
checkedTables <- Monad.foldM checkElem checkedMems elems
|
checkedTables <- Monad.foldM checkElem checkedMems elems
|
||||||
storeWithTables <- Monad.foldM initElem checkedMems elems
|
storeWithTables <- Monad.foldM initElem checkedMems elems
|
||||||
storeWithMems <- Monad.foldM initData storeWithTables datas
|
st <- Monad.foldM initData storeWithTables datas
|
||||||
case storeWithMems of
|
case start of
|
||||||
Right st -> do
|
Just (StartFunction idx) -> do
|
||||||
case start of
|
let funInst = funcInstances store ! (funcaddrs inst ! fromIntegral idx)
|
||||||
Just (StartFunction idx) -> do
|
mainRes <- liftIO $ eval defaultBudget st funInst []
|
||||||
let funInst = funcInstances store ! (funcaddrs inst ! fromIntegral idx)
|
case mainRes of
|
||||||
mainRes <- eval defaultBudget st funInst []
|
Just [] -> return st
|
||||||
case mainRes of
|
_ -> throwError "Start function terminated with trap"
|
||||||
Just [] -> return $ Right st
|
Nothing -> return st
|
||||||
_ -> return $ Left "Start function terminated with trap"
|
|
||||||
Nothing -> return $ Right st
|
|
||||||
Left reason -> return $ Left reason
|
|
||||||
where
|
where
|
||||||
checkElem :: Either String Store -> ElemSegment -> IO (Either String Store)
|
checkElem :: Store -> ElemSegment -> Initialize Store
|
||||||
checkElem (Left err) _ = return $ Left err
|
checkElem st ElemSegment {tableIndex, offset, funcIndexes} = do
|
||||||
checkElem (Right st) ElemSegment {tableIndex, offset, funcIndexes} = do
|
VI32 val <- liftIO $ evalConstExpr inst st offset
|
||||||
VI32 val <- evalConstExpr inst st offset
|
|
||||||
let from = fromIntegral val
|
let from = fromIntegral val
|
||||||
let funcs = map ((funcaddrs inst !) . fromIntegral) funcIndexes
|
let funcs = map ((funcaddrs inst !) . fromIntegral) funcIndexes
|
||||||
let idx = tableaddrs inst ! fromIntegral tableIndex
|
let idx = tableaddrs inst ! fromIntegral tableIndex
|
||||||
@@ -513,13 +513,12 @@ initialize inst Module {elems, datas, start} store = do
|
|||||||
let TableInstance lim elems = tableInstances st ! idx
|
let TableInstance lim elems = tableInstances st ! idx
|
||||||
let len = Vector.length elems
|
let len = Vector.length elems
|
||||||
if last > len
|
if last > len
|
||||||
then return $ Left "elements segment does not fit"
|
then throwError "elements segment does not fit"
|
||||||
else return $ Right st
|
else return st
|
||||||
|
|
||||||
initElem :: Either String Store -> ElemSegment -> IO (Either String Store)
|
initElem :: Store -> ElemSegment -> Initialize Store
|
||||||
initElem (Left err) _ = return $ Left err
|
initElem st ElemSegment {tableIndex, offset, funcIndexes} = do
|
||||||
initElem (Right st) ElemSegment {tableIndex, offset, funcIndexes} = do
|
VI32 val <- liftIO $ evalConstExpr inst st offset
|
||||||
VI32 val <- evalConstExpr inst st offset
|
|
||||||
let from = fromIntegral val
|
let from = fromIntegral val
|
||||||
let funcs = map ((funcaddrs inst !) . fromIntegral) funcIndexes
|
let funcs = map ((funcaddrs inst !) . fromIntegral) funcIndexes
|
||||||
let idx = tableaddrs inst ! fromIntegral tableIndex
|
let idx = tableaddrs inst ! fromIntegral tableIndex
|
||||||
@@ -527,36 +526,34 @@ initialize inst Module {elems, datas, start} store = do
|
|||||||
let TableInstance lim elems = tableInstances st ! idx
|
let TableInstance lim elems = tableInstances st ! idx
|
||||||
let len = Vector.length elems
|
let len = Vector.length elems
|
||||||
if last > len
|
if last > len
|
||||||
then return $ Left "elements segment does not fit"
|
then throwError "elements segment does not fit"
|
||||||
else do
|
else do
|
||||||
let table = TableInstance lim (elems // zip [from..] (map Just funcs))
|
let table = TableInstance lim (elems // zip [from..] (map Just funcs))
|
||||||
return $ Right st { tableInstances = tableInstances st Vector.// [(idx, table)] }
|
return st { tableInstances = tableInstances st Vector.// [(idx, table)] }
|
||||||
|
|
||||||
checkData :: Either String Store -> DataSegment -> IO (Either String Store)
|
checkData :: Store -> DataSegment -> Initialize Store
|
||||||
checkData (Left err) _ = return $ Left err
|
checkData st DataSegment {memIndex, offset, chunk} = do
|
||||||
checkData (Right st) DataSegment {memIndex, offset, chunk} = do
|
VI32 val <- liftIO $ evalConstExpr inst st offset
|
||||||
VI32 val <- evalConstExpr inst st offset
|
|
||||||
let from = fromIntegral val
|
let from = fromIntegral val
|
||||||
let idx = memaddrs inst ! fromIntegral memIndex
|
let idx = memaddrs inst ! fromIntegral memIndex
|
||||||
let last = from + (fromIntegral $ LBS.length chunk)
|
let last = from + (fromIntegral $ LBS.length chunk)
|
||||||
let MemoryInstance _ memory = memInstances st ! idx
|
let MemoryInstance _ memory = memInstances st ! idx
|
||||||
mem <- readIORef memory
|
mem <- liftIO $ readIORef memory
|
||||||
let len = IOVector.length mem
|
let len = IOVector.length mem
|
||||||
if last > len
|
if last > len
|
||||||
then return $ Left "data segment does not fit"
|
then throwError "data segment does not fit"
|
||||||
else return $ Right st
|
else return st
|
||||||
|
|
||||||
initData :: Either String Store -> DataSegment -> IO (Either String Store)
|
initData :: Store -> DataSegment -> Initialize Store
|
||||||
initData (Left err) _ = return $ Left err
|
initData st DataSegment {memIndex, offset, chunk} = do
|
||||||
initData (Right st) DataSegment {memIndex, offset, chunk} = do
|
VI32 val <- liftIO $ evalConstExpr inst st offset
|
||||||
VI32 val <- evalConstExpr inst st offset
|
|
||||||
let from = fromIntegral val
|
let from = fromIntegral val
|
||||||
let idx = memaddrs inst ! fromIntegral memIndex
|
let idx = memaddrs inst ! fromIntegral memIndex
|
||||||
let last = from + (fromIntegral $ LBS.length chunk)
|
let last = from + (fromIntegral $ LBS.length chunk)
|
||||||
let MemoryInstance _ memory = memInstances st ! idx
|
let MemoryInstance _ memory = memInstances st ! idx
|
||||||
mem <- readIORef memory
|
mem <- liftIO $ readIORef memory
|
||||||
mapM_ (\(i,b) -> IOVector.write mem i b) $ zip [from..] $ LBS.unpack chunk
|
mapM_ (\(i,b) -> IOVector.write mem i b) $ zip [from..] $ LBS.unpack chunk
|
||||||
return $ Right st
|
return st
|
||||||
|
|
||||||
instantiate :: Store -> Imports -> Module -> IO (Either String (ModuleInstance, Store))
|
instantiate :: Store -> Imports -> Module -> IO (Either String (ModuleInstance, Store))
|
||||||
instantiate st imps m =
|
instantiate st imps m =
|
||||||
@@ -567,7 +564,7 @@ instantiate st imps m =
|
|||||||
globals <- (globalInstances st <>) <$> (allocAndInitGlobals inst st $ Struct.globals m)
|
globals <- (globalInstances st <>) <$> (allocAndInitGlobals inst st $ Struct.globals m)
|
||||||
let tables = tableInstances st <> (allocTables $ Struct.tables m)
|
let tables = tableInstances st <> (allocTables $ Struct.tables m)
|
||||||
mems <- (memInstances st <>) <$> (allocMems $ Struct.mems m)
|
mems <- (memInstances st <>) <$> (allocMems $ Struct.mems m)
|
||||||
st' <- initialize inst m $ st {
|
st' <- runExceptT $ initialize inst m $ st {
|
||||||
funcInstances = functions,
|
funcInstances = functions,
|
||||||
tableInstances = tables,
|
tableInstances = tables,
|
||||||
memInstances = mems,
|
memInstances = mems,
|
||||||
|
|||||||
Reference in New Issue
Block a user