{-# LANGUAGE FlexibleContexts #-}

module Saturn.Unstable.Type.Element where

import qualified Data.Coerce as Coerce
import qualified Data.Set as Set
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Word as Word
import qualified Saturn.Unstable.Extra.Parsec as Parsec
import qualified Saturn.Unstable.Type.Number as Number
import qualified Saturn.Unstable.Type.Range as Range
import qualified Text.Parsec as Parsec

newtype Element
  = Element (Either Range.Range Number.Number)
  deriving (Element -> Element -> Bool
(Element -> Element -> Bool)
-> (Element -> Element -> Bool) -> Eq Element
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Element -> Element -> Bool
== :: Element -> Element -> Bool
$c/= :: Element -> Element -> Bool
/= :: Element -> Element -> Bool
Eq, Int -> Element -> ShowS
[Element] -> ShowS
Element -> String
(Int -> Element -> ShowS)
-> (Element -> String) -> ([Element] -> ShowS) -> Show Element
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Element -> ShowS
showsPrec :: Int -> Element -> ShowS
$cshow :: Element -> String
show :: Element -> String
$cshowList :: [Element] -> ShowS
showList :: [Element] -> ShowS
Show)

fromEither :: Either Range.Range Number.Number -> Element
fromEither :: Either Range Number -> Element
fromEither = Either Range Number -> Element
forall a b. Coercible a b => a -> b
Coerce.coerce

toEither :: Element -> Either Range.Range Number.Number
toEither :: Element -> Either Range Number
toEither = Element -> Either Range Number
forall a b. Coercible a b => a -> b
Coerce.coerce

parsec :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Element
parsec :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Element
parsec = Either Range Number -> Element
fromEither (Either Range Number -> Element)
-> ParsecT s u m (Either Range Number) -> ParsecT s u m Element
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s u m Range
-> ParsecT s u m Number -> ParsecT s u m (Either Range Number)
forall s u (m :: * -> *) a b.
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m (Either a b)
Parsec.either (ParsecT s u m Range -> ParsecT s u m Range
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
Parsec.try ParsecT s u m Range
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Range
Range.parsec) ParsecT s u m Number
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Number
Number.parsec

toBuilder :: Element -> Builder.Builder
toBuilder :: Element -> Builder
toBuilder = (Range -> Builder)
-> (Number -> Builder) -> Either Range Number -> Builder
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Range -> Builder
Range.toBuilder Number -> Builder
Number.toBuilder (Either Range Number -> Builder)
-> (Element -> Either Range Number) -> Element -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> Either Range Number
toEither

isValid :: (Word.Word8, Word.Word8) -> Element -> Bool
isValid :: (Word8, Word8) -> Element -> Bool
isValid (Word8, Word8)
tuple = (Range -> Bool) -> (Number -> Bool) -> Either Range Number -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((Word8, Word8) -> Range -> Bool
Range.isValid (Word8, Word8)
tuple) ((Word8, Word8) -> Number -> Bool
Number.isValid (Word8, Word8)
tuple) (Either Range Number -> Bool)
-> (Element -> Either Range Number) -> Element -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> Either Range Number
toEither

expand :: Element -> Set.Set Word.Word8
expand :: Element -> Set Word8
expand = (Range -> Set Word8)
-> (Number -> Set Word8) -> Either Range Number -> Set Word8
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Range -> Set Word8
Range.expand (Word8 -> Set Word8
forall a. a -> Set a
Set.singleton (Word8 -> Set Word8) -> (Number -> Word8) -> Number -> Set Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Number -> Word8
Number.toWord8) (Either Range Number -> Set Word8)
-> (Element -> Either Range Number) -> Element -> Set Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> Either Range Number
toEither