pass all assert_return tests
This commit is contained in:
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user