summaryrefslogtreecommitdiff
path: root/compiler/utils/Util.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/Util.hs')
-rw-r--r--compiler/utils/Util.hs59
1 files changed, 57 insertions, 2 deletions
diff --git a/compiler/utils/Util.hs b/compiler/utils/Util.hs
index 3b402f2833..7a46db7665 100644
--- a/compiler/utils/Util.hs
+++ b/compiler/utils/Util.hs
@@ -89,6 +89,7 @@ module Util (
-- * Floating point
readRational,
+ readHexRational,
-- * read helpers
maybeRead, maybeReadFuzzy,
@@ -143,7 +144,7 @@ import GHC.Exts
import GHC.Stack (HasCallStack)
import Control.Applicative ( liftA2 )
-import Control.Monad ( liftM )
+import Control.Monad ( liftM, guard )
import GHC.IO.Encoding (mkTextEncoding, textEncodingName)
import GHC.Conc.Sync ( sharedCAF )
import System.IO (Handle, hGetEncoding, hSetEncoding)
@@ -151,7 +152,8 @@ import System.IO.Error as IO ( isDoesNotExistError )
import System.Directory ( doesDirectoryExist, getModificationTime )
import System.FilePath
-import Data.Char ( isUpper, isAlphaNum, isSpace, chr, ord, isDigit, toUpper)
+import Data.Char ( isUpper, isAlphaNum, isSpace, chr, ord, isDigit, toUpper
+ , isHexDigit, digitToInt )
import Data.Int
import Data.Ratio ( (%) )
import Data.Ord ( comparing )
@@ -1159,6 +1161,59 @@ readRational top_s
_ -> error ("readRational: ambiguous parse:" ++ top_s)
+readHexRational :: String -> Rational
+readHexRational str =
+ case str of
+ '-' : xs -> - (readMe xs)
+ xs -> readMe xs
+ where
+ readMe as =
+ case readHexRational__ as of
+ Just n -> n
+ _ -> error ("readHexRational: no parse:" ++ str)
+
+
+readHexRational__ :: String -> Maybe Rational
+readHexRational__ ('0' : x : rest)
+ | x == 'X' || x == 'x' =
+ do let (front,rest2) = span isHexDigit rest
+ guard (not (null front))
+ let frontNum = steps 16 0 front
+ case rest2 of
+ '.' : rest3 ->
+ do let (back,rest4) = span isHexDigit rest3
+ guard (not (null back))
+ let backNum = steps 16 frontNum back
+ exp1 = -4 * length back
+ case rest4 of
+ p : ps | isExp p -> fmap (mk backNum . (+ exp1)) (getExp ps)
+ _ -> return (mk backNum exp1)
+ p : ps | isExp p -> fmap (mk frontNum) (getExp ps)
+ _ -> Nothing
+
+ where
+ isExp p = p == 'p' || p == 'P'
+
+ getExp ('+' : ds) = dec ds
+ getExp ('-' : ds) = fmap negate (dec ds)
+ getExp ds = dec ds
+
+ mk :: Integer -> Int -> Rational
+ mk n e = fromInteger n * 2^^e
+
+ dec cs = case span isDigit cs of
+ (ds,"") | not (null ds) -> Just (steps 10 0 ds)
+ _ -> Nothing
+
+ steps base n ds = foldl' (step base) n ds
+ step base n d = base * n + fromIntegral (digitToInt d)
+
+
+readHexRational__ _ = Nothing
+
+
+
+
-----------------------------------------------------------------------------
-- read helpers