pass all assert_return tests

This commit is contained in:
Ilya Rezvov
2018-04-11 21:15:56 -07:00
parent 7a4735bbfc
commit 2955456e26
6 changed files with 72 additions and 28 deletions
+44
View File
@@ -0,0 +1,44 @@
{-# LANGUAGE FlexibleContexts #-}
module Language.Wasm.FloatUtils (
wordToFloat,
floatToWord,
wordToDouble,
doubleToWord,
makeNaN,
doubleToFloat
) where
import Data.Word (Word32, Word64)
import Data.Bits ((.|.), (.&.), shiftR)
import Data.Array.ST (newArray, readArray, MArray, STUArray)
import Data.Array.Unsafe (castSTUArray)
import GHC.ST (runST, ST)
-- brough from https://stackoverflow.com/questions/6976684/converting-ieee-754-floating-point-in-haskell-word32-64-to-and-from-haskell-floa
wordToFloat :: Word32 -> Float
wordToFloat x = runST (cast x)
floatToWord :: Float -> Word32
floatToWord x = runST (cast x)
wordToDouble :: Word64 -> Double
wordToDouble x = runST (cast x)
doubleToWord :: Double -> Word64
doubleToWord x = runST (cast x)
{-# INLINE cast #-}
cast :: (MArray (STUArray s) a (ST s),
MArray (STUArray s) b (ST s)) => a -> ST s b
cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0
makeNaN :: Word64 -> Double
makeNaN w = wordToDouble $ 0x7FF0000000000000 .|. (0x000FFFFFFFFFFFFF .&. w)
doubleToFloat :: Double -> Float
doubleToFloat d =
let w = doubleToWord d in
if 0x7FF0000000000000 == (w .&. 0x7FF0000000000000) && (w .&. 0x0007FFFFFFFFFFFF) /= 0
then wordToFloat $ fromIntegral $ ((0x8000000000000000 .&. w) `shiftR` 32) .|. 0x7F800000 .|. (0x7FFFFF .&. w)
else realToFrac d
+7 -22
View File
@@ -1,6 +1,5 @@
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
module Language.Wasm.Interpreter ( module Language.Wasm.Interpreter (
@@ -49,14 +48,18 @@ import Data.Bits (
countLeadingZeros, countLeadingZeros,
countTrailingZeros countTrailingZeros
) )
import Data.Array.ST (newArray, readArray, MArray, STUArray)
import Data.Array.Unsafe (castSTUArray)
import GHC.ST (runST, ST)
import Numeric.IEEE (IEEE, copySign, minNum, maxNum, identicalIEEE) import Numeric.IEEE (IEEE, copySign, minNum, maxNum, identicalIEEE)
import Debug.Trace as Debug import Debug.Trace as Debug
import Language.Wasm.Structure as Struct import Language.Wasm.Structure as Struct
import Language.Wasm.FloatUtils (
wordToFloat,
floatToWord,
wordToDouble,
doubleToWord,
makeNaN
)
data Value = data Value =
VI32 Word32 VI32 Word32
@@ -87,24 +90,6 @@ asWord64 i
| i >= 0 = fromIntegral i | i >= 0 = fromIntegral i
| otherwise = 0xFFFFFFFFFFFFFFFF - (fromIntegral (abs i)) + 1 | otherwise = 0xFFFFFFFFFFFFFFFF - (fromIntegral (abs i)) + 1
-- brough from https://stackoverflow.com/questions/6976684/converting-ieee-754-floating-point-in-haskell-word32-64-to-and-from-haskell-floa
wordToFloat :: Word32 -> Float
wordToFloat x = runST (cast x)
floatToWord :: Float -> Word32
floatToWord x = runST (cast x)
wordToDouble :: Word64 -> Double
wordToDouble x = runST (cast x)
doubleToWord :: Double -> Word64
doubleToWord x = runST (cast x)
{-# INLINE cast #-}
cast :: (MArray (STUArray s) a (ST s),
MArray (STUArray s) b (ST s)) => a -> ST s b
cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0
nearest :: (IEEE a) => a -> a nearest :: (IEEE a) => a -> a
nearest f nearest f
| f >= 0 && f <= 0.5 = copySign 0 f | f >= 0 && f <= 0.5 = copySign 0 f
+17 -4
View File
@@ -1,4 +1,6 @@
{ {
{-# LANGUAGE FlexibleContexts #-}
module Language.Wasm.Lexer ( module Language.Wasm.Lexer (
Lexeme(..), Lexeme(..),
Token(..), Token(..),
@@ -11,7 +13,10 @@ import qualified Data.Char as Char
import qualified Data.ByteString.Lazy.UTF8 as LBSUtf8 import qualified Data.ByteString.Lazy.UTF8 as LBSUtf8
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import Control.Monad (when) import Control.Monad (when)
import Numeric.IEEE (infinity, nan, nanWithPayload) import Numeric.IEEE (infinity, nan)
import Language.Wasm.FloatUtils (makeNaN)
import qualified Debug.Trace as Debug
} }
@@ -124,7 +129,7 @@ parseNanSigned :: AlexAction Lexeme
parseNanSigned = token $ \(pos, _, s, _) len -> parseNanSigned = token $ \(pos, _, s, _) len ->
let (sign, slen) = parseSign s in let (sign, slen) = parseSign s in
let num = readHexFromPrefix (len - 6 - slen) $ LBSUtf8.drop (6 + slen) s in let num = readHexFromPrefix (len - 6 - slen) $ LBSUtf8.drop (6 + slen) s in
Lexeme pos $ TFloatLit $ sign $ nanWithPayload $ fromIntegral num Lexeme pos $ TFloatLit $ sign $ makeNaN $ fromIntegral num
parseDecimalSignedInt :: AlexAction Lexeme parseDecimalSignedInt :: AlexAction Lexeme
parseDecimalSignedInt = token $ \(pos, _, s, _) len -> parseDecimalSignedInt = token $ \(pos, _, s, _) len ->
@@ -134,8 +139,9 @@ parseDecimalSignedInt = token $ \(pos, _, s, _) len ->
parseDecFloat :: AlexAction Lexeme parseDecFloat :: AlexAction Lexeme
parseDecFloat = token $ \(pos, _, s, _) len -> parseDecFloat = token $ \(pos, _, s, _) len ->
let str = filter (/= '_') $ takeChars len s in let (sign, slen) = parseSign s in
Lexeme pos $ TFloatLit $ read str let str = filter (/= '_') $ takeChars (len - slen) $ LBSUtf8.drop slen s in
Lexeme pos $ TFloatLit $ sign $ readDecFloat str
parseHexFloat :: AlexAction Lexeme parseHexFloat :: AlexAction Lexeme
parseHexFloat = token $ \(pos, _, s, _) len -> parseHexFloat = token $ \(pos, _, s, _) len ->
@@ -349,6 +355,13 @@ readHexFloat str =
let len = length val in let len = length val in
sum $ zipWith (\i c -> readHexFromChar c / (16 ^ i)) [1..] val sum $ zipWith (\i c -> readHexFromChar c / (16 ^ i)) [1..] val
readDecFloat :: String -> Double
readDecFloat str =
let (val, exp) = splitBy (\c -> c == 'E' || c == 'e') str in
let (int, frac) = splitBy (== '.') val in
let nullIfEmpty str = if null str then "0" else str in
read $ nullIfEmpty int ++ "." ++ nullIfEmpty frac ++ "e" ++ nullIfEmpty exp
scanner :: LBS.ByteString -> Either String [Lexeme] scanner :: LBS.ByteString -> Either String [Lexeme]
scanner str = runAlex str loop scanner str = runAlex str loop
where where
+2 -1
View File
@@ -72,6 +72,7 @@ import Numeric.Natural (Natural)
import Data.Word (Word32, Word64) import Data.Word (Word32, Word64)
import Data.Bits ((.|.)) import Data.Bits ((.|.))
import Numeric.IEEE (infinity, nan) import Numeric.IEEE (infinity, nan)
import Language.Wasm.FloatUtils (doubleToFloat)
import Language.Wasm.Lexer ( import Language.Wasm.Lexer (
Token ( Token (
@@ -1103,7 +1104,7 @@ asInt64 val
| otherwise = Nothing | otherwise = Nothing
asFloat32 :: Double -> Float asFloat32 :: Double -> Float
asFloat32 v = realToFrac v asFloat32 v = doubleToFloat v
asOffset :: LBS.ByteString -> Maybe Natural asOffset :: LBS.ByteString -> Maybe Natural
asOffset str = do asOffset str = do
+1 -1
View File
@@ -34,7 +34,7 @@ compile file = do
main :: IO () main :: IO ()
main = do main = do
files <- Directory.listDirectory "tests/samples" files <- Directory.listDirectory "tests/samples"
-- let files = ["conversions.wast"] -- let files = ["float_literals.wast"]
scriptTestCases <- (`mapM` files) $ \file -> do scriptTestCases <- (`mapM` files) $ \file -> do
content <- LBS.readFile $ "tests/samples/" ++ file content <- LBS.readFile $ "tests/samples/" ++ file
let Right script = Parser.parseScript <$> Lexer.scanner content let Right script = Parser.parseScript <$> Lexer.scanner content
+1
View File
@@ -43,6 +43,7 @@ library
Language.Wasm.Validate Language.Wasm.Validate
Language.Wasm.Interpreter Language.Wasm.Interpreter
Language.Wasm.Script Language.Wasm.Script
Language.Wasm.FloatUtils
Language.Wasm Language.Wasm
other-modules: other-modules:
Paths_wasm Paths_wasm