hslua 1.0.0 → 1.0.1
raw patch · 6 files changed
+151/−8 lines, 6 filesdep ~containersdep ~criterionPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: containers, criterion
API changes (from Hackage documentation)
+ Foreign.Lua.Core: getmetafield :: StackIndex -> String -> Lua Type
+ Foreign.Lua.Core: getmetatable' :: String -> Lua Type
+ Foreign.Lua.Core: getsubtable :: StackIndex -> String -> Lua Bool
+ Foreign.Lua.Core: traceback :: State -> Maybe String -> Int -> Lua ()
Files
- CHANGELOG.md +17/−0
- hslua.cabal +6/−5
- src/Foreign/Lua/Core.hs +4/−0
- src/Foreign/Lua/Core/Auxiliary.hsc +61/−0
- test/Foreign/Lua/Core/AuxiliaryTests.hs +60/−2
- test/Foreign/Lua/CoreTests.hs +3/−1
CHANGELOG.md view
@@ -1,5 +1,22 @@ ## Changelog +### 1.0.1++- Exposed more functions from Lua's `lauxlib` library:++ + `getmetafield`,+ + `getmetatable'`,+ + `getsubtable`, and+ + `traceback`.++ The function `getsubtable` is a reimplementation instead of a wrapper+ to the C function for simplicity (thereby avoiding additional C+ wrappers).++- Fixed tests for GHC 8.6 by no longer depending on failable pattern+ matching.++ ### 1.0.0 #### New features
hslua.cabal view
@@ -1,5 +1,5 @@ name: hslua-version: 1.0.0+version: 1.0.1 synopsis: Bindings to Lua, an embeddable scripting language description: HsLua provides bindings, wrappers, types, and helper functions to bridge Haskell and <https://www.lua.org/ Lua>.@@ -27,7 +27,8 @@ CHANGELOG.md test/lua/*.lua cabal-version: >=1.10-tested-with: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.2+tested-with: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3+ , GHC == 8.6.1 source-repository head type: git@@ -88,7 +89,7 @@ , Foreign.Lua.Core.Functions build-depends: base >= 4.8 && < 5 , bytestring >= 0.10.2 && < 0.11- , containers >= 0.5 && < 0.6+ , containers >= 0.5 && < 0.7 , exceptions >= 0.8 && < 0.11 , fail >= 4.9 && < 5 , mtl >= 2.2 && < 2.3@@ -194,7 +195,7 @@ , Test.HsLua.Util build-depends: base >= 4.8 && < 5 , bytestring >= 0.10.2 && < 0.11- , containers >= 0.5 && < 0.6+ , containers >= 0.5 && < 0.7 , exceptions >= 0.8 && < 0.11 , fail >= 4.9 && < 5 , mtl >= 2.2 && < 2.3@@ -215,7 +216,7 @@ build-depends: hslua , base >= 4.8 , bytestring >= 0.10.2 && < 0.11- , criterion >= 1.0 && < 1.5+ , criterion >= 1.0 && < 1.6 , deepseq >= 1.4.1 && < 1.5 c-sources: benchmark/benchmark-functions.c include-dirs: benchmark
src/Foreign/Lua/Core.hs view
@@ -149,8 +149,12 @@ -- * Auxiliary library , dostring , dofile+ , getmetafield+ , getmetatable'+ , getsubtable , newmetatable , tostring'+ , traceback -- ** References , Reference (..) , ref
src/Foreign/Lua/Core/Auxiliary.hsc view
@@ -14,12 +14,16 @@ module Foreign.Lua.Core.Auxiliary ( dostring , dofile+ , getmetafield+ , getmetatable'+ , getsubtable , loadbuffer , loadfile , loadstring , newmetatable , newstate , tostring'+ , traceback -- * References , getref , ref@@ -93,10 +97,53 @@ then Lua.pcall 0 multret Nothing else return loadRes +-- | Pushes onto the stack the field @e@ from the metatable of the object at+-- index @obj@ and returns the type of the pushed value. If the object does not+-- have a metatable, or if the metatable does not have this field, pushes+-- nothing and returns TypeNil.+getmetafield :: StackIndex -- ^ obj+ -> String -- ^ e+ -> Lua Lua.Type+getmetafield obj e = liftLua $ \l ->+ withCString e $ fmap Lua.toType . luaL_getmetafield l obj++foreign import capi SAFTY "lauxlib.h luaL_getmetafield"+ luaL_getmetafield :: Lua.State -> StackIndex -> CString -> IO Lua.TypeCode++-- | Pushes onto the stack the metatable associated with name @tname@ in the+-- registry (see @newmetatable@) (@nil@ if there is no metatable associated+-- with that name). Returns the type of the pushed value.+getmetatable' :: String -- ^ tname+ -> Lua Lua.Type+getmetatable' tname = liftLua $ \l ->+ withCString tname $ fmap Lua.toType . luaL_getmetatable l++foreign import capi SAFTY "lauxlib.h luaL_getmetatable"+ luaL_getmetatable :: Lua.State -> CString -> IO Lua.TypeCode+ -- | Push referenced value from the table at the given index. getref :: StackIndex -> Reference -> Lua () getref idx ref' = Lua.rawgeti idx (fromIntegral (Lua.fromReference ref')) +-- | Ensures that the value @t[fname]@, where @t@ is the value at index @idx@,+-- is a table, and pushes that table onto the stack. Returns True if it finds a+-- previous table there and False if it creates a new table.+getsubtable :: StackIndex -> String -> Lua Bool+getsubtable idx fname = do+ -- This is a reimplementation of luaL_getsubtable from lauxlib.c.+ idx' <- Lua.absindex idx+ Lua.pushstring (Utf8.fromString fname)+ Lua.gettable idx'+ isTbl <- Lua.istable Lua.stackTop+ if isTbl+ then return True+ else do+ Lua.pop 1+ Lua.newtable+ Lua.pushvalue Lua.stackTop -- copy to be left at top+ Lua.setfield idx' fname+ return False+ -- | Loads a ByteString as a Lua chunk. -- -- This function returns the same results as @'load'@. @name@ is the chunk name,@@ -238,6 +285,20 @@ foreign import ccall safe "error-conversion.h hsluaL_tolstring" hsluaL_tolstring :: Lua.State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)+++-- | Creates and pushes a traceback of the stack L1. If a message is given it+-- appended at the beginning of the traceback. The level parameter tells at+-- which level to start the traceback.+traceback :: Lua.State -> Maybe String -> Int -> Lua ()+traceback l1 msg level = liftLua $ \l ->+ case msg of+ Nothing -> luaL_traceback l l1 nullPtr (fromIntegral level)+ Just msg' -> withCString msg' $ \cstr ->+ luaL_traceback l l1 cstr (fromIntegral level)++foreign import capi unsafe "lauxlib.h luaL_traceback"+ luaL_traceback :: Lua.State -> Lua.State -> CString -> CInt -> IO () -- | Releases reference @'ref'@ from the table at index @idx@ (see @'ref'@). The
test/Foreign/Lua/Core/AuxiliaryTests.hs view
@@ -1,8 +1,9 @@+{-# LANGUAGE OverloadedStrings #-} {-| Tests for the auxiliary library. -} module Foreign.Lua.Core.AuxiliaryTests (tests) where -import Test.HsLua.Util ( (=:))+import Test.HsLua.Util ((?:), (=:), pushLuaExpr, shouldBeResultOf) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit ((@=?)) @@ -11,6 +12,63 @@ -- | Specifications for Attributes parsing functions. tests :: TestTree tests = testGroup "Auxiliary"- [ "loadedTable" =: ("_LOADED" @=? Lua.loadedTableRegistryField)+ [ testGroup "getsubtable"+ [ "gets a subtable from field" =:+ [1, 2, 3, 5, 8] `shouldBeResultOf` do+ pushLuaExpr "{foo = {1, 2, 3, 5, 8}}"+ _ <- Lua.getsubtable Lua.stackTop "foo"+ Lua.peek Lua.stackTop :: Lua.Lua [Int]++ , "creates new table at field if necessary" =:+ Lua.TypeTable `shouldBeResultOf` do+ Lua.newtable+ _ <- Lua.getsubtable Lua.stackTop "new"+ Lua.getfield (Lua.nthFromTop 2) "new"+ Lua.ltype Lua.stackTop++ , "returns True if a table exists" ?: do+ pushLuaExpr "{yep = {}}"+ Lua.getsubtable Lua.stackTop "yep"++ , "returns False if field does not contain a table" ?: do+ pushLuaExpr "{nope = 5}"+ not <$> Lua.getsubtable Lua.stackTop "nope"++ ]++ , testGroup "getmetafield'"+ [ "gets field from the object's metatable" =:+ ("testing" :: String) `shouldBeResultOf` do+ Lua.newtable+ pushLuaExpr "{foo = 'testing'}"+ Lua.setmetatable (Lua.nthFromTop 2)+ _ <- Lua.getmetafield Lua.stackTop "foo"+ Lua.peek Lua.stackTop++ , "returns TypeNil if the object doesn't have a metatable" =:+ Lua.TypeNil `shouldBeResultOf` do+ Lua.newtable+ Lua.getmetafield Lua.stackTop "foo"+ ]++ , testGroup "getmetatable'"+ [ "gets table created with newmetatable" =:+ [("__name" :: String, "testing" :: String)] `shouldBeResultOf` do+ Lua.newmetatable "testing" *> Lua.pop 1+ _ <- Lua.getmetatable' "testing"+ Lua.peekKeyValuePairs Lua.stackTop++ , "returns nil if there is no such metatable" =:+ Lua.TypeNil `shouldBeResultOf` do+ _ <- Lua.getmetatable' "nope"+ Lua.ltype Lua.stackTop++ , "returns TypeTable if metatable exists" =:+ Lua.TypeTable `shouldBeResultOf` do+ _ <- Lua.newmetatable "yep"+ Lua.getmetatable' "yep"+ ]++ , "loadedTable" =: ("_LOADED" @=? Lua.loadedTableRegistryField) , "preloadTable" =: ("_PRELOAD" @=? Lua.preloadTableRegistryField) ]
test/Foreign/Lua/CoreTests.hs view
@@ -37,6 +37,7 @@ import Prelude hiding (compare) import Control.Monad (forM_)+import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) import Foreign.Lua as Lua import Test.HsLua.Arbitrary ()@@ -225,7 +226,8 @@ getglobal "coroutine" getfield stackTop "resume" pushLuaExpr "coroutine.create(function() coroutine.yield(9) end)"- (Just contThread) <- tothread stackTop+ contThread <- fromMaybe (Prelude.error "not a thread at top of stack")+ <$> tothread stackTop call 1 0 liftIO $ runWith contThread status ]