add actions interpretatiion
This commit is contained in:
@@ -15,6 +15,7 @@ module Language.Wasm.Interpreter (
|
|||||||
instantiate,
|
instantiate,
|
||||||
invoke,
|
invoke,
|
||||||
invokeExport,
|
invokeExport,
|
||||||
|
getGlobalValueByName,
|
||||||
emptyStore,
|
emptyStore,
|
||||||
emptyImports,
|
emptyImports,
|
||||||
makeHostModule,
|
makeHostModule,
|
||||||
@@ -1044,3 +1045,13 @@ invokeExport st ModuleInstance { exports } name args =
|
|||||||
case Vector.find (\(ExportInstance n _) -> n == name) exports of
|
case Vector.find (\(ExportInstance n _) -> n == name) exports of
|
||||||
Just (ExportInstance _ (ExternFunction addr)) -> invoke st addr args
|
Just (ExportInstance _ (ExternFunction addr)) -> invoke st addr args
|
||||||
_ -> error $ "Function with name " ++ show name ++ " was not found in module's exports"
|
_ -> error $ "Function with name " ++ show name ++ " was not found in module's exports"
|
||||||
|
|
||||||
|
getGlobalValueByName :: Store -> ModuleInstance -> TL.Text -> IO Value
|
||||||
|
getGlobalValueByName store ModuleInstance { exports } name =
|
||||||
|
case Vector.find (\(ExportInstance n _) -> n == name) exports of
|
||||||
|
Just (ExportInstance _ (ExternGlobal addr)) ->
|
||||||
|
let globalInst = globalInstances store ! addr in
|
||||||
|
case globalInst of
|
||||||
|
GIConst v -> return v
|
||||||
|
GIMut ref -> readIORef ref
|
||||||
|
_ -> error $ "Function with name " ++ show name ++ " was not found in module's exports"
|
||||||
@@ -1030,11 +1030,11 @@ module1 :: { ModuleDef }
|
|||||||
| modulefield1 list(modulefield) { RawModDef Nothing (desugarize $ $1 ++ concat $2) }
|
| modulefield1 list(modulefield) { RawModDef Nothing (desugarize $ $1 ++ concat $2) }
|
||||||
|
|
||||||
action1 :: { Action }
|
action1 :: { Action }
|
||||||
: 'invoke' opt(ident) string list(foldedinstr) ')' { Invoke $2 $3 $4 }
|
: 'invoke' opt(ident) string list(foldedinstr) ')' { Invoke $2 $3 (map (map constInstructionToValue) $4) }
|
||||||
| 'get' opt(ident) string ')' { Get $2 $3 }
|
| 'get' opt(ident) string ')' { Get $2 $3 }
|
||||||
|
|
||||||
assertion1 :: { Assertion }
|
assertion1 :: { Assertion }
|
||||||
: 'assert_return' '(' action1 list(foldedinstr) ')' { AssertReturn $3 $4 }
|
: 'assert_return' '(' action1 list(foldedinstr) ')' { AssertReturn $3 (map (map constInstructionToValue) $4) }
|
||||||
| 'assert_return_canonical_nan' '(' action1 ')' { AssertReturnCanonicalNaN $3 }
|
| 'assert_return_canonical_nan' '(' action1 ')' { AssertReturnCanonicalNaN $3 }
|
||||||
| 'assert_return_arithmetic_nan' '(' action1 ')' { AssertReturnArithmeticNaN $3 }
|
| 'assert_return_arithmetic_nan' '(' action1 ')' { AssertReturnArithmeticNaN $3 }
|
||||||
| 'assert_trap' '(' assertion_trap string ')' { AssertTrap $3 $4 }
|
| 'assert_trap' '(' assertion_trap string ')' { AssertTrap $3 $4 }
|
||||||
@@ -1383,14 +1383,14 @@ data Command
|
|||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data Action
|
data Action
|
||||||
= Invoke (Maybe Ident) TL.Text [Expression]
|
= Invoke (Maybe Ident) TL.Text [[S.Instruction]]
|
||||||
| Get (Maybe Ident) TL.Text
|
| Get (Maybe Ident) TL.Text
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
type FailureString = TL.Text
|
type FailureString = TL.Text
|
||||||
|
|
||||||
data Assertion
|
data Assertion
|
||||||
= AssertReturn Action [Expression]
|
= AssertReturn Action [[S.Instruction]]
|
||||||
| AssertReturnCanonicalNaN Action
|
| AssertReturnCanonicalNaN Action
|
||||||
| AssertReturnArithmeticNaN Action
|
| AssertReturnArithmeticNaN Action
|
||||||
| AssertTrap (Either Action ModuleDef) FailureString
|
| AssertTrap (Either Action ModuleDef) FailureString
|
||||||
@@ -1415,6 +1415,13 @@ data FunCtx = FunCtx {
|
|||||||
ctxParams :: [ParamType]
|
ctxParams :: [ParamType]
|
||||||
} deriving (Eq, Show)
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
|
constInstructionToValue :: Instruction -> S.Instruction
|
||||||
|
constInstructionToValue (PlainInstr (I32Const v)) = S.I32Const $ integerToWord32 v
|
||||||
|
constInstructionToValue (PlainInstr (F32Const v)) = S.F32Const v
|
||||||
|
constInstructionToValue (PlainInstr (I64Const v)) = S.I64Const $ integerToWord64 v
|
||||||
|
constInstructionToValue (PlainInstr (F64Const v)) = S.F64Const v
|
||||||
|
constInstructionToValue _ = error "Only const instructions supported as arguments for actions"
|
||||||
|
|
||||||
desugarize :: [ModuleField] -> S.Module
|
desugarize :: [ModuleField] -> S.Module
|
||||||
desugarize fields =
|
desugarize fields =
|
||||||
let mod = Module {
|
let mod = Module {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ runScript onAssertFail script = do
|
|||||||
]
|
]
|
||||||
go script $ emptyState { store = st, moduleRegistery = Map.singleton "spectest" inst }
|
go script $ emptyState { store = st, moduleRegistery = Map.singleton "spectest" inst }
|
||||||
where
|
where
|
||||||
hostPrint paramTypes = Interpreter.HostFunction (Struct.FuncType paramTypes []) (\args -> print args >> return [])
|
hostPrint paramTypes = Interpreter.HostFunction (Struct.FuncType paramTypes []) (const $ return [])
|
||||||
hostGlobals = do
|
hostGlobals = do
|
||||||
globI32 <- Interpreter.makeMutGlobal $ Interpreter.VI32 666
|
globI32 <- Interpreter.makeMutGlobal $ Interpreter.VI32 666
|
||||||
globF32 <- Interpreter.makeMutGlobal $ Interpreter.VF32 666
|
globF32 <- Interpreter.makeMutGlobal $ Interpreter.VF32 666
|
||||||
@@ -102,6 +102,23 @@ runScript onAssertFail script = do
|
|||||||
getModule st (Just (Ident i)) = Map.lookup i (modules st)
|
getModule st (Just (Ident i)) = Map.lookup i (modules st)
|
||||||
getModule st Nothing = lastModule st
|
getModule st Nothing = lastModule st
|
||||||
|
|
||||||
|
asArg :: [Struct.Instruction] -> Interpreter.Value
|
||||||
|
asArg [Struct.I32Const v] = Interpreter.VI32 v
|
||||||
|
asArg [Struct.F32Const v] = Interpreter.VF32 v
|
||||||
|
asArg [Struct.I64Const v] = Interpreter.VI64 v
|
||||||
|
asArg [Struct.F64Const v] = Interpreter.VF64 v
|
||||||
|
asArg _ = error "Only const instructions supported as arguments for actions"
|
||||||
|
|
||||||
|
runAction :: ScriptState -> Action -> IO [Interpreter.Value]
|
||||||
|
runAction st (Invoke ident name args) = do
|
||||||
|
case getModule st ident of
|
||||||
|
Just m -> Interpreter.invokeExport (store st) m name $ map asArg args
|
||||||
|
Nothing -> error $ "Cannot invoke function on module with identifier '" ++ show ident ++ "'. No such module"
|
||||||
|
runAction st (Get ident name) = do
|
||||||
|
case getModule st ident of
|
||||||
|
Just m -> Interpreter.getGlobalValueByName (store st) m name >>= return . (: [])
|
||||||
|
Nothing -> error $ "Cannot invoke function on module with identifier '" ++ show ident ++ "'. No such module"
|
||||||
|
|
||||||
runCommand :: ScriptState -> Command -> IO ScriptState
|
runCommand :: ScriptState -> Command -> IO ScriptState
|
||||||
runCommand st (ModuleDef (RawModDef ident m)) = addModule ident m st
|
runCommand st (ModuleDef (RawModDef ident m)) = addModule ident m st
|
||||||
runCommand st (ModuleDef (TextModDef ident textRep)) =
|
runCommand st (ModuleDef (TextModDef ident textRep)) =
|
||||||
@@ -111,4 +128,5 @@ runScript onAssertFail script = do
|
|||||||
let Right m = Binary.decodeModuleLazy binaryRep in
|
let Right m = Binary.decodeModuleLazy binaryRep in
|
||||||
addModule ident m st
|
addModule ident m st
|
||||||
runCommand st (Register name i) = return $ addToRegistery name i st
|
runCommand st (Register name i) = return $ addToRegistery name i st
|
||||||
|
runCommand st (Action action) = runAction st action >> return st
|
||||||
runCommand st _ = return st
|
runCommand st _ = return st
|
||||||
|
|||||||
Reference in New Issue
Block a user