@@ -35,13 +35,15 @@ module Text.Pandoc.Lua.StackInstances () where
36import Control.Applicative ((<|>))
36import Control.Applicative ((<|>))
37import Control.Monad (when)
37import Control.Monad (when)
38+import Control.Monad.Catch (finally)
38import Data.Data (showConstr, toConstr)
39import Data.Data (showConstr, toConstr)
39import Data.Foldable (forM_)
40import Data.Foldable (forM_)
40import Foreign.Lua (FromLuaStack (peek), Lua, LuaInteger, LuaNumber, StackIndex,
41import Foreign.Lua (FromLuaStack (peek), Lua, LuaInteger, LuaNumber, StackIndex,
41 ToLuaStack (push), Type (..), throwLuaError, tryLua)
42 ToLuaStack (push), Type (..), throwLuaError, tryLua)
42import Text.Pandoc.Definition
43import Text.Pandoc.Definition
43import Text.Pandoc.Extensions (Extensions)
44import Text.Pandoc.Extensions (Extensions)
44−import Text.Pandoc.Lua.Util (adjustIndexBy, getTable, pushViaConstructor)
45+import Text.Pandoc.Lua.Util (adjustIndexBy, getTable, pushViaConstructor,
45import Text.Pandoc.Options (ReaderOptions (..), TrackChanges)
47import Text.Pandoc.Options (ReaderOptions (..), TrackChanges)
46import Text.Pandoc.Shared (Element (Blk, Sec), safeRead)
48import Text.Pandoc.Shared (Element (Blk, Sec), safeRead)
@@ -49,21 +51,27 @@ import qualified Foreign.Lua as Lua
49import qualified Data.Set as Set
51import qualified Data.Set as Set
50import qualified Text.Pandoc.Lua.Util as LuaUtil
52import qualified Text.Pandoc.Lua.Util as LuaUtil
54+defineHowTo :: String -> Lua a -> Lua a
55+defineHowTo ctx op = op `Lua.modifyLuaError` (("Could not " ++ ctx ++ ": ") ++)
52instance ToLuaStack Pandoc where
57instance ToLuaStack Pandoc where
53 push (Pandoc meta blocks) =
58 push (Pandoc meta blocks) =
54 pushViaConstructor "Pandoc" blocks meta
59 pushViaConstructor "Pandoc" blocks meta
56instance FromLuaStack Pandoc where
61instance FromLuaStack Pandoc where
57− peek idx = do
62+ peek idx = defineHowTo "get Pandoc value" $ do
63+ typeCheck idx Lua.TypeTable
58 blocks <- getTable idx "blocks"
64 blocks <- getTable idx "blocks"
59− meta <- getTable idx "meta"
65+ meta <- Lua.getfield idx "meta" *> (Lua.peek Lua.stackTop `finally` Lua.pop 1)
60 return $ Pandoc meta blocks
66 return $ Pandoc meta blocks
62instance ToLuaStack Meta where
68instance ToLuaStack Meta where
63 push (Meta mmap) =
69 push (Meta mmap) =
64 pushViaConstructor "Meta" mmap
70 pushViaConstructor "Meta" mmap
65instance FromLuaStack Meta where
71instance FromLuaStack Meta where
72+ peek idx = defineHowTo "get Meta value" $ do
73+ typeCheck idx Lua.TypeTable
66− peek idx = Meta <$> peek idx
74+ Meta <$> peek idx
68instance ToLuaStack MetaValue where
76instance ToLuaStack MetaValue where
69 push = pushMetaValue
77 push = pushMetaValue
@@ -160,7 +168,7 @@ pushMetaValue = \case
161-- | Interpret the value at the given stack index as meta value.
169-- | Interpret the value at the given stack index as meta value.
162peekMetaValue :: StackIndex -> Lua MetaValue
170peekMetaValue :: StackIndex -> Lua MetaValue
163−peekMetaValue idx = do
171+peekMetaValue idx = defineHowTo "get MetaValue" $ do
164 -- Get the contents of an AST element.
172 -- Get the contents of an AST element.
165 let elementContent :: FromLuaStack a => Lua a
173 let elementContent :: FromLuaStack a => Lua a
166 elementContent = peek idx
174 elementContent = peek idx
@@ -209,7 +217,8 @@ pushBlock = \case
210-- | Return the value at the given index as block if possible.
218-- | Return the value at the given index as block if possible.
211peekBlock :: StackIndex -> Lua Block
219peekBlock :: StackIndex -> Lua Block
212−peekBlock idx = do
220+peekBlock idx = defineHowTo "get Block value" $ do
221+ typeCheck idx Lua.TypeTable
213 tag <- getTag idx
222 tag <- getTag idx
214 case tag of
223 case tag of
215 "BlockQuote" -> BlockQuote <$> elementContent
224 "BlockQuote" -> BlockQuote <$> elementContent
@@ -260,7 +269,8 @@ pushInline = \case
261-- | Return the value at the given index as inline if possible.
270-- | Return the value at the given index as inline if possible.
262peekInline :: StackIndex -> Lua Inline
271peekInline :: StackIndex -> Lua Inline
263−peekInline idx = do
272+peekInline idx = defineHowTo "get Inline value" $ do
273+ typeCheck idx Lua.TypeTable
264 tag <- getTag idx
274 tag <- getTag idx
265 case tag of
275 case tag of
266 "Cite" -> uncurry Cite <$> elementContent
276 "Cite" -> uncurry Cite <$> elementContent
@@ -296,11 +306,7 @@ getTag idx = do
296 hasMT <- Lua.getmetatable idx
306 hasMT <- Lua.getmetatable idx
297 push "tag"
307 push "tag"
298 if hasMT then Lua.rawget (-2) else Lua.rawget (idx `adjustIndexBy` 1)
308 if hasMT then Lua.rawget (-2) else Lua.rawget (idx `adjustIndexBy` 1)
299− r <- tryLua (peek (-1))
300− Lua.settop top
309+ peek Lua.stackTop `finally` Lua.settop top
302− Left (Lua.LuaException err) -> throwLuaError err
303− Right res -> return res
305withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
311withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
306withAttr f (attributes, x) = f (fromLuaAttr attributes) x
312withAttr f (attributes, x) = f (fromLuaAttr attributes) x
@@ -313,7 +319,7 @@ instance ToLuaStack LuaAttr where
313 pushViaConstructor "Attr" id' classes kv
319 pushViaConstructor "Attr" id' classes kv
315instance FromLuaStack LuaAttr where
321instance FromLuaStack LuaAttr where
316− peek idx = LuaAttr <$> peek idx
322+ peek idx = defineHowTo "get Attr value" (LuaAttr <$> peek idx)
319-- Hierarchical elements
325-- Hierarchical elements