-- | Extension to the ''Prelude''.

module BNFC.Prelude
  ( module Prelude

  , module BNFC.Utils.Decoration
  , module BNFC.Utils.List1
  , module BNFC.Utils.List2
  , module BNFC.Utils.Singleton
  , module BNFC.Utils.Panic

  , module Control.Monad
  , module Control.Monad.Except
  , module Control.Monad.Reader
  , module Control.Monad.State
  , module Control.Monad.Trans
  , module Control.Monad.Trans.Control
  , module Control.Monad.Writer

  , module Data.Bifunctor
  , module Data.Char
  , module Data.Containers.ListUtils
  , module Data.Either
  , module Data.Foldable
  , module Data.Function
  , module Data.Functor
  -- , module Data.Functor.Compat
  , module Data.Maybe
  , module Data.Semigroup
  , module Data.Tuple

  -- , module Data.List.Extra

  , module Data.List.NonEmpty
  , module Data.Map
  , module Data.Set

  , module Lens.Micro
  , module Lens.Micro.Mtl

  , spanEnd
  , forMM_
  )
  where

-- Keep in order!
-- By default, in alphabetical order.

import Prelude hiding (exp)

import BNFC.Utils.Decoration
import BNFC.Utils.List1             ( List1, pattern (:|), (<|), nonEmpty, String1, trim1 )
import BNFC.Utils.List2             ( List2(..) )
import BNFC.Utils.Singleton
import BNFC.Utils.Panic

import Control.Monad
import Control.Monad.Except         ( MonadError(..), ExceptT(..), runExceptT )
import Control.Monad.Reader         ( MonadReader(..), asks, ReaderT(..), mapReaderT, runReaderT )
import Control.Monad.State          ( MonadState(..), gets, modify, StateT(..), evalStateT, execStateT )
import Control.Monad.Trans          ( MonadTrans(..), lift )
import Control.Monad.Trans.Control  ( MonadTransControl(..), liftThrough )
import Control.Monad.Writer         ( MonadWriter(..), WriterT(..), Writer, runWriter )

import Data.Bifunctor
import Data.Char
import Data.Containers.ListUtils    ( nubOrd )
import Data.Either
import Data.Foldable                ( all, toList )
import Data.Function                ( on )
import Data.Functor
-- (<&>) is also exported by Lens.Micro
-- import Data.Functor.Compat          ( (<&>) )
import Data.Maybe
import Data.Semigroup               ( Semigroup(..) )
import Data.Tuple

-- extra: export functions individually
-- import Data.List.Extra              ( trim )

-- containers: only export types and operators
import Data.List.NonEmpty           ( pattern (:|), (<|) )
import Data.Map                     ( Map )
import Data.Set                     ( Set )

import Lens.Micro
import Lens.Micro.Mtl

import qualified Data.List.NonEmpty

-- * Non-empty lists and their utilities.

-- * List utilities

-- Note: there is also spanEnd in Data.List.Extra, but this implementation
-- seems more efficient.

-- | @spanEnd p l == reverse (span p (reverse l))@.
--
-- Invariant: @l == front ++ end where (end, front) = spanEnd p l@
--
-- (From package ghc, module Util.)
spanEnd :: (a -> Bool) -> [a] -> ([a], [a])
spanEnd :: (a -> Bool) -> [a] -> ([a], [a])
spanEnd a -> Bool
p [a]
l = [a] -> [a] -> [a] -> [a] -> ([a], [a])
go [a]
l [] [] [a]
l
  where
  go :: [a] -> [a] -> [a] -> [a] -> ([a], [a])
go [a]
yes [a]
_        [a]
rev_no [] = ([a]
yes, [a] -> [a]
forall a. [a] -> [a]
reverse [a]
rev_no)
  go [a]
yes [a]
rev_yes  [a]
rev_no (a
x:[a]
xs)
    | a -> Bool
p a
x       = [a] -> [a] -> [a] -> [a] -> ([a], [a])
go [a]
yes (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
rev_yes) [a]
rev_no                  [a]
xs
    | Bool
otherwise = [a] -> [a] -> [a] -> [a] -> ([a], [a])
go [a]
xs  []            (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
rev_yes [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
rev_no) [a]
xs

-- * Monad utilities

forMM_ :: (Monad m, Foldable t) => m (t a) -> (a -> m ()) -> m ()
forMM_ :: m (t a) -> (a -> m ()) -> m ()
forMM_ m (t a)
m a -> m ()
f = (a -> m ()) -> t a -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ a -> m ()
f (t a -> m ()) -> m (t a) -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m (t a)
m