@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2929Lua utility functions.
3030-}
3131module Text.Pandoc.Lua.Util
32− ( adjustIndexBy
32+ ( getTag
3333 , getTable
3434 , addValue
3535 , addFunction
@@ -47,6 +47,7 @@ module Text.Pandoc.Lua.Util
4747 ) where
4848
4949import Control.Monad (when)
50+import Control.Monad.Catch (finally)
5051import Data.ByteString.Char8 (unpack)
5152import Foreign.Lua (FromLuaStack (..), NumResults, Lua, NumArgs, StackIndex,
5253 ToLuaStack (..), ToHaskellFunction, getglobal')
@@ -163,11 +164,23 @@ loadScriptFromDataDir datadir scriptFile = do
163164-- to @require@, the a new loader function was created which then become
164165-- garbage. If that function is collected at an inopportune times, i.e. when the
165166-- Lua API is called via a function that doesn't allow calling back into Haskell
166−-- (getraw, setraw, …). The function's finalizer, and the full program, hangs
167−-- when that happens.
167+-- (getraw, setraw, …), then the function's finalizer, and the full program,
168+-- will hang.
168169dostring' :: String -> Lua Status
169170dostring' script = do
170171 loadRes <- Lua.loadstring script
171172 if loadRes == Lua.OK
172173 then Lua.pcall 0 1 Nothing <* Lua.gc Lua.GCCOLLECT 0
173174 else return loadRes
175+
176+-- | Get the tag of a value. This is an optimized and specialized version of
177+-- @Lua.getfield idx "tag"@. It only checks for the field on the table at index
178+-- @idx@ and on its metatable, also ignoring any @__index@ value on the
179+-- metatable.
180+getTag :: StackIndex -> Lua String
181+getTag idx = do
182+ top <- Lua.gettop
183+ hasMT <- Lua.getmetatable idx
184+ push "tag"
185+ if hasMT then Lua.rawget (-2) else Lua.rawget (idx `adjustIndexBy` 1)
186+ peek Lua.stackTop `finally` Lua.settop top