make validation result monoid instance
This commit is contained in:
@@ -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
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user