content: {-# OPTIONS_JHC -fm4 -fno-prelude -fffi -funboxed-values #-}
  module Jhc.Enum(Enum(..),Bounded(..)) where
  -- Enumeration and Bounded classes
  
  import Jhc.Basics
  import Jhc.Inst.PrimEnum()
  import Jhc.Int
  
  m4_include(Jhc/Enum.m4)
  
  otherwise = True
  
  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' `intLt` c    = minBound
                                      | otherwise = maxBound
      enumFromTo x y = f x where
          f x | x `intGt` y = []
              | otherwise = x:f (increment x)
      enumFromThenTo x y z | y `intGte` x = f x where
          inc = y `minus` x
          f x | x `intLte` z = x:f (x `plus` inc)
              | otherwise = []
      enumFromThenTo x y z  = f x where
          inc = y `minus` x
          f x | x `intGte` z = x:f (x `plus` inc)
              | otherwise = []
  
  foreign import primitive "box" boxBool :: Bool_ -> Bool
  foreign import primitive "Gte" intGte' :: Int -> Int -> Bool_
  foreign import primitive "Gt" intGt' :: Int -> Int -> Bool_
  foreign import primitive "Lte" intLte' :: Int -> Int -> Bool_
  foreign import primitive "Lt" intLt' :: Int -> Int -> Bool_
  foreign import primitive "Lt" charLt' :: Char -> Char -> Bool_
  
  intGte x y = boxBool (intGte' x y)
  intGt x y = boxBool (intGt' x y)
  intLte x y = boxBool (intLte' x y)
  intLt x y = boxBool (intLt' x y)
  charLt x y = boxBool (charLt' x y)
  
  instance Enum Char where
      toEnum = chr
      fromEnum = ord
      enumFrom c        = [c .. maxBound::Char]
      enumFromThen c c' = [c, c' .. lastChar]
                        where lastChar :: Char
                              lastChar | c' `charLt` 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
  
  deriving instance Enum Bool
  deriving instance Enum Ordering
  
  instance Bounded Bool where
      minBound = False
      maxBound = True
  instance Bounded Ordering where
      minBound = LT
      maxBound = GT
  instance Bounded () where
      minBound = ()
      maxBound = ()
  instance Bounded Char where
      minBound = Char 0#
      maxBound = Char 0x10ffff#
  
  BOUNDED(Int)
  BOUNDED(Integer)
  
  --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_
  