    {-# LANGUAGE CPP                 #-}
    {-# LANGUAGE DeriveTraversable   #-}
    {-# LANGUAGE OverloadedStrings   #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-|
    Module      : HsLua.Marshalling.Peek
    Copyright   : © 2020-2024 Albert Krewinkel
    License     : MIT
    Maintainer  : Albert Krewinkel <tarleb@hslua.org>
    Stability   : beta
    Portability : Portable

    Types for unmarshalling of values from Lua.
    -}
    module HsLua.Marshalling.Peek
      ( Peeker
      , runPeeker
      , Result (..)
      , isFailure
      , failure
      , force
      , retrieving
      , resultToEither
      , toPeeker
      -- * Lua peek monad
      , Peek (..)
      , forcePeek
      , failPeek
      , liftLua
      , withContext
      , lastly
      , cleanup
      ) where

    import Control.Applicative (Alternative (..))
    import Control.Monad ((<$!>), (<=<), MonadPlus)
    import Data.ByteString (ByteString)
    import Data.List (intercalate)
    import HsLua.Core as Lua
    #if !MIN_VERSION_base(4,13,0)
    import Control.Monad.Fail (MonadFail (..))
    #endif
    import qualified HsLua.Core.Utf8 as Utf8

    -- | Record to keep track of failure contexts while retrieving objects
    -- from the Lua stack.
    data Result a
      = Success !a
      | Failure ByteString [Name]       -- ^ Error message and stack of contexts
      deriving (Int -> Result a -> ShowS
    [Result a] -> ShowS
    Result a -> String
    (Int -> Result a -> ShowS)
    -> (Result a -> String) -> ([Result a] -> ShowS) -> Show (Result a)
    forall a. Show a => Int -> Result a -> ShowS
    forall a. Show a => [Result a] -> ShowS
    forall a. Show a => Result a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> Result a -> ShowS
    showsPrec :: Int -> Result a -> ShowS
    $cshow :: forall a. Show a => Result a -> String
    show :: Result a -> String
    $cshowList :: forall a. Show a => [Result a] -> ShowS
    showList :: [Result a] -> ShowS
    Show, Result a -> Result a -> Bool
    (Result a -> Result a -> Bool)
    -> (Result a -> Result a -> Bool) -> Eq (Result a)
    forall a. Eq a => Result a -> Result a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall a. Eq a => Result a -> Result a -> Bool
    == :: Result a -> Result a -> Bool
    $c/= :: forall a. Eq a => Result a -> Result a -> Bool
    /= :: Result a -> Result a -> Bool
    Eq, (forall m. Monoid m => Result m -> m)
    -> (forall m a. Monoid m => (a -> m) -> Result a -> m)
    -> (forall m a. Monoid m => (a -> m) -> Result a -> m)
    -> (forall a b. (a -> b -> b) -> b -> Result a -> b)
    -> (forall a b. (a -> b -> b) -> b -> Result a -> b)
    -> (forall b a. (b -> a -> b) -> b -> Result a -> b)
    -> (forall b a. (b -> a -> b) -> b -> Result a -> b)
    -> (forall a. (a -> a -> a) -> Result a -> a)
    -> (forall a. (a -> a -> a) -> Result a -> a)
    -> (forall a. Result a -> [a])
    -> (forall a. Result a -> Bool)
    -> (forall a. Result a -> Int)
    -> (forall a. Eq a => a -> Result a -> Bool)
    -> (forall a. Ord a => Result a -> a)
    -> (forall a. Ord a => Result a -> a)
    -> (forall a. Num a => Result a -> a)
    -> (forall a. Num a => Result a -> a)
    -> Foldable Result
    forall a. Eq a => a -> Result a -> Bool
    forall a. Num a => Result a -> a
    forall a. Ord a => Result a -> a
    forall m. Monoid m => Result m -> m
    forall a. Result a -> Bool
    forall a. Result a -> Int
    forall a. Result a -> [a]
    forall a. (a -> a -> a) -> Result a -> a
    forall m a. Monoid m => (a -> m) -> Result a -> m
    forall b a. (b -> a -> b) -> b -> Result a -> b
    forall a b. (a -> b -> b) -> b -> Result a -> b
    forall (t :: * -> *).
    (forall m. Monoid m => t m -> m)
    -> (forall m a. Monoid m => (a -> m) -> t a -> m)
    -> (forall m a. Monoid m => (a -> m) -> t a -> m)
    -> (forall a b. (a -> b -> b) -> b -> t a -> b)
    -> (forall a b. (a -> b -> b) -> b -> t a -> b)
    -> (forall b a. (b -> a -> b) -> b -> t a -> b)
    -> (forall b a. (b -> a -> b) -> b -> t a -> b)
    -> (forall a. (a -> a -> a) -> t a -> a)
    -> (forall a. (a -> a -> a) -> t a -> a)
    -> (forall a. t a -> [a])
    -> (forall a. t a -> Bool)
    -> (forall a. t a -> Int)
    -> (forall a. Eq a => a -> t a -> Bool)
    -> (forall a. Ord a => t a -> a)
    -> (forall a. Ord a => t a -> a)
    -> (forall a. Num a => t a -> a)
    -> (forall a. Num a => t a -> a)
    -> Foldable t
    $cfold :: forall m. Monoid m => Result m -> m
    fold :: forall m. Monoid m => Result m -> m
    $cfoldMap :: forall m a. Monoid m => (a -> m) -> Result a -> m
    foldMap :: forall m a. Monoid m => (a -> m) -> Result a -> m
    $cfoldMap' :: forall m a. Monoid m => (a -> m) -> Result a -> m
    foldMap' :: forall m a. Monoid m => (a -> m) -> Result a -> m
    $cfoldr :: forall a b. (a -> b -> b) -> b -> Result a -> b
    foldr :: forall a b. (a -> b -> b) -> b -> Result a -> b
    $cfoldr' :: forall a b. (a -> b -> b) -> b -> Result a -> b
    foldr' :: forall a b. (a -> b -> b) -> b -> Result a -> b
    $cfoldl :: forall b a. (b -> a -> b) -> b -> Result a -> b
    foldl :: forall b a. (b -> a -> b) -> b -> Result a -> b
    $cfoldl' :: forall b a. (b -> a -> b) -> b -> Result a -> b
    foldl' :: forall b a. (b -> a -> b) -> b -> Result a -> b
    $cfoldr1 :: forall a. (a -> a -> a) -> Result a -> a
    foldr1 :: forall a. (a -> a -> a) -> Result a -> a
    $cfoldl1 :: forall a. (a -> a -> a) -> Result a -> a
    foldl1 :: forall a. (a -> a -> a) -> Result a -> a
    $ctoList :: forall a. Result a -> [a]
    toList :: forall a. Result a -> [a]
    $cnull :: forall a. Result a -> Bool
    null :: forall a. Result a -> Bool
    $clength :: forall a. Result a -> Int
    length :: forall a. Result a -> Int
    $celem :: forall a. Eq a => a -> Result a -> Bool
    elem :: forall a. Eq a => a -> Result a -> Bool
    $cmaximum :: forall a. Ord a => Result a -> a
    maximum :: forall a. Ord a => Result a -> a
    $cminimum :: forall a. Ord a => Result a -> a
    minimum :: forall a. Ord a => Result a -> a
    $csum :: forall a. Num a => Result a -> a
    sum :: forall a. Num a => Result a -> a
    $cproduct :: forall a. Num a => Result a -> a
    product :: forall a. Num a => Result a -> a
    Foldable, (forall a b. (a -> b) -> Result a -> Result b)
    -> (forall a b. a -> Result b -> Result a) -> Functor Result
    forall a b. a -> Result b -> Result a
    forall a b. (a -> b) -> Result a -> Result b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> Result a -> Result b
    fmap :: forall a b. (a -> b) -> Result a -> Result b
    $c<$ :: forall a b. a -> Result b -> Result a
    <$ :: forall a b. a -> Result b -> Result a
    Functor, Functor Result
    Foldable Result
    (Functor Result, Foldable Result) =>
    (forall (f :: * -> *) a b.
     Applicative f =>
     (a -> f b) -> Result a -> f (Result b))
    -> (forall (f :: * -> *) a.
        Applicative f =>
        Result (f a) -> f (Result a))
    -> (forall (m :: * -> *) a b.
        Monad m =>
        (a -> m b) -> Result a -> m (Result b))
    -> (forall (m :: * -> *) a.
        Monad m =>
        Result (m a) -> m (Result a))
    -> Traversable Result
    forall (t :: * -> *).
    (Functor t, Foldable t) =>
    (forall (f :: * -> *) a b.
     Applicative f =>
     (a -> f b) -> t a -> f (t b))
    -> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
    -> (forall (m :: * -> *) a b.
        Monad m =>
        (a -> m b) -> t a -> m (t b))
    -> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
    -> Traversable t
    forall (m :: * -> *) a. Monad m => Result (m a) -> m (Result a)
    forall (f :: * -> *) a.
    Applicative f =>
    Result (f a) -> f (Result a)
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Result a -> m (Result b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Result a -> f (Result b)
    $ctraverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Result a -> f (Result b)
    traverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Result a -> f (Result b)
    $csequenceA :: forall (f :: * -> *) a.
    Applicative f =>
    Result (f a) -> f (Result a)
    sequenceA :: forall (f :: * -> *) a.
    Applicative f =>
    Result (f a) -> f (Result a)
    $cmapM :: forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Result a -> m (Result b)
    mapM :: forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Result a -> m (Result b)
    $csequence :: forall (m :: * -> *) a. Monad m => Result (m a) -> m (Result a)
    sequence :: forall (m :: * -> *) a. Monad m => Result (m a) -> m (Result a)
    Traversable)

    instance Applicative Result where
      pure :: forall a. a -> Result a
    pure = a -> Result a
    forall a. a -> Result a
    Success
      {-# INLINE pure #-}
      Success a -> b
    f         <*> :: forall a b. Result (a -> b) -> Result a -> Result b
    <*> Result a
    s = a -> b
    f (a -> b) -> Result a -> Result b
    forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
    <$!> Result a
    s
      Failure ByteString
    msg [Name]
    stack <*> Result a
    _ = ByteString -> [Name] -> Result b
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    msg [Name]
    stack
      {-# INLINE (<*>) #-}

    instance Monad Result where
      Failure ByteString
    msg [Name]
    stack >>= :: forall a b. Result a -> (a -> Result b) -> Result b
    >>= a -> Result b
    _ = ByteString -> [Name] -> Result b
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    msg [Name]
    stack
      Success a
    x         >>= a -> Result b
    f = a -> Result b
    f a
    x

    instance Alternative Result where
      empty :: forall a. Result a
    empty = ByteString -> [Name] -> Result a
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    "empty" []
      {-# INLINE empty #-}
      Result a
    x <|> :: forall a. Result a -> Result a -> Result a
    <|> Result a
    y = case Result a
    x of
        Failure {} -> Result a
    y
        Result a
    _          -> Result a
    x
      {-# INLINE (<|>) #-}

    instance MonadPlus Result

    instance MonadFail Result where
      fail :: forall a. String -> Result a
    fail = ByteString -> Result a
    forall a. ByteString -> Result a
    failure (ByteString -> Result a)
    -> (String -> ByteString) -> String -> Result a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ByteString
    Utf8.fromString
      {-# INLINABLE fail #-}

    --
    -- Peek
    --

    -- | Lua operation with an additional failure mode that can stack errors
    -- from different contexts; errors are not based on exceptions).
    newtype Peek e a = Peek { forall e a. Peek e a -> LuaE e (Result a)
    runPeek :: LuaE e (Result a) }
      deriving ((forall a b. (a -> b) -> Peek e a -> Peek e b)
    -> (forall a b. a -> Peek e b -> Peek e a) -> Functor (Peek e)
    forall a b. a -> Peek e b -> Peek e a
    forall a b. (a -> b) -> Peek e a -> Peek e b
    forall e a b. a -> Peek e b -> Peek e a
    forall e a b. (a -> b) -> Peek e a -> Peek e b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall e a b. (a -> b) -> Peek e a -> Peek e b
    fmap :: forall a b. (a -> b) -> Peek e a -> Peek e b
    $c<$ :: forall e a b. a -> Peek e b -> Peek e a
    <$ :: forall a b. a -> Peek e b -> Peek e a
    Functor)

    -- | Converts a Peek action into a LuaE action, throwing an exception in
    -- case of a peek failure.
    forcePeek :: LuaError e => Peek e a -> LuaE e a
    forcePeek :: forall e a. LuaError e => Peek e a -> LuaE e a
    forcePeek = Result a -> LuaE e a
    forall e a. LuaError e => Result a -> LuaE e a
    force (Result a -> LuaE e a)
    -> (Peek e a -> LuaE e (Result a)) -> Peek e a -> LuaE e a
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek
    {-# INLINE forcePeek #-}

    -- | Fails the peek operation.
    failPeek :: forall a e. ByteString -> Peek e a
    failPeek :: forall a e. ByteString -> Peek e a
    failPeek = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a)
    -> (ByteString -> LuaE e (Result a)) -> ByteString -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result a -> LuaE e (Result a))
    -> (ByteString -> Result a) -> ByteString -> LuaE e (Result a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Result a
    forall a. ByteString -> Result a
    failure
    {-# INLINE failPeek #-}

    -- | Lifts a Lua operation into the Peek monad.
    liftLua :: LuaE e a -> Peek e a
    liftLua :: forall e a. LuaE e a -> Peek e a
    liftLua = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a)
    -> (LuaE e a -> LuaE e (Result a)) -> LuaE e a -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> Result a) -> LuaE e a -> LuaE e (Result a)
    forall a b. (a -> b) -> LuaE e a -> LuaE e b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> Result a
    forall a. a -> Result a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
    {-# INLINE liftLua #-}

    instance Applicative (Peek e) where
      pure :: forall a. a -> Peek e a
    pure = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a)
    -> (a -> LuaE e (Result a)) -> a -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result a -> LuaE e (Result a))
    -> (a -> Result a) -> a -> LuaE e (Result a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Result a
    forall a. a -> Result a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE pure #-}

      Peek LuaE e (Result (a -> b))
    f <*> :: forall a b. Peek e (a -> b) -> Peek e a -> Peek e b
    <*> Peek e a
    x = LuaE e (Result b) -> Peek e b
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result b) -> Peek e b) -> LuaE e (Result b) -> Peek e b
    forall a b. (a -> b) -> a -> b
    $! LuaE e (Result (a -> b))
    f LuaE e (Result (a -> b))
    -> (Result (a -> b) -> LuaE e (Result b)) -> LuaE e (Result b)
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
        Failure ByteString
    msg [Name]
    stack -> Result b -> LuaE e (Result b)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result b -> LuaE e (Result b)) -> Result b -> LuaE e (Result b)
    forall a b. (a -> b) -> a -> b
    $ ByteString -> [Name] -> Result b
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    msg [Name]
    stack
        Success a -> b
    f'        -> (a -> b) -> Result a -> Result b
    forall a b. (a -> b) -> Result a -> Result b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f' (Result a -> Result b) -> LuaE e (Result a) -> LuaE e (Result b)
    forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
    <$!> Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek Peek e a
    x
      {-# INLINEABLE (<*>) #-}

      Peek e a
    m *> :: forall a b. Peek e a -> Peek e b -> Peek e b
    *> Peek e b
    k = Peek e a
    m Peek e a -> (a -> Peek e b) -> Peek e b
    forall a b. Peek e a -> (a -> Peek e b) -> Peek e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Peek e b -> a -> Peek e b
    forall a b. a -> b -> a
    const Peek e b
    k
      {-# INLINE (*>) #-}

    instance Monad (Peek e) where
      Peek LuaE e (Result a)
    m >>= :: forall a b. Peek e a -> (a -> Peek e b) -> Peek e b
    >>= a -> Peek e b
    k = LuaE e (Result b) -> Peek e b
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result b) -> Peek e b) -> LuaE e (Result b) -> Peek e b
    forall a b. (a -> b) -> a -> b
    $
        LuaE e (Result a)
    m LuaE e (Result a)
    -> (Result a -> LuaE e (Result b)) -> LuaE e (Result b)
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
          Failure ByteString
    msg [Name]
    stack -> Result b -> LuaE e (Result b)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result b -> LuaE e (Result b)) -> Result b -> LuaE e (Result b)
    forall a b. (a -> b) -> a -> b
    $ ByteString -> [Name] -> Result b
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    msg [Name]
    stack
          Success a
    x         -> Peek e b -> LuaE e (Result b)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek (a -> Peek e b
    k a
    x)
      {-# INLINE (>>=) #-}

    instance Alternative (Peek e) where
      empty :: forall a. Peek e a
    empty = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a)
    -> (Result a -> LuaE e (Result a)) -> Result a -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result a -> Peek e a) -> Result a -> Peek e a
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Result a
    forall a. ByteString -> Result a
    failure ByteString
    "empty"
      {-# INLINE empty #-}

      Peek e a
    a <|> :: forall a. Peek e a -> Peek e a -> Peek e a
    <|> Peek e a
    b = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a) -> LuaE e (Result a) -> Peek e a
    forall a b. (a -> b) -> a -> b
    $ Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek Peek e a
    a LuaE e (Result a)
    -> (Result a -> LuaE e (Result a)) -> LuaE e (Result a)
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
        Success a
    ra -> Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> Result a
    forall a. a -> Result a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure a
    ra)
        Result a
    _          -> Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek Peek e a
    b
      {-# INLINE (<|>) #-}

    instance MonadPlus (Peek e)

    instance MonadFail (Peek e) where
      fail :: forall a. String -> Peek e a
    fail = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a)
    -> (String -> LuaE e (Result a)) -> String -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result a -> LuaE e (Result a))
    -> (String -> Result a) -> String -> LuaE e (Result a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Result a
    forall a. ByteString -> Result a
    failure (ByteString -> Result a)
    -> (String -> ByteString) -> String -> Result a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ByteString
    Utf8.fromString
      {-# INLINABLE fail #-}

    -- | Transform the result using the given function.
    withContext :: Name -> Peek e a -> Peek e a
    withContext :: forall e a. Name -> Peek e a -> Peek e a
    withContext Name
    ctx = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a)
    -> (Peek e a -> LuaE e (Result a)) -> Peek e a -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Result a -> Result a) -> LuaE e (Result a) -> LuaE e (Result a)
    forall a b. (a -> b) -> LuaE e a -> LuaE e b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Name -> Result a -> Result a
    forall a. Name -> Result a -> Result a
    addFailureContext Name
    ctx) (LuaE e (Result a) -> LuaE e (Result a))
    -> (Peek e a -> LuaE e (Result a)) -> Peek e a -> LuaE e (Result a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek
    {-# INLINABLE withContext #-}

    -- | Runs the peek action and Lua action in sequence, even if the peek
    -- action fails.
    lastly :: Peek e a -> LuaE e b -> Peek e a
    lastly :: forall e a b. Peek e a -> LuaE e b -> Peek e a
    lastly Peek e a
    p LuaE e b
    after = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a) -> LuaE e (Result a) -> Peek e a
    forall a b. (a -> b) -> a -> b
    $! Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek Peek e a
    p LuaE e (Result a) -> LuaE e b -> LuaE e (Result a)
    forall a b. LuaE e a -> LuaE e b -> LuaE e a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* LuaE e b
    after
    {-# INLINABLE lastly #-}

    -- | Runs the peek action, resetting the stack top afterwards. This can
    -- be used with peek actions that might otherwise leave elements on the
    -- stack in case of a failure.
    cleanup :: Peek e a -> Peek e a
    cleanup :: forall e a. Peek e a -> Peek e a
    cleanup Peek e a
    p = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a) -> LuaE e (Result a) -> Peek e a
    forall a b. (a -> b) -> a -> b
    $ do
      oldtop <- LuaE e StackIndex
    forall e. LuaE e StackIndex
    gettop
      result <- runPeek p
      settop oldtop
      return result
    {-# INLINABLE cleanup #-}

    -- | Returns 'True' iff the peek result is a Failure.
    isFailure :: Result a -> Bool
    isFailure :: forall a. Result a -> Bool
    isFailure Failure {} = Bool
    True
    isFailure Result a
    _          = Bool
    False

    -- | Combines the peek failure components into a reportable string.
    formatPeekFailure :: ByteString -> [Name] -> String
    formatPeekFailure :: ByteString -> [Name] -> String
    formatPeekFailure ByteString
    msg [Name]
    stack =
      String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    "\n\twhile " ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $
      (ByteString -> String) -> [ByteString] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map ByteString -> String
    Utf8.toString (ByteString
    msg ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : (Name -> ByteString) -> [Name] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map Name -> ByteString
    fromName ([Name] -> [Name]
    forall a. [a] -> [a]
    reverse [Name]
    stack))

    -- | Function to retrieve a value from Lua's stack.
    type Peeker e a = StackIndex -> Peek e a

    -- | Runs the peeker function.
    runPeeker :: Peeker e a -> StackIndex -> LuaE e (Result a)
    runPeeker :: forall e a. Peeker e a -> StackIndex -> LuaE e (Result a)
    runPeeker Peeker e a
    p = Peek e a -> LuaE e (Result a)
    forall e a. Peek e a -> LuaE e (Result a)
    runPeek (Peek e a -> LuaE e (Result a))
    -> Peeker e a -> StackIndex -> LuaE e (Result a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Peeker e a
    p

    -- | Create a peek failure record from an error message.
    failure :: ByteString -> Result a
    failure :: forall a. ByteString -> Result a
    failure ByteString
    msg = ByteString -> [Name] -> Result a
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    msg []

    -- | Add a message to the peek traceback stack.
    addFailureContext :: Name -> Result a -> Result a
    addFailureContext :: forall a. Name -> Result a -> Result a
    addFailureContext Name
    name = \case
      Failure ByteString
    msg [Name]
    stack -> ByteString -> [Name] -> Result a
    forall a. ByteString -> [Name] -> Result a
    Failure ByteString
    msg (Name
    name Name -> [Name] -> [Name]
    forall a. a -> [a] -> [a]
    : [Name]
    stack)
      Result a
    x -> Result a
    x
    {-# INLINABLE addFailureContext #-}

    -- | Add context information to the peek traceback stack.
    retrieving :: Name
               -> Peek e a
               -> Peek e a
    retrieving :: forall e a. Name -> Peek e a -> Peek e a
    retrieving = Name -> Peek e a -> Peek e a
    forall e a. Name -> Peek e a -> Peek e a
    withContext (Name -> Peek e a -> Peek e a)
    -> (Name -> Name) -> Name -> Peek e a -> Peek e a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name
    "retrieving " Name -> Name -> Name
    forall a. Semigroup a => a -> a -> a
    <>)
    {-# INLINE retrieving #-}

    -- | Force creation of an unwrapped result, throwing an exception if
    -- that's not possible.
    force :: LuaError e => Result a -> LuaE e a
    force :: forall e a. LuaError e => Result a -> LuaE e a
    force = \case
      Success a
    x -> a -> LuaE e a
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x
      Failure ByteString
    msg [Name]
    stack -> String -> LuaE e a
    forall e a. LuaError e => String -> LuaE e a
    failLua (String -> LuaE e a) -> String -> LuaE e a
    forall a b. (a -> b) -> a -> b
    $ ByteString -> [Name] -> String
    formatPeekFailure ByteString
    msg [Name]
    stack
    {-# INLINABLE force #-}

    -- | Converts a Result into an Either, where @Left@ holds the reportable
    -- string in case of an failure.
    resultToEither :: Result a -> Either String a
    resultToEither :: forall a. Result a -> Either String a
    resultToEither = \case
      Failure ByteString
    msg [Name]
    stack -> String -> Either String a
    forall a b. a -> Either a b
    Left (String -> Either String a) -> String -> Either String a
    forall a b. (a -> b) -> a -> b
    $ ByteString -> [Name] -> String
    formatPeekFailure ByteString
    msg [Name]
    stack
      Success a
    x         -> a -> Either String a
    forall a b. b -> Either a b
    Right a
    x

    -- | Converts an old peek funtion to a 'Peeker'.
    toPeeker :: LuaError e
             => (StackIndex -> LuaE e a)
             -> Peeker e a
    toPeeker :: forall e a. LuaError e => (StackIndex -> LuaE e a) -> Peeker e a
    toPeeker StackIndex -> LuaE e a
    op StackIndex
    idx = LuaE e (Result a) -> Peek e a
    forall e a. LuaE e (Result a) -> Peek e a
    Peek (LuaE e (Result a) -> Peek e a) -> LuaE e (Result a) -> Peek e a
    forall a b. (a -> b) -> a -> b
    $ LuaE e a -> LuaE e (Either e a)
    forall e a. Exception e => LuaE e a -> LuaE e (Either e a)
    try (StackIndex -> LuaE e a
    op StackIndex
    idx) LuaE e (Either e a)
    -> (Either e a -> LuaE e (Result a)) -> LuaE e (Result a)
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
      Left e
    err  -> Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result a -> LuaE e (Result a)) -> Result a -> LuaE e (Result a)
    forall a b. (a -> b) -> a -> b
    $! ByteString -> Result a
    forall a. ByteString -> Result a
    failure (ByteString -> Result a) -> ByteString -> Result a
    forall a b. (a -> b) -> a -> b
    $ String -> ByteString
    Utf8.fromString (e -> String
    forall a. Show a => a -> String
    show e
    err)
      Right a
    res -> Result a -> LuaE e (Result a)
    forall a. a -> LuaE e a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result a -> LuaE e (Result a)) -> Result a -> LuaE e (Result a)
    forall a b. (a -> b) -> a -> b
    $! a -> Result a
    forall a. a -> Result a
    Success a
    res