module Language.Lexer.Tlex.Data.SymEnumSet (
    SymEnumSet,
    empty,
    full,
    complement,
    singleton,
    union,
    intersection,
    difference,
    fromEnumSet,
    toEnumSet,
) where

import           Prelude

import qualified Language.Lexer.Tlex.Data.EnumSet as EnumSet


data SymEnumSet a = SymEnumSet
    { SymEnumSet a -> Bool
isStraight      :: Bool
    , SymEnumSet a -> EnumSet a
internalEnumSet :: EnumSet.EnumSet a
    }
    deriving (SymEnumSet a -> SymEnumSet a -> Bool
(SymEnumSet a -> SymEnumSet a -> Bool)
-> (SymEnumSet a -> SymEnumSet a -> Bool) -> Eq (SymEnumSet a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k (a :: k). SymEnumSet a -> SymEnumSet a -> Bool
/= :: SymEnumSet a -> SymEnumSet a -> Bool
$c/= :: forall k (a :: k). SymEnumSet a -> SymEnumSet a -> Bool
== :: SymEnumSet a -> SymEnumSet a -> Bool
$c== :: forall k (a :: k). SymEnumSet a -> SymEnumSet a -> Bool
Eq, Int -> SymEnumSet a -> ShowS
[SymEnumSet a] -> ShowS
SymEnumSet a -> String
(Int -> SymEnumSet a -> ShowS)
-> (SymEnumSet a -> String)
-> ([SymEnumSet a] -> ShowS)
-> Show (SymEnumSet a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall k (a :: k). Int -> SymEnumSet a -> ShowS
forall k (a :: k). [SymEnumSet a] -> ShowS
forall k (a :: k). SymEnumSet a -> String
showList :: [SymEnumSet a] -> ShowS
$cshowList :: forall k (a :: k). [SymEnumSet a] -> ShowS
show :: SymEnumSet a -> String
$cshow :: forall k (a :: k). SymEnumSet a -> String
showsPrec :: Int -> SymEnumSet a -> ShowS
$cshowsPrec :: forall k (a :: k). Int -> SymEnumSet a -> ShowS
Show)

instance Enum a => Semigroup (SymEnumSet a) where
    <> :: SymEnumSet a -> SymEnumSet a -> SymEnumSet a
(<>) = SymEnumSet a -> SymEnumSet a -> SymEnumSet a
forall a. Enum a => SymEnumSet a -> SymEnumSet a -> SymEnumSet a
union

instance Enum a => Monoid (SymEnumSet a) where
    mempty :: SymEnumSet a
mempty = SymEnumSet a
forall a. Enum a => SymEnumSet a
empty

empty :: Enum a => SymEnumSet a
empty :: SymEnumSet a
empty = SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
    { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
    , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a
forall a. Enum a => EnumSet a
EnumSet.empty
    }

full :: Enum a => SymEnumSet a
full :: SymEnumSet a
full = SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
    { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
False
    , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a
forall a. Enum a => EnumSet a
EnumSet.empty
    }

complement :: Enum a => SymEnumSet a -> SymEnumSet a
complement :: SymEnumSet a -> SymEnumSet a
complement SymEnumSet a
s = SymEnumSet a
s
    { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool -> Bool
not do SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s
    }

singleton :: Enum a => a -> SymEnumSet a
singleton :: a -> SymEnumSet a
singleton a
x = SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
    { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
    , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = a -> EnumSet a
forall a. Enum a => a -> EnumSet a
EnumSet.singleton a
x
    }

union :: Enum a => SymEnumSet a -> SymEnumSet a -> SymEnumSet a
union :: SymEnumSet a -> SymEnumSet a -> SymEnumSet a
union SymEnumSet a
s1 SymEnumSet a
s2 = case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s1 of
    Bool
True -> case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s2 of
        Bool
True -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.union
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }
        Bool
False -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
False
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.difference
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
            }
    Bool
False -> case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s2 of
        Bool
True -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
False
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.difference
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }
        Bool
False -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
False
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.intersection
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }

intersection :: Enum a => SymEnumSet a -> SymEnumSet a -> SymEnumSet a
intersection :: SymEnumSet a -> SymEnumSet a -> SymEnumSet a
intersection SymEnumSet a
s1 SymEnumSet a
s2 = case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s1 of
    Bool
True -> case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s2 of
        Bool
True -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.intersection
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }
        Bool
False -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.difference
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }
    Bool
False -> case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s2 of
        Bool
True -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.difference
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
            }
        Bool
False -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
False
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.union
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }

difference :: Enum a => SymEnumSet a -> SymEnumSet a -> SymEnumSet a
difference :: SymEnumSet a -> SymEnumSet a -> SymEnumSet a
difference SymEnumSet a
s1 SymEnumSet a
s2 = case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s1 of
    Bool
True -> case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s2 of
        Bool
True -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.difference
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }
        Bool
False -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.intersection
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
            }
    Bool
False -> case SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s2 of
        Bool
True -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
False
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.union
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
            }
        Bool
False -> SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
            { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
True
            , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a -> EnumSet a -> EnumSet a
forall a. Enum a => EnumSet a -> EnumSet a -> EnumSet a
EnumSet.difference
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s2
                do SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s1
            }

fromEnumSet :: Enum a => Bool -> EnumSet.EnumSet a -> SymEnumSet a
fromEnumSet :: Bool -> EnumSet a -> SymEnumSet a
fromEnumSet Bool
b EnumSet a
s = SymEnumSet :: forall k (a :: k). Bool -> EnumSet a -> SymEnumSet a
SymEnumSet
    { $sel:isStraight:SymEnumSet :: Bool
isStraight = Bool
b
    , $sel:internalEnumSet:SymEnumSet :: EnumSet a
internalEnumSet = EnumSet a
s
    }

toEnumSet :: Enum a => SymEnumSet a -> (Bool, EnumSet.EnumSet a)
toEnumSet :: SymEnumSet a -> (Bool, EnumSet a)
toEnumSet SymEnumSet a
s = (SymEnumSet a -> Bool
forall k (a :: k). SymEnumSet a -> Bool
isStraight SymEnumSet a
s, SymEnumSet a -> EnumSet a
forall k (a :: k). SymEnumSet a -> EnumSet a
internalEnumSet SymEnumSet a
s)