module Basement.NormalForm
    ( NormalForm(..)
    , deepseq
    , force
    ) where

import Basement.Compat.Base
import Basement.Compat.C.Types
import Basement.Compat.Natural
import Basement.Types.OffsetSize
import Basement.Types.Char7
import Basement.Types.Word128 (Word128)
import Basement.Types.Word256 (Word256)
import Basement.Bounded
import Basement.Endianness

-- | Data that can be fully evaluated in Normal Form
--
class NormalForm a where
    toNormalForm :: a -> ()

deepseq :: NormalForm a => a -> b -> b
deepseq :: a -> b -> b
deepseq a
a b
b = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> b -> b
`seq` b
b

force :: NormalForm a => a -> a
force :: a -> a
force a
a = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> a -> a
`seq` a
a

-----
-- GHC / base types

instance NormalForm Int8    where toNormalForm :: Int8 -> ()
toNormalForm !Int8
_ = ()
instance NormalForm Int16   where toNormalForm :: Int16 -> ()
toNormalForm !Int16
_ = ()
instance NormalForm Int32   where toNormalForm :: Int32 -> ()
toNormalForm !Int32
_ = ()
instance NormalForm Int64   where toNormalForm :: Int64 -> ()
toNormalForm !Int64
_ = ()
instance NormalForm Int     where toNormalForm :: Int -> ()
toNormalForm !Int
_ = ()
instance NormalForm Integer where toNormalForm :: Integer -> ()
toNormalForm !Integer
_ = ()

instance NormalForm Word8   where toNormalForm :: Word8 -> ()
toNormalForm !Word8
_ = ()
instance NormalForm Word16  where toNormalForm :: Word16 -> ()
toNormalForm !Word16
_ = ()
instance NormalForm Word32  where toNormalForm :: Word32 -> ()
toNormalForm !Word32
_ = ()
instance NormalForm Word64  where toNormalForm :: Word64 -> ()
toNormalForm !Word64
_ = ()
instance NormalForm Word    where toNormalForm :: Word -> ()
toNormalForm !Word
_ = ()
instance NormalForm Natural where toNormalForm :: Natural -> ()
toNormalForm !Natural
_ = ()

instance NormalForm Float  where toNormalForm :: Float -> ()
toNormalForm !Float
_ = ()
instance NormalForm Double where toNormalForm :: Double -> ()
toNormalForm !Double
_ = ()

instance NormalForm Char where toNormalForm :: Char -> ()
toNormalForm !Char
_ = ()
instance NormalForm Bool where toNormalForm :: Bool -> ()
toNormalForm !Bool
_ = ()
instance NormalForm ()   where toNormalForm :: () -> ()
toNormalForm !()
_ = ()

-----
-- C Types
instance NormalForm CChar  where toNormalForm :: CChar -> ()
toNormalForm !CChar
_ = ()
instance NormalForm CUChar where toNormalForm :: CUChar -> ()
toNormalForm !CUChar
_ = ()
instance NormalForm CSChar where toNormalForm :: CSChar -> ()
toNormalForm !CSChar
_ = ()

instance NormalForm CShort  where toNormalForm :: CShort -> ()
toNormalForm !CShort
_ = ()
instance NormalForm CUShort where toNormalForm :: CUShort -> ()
toNormalForm !CUShort
_ = ()
instance NormalForm CInt    where toNormalForm :: CInt -> ()
toNormalForm !CInt
_ = ()
instance NormalForm CUInt   where toNormalForm :: CUInt -> ()
toNormalForm !CUInt
_ = ()
instance NormalForm CLong   where toNormalForm :: CLong -> ()
toNormalForm !CLong
_ = ()
instance NormalForm CULong  where toNormalForm :: CULong -> ()
toNormalForm !CULong
_ = ()
instance NormalForm CLLong  where toNormalForm :: CLLong -> ()
toNormalForm !CLLong
_ = ()
instance NormalForm CULLong where toNormalForm :: CULLong -> ()
toNormalForm !CULLong
_ = ()

instance NormalForm CFloat  where toNormalForm :: CFloat -> ()
toNormalForm !CFloat
_ = ()
instance NormalForm CDouble where toNormalForm :: CDouble -> ()
toNormalForm !CDouble
_ = ()

instance NormalForm (Ptr a) where toNormalForm :: Ptr a -> ()
toNormalForm !Ptr a
_ = ()

-----
-- Basic Foundation primitive types
instance NormalForm (Offset a) where toNormalForm :: Offset a -> ()
toNormalForm !Offset a
_ = ()
instance NormalForm (CountOf a) where toNormalForm :: CountOf a -> ()
toNormalForm !CountOf a
_ = ()

instance NormalForm Char7 where toNormalForm :: Char7 -> ()
toNormalForm !Char7
_ = ()
instance NormalForm Word128 where toNormalForm :: Word128 -> ()
toNormalForm !Word128
_ = ()
instance NormalForm Word256 where toNormalForm :: Word256 -> ()
toNormalForm !Word256
_ = ()
instance NormalForm (Zn n) where toNormalForm :: Zn n -> ()
toNormalForm = Natural -> ()
forall a. NormalForm a => a -> ()
toNormalForm (Natural -> ()) -> (Zn n -> Natural) -> Zn n -> ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Zn n -> Natural
forall (n :: Nat). Zn n -> Natural
unZn
instance NormalForm (Zn64 n) where toNormalForm :: Zn64 n -> ()
toNormalForm = Word64 -> ()
forall a. NormalForm a => a -> ()
toNormalForm (Word64 -> ()) -> (Zn64 n -> Word64) -> Zn64 n -> ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Zn64 n -> Word64
forall (n :: Nat). Zn64 n -> Word64
unZn64

-----
-- composed type

instance NormalForm a => NormalForm (Maybe a) where
    toNormalForm :: Maybe a -> ()
toNormalForm Maybe a
Nothing  = ()
    toNormalForm (Just a
a) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` ()
instance (NormalForm l, NormalForm r) => NormalForm (Either l r) where
    toNormalForm :: Either l r -> ()
toNormalForm (Left l
l)  = l -> ()
forall a. NormalForm a => a -> ()
toNormalForm l
l () -> () -> ()
`seq` ()
    toNormalForm (Right r
r) = r -> ()
forall a. NormalForm a => a -> ()
toNormalForm r
r () -> () -> ()
`seq` ()
instance NormalForm a => NormalForm (LE a) where
    toNormalForm :: LE a -> ()
toNormalForm (LE a
a) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` ()
instance NormalForm a => NormalForm (BE a) where
    toNormalForm :: BE a -> ()
toNormalForm (BE a
a) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` ()

instance NormalForm a => NormalForm [a] where
    toNormalForm :: [a] -> ()
toNormalForm []     = ()
    toNormalForm (a
x:[a]
xs) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
x () -> () -> ()
`seq` [a] -> ()
forall a. NormalForm a => a -> ()
toNormalForm [a]
xs

instance (NormalForm a, NormalForm b) => NormalForm (a,b) where
    toNormalForm :: (a, b) -> ()
toNormalForm (a
a,b
b) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b

instance (NormalForm a, NormalForm b, NormalForm c) => NormalForm (a,b,c) where
    toNormalForm :: (a, b, c) -> ()
toNormalForm (a
a,b
b,c
c) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b () -> () -> ()
`seq` c -> ()
forall a. NormalForm a => a -> ()
toNormalForm c
c

instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d) => NormalForm (a,b,c,d) where
    toNormalForm :: (a, b, c, d) -> ()
toNormalForm (a
a,b
b,c
c,d
d) = a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b () -> () -> ()
`seq` c -> ()
forall a. NormalForm a => a -> ()
toNormalForm c
c () -> () -> ()
`seq` d -> ()
forall a. NormalForm a => a -> ()
toNormalForm d
d

instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e)
      => NormalForm (a,b,c,d,e) where
    toNormalForm :: (a, b, c, d, e) -> ()
toNormalForm (a
a,b
b,c
c,d
d,e
e) =
        a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b () -> () -> ()
`seq` c -> ()
forall a. NormalForm a => a -> ()
toNormalForm c
c () -> () -> ()
`seq` d -> ()
forall a. NormalForm a => a -> ()
toNormalForm d
d () -> () -> ()
`seq`
        e -> ()
forall a. NormalForm a => a -> ()
toNormalForm e
e

instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e, NormalForm f)
      => NormalForm (a,b,c,d,e,f) where
    toNormalForm :: (a, b, c, d, e, f) -> ()
toNormalForm (a
a,b
b,c
c,d
d,e
e,f
f) =
        a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b () -> () -> ()
`seq` c -> ()
forall a. NormalForm a => a -> ()
toNormalForm c
c () -> () -> ()
`seq` d -> ()
forall a. NormalForm a => a -> ()
toNormalForm d
d () -> () -> ()
`seq`
        e -> ()
forall a. NormalForm a => a -> ()
toNormalForm e
e () -> () -> ()
`seq` f -> ()
forall a. NormalForm a => a -> ()
toNormalForm f
f

instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e, NormalForm f, NormalForm g)
      => NormalForm (a,b,c,d,e,f,g) where
    toNormalForm :: (a, b, c, d, e, f, g) -> ()
toNormalForm (a
a,b
b,c
c,d
d,e
e,f
f,g
g) =
        a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b () -> () -> ()
`seq` c -> ()
forall a. NormalForm a => a -> ()
toNormalForm c
c () -> () -> ()
`seq` d -> ()
forall a. NormalForm a => a -> ()
toNormalForm d
d () -> () -> ()
`seq`
        e -> ()
forall a. NormalForm a => a -> ()
toNormalForm e
e () -> () -> ()
`seq` f -> ()
forall a. NormalForm a => a -> ()
toNormalForm f
f () -> () -> ()
`seq` g -> ()
forall a. NormalForm a => a -> ()
toNormalForm g
g
instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e, NormalForm f, NormalForm g, NormalForm h)
      => NormalForm (a,b,c,d,e,f,g,h) where
    toNormalForm :: (a, b, c, d, e, f, g, h) -> ()
toNormalForm (a
a,b
b,c
c,d
d,e
e,f
f,g
g,h
h) =
        a -> ()
forall a. NormalForm a => a -> ()
toNormalForm a
a () -> () -> ()
`seq` b -> ()
forall a. NormalForm a => a -> ()
toNormalForm b
b () -> () -> ()
`seq` c -> ()
forall a. NormalForm a => a -> ()
toNormalForm c
c () -> () -> ()
`seq` d -> ()
forall a. NormalForm a => a -> ()
toNormalForm d
d () -> () -> ()
`seq`
        e -> ()
forall a. NormalForm a => a -> ()
toNormalForm e
e () -> () -> ()
`seq` f -> ()
forall a. NormalForm a => a -> ()
toNormalForm f
f () -> () -> ()
`seq` g -> ()
forall a. NormalForm a => a -> ()
toNormalForm g
g () -> () -> ()
`seq` h -> ()
forall a. NormalForm a => a -> ()
toNormalForm h
h