load modules in wasm script commands

This commit is contained in:
Ilya Rezvov
2018-04-08 09:43:41 -07:00
parent 8c8cec0498
commit 43feccbf08
5 changed files with 93 additions and 47 deletions
+2
View File
@@ -5,6 +5,8 @@
module Language.Wasm.Interpreter (
Value(..),
Store,
ModuleInstance,
instantiate,
invoke,
invokeExport,
+14 -7
View File
@@ -29,7 +29,14 @@ module Language.Wasm.Parser (
Index(..),
Ident(..),
ParamType(..),
FuncType(..)
FuncType(..),
-- script
Script,
ModuleDef(..),
Command(..),
Action(..),
Assertion(..),
Meta(..)
) where
import Language.Wasm.Structure (
@@ -323,7 +330,7 @@ name :: { TL.Text }
: string { $1 }
ident :: { Ident }
: id { Ident (TL.toStrict (TLEncoding.decodeUtf8 $1)) }
: id { Ident (TLEncoding.decodeUtf8 $1) }
valtype :: { ValueType }
: 'i32' { I32 }
@@ -1017,8 +1024,8 @@ command1 :: { Command }
| meta1 { Meta $1 }
module1 :: { ModuleDef }
: 'module' opt(ident) 'binary' list(string) ')' { BinaryModDef $2 $4 }
| 'module' opt(ident) 'quote' list(string) ')' { TextModDef $2 $4 }
: 'module' opt(ident) 'binary' list(string) ')' { BinaryModDef $2 (TLEncoding.encodeUtf8 $ TL.concat $4) }
| 'module' opt(ident) 'quote' list(string) ')' { TextModDef $2 (TL.concat $4) }
| 'module' opt(ident) list(modulefield) ')' { RawModDef $2 (desugarize $ concat $3) }
| modulefield1 list(modulefield) { RawModDef Nothing (desugarize $ $1 ++ concat $2) }
@@ -1141,7 +1148,7 @@ data ParamType = ParamType {
paramType :: ValueType
} deriving (Show, Eq)
newtype Ident = Ident T.Text deriving (Show, Eq)
newtype Ident = Ident TL.Text deriving (Show, Eq)
data Index = Named Ident | Index Natural deriving (Show, Eq)
@@ -1366,8 +1373,8 @@ type Expression = [Instruction]
data ModuleDef
= RawModDef (Maybe Ident) S.Module
| TextModDef (Maybe Ident) [TL.Text]
| BinaryModDef (Maybe Ident) [TL.Text]
| TextModDef (Maybe Ident) TL.Text
| BinaryModDef (Maybe Ident) LBS.ByteString
deriving (Show, Eq)
data Command
+70
View File
@@ -0,0 +1,70 @@
module Language.Wasm.Script (
runScript,
OnAssertFail
) where
import qualified Data.Map as Map
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TLEncoding
import Language.Wasm.Parser (
Ident(..),
Script,
ModuleDef(..),
Command(..),
Action(..),
Assertion(..),
Meta(..)
)
import qualified Language.Wasm.Interpreter as Interpreter
import qualified Language.Wasm.Validate as Validate
import qualified Language.Wasm.Structure as Struct
import qualified Language.Wasm.Parser as Parser
import qualified Language.Wasm.Lexer as Lexer
import qualified Language.Wasm.Binary as Binary
type OnAssertFail = Assertion -> IO ()
data ScriptState = ScriptState {
store :: Interpreter.Store,
lastModule :: Maybe Interpreter.ModuleInstance,
modules :: Map.Map TL.Text Interpreter.ModuleInstance,
moduleRegistery :: Map.Map TL.Text Interpreter.ModuleInstance
}
emptyState :: ScriptState
emptyState = ScriptState {
store = Interpreter.emptyStore,
lastModule = Nothing,
modules = Map.empty,
moduleRegistery = Map.empty
}
runScript :: OnAssertFail -> Script -> IO ()
runScript onAssertFail script = go script emptyState
where
go [] _ = return ()
go (c:cs) st = runCommand st c >>= go cs
addToRegistery :: Maybe Ident -> Interpreter.ModuleInstance -> ScriptState -> ScriptState
addToRegistery (Just (Ident ident)) m st = st { moduleRegistery = Map.insert ident m $ moduleRegistery st }
addToRegistery Nothing _ st = st
addModule :: Maybe Ident -> Struct.Module -> ScriptState -> IO ScriptState
addModule ident m st =
case Validate.validate m of
Validate.Valid -> do
(modInst, store') <- Interpreter.instantiate (store st) Interpreter.emptyImports m
return $ addToRegistery ident modInst $ st { lastModule = Just modInst, store = store' }
reason -> error $ "Module instantiation failed dut to invalid module with reason: " ++ show reason
runCommand :: ScriptState -> Command -> IO ScriptState
runCommand st (ModuleDef (RawModDef ident m)) = addModule ident m st
runCommand st (ModuleDef (TextModDef ident textRep)) =
let Right m = Parser.parseModule <$> Lexer.scanner (TLEncoding.encodeUtf8 textRep) in
addModule ident m st
runCommand st (ModuleDef (BinaryModDef ident binaryRep)) =
let Right m = Binary.decodeModuleLazy binaryRep in
addModule ident m st
runCommand st _ = return st
+6 -40
View File
@@ -16,6 +16,7 @@ import qualified Language.Wasm.Structure as Structure
import qualified Language.Wasm.Binary as Binary
import qualified Language.Wasm.Validate as Validate
import qualified Language.Wasm.Interpreter as Interpreter
import qualified Language.Wasm.Script as Script
import qualified Debug.Trace as Debug
@@ -33,44 +34,9 @@ compile file = do
main :: IO ()
main = do
files <- Directory.listDirectory "tests/samples"
-- let files = ["call_indirect.wast"]
-- compile "fact.wast"
syntaxTestCases <- (`mapM` files) $ \file -> do
scriptTestCases <- (`mapM` files) $ \file -> do
content <- LBS.readFile $ "tests/samples/" ++ file
let result = Parser.parseScript <$> Lexer.scanner content
return $ testCase ("Parse module from core Test Suit: " ++ file) $
assertBool "Module parsed" $ isRight result
-- binaryTestCases <- (`mapM` files) $ \file -> do
-- content <- LBS.readFile $ "tests/samples/" ++ file
-- let Right mod = Parser.parseModule <$> Lexer.scanner content
-- let Right mod' = Binary.decodeModuleLazy $ Binary.dumpModuleLazy mod
-- return $ testCase ("Dump module to binary and parse back: " ++ file) $
-- assertEqual "Module matched" mod mod'
-- validationTestCases <- (`mapM` files) $ \file -> do
-- content <- LBS.readFile $ "tests/samples/" ++ file
-- let Right mod = Parser.parseModule <$> Lexer.scanner content
-- return $ testCase ("Validate module: " ++ file) $
-- case file of
-- "import.wast" ->
-- assertEqual "Too many tables" Validate.MoreThanOneTable $ Validate.validate mod
-- _ ->
-- assertBool "Module matched" $ Validate.isValid $ Validate.validate mod
-- interpretFactTestCases <- do
-- content <- LBS.readFile "tests/samples/fact.wast"
-- let Right mod = Parser.parseModule <$> Lexer.scanner content
-- (modInst, store) <- Interpreter.instantiate Interpreter.emptyStore Interpreter.emptyImports mod
-- (`mapM` ["fac-rec", "fac-rec-named", "fac-iter", "fac-iter-named", "fac-opt"]) $ \fn -> do
-- let fac = \n -> Interpreter.invokeExport store modInst fn [Interpreter.VI64 n]
-- fac3 <- fac 3
-- fac5 <- fac 5
-- fac8 <- fac 8
-- return $ testCase ("Interprete " ++ show fn) $ do
-- assertEqual "Fact 3! == 6" [Interpreter.VI64 6] fac3
-- assertEqual "Fact 5! == 120" [Interpreter.VI64 120] fac5
-- assertEqual "Fact 8! == 40320" [Interpreter.VI64 40320] fac8
defaultMain $ testGroup "tests" [
testGroup "Syntax parsing" syntaxTestCases
-- testGroup "Binary format" binaryTestCases,
-- testGroup "Validation" validationTestCases,
-- testGroup "Interpretation" interpretFactTestCases
]
let Right script = Parser.parseScript <$> Lexer.scanner content
return $ testCase file $ do
Script.runScript (assertFailure . ("Failed assert: " ++) . show) script
defaultMain $ testGroup "Wasm Core Test Suit" scriptTestCases
+1
View File
@@ -41,6 +41,7 @@ library
Language.Wasm.Binary
Language.Wasm.Validate
Language.Wasm.Interpreter
Language.Wasm.Script
Language.Wasm
other-modules:
Paths_wasm