diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx | 128 |
1 files changed, 122 insertions, 6 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index ac63d0f89a3..918f36c3acf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -370,9 +370,47 @@ local scan_int = token.scan_int or token.scan_integer local scan_string = token.scan_string local scan_keyword = token.scan_keyword local put_next = token.put_next +local token_create = token.create +% \end{macrocode} +% +% Since token.create only returns useful values after the tokens +% has been added to TeX's hash table, we define a variant which +% defines it first if necessary. +% \begin{macrocode} +local token_create_safe +do + local is_defined = token.is_defined + local set_char = token.set_char + local runtoks = tex.runtoks + local let_token = token_create'let' -local true_tok = token.create'prg_return_true:' -local false_tok = token.create'prg_return_false:' + function token_create_safe(s) + local orig_token = token_create(s) + if is_defined(s, true) then + return orig_token + end + set_char(s, 0) + local new_token = token_create(s) + runtoks(function() + put_next(let_token, new_token, orig_token) + end) + return new_token + end +end + +local true_tok = token_create_safe'prg_return_true:' +local false_tok = token_create_safe'prg_return_false:' +% \end{macrocode} +% In Con\TeX{}t lmtx \texttt{token.command_id} does not exist, +% but it can easily be emulated with Con\TeX{}t's \texttt{tokens.commands}. +% \begin{macrocode} +local command_id = token.command_id +if not command_id and tokens and tokens.commands then + local id_map = tokens.commands + function command_id(name) + return id_map[name] + end +end % \end{macrocode} % % \begin{macrocode} @@ -642,9 +680,8 @@ end) % a function instead of an index into the functions table. % \begin{macrocode} local luacmd do - local token_create = token.create local set_lua = token.set_lua - local undefined_cs = token.command_id'undefined_cs' + local undefined_cs = command_id'undefined_cs' if not context and not luatexbase then require'ltluatex' end if luatexbase then @@ -665,7 +702,7 @@ local luacmd do local register = context.functions.register local functions = context.functions.known function luacmd(name, func, ...) - local tok = token.create(name) + local tok = token_create(name) if tok.command == undefined_cs then token.set_lua(name, register(func), ...) else @@ -677,6 +714,85 @@ end % \end{macrocode} % \end{macro} % +% \subsection{Preserving iniTeX Lua data for runs} +% +% \begin{macrocode} +%<@@=lua> +% \end{macrocode} +% +% The Lua state is not dumped when a forat is written, therefore any Lua +% variables filled doing format building need to be restored in order to +% be accessible during normal runs. +% +% We provide some kernel-internal helpers for this. They will only be available if +% \texttt{luatexbase} is available. This is not a big restriction though, because +% Con\TeX{}t (which does not use \texttt{luatexbase}) does not load \pkg{expl3} +% in the format. +% +% \begin{macrocode} +local register_luadata, get_luadata + +if luatexbase then + local register = token_create'@expl@luadata@bytecode'.index + if status.ini_version then +% \end{macrocode} +% +% \begin{macro}{register_luadata} +% \texttt{register_luadata} is only available during format generation. +% It accept a string which uniquely identifies the data object and has to be +% provided to retrieve it later. Additionally it accepts a function which is +% called in the \texttt{pre_dump} callback and which has to return a string that +% evaluates to a valid Lua object to be preserved. +% \begin{macrocode} + local luadata, luadata_order = {}, {} + + function register_luadata(name, func) + if luadata[name] then + error(format("LaTeX error: data name %q already in use", name)) + end + luadata[name] = func + luadata_order[#luadata_order + 1] = func and name + end +% \end{macrocode} +% \end{macro} +% +% The actual work is done in \texttt{pre_dump}. The \texttt{luadata_order} is used +% to ensure that the order is consistent over multiple runs. +% \begin{macrocode} + luatexbase.add_to_callback("pre_dump", function() + if next(luadata) then + local str = "return {" + for i=1, #luadata_order do + local name = luadata_order[i] + str = format('%s[%q]=%s,', str, name, luadata[name]()) + end + lua.bytecode[register] = assert(load(str .. "}")) + end + end, "ltx.luadata") + else +% \end{macrocode} +% +% \begin{macro}{get_luadata} +% \texttt{get_luadata} is only available if data should be restored. +% It accept the identifier which was used when the data object was registered and +% returns the associated object. Every object can only be retrieved once. +% \begin{macrocode} + local luadata = lua.bytecode[register] + if luadata then + lua.bytecode[register] = nil + luadata = luadata() + end + function get_luadata(name) + if not luadata then return end + local data = luadata[name] + luadata[name] = nil + return data + end + end +end +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} %</lua> % \end{macrocode} |