packages feed

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 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"