Ticket #5688: 0001-Better-handling-of-exponential-notation-when-parsing.patch

File 0001-Better-handling-of-exponential-notation-when-parsing.patch, 3.4 KB (added by gracjan, 2 years ago)
  • GHC/Read.lhs

    From 8797698d93079dd27e4f1428c2aad6a29d4dd1dc Mon Sep 17 00:00:00 2001
    From: Gracjan Polak <gracjanpolak@gmail.com>
    Date: Fri, 9 Dec 2011 00:36:52 +0100
    Subject: [PATCH] Better handling of exponential notation when parsing decimal
     lexemes, fixes #5688
    
    ---
     GHC/Read.lhs     |   20 +++++++++++++++-----
     Text/Read/Lex.hs |   16 +++++-----------
     2 files changed, 20 insertions(+), 16 deletions(-)
    
    diff --git a/GHC/Read.lhs b/GHC/Read.lhs
    index fcbdb8e..8b4ec0b 100644
    a b import {-# SOURCE #-} GHC.Unicode ( isDigit ) 
    6969#endif 
    7070import GHC.Num 
    7171import GHC.Real 
    72 import GHC.Float () 
     72import GHC.Float 
    7373import GHC.Show 
     74import GHC.Enum 
    7475import GHC.Base 
    7576import GHC.Arr 
    7677-- For defining instances for the generic deriving mechanism 
    convertInt :: Num a => L.Lexeme -> ReadPrec a 
    473474convertInt (L.Int i) = return (fromInteger i) 
    474475convertInt _         = pfail 
    475476 
    476 convertFrac :: Fractional a => L.Lexeme -> ReadPrec a 
    477 convertFrac (L.Int i) = return (fromInteger i) 
    478 convertFrac (L.Rat r) = return (fromRational r) 
    479 convertFrac _         = pfail 
     477clampToInt :: Integer -> Int 
     478clampToInt a | a < fromIntegral minBound' = minBound' 
     479             | a > fromIntegral maxBound' = maxBound' 
     480             | otherwise = fromIntegral a 
     481  where 
     482     minBound' = minBound 
     483     maxBound' = maxBound 
     484 
     485convertFrac :: RealFloat a => L.Lexeme -> ReadPrec a 
     486convertFrac (L.Int i)   = return (fromInteger i) 
     487convertFrac (L.Rat r)   = return (fromRational r) 
     488convertFrac (L.Exp b e) = return (encodeFloat b (clampToInt e)) 
     489convertFrac _           = pfail 
    480490 
    481491instance Read Int where 
    482492  readPrec     = readNumber convertInt 
  • Text/Read/Lex.hs

    diff --git a/Text/Read/Lex.hs b/Text/Read/Lex.hs
    index e4563b6..ec03830 100644
    a b data Lexeme 
    6767  | Symbol String       -- ^ Haskell symbol, e.g. @>>@, @:%@ 
    6868  | Int Integer         -- ^ Integer literal 
    6969  | Rat Rational        -- ^ Floating point literal 
     70  | Exp Integer Integer -- ^ Floating point literal in exponential form a*10^b 
    7071  | EOF 
    7172 deriving (Eq, Show) 
    7273 
    lexDecNumber = 
    345346  valueFracExp a Nothing Nothing 
    346347    = Int a                                             -- 43 
    347348  valueFracExp a Nothing (Just exp) 
    348     | exp >= 0  = Int (a * (10 ^ exp))                  -- 43e7 
    349     | otherwise = Rat (a % (10 ^ (-exp)))               -- 43e-7 
     349    = Exp a exp 
    350350  valueFracExp a (Just fs) mExp                         -- 4.3[e2] 
    351     = Rat (fracExp (fromMaybe 0 mExp) a fs) 
    352     -- Be a bit more efficient in calculating the Rational. 
    353     -- Instead of calculating the fractional part alone, then 
    354     -- adding the integral part and finally multiplying with 
    355     -- 10 ^ exp if an exponent was given, do it all at once. 
     351    = let (a,e) = fracExp (fromMaybe 0 mExp) a fs in Exp a e 
    356352 
    357353lexFrac :: ReadP (Maybe Digits) 
    358354-- Read the fractional part; fail if it doesn't 
    val base y (x:xs) = y' `seq` val base y' xs 
    404400-- 
    405401-- frac was never used with anything but Integer and base 10, so 
    406402-- those are hardcoded now (trivial to change if necessary). 
    407 fracExp :: Integer -> Integer -> Digits -> Rational 
    408 fracExp exp mant [] 
    409   | exp < 0     = mant % (10 ^ (-exp)) 
    410   | otherwise   = fromInteger (mant * 10 ^ exp) 
     403fracExp :: Integer -> Integer -> Digits -> (Integer,Integer) 
     404fracExp exp mant [] = (mant, exp) 
    411405fracExp exp mant (d:ds) = exp' `seq` mant' `seq` fracExp exp' mant' ds 
    412406  where 
    413407    exp'  = exp - 1