git.iko.soy/typeable/pandoc
on master help sign in
Text.Pandoc.Lua: more code simplification.

Also, now we check before running walkM that the function table actually does contain something relevant. E.g. if your filter just defines Str, there's no need to run walkM for blocks, meta, or the whole document. This should help performance a bit (and it does, in my tests).

commitcb25326fa313690c3c67caa2a8b44642409fd24c authorJohn MacFarlane <jgm@berkeley.edu> dateThu 29 Jun 2017, 17:07 (9 years ago) parent780a65f
1 file changed+26−30
src/Text/Pandoc/Lua.hs+26−30
src/Text/Pandoc/Lua.hs+26−30
@@ -2,6 +2,7 @@
22{-# LANGUAGE FlexibleInstances #-}
33{-# LANGUAGE MultiParamTypeClasses #-}
44{-# LANGUAGE DeriveDataTypeable #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
56{-
67Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
78
@@ -34,10 +35,11 @@ module Text.Pandoc.Lua ( LuaException(..),
3435 pushPandocModule ) where
3536
3637import Control.Exception
37−import Control.Monad (unless, when, (>=>))
38+import Control.Monad (unless, when, (>=>), mplus)
3839import Control.Monad.Trans (MonadIO (..))
39−import Data.Data (toConstr)
40+import Data.Data (toConstr, showConstr, dataTypeOf, dataTypeConstrs, Data)
4041import Data.Map (Map)
42+import Data.Maybe (isJust)
4143import Data.Typeable (Typeable)
4244import Scripting.Lua (LuaState, StackValue (..))
4345import Text.Pandoc.Definition
@@ -91,44 +93,38 @@ runAll = foldr ((>=>) . walkMWithLuaFilter) return
9193
9294walkMWithLuaFilter :: LuaFilter -> Pandoc -> IO Pandoc
9395walkMWithLuaFilter (LuaFilter lua fnMap) =
94− walkM (execInlineLuaFilter lua fnMap) >=>
95− walkM (execBlockLuaFilter lua fnMap) >=>
96− walkM (execMetaLuaFilter lua fnMap) >=>
97− walkM (execDocLuaFilter lua fnMap)
96+ (if hasOneOf (constructorsFor (dataTypeOf (Str [])))
97+ then walkM (tryFilter lua fnMap :: Inline -> IO Inline)
98+ else return)
99+ >=>
100+ (if hasOneOf (constructorsFor (dataTypeOf (Para [])))
101+ then walkM (tryFilter lua fnMap :: Block -> IO Block)
102+ else return)
103+ >=>
104+ (case Map.lookup "Meta" fnMap of
105+ Just fn -> walkM (\(Pandoc meta blocks) -> do
106+ meta' <- runFilterFunction lua fn meta
107+ return $ Pandoc meta' blocks)
108+ Nothing -> return)
109+ >=>
110+ (case Map.lookup "Pandoc" fnMap `mplus` Map.lookup "Doc" fnMap of
111+ Just fn -> (runFilterFunction lua fn) :: Pandoc -> IO Pandoc
112+ Nothing -> return)
113+ where hasOneOf = any (\k -> isJust (Map.lookup k fnMap))
114+ constructorsFor x = map show (dataTypeConstrs x)
98115
99116type FunctionMap = Map String LuaFilterFunction
100117data LuaFilter = LuaFilter LuaState FunctionMap
101118
102119newtype LuaFilterFunction = LuaFilterFunction { functionIndex :: Int }
103120
104−tryFilter :: StackValue a => LuaState -> FunctionMap -> String -> a -> IO a
105−tryFilter lua fnMap filterFnName x =
121+tryFilter :: (Data a, StackValue a) => LuaState -> FunctionMap -> a -> IO a
122+tryFilter lua fnMap x =
123+ let filterFnName = showConstr (toConstr x) in
106124 case Map.lookup filterFnName fnMap of
107125 Nothing -> return x
108126 Just fn -> runFilterFunction lua fn x
109127
110−execDocLuaFilter :: LuaState
111− -> FunctionMap
112− -> Pandoc -> IO Pandoc
113−execDocLuaFilter lua fnMap = tryFilter lua fnMap "Doc"
114−
115−execMetaLuaFilter :: LuaState
116− -> FunctionMap
117− -> Pandoc -> IO Pandoc
118−execMetaLuaFilter lua fnMap (Pandoc meta blks) = do
119− meta' <- tryFilter lua fnMap "Meta" meta
120− return $ Pandoc meta' blks
121−
122−execBlockLuaFilter :: LuaState
123− -> FunctionMap
124− -> Block -> IO Block
125−execBlockLuaFilter lua fnMap x = tryFilter lua fnMap (show (toConstr x)) x
126−
127−execInlineLuaFilter :: LuaState
128− -> FunctionMap
129− -> Inline -> IO Inline
130−execInlineLuaFilter lua fnMap x = tryFilter lua fnMap (show (toConstr x)) x
131−
132128instance StackValue LuaFilter where
133129 valuetype _ = Lua.TTABLE
134130 push = undefined