module Language.Lexer.Tlex.Data.Reporter (
    Reporter,
    report,
    getResult,
    getReports,
    toEither,
) where

import           Language.Lexer.Tlex.Prelude

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


data Reporter e a = Reporter
    { Reporter e a -> Bag e
getReportBag :: Bag.Bag e
    , Reporter e a -> a
getResult    :: a
    }
    deriving (Reporter e a -> Reporter e a -> Bool
(Reporter e a -> Reporter e a -> Bool)
-> (Reporter e a -> Reporter e a -> Bool) -> Eq (Reporter e a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall e a. (Eq e, Eq a) => Reporter e a -> Reporter e a -> Bool
/= :: Reporter e a -> Reporter e a -> Bool
$c/= :: forall e a. (Eq e, Eq a) => Reporter e a -> Reporter e a -> Bool
== :: Reporter e a -> Reporter e a -> Bool
$c== :: forall e a. (Eq e, Eq a) => Reporter e a -> Reporter e a -> Bool
Eq, Int -> Reporter e a -> ShowS
[Reporter e a] -> ShowS
Reporter e a -> String
(Int -> Reporter e a -> ShowS)
-> (Reporter e a -> String)
-> ([Reporter e a] -> ShowS)
-> Show (Reporter e a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall e a. (Show e, Show a) => Int -> Reporter e a -> ShowS
forall e a. (Show e, Show a) => [Reporter e a] -> ShowS
forall e a. (Show e, Show a) => Reporter e a -> String
showList :: [Reporter e a] -> ShowS
$cshowList :: forall e a. (Show e, Show a) => [Reporter e a] -> ShowS
show :: Reporter e a -> String
$cshow :: forall e a. (Show e, Show a) => Reporter e a -> String
showsPrec :: Int -> Reporter e a -> ShowS
$cshowsPrec :: forall e a. (Show e, Show a) => Int -> Reporter e a -> ShowS
Show, a -> Reporter e b -> Reporter e a
(a -> b) -> Reporter e a -> Reporter e b
(forall a b. (a -> b) -> Reporter e a -> Reporter e b)
-> (forall a b. a -> Reporter e b -> Reporter e a)
-> Functor (Reporter e)
forall a b. a -> Reporter e b -> Reporter e a
forall a b. (a -> b) -> Reporter e a -> Reporter e b
forall e a b. a -> Reporter e b -> Reporter e a
forall e a b. (a -> b) -> Reporter e a -> Reporter e b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Reporter e b -> Reporter e a
$c<$ :: forall e a b. a -> Reporter e b -> Reporter e a
fmap :: (a -> b) -> Reporter e a -> Reporter e b
$cfmap :: forall e a b. (a -> b) -> Reporter e a -> Reporter e b
Functor)

getReports :: Reporter e a -> [e]
getReports :: Reporter e a -> [e]
getReports Reporter e a
x = Bag e -> [e]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList do Reporter e a -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e a
x

report :: e -> Reporter e ()
report :: e -> Reporter e ()
report e
x = Reporter :: forall e a. Bag e -> a -> Reporter e a
Reporter
    { $sel:getReportBag:Reporter :: Bag e
getReportBag = e -> Bag e
forall a. a -> Bag a
Bag.singleton e
x
    , $sel:getResult:Reporter :: ()
getResult = ()
    }

toEither :: Reporter e a -> Either [e] a
toEither :: Reporter e a -> Either [e] a
toEither Reporter e a
x = case Reporter e a -> [e]
forall e a. Reporter e a -> [e]
getReports Reporter e a
x of
    [] -> a -> Either [e] a
forall a b. b -> Either a b
Right do Reporter e a -> a
forall e a. Reporter e a -> a
getResult Reporter e a
x
    [e]
es -> [e] -> Either [e] a
forall a b. a -> Either a b
Left [e]
es

instance Applicative (Reporter e) where
    pure :: a -> Reporter e a
pure a
x = Reporter :: forall e a. Bag e -> a -> Reporter e a
Reporter
        { $sel:getReportBag:Reporter :: Bag e
getReportBag = Bag e
forall a. Monoid a => a
mempty
        , $sel:getResult:Reporter :: a
getResult = a
x
        }

    Reporter e (a -> b)
mf <*> :: Reporter e (a -> b) -> Reporter e a -> Reporter e b
<*> Reporter e a
mx = Reporter :: forall e a. Bag e -> a -> Reporter e a
Reporter
        { $sel:getReportBag:Reporter :: Bag e
getReportBag = Reporter e (a -> b) -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e (a -> b)
mf Bag e -> Bag e -> Bag e
forall a. Semigroup a => a -> a -> a
<> Reporter e a -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e a
mx
        , $sel:getResult:Reporter :: b
getResult = Reporter e (a -> b) -> a -> b
forall e a. Reporter e a -> a
getResult Reporter e (a -> b)
mf do Reporter e a -> a
forall e a. Reporter e a -> a
getResult Reporter e a
mx
        }

instance Monad (Reporter e) where
    Reporter e a
mx >>= :: Reporter e a -> (a -> Reporter e b) -> Reporter e b
>>= a -> Reporter e b
f =
        let my :: Reporter e b
my = a -> Reporter e b
f do Reporter e a -> a
forall e a. Reporter e a -> a
getResult Reporter e a
mx
        in Reporter :: forall e a. Bag e -> a -> Reporter e a
Reporter
            { $sel:getReportBag:Reporter :: Bag e
getReportBag = Reporter e a -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e a
mx Bag e -> Bag e -> Bag e
forall a. Semigroup a => a -> a -> a
<> Reporter e b -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e b
my
            , $sel:getResult:Reporter :: b
getResult = Reporter e b -> b
forall e a. Reporter e a -> a
getResult Reporter e b
my
            }

    Reporter e a
mx >> :: Reporter e a -> Reporter e b -> Reporter e b
>> Reporter e b
my = Reporter :: forall e a. Bag e -> a -> Reporter e a
Reporter
        { $sel:getReportBag:Reporter :: Bag e
getReportBag = Reporter e a -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e a
mx Bag e -> Bag e -> Bag e
forall a. Semigroup a => a -> a -> a
<> Reporter e b -> Bag e
forall e a. Reporter e a -> Bag e
getReportBag Reporter e b
my
        , $sel:getResult:Reporter :: b
getResult = Reporter e b -> b
forall e a. Reporter e a -> a
getResult Reporter e b
my
        }