@@ -49,6 +49,7 @@ import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
4949import qualified Foreign.Lua as Lua
5050import qualified Foreign.Lua.Module.Text as Lua
5151import qualified Text.Pandoc.Definition as Pandoc
52+import qualified Text.Pandoc.Lua.Module.Pandoc as ModulePandoc
5253
5354-- | Lua error message
5455newtype LuaException = LuaException String deriving (Show)
@@ -95,16 +96,37 @@ luaPackageParams = do
9596
9697-- | Initialize the lua state with all required values
9798initLuaState :: LuaPackageParams -> Lua ()
98−initLuaState luaPkgParams = do
99+initLuaState pkgParams = do
99100 Lua.openlibs
100101 Lua.preloadTextModule "text"
101− installPandocPackageSearcher luaPkgParams
102− loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
103− putConstructorsInRegistry
102+ installPandocPackageSearcher pkgParams
103+ initPandocModule
104+ loadScriptFromDataDir (luaPkgDataDir pkgParams) "init.lua"
105+ where
106+ initPandocModule :: Lua ()
107+ initPandocModule = do
108+ -- Push module table
109+ ModulePandoc.pushModule (luaPkgDataDir pkgParams)
110+ -- register as loaded module
111+ Lua.pushvalue Lua.stackTop
112+ Lua.getfield Lua.registryindex Lua.loadedTableRegistryField
113+ Lua.setfield (Lua.nthFromTop 2) "pandoc"
114+ Lua.pop 1
115+ -- copy constructors into registry
116+ putConstructorsInRegistry
117+ -- assign module to global variable
118+ Lua.setglobal "pandoc"
104119
120+-- | AST elements are marshaled via normal constructor functions in the
121+-- @pandoc@ module. However, accessing Lua globals from Haskell is
122+-- expensive (due to error handling). Accessing the Lua registry is much
123+-- cheaper, which is why the constructor functions are copied into the
124+-- Lua registry and called from there.
125+--
126+-- This function expects the @pandoc@ module to be at the top of the
127+-- stack.
105128putConstructorsInRegistry :: Lua ()
106129putConstructorsInRegistry = do
107− Lua.getglobal "pandoc"
108130 constrsToReg $ Pandoc.Pandoc mempty mempty
109131 constrsToReg $ Pandoc.Str mempty
110132 constrsToReg $ Pandoc.Para mempty
@@ -113,7 +135,6 @@ putConstructorsInRegistry = do
113135 constrsToReg $ Pandoc.Citation mempty mempty mempty Pandoc.AuthorInText 0 0
114136 putInReg "Attr" -- used for Attr type alias
115137 putInReg "ListAttributes" -- used for ListAttributes type alias
116− Lua.pop 1
117138 where
118139 constrsToReg :: Data a => a -> Lua ()
119140 constrsToReg = mapM_ (putInReg . showConstr) . dataTypeConstrs . dataTypeOf