lhc-0.6.20090126: lib/base/src/Lhc/Enum.hs
{-# OPTIONS_LHC -N -fffi -funboxed-values #-}
module Lhc.Enum(Enum(..),Bounded(..)) where
-- Enumeration and Bounded classes
import Lhc.Inst.PrimEnum()
import Data.Int
import Lhc.Types
import Lhc.Basics
import Lhc.Order
import Lhc.Int
class Enum a where
succ, pred :: a -> a
toEnum :: Int -> a
fromEnum :: a -> Int
enumFrom :: a -> [a] -- [n..]
enumFromThen :: a -> a -> [a] -- [n,n'..]
enumFromTo :: a -> a -> [a] -- [n..m]
enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
-- Minimal complete definition:
-- toEnum, fromEnum
--
-- NOTE: these default methods only make sense for types
-- that map injectively into Int using fromEnum
-- and toEnum.
succ = toEnum . increment . fromEnum
pred = toEnum . decrement . fromEnum
enumFrom x = map toEnum [fromEnum x ..]
enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]
enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]
enumFromThenTo x y z =
map toEnum [fromEnum x, fromEnum y .. fromEnum z]
class Bounded a where
minBound :: a
maxBound :: a
instance Enum Int where
succ = increment
pred = decrement
toEnum x = x
fromEnum x = x
enumFrom x | x `seq` True = enumFromTo x maxBound
enumFromThen c c' = [c, c' .. lastInt]
where lastInt | c' < c = minBound
| otherwise = maxBound
enumFromTo x y = f x where
f x | x > y = []
| otherwise = x:f (increment x)
enumFromThenTo = efdtInt
----------------------------------------------------------------------
-- Shamelessly stolen from GHC.Enum
efdtInt :: Int -> Int -> Int -> [Int]
-- [x1,x2..y]
efdtInt x1 x2 y
| x2 >= x1 = efdtIntUp x1 x2 y
| otherwise = efdtIntDn x1 x2 y
-- Requires x2 >= x1
efdtIntUp :: Int -> Int -> Int -> [Int]
efdtIntUp x1 x2 y -- Be careful about overflow!
| y < x2 = if y < x1 then [] else [x1]
| otherwise = -- Common case: x1 <= x2 <= y
let delta = x2 `minus` x1 -- >= 0
y' = y `minus` delta -- x1 <= y' <= y; hence y' is representable
-- Invariant: x <= y
-- Note that: z <= y' => z + delta won't overflow
-- so we are guaranteed not to overflow if/when we recurse
go_up x | x > y' = [x]
| otherwise = x : go_up (x `plus` delta)
in x1 : go_up x2
-- Requires x2 <= x1
efdtIntDn :: Int -> Int -> Int -> [Int]
efdtIntDn x1 x2 y -- Be careful about underflow!
| y > x2 = if y > x1 then [] else [x1]
| otherwise = -- Common case: x1 >= x2 >= y
let delta = x2 `minus` x1 -- <= 0
y' = y `minus` delta -- y <= y' <= x1; hence y' is representable
-- Invariant: x >= y
-- Note that: z >= y' => z + delta won't underflow
-- so we are guaranteed not to underflow if/when w-e recurse
go_dn x | x < y' = [x]
| otherwise = x : go_dn (x `plus` delta)
in x1 : go_dn x2
-- End shameless theft
----------------------------------------------------------------------
instance Enum Char where
toEnum = chr
fromEnum = ord
enumFrom c = [c .. maxBound::Char]
enumFromThen c c' = [c, c' .. lastChar]
where lastChar :: Char
lastChar | c' < c = minBound
| otherwise = maxBound
-- enumFromTo (Char x) (Char y) = f x where
-- f x = case x `bits32UGt` y of
-- 0# -> []
-- 1# -> Char x:f (bits32Increment x)
-- enumFromThenTo (Char x) (Char y) (Char z) =
-- case y `bits32Sub` x of
-- inc -> let f x = case x `bits32UGte` z of
-- 1# -> Char x:f (x `bits32Add` inc)
-- 0# -> []
-- in f x
instance Bounded Char where
minBound = Char 0#
maxBound = Char 0x10ffff#
foreign import primitive "UGt" bits32UGt :: Bits32_ -> Bits32_ -> Bool__
foreign import primitive "UGte" bits32UGte :: Bits32_ -> Bits32_ -> Bool__
foreign import primitive "increment" bits32Increment :: Bits32_ -> Bits32_
foreign import primitive "Add" bits32Add :: Bits32_ -> Bits32_ -> Bits32_
foreign import primitive "Sub" bits32Sub :: Bits32_ -> Bits32_ -> Bits32_