packages feed

hslua-classes 2.0.0 → 2.1.0

raw patch · 16 files changed

+169/−252 lines, 16 filesdep ~hslua-coredep ~hslua-marshallingdep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hslua-core, hslua-marshalling, text

API changes (from Hackage documentation)

- HsLua.Class.Exposable: instance (HsLua.Class.Peekable.PeekError e, HsLua.Class.Pushable.Pushable a) => HsLua.Class.Exposable.Exposable e (HsLua.Core.Types.LuaE e a)
- HsLua.Class.Exposable: instance HsLua.Class.Peekable.PeekError e => HsLua.Class.Exposable.Exposable e (HsLua.Core.Types.HaskellFunction e)
- HsLua.Class.Invokable: instance (HsLua.Class.Peekable.PeekError e, HsLua.Class.Peekable.Peekable a) => HsLua.Class.Invokable.Invokable e (HsLua.Core.Types.LuaE e a)
- HsLua.Class.Invokable: instance (HsLua.Class.Pushable.Pushable a, HsLua.Class.Peekable.PeekError e, HsLua.Class.Invokable.Invokable e b) => HsLua.Class.Invokable.Invokable e (a -> b)
- HsLua.Class.Peekable: class LuaError e => PeekError e
- HsLua.Class.Peekable: inContext :: forall e a. PeekError e => String -> LuaE e a -> LuaE e a
- HsLua.Class.Peekable: instance HsLua.Class.Peekable.PeekError HsLua.Core.Error.Exception
- HsLua.Class.Peekable: messageFromException :: PeekError e => e -> String
- HsLua.Class.Peekable: peekKeyValuePairs :: (Peekable a, Peekable b, PeekError e) => StackIndex -> LuaE e [(a, b)]
- HsLua.Class.Peekable: peekList :: (PeekError e, Peekable a) => StackIndex -> LuaE e [a]
- HsLua.Class.Peekable: reportValueOnFailure :: forall e a. PeekError e => ByteString -> (StackIndex -> LuaE e (Maybe a)) -> StackIndex -> LuaE e a
- HsLua.Classes: peek :: (Peekable a, PeekError e) => StackIndex -> LuaE e a
- HsLua.Classes: peekKeyValuePairs :: (Peekable a, Peekable b, PeekError e) => StackIndex -> LuaE e [(a, b)]
- HsLua.Classes: peekList :: (PeekError e, Peekable a) => StackIndex -> LuaE e [a]
+ HsLua.Class.Exposable: instance (HsLua.Core.Error.LuaError e, HsLua.Class.Pushable.Pushable a) => HsLua.Class.Exposable.Exposable e (HsLua.Core.Types.LuaE e a)
+ HsLua.Class.Exposable: instance (HsLua.Core.Error.LuaError e, HsLua.Class.Pushable.Pushable a) => HsLua.Class.Exposable.Exposable e (HsLua.Marshalling.Peek.Peek e a)
+ HsLua.Class.Exposable: instance HsLua.Core.Error.LuaError e => HsLua.Class.Exposable.Exposable e (HsLua.Core.Types.HaskellFunction e)
+ HsLua.Class.Exposable: pushAsHaskellFunction :: forall e a. Exposable e a => a -> LuaE e ()
+ HsLua.Class.Invokable: instance (HsLua.Class.Pushable.Pushable a, HsLua.Class.Invokable.Invokable b) => HsLua.Class.Invokable.Invokable (a -> b)
+ HsLua.Class.Invokable: instance (HsLua.Core.Error.LuaError e, HsLua.Class.Peekable.Peekable a) => HsLua.Class.Invokable.Invokable (HsLua.Core.Types.LuaE e a)
+ HsLua.Class.Peekable: safepeek :: (Peekable a, LuaError e) => Peeker e a
+ HsLua.Classes: safepeek :: (Peekable a, LuaError e) => Peeker e a
- HsLua.Class.Exposable: class PeekError e => Exposable e a
+ HsLua.Class.Exposable: class LuaError e => Exposable e a
- HsLua.Class.Exposable: partialApply :: Exposable e a => StackIndex -> a -> LuaE e NumResults
+ HsLua.Class.Exposable: partialApply :: Exposable e a => StackIndex -> a -> Peek e NumResults
- HsLua.Class.Invokable: addArg :: Invokable e a => Name -> LuaE e () -> NumArgs -> a
+ HsLua.Class.Invokable: addArg :: Invokable a => Name -> (forall e. LuaError e => LuaE e ()) -> NumArgs -> a
- HsLua.Class.Invokable: class PeekError e => Invokable e a
+ HsLua.Class.Invokable: class Invokable a
- HsLua.Class.Invokable: invoke :: forall e a. Invokable e a => Name -> a
+ HsLua.Class.Invokable: invoke :: Invokable a => Name -> a
- HsLua.Class.Peekable: peek :: (Peekable a, PeekError e) => StackIndex -> LuaE e a
+ HsLua.Class.Peekable: peek :: forall a e. (LuaError e, Peekable a) => StackIndex -> LuaE e a
- HsLua.Class.Util: peekEither :: (PeekError e, Peekable a) => StackIndex -> LuaE e (Either e a)
+ HsLua.Class.Util: peekEither :: (LuaError e, Peekable a) => StackIndex -> LuaE e (Either e a)
- HsLua.Class.Util: popValue :: (PeekError e, Peekable a) => LuaE e a
+ HsLua.Class.Util: popValue :: (LuaError e, Peekable a) => LuaE e a
- HsLua.Class.Util: raiseError :: (PeekError e, Pushable a) => a -> LuaE e NumResults
+ HsLua.Class.Util: raiseError :: (LuaError e, Pushable a) => a -> LuaE e NumResults
- HsLua.Classes: class PeekError e => Exposable e a
+ HsLua.Classes: class LuaError e => Exposable e a
- HsLua.Classes: invoke :: forall e a. Invokable e a => Name -> a
+ HsLua.Classes: invoke :: Invokable a => Name -> a
- HsLua.Classes: partialApply :: Exposable e a => StackIndex -> a -> LuaE e NumResults
+ HsLua.Classes: partialApply :: Exposable e a => StackIndex -> a -> Peek e NumResults
- HsLua.Classes: peekEither :: (PeekError e, Peekable a) => StackIndex -> LuaE e (Either e a)
+ HsLua.Classes: peekEither :: (LuaError e, Peekable a) => StackIndex -> LuaE e (Either e a)
- HsLua.Classes: popValue :: (PeekError e, Peekable a) => LuaE e a
+ HsLua.Classes: popValue :: (LuaError e, Peekable a) => LuaE e a
- HsLua.Classes: raiseError :: (PeekError e, Pushable a) => a -> LuaE e NumResults
+ HsLua.Classes: raiseError :: (LuaError e, Pushable a) => a -> LuaE e NumResults

Files

CHANGELOG.md view
@@ -1,12 +1,46 @@ # Changelog -`hslua-classes` uses [PVP Versioning][1].+`hslua-classes` uses [PVP Versioning][]. -## hslua-classes 2.0.0+## hslua-classes-2.1.0 -Release pending.+Released 29-01-2022. -- Initially created. Contains modules previously found in the-  `Foreign.Lua.Types` hierarchy from `hslua-1.3`.+-   Updated to hslua-core 2.1 and hslua-marshalling 2.1. -[1]: https://pvp.haskell.org+-   The Peekable class has been remodeled:++    -   Peekable now contains `safepeek`, which is a `Peeker`+        function for the type.++    -   `peek` is no longer part of Peekable, but a normal+        function defined as `forcePeek . safepeek`.++-   HsLua.Class no longer exports `peekList` and+    `peekKeyValuePairs`. Use the functions from HsLua.Marshalling+    instead.++-   The Exposable class is changed to use the `Peek` monad+    instead of `LuaE`, thereby unifying the way errors are+    reported in HsLua.++-   PeekError has been removed; it is now sufficient for+    exception types used with Peekable, Exposable, and Invokable+    to be instances of LuaError.++-   The Invokable type class now has a single parameter. This+    removes the need for the AllowAmbiguousTypes extension and+    makes using `invoke` much more convenient, as the proper error+    type can now be inferred automatically.++-   Added function `pushAsHaskellFunction` to make it even easier+    to use Haskell functions in Lua.++## hslua-classes-2.0.0++Released 2021-10-21.++-   Initially created. Contains modules previously found in the+    `Foreign.Lua.Types` hierarchy from `hslua-1.3`.++  [PVP Versioning]: https://pvp.haskell.org
LICENSE view
@@ -1,7 +1,7 @@ Copyright © 1994-2020 Lua.org, PUC-Rio. Copyright © 2007-2012 Gracjan Polak Copyright © 2012-2015 Ömer Sinan Ağacan-Copyright © 2016-2021 Albert Krewinkel+Copyright © 2016-2022 Albert Krewinkel  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
hslua-classes.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                hslua-classes-version:             2.0.0+version:             2.1.0 synopsis:            Type classes for HsLua description:         Type classes for convenient marshalling and calling of                      Lua functions.@@ -12,7 +12,7 @@ maintainer:          albert+hslua@zeitkraut.de copyright:           © 2007–2012 Gracjan Polak;                      © 2012–2016 Ömer Sinan Ağacan;-                     © 2017-2021 Albert Krewinkel+                     © 2017-2022 Albert Krewinkel category:            Foreign build-type:          Simple extra-source-files:  README.md@@ -22,8 +22,9 @@                    , GHC == 8.4.4                    , GHC == 8.6.5                    , GHC == 8.8.4-                   , GHC == 8.10.4+                   , GHC == 8.10.7                    , GHC == 9.0.1+                   , GHC == 9.2.1  source-repository head   type:                git@@ -36,9 +37,9 @@                      , bytestring        >= 0.10.2 && < 0.12                      , containers        >= 0.5.9  && < 0.7                      , exceptions        >= 0.8    && < 0.11-                     , hslua-core        >= 2.0    && < 2.1-                     , hslua-marshalling >= 2.0    && < 2.1-                     , text              >= 1.0    && < 1.3+                     , hslua-core        >= 2.1    && < 2.2+                     , hslua-marshalling >= 2.1    && < 2.2+                     , text              >= 1.2    && < 2.1   ghc-options:         -Wall                        -Wincomplete-record-updates                        -Wnoncanonical-monad-instances
src/HsLua/Class/Exposable.hs view
@@ -6,75 +6,82 @@ Module      : HsLua.Class.Exposable Copyright   : © 2007–2012 Gracjan Polak,                 2012–2016 Ömer Sinan Ağacan,-                2017-2021 Albert Krewinkel+                2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>-Stability   : beta-Portability : FlexibleInstances, ForeignFunctionInterface, ScopedTypeVariables  Call Haskell functions from Lua. -} module HsLua.Class.Exposable   ( Exposable (..)   , toHaskellFunction+  , pushAsHaskellFunction   , registerHaskellFunction   ) where +import Data.String (fromString) import HsLua.Core as Lua-import HsLua.Class.Peekable (Peekable (peek), PeekError (..), inContext)+import HsLua.Marshalling (Peek, forcePeek, liftLua, retrieving, withContext)+import HsLua.Class.Peekable (Peekable (safepeek)) import HsLua.Class.Pushable (Pushable (push))  -- | Operations and functions that can be pushed to the Lua stack. This -- is a helper function not intended to be used directly. Use the -- @'toHaskellFunction'@ wrapper instead.-class PeekError e => Exposable e a where+class LuaError e => Exposable e a where   -- | Helper function, called by @'toHaskellFunction'@. Should do a   -- partial application of the argument at the given index to the   -- underlying function. Recurses if necessary, causing further partial   -- applications until the operation is a easily exposable to Lua.-  partialApply :: StackIndex -> a -> LuaE e NumResults+  partialApply :: StackIndex -> a -> Peek e NumResults -instance {-# OVERLAPPING #-} PeekError e =>+instance {-# OVERLAPPING #-} LuaError e =>          Exposable e (HaskellFunction e) where-  partialApply _ = id+  partialApply _ = liftLua -instance (PeekError e, Pushable a) => Exposable e (LuaE e a) where-  partialApply _narg x = 1 <$ (x >>= push)+instance (LuaError e, Pushable a) => Exposable e (LuaE e a) where+  partialApply _narg x = 1 <$ liftLua (x >>= push) +instance (LuaError e, Pushable a) => Exposable e (Peek e a) where+  partialApply _narg x = 1 <$ (x >>= liftLua . push)+ instance (Peekable a, Exposable e b) => Exposable e (a -> b) where   partialApply narg f = getArg >>= partialApply (narg + 1) . f     where-      getArg = inContext errorPrefix (peek narg)-      errorPrefix = "could not read argument " ++-                    show (fromStackIndex narg) ++ ":"+      getArg = retrieving (fromString errorPrefix) (safepeek narg)+      errorPrefix = "argument " ++ show (fromStackIndex narg)  -- | Convert a Haskell function to a function type directly exposable to -- Lua. Any Haskell function can be converted provided that: -- --   * all arguments are instances of @'Peekable'@---   * return type is @Lua a@, where @a@ is an instance of+--   * return type is @LuaE e a@, where @a@ is an instance of --     @'Pushable'@ ----- Any @'Lua.Exception'@ will be converted to a string and returned--- as Lua error.+-- Any exception of type @e@ will be caught. ----- /Important/: this does __not__ catch exceptions other than--- @'Lua.Exception'@; exception handling must be done by the converted--- Haskell function. Failure to do so will cause the program to crash.+-- /Important/: this does __not__ catch exceptions other than @e@;+-- exception handling must be done by the Haskell function. Failure to+-- do so will cause the program to crash. -- -- E.g., the following code could be used to handle an Exception -- of type FooException, if that type is an instance of -- 'Control.Monad.Catch.MonadCatch' and 'Pushable': -- -- > toHaskellFunction (myFun `catchM` (\e -> raiseError (e :: FooException)))--- toHaskellFunction :: forall e a. Exposable e a => a -> HaskellFunction e-toHaskellFunction a = do-  inContext "Error during function call:" $ partialApply 1 a+toHaskellFunction a = forcePeek $ do+  withContext "executing function call" $ partialApply 1 a +-- | Pushes the given value as a function to the Lua stack.+--+-- See 'toHaskellFunction' for details.+pushAsHaskellFunction :: forall e a. Exposable e a => a -> LuaE e ()+pushAsHaskellFunction = pushHaskellFunction . toHaskellFunction+ -- | Imports a Haskell function and registers it at global name. registerHaskellFunction :: Exposable e a                         => Name -> a -> LuaE e () registerHaskellFunction n f = do-  pushHaskellFunction $ toHaskellFunction f+  pushAsHaskellFunction f   setglobal n
src/HsLua/Class/Invokable.hs view
@@ -1,14 +1,10 @@-{-# LANGUAGE AllowAmbiguousTypes   #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE RankNTypes            #-} {-| Module      : HsLua.Class.Invokable Copyright   : © 2007–2012 Gracjan Polak,                 2012–2016 Ömer Sinan Ağacan,-                2017-2021 Albert Krewinkel+                2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta@@ -28,22 +24,22 @@ import HsLua.Class.Util (popValue)  -- | Helper class used to make Lua functions useable from Haskell.-class PeekError e => Invokable e a where-  addArg :: Name -> LuaE e () -> NumArgs -> a+class Invokable a where+  addArg :: Name -> (forall e. LuaError e => LuaE e ()) -> NumArgs -> a -instance (PeekError e, Peekable a) => Invokable e (LuaE e a) where+instance (LuaError e, Peekable a) => Invokable (LuaE e a) where   addArg fnName pushArgs nargs = do     _ <- dostring $ "return " `append` Lua.fromName fnName     pushArgs     call nargs 1     popValue -instance (Pushable a, PeekError e, Invokable e b) => Invokable e (a -> b) where+instance (Pushable a, Invokable b) => Invokable (a -> b) where   addArg fnName pushArgs nargs x =     addArg fnName (pushArgs *> push x) (nargs + 1)  -- | Invoke a Lua function. Use as: -- -- > v <- invoke "proc" "abc" (1::Int) (5.0::Double)-invoke :: forall e a. Invokable e a => Name -> a-invoke fname = addArg @e fname (return ()) 0+invoke :: Invokable a => Name -> a+invoke fname = addArg fname (return ()) 0
src/HsLua/Class/Peekable.hs view
@@ -1,12 +1,11 @@ {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications    #-} {-| Module      : HsLua.Class.Peekable Copyright   : © 2007–2012 Gracjan Polak;               © 2012–2016 Ömer Sinan Ağacan;-              © 2017-2021 Albert Krewinkel+              © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta@@ -16,174 +15,83 @@ -} module HsLua.Class.Peekable   ( Peekable (..)-  , PeekError (..)-  , peekKeyValuePairs-  , peekList-  , reportValueOnFailure-  , inContext+  , peek   ) where -import Control.Monad ((>=>))-import Data.ByteString (ByteString)-import Data.Map (Map, fromList)+import Data.Map (Map) import Data.Set (Set)+import Data.Text (Text) import HsLua.Core as Lua-import HsLua.Marshalling.Peek (runPeeker)+import HsLua.Marshalling import Foreign.Ptr (Ptr) -import qualified Control.Monad.Catch as Catch-import qualified Data.Set as Set-import qualified Data.Text as T+import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL-import qualified HsLua.Core.Unsafe as Unsafe-import qualified HsLua.Marshalling as Peek---- | Use @test@ to check whether the value at stack index @n@ has the--- correct type and use @peekfn@ to convert it to a haskell value if--- possible. Throws and exception if the test failes with the expected--- type name as part of the message.-typeChecked :: forall e a. LuaError e-            => ByteString                  -- ^ expected type-            -> (StackIndex -> LuaE e Bool) -- ^ pre-condition Checker-            -> (StackIndex -> LuaE e a)    -- ^ retrieval function-            -> StackIndex -> LuaE e a-typeChecked expectedType test peekfn idx = do-  v <- test idx-  if v-    then peekfn idx-    else throwTypeMismatchError expectedType idx---- | Report the expected and actual type of the value under the given--- index if conversion failed.-reportValueOnFailure :: forall e a. PeekError e-                     => ByteString-                     -> (StackIndex -> LuaE e (Maybe a))-                     -> StackIndex -> LuaE e a-reportValueOnFailure expected peekMb idx = do-  res <- peekMb idx-  case res of-    (Just x) -> return x-    Nothing  -> throwTypeMismatchError expected idx+import qualified HsLua.Marshalling.Peekers as Peekers  -- | A value that can be read from the Lua stack. class Peekable a where-  -- | Check if at index @n@ there is a convertible Lua value and if so return-  -- it.  Throws a @'Lua.Exception'@ otherwise.-  peek :: PeekError e => StackIndex -> LuaE e a+  -- | Function that retrieves a value from the Lua stack.+  safepeek :: LuaError e => Peeker e a +-- | Retrieves a 'Peekable' value from the stack. Throws an exception of+-- type @e@ if the given stack index does not a suitable value.+peek :: forall a e. (LuaError e, Peekable a) => StackIndex -> LuaE e a+peek = forcePeek . safepeek+ instance Peekable () where-  peek = reportValueOnFailure "nil" $ \idx -> do-    isNil <- isnil idx-    return (if isNil then Just () else Nothing)+  safepeek = peekNil  instance Peekable Lua.Integer where-  peek = reportValueOnFailure "integer" tointeger+  safepeek = reportValueOnFailure "integer" tointeger  instance Peekable Lua.Number where-  peek = reportValueOnFailure "number" tonumber+  safepeek = reportValueOnFailure "number" tonumber -instance Peekable ByteString where-  peek = runPeeker Peek.peekByteString >=> Peek.force+instance Peekable B.ByteString where+  safepeek = peekByteString  instance Peekable Bool where-  peek = toboolean+  safepeek = peekBool  instance Peekable CFunction where-  peek = reportValueOnFailure "C function" tocfunction+  safepeek = reportValueOnFailure "C function" tocfunction  instance Peekable (Ptr a) where-  peek = reportValueOnFailure "userdata" touserdata+  safepeek = reportValueOnFailure "userdata" touserdata  instance Peekable Lua.State where-  peek = reportValueOnFailure "Lua state (i.e., a thread)" tothread+  safepeek = reportValueOnFailure "Lua state (i.e., a thread)" tothread -instance Peekable T.Text where-  peek = runPeeker Peek.peekText >=> Peek.force+instance Peekable Text where+  safepeek = peekText  instance Peekable BL.ByteString where-  peek = runPeeker Peek.peekLazyByteString >=> Peek.force+  safepeek = peekLazyByteString  instance Peekable Prelude.Integer where-  peek = runPeeker Peek.peekIntegral >=> Peek.force+  safepeek = peekIntegral  instance Peekable Int where-  peek = runPeeker Peek.peekIntegral >=> Peek.force+  safepeek = peekIntegral  instance Peekable Float where-  peek = runPeeker Peek.peekRealFloat >=> Peek.force+  safepeek = peekRealFloat  instance Peekable Double where-  peek = runPeeker Peek.peekRealFloat >=> Peek.force+  safepeek = peekRealFloat  instance {-# OVERLAPS #-} Peekable [Char] where-  peek = runPeeker Peek.peekString >=> Peek.force+  safepeek = peekString  instance Peekable a => Peekable [a] where-  peek = peekList+  safepeek = peekList safepeek  instance (Ord a, Peekable a, Peekable b) => Peekable (Map a b) where-  peek = fmap fromList . peekKeyValuePairs+  safepeek = peekMap safepeek safepeek  instance (Ord a, Peekable a) => Peekable (Set a) where-  peek = -- All keys with non-nil values are in the set-    fmap (Set.fromList . map fst . filter snd) . peekKeyValuePairs---- | Read a table into a list-peekList :: (PeekError e, Peekable a) => StackIndex -> LuaE e [a]-peekList = typeChecked "table" istable $ \idx -> do-  let elementsAt [] = return []-      elementsAt (i : is) = do-        x <- (rawgeti idx i *> peek top) `Catch.finally` pop 1-        (x:) <$> elementsAt is-  listLength <- fromIntegral <$> rawlen idx-  inContext "Could not read list:" (elementsAt [1..listLength])---- | Read a table into a list of pairs.-peekKeyValuePairs :: (Peekable a, Peekable b, PeekError e)-                  => StackIndex -> LuaE e [(a, b)]-peekKeyValuePairs = typeChecked "table" istable $ \idx -> do-  let remainingPairs = do-        res <- nextPair (if idx < 0 then idx - 1 else idx)-        case res of-          Nothing -> [] <$ return ()-          Just a  -> (a:) <$> remainingPairs-  pushnil-  remainingPairs-    -- ensure the remaining key is removed from the stack on exception-    `Catch.onException` pop 1---- | Get the next key-value pair from a table. Assumes the last key to--- be on the top of the stack and the table at the given index @idx@.-nextPair :: (PeekError e, Peekable a, Peekable b)-         => StackIndex -> LuaE e (Maybe (a, b))-nextPair idx = do-  hasNext <- Unsafe.next idx-  if hasNext-    then let pair = (,) <$> inContext "Could not read key of key-value pair:"-                                      (peek (nth 2))-                        <*> inContext "Could not read value of key-value pair:"-                                      (peek (nth 1))-         in Just <$> pair `Catch.finally` pop 1-            -- removes the value, keeps the key-    else return Nothing---- | Specify a name for the context in which a computation is run. The--- name is added to the error message in case of an exception.-inContext :: forall e a. PeekError e-          => String -> LuaE e a -> LuaE e a-inContext ctx op = try op >>= \case-  Right x  -> return x-  Left (err :: e) -> Catch.throwM $-    luaException @e (ctx ++ "\n\t" ++ messageFromException err)---- | Exceptions that are to be used with 'peek' and similar functions--- must be instances of this class. It ensures that error can be amended--- with the context in which they happened.-class LuaError e => PeekError e where-  messageFromException :: e -> String--instance PeekError Lua.Exception where-  messageFromException = Lua.exceptionMessage+  safepeek = peekSet safepeek  -- -- Tuples@@ -193,21 +101,19 @@   (Peekable a, Peekable b) =>   Peekable (a, b)  where-  peek = typeChecked "table" istable $ \idx ->-    (,) <$> nthValue idx 1 <*> nthValue idx 2+  safepeek = peekPair safepeek safepeek  instance {-# OVERLAPPABLE #-}   (Peekable a, Peekable b, Peekable c) =>   Peekable (a, b, c)  where-  peek = typeChecked "table" istable $ \idx ->-    (,,) <$> nthValue idx 1 <*> nthValue idx 2 <*> nthValue idx 3+  safepeek = peekTriple safepeek safepeek safepeek  instance {-# OVERLAPPABLE #-}   (Peekable a, Peekable b, Peekable c, Peekable d) =>   Peekable (a, b, c, d)  where-  peek = typeChecked "table" istable $ \idx ->+  safepeek = typeChecked "table" istable $ \idx ->     (,,,) <$> nthValue idx 1 <*> nthValue idx 2 <*> nthValue idx 3           <*> nthValue idx 4 @@ -215,7 +121,7 @@   (Peekable a, Peekable b, Peekable c, Peekable d, Peekable e) =>   Peekable (a, b, c, d, e)  where-  peek = typeChecked "table" istable $ \idx ->+  safepeek = typeChecked "table" istable $ \idx ->     (,,,,) <$> nthValue idx 1 <*> nthValue idx 2 <*> nthValue idx 3            <*> nthValue idx 4 <*> nthValue idx 5 @@ -223,7 +129,7 @@   (Peekable a, Peekable b, Peekable c, Peekable d, Peekable e, Peekable f) =>   Peekable (a, b, c, d, e, f)  where-  peek = typeChecked "table" istable $ \idx ->+  safepeek = typeChecked "table" istable $ \idx ->     (,,,,,) <$> nthValue idx 1 <*> nthValue idx 2 <*> nthValue idx 3             <*> nthValue idx 4 <*> nthValue idx 5 <*> nthValue idx 6 @@ -233,7 +139,7 @@    Peekable e, Peekable f, Peekable g) =>   Peekable (a, b, c, d, e, f, g)  where-  peek = typeChecked "table" istable $ \idx ->+  safepeek = typeChecked "table" istable $ \idx ->     (,,,,,,) <$> nthValue idx 1 <*> nthValue idx 2 <*> nthValue idx 3              <*> nthValue idx 4 <*> nthValue idx 5 <*> nthValue idx 6              <*> nthValue idx 7@@ -243,14 +149,12 @@    Peekable e, Peekable f, Peekable g, Peekable h) =>   Peekable (a, b, c, d, e, f, g, h)  where-  peek = typeChecked "table" istable $ \idx ->+  safepeek = typeChecked "table" istable $ \idx ->     (,,,,,,,) <$> nthValue idx 1 <*> nthValue idx 2 <*> nthValue idx 3               <*> nthValue idx 4 <*> nthValue idx 5 <*> nthValue idx 6               <*> nthValue idx 7 <*> nthValue idx 8  -- | Helper function to get the nth table value-nthValue :: (PeekError e, Peekable a)-         => StackIndex -> Lua.Integer -> LuaE e a-nthValue idx n = do-  rawgeti idx n-  peek top `Catch.finally` pop 1+nthValue :: (LuaError e, Peekable a)+         => StackIndex -> Lua.Integer -> Peek e a+nthValue idx n = Peekers.peekIndexRaw n safepeek idx
src/HsLua/Class/Pushable.hs view
@@ -4,7 +4,7 @@ Module      : HsLua.Class.Pushable Copyright   : © 2007–2012 Gracjan Polak;               © 2012–2016 Ömer Sinan Ağacan;-              © 2017-2021 Albert Krewinkel+              © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta
src/HsLua/Class/Util.hs view
@@ -3,7 +3,7 @@ Module      : HsLua.Class.Util Copyright   : © 2007–2012 Gracjan Polak;               © 2012–2016 Ömer Sinan Ağacan;-              © 2017-2021 Albert Krewinkel+              © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta@@ -19,15 +19,16 @@   , popValue   ) where -import HsLua.Core (LuaE, NumResults, StackIndex, top)-import HsLua.Class.Peekable (Peekable (peek), PeekError)+import Control.Applicative ((<|>))+import HsLua.Core (LuaE, LuaError, NumResults, StackIndex, top)+import HsLua.Class.Peekable (Peekable (safepeek), peek) import HsLua.Class.Pushable (Pushable (push)) -import qualified Control.Monad.Catch as Catch import qualified HsLua.Core as Lua+import qualified HsLua.Marshalling as Lua  -- | Raise a Lua error, using the given value as the error object.-raiseError :: (PeekError e, Pushable a) => a -> LuaE e NumResults+raiseError :: (LuaError e, Pushable a) => a -> LuaE e NumResults raiseError e = do   push e   Lua.error@@ -40,11 +41,8 @@ newtype Optional a = Optional { fromOptional :: Maybe a }  instance Peekable a => Peekable (Optional a) where-  peek idx = do-    noValue <- Lua.isnoneornil idx-    if noValue-      then return $ Optional Nothing-      else Optional . Just <$> peek idx+  safepeek idx = (Optional Nothing <$ Lua.peekNoneOrNil idx)+             <|> (Optional . Just <$> safepeek idx)  instance Pushable a => Pushable (Optional a) where   push (Optional Nothing)  = Lua.pushnil@@ -57,12 +55,12 @@  -- | Try to convert the value at the given stack index to a Haskell value. -- Returns 'Left' with the error on failure.-peekEither :: (PeekError e, Peekable a)+peekEither :: (LuaError e, Peekable a)            => StackIndex -> LuaE e (Either e a) peekEither = Lua.try . peek  -- | Get, then pop the value at the top of the stack. The pop operation is -- executed even if the retrieval operation failed.-popValue :: (PeekError e, Peekable a) => LuaE e a-popValue = peek top `Catch.finally` Lua.pop 1+popValue :: (LuaError e, Peekable a) => LuaE e a+popValue = Lua.forcePeek $ safepeek top `Lua.lastly` Lua.pop 1 {-# INLINABLE popValue #-}
src/HsLua/Classes.hs view
@@ -2,7 +2,7 @@ Module      : HsLua.Classes Copyright   : © 2007–2012 Gracjan Polak;               © 2012–2016 Ömer Sinan Ağacan;-              © 2017-2021 Albert Krewinkel+              © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta@@ -15,8 +15,6 @@   ( -- * Receiving values from Lua stack (Lua → Haskell)     Peekable (..)   , peekEither-  , peekList-  , peekKeyValuePairs     -- * Pushing values to Lua stack (Haskell → Lua)   , Pushable (..)   , pushList
test/HsLua/Class/ExposableTests.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE TypeApplications #-} {-| Module      : HsLua.Class.ExposableTests-Copyright   : © 2017-2021 Albert Krewinkel+Copyright   : © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> @@ -34,7 +34,7 @@             i1 <- Lua.peek (-1)             i2 <- Lua.peek (-2)             return (i1 + i2)-      Lua.registerHaskellFunction "add" $ toHaskellFunction @Lua.Exception add+      Lua.registerHaskellFunction "add" add       Lua.loadstring "return add(23, 5)" *> Lua.call 0 1       Lua.peek Lua.top <* Lua.pop 1 @@ -45,16 +45,16 @@       Lua.peek (-1) <* Lua.pop 1    , "argument type errors are propagated" =:-     ("Error during function call:\n\tcould not read argument 2:\n\t"-      ++ "integer expected, got boolean") `shouldBeErrorMessageOf` do+     ("integer expected, got boolean" +++      "\n\twhile retrieving argument 2" +++      "\n\twhile executing function call") `shouldBeErrorMessageOf` do           Lua.registerHaskellFunction "integerOp" integerOperation           pushLuaExpr "integerOp(23, true)"    , "Error in Haskell function is converted into Lua error" =:-    (False, "Error during function call:\n\tfoo") `shouldBeResultOf` do+    (False, "foo") `shouldBeResultOf` do       Lua.openlibs-      Lua.pushHaskellFunction $-        toHaskellFunction (Lua.failLua "foo" :: Lua ())+      Lua.pushAsHaskellFunction (Lua.failLua "foo" :: Lua ())       Lua.setglobal "throw_foo"       Lua.loadstring "return pcall(throw_foo)" *> Lua.call 0 2       (,) <$> Lua.peek (Lua.nth 2) <*> Lua.peek @String (Lua.nth 1)
test/HsLua/Class/InvokableTests.hs view
@@ -1,8 +1,7 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeApplications #-} {-| Module      : HsLua.Class.InvokableTests-Copyright   : © 2017-2021 Albert Krewinkel+Copyright   : © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> @@ -24,25 +23,25 @@   [ "test equality within lua" =:     True `shouldBeResultOf` do       openlibs-      invoke @Lua.Exception "rawequal" (5 :: Lua.Integer) (5.0 :: Lua.Number)+      invoke "rawequal" (5 :: Lua.Integer) (5.0 :: Lua.Number)    , "failing lua function call" =:     "foo" `shouldBeErrorMessageOf` do       openlibs-      invoke @Lua.Exception "assert" False (Char8.pack "foo") :: Lua Bool+      invoke "assert" False (Char8.pack "foo") :: Lua Bool    , "pack table via lua procedure" =:     (True, 23 :: Lua.Integer, "moin" :: ByteString) `shouldBeResultOf` do       openlibs-      invoke @Lua.Exception "table.pack" True (23 :: Lua.Integer) (Char8.pack "moin")+      invoke "table.pack" True (23 :: Lua.Integer) (Char8.pack "moin")    , "failing lua procedure call" =:     "foo" `shouldBeErrorMessageOf` do       openlibs-      invoke @Lua.Exception "error" (Char8.pack "foo") :: Lua ()+      invoke "error" (Char8.pack "foo") :: Lua ()    , "Error when Lua-to-Haskell result conversion fails" =:     "string expected, got boolean" `shouldBeErrorMessageOf` do       openlibs-      invoke @Lua.Exception "rawequal" (Char8.pack "a") () :: Lua String+      invoke "rawequal" (Char8.pack "a") () :: Lua String   ]
test/HsLua/Class/PeekableTests.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE TypeApplications #-} {-| Module      :  HsLua.Class.PeekableTests-Copyright   :  © 2017-2021 Albert Krewinkel+Copyright   :  © 2017-2022 Albert Krewinkel License     :  MIT  Maintainer  :  Albert Krewinkel <tarleb+hslua@zeitkraut.de>@@ -20,8 +20,6 @@                        , shouldBeErrorMessageOf ) import Test.Tasty (TestTree, testGroup) -import qualified Data.Set as Set- -- | Specifications for Attributes parsing functions. tests :: TestTree tests = testGroup "Peekable"@@ -58,27 +56,6 @@         peek top     ] -  , testGroup "peekKeyValuePairs"-    [ "`next` is not confused when peeking at number keys as strings" =:-      -- list of numbers can be retrieved as pair of strings-      [("1", "2"), ("2", "4"), ("3", "8"), ("4", "16")] `shouldBeResultOf` do-        pushLuaExpr "{2, 4, 8, 16}"-        peekKeyValuePairs top :: Lua [(String, String)]--    , "peek string pairs" =:-      Set.fromList [("foo", "bar"), ("qux", "quux")] `shouldBeResultOf` do-        pushLuaExpr "{foo = 'bar', qux = 'quux'}"-        Set.fromList <$> (peekKeyValuePairs top :: Lua [(String, String)])--    , "stack is left unchanged" =:-      0 `shouldBeResultOf` do-        pushLuaExpr "{foo = 'bar', qux = 'quux'}"-        topBefore <- gettop-        _ <- peekKeyValuePairs top :: Lua [(String, String)]-        topAfter <- gettop-        return (topAfter - topBefore)-    ]-   , testGroup "error handling"     [ "error is thrown if boolean is given instead of stringy value" =:       "string expected, got boolean" `shouldBeErrorMessageOf` do@@ -96,7 +73,9 @@         peek top :: Lua Lua.Number      , "list cannot be read if a peeking at list element fails" =:-      "Could not read list:\n\tnumber expected, got boolean"+      ("number expected, got boolean" +++       "\n\twhile retrieving index 4" +++       "\n\twhile retrieving list")       `shouldBeErrorMessageOf` do         pushLuaExpr "{1, 5, 23, true, 42}"         peek top :: Lua [Lua.Number]@@ -105,7 +84,7 @@       0 `shouldBeResultOf` do         pushLuaExpr "{true, 1, 1, 2, 3, 5, 8}"         topBefore <- gettop-        _ <- peekList top :: Lua [Bool]+        _ <- peek top :: Lua [Bool]         topAfter <- gettop         return (topAfter - topBefore) @@ -113,7 +92,7 @@       0 `shouldBeResultOf` do         pushLuaExpr "{foo = 'bar', baz = false}"         topBefore <- gettop-        _ <- try (peekKeyValuePairs top :: Lua [(String, String)])+        _ <- try (peek top :: Lua [(String, String)])         topAfter <- gettop         return (topAfter - topBefore)     ]
test/HsLua/Class/PushableTests.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE TypeApplications  #-} {-| Module      :  HsLua.Class.PushableTests-Copyright   :  © 2017-2021 Albert Krewinkel+Copyright   :  © 2017-2022 Albert Krewinkel License     :  MIT  Maintainer  :  Albert Krewinkel <tarleb+hslua@zeitkraut.de>
test/HsLua/Class/UtilTests.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {-| Module      :  HsLua.Class.UtilTests-Copyright   :  © 2017-2021 Albert Krewinkel+Copyright   :  © 2017-2022 Albert Krewinkel License     :  MIT  Maintainer  :  Albert Krewinkel <tarleb+hslua@zeitkraut.de>@@ -66,8 +66,9 @@         peekEither top      , "return error message on failure" =:-      let msg = "Could not read list:\n"-             <> "\tinteger expected, got boolean"+      let msg = "integer expected, got boolean"+            <> "\n\twhile retrieving index 2"+            <> "\n\twhile retrieving list"       in       Left (Lua.Exception msg)       `shouldBeResultOf` do
test/HsLua/ClassesTests.hs view
@@ -3,7 +3,7 @@ Module      : HsLua.ClassesTests Copyright   : © 2007–2012 Gracjan Polak;               © 2012–2016 Ömer Sinan Ağacan;-              © 2017-2021 Albert Krewinkel+              © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta
test/test-hslua-classes.hs view
@@ -2,7 +2,7 @@ Module      : Main Copyright   : © 2007–2012 Gracjan Polak;               © 2012–2016 Ömer Sinan Ağacan;-              © 2017-2021 Albert Krewinkel+              © 2017-2022 Albert Krewinkel License     : MIT Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de> Stability   : beta