hslua 0.4.1 → 0.5.0
raw patch · 5 files changed
+420/−129 lines, 5 filesdep ~basedep ~bytestringnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, bytestring
API changes (from Hackage documentation)
- Scripting.Lua: instance (StackValue a, LuaImport b) => LuaImport (a -> b)
- Scripting.Lua: instance (StackValue t, LuaCallFunc b) => LuaCallFunc (t -> b)
- Scripting.Lua: instance (StackValue t, LuaCallProc b) => LuaCallProc (t -> b)
- Scripting.Lua: instance Enum GCCONTROL
- Scripting.Lua: instance Enum LTYPE
- Scripting.Lua: instance Eq GCCONTROL
- Scripting.Lua: instance Eq LTYPE
- Scripting.Lua: instance LuaCallProc (IO t)
- Scripting.Lua: instance Ord GCCONTROL
- Scripting.Lua: instance Ord LTYPE
- Scripting.Lua: instance Show GCCONTROL
- Scripting.Lua: instance Show LTYPE
- Scripting.Lua: instance StackValue ()
- Scripting.Lua: instance StackValue (FunPtr LuaCFunction)
- Scripting.Lua: instance StackValue (Ptr a)
- Scripting.Lua: instance StackValue Bool
- Scripting.Lua: instance StackValue ByteString
- Scripting.Lua: instance StackValue Int
- Scripting.Lua: instance StackValue LuaInteger
- Scripting.Lua: instance StackValue LuaNumber
- Scripting.Lua: instance StackValue LuaState
- Scripting.Lua: instance StackValue a => LuaImport (IO a)
- Scripting.Lua: instance StackValue a => StackValue [a]
- Scripting.Lua: instance StackValue t => LuaCallFunc (IO t)
- Scripting.Lua: mkStringReader :: LuaReader -> IO (FunPtr LuaReader)
+ Scripting.Lua: instance (Scripting.Lua.StackValue a, Scripting.Lua.LuaImport b) => Scripting.Lua.LuaImport (a -> b)
+ Scripting.Lua: instance (Scripting.Lua.StackValue t, Scripting.Lua.LuaCallFunc b) => Scripting.Lua.LuaCallFunc (t -> b)
+ Scripting.Lua: instance (Scripting.Lua.StackValue t, Scripting.Lua.LuaCallProc b) => Scripting.Lua.LuaCallProc (t -> b)
+ Scripting.Lua: instance GHC.Classes.Eq Scripting.Lua.GCCONTROL
+ Scripting.Lua: instance GHC.Classes.Eq Scripting.Lua.LTYPE
+ Scripting.Lua: instance GHC.Classes.Ord Scripting.Lua.GCCONTROL
+ Scripting.Lua: instance GHC.Classes.Ord Scripting.Lua.LTYPE
+ Scripting.Lua: instance GHC.Enum.Enum Scripting.Lua.GCCONTROL
+ Scripting.Lua: instance GHC.Enum.Enum Scripting.Lua.LTYPE
+ Scripting.Lua: instance GHC.Show.Show Scripting.Lua.GCCONTROL
+ Scripting.Lua: instance GHC.Show.Show Scripting.Lua.LTYPE
+ Scripting.Lua: instance Scripting.Lua.LuaCallProc (GHC.Types.IO t)
+ Scripting.Lua: instance Scripting.Lua.StackValue ()
+ Scripting.Lua: instance Scripting.Lua.StackValue (GHC.Ptr.FunPtr Scripting.Lua.Raw.LuaCFunction)
+ Scripting.Lua: instance Scripting.Lua.StackValue (GHC.Ptr.Ptr a)
+ Scripting.Lua: instance Scripting.Lua.StackValue Data.ByteString.Internal.ByteString
+ Scripting.Lua: instance Scripting.Lua.StackValue GHC.Types.Bool
+ Scripting.Lua: instance Scripting.Lua.StackValue GHC.Types.Int
+ Scripting.Lua: instance Scripting.Lua.StackValue Scripting.Lua.Raw.LuaInteger
+ Scripting.Lua: instance Scripting.Lua.StackValue Scripting.Lua.Raw.LuaNumber
+ Scripting.Lua: instance Scripting.Lua.StackValue Scripting.Lua.Raw.LuaState
+ Scripting.Lua: instance Scripting.Lua.StackValue a => Scripting.Lua.LuaImport (GHC.Types.IO a)
+ Scripting.Lua: instance Scripting.Lua.StackValue a => Scripting.Lua.StackValue [a]
+ Scripting.Lua: instance Scripting.Lua.StackValue t => Scripting.Lua.LuaCallFunc (GHC.Types.IO t)
+ Scripting.Lua: openbase :: LuaState -> IO ()
+ Scripting.Lua: opendebug :: LuaState -> IO ()
+ Scripting.Lua: openio :: LuaState -> IO ()
+ Scripting.Lua: openmath :: LuaState -> IO ()
+ Scripting.Lua: openos :: LuaState -> IO ()
+ Scripting.Lua: openpackage :: LuaState -> IO ()
+ Scripting.Lua: openstring :: LuaState -> IO ()
+ Scripting.Lua: opentable :: LuaState -> IO ()
+ Scripting.Lua.Raw: c_luaL_loadfile :: LuaState -> Ptr CChar -> IO CInt
+ Scripting.Lua.Raw: c_luaL_loadstring :: LuaState -> Ptr CChar -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_base :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_base_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_debug :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_debug_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_io :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_io_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_math :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_math_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_os :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_os_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_package :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_package_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_string :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_string_ptr :: FunPtr (LuaState -> IO CInt)
+ Scripting.Lua.Raw: c_lua_open_table :: LuaState -> IO CInt
+ Scripting.Lua.Raw: c_lua_open_table_ptr :: FunPtr (LuaState -> IO CInt)
- Scripting.Lua: callfunc :: LuaCallFunc a => LuaState -> String -> a
+ Scripting.Lua: callfunc :: (LuaCallFunc a) => LuaState -> String -> a
- Scripting.Lua: callproc :: LuaCallProc a => LuaState -> String -> a
+ Scripting.Lua: callproc :: (LuaCallProc a) => LuaState -> String -> a
- Scripting.Lua: loadstring :: LuaState -> String -> String -> IO Int
+ Scripting.Lua: loadstring :: LuaState -> String -> IO Int
Files
- CHANGELOG.md +14/−0
- hslua.cabal +8/−5
- src/Scripting/Lua.hsc +134/−124
- src/Scripting/Lua/Raw.hsc +54/−0
- test/HsLuaSpec.hs +210/−0
CHANGELOG.md view
@@ -1,5 +1,19 @@ ## Changelog +### 0.5.0++* New raw functions for `luaopen_base`, `luaopen_package`, `luaopen_string`,+ `luaopen_table`, `luaopen_math`, `luaopen_io`, `luaopen_os`, `luaopen_debug`+ and their high-level wrappers (with names `openbase`, `opentable` etc.)+ implemented.+* Remove custom versions of `loadfile` and `loadstring`.+* Drop support for GHC versions < 7.8, avoid compiler warnings.+* Ensure no symbols are stripped when linking the bundled lua interpreter.+* Simplify `tostring` function definition. (Sean Proctor)+* Explicitly decprecate `strlen`. (Sean Proctor)+* Add links to lua documentation for functions wrapping the official lua C API.+ (Sean Proctor).+ ### 0.4.1 * Bugfix(#30): `tolist` wasn't popping elements of the list from stack.
hslua.cabal view
@@ -1,5 +1,5 @@ name: hslua-version: 0.4.1+version: 0.5.0 stability: beta cabal-version: >= 1.8 license: MIT@@ -42,7 +42,8 @@ default: False library- build-depends: base == 4.*, bytestring >= 0.10.2.0 && < 0.11+ build-depends: base >= 4.7 && < 5,+ bytestring >= 0.10.2 && < 0.11 exposed-modules: Scripting.Lua, Scripting.Lua.Raw hs-source-dirs: src ghc-options: -Wall -O2@@ -69,18 +70,20 @@ if os(linux) cc-options: "-DLUA_USE_LINUX"+ ld-options: "-Wl,-E" if os(darwin) cc-options: "-DLUA_USE_MACOSX" if os(freebsd) cc-options: "-DLUA_USE_POSIX"+ ld-options: "-Wl,-E" if os(windows)- cc-options: "-D__NO_ISOCEXT"+ cc-options: "-D__NO_ISOCEXT" if flag(apicheck)- cc-Options: "-DLUA_USE_APICHECK"+ cc-options: "-DLUA_USE_APICHECK" -- This is not necessary because we have a test suite now. Still keeping here as -- a very simple test. Originally added with 799a4c2 to test if linking with@@ -114,7 +117,7 @@ main-is: Spec.hs hs-source-dirs: test ghc-options: -Wall -threaded-+ other-modules: HsLuaSpec build-depends: base, bytestring,
src/Scripting/Lua.hsc view
@@ -1,9 +1,6 @@-{-# LANGUAGE FlexibleInstances, ForeignFunctionInterface, ScopedTypeVariables #-}---- In older versions of GHC, FlexibleInstances doesn't imply--- TypeSynonymInstances, so we need to enable it explicitly.--- See #29.-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE ScopedTypeVariables #-} module Scripting.Lua ( LuaState@@ -13,7 +10,10 @@ , module Scripting.Lua ) where +#if MIN_VERSION_base(4,8,0)+#else import Control.Applicative ((<$>))+#endif import Control.Monad import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC@@ -23,7 +23,6 @@ import Data.Maybe import Foreign.C import Foreign.Marshal.Alloc-import Foreign.Marshal.Array import Foreign.Ptr import Foreign.StablePtr import qualified Foreign.Storable as F@@ -34,7 +33,7 @@ #include "lua.h" --- | Enumeration used as type tag. See @lua_type@ in Lua Reference Manual.+-- | Enumeration used as type tag. See <https://www.lua.org/manual/5.1/manual.html#lua_type lua_type>. data LTYPE = TNONE | TNIL@@ -84,51 +83,52 @@ | GCSETSTEPMUL deriving (Eq,Ord,Show,Enum) --- | See @LUA_MULTRET@ in Lua Reference Manual.+-- | Alias for C constant @LUA_MULTRET@. See <https://www.lua.org/manual/5.1/manual.html#lua_call lua_call>. multret :: Int multret = #{const LUA_MULTRET} --- | See @lua_settop@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_settop lua_settop>. settop :: LuaState -> Int -> IO () settop l n = c_lua_settop l (fromIntegral n) --- | See @lua_createtable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_createtable lua_createtable>. createtable :: LuaState -> Int -> Int -> IO () createtable l s z = c_lua_createtable l (fromIntegral s) (fromIntegral z) --- | See @lua_objlen@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_objlen lua_objlen>. objlen :: LuaState -> Int -> IO Int objlen l n = liftM fromIntegral (c_lua_objlen l (fromIntegral n)) --- | See @lua_pop@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pop lua_pop>. pop :: LuaState -> Int -> IO () pop l n = settop l (-n-1) --- | See @lua_newtable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_newtable lua_newtable>. newtable :: LuaState -> IO () newtable l = createtable l 0 0 --- | See @lua_pushcclosure@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushcclosure lua_pushcclosure>. pushcclosure :: LuaState -> FunPtr LuaCFunction -> Int -> IO () pushcclosure l f n = c_lua_pushcclosure l f (fromIntegral n) --- | See @lua_pushcfunction@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushcfunction lua_pushcfunction>. pushcfunction :: LuaState -> FunPtr LuaCFunction -> IO () pushcfunction l f = pushcclosure l f 0 --- | See @lua_strlen@ in Lua Reference Manual.+{-# DEPRECATED strlen "Use objlen instead." #-}+-- | Compatibility alias for objlen strlen :: LuaState -> Int -> IO Int strlen = objlen --- | See @lua_type@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_type lua_type>. ltype :: LuaState -> Int -> IO LTYPE ltype l n = liftM (toEnum . fromIntegral) (c_lua_type l (fromIntegral n)) --- | See @lua_isfunction@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isfunction lua_isfunction>. isfunction :: LuaState -> Int -> IO Bool isfunction l n = liftM (== TFUNCTION) (ltype l n) --- | See @lua_istable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_istable lua_istable>. istable :: LuaState -> Int -> IO Bool istable l n = liftM (== TTABLE) (ltype l n) @@ -151,85 +151,82 @@ Nothing -> Nothing Just vals -> Just (val : vals) --- | See @lua_islightuserdata@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_islightuserdata lua_islightuserdata>. islightuserdata :: LuaState -> Int -> IO Bool islightuserdata l n = liftM (== TLIGHTUSERDATA) (ltype l n) --- | See @lua_isnil@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isnil lua_isnil>. isnil :: LuaState -> Int -> IO Bool isnil l n = liftM (== TNIL) (ltype l n) --- | See @lua_isboolean@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isboolean lua_isboolean>. isboolean :: LuaState -> Int -> IO Bool isboolean l n = liftM (== TBOOLEAN) (ltype l n) --- | See @lua_isthread@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isthread lua_isthread>. isthread :: LuaState -> Int -> IO Bool isthread l n = liftM (== TTHREAD) (ltype l n) --- | See @lua_none@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isnone lua_isnone>. isnone :: LuaState -> Int -> IO Bool isnone l n = liftM (== TNONE) (ltype l n) --- | See @lua_noneornil@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isnoneornil lua_isnoneornil>. isnoneornil :: LuaState -> Int -> IO Bool isnoneornil l n = liftM (<= TNIL) (ltype l n) --- | See @LUA_REGISTRYINDEX@ in Lua Reference Manual.+-- | Alias for C constant @LUA_REGISTRYINDEX@. See <https://www.lua.org/manual/5.1/manual.html#3.5 Lua registry>. registryindex :: Int registryindex = #{const LUA_REGISTRYINDEX} --- | See @LUA_ENVIRONINDEX@ in Lua Reference Manual.+-- | Alias for C constant @LUA_ENVIRONINDEX@. See <https://www.lua.org/manual/5.1/manual.html#3.3 pseudo-indices>. environindex :: Int environindex = #{const LUA_ENVIRONINDEX} --- | See @LUA_GLOBALSINDEX@ in Lua Reference Manual.+-- | Alias for C constant @LUA_GLOBALSINDEX@. See <https://www.lua.org/manual/5.1/manual.html#3.3 pseudo-indices>. globalsindex :: Int globalsindex = #{const LUA_GLOBALSINDEX} --- | See @lua_upvalueindex@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_upvalueindex lua_upvalueindex>. upvalueindex :: Int -> Int upvalueindex i = globalsindex - i --- | See @lua_atpanic@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_atpanic lua_atpanic>. atpanic :: LuaState -> FunPtr LuaCFunction -> IO (FunPtr LuaCFunction) atpanic = c_lua_atpanic --- | See @lua_tostring@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_tostring lua_tostring>. tostring :: LuaState -> Int -> IO B.ByteString tostring l n = alloca $ \lenPtr -> do cstr <- c_lua_tolstring l (fromIntegral n) lenPtr- len <- F.peek lenPtr- -- Lua string may change or get garbage collected, copy it- cstr' <- mallocBytes (fromIntegral len)- copyArray cstr' cstr (fromIntegral len)- B.unsafePackMallocCStringLen (cstr', fromIntegral len)+ cstrLen <- F.peek lenPtr+ B.packCStringLen (cstr, fromIntegral cstrLen) --- | See @lua_tothread@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_tothread lua_tothread>. tothread :: LuaState -> Int -> IO LuaState tothread l n = c_lua_tothread l (fromIntegral n) --- | See @lua_touserdata@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_touserdata lua_touserdata>. touserdata :: LuaState -> Int -> IO (Ptr a) touserdata l n = c_lua_touserdata l (fromIntegral n) --- | See @lua_typename@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_typename lua_typename>. typename :: LuaState -> LTYPE -> IO String typename l n = c_lua_typename l (fromIntegral (fromEnum n)) >>= peekCString --- | See @lua_xmove@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_xmove lua_xmove>. xmove :: LuaState -> LuaState -> Int -> IO () xmove l1 l2 n = c_lua_xmove l1 l2 (fromIntegral n) --- | See @lua_yield@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_yield lua_yield>. yield :: LuaState -> Int -> IO Int yield l n = liftM fromIntegral (c_lua_yield l (fromIntegral n)) --- | See @lua_checkstack@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_checkstack lua_checkstack>. checkstack :: LuaState -> Int -> IO Bool checkstack l n = liftM (/= 0) (c_lua_checkstack l (fromIntegral n)) --- | See @lua_newstate@ and @luaL_newstate@ in Lua Reference Manual.+-- | See @lua_newstate@ and <https://www.lua.org/manual/5.1/manual.html#luaL_newstate luaL_newstate>. newstate :: IO LuaState newstate = do l <- c_luaL_newstate@@ -237,49 +234,81 @@ setglobal l "_HASKELLERR" return l --- | See @lua_close@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_close lua_close>. close :: LuaState -> IO () close = c_lua_close --- | See @lua_concat@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_concat lua_concat>. concat :: LuaState -> Int -> IO () concat l n = c_lua_concat l (fromIntegral n) --- | See @lua_call@ and @lua_call@ in Lua Reference Manual.+-- | See @lua_call@ and <https://www.lua.org/manual/5.1/manual.html#lua_call lua_call>. call :: LuaState -> Int -> Int -> IO () call l a b = c_lua_call l (fromIntegral a) (fromIntegral b) --- | See @lua_pcall@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pcall lua_pcall>. pcall :: LuaState -> Int -> Int -> Int -> IO Int pcall l a b c = liftM fromIntegral (c_lua_pcall l (fromIntegral a) (fromIntegral b) (fromIntegral c)) --- | See @lua_cpcall@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_cpcall lua_cpcall>. cpcall :: LuaState -> FunPtr LuaCFunction -> Ptr a -> IO Int cpcall l a c = liftM fromIntegral (c_lua_cpcall l a c) --- | See @lua_getfield@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_getfield lua_getfield>. getfield :: LuaState -> Int -> String -> IO () getfield l i s = withCString s $ \sPtr -> c_lua_getfield l (fromIntegral i) sPtr --- | See @lua_setfield@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_setfield lua_setfield>. setfield :: LuaState -> Int -> String -> IO () setfield l i s = withCString s $ \sPtr -> c_lua_setfield l (fromIntegral i) sPtr --- | See @lua_getglobal@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_getglobal lua_getglobal>. getglobal :: LuaState -> String -> IO () getglobal l n = getfield l globalsindex n --- | See @lua_setglobal@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_setglobal lua_setglobal>. setglobal :: LuaState -> String -> IO () setglobal l n = setfield l globalsindex n --- | See @luaL_openlibs@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_openlibs luaL_openlibs>. openlibs :: LuaState -> IO () openlibs = c_luaL_openlibs +-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_base luaopen_base>.+openbase :: LuaState -> IO ()+openbase l = pushcfunction l c_lua_open_base_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_table luaopen_table>.+opentable :: LuaState -> IO ()+opentable l = pushcfunction l c_lua_open_table_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_io luaopen_io>.+openio :: LuaState -> IO ()+openio l = pushcfunction l c_lua_open_io_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_os luaopen_os>.+openos :: LuaState -> IO ()+openos l = pushcfunction l c_lua_open_os_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_string luaopen_string>.+openstring :: LuaState -> IO ()+openstring l = pushcfunction l c_lua_open_string_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_math luaopen_math>.+openmath :: LuaState -> IO ()+openmath l = pushcfunction l c_lua_open_math_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_debug luaopen_debug>.+opendebug :: LuaState -> IO ()+opendebug l = pushcfunction l c_lua_open_debug_ptr >> call l 0 multret++-- | See <https://www.lua.org/manual/5.1/manual.html#pdf-luaopen_package luaopen_package>.+openpackage :: LuaState -> IO ()+openpackage l = pushcfunction l c_lua_open_package_ptr >> call l 0 multret+ foreign import ccall "wrapper" mkStringWriter :: LuaWriter -> IO (FunPtr LuaWriter) --- | See @lua_dump@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_dump lua_dump>. dump :: LuaState -> IO String dump l = do r <- newIORef ""@@ -293,7 +322,7 @@ freeHaskellFunPtr writer readIORef r --- | See @lua_equal@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_equal lua_equal>. equal :: LuaState -> Int -> Int -> IO Bool equal l i j = liftM (/= 0) (c_lua_equal l (fromIntegral i) (fromIntegral j)) @@ -307,111 +336,92 @@ insert l (-2) return 2 --- | See @lua_gc@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_gc lua_gc>. gc :: LuaState -> GCCONTROL -> Int -> IO Int gc l i j= liftM fromIntegral (c_lua_gc l (fromIntegral (fromEnum i)) (fromIntegral j)) --- | See @lua_getfenv@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_getfenv lua_getfenv>. getfenv :: LuaState -> Int -> IO () getfenv l n = c_lua_getfenv l (fromIntegral n) --- | See @lua_getmetatable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_getmetatable lua_getmetatable>. getmetatable :: LuaState -> Int -> IO Bool getmetatable l n = liftM (/= 0) (c_lua_getmetatable l (fromIntegral n)) --- | See @lua_gettable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_gettable lua_gettable>. gettable :: LuaState -> Int -> IO () gettable l n = c_lua_gettable l (fromIntegral n) --- | See @lua_gettop@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_gettop lua_gettop>. gettop :: LuaState -> IO Int gettop l = liftM fromIntegral (c_lua_gettop l) --- | See @lua_insert@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_insert lua_insert>. insert :: LuaState -> Int -> IO () insert l n = c_lua_insert l (fromIntegral n) --- | See @lua_iscfunction@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_iscfunction lua_iscfunction>. iscfunction :: LuaState -> Int -> IO Bool iscfunction l n = liftM (/= 0) (c_lua_iscfunction l (fromIntegral n)) --- | See @lua_isnumber@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isnumber lua_isnumber>. isnumber :: LuaState -> Int -> IO Bool isnumber l n = liftM (/= 0) (c_lua_isnumber l (fromIntegral n)) --- | See @lua_isstring@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isstring lua_isstring>. isstring :: LuaState -> Int -> IO Bool isstring l n = liftM (/= 0) (c_lua_isstring l (fromIntegral n)) --- | See @lua_isuserdata@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_isuserdata lua_isuserdata>. isuserdata :: LuaState -> Int -> IO Bool isuserdata l n = liftM (/= 0) (c_lua_isuserdata l (fromIntegral n)) --- | See @lua_lessthan@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_lessthan lua_lessthan>. lessthan :: LuaState -> Int -> Int -> IO Bool lessthan l i j = liftM (/= 0) (c_lua_lessthan l (fromIntegral i) (fromIntegral j)) --- | See @luaL_loadfile@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_loadfile luaL_loadfile>. loadfile :: LuaState -> String -> IO Int-loadfile l f = readFile f >>= \c -> loadstring l c f--foreign import ccall "wrapper" mkStringReader :: LuaReader -> IO (FunPtr LuaReader)+loadfile l f = withCString f $ \fPtr -> fmap fromIntegral (c_luaL_loadfile l fPtr) --- | See @luaL_loadstring@ in Lua Reference Manual.-loadstring :: LuaState -> String -> String -> IO Int-loadstring l script cn = do- w <- newIORef nullPtr- let rd :: LuaReader- rd _l _d ps = do- k <- readIORef w- if k == nullPtr- then do- (s, len) <- newCStringLen script- writeIORef w s- F.poke ps (fromIntegral len)- return s- else return nullPtr- writer <- mkStringReader rd- res <- withCString cn $ \cnPtr -> c_lua_load l writer nullPtr cnPtr- freeHaskellFunPtr writer- k <- readIORef w- free k- return (fromIntegral res)+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_loadstring luaL_loadstring>.+loadstring :: LuaState -> String -> IO Int+loadstring l str = withCString str $ \strPtr -> fmap fromIntegral (c_luaL_loadstring l strPtr) --- | See @lua_newthread@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_newthread lua_newthread>. newthread :: LuaState -> IO LuaState newthread l = c_lua_newthread l --- | See @lua_newuserdata@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_newuserdata lua_newuserdata>. newuserdata :: LuaState -> Int -> IO (Ptr ()) newuserdata l s = c_lua_newuserdata l (fromIntegral s) --- | See @lua_next@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_next lua_next>. next :: LuaState -> Int -> IO Bool next l i = liftM (/= 0) (c_lua_next l (fromIntegral i)) --- | See @lua_pushboolean@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushboolean lua_pushboolean>. pushboolean :: LuaState -> Bool -> IO () pushboolean l v = c_lua_pushboolean l (fromIntegral (fromEnum v)) --- | See @lua_pushinteger@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushinteger lua_pushinteger>. pushinteger :: LuaState -> LuaInteger -> IO () pushinteger = c_lua_pushinteger --- | See @lua_pushlightuserdata@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushlightuserdata lua_pushlightuserdata>. pushlightuserdata :: LuaState -> Ptr a -> IO () pushlightuserdata = c_lua_pushlightuserdata --- | See @lua_pushnil@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushnil lua_pushnil>. pushnil :: LuaState -> IO () pushnil = c_lua_pushnil --- | See @lua_pushnumber@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushnumber lua_pushnumber>. pushnumber :: LuaState -> LuaNumber -> IO () pushnumber = c_lua_pushnumber --- | See @lua_pushstring@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushstring lua_pushstring>. pushstring :: LuaState -> B.ByteString -> IO () pushstring l s = B.unsafeUseAsCStringLen s $ \(sPtr, z) -> c_lua_pushlstring l sPtr (fromIntegral z) @@ -423,94 +433,94 @@ push l val rawseti l (-2) idx --- | See @lua_pushthread@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushthread lua_pushthread>. pushthread :: LuaState -> IO Bool pushthread l = liftM (/= 0) (c_lua_pushthread l) --- | See @lua_pushvalue@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pushvalue lua_pushvalue>. pushvalue :: LuaState -> Int -> IO () pushvalue l n = c_lua_pushvalue l (fromIntegral n) --- | See @lua_rawequal@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_rawequal lua_rawequal>. rawequal :: LuaState -> Int -> Int -> IO Bool rawequal l n m = liftM (/= 0) (c_lua_rawequal l (fromIntegral n) (fromIntegral m)) --- | See @lua_rawget@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_rawget lua_rawget>. rawget :: LuaState -> Int -> IO () rawget l n = c_lua_rawget l (fromIntegral n) --- | See @lua_rawgeti@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_rawgeti lua_rawgeti>. rawgeti :: LuaState -> Int -> Int -> IO () rawgeti l k m = c_lua_rawgeti l (fromIntegral k) (fromIntegral m) --- | See @lua_rawset@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_rawset lua_rawset>. rawset :: LuaState -> Int -> IO () rawset l n = c_lua_rawset l (fromIntegral n) --- | See @lua_rawseti@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_rawseti lua_rawseti>. rawseti :: LuaState -> Int -> Int -> IO () rawseti l k m = c_lua_rawseti l (fromIntegral k) (fromIntegral m) --- | See @lua_remove@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_remove lua_remove>. remove :: LuaState -> Int -> IO () remove l n = c_lua_remove l (fromIntegral n) --- | See @lua_replace@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_replace lua_replace>. replace :: LuaState -> Int -> IO () replace l n = c_lua_replace l (fromIntegral n) --- | See @lua_resume@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_resume lua_resume>. resume :: LuaState -> Int -> IO Int resume l n = liftM fromIntegral (c_lua_resume l (fromIntegral n)) --- | See @lua_setfenv@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_setfenv lua_setfenv>. setfenv :: LuaState -> Int -> IO Int setfenv l n = liftM fromIntegral (c_lua_setfenv l (fromIntegral n)) --- | See @lua_setmetatable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_setmetatable lua_setmetatable>. setmetatable :: LuaState -> Int -> IO () setmetatable l n = c_lua_setmetatable l (fromIntegral n) --- | See @lua_settable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_settable lua_settable>. settable :: LuaState -> Int -> IO () settable l index = c_lua_settable l (fromIntegral index) --- | See @lua_status@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_status lua_status>. status :: LuaState -> IO Int status l = liftM fromIntegral (c_lua_status l) --- | See @lua_toboolean@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_toboolean lua_toboolean>. toboolean :: LuaState -> Int -> IO Bool toboolean l n = liftM (/= 0) (c_lua_toboolean l (fromIntegral n)) --- | See @lua_tocfunction@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_tocfunction lua_tocfunction>. tocfunction :: LuaState -> Int -> IO (FunPtr LuaCFunction) tocfunction l n = c_lua_tocfunction l (fromIntegral n) --- | See @lua_tointeger@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_tointeger lua_tointeger>. tointeger :: LuaState -> Int -> IO LuaInteger tointeger l n = c_lua_tointeger l (fromIntegral n) --- | See @lua_tonumber@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_tonumber lua_tonumber>. tonumber :: LuaState -> Int -> IO LuaNumber tonumber l n = c_lua_tonumber l (fromIntegral n) --- | See @lua_topointer@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_topointer lua_topointer>. topointer :: LuaState -> Int -> IO (Ptr ()) topointer l n = c_lua_topointer l (fromIntegral n) --- | See @lua_register@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#lua_register lua_register>. register :: LuaState -> String -> FunPtr LuaCFunction -> IO () register l n f = do pushcclosure l f 0 setglobal l n --- | See @luaL_newmetatable@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_newmetatable luaL_newmetatable>. newmetatable :: LuaState -> String -> IO Int newmetatable l s = withCString s $ \sPtr -> liftM fromIntegral (c_luaL_newmetatable l sPtr) --- | See @luaL_argerror@ in Lua Reference Manual. Contrary to the+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_argerror luaL_argerror>. Contrary to the -- manual, Haskell function does return with value less than zero. argerror :: LuaState -> Int -> String -> IO CInt argerror l n msg = withCString msg $ \msgPtr -> do@@ -521,11 +531,11 @@ -- here we should have error message string on top of the stack return (-1) --- | See @luaL_ref@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_ref luaL_ref>. ref :: LuaState -> Int -> IO Int ref l n = fmap fromIntegral $ c_luaL_ref l (fromIntegral n) --- | See @luaL_unref@ in Lua Reference Manual.+-- | See <https://www.lua.org/manual/5.1/manual.html#luaL_unref luaL_unref>. unref :: LuaState -> Int -> Int -> IO () unref l t r = c_luaL_unref l (fromIntegral t) (fromIntegral r)
src/Scripting/Lua/Raw.hsc view
@@ -281,7 +281,55 @@ foreign import ccall "lualib.h luaL_openlibs" c_luaL_openlibs :: LuaState -> IO () +foreign import ccall "lualib.h luaopen_base"+ c_lua_open_base :: LuaState -> IO CInt +foreign import ccall "lualib.h &luaopen_base"+ c_lua_open_base_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_table"+ c_lua_open_table :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_table"+ c_lua_open_table_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_io"+ c_lua_open_io :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_io"+ c_lua_open_io_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_os"+ c_lua_open_os :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_os"+ c_lua_open_os_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_string"+ c_lua_open_string :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_string"+ c_lua_open_string_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_math"+ c_lua_open_math :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_math"+ c_lua_open_math_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_debug"+ c_lua_open_debug :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_debug"+ c_lua_open_debug_ptr :: FunPtr (LuaState -> IO CInt)++foreign import ccall "lualib.h luaopen_package"+ c_lua_open_package :: LuaState -> IO CInt++foreign import ccall "lualib.h &luaopen_package"+ c_lua_open_package_ptr :: FunPtr (LuaState -> IO CInt)++ -------------------------------------------------------------------------------- -- * The Auxiliary Library @@ -299,3 +347,9 @@ foreign import ccall "lauxlib.h luaL_unref" c_luaL_unref :: LuaState -> CInt -> CInt -> IO ()++foreign import ccall "lauxlib.h luaL_loadfile"+ c_luaL_loadfile :: LuaState -> Ptr CChar -> IO CInt++foreign import ccall "lauxlib.h luaL_loadstring"+ c_luaL_loadstring :: LuaState -> Ptr CChar -> IO CInt
+ test/HsLuaSpec.hs view
@@ -0,0 +1,210 @@+module HsLuaSpec where++import Control.Monad (forM, forM_, when)+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as B+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import System.Mem (performMajorGC)++import Test.Hspec+import Test.Hspec.Contrib.HUnit+import Test.HUnit++import Test.QuickCheck+import Test.QuickCheck.Instances ()+import qualified Test.QuickCheck.Monadic as QM++import Scripting.Lua++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "StackValue" $ mapM_ fromHUnitTest+ [bytestring, bsShouldLive, listInstance, nulString]+ describe "Random StackValues" $ do+ it "can push/pop booleans" $ property prop_bool+ it "can push/pop ints" $ property prop_int+ it "can push/pop doubles" $ property prop_double+ it "can push/pop bytestrings" $ property prop_bytestring+ it "can push/pop lists of booleans" $ property prop_lists_bool+ it "can push/pop lists of ints" $ property prop_lists_int+ it "can push/pop lists of bytestrings" $ property prop_lists_bytestring+ describe "luaopen_* functions" $ mapM_ fromHUnitTest $ map (uncurry testOpen) $+ [ ("table", opentable), ("io", openio), ("os", openos),+ ("string", openstring), ("math", openmath), ("debug", opendebug),+ ("package", openpackage) ]+ describe "luaopen_base returns two tables" $ fromHUnitTest $ testOpenBase++bytestring :: Test+bytestring = TestLabel "ByteString -- unicode stuff" $ TestCase $ do+ l <- newstate+ let val = T.pack "öçşiğüİĞı"+ pushstring l (T.encodeUtf8 val)+ val' <- T.decodeUtf8 `fmap` tostring l 1+ close l+ assertEqual "Popped a different value or pop failed" val val'++bsShouldLive :: Test+bsShouldLive = TestLabel "ByteString should survive after GC/Lua destroyed" $ TestCase $ do+ (val, val') <- do+ l <- newstate+ let val = B.pack "ByteString should survive"+ pushstring l val+ val' <- tostring l 1+ pop l 1+ close l+ return (val, val')+ performMajorGC+ assertEqual "Popped a different value or pop failed" val val'++listInstance :: Test+listInstance = TestLabel "Push/pop StackValue lists" $ TestCase $ do+ let lst = [B.pack "first", B.pack "second"]+ l <- newstate+ pushlist l lst+ setglobal l "mylist"+ size0 <- gettop l+ assertEqual+ "After pushing the list and assigning to a variable, stack is not empty"+ 0 size0+ getglobal l "mylist"+ size1 <- gettop l+ assertEqual "`getglobal` pushed more than one value to the stack" 1 size1+ lst' <- tolist l 1+ size2 <- gettop l+ assertEqual "`tolist` left stuff on the stack" size1 size2+ close l+ assertEqual "Popped a different list or pop failed" (Just lst) lst'++nulString :: Test+nulString =+ TestLabel "String with NUL byte should be pushed/popped correctly" $ TestCase $ do+ l <- newstate+ let str = "A\NULB"+ pushstring l (B.pack str)+ str' <- tostring l 1+ close l+ assertEqual "Popped string is different than what's pushed" str (B.unpack str')+++-----+-- Random Quickcheck testing for StackValue instances+-----++-- Bools+prop_bool :: Bool -> Property+prop_bool = testStackValueInstance+-- Ints+prop_int :: Int -> Property+prop_int = testStackValueInstance+-- Doubles+prop_double :: Double -> Property+prop_double = testStackValueInstance+-- Bytestrings+prop_bytestring :: ByteString -> Property+prop_bytestring = testStackValueInstance+-- Lists of bools+prop_lists_bool :: [Bool] -> Property+prop_lists_bool = testStackValueInstance+-- Lists of ints+prop_lists_int :: [Int] -> Property+prop_lists_int = testStackValueInstance+-- Lists of bytestrings+prop_lists_bytestring :: [ByteString] -> Property+prop_lists_bytestring = testStackValueInstance++-- Check that the StackValue instance for a datatype works+testStackValueInstance :: (Show t, Eq t, StackValue t) => t -> Property+testStackValueInstance t = QM.monadicIO $ do+ -- Init Lua state+ l <- QM.run newstate+ -- Get an ascending list of small (1-100) positive integers+ -- These are the indices at which we will push the value to be tested+ -- Note that duplicate values don't matter so we don't need to guard against that+ Ordered indices' <- QM.pick arbitrary+ let indices = map getPositive indices'+ let nItems = if null indices then 0 else last indices+ -- Make sure there's enough room in the stack+ QM.assert =<< QM.run (checkstack l nItems)+ -- Push elements+ QM.run $ forM_ [1..nItems] $ \n ->+ if n `elem` indices+ then push l t+ else push l n+ -- Check that the stack size is the same as the total number of pushed items+ stackSize <- QM.run $ gettop l+ QM.assert $ stackSize == nItems+ -- Peek all items+ vals <- QM.run $ forM indices $ peek l+ -- Check that the stack size did not change after peeking+ newStackSize <- QM.run $ gettop l+ QM.assert $ stackSize == newStackSize+ -- Check that we were able to peek at all pushed elements+ forM_ vals $ QM.assert . (== Just t)++ -- DEBUGGING -----------------------------------------------+ -- QM.run $ putStrLn $ "Testing value -------- " ++ show t+ -- QM.run $ putStrLn $ "Indices: " ++ show indices+ -- QM.run $ putStrLn $ "StackSize: " ++ show stackSize+ -- QM.run $ putStrLn $ "NewStackSize: " ++ show newStackSize+ -- QM.run $ putStrLn $ "Peeked Values: " ++ show vals++--------------------------------------------------------------------------------+-- luaopen_* functions++testOpen :: String -> (LuaState -> IO ()) -> Test+testOpen lib openfn = TestLabel ("open" ++ lib) $ TestCase $ do+ l <- newstate+ openlibs l+ loadInspect l++ getglobal l "print"+ getglobal2 l "inspect.inspect"+ openfn l+ call l 1 1+ call l 1 0++ close l++testOpenBase :: Test+testOpenBase = TestLabel "openbase" $ TestCase $ do+ l <- newstate+ openlibs l+ loadInspect l++ getglobal l "print"+ getglobal2 l "inspect.inspect"+ getglobal l "print"+ getglobal2 l "inspect.inspect"++ openbase l+ insert l 3++ putStrLn "--- First table ---"++ call l 1 1+ call l 1 0++ putStrLn "--- Second table ---"++ call l 1 1+ call l 1 0++ return ()++loadInspect :: LuaState -> Assertion+loadInspect l = do+ loadRet <- loadfile l "test/inspect.lua"+ assertEqual "load failed" 0 loadRet+ pcallRet <- pcall l 0 multret 0++ when (pcallRet /= 0) $ do+ msg <- tostring l 1+ close l+ assertFailure ("pcall failed with " ++ show pcallRet ++ "\n" +++ "error message was: " ++ B.unpack msg)++ setglobal l "inspect"