From 5d92591e6728e2f195cf778880d9e3453d10796e Mon Sep 17 00:00:00 2001 From: sof Date: Sat, 23 Jan 1999 17:47:04 +0000 Subject: [PATCH] [project @ 1999-01-23 17:47:03 by sof] Bunch of bug fixes related to Enum instances. Code clean-up. --- ghc/lib/exts/Int.lhs | 316 +++++++++++++++++++------------ ghc/lib/exts/Word.lhs | 495 +++++++++++++++++++++++++++++++------------------ 2 files changed, 512 insertions(+), 299 deletions(-) diff --git a/ghc/lib/exts/Int.lhs b/ghc/lib/exts/Int.lhs index 0468216..41a366f 100644 --- a/ghc/lib/exts/Int.lhs +++ b/ghc/lib/exts/Int.lhs @@ -1,5 +1,5 @@ % -% (c) The AQUA Project, Glasgow University, 1997-1998 +% (c) The AQUA Project, Glasgow University, 1997-1999 % \section[Int]{Module @Int@} @@ -15,17 +15,41 @@ module Int , Int16 , Int32 , Int64 + + , int8ToInt16 -- :: Int8 -> Int16 + , int8ToInt32 -- :: Int8 -> Int32 + , int8ToInt64 -- :: Int8 -> Int64 + + , int16ToInt8 -- :: Int16 -> Int8 + , int16ToInt32 -- :: Int16 -> Int32 + , int16ToInt64 -- :: Int16 -> Int64 + + , int32ToInt8 -- :: Int32 -> Int8 + , int32ToInt16 -- :: Int32 -> Int16 + , int32ToInt64 -- :: Int32 -> Int64 + + , int64ToInt8 -- :: Int64 -> Int8 + , int64ToInt16 -- :: Int64 -> Int16 + , int64ToInt32 -- :: Int64 -> Int32 + , int8ToInt -- :: Int8 -> Int - , intToInt8 -- :: Int -> Int8 , int16ToInt -- :: Int16 -> Int - , intToInt16 -- :: Int -> Int16 , int32ToInt -- :: Int32 -> Int - , intToInt32 -- :: Int -> Int32 + , int64ToInt -- :: Int32 -> Int - , intToInt64 -- :: Int -> Int64 - , int64ToInt -- :: Int64 -> Int + , intToInt8 -- :: Int -> Int8 + , intToInt16 -- :: Int -> Int16 + , intToInt32 -- :: Int -> Int32 + , intToInt64 -- :: Int -> Int32 + , integerToInt8 -- :: Integer -> Int8 + , integerToInt16 -- :: Integer -> Int16 + , integerToInt32 -- :: Integer -> Int32 , integerToInt64 -- :: Integer -> Int64 + + , int8ToInteger -- :: Int8 -> Integer + , int16ToInteger -- :: Int16 -> Integer + , int32ToInteger -- :: Int32 -> Integer , int64ToInteger -- :: Int64 -> Integer -- plus Eq, Ord, Num, Bounded, Real, Integral, Ix, Enum, Read, @@ -96,25 +120,30 @@ import Word ( Word32 ) ----------------------------------------------------------------------------- int8ToInt :: Int8 -> Int -intToInt8 :: Int -> Int8 int16ToInt :: Int16 -> Int -intToInt16 :: Int -> Int16 int32ToInt :: Int32 -> Int -intToInt32 :: Int -> Int32 --- And some non-exported ones +intToInt8 :: Int -> Int8 +intToInt16 :: Int -> Int16 +intToInt32 :: Int -> Int32 int8ToInt16 :: Int8 -> Int16 int8ToInt32 :: Int8 -> Int32 + int16ToInt8 :: Int16 -> Int8 int16ToInt32 :: Int16 -> Int32 + int32ToInt8 :: Int32 -> Int8 int32ToInt16 :: Int32 -> Int16 int8ToInt16 (I8# x) = I16# x int8ToInt32 (I8# x) = I32# x +int8ToInt64 = int32ToInt64 . int8ToInt32 + int16ToInt8 (I16# x) = I8# x int16ToInt32 (I16# x) = I32# x +int16ToInt64 = int32ToInt64 . int16ToInt32 + int32ToInt8 (I32# x) = I8# x int32ToInt16 (I32# x) = I16# x @@ -189,10 +218,10 @@ instance Integral Int8 where quot x@(I8# _) y@(I8# y#) | y# /=# 0# = x `quotInt8` y - | otherwise = error "Integral.Int8.quot: divide by 0\n" + | otherwise = divZeroError "quot{Int8}" x rem x@(I8# _) y@(I8# y#) | y# /=# 0# = x `remInt8` y - | otherwise = error "Integral.Int8.rem: divide by 0\n" + | otherwise = divZeroError "rem{Int8}" x mod x y | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0 | otherwise = r @@ -215,17 +244,26 @@ instance Ix Int8 where instance Enum Int8 where succ i - | i == maxBound = error ("Enum{Int8}.succ: tried to take `succ' of " ++ show i) + | i == maxBound = succError "Int8" | otherwise = i+1 pred i - | i == minBound = error ("Enum{Int8}.pred: tried to take `pred' of " ++ show i) - | otherwise = i+1 - - toEnum = intToInt8 - fromEnum = int8ToInt - enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Int8)] - enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Int8)] - where last = if d < c then minBound else maxBound + | i == minBound = predError "Int8" + | otherwise = i-1 + + toEnum x + | x >= toInt (minBound::Int8) && x <= toInt (maxBound::Int8) + = intToInt8 x + | otherwise + = toEnumError "Int8" x (minBound::Int8,maxBound::Int8) + + fromEnum = int8ToInt + enumFrom e1 = map toEnum [fromEnum e1 .. fromEnum (maxBound::Int8)] + enumFromThen e1 e2 = + map toEnum [fromEnum e1, fromEnum e2 .. fromEnum (last::Int8)] + where + last + | e2 < e1 = minBound + | otherwise = maxBound instance Read Int8 where readsPrec p s = [ (intToInt8 x,r) | (x,r) <- readsPrec p s ] @@ -330,10 +368,10 @@ instance Integral Int16 where quot x@(I16# _) y@(I16# y#) | y# /=# 0# = x `quotInt16` y - | otherwise = error "Integral.Int16.quot: divide by 0\n" + | otherwise = divZeroError "quot{Int16}" x rem x@(I16# _) y@(I16# y#) | y# /=# 0# = x `remInt16` y - | otherwise = error "Integral.Int16.rem: divide by 0\n" + | otherwise = divZeroError "rem{Int16}" x mod x y | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0 | otherwise = r @@ -356,17 +394,26 @@ instance Ix Int16 where instance Enum Int16 where succ i - | i == maxBound = error ("Enum{Int16}.succ: tried to take `succ' of " ++ show i) + | i == maxBound = succError "Int16" | otherwise = i+1 + pred i - | i == minBound = error ("Enum{Int16}.pred: tried to take `pred' of " ++ show i) - | otherwise = i+1 + | i == minBound = predError "Int16" + | otherwise = i-1 + + toEnum x + | x >= toInt (minBound::Int16) && x <= toInt (maxBound::Int16) + = intToInt16 x + | otherwise + = toEnumError "Int16" x (minBound::Int16, maxBound::Int16) - toEnum = intToInt16 fromEnum = int16ToInt - enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Int16)] - enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Int16)] - where last = if d < c then minBound else maxBound + + enumFrom e1 = map toEnum [fromEnum e1 .. fromEnum (maxBound::Int16)] + enumFromThen e1 e2 = map toEnum [fromEnum e1, fromEnum e2 .. fromEnum (last::Int16)] + where last + | e2 < e1 = minBound + | otherwise = maxBound instance Read Int16 where readsPrec p s = [ (intToInt16 x,r) | (x,r) <- readsPrec p s ] @@ -464,11 +511,9 @@ instance Num Int32 where = case (integer2Int# a# s# d#) of { i# -> I32# (intToInt32# i#) } fromInt = intToInt32 --- ToDo: remove LitLit when minBound::Int is fixed (currently it's one --- too high, and doesn't allow the correct minBound to be defined here). instance Bounded Int32 where - minBound = case ``0x80000000'' of { I# x -> I32# x } - maxBound = I32# 0x7fffffff# + minBound = fromInt minBound + maxBound = fromInt maxBound instance Real Int32 where toRational x = toInteger x % 1 @@ -480,10 +525,10 @@ instance Integral Int32 where | otherwise = quotInt32 x y quot x@(I32# _) y@(I32# y#) | y# /=# 0# = x `quotInt32` y - | otherwise = error "Integral.Int32.quot: divide by 0\n" + | otherwise = divZeroError "quot{Int32}" x rem x@(I32# _) y@(I32# y#) | y# /=# 0# = x `remInt32` y - | otherwise = error "Integral.Int32.rem: divide by 0\n" + | otherwise = divZeroError "rem{Int32}" x mod x y | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0 | otherwise = r @@ -506,17 +551,29 @@ instance Ix Int32 where instance Enum Int32 where succ i - | i == maxBound = error ("Enum{Int32}.succ: tried to take `succ' of " ++ show i) - | otherwise = i+1 - pred i - | i == minBound = error ("Enum{Int32}.pred: tried to take `pred' of " ++ show i) + | i == maxBound = succError "Int32" | otherwise = i+1 - toEnum = intToInt32 - fromEnum = int32ToInt - enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Int32)] - enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Int32)] - where last = if d < c then minBound else maxBound + pred i + | i == minBound = predError "Int32" + | otherwise = i-1 + + toEnum x + -- with Int having the same range as Int32, the following test + -- shouldn't fail. However, having it here + | x >= toInt (minBound::Int32) && x <= toInt (maxBound::Int32) + = intToInt32 x + | otherwise + = toEnumError "Int32" x (minBound::Int32, maxBound::Int32) + + fromEnum = int32ToInt + + enumFrom e1 = map toEnum [fromEnum e1 .. fromEnum (maxBound::Int32)] + enumFromThen e1 e2 = map toEnum [fromEnum e1, fromEnum e2 .. fromEnum (last::Int32)] + where + last + | e2 < e1 = minBound + | otherwise = maxBound instance Read Int32 where readsPrec p s = [ (intToInt32 x,r) | (x,r) <- readsPrec p s ] @@ -602,9 +659,6 @@ instance Bounded Int64 where minBound = integerToInt64 (-0x8000000000000000) maxBound = integerToInt64 0x7fffffffffffffff -instance Real Int64 where - toRational x = toInteger x % 1 - instance Integral Int64 where div x y | x > 0 && y < 0 = quotInt64 (x-y-1) y @@ -613,11 +667,11 @@ instance Integral Int64 where quot x@(I64# _) y@(I64# y#) | y# /=# 0# = x `quotInt64` y - | otherwise = error "Integral.Int64.quot: divide by 0\n" + | otherwise = divZeroError "quot{Int64}" x rem x@(I64# _) y@(I64# y#) | y# /=# 0# = x `remInt64` y - | otherwise = error "Integral.Int32.rem: divide by 0\n" + | otherwise = divZeroError "rem{Int64}" x mod x y | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0 @@ -628,27 +682,6 @@ instance Integral Int64 where toInteger (I64# i#) = toInteger (I# i#) toInt (I64# i#) = I# i# -instance Enum Int64 where - succ i - | i == maxBound = error ("Enum{Int64}.succ: tried to take `succ' of " ++ show i) - | otherwise = i+1 - pred i - | i == minBound = error ("Enum{Int64}.pred: tried to take `pred' of " ++ show i) - | otherwise = i+1 - - toEnum (I# i) = I64# i# - fromEnum (I64# i) = I64# i# - enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Int64)] -- a long list! - enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Int64)] - where last = if d < c then minBound else maxBound - - -instance Read Int64 where - readsPrec p s = [ (intToInt64 x,r) | (x,r) <- readsPrec p s ] - -instance Show Int64 where - showsPrec p i64 = showsPrec p (int64ToInt i64) - instance Bits Int64 where (I64# x) .&. (I64# y) = I64# (word2Int# ((int2Word# x) `and#` (int2Word# y))) (I64# x) .|. (I64# y) = I64# (word2Int# ((int2Word# x) `or#` (int2Word# y))) @@ -717,12 +750,6 @@ int64ToInteger (I64# x#) = integerToInt64 :: Integer -> Int64 integerToInt64 (J# a# s# d#) = I64# (integerToInt64# a# s# d#) -instance Show Int64 where - showsPrec p x = showsPrec p (int64ToInteger x) - -instance Read Int64 where - readsPrec _ s = [ (integerToInt64 x,r) | (x,r) <- readDec s ] - instance Eq Int64 where (I64# x) == (I64# y) = x `eqInt64#` y (I64# x) /= (I64# y) = x `neInt64#` y @@ -758,9 +785,6 @@ instance Bounded Int64 where minBound = integerToInt64 (-0x8000000000000000) maxBound = integerToInt64 0x7fffffffffffffff -instance Real Int64 where - toRational x = toInteger x % 1 - instance Integral Int64 where div x y | x > 0 && y < 0 = quotInt64 (x-y-1) y @@ -769,11 +793,11 @@ instance Integral Int64 where quot x@(I64# _) y@(I64# y#) | y# `neInt64#` (intToInt64# 0#) = x `quotInt64` y - | otherwise = error "Integral.Int64.quot: divide by 0\n" + | otherwise = divZeroError "quot{Int64}" x rem x@(I64# _) y@(I64# y#) | y# `neInt64#` (intToInt64# 0#) = x `remInt64` y - | otherwise = error "Integral.Int32.rem: divide by 0\n" + | otherwise = divZeroError "rem{Int64}" x mod x y | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0 @@ -784,25 +808,6 @@ instance Integral Int64 where toInteger i = int64ToInteger i toInt i = int64ToInt i -instance Enum Int64 where - succ i - | i == maxBound = error ("Enum{Int64}.succ: tried to take `succ' of " ++ show i) - | otherwise = i+1 - pred i - | i == minBound = error ("Enum{Int64}.pred: tried to take `pred' of " ++ show i) - | otherwise = i+1 - - toEnum (I# i) = I64# (intToInt64# i) - fromEnum (I64# w) = I# (int64ToInt# w) - enumFrom i = eft64 i 1 - enumFromTo i1 i2 = eftt64 i1 1 (> i2) - enumFromThen i1 i2 = eftt64 i1 (i2 - i1) (>last) - where - last - | i1 < i2 = maxBound::Int64 - | otherwise = minBound - - instance Bits Int64 where (I64# x) .&. (I64# y) = I64# (word64ToInt64# ((int64ToWord64# x) `and64#` (int64ToWord64# y))) (I64# x) .|. (I64# y) = I64# (word64ToInt64# ((int64ToWord64# x) `or64#` (int64ToWord64# y))) @@ -843,23 +848,6 @@ intToInt64 (I# i#) = I64# (intToInt64# i#) int64ToInt :: Int64 -> Int int64ToInt (I64# i#) = I# (int64ToInt# i#) --- Enum Int64 helper funs: - -eftt64 :: Int64 -> Int64 -> (Int64->Bool) -> [Int64] -eftt64 init step done = go init - where - go now - | done now = [] - | otherwise = now : go (now+step) - -eft64 :: Int64 -> Int64 -> [Int64] -eft64 now step = go now - where - go x - | x == maxBound = [x] - | otherwise = x:go (x+step) - - -- Word64# primop wrappers: ltInt64# :: Int64# -> Int64# -> Bool @@ -1006,6 +994,44 @@ intToInt64# i# = #endif +-- +-- Code that's independent of Int64 rep. +-- +instance Enum Int64 where + succ i + | i == maxBound = succError "Int64" + | otherwise = i+1 + + pred i + | i == minBound = predError "Int64" + | otherwise = i-1 + + toEnum i = intToInt64 i + fromEnum x + | x >= intToInt64 (minBound::Int) && x <= intToInt64 (maxBound::Int) + = int64ToInt x + | otherwise + = fromEnumError "Int64" x + + enumFrom e1 = map integerToInt64 [int64ToInteger e1 .. int64ToInteger (maxBound::Int64)] + enumFromTo e1 e2 = map integerToInt64 [int64ToInteger e1 .. int64ToInteger e2] + enumFromThen e1 e2 = map integerToInt64 [int64ToInteger e1, int64ToInteger e2 .. int64ToInteger last] + where + last :: Int64 + last + | e2 < e1 = minBound + | otherwise = maxBound + + enumFromThenTo e1 e2 e3 = map integerToInt64 [int64ToInteger e1, int64ToInteger e2 .. int64ToInteger e3] + + +instance Show Int64 where + showsPrec p i64 = showsPrec p (int64ToInteger i64) + +instance Read Int64 where + readsPrec _ s = [ (integerToInt64 x,r) | (x,r) <- readDec s ] + + instance Ix Int64 where range (m,n) = [m..n] index b@(m,_) i @@ -1013,9 +1039,37 @@ instance Ix Int64 where | otherwise = indexError i b "Int64" inRange (m,n) i = m <= i && i <= n +instance Real Int64 where + toRational x = toInteger x % 1 + sizeofInt64 :: Word32 sizeofInt64 = 8 + +int8ToInteger :: Int8 -> Integer +int8ToInteger i = toInteger i + +int16ToInteger :: Int16 -> Integer +int16ToInteger i = toInteger i + +int32ToInteger :: Int32 -> Integer +int32ToInteger i = toInteger i + +int64ToInt8 :: Int64 -> Int8 +int64ToInt8 = int32ToInt8 . int64ToInt32 + +int64ToInt16 :: Int64 -> Int16 +int64ToInt16 = int32ToInt16 . int64ToInt32 + +integerToInt8 :: Integer -> Int8 +integerToInt8 = fromInteger + +integerToInt16 :: Integer -> Int16 +integerToInt16 = fromInteger + +integerToInt32 :: Integer -> Int32 +integerToInt32 = fromInteger + \end{code} % @@ -1203,4 +1257,30 @@ indexError i rng tp showParen True (showsPrec 0 rng) "") +toEnumError :: (Show a,Show b) => String -> a -> (b,b) -> c +toEnumError inst_ty tag bnds + = error ("Enum.toEnum{" ++ inst_ty ++ "}: tag " ++ + (showParen True (showsPrec 0 tag) $ + " is outside of bounds " ++ + show bnds)) + +fromEnumError :: (Show a,Show b) => String -> a -> b +fromEnumError inst_ty tag + = error ("Enum.fromEnum{" ++ inst_ty ++ "}: value " ++ + (showParen True (showsPrec 0 tag) $ + " is outside of Int's bounds " ++ + show (minBound::Int,maxBound::Int))) + +succError :: String -> a +succError inst_ty + = error ("Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound") + +predError :: String -> a +predError inst_ty + = error ("Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound") + +divZeroError :: (Show a) => String -> a -> b +divZeroError meth v + = error ("Integral." ++ meth ++ ": divide by 0 (" ++ show v ++ " / 0)") + \end{code} diff --git a/ghc/lib/exts/Word.lhs b/ghc/lib/exts/Word.lhs index 6e255f1..1e68948 100644 --- a/ghc/lib/exts/Word.lhs +++ b/ghc/lib/exts/Word.lhs @@ -17,34 +17,53 @@ module Word , Word64 -- Integral, Ix, Enum, -- Read, Show, Bits, -- CCallable, CReturnable - -- (last two + -- (last two are GHC specific.) + , word8ToWord16 -- :: Word8 -> Word16 , word8ToWord32 -- :: Word8 -> Word32 - , word32ToWord8 -- :: Word32 -> Word8 + , word8ToWord64 -- :: Word8 -> Word64 + + , word16ToWord8 -- :: Word16 -> Word32 , word16ToWord32 -- :: Word16 -> Word32 + , word16ToWord64 -- :: Word8 -> Word64 + + , word32ToWord8 -- :: Word32 -> Word8 , word32ToWord16 -- :: Word32 -> Word16 + , word32ToWord64 -- :: Word32 -> Word64 + , word64ToWord8 -- :: Word64 -> Word8 + , word64ToWord16 -- :: Word64 -> Word16 + , word64ToWord32 -- :: Word64 -> Word32 + , word8ToInt -- :: Word8 -> Int - , intToWord8 -- :: Int -> Word8 , word16ToInt -- :: Word16 -> Int - , intToWord16 -- :: Int -> Word16 , word32ToInt -- :: Word32 -> Int + , word64ToInt -- :: Word64 -> Int + + , intToWord8 -- :: Int -> Word8 + , intToWord16 -- :: Int -> Word16 , intToWord32 -- :: Int -> Word32 + , intToWord64 -- :: Int -> Word64 - , word32ToWord64 -- :: Word32 -> Word64 - , word64ToWord32 -- :: Word64 -> Word32 - + , word8ToInteger -- :: Word8 -> Integer + , word16ToInteger -- :: Word16 -> Integer + , word32ToInteger -- :: Word32 -> Integer , word64ToInteger -- :: Word64 -> Integer + + , integerToWord8 -- :: Integer -> Word8 + , integerToWord16 -- :: Integer -> Word16 + , integerToWord32 -- :: Integer -> Word32 , integerToWord64 -- :: Integer -> Word64 -- NB! GHC SPECIFIC: , wordToWord8 -- :: Word -> Word8 - , word8ToWord -- :: Word8 -> Word , wordToWord16 -- :: Word -> Word16 - , word16ToWord -- :: Word16 -> Word , wordToWord32 -- :: Word -> Word32 - , word32ToWord -- :: Word32 -> Word , wordToWord64 -- :: Word -> Word64 + + , word8ToWord -- :: Word8 -> Word + , word16ToWord -- :: Word16 -> Word + , word32ToWord -- :: Word32 -> Word , word64ToWord -- :: Word64 -> Word -- The "official" place to get these from is Addr. @@ -110,19 +129,26 @@ import Numeric (readDec, showInt) ----------------------------------------------------------------------------- word8ToWord32 :: Word8 -> Word32 -word32ToWord8 :: Word32 -> Word8 word16ToWord32 :: Word16 -> Word32 +word32ToWord8 :: Word32 -> Word8 word32ToWord16 :: Word32 -> Word16 -word8ToInt :: Word8 -> Int -intToWord8 :: Int -> Word8 -word16ToInt :: Word16 -> Int -intToWord16 :: Int -> Word16 +word8ToInt :: Word8 -> Int +word16ToInt :: Word16 -> Int +intToWord8 :: Int -> Word8 +intToWord16 :: Int -> Word16 + +integerToWord8 :: Integer -> Word8 +integerToWord16 :: Integer -> Word16 -word8ToInt = word32ToInt . word8ToWord32 -intToWord8 = word32ToWord8 . intToWord32 -word16ToInt = word32ToInt . word16ToWord32 -intToWord16 = word32ToWord16 . intToWord32 +word8ToInt = word32ToInt . word8ToWord32 +intToWord8 = word32ToWord8 . intToWord32 +word16ToInt = word32ToInt . word16ToWord32 +intToWord16 = word32ToWord16 . intToWord32 +word8ToInteger = word32ToInteger . word8ToWord32 +word16ToInteger = word32ToInteger . word16ToWord32 +integerToWord8 = fromInteger +integerToWord16 = fromInteger intToWord32 :: Int -> Word32 intToWord32 (I# x) = W32# ((int2Word# x) `and#` (case (maxBound::Word32) of W32# x# -> x#)) @@ -131,6 +157,12 @@ intToWord32 (I# x) = W32# ((int2Word# x) `and#` (case (maxBound::Word32) of W3 word32ToInt :: Word32 -> Int word32ToInt (W32# x) = I# (word2Int# x) +word32ToInteger :: Word32 -> Integer +word32ToInteger (W32# x) = word2Integer x + +integerToWord32 :: Integer -> Word32 +integerToWord32 = fromInteger + wordToInt :: Word -> Int wordToInt (W# w#) = I# (word2Int# w#) @@ -152,6 +184,7 @@ instance CCallable Word8 instance CReturnable Word8 word8ToWord32 (W8# x) = W32# x +word8ToWord16 (W8# x) = W16# x word32ToWord8 (W32# x) = W8# (wordToWord8# x) -- mask out upper three bytes. @@ -211,12 +244,25 @@ instance Real Word8 where -- Note: no need to mask results here -- as they cannot overflow. instance Integral Word8 where - div (W8# x) (W8# y) = W8# (x `quotWord#` y) - quot (W8# x) (W8# y) = W8# (x `quotWord#` y) - rem (W8# x) (W8# y) = W8# (x `remWord#` y) - mod (W8# x) (W8# y) = W8# (x `remWord#` y) + div x@(W8# x#) (W8# y#) + | y# `neWord#` (int2Word# 0#) = W8# (x# `quotWord#` y#) + | otherwise = divZeroError "div{Word8}" x + + quot x@(W8# x#) (W8# y#) + | y# `neWord#` (int2Word# 0#) = W8# (x# `quotWord#` y#) + | otherwise = divZeroError "quot{Word8}" x + + rem x@(W8# x#) (W8# y#) + | y# `neWord#` (int2Word# 0#) = W8# (x# `remWord#` y#) + | otherwise = divZeroError "rem{Word8}" x + + mod x@(W8# x#) (W8# y#) + | y# `neWord#` (int2Word# 0#) = W8# (x# `remWord#` y#) + | otherwise = divZeroError "mod{Word8}" x + quotRem (W8# x) (W8# y) = (W8# (x `quotWord#` y), W8# (x `remWord#` y)) divMod (W8# x) (W8# y) = (W8# (x `quotWord#` y), W8# (x `remWord#` y)) + toInteger (W8# x) = word2Integer x toInt x = word8ToInt x @@ -229,17 +275,26 @@ instance Ix Word8 where instance Enum Word8 where succ w - | w == maxBound = error ("Enum{Word8}.succ: tried to take `succ' of " ++ show w) + | w == maxBound = succError "Word8" | otherwise = w+1 pred w - | w == minBound = error ("Enum{Word8}.pred: tried to take `pred' of " ++ show w) - | otherwise = w+1 + | w == minBound = predError "Word8" + | otherwise = w-1 + + toEnum i@(I# i#) + | i >= toInt (minBound::Word8) && i <= toInt (maxBound::Word8) + = W8# (intToWord8# i#) + | otherwise + = toEnumError "Word8" i (minBound::Word8,maxBound::Word8) - toEnum (I# i) = W8# (intToWord8# i) fromEnum (W8# w) = I# (word2Int# w) - enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Word8)] - enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Word8)] - where last = if d < c then minBound else maxBound + enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Word8)] + enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum last] + where + last :: Word8 + last + | d < c = minBound + | otherwise = maxBound instance Read Word8 where readsPrec _ = readDec @@ -316,6 +371,7 @@ instance CCallable Word16 instance CReturnable Word16 word16ToWord32 (W16# x) = W32# x +word16ToWord8 (W16# x) = W8# (wordToWord8# x) word32ToWord16 (W32# x) = W16# (wordToWord16# x) -- mask out upper 16 bits. @@ -366,12 +422,25 @@ instance Real Word16 where toRational x = toInteger x % 1 instance Integral Word16 where - div (W16# x) (W16# y) = W16# (x `quotWord#` y) - quot (W16# x) (W16# y) = W16# (x `quotWord#` y) - rem (W16# x) (W16# y) = W16# (x `remWord#` y) - mod (W16# x) (W16# y) = W16# (x `remWord#` y) + div x@(W16# x#) (W16# y#) + | y# `neWord#` (int2Word# 0#) = W16# (x# `quotWord#` y#) + | otherwise = divZeroError "div{Word16}" x + + quot x@(W16# x#) (W16# y#) + | y# `neWord#`(int2Word# 0#) = W16# (x# `quotWord#` y#) + | otherwise = divZeroError "quot{Word16}" x + + rem x@(W16# x#) (W16# y#) + | y# `neWord#` (int2Word# 0#) = W16# (x# `remWord#` y#) + | otherwise = divZeroError "rem{Word16}" x + + mod x@(W16# x#) (W16# y#) + | y# `neWord#` (int2Word# 0#) = W16# (x# `remWord#` y#) + | otherwise = divZeroError "mod{Word16}" x + quotRem (W16# x) (W16# y) = (W16# (x `quotWord#` y), W16# (x `remWord#` y)) divMod (W16# x) (W16# y) = (W16# (x `quotWord#` y), W16# (x `remWord#` y)) + toInteger (W16# x) = word2Integer x toInt x = word16ToInt x @@ -383,17 +452,27 @@ instance Ix Word16 where inRange (m,n) i = m <= i && i <= n instance Enum Word16 where - succ w - | w == maxBound = error ("Enum{Word16}.succ: tried to take `succ' of " ++ show w) - | otherwise = w+1 - pred w - | w == minBound = error ("Enum{Word16}.pred: tried to take `pred' of " ++ show w) + succ w + | w == maxBound = succError "Word16" | otherwise = w+1 - toEnum (I# i) = W16# (intToWord16# i) - fromEnum (W16# w) = I# (word2Int# w) - enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Word16)] - enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Word16)] - where last = if d < c then minBound else maxBound + pred w + | w == minBound = predError "Word16" + | otherwise = w-1 + + toEnum i@(I# i#) + | i >= toInt (minBound::Word16) && i <= toInt (maxBound::Word16) + = W16# (intToWord16# i#) + | otherwise + = toEnumError "Word16" i (minBound::Word16,maxBound::Word16) + + fromEnum (W16# w) = I# (word2Int# w) + enumFrom c = map toEnum [fromEnum c .. fromEnum (maxBound::Word16)] + enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum last] + where + last :: Word16 + last + | d < c = minBound + | otherwise = maxBound instance Read Word16 where readsPrec _ = readDec @@ -497,9 +576,9 @@ intToWord32# :: Int# -> Word# wordToWord32# :: Word# -> Word# #if WORD_SIZE_IN_BYTES == 8 -intToWord32# i# = (int2Word# i#) `and#` (int2Word# 0xffffffff) -wordToWord32# w# = w# `and#` (int2Word# 0xffffffff) -wordToWord64# w# = w# +intToWord32# i# = (int2Word# i#) `and#` (int2Word# 0xffffffff#) +wordToWord32# w# = w# `and#` (int2Word# 0xffffffff#) +wordToWord64# w# = w# #else intToWord32# i# = int2Word# i# wordToWord32# w# = w# @@ -518,12 +597,25 @@ instance Real Word32 where toRational x = toInteger x % 1 instance Integral Word32 where - div x y = quotWord32 x y - quot x y = quotWord32 x y - rem x y = remWord32 x y - mod x y = remWord32 x y + div x y + | y /= 0 = quotWord32 x y + | otherwise = divZeroError "div{Word32}" x + + quot x y + | y /= 0 = quotWord32 x y + | otherwise = divZeroError "quot{Word32}" x + + rem x y + | y /= 0 = remWord32 x y + | otherwise = divZeroError "rem{Word32}" x + + mod x y + | y /= 0 = remWord32 x y + | otherwise = divZeroError "mod{Word32}" x + quotRem a b = (a `quotWord32` b, a `remWord32` b) divMod x y = quotRem x y + toInteger (W32# x) = word2Integer x toInt (W32# x) = I# (word2Int# x) @@ -542,55 +634,71 @@ instance Ix Word32 where instance Enum Word32 where succ w - | w == maxBound = error ("Enum{Word32}.succ: tried to take `succ' of " ++ show w) + | w == maxBound = succError "Word32" | otherwise = w+1 pred w - | w == minBound = error ("Enum{Word32}.pred: tried to take `pred' of " ++ show w) - | otherwise = w+1 - toEnum = intToWord32 - fromEnum = word32ToInt -- lossy, don't use. - enumFrom w = [w .. maxBound] - enumFromTo w1 w2 - | w1 > w2 = [] - | otherwise = eft32 w1 w2 - + | w == minBound = predError "Word32" + | otherwise = w-1 + + -- the toEnum/fromEnum will fail if the mapping isn't legal, + -- use the intTo* & *ToInt coercion functions to 'bypass' these range checks. + toEnum x + | x >= 0 = intToWord32 x + | otherwise + = toEnumError "Word32" x (minBound::Word32,maxBound::Word32) + + fromEnum x + | x <= intToWord32 (maxBound::Int) + = word32ToInt x + | otherwise + = fromEnumError "Word32" x + + enumFrom w = [w .. maxBound] + enumFromTo w1 w2 = eftt32 increasing w1 diff_f last + where + increasing = w1 <= w2 + + last + | increasing = (> w2) + | otherwise = (< w2) + + diff_f + | increasing = \ x -> x + 1 + | otherwise = \ x -> x - 1 + enumFromThen w1 w2 = [w1,w2 .. last] where + last :: Word32 last - | w1 < w2 = maxBound::Word32 + | w1 <=w2 = maxBound | otherwise = minBound - enumFromThenTo w1 w2 wend = eftt32 w1 stepWith + enumFromThenTo w1 w2 wend = eftt32 increasing w1 step_f last where + increasing = w1 <= w2 diff1 = w2 - w1 diff2 = w1 - w2 + + last + | increasing = (> wend) + | otherwise = (< wend) - increasing = w2 > w1 + step_f + | increasing = \ x -> x + diff1 + | otherwise = \ x -> x - diff2 - stepWith :: Word32 -> Maybe Word32 - stepWith x - | increasing && x > nxt = Nothing --oflow. - | wend <= x = Nothing - | otherwise = Just nxt - where - nxt - | increasing = x + diff1 - | otherwise = x - diff2 -eftt32 :: Word32 -> (Word32 -> Maybe Word32) -> [Word32] -eftt32 init stepper = go init +eftt32 :: Bool -> Word32 -> (Word32 -> Word32) -> (Word32-> Bool) -> [Word32] +eftt32 increasing init stepper done = go init where - go now = - case stepper now of - Nothing -> [now] - Just v -> now : go v - -eft32 :: Word32 -> Word32 -> [Word32] -eft32 now last = go now - where - go x - | x == last = [x] - | otherwise = x:go (x+1) + go now + | done now = [] + | increasing && now > nxt = [now] -- oflow + | not increasing && now < nxt = [now] -- uflow + | otherwise = now : go nxt + where + nxt = stepper now + instance Read Word32 where readsPrec _ = readDec @@ -645,6 +753,18 @@ sizeofWord32 = 4 word32ToWord64 :: Word32 -> Word64 word32ToWord64 (W32 w#) = W64# w# +word8ToWord64 :: Word8 -> Word64 +word8ToWord64 (W8# w#) = W64# w# + +word64ToWord8 :: Word64 -> Word8 +word64ToWord8 (W64# w#) = W8# (w# `and#` (int2Word# 0xff#)) + +word16ToWord64 :: Word16 -> Word64 +word16ToWord64 (W16# w#) = W64# w# + +word64ToWord16 :: Word64 -> Word16 +word64ToWord16 (W64# w#) = W16# (w# `and#` (int2Word# 0xffff#)) + wordToWord32# :: Word# -> Word# wordToWord32# w# = w# `and#` (case (maxBound::Word32) of W# x# -> x#) @@ -687,54 +807,30 @@ instance Num Word64 where fromInteger (J# a# s# d#) = W64# (integer2Word# a# s# d#) fromInt = intToWord64 -instance Bounded Word64 where - minBound = 0 - maxBound = minBound - 1 - -instance Real Word64 where - toRational x = toInteger x % 1 - -- Note: no need to mask results here -- as they cannot overflow. instance Integral Word64 where - div (W64# x) (W64# y) = W64# (x `quotWord#` y) - quot (W64# x) (W64# y) = W64# (x `quotWord#` y) - rem (W64# x) (W64# y) = W64# (x `remWord#` y) - mod (W64# x) (W64# y) = W64# (x `remWord#` y) - quotRem (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y)) - divMod (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y)) - toInteger (W64# x) = word2Integer# x - toInt x = word64ToInt x + div x@(W64# x#) (W64# y#) + | y# `neWord#` (int2Word# 0#) = W64# (x# `quotWord#` y#) + | otherwise = divZeroError "div{Word64}" x -instance Ix Word64 where - range (m,n) = [m..n] - index b@(m,_) i - | inRange b i = word64ToInt (i-m) - | otherwise = indexError i b "Word64" - inRange (m,n) i = m <= i && i <= n + quot x@(W64# x#) (W64# y#) + | y# `neWord#` (int2Word# 0#) = W64# (x# `quotWord#` y#) + | otherwise = divZeroError "quot{Word64}" x -instance Enum Word64 where - succ w - | w == maxBound = error ("Enum{Word64}.succ: tried to take `succ' of " ++ show w) - | otherwise = w+1 - pred w - | w == minBound = error ("Enum{Word64}.pred: tried to take `pred' of " ++ show w) - | otherwise = w+1 - toEnum (I# i) = W64# (intToWord# i) - fromEnum (W64# w) = I# (word2Int# w) -- lossy, don't use. - enumFrom w = eft64 w 1 - enumFromTo w1 w2 = eftt64 w1 1 (> w2) - enumFromThen w1 w2 = eftt64 w1 (w2 - w1) (>last) - where - last - | w1 < w2 = maxBound::Word64 - | otherwise = minBound + rem x@(W64# x#) (W64# y#) + | y# `neWord#` (int2Word# 0#) = W64# (x# `remWord#` y#) + | otherwise = divZeroError "rem{Word64}" x -instance Read Word64 where - readsPrec _ = readDec + mod (W64# x) (W64# y) + | y# `neWord#` (int2Word# 0#) = W64# (x `remWord#` y) + | otherwise = divZeroError "mod{Word64}" x -instance Show Word64 where - showsPrec _ = showInt + quotRem (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y)) + divMod (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y)) + + toInteger (W64# x) = word2Integer# x + toInt x = word64ToInt x instance Bits Word64 where @@ -783,6 +879,19 @@ word32ToWord64 (W32# w#) = W64# (wordToWord64# w#) word64ToWord32 :: Word64 -> Word32 word64ToWord32 (W64# w#) = W32# (word64ToWord# w#) +word8ToWord64 :: Word8 -> Word64 +word8ToWord64 (W8# w#) = W64# (wordToWord64# w#) + +word64ToWord8 :: Word64 -> Word8 +word64ToWord8 (W64# w#) = W8# ((word64ToWord# w#) `and#` (int2Word# 0xff#)) + +word16ToWord64 :: Word16 -> Word64 +word16ToWord64 (W16# w#) = W64# (wordToWord64# w#) + +word64ToWord16 :: Word64 -> Word16 +word64ToWord16 (W64# w#) = W16# ((word64ToWord# w#) `and#` (int2Word# 0xffff#)) + + word64ToInteger :: Word64 -> Integer word64ToInteger (W64# w#) = case word64ToInteger# w# of @@ -802,12 +911,6 @@ intToWord64 (I# i#) = W64# (intToWord64# i#) integerToWord64 :: Integer -> Word64 integerToWord64 (J# a# s# d#) = W64# (integerToWord64# a# s# d#) -instance Show Word64 where - showsPrec p x = showsPrec p (word64ToInteger x) - -instance Read Word64 where - readsPrec _ s = [ (integerToWord64 x,r) | (x,r) <- readDec s ] - instance Eq Word64 where (W64# x) == (W64# y) = x `eqWord64#` y (W64# x) /= (W64# y) = not (x `eqWord64#` y) @@ -839,15 +942,9 @@ instance Num Word64 where fromInteger i = integerToWord64 i fromInt = intToWord64 -instance Bounded Word64 where - minBound = 0 - maxBound = minBound - 1 - -instance Real Word64 where - toRational x = toInteger x % 1 - -- Note: no need to mask results here -- as they cannot overflow. +-- ToDo: protect against div by zero. instance Integral Word64 where div (W64# x) (W64# y) = W64# (x `quotWord64#` y) quot (W64# x) (W64# y) = W64# (x `quotWord64#` y) @@ -859,30 +956,6 @@ instance Integral Word64 where toInt x = word64ToInt x -instance Ix Word64 where - range (m,n) = [m..n] - index b@(m,_) i - | inRange b i = word64ToInt (i-m) - | otherwise = indexError i b "Word64" - inRange (m,n) i = m <= i && i <= n - -instance Enum Word64 where - succ w - | w == maxBound = error ("Enum{Word64}.succ: tried to take `succ' of " ++ show w) - | otherwise = w+1 - pred w - | w == minBound = error ("Enum{Word64}.pred: tried to take `pred' of " ++ show w) - | otherwise = w+1 - toEnum (I# i) = W64# (intToWord64# i) - fromEnum (W64# w) = I# (word2Int# (word64ToWord# w)) -- lossy, don't use. - enumFrom w = eft64 w 1 - enumFromTo w1 w2 = eftt64 w1 1 (> w2) - enumFromThen w1 w2 = eftt64 w1 (w2 - w1) (>last) - where - last - | w1 < w2 = maxBound::Word64 - | otherwise = minBound - instance Bits Word64 where (W64# x) .&. (W64# y) = W64# (x `and64#` y) (W64# x) .|. (W64# y) = W64# (x `or64#` y) @@ -1057,24 +1130,59 @@ intToInt64# i# = #endif +instance Enum Word64 where + succ w + | w == maxBound = succError "Word64" + | otherwise = w+1 + pred w + | w == minBound = predError "Word64" + | otherwise = w-1 + + toEnum i + | i >= 0 = intToWord64 i + | otherwise + = toEnumError "Word64" i (minBound::Word64,maxBound::Word64) + + fromEnum w + | w <= intToWord64 (maxBound::Int) + = word64ToInt w + | otherwise + = fromEnumError "Word64" w + + enumFrom e1 = map integerToWord64 [word64ToInteger e1 .. word64ToInteger maxBound] + enumFromTo e1 e2 = map integerToWord64 [word64ToInteger e1 .. word64ToInteger e2] + enumFromThen e1 e2 = map integerToWord64 [word64ToInteger e1, word64ToInteger e2 .. word64ToInteger last] + where + last :: Word64 + last + | e2 < e1 = minBound + | otherwise = maxBound + + enumFromThenTo e1 e2 e3 = map integerToWord64 [word64ToInteger e1, word64ToInteger e2 .. word64ToInteger e3] + +instance Show Word64 where + showsPrec p x = showsPrec p (word64ToInteger x) + +instance Read Word64 where + readsPrec _ s = [ (integerToWord64 x,r) | (x,r) <- readDec s ] + +instance Ix Word64 where + range (m,n) = [m..n] + index b@(m,_) i + | inRange b i = word64ToInt (i-m) + | otherwise = indexError i b "Word64" + inRange (m,n) i = m <= i && i <= n + +instance Bounded Word64 where + minBound = 0 + maxBound = minBound - 1 + +instance Real Word64 where + toRational x = toInteger x % 1 + sizeofWord64 :: Word32 sizeofWord64 = 8 --- Enum Word64 helper funs: - -eftt64 :: Word64 -> Word64 -> (Word64->Bool) -> [Word64] -eftt64 init step done = go init - where - go now - | done now = [] - | otherwise = now : go (now+step) - -eft64 :: Word64 -> Word64 -> [Word64] -eft64 now step = go now - where - go x - | x == maxBound = [x] - | otherwise = x:go (x+step) \end{code} @@ -1299,16 +1407,41 @@ writeWord64OffForeignObj fo i e = _casm_ `` (((StgNat64*)%0)[(StgInt)%1])=(StgNa \end{code} -C&P'ed from Ix.lhs +Utils for generating friendly error messages. \begin{code} {-# NOINLINE indexError #-} -indexError :: Show a => a -> (a,a) -> String -> b +indexError :: (Show a) => a -> (a,a) -> String -> b indexError i rng tp = error (showString "Ix{" . showString tp . showString "}.index: Index " . showParen True (showsPrec 0 i) . showString " out of range " $ showParen True (showsPrec 0 rng) "") +toEnumError :: (Show a,Show b) => String -> a -> (b,b) -> c +toEnumError inst_ty tag bnds + = error ("Enum.toEnum{" ++ inst_ty ++ "}: tag " ++ + (showParen True (showsPrec 0 tag) $ + " is outside of bounds " ++ + show bnds)) + +fromEnumError :: (Show a,Show b) => String -> a -> b +fromEnumError inst_ty tag + = error ("Enum.fromEnum{" ++ inst_ty ++ "}: value " ++ + (showParen True (showsPrec 0 tag) $ + " is outside of Int's bounds " ++ + show (minBound::Int,maxBound::Int))) + +succError :: String -> a +succError inst_ty + = error ("Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound") + +predError :: String -> a +predError inst_ty + = error ("Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound") + +divZeroError :: (Show a) => String -> a -> b +divZeroError meth v + = error ("Integral." ++ meth ++ ": divide by 0 (" ++ show v ++ " / 0)") \end{code} -- 1.7.10.4