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
    { forall e a. Reporter e a -> Bag e
getReportBag :: Bag.Bag e
    , forall e a. Reporter e a -> a
getResult    :: a
    }
    deriving (Reporter e a -> Reporter e a -> Bool
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
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, 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
<$ :: forall a b. a -> Reporter e b -> Reporter e a
$c<$ :: forall e a b. a -> Reporter e b -> Reporter e a
fmap :: forall a b. (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 :: forall e a. Reporter e a -> [e]
getReports Reporter e a
x = forall (t :: * -> *) a. Foldable t => t a -> [a]
toList do forall e a. Reporter e a -> Bag e
getReportBag Reporter e a
x

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

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

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

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

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

instance Monad (Reporter e) where
    Reporter e a
mx >>= :: forall a b. 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 forall e a. Reporter e a -> a
getResult Reporter e a
mx
        in Reporter
            { $sel:getReportBag:Reporter :: Bag e
getReportBag = forall e a. Reporter e a -> Bag e
getReportBag Reporter e a
mx forall a. Semigroup a => a -> a -> a
<> forall e a. Reporter e a -> Bag e
getReportBag Reporter e b
my
            , $sel:getResult:Reporter :: b
getResult = forall e a. Reporter e a -> a
getResult Reporter e b
my
            }