-
-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathUtil.hs
More file actions
68 lines (57 loc) · 2.06 KB
/
Util.hs
File metadata and controls
68 lines (57 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{-# LANGUAGE ScopedTypeVariables #-}
{-|
Module : HsLua.Class.Util
Copyright : © 2007–2012 Gracjan Polak;
© 2012–2016 Ömer Sinan Ağacan;
© 2017-2021 Albert Krewinkel
License : MIT
Maintainer : Albert Krewinkel <tarleb+hslua@zeitkraut.de>
Stability : beta
Portability : non-portable (depends on GHC)
HsLua utility functions.
-}
module HsLua.Class.Util
( raiseError
, Optional (Optional, fromOptional)
-- * getting values
, peekEither
, popValue
) where
import HsLua.Core (LuaE, NumResults, StackIndex, top)
import HsLua.Class.Peekable (Peekable (peek), PeekError)
import HsLua.Class.Pushable (Pushable (push))
import qualified Control.Monad.Catch as Catch
import qualified HsLua.Core as Lua
-- | Raise a Lua error, using the given value as the error object.
raiseError :: (PeekError e, Pushable a) => a -> LuaE e NumResults
raiseError e = do
push e
Lua.error
{-# INLINABLE raiseError #-}
-- | Newtype wrapper intended to be used for optional Lua values. Nesting this
-- type is strongly discouraged as missing values on inner levels are
-- indistinguishable from missing values on an outer level; wrong values
-- would be the likely result.
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
instance Pushable a => Pushable (Optional a) where
push (Optional Nothing) = Lua.pushnil
push (Optional (Just x)) = push x
--
-- Getting Values
--
-- | 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)
=> 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
{-# INLINABLE popValue #-}