bump version to 1.0 tag

This commit is contained in:
Ilya Rezvov
2018-06-20 16:33:52 -07:00
parent db18150ec9
commit 709c8d994c
9 changed files with 137 additions and 132 deletions
+2 -7
View File
@@ -5,9 +5,7 @@ import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Base64.Lazy as Base64 import qualified Data.ByteString.Base64.Lazy as Base64
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import qualified Language.Wasm.Lexer as Lexer import qualified Language.Wasm as Wasm
import qualified Language.Wasm.Parser as Parser
import qualified Language.Wasm.Binary as Binary
import Options.Applicative import Options.Applicative
import Data.Semigroup ((<>)) import Data.Semigroup ((<>))
@@ -105,10 +103,7 @@ config = subparser (
) )
toBinary :: LBS.ByteString -> Either String LBS.ByteString toBinary :: LBS.ByteString -> Either String LBS.ByteString
toBinary content = do toBinary = fmap Wasm.encodeLazy . Wasm.parse
lexemes <- Lexer.scanner content
mod <- Parser.parseModule lexemes
return $ Binary.dumpModuleLazy mod
compileAs :: (LBS.ByteString -> LBS.ByteString) -> String -> String -> IO () compileAs :: (LBS.ByteString -> LBS.ByteString) -> String -> String -> IO ()
compileAs transform input output = do compileAs transform input output = do
+45 -3
View File
@@ -1,6 +1,48 @@
module Language.Wasm ( module Language.Wasm (
something Module,
ValidModule,
ValidationError(..),
parse,
validate,
Language.Wasm.parseScript,
encode,
encodeLazy,
decode,
decodeLazy,
Script,
runScript
) where ) where
something :: Int import qualified Data.ByteString as BS
something = 42 import qualified Data.ByteString.Lazy as LBS
import Language.Wasm.Structure as Struct
import Language.Wasm.Script as Script
import Language.Wasm.Lexer as Lexer
import Language.Wasm.Parser as Parser
import Language.Wasm.Validate as Valid
import Language.Wasm.Binary as Binary
-- | Parse WebAssembly text representation to `Module`
parse :: LBS.ByteString -> Either String Module
parse content = Lexer.scanner content >>= Parser.parseModule
-- | Parse WebAssembly extended scipt grammar
parseScript :: LBS.ByteString -> Either String Script
parseScript content = Lexer.scanner content >>= Parser.parseScript
-- | Dump `Module` to binary representation
encode :: Module -> BS.ByteString
encode = dumpModule
-- | Dump `Module` to binary representation lazily
encodeLazy :: Module -> LBS.ByteString
encodeLazy = dumpModuleLazy
-- | Decode `Module` from binary representation
decode :: BS.ByteString -> Either String Module
decode = decodeModule
-- | Decode `Module` from binary representation lazily
decodeLazy :: LBS.ByteString -> Either String Module
decodeLazy = decodeModuleLazy
+4 -4
View File
@@ -53,9 +53,8 @@ import Numeric.IEEE (IEEE, copySign, minNum, maxNum, identicalIEEE)
import Control.Monad.Except (ExceptT, runExceptT, throwError) import Control.Monad.Except (ExceptT, runExceptT, throwError)
import Control.Monad.IO.Class (liftIO) import Control.Monad.IO.Class (liftIO)
import Debug.Trace as Debug
import Language.Wasm.Structure as Struct import Language.Wasm.Structure as Struct
import Language.Wasm.Validate as Valid
import Language.Wasm.FloatUtils ( import Language.Wasm.FloatUtils (
wordToFloat, wordToFloat,
floatToWord, floatToWord,
@@ -532,8 +531,9 @@ initialize inst Module {elems, datas, start} store = do
initData (from, mem, chunk) = initData (from, mem, chunk) =
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
instantiate :: Store -> Imports -> Module -> IO (Either String (ModuleInstance, Store)) instantiate :: Store -> Imports -> Valid.ValidModule -> IO (Either String (ModuleInstance, Store))
instantiate st imps m = runExceptT $ do instantiate st imps mod = runExceptT $ do
let m = Valid.getModule mod
inst <- calcInstance st imps m inst <- calcInstance st imps m
let functions = funcInstances st <> (allocFunctions inst $ Struct.functions m) let functions = funcInstances st <> (allocFunctions inst $ Struct.functions m)
globals <- liftIO $ (globalInstances st <>) <$> (allocAndInitGlobals inst st $ Struct.globals m) globals <- liftIO $ (globalInstances st <>) <$> (allocAndInitGlobals inst st $ Struct.globals m)
-2
View File
@@ -21,8 +21,6 @@ import Data.Word (Word8)
import Data.List (isPrefixOf) import Data.List (isPrefixOf)
import Text.Read (readEither) import Text.Read (readEither)
import qualified Debug.Trace as Debug
} }
%wrapper "monadUserState-bytestring" %wrapper "monadUserState-bytestring"
-2
View File
@@ -96,8 +96,6 @@ import Language.Wasm.Lexer (
asDouble asDouble
) )
import Debug.Trace as Debug
} }
%name parseModule mod %name parseModule mod
+9 -9
View File
@@ -95,12 +95,12 @@ runScript onAssertFail script = do
addModule :: Maybe Ident -> Struct.Module -> ScriptState -> IO ScriptState addModule :: Maybe Ident -> Struct.Module -> ScriptState -> IO ScriptState
addModule ident m st = addModule ident m st =
case Validate.validate m of case Validate.validate m of
Validate.Valid -> do Right m -> do
res <- Interpreter.instantiate (store st) (buildImports st) m res <- Interpreter.instantiate (store st) (buildImports st) m
case res of case res of
Right (modInst, store') -> return $ addToStore ident modInst $ st { lastModule = Just modInst, store = store' } Right (modInst, store') -> return $ addToStore ident modInst $ st { lastModule = Just modInst, store = store' }
Left reason -> error $ "Module instantiation failed dut to invalid module with reason: " ++ show reason Left reason -> error $ "Module instantiation failed dut to invalid module with reason: " ++ show reason
reason -> error $ "Module instantiation failed dut to invalid module with reason: " ++ show reason Left reason -> error $ "Module instantiation failed dut to invalid module with reason: " ++ show reason
getModule :: ScriptState -> Maybe Ident -> Maybe Interpreter.ModuleInstance getModule :: ScriptState -> Maybe Ident -> Maybe Interpreter.ModuleInstance
getModule st (Just (Ident i)) = Map.lookup i (modules st) getModule st (Just (Ident i)) = Map.lookup i (modules st)
@@ -156,7 +156,7 @@ runScript onAssertFail script = do
checkModuleInvalid :: Struct.Module -> IO () checkModuleInvalid :: Struct.Module -> IO ()
checkModuleInvalid _ = return () checkModuleInvalid _ = return ()
getFailureString :: Validate.ValidationResult -> [TL.Text] getFailureString :: Validate.ValidationError -> [TL.Text]
getFailureString (Validate.TypeMismatch _ _) = ["type mismatch"] getFailureString (Validate.TypeMismatch _ _) = ["type mismatch"]
getFailureString Validate.ResultTypeDoesntMatch = ["type mismatch"] getFailureString Validate.ResultTypeDoesntMatch = ["type mismatch"]
getFailureString Validate.MoreThanOneMemory = ["multiple memories"] getFailureString Validate.MoreThanOneMemory = ["multiple memories"]
@@ -194,8 +194,8 @@ runScript onAssertFail script = do
runAssert st assert@(AssertInvalid moduleDef failureString) = runAssert st assert@(AssertInvalid moduleDef failureString) =
let (_, m) = buildModule moduleDef in let (_, m) = buildModule moduleDef in
case Validate.validate m of case Validate.validate m of
Validate.Valid -> onAssertFail "Invalid module pass validation" assert Right _ -> onAssertFail "Invalid module pass validation" assert
reason -> Left reason ->
if failureString `elem` getFailureString reason if failureString `elem` getFailureString reason
then return () then return ()
else else
@@ -216,12 +216,12 @@ runScript onAssertFail script = do
runAssert st assert@(AssertUnlinkable moduleDef failureString) = runAssert st assert@(AssertUnlinkable moduleDef failureString) =
let (_, m) = buildModule moduleDef in let (_, m) = buildModule moduleDef in
case Validate.validate m of case Validate.validate m of
Validate.Valid -> do Right m -> do
res <- Interpreter.instantiate (store st) (buildImports st) m res <- Interpreter.instantiate (store st) (buildImports st) m
case res of case res of
Left err -> return () Left err -> return ()
Right _ -> onAssertFail ("Module linking should fail with failure string " ++ show failureString) assert Right _ -> onAssertFail ("Module linking should fail with failure string " ++ show failureString) assert
reason -> error $ "Module linking failed dut to invalid module with reason: " ++ show reason Left reason -> error $ "Module linking failed dut to invalid module with reason: " ++ show reason
runAssert st assert@(AssertTrap (Left action) failureString) = do runAssert st assert@(AssertTrap (Left action) failureString) = do
result <- runAction st action result <- runAction st action
if isNothing result if isNothing result
@@ -230,12 +230,12 @@ runScript onAssertFail script = do
runAssert st assert@(AssertTrap (Right moduleDef) failureString) = runAssert st assert@(AssertTrap (Right moduleDef) failureString) =
let (_, m) = buildModule moduleDef in let (_, m) = buildModule moduleDef in
case Validate.validate m of case Validate.validate m of
Validate.Valid -> do Right m -> do
res <- Interpreter.instantiate (store st) (buildImports st) m res <- Interpreter.instantiate (store st) (buildImports st) m
case res of case res of
Left "Start function terminated with trap" -> return () Left "Start function terminated with trap" -> return ()
_ -> onAssertFail ("Module linking should fail with trap during execution of a start function") assert _ -> onAssertFail ("Module linking should fail with trap during execution of a start function") assert
reason -> error $ "Module linking failed dut to invalid module with reason: " ++ show reason Left reason -> error $ "Module linking failed dut to invalid module with reason: " ++ show reason
runAssert st assert@(AssertExhaustion action failureString) = do runAssert st assert@(AssertExhaustion action failureString) = do
result <- runAction st action result <- runAction st action
if isNothing result if isNothing result
+72 -74
View File
@@ -3,9 +3,12 @@
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
module Language.Wasm.Validate ( module Language.Wasm.Validate (
ValidationError(..),
ValidationResult(..), ValidationResult(..),
validate, validate,
isValid isValid,
ValidModule,
getModule
) where ) where
import Language.Wasm.Structure import Language.Wasm.Structure
@@ -22,7 +25,7 @@ import Control.Monad.Except (Except, runExcept, throwError)
import Debug.Trace as Debug import Debug.Trace as Debug
data ValidationResult = data ValidationError =
DuplicatedExportNames [String] DuplicatedExportNames [String]
| InvalidTableType | InvalidTableType
| MinMoreThanMaxInMemoryLimit | MinMoreThanMaxInMemoryLimit
@@ -45,18 +48,19 @@ data ValidationResult =
| ImportedGlobalIsNotConst | ImportedGlobalIsNotConst
| ExportedGlobalIsNotConst | ExportedGlobalIsNotConst
| GlobalIsImmutable | GlobalIsImmutable
| Valid
deriving (Show, Eq) deriving (Show, Eq)
type ValidationResult = Either ValidationError ()
instance Monoid ValidationResult where instance Monoid ValidationResult where
mempty = Valid mempty = Right ()
mappend Valid vr = vr mappend (Right ()) vr = vr
mappend vr Valid = vr mappend vr (Right ()) = vr
mappend vr _ = vr mappend vr _ = vr
isValid :: ValidationResult -> Bool isValid :: ValidationResult -> Bool
isValid Valid = True isValid (Right ()) = True
isValid reason = Debug.trace ("Module mismatched with reason " ++ show reason) $ False isValid (Left reason) = Debug.trace ("Module mismatched with reason " ++ show reason) $ False
type Validator = Module -> ValidationResult type Validator = Module -> ValidationResult
@@ -129,12 +133,12 @@ data Ctx = Ctx {
importedGlobals :: Natural importedGlobals :: Natural
} deriving (Show, Eq) } deriving (Show, Eq)
type Checker = ReaderT Ctx (Except ValidationResult) type Checker = ReaderT Ctx (Except ValidationError)
freshVar :: Checker VType freshVar :: Checker VType
freshVar = return Var freshVar = return Var
runChecker :: Ctx -> Checker a -> Either ValidationResult a runChecker :: Ctx -> Checker a -> Either ValidationError a
runChecker ctx = runExcept . flip runReaderT ctx runChecker ctx = runExcept . flip runReaderT ctx
(!?) :: [a] -> Natural -> Maybe a (!?) :: [a] -> Natural -> Maybe a
@@ -146,7 +150,7 @@ safeHead :: [a] -> Maybe a
safeHead (x: _) = Just x safeHead (x: _) = Just x
safeHead [] = Nothing safeHead [] = Nothing
maybeToEither :: ValidationResult -> Maybe a -> Checker a maybeToEither :: ValidationError -> Maybe a -> Checker a
maybeToEither _ (Just a) = return a maybeToEither _ (Just a) = return a
maybeToEither l Nothing = throwError l maybeToEither l Nothing = throwError l
@@ -453,17 +457,15 @@ isFunctionValid Function {funcType, localTypes = locals, body} mod@Module {types
then then
let FuncType params results = types !! fromIntegral funcType in let FuncType params results = types !! fromIntegral funcType in
if length results > 1 if length results > 1
then InvalidResultArity then Left InvalidResultArity
else else do
let r = safeHead results in let r = safeHead results
let ctx = ctxFromModule (params ++ locals) [r] r mod in let ctx = ctxFromModule (params ++ locals) [r] r mod
case runChecker ctx $ getExpressionType body of arr <- runChecker ctx $ getExpressionType body
Left err -> err if isArrowMatch arr (empty ==> results)
Right arr -> then return ()
if isArrowMatch arr (empty ==> results) else Left $ TypeMismatch arr (empty ==> results)
then Valid else Left TypeIndexOutOfRange
else TypeMismatch arr (empty ==> results)
else TypeIndexOutOfRange
functionsShouldBeValid :: Validator functionsShouldBeValid :: Validator
functionsShouldBeValid mod@Module {functions} = functionsShouldBeValid mod@Module {functions} =
@@ -476,13 +478,13 @@ tablesShouldBeValid Module { imports, tables } =
let res' = foldl' (\r (Table t) -> r <> isValidTableType t) res tables in let res' = foldl' (\r (Table t) -> r <> isValidTableType t) res tables in
if length tableImports + length tables <= 1 if length tableImports + length tables <= 1
then res' then res'
else MoreThanOneTable else Left MoreThanOneTable
where where
isValidTableType :: TableType -> ValidationResult isValidTableType :: TableType -> ValidationResult
isValidTableType (TableType (Limit min max) _) = isValidTableType (TableType (Limit min max) _) =
if min <= fromMaybe min max if min <= fromMaybe min max
then Valid then return ()
else InvalidTableType else Left InvalidTableType
memoryShouldBeValid :: Validator memoryShouldBeValid :: Validator
memoryShouldBeValid Module { imports, mems } = memoryShouldBeValid Module { imports, mems } =
@@ -491,12 +493,12 @@ memoryShouldBeValid Module { imports, mems } =
let res' = foldl' (\r (Memory l) -> r <> isValidLimit l) res mems in let res' = foldl' (\r (Memory l) -> r <> isValidLimit l) res mems in
if length memImports + length mems <= 1 if length memImports + length mems <= 1
then res' then res'
else MoreThanOneMemory else Left MoreThanOneMemory
where where
isValidLimit :: Limit -> ValidationResult isValidLimit :: Limit -> ValidationResult
isValidLimit (Limit min max) = isValidLimit (Limit min max) =
let minMax = if min <= fromMaybe min max then Valid else MinMoreThanMaxInMemoryLimit in let minMax = if min <= fromMaybe min max then return () else Left MinMoreThanMaxInMemoryLimit in
let maxLim = if fromMaybe min max <= 65536 then Valid else MemoryLimitExceeded in let maxLim = if fromMaybe min max <= 65536 then return () else Left MemoryLimitExceeded in
minMax <> maxLim minMax <> maxLim
globalsShouldBeValid :: Validator globalsShouldBeValid :: Validator
@@ -509,16 +511,11 @@ globalsShouldBeValid m@Module { imports, globals } =
getGlobalType (Mut vt) = vt getGlobalType (Mut vt) = vt
isGlobalValid :: Ctx -> Global -> ValidationResult isGlobalValid :: Ctx -> Global -> ValidationResult
isGlobalValid ctx (Global gt init) = isGlobalValid ctx (Global gt init) = runChecker ctx $ do
let check = runChecker ctx $ do isConstExpression init
isConstExpression init t <- getExpressionType init
t <- getExpressionType init let expected = empty ==> getGlobalType gt
let expected = empty ==> getGlobalType gt if isArrowMatch expected t then return () else throwError $ TypeMismatch t expected
return $ if isArrowMatch expected t then Valid else TypeMismatch t expected
in
case check of
Left err -> err
Right res -> res
elemsShouldBeValid :: Validator elemsShouldBeValid :: Validator
elemsShouldBeValid m@Module { elems, functions, tables, imports } = elemsShouldBeValid m@Module { elems, functions, tables, imports } =
@@ -530,22 +527,20 @@ elemsShouldBeValid m@Module { elems, functions, tables, imports } =
let check = runChecker ctx $ do let check = runChecker ctx $ do
isConstExpression offset isConstExpression offset
t <- getExpressionType offset t <- getExpressionType offset
return $ if isArrowMatch (empty ==> I32) t then Valid else TypeMismatch t (empty ==> I32) if isArrowMatch (empty ==> I32) t
in then return ()
let isIniterValid = case check of else throwError $ TypeMismatch t (empty ==> I32)
Left err -> err
Right res -> res
in in
let tableImports = filter isTableImport imports in let tableImports = filter isTableImport imports in
let isTableIndexValid = let isTableIndexValid =
if tableIdx < (fromIntegral $ length tableImports + length tables) if tableIdx < (fromIntegral $ length tableImports + length tables)
then Valid then return ()
else TableIndexOutOfRange else Left TableIndexOutOfRange
in in
let funImports = filter isFuncImport imports in let funImports = filter isFuncImport imports in
let funsLength = fromIntegral $ length functions + length funImports in let funsLength = fromIntegral $ length functions + length funImports in
let isFunsValid = foldMap (\i -> if i < funsLength then Valid else FunctionIndexOutOfRange) funs in let isFunsValid = foldMap (\i -> if i < funsLength then return () else Left FunctionIndexOutOfRange) funs in
isIniterValid <> isFunsValid <> isTableIndexValid check <> isFunsValid <> isTableIndexValid
datasShouldBeValid :: Validator datasShouldBeValid :: Validator
datasShouldBeValid m@Module { datas, mems, imports } = datasShouldBeValid m@Module { datas, mems, imports } =
@@ -557,25 +552,23 @@ datasShouldBeValid m@Module { datas, mems, imports } =
let check = runChecker ctx $ do let check = runChecker ctx $ do
isConstExpression offset isConstExpression offset
t <- getExpressionType offset t <- getExpressionType offset
return $ if isArrowMatch (empty ==> I32) t then Valid else TypeMismatch t (empty ==> I32) if isArrowMatch (empty ==> I32) t
in then return ()
let isOffsetValid = case check of else throwError $ TypeMismatch t (empty ==> I32)
Left err -> err
Right res -> res
in in
let memImports = filter isMemImport imports in let memImports = filter isMemImport imports in
if memIdx < (fromIntegral $ length memImports + length mems) if memIdx < (fromIntegral $ length memImports + length mems)
then isOffsetValid then check
else MemoryIndexOutOfRange else Left MemoryIndexOutOfRange
startShouldBeValid :: Validator startShouldBeValid :: Validator
startShouldBeValid Module { start = Nothing } = Valid startShouldBeValid Module { start = Nothing } = return ()
startShouldBeValid m@Module { start = Just (StartFunction idx) } = startShouldBeValid m@Module { start = Just (StartFunction idx) } =
let types = getFuncTypes m in let types = getFuncTypes m in
let i = fromIntegral idx in let i = fromIntegral idx in
if length types > i if length types > i
then if FuncType [] [] == types !! i then Valid else InvalidStartFunctionType then if FuncType [] [] == types !! i then return () else Left InvalidStartFunctionType
else FunctionIndexOutOfRange else Left FunctionIndexOutOfRange
exportsShouldBeValid :: Validator exportsShouldBeValid :: Validator
exportsShouldBeValid Module { exports, imports, functions, mems, tables, globals } = exportsShouldBeValid Module { exports, imports, functions, mems, tables, globals } =
@@ -588,29 +581,29 @@ exportsShouldBeValid Module { exports, imports, functions, mems, tables, globals
isExportValid :: Export -> ValidationResult isExportValid :: Export -> ValidationResult
isExportValid (Export _ (ExportFunc funIdx)) = isExportValid (Export _ (ExportFunc funIdx)) =
if fromIntegral funIdx < length funcImports + length functions then Valid else FunctionIndexOutOfRange if fromIntegral funIdx < length funcImports + length functions then return () else Left FunctionIndexOutOfRange
isExportValid (Export _ (ExportTable tableIdx)) = isExportValid (Export _ (ExportTable tableIdx)) =
if fromIntegral tableIdx < length tableImports + length tables then Valid else TableIndexOutOfRange if fromIntegral tableIdx < length tableImports + length tables then return () else Left TableIndexOutOfRange
isExportValid (Export _ (ExportMemory memIdx)) = isExportValid (Export _ (ExportMemory memIdx)) =
if fromIntegral memIdx < length memImports + length mems then Valid else MemoryIndexOutOfRange if fromIntegral memIdx < length memImports + length mems then return () else Left MemoryIndexOutOfRange
isExportValid (Export _ (ExportGlobal globalIdx)) = isExportValid (Export _ (ExportGlobal globalIdx)) =
if fromIntegral globalIdx < length globalImports + length globals if fromIntegral globalIdx < length globalImports + length globals
then ( then (
if fromIntegral globalIdx >= length globalImports if fromIntegral globalIdx >= length globalImports
then ( then (
case globals !! (fromIntegral globalIdx - length globalImports) of case globals !! (fromIntegral globalIdx - length globalImports) of
(Global (Mut _) _) -> ExportedGlobalIsNotConst (Global (Mut _) _) -> Left ExportedGlobalIsNotConst
_ -> Valid _ -> return ()
) )
else Valid else return ()
) )
else GlobalIndexOutOfRange else Left GlobalIndexOutOfRange
areExportNamesUnique :: ValidationResult areExportNamesUnique :: ValidationResult
areExportNamesUnique = areExportNamesUnique =
case foldl' go (Set.empty, []) exports of case foldl' go (Set.empty, []) exports of
(_, []) -> Valid (_, []) -> return ()
(_, dup) -> DuplicatedExportNames dup (_, dup) -> Left $ DuplicatedExportNames dup
where where
go :: (Set.Set TL.Text, [String]) -> Export -> (Set.Set TL.Text, [String]) go :: (Set.Set TL.Text, [String]) -> Export -> (Set.Set TL.Text, [String])
go (set, dup) (Export name _) = go (set, dup) (Export name _) =
@@ -623,20 +616,25 @@ importsShouldBeValid Module { imports, types } =
foldMap isImportValid imports foldMap isImportValid imports
where where
isImportValid :: Import -> ValidationResult isImportValid :: Import -> ValidationResult
isImportValid (Import _ _ (ImportFunc typeIdx)) = if fromIntegral typeIdx < length types then Valid else TypeIndexOutOfRange isImportValid (Import _ _ (ImportFunc typeIdx)) =
isImportValid (Import _ _ (ImportTable _)) = Valid -- checked in tables section if fromIntegral typeIdx < length types
isImportValid (Import _ _ (ImportMemory _)) = Valid -- checked in mems section then return ()
isImportValid (Import _ _ (ImportGlobal (Const _))) = Valid else Left TypeIndexOutOfRange
isImportValid (Import _ _ (ImportGlobal (Mut _))) = ImportedGlobalIsNotConst isImportValid (Import _ _ (ImportTable _)) = return () -- checked in tables section
isImportValid (Import _ _ (ImportMemory _)) = return () -- checked in mems section
isImportValid (Import _ _ (ImportGlobal (Const _))) = return ()
isImportValid (Import _ _ (ImportGlobal (Mut _))) = Left ImportedGlobalIsNotConst
typesShouldBeValid :: Validator typesShouldBeValid :: Validator
typesShouldBeValid Module { types } = foldMap isTypeValid types typesShouldBeValid Module { types } = foldMap isTypeValid types
where where
isTypeValid :: FuncType -> ValidationResult isTypeValid :: FuncType -> ValidationResult
isTypeValid FuncType { results } = if length results <= 1 then Valid else InvalidResultArity isTypeValid FuncType { results } = if length results <= 1 then return () else Left InvalidResultArity
validate :: Validator newtype ValidModule = ValidModule { getModule :: Module } deriving (Show, Eq)
validate mod = foldMap ($ mod) validators
validate :: Module -> Either ValidationError ValidModule
validate mod = const (ValidModule mod) <$> foldMap ($ mod) validators
where where
validators :: [Validator] validators :: [Validator]
validators = [ validators = [
+2 -22
View File
@@ -10,34 +10,14 @@ import qualified System.Directory as Directory
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
import qualified Language.Wasm.Lexer as Lexer import qualified Language.Wasm as Wasm
import qualified Language.Wasm.Parser as Parser
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 Language.Wasm.Script as Script
import qualified Debug.Trace as Debug
isRight :: (Show b) => Either a b -> Bool
isRight (Right x) = x `seq` True
isRight _ = False
compile :: String -> IO ()
compile file = do
content <- LBS.readFile $ "tests/samples/" ++ file
let Right mod = Lexer.scanner content >>= Parser.parseModule
LBS.writeFile ("tests/runnable/" ++ file) $ Binary.dumpModuleLazy mod
-- to run: python -m SimpleHTTPServer 8081 && open http://localhost:8081/tests/runnable
main :: IO () main :: IO ()
main = do main = do
files <- Directory.listDirectory "tests/samples" files <- Directory.listDirectory "tests/samples"
-- let files = ["address.wast"]
scriptTestCases <- (`mapM` files) $ \file -> do scriptTestCases <- (`mapM` files) $ \file -> do
content <- LBS.readFile $ "tests/samples/" ++ file Right script <- Wasm.parseScript <$> LBS.readFile ("tests/samples/" ++ file)
let Right script = Lexer.scanner content >>= Parser.parseScript
return $ testCase file $ do return $ testCase file $ do
Script.runScript (\msg assert -> assertFailure ("Failed assert: " ++ msg ++ ". Assert " ++ show assert)) script Script.runScript (\msg assert -> assertFailure ("Failed assert: " ++ msg ++ ". Assert " ++ show assert)) script
defaultMain $ testGroup "Wasm Core Test Suit" scriptTestCases defaultMain $ testGroup "Wasm Core Test Suit" scriptTestCases
+3 -9
View File
@@ -1,11 +1,5 @@
-- This file has been generated from package.yaml by hpack version 0.20.0.
--
-- see: https://github.com/sol/hpack
--
-- hash: 1b02a1858ead3517927e9405dabc17ffb37f0df038564d37e8321b18227389ec
name: wasm name: wasm
version: 0.1.0 version: 1.0.0
author: Ilya Rezvov author: Ilya Rezvov
maintainer: rezvov.ilya@gmail.com maintainer: rezvov.ilya@gmail.com
license: MIT license: MIT
@@ -56,7 +50,7 @@ executable wasm
hs-source-dirs: exec hs-source-dirs: exec
build-depends: build-depends:
base >=4.6 && <5.0 base >=4.6 && <5.0
, wasm ==0.1.0 , wasm >= 1.0.0
, optparse-applicative >= 0.14 , optparse-applicative >= 0.14
, bytestring >=0.10 && <0.11 , bytestring >=0.10 && <0.11
, base64-bytestring >= 1.0 , base64-bytestring >= 1.0
@@ -75,7 +69,7 @@ test-suite test
, tasty >=0.7 , tasty >=0.7
, tasty-hunit >=0.4.1 && <0.10 , tasty-hunit >=0.4.1 && <0.10
, text >=1.1 && <1.3 , text >=1.1 && <1.3
, wasm ==0.1.0 , wasm >= 1.0
build-tools: build-tools:
alex >=3.1.3 alex >=3.1.3
, happy >=1.9.4 , happy >=1.9.4