aboutsummaryrefslogtreecommitdiff
path: root/src/Text/Pandoc
diff options
context:
space:
mode:
authorAlbert Krewinkel <albert@zeitkraut.de>2017-04-06 00:02:33 +0200
committerAlbert Krewinkel <albert@zeitkraut.de>2017-04-06 19:25:42 +0200
commitdd00163a35a9c1aa9ddc58b720919a6219c87a17 (patch)
tree891add6e83db6d0719e3cd84b9d652a374292f01 /src/Text/Pandoc
parentfca93efb624af48a212a4597a116bfcde8b7192f (diff)
downloadpandoc-dd00163a35a9c1aa9ddc58b720919a6219c87a17.tar.gz
Lua filter: Improve inline filter performance
Getting inline instances from the lua stack is handled manually for some simple inline constructors, including the `Str` constructor. This avoids the indirect route through aeson's Value type and improves performance considerably (approx. 30% speedup for some filters).
Diffstat (limited to 'src/Text/Pandoc')
-rw-r--r--src/Text/Pandoc/Lua/StackInstances.hs80
1 files changed, 73 insertions, 7 deletions
diff --git a/src/Text/Pandoc/Lua/StackInstances.hs b/src/Text/Pandoc/Lua/StackInstances.hs
index 0c9addc23..59c5ec6b5 100644
--- a/src/Text/Pandoc/Lua/StackInstances.hs
+++ b/src/Text/Pandoc/Lua/StackInstances.hs
@@ -36,7 +36,7 @@ StackValue instances for pandoc types.
module Text.Pandoc.Lua.StackInstances () where
import Data.Aeson ( FromJSON(..), ToJSON(..), Result(..), Value, fromJSON )
-import Scripting.Lua ( StackValue(..) )
+import Scripting.Lua ( LuaState, StackValue(..), newtable, pop, rawget, rawset )
import Scripting.Lua.Aeson ()
import Text.Pandoc.Definition ( Block(..), Inline(..), Pandoc(..) )
@@ -59,8 +59,20 @@ instance StackValue Block where
valuetype _ = Lua.TTABLE
instance StackValue Inline where
- push lua = Lua.push lua . toJSON
- peek lua i = maybeFromJson <$> peek lua i
+ push lua = \case
+ Emph inlns -> pushTagged lua "Emph" inlns
+ LineBreak -> pushTagged' lua "LineBreak"
+ Note blcks -> pushTagged lua "Note" blcks
+ SmallCaps inlns -> pushTagged lua "SmallCaps" inlns
+ SoftBreak -> pushTagged' lua "SoftBreak"
+ Space -> pushTagged' lua "Space"
+ Str s -> pushTagged lua "Str" s
+ Strikeout inlns -> pushTagged lua "Strikeout" inlns
+ Strong inlns -> pushTagged lua "Strong" inlns
+ Subscript inlns -> pushTagged lua "Subscript" inlns
+ Superscript inlns -> pushTagged lua "Superscript" inlns
+ x -> push lua (toJSON x)
+ peek = peekInline
valuetype _ = Lua.TTABLE
#if MIN_VERSION_base(4,8,0)
@@ -68,8 +80,62 @@ instance {-# OVERLAPS #-} StackValue [Char] where
#else
instance StackValue [Char] where
#endif
- push lua cs = Lua.push lua (UTF8.fromString cs)
- peek lua i = do
- res <- Lua.peek lua i
- return $ UTF8.toString `fmap` res
+ push lua cs = push lua (UTF8.fromString cs)
+ peek lua i = fmap UTF8.toString <$> peek lua i
valuetype _ = Lua.TSTRING
+
+-- | Push a value to the lua stack, tagged with a given string. This currently
+-- creates a structure equivalent to what the JSONified value would look like
+-- when pushed to lua.
+pushTagged :: StackValue a => LuaState -> String -> a -> IO ()
+pushTagged lua tag value = do
+ newtable lua
+ push lua "t"
+ push lua tag
+ rawset lua (-3)
+ push lua "c"
+ push lua value
+ rawset lua (-3)
+
+pushTagged' :: LuaState -> String -> IO ()
+pushTagged' lua tag = do
+ newtable lua
+ push lua "t"
+ push lua tag
+ rawset lua (-3)
+
+-- | Return the value at the given index as inline if possible.
+peekInline :: LuaState -> Int -> IO (Maybe Inline)
+peekInline lua idx = do
+ push lua "t"
+ rawget lua (idx `adjustIndexBy` 1)
+ tag <- peek lua (-1) <* pop lua 1
+ case tag of
+ Nothing -> return Nothing
+ Just t -> case t of
+ "Emph" -> fmap Emph <$> elementContent
+ "LineBreak" -> return (Just LineBreak)
+ "Note" -> fmap Note <$> elementContent
+ "SmallCaps" -> fmap SmallCaps <$> elementContent
+ "SoftBreak" -> return (Just SoftBreak)
+ "Space" -> return (Just Space)
+ "Str" -> fmap Str <$> elementContent
+ "Strikeout" -> fmap Strikeout <$> elementContent
+ "Strong" -> fmap Strong <$> elementContent
+ "Subscript" -> fmap Subscript <$> elementContent
+ "Superscript"-> fmap Superscript <$> elementContent
+ _ -> maybeFromJson <$> peek lua idx
+ where
+ elementContent :: StackValue a => IO (Maybe a)
+ elementContent = do
+ push lua "c"
+ rawget lua (idx `adjustIndexBy` 1)
+ peek lua (-1) <* pop lua 1
+
+-- | Adjust the stack index, assuming that @n@ new elements have been pushed on
+-- the stack.
+adjustIndexBy :: Int -> Int -> Int
+adjustIndexBy idx n =
+ if idx < 0
+ then idx - n
+ else idx