make validation result monoid instance

This commit is contained in:
Ilya Rezvov
2018-02-21 20:52:46 -08:00
parent 7bd2914148
commit 62bca80a3a
2 changed files with 29 additions and 14 deletions
+23 -12
View File
@@ -2,6 +2,7 @@
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
module Language.Wasm.Validate ( module Language.Wasm.Validate (
ValidationResult(..),
validate, validate,
isValid isValid
) where ) where
@@ -10,27 +11,41 @@ import Language.Wasm.Structure
import qualified Data.Set as Set import qualified Data.Set as Set
import Data.List (foldl') import Data.List (foldl')
import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy as TL
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
data ValidationResult = data ValidationResult =
DuplicatedExportNames [String] DuplicatedExportNames [String]
| InvalidTableType
| MoreThanOneMemory | MoreThanOneMemory
| MoreThanOneTable | MoreThanOneTable
| Valid | Valid
deriving (Show, Eq) deriving (Show, Eq)
instance Monoid ValidationResult where
mempty = Valid
mappend Valid vr = vr
mappend vr Valid = vr
mappend vr _ = vr
isValid :: ValidationResult -> Bool isValid :: ValidationResult -> Bool
isValid Valid = True isValid Valid = True
isValid _ = False isValid _ = False
type Validator = Module -> ValidationResult type Validator = Module -> ValidationResult
shouldBeAtMostOneTable :: Validator tablesShouldBeValid :: Validator
shouldBeAtMostOneTable Module { imports, tables } = tablesShouldBeValid Module { imports, tables } =
let memImports = filter isTableImport imports in let tableImports = filter isTableImport imports in
if length memImports + length tables <= 1 let res = foldMap (\Import { desc = ImportTable t } -> isValidTableType t) tableImports in
then Valid let res' = foldl' (\r (Table t) -> r <> isValidTableType t) res tables in
else MoreThanOneTable if length tableImports + length tables <= 1
then res'
else MoreThanOneTable
where where
isValidTableType :: TableType -> ValidationResult
isValidTableType (TableType (Limit min max) _) = if min <= fromMaybe min max then Valid else InvalidTableType
isTableImport Import { desc = ImportTable _ } = True isTableImport Import { desc = ImportTable _ } = True
isTableImport _ = False isTableImport _ = False
@@ -57,15 +72,11 @@ exportNamesShouldBeDifferent Module { exports } =
else (Set.insert name set, dup) else (Set.insert name set, dup)
validate :: Validator validate :: Validator
validate mod = foldl' go Valid validators validate mod = foldMap ($ mod) validators
where where
go :: ValidationResult -> Validator -> ValidationResult
go Valid validator = validator mod
go res _ = res
validators :: [Validator] validators :: [Validator]
validators = [ validators = [
shouldBeAtMostOneTable, tablesShouldBeValid,
shouldBeAtMostOneMemory, shouldBeAtMostOneMemory,
exportNamesShouldBeDifferent exportNamesShouldBeDifferent
] ]
+6 -2
View File
@@ -43,11 +43,15 @@ main = do
let Right mod' = Binary.decodeModuleLazy $ Binary.dumpModuleLazy mod let Right mod' = Binary.decodeModuleLazy $ Binary.dumpModuleLazy mod
return $ testCase ("Dump module to binary and parse back: " ++ file) $ return $ testCase ("Dump module to binary and parse back: " ++ file) $
assertEqual "Module matched" mod mod' assertEqual "Module matched" mod mod'
validationTestCases <- (`mapM` (filter (/= "import.wast") files)) $ \file -> do validationTestCases <- (`mapM` files) $ \file -> do
content <- LBS.readFile $ "tests/samples/" ++ file content <- LBS.readFile $ "tests/samples/" ++ file
let Right mod = Parser.parseModule <$> Lexer.scanner content let Right mod = Parser.parseModule <$> Lexer.scanner content
return $ testCase ("Validate module: " ++ file) $ return $ testCase ("Validate module: " ++ file) $
assertBool "Module matched" $ Validate.isValid $ Validate.validate mod case file of
"import.wast" ->
assertEqual "Too many tables" Validate.MoreThanOneTable $ Validate.validate mod
_ ->
assertBool "Module matched" $ Validate.isValid $ Validate.validate mod
defaultMain $ testGroup "tests" [ defaultMain $ testGroup "tests" [
testGroup "Syntax parsing" syntaxTestCases, testGroup "Syntax parsing" syntaxTestCases,
testGroup "Binary format" binaryTestCases, testGroup "Binary format" binaryTestCases,