implement caching in groupthm
This commit is contained in:
parent
64fbca35dd
commit
f1dacf4a5d
1 changed files with 251 additions and 109 deletions
|
@ -23,7 +23,7 @@
|
|||
% https://www.latex-project.org/lppl.txt
|
||||
%
|
||||
% -----------------------------------------------------------------------
|
||||
%<package>\ProvidesExplPackage{groupthm}{2022/01/17}{0.0.1}{Grouped theorems.}
|
||||
%<package>\ProvidesExplPackage{groupthm}{2022/02/02}{0.0.2}{Grouped theorems.}
|
||||
%
|
||||
%<*driver>
|
||||
\documentclass[full,kernel]{l3doc}
|
||||
|
@ -846,25 +846,16 @@
|
|||
%
|
||||
% This is just a private wrapper around \cs{declaretheorem} of the \pkg{thmtools} package.
|
||||
%
|
||||
% We additionally cache
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_new:Npn \@@_thmtools_declare_theorem:nn #1 #2
|
||||
{
|
||||
\tl_log:n { Declaring ~ thmtools ~ theorem ~ #2 }
|
||||
\declaretheorem [ #1 ] { #2 }
|
||||
\bool_if:NT \g_@@_cache_bool
|
||||
\@@_cache:n
|
||||
{
|
||||
\hook_gput_code:nnn { enddocument / afterlastpage } { groupthm }
|
||||
{
|
||||
\iow_now:cn { @auxout }
|
||||
{
|
||||
\ExplSyntaxOn
|
||||
\hook_gput_code:nnn { @@ / auxfile define cached } { groupthm }
|
||||
{
|
||||
\@@_thmtools_declare_theorem:nn { #1 } { #2 }
|
||||
}
|
||||
\ExplSyntaxOff
|
||||
}
|
||||
}
|
||||
\csname @@_thmtools_declare_theorem:nn \endcsname { #1 } { #2 }
|
||||
}
|
||||
}
|
||||
\cs_generate_variant:Nn \@@_thmtools_declare_theorem:nn { V n }
|
||||
|
@ -982,10 +973,6 @@
|
|||
\hook_new:n { @@/thmtools }
|
||||
% \end{macrocode}
|
||||
% \begin{macrocode}
|
||||
\hook_new:n { @@/document define cached }
|
||||
\hook_new:n { @@/auxfile define cached }
|
||||
% \end{macrocode}
|
||||
% \begin{macrocode}
|
||||
\hook_new:n { @@/groupsort }
|
||||
% \end{macrocode}
|
||||
%
|
||||
|
@ -1109,6 +1096,36 @@
|
|||
%
|
||||
%
|
||||
%
|
||||
% \begin{variable}{\g_@@_lazy_document_tl, \g_@@_lazy_auxfile_tl}
|
||||
%
|
||||
% During the preamble, if in caching mode, we will collect definitions for
|
||||
% theorems in these token lists. At the beginning of the document, we select the
|
||||
% proper one.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\tl_new:N \g_@@_lazy_document_tl
|
||||
\tl_new:N \g_@@_lazy_auxfile_tl
|
||||
% \end{macrocode}
|
||||
% \end{variable}
|
||||
%
|
||||
%
|
||||
%
|
||||
% \begin{variable}{\g_@@_dump_auxfile_clist, \g_@@_dump_cache_clist}
|
||||
%
|
||||
% With these, we collect stuff written to the aux file at the end of the document
|
||||
%
|
||||
% The \cs{g_@@_dump_cache_clist} will be treated specially:
|
||||
% We will dump such that in a re-run of \LaTeX, the contents will
|
||||
% be available for execution in the \cs{g_@@_lazy_auxfile_tl}
|
||||
% \begin{macrocode}
|
||||
\clist_new:N \g_@@_dump_auxfile_clist
|
||||
\clist_new:N \g_@@_dump_cache_clist
|
||||
% \end{macrocode}
|
||||
% \end{variable}
|
||||
%
|
||||
%
|
||||
%
|
||||
%
|
||||
% \subsection{Key interface}
|
||||
% As mentioned, all keys will set their corresponding local variables
|
||||
% (containing \enquote{\texttt{_key_}} in their name) and store the
|
||||
|
@ -1799,7 +1816,7 @@
|
|||
{ \@@_Declarator: TheoremGroup }
|
||||
{ O{} m }
|
||||
{
|
||||
\groupthm_do_cached:n
|
||||
\@@_lazy:n
|
||||
{
|
||||
\use:c { groupthm_#1 _group:nn } { ##1 } { ##2 }
|
||||
}
|
||||
|
@ -1857,7 +1874,7 @@
|
|||
% \begin{macrocode}
|
||||
\NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m }
|
||||
{
|
||||
\groupthm_do_cached:n
|
||||
\@@_lazy:n
|
||||
{
|
||||
\groupthm_declare_group_rule:nnnn {#1} {#2} {#3} {#4}
|
||||
}
|
||||
|
@ -1896,7 +1913,7 @@
|
|||
% \begin{macrocode}
|
||||
\NewDocumentCommand { \AddTheoremGroupParent } { m m }
|
||||
{
|
||||
\groupthm_do_cached:n
|
||||
\@@lazy:n
|
||||
{
|
||||
\groupthm_add_parent:nn { #1 } { #2 }
|
||||
}
|
||||
|
@ -1986,7 +2003,8 @@
|
|||
% \begin{macrocode}
|
||||
\NewDocumentCommand { \AppendToTheoremGroup } { O{} m }
|
||||
{
|
||||
\groupthm_do_cached:n {
|
||||
\@@lazy:n
|
||||
{
|
||||
\groupthm_append_to_group:nn { #1 } { #2 }
|
||||
}
|
||||
}
|
||||
|
@ -2304,7 +2322,7 @@
|
|||
{ \@@_Declarator: GroupedTheorem }
|
||||
{ s O{} m }
|
||||
{
|
||||
\groupthm_do_cached:n
|
||||
\@@_lazy:n
|
||||
{
|
||||
\use:c { groupthm_#1_theorem:nnn }
|
||||
{ ##2 }
|
||||
|
@ -2457,7 +2475,7 @@
|
|||
{ \@@_Declarator: GroupedTheoremFamily }
|
||||
{ s O{} m }
|
||||
{
|
||||
\groupthm_do_cached:n
|
||||
\@@_lazy:n
|
||||
{
|
||||
\use:c { groupthm_#1_family:nnn }
|
||||
{ ##2 }
|
||||
|
@ -2581,21 +2599,15 @@
|
|||
\@@_sort_group_names:
|
||||
\end { __#1__groups_ \clist_use:Nn \l_@@_group_clist { _ } }
|
||||
}
|
||||
\bool_if:NT \g_@@_cache_bool
|
||||
{
|
||||
\hook_gput_code:nnn { enddocument / afterlastpage } { groupthm }
|
||||
{
|
||||
\iow_now:cn { @auxout }
|
||||
{
|
||||
\ExplSyntaxOn
|
||||
\hook_gput_code:nnn { @@ / auxfile define cached } { groupthm }
|
||||
% \end{macrocode}
|
||||
%
|
||||
% Cache this definition for re-runs of \LaTeX.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\@@_cache:n
|
||||
{
|
||||
\@@_define_family_options:nnnn { #1 } { #2 } { #3 } { #4 }
|
||||
}
|
||||
\ExplSyntaxOff
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
|
@ -2658,7 +2670,7 @@
|
|||
{ \@@_Declarator: GroupedTheoremFamilyOptions }
|
||||
{ s O{} m m m }
|
||||
{
|
||||
\groupthm_do_cached:n
|
||||
\@@_lazy:n
|
||||
{
|
||||
\keys_set:nn { groupthm / theorem ~ family ~ options } { starred ~ version }
|
||||
\keys_set:nn { groupthm / theorem ~ family ~ options } { ##2 }
|
||||
|
@ -2697,90 +2709,220 @@
|
|||
%
|
||||
%
|
||||
%
|
||||
% We differentiate between caching and non-caching mode here.
|
||||
% First, we provide some wrappers for writing to the aux file:
|
||||
%
|
||||
%
|
||||
% \begin{macro}{\groupthm_do_cached:n}
|
||||
% \begin{syntax}
|
||||
% \cs{groupthm_do_cached:n}\marg{code}
|
||||
% \end{syntax}
|
||||
%
|
||||
% Executes this code lazy at beginning of the document,
|
||||
% iff caching is active.
|
||||
%
|
||||
% At beginning of document, code will be only executed
|
||||
% if the aux file version was too old, otherwise dropped.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_new:Npn \groupthm_do_cached:n
|
||||
\bool_if:NTF \g_@@_cache_bool
|
||||
{
|
||||
\bool_if:NTF \g_@@_cache_bool
|
||||
% \end{macrocode}
|
||||
%
|
||||
%
|
||||
% \begin{macro}{\@@_write_auxout:n, \@@_write_auxout:x}
|
||||
%
|
||||
% Immediate write to aux file.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_new:Npn \@@_write_auxout:n
|
||||
{
|
||||
\hook_gput_code:nnn {@@/document define cached} { groupthm }
|
||||
\iow_now:cn { @auxout }
|
||||
}
|
||||
\cs_generate_variant:Nn \@@_write_auxout:n { x }
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
%
|
||||
%
|
||||
% \begin{macro}{\@@_dump_auxfile:n}
|
||||
%
|
||||
% Dump to auxfile at end of document.
|
||||
% This is used to dump to the aux file at any point of the document
|
||||
% without messing with preamble / document treatment etc.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_new:Npn \@@_dump_auxfile:n
|
||||
{
|
||||
\use:n
|
||||
\clist_gput_right:Nn \g_@@_dump_auxfile_clist
|
||||
}
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
|
||||
|
||||
% \begin{macro}{\@@_cache_auxfile:n, \@@_cache_auxfile:V}
|
||||
%
|
||||
%
|
||||
% This also pipes data through the auxfile,
|
||||
% but will cache it to make it available in the next run.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_new:Npn \@@_cache_auxfile:n
|
||||
{
|
||||
\clist_gput_right:Nn \g_@@_dump_cache_clist
|
||||
}
|
||||
\cs_generate_variant:NN \@@_cache_auxfile:n { V }
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
|
||||
|
||||
% This handles the dumping to the auxfile at the end of the document:
|
||||
% \begin{macrocode}
|
||||
\hook_gput_code:nnn { enddocument } { groupthm }
|
||||
{
|
||||
% \end{macrocode}
|
||||
% First, perform the regular dump:
|
||||
% \begin{macrocode}
|
||||
\clist_map_function:NN \g_@@_dump_auxfile_clist
|
||||
\_@@_write_auxout:n
|
||||
|
||||
% \end{macrocode}
|
||||
% Now, we want to dump the cached clist, but wrap it into the
|
||||
% the corresponding macro call for storing it in
|
||||
% \cs{g_@@_lazy_auxfile_tl} on re-reading the auxfile.
|
||||
% For this, we have to put two single braces into the auxfile
|
||||
% separately
|
||||
% \begin{macrocode}
|
||||
\_@@_write_auxout:n
|
||||
{
|
||||
\csname tl_gput_right:cn \endcsname
|
||||
{
|
||||
g_@@_lazy_auxfile_tl
|
||||
}
|
||||
}
|
||||
\_@@_write_auxout:x { \str_use:N \c_left_brace_str }
|
||||
% \end{macrocode}
|
||||
% Now, dump the list
|
||||
% \begin{macrocode}
|
||||
\clist_map_function:NN \g_@@_dump_cache_clist
|
||||
\_@@_write_auxout:n
|
||||
|
||||
\_@@_write_auxout:x { \str_use:N \c_right_brace_str }
|
||||
}
|
||||
% \end{macrocode}
|
||||
|
||||
|
||||
% This makes sure that we restore the cache version
|
||||
% on the next run of LaTeX
|
||||
% \begin{macrocode}
|
||||
\_@@_dump_auxfile:x
|
||||
{
|
||||
\ExplSyntaxOn
|
||||
\int_gset:Nn \exp_not:N \g_@@_cache_version_aux_int
|
||||
{
|
||||
\int_use:N \g_@@_cache_version_document_int
|
||||
}
|
||||
\ExplSyntaxOff
|
||||
}
|
||||
% \end{macrocode}
|
||||
%
|
||||
%
|
||||
% We can now provide the two main macros responsible for the caching feature.
|
||||
%
|
||||
% \begin{macro}{\@@_lazy:n}
|
||||
% \begin{syntax}
|
||||
% \cs{@@_lazy:n}\marg{code}
|
||||
% \end{syntax}
|
||||
%
|
||||
% Lazy execution will just append to the corresponding token list
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_new:Npn \@@_lazy:n
|
||||
{
|
||||
\tl_gput_right:Nn \g_@@_lazy_document_tl
|
||||
}
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
%
|
||||
%
|
||||
%
|
||||
% This makes sure that at the beginning of the document, after reading
|
||||
% in the aux file with possible precomputed definitions of the last run,
|
||||
% we will execute either the definitions of the auxfile or all the
|
||||
% lazy computation from the current run that we collected.
|
||||
%
|
||||
% These hooks should actually be one-time hooks, but this would cause
|
||||
% problems when \LaTeX rereads the aux file a second time at the end
|
||||
% of the document, since we want no declarations there
|
||||
% \begin{macro}{\@@_cache:n}
|
||||
% \begin{syntax}
|
||||
% \cs{@@_cache:n}\marg{code}
|
||||
% \end{syntax}
|
||||
%
|
||||
% We have to replace parameter-tokens of category code 6
|
||||
% with regular \enquote{\#} tokens of category code 12
|
||||
% so that we don't double them when writing to the aux file.
|
||||
% See
|
||||
% \href
|
||||
% {https://tex.stackexchange.com/questions/632294/writing-nested-argument-specifier-to-aux-file}
|
||||
% {https://tex.stackexchange.com/questions/632294/writing-nested-argument-specifier-to-aux-file}
|
||||
% for details.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\hook_gput_code:nnn { begindocument } { groupthm }
|
||||
\cs_new:Npn \@@_cache:n #1
|
||||
{
|
||||
\bool_if:nTF
|
||||
\tl_set:Nn \l_tmpa_tl
|
||||
{
|
||||
\g_@@_cache_bool
|
||||
&&
|
||||
\int_compare_p:n
|
||||
{ #1 }
|
||||
}
|
||||
\regex_replace_all:nnN { \cP\# } { \cO\# } \l_tmpa_tl
|
||||
\@@_dump_cache:V \l_tmpa_tl
|
||||
}
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
%
|
||||
%
|
||||
%
|
||||
% Finally, at the beginning of the document, call the correct code for execution
|
||||
% \begin{macrocode}
|
||||
\hook_gput_code:nnn { begindocument } { groupthm }
|
||||
{
|
||||
\int_compare:nNnTF
|
||||
\g_@@_cache_version_aux_int < \g_@@_cache_version_document_int
|
||||
}
|
||||
{
|
||||
\tl_use:N \g_@@_lazy_document_tl
|
||||
}
|
||||
{
|
||||
\hook_use:n { @@ / document define cached }
|
||||
}
|
||||
{
|
||||
\hook_use:n { @@ / auxfile define cached }
|
||||
\tl_use:N \g_@@_lazy_auxfile_tl
|
||||
}
|
||||
}
|
||||
% \end{macrocode}
|
||||
%
|
||||
%
|
||||
% This code makes sure that in the next run of \LaTeX, when reading in the aux-file,
|
||||
% before processing the rest of the groupthm aux file macros,
|
||||
% we set the depth of the document cache version available so that we can
|
||||
% query this value in the next run as soon as possible.
|
||||
% It remains to handle the non-caching case, in which
|
||||
% we only have to define \cs{@@_cache:n} and \cs{@@_lazy:n} to be simple
|
||||
% wrappers.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\bool_if:NT \g_@@_cache_bool
|
||||
{
|
||||
\hook_gput_code:nnn { enddocument / afterlastpage } { before-groupthm }
|
||||
{
|
||||
\iow_now:cx { @auxout }
|
||||
{
|
||||
\token_to_str:N \ExplSyntaxOn
|
||||
\int_gset:Nn \g_@@_cache_version_aux_int
|
||||
{ \int_use:N \g_@@_cache_version_document_int }
|
||||
\token_to_str:N \ExplSyntaxOff
|
||||
}
|
||||
}
|
||||
}
|
||||
\hook_gset_rule:nnnn { enddocument / afterlastpage } { before-groupthm } { before } { groupthm }
|
||||
{
|
||||
% \end{macrocode}
|
||||
%
|
||||
%
|
||||
%
|
||||
%
|
||||
%
|
||||
% \begin{macro}{\@@_cache:n}
|
||||
%
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_set_eq:NN \@@_cache:n \use_none:n
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
%
|
||||
%
|
||||
% \begin{macro}{\@@_lazy:n}
|
||||
%
|
||||
%
|
||||
%
|
||||
% \begin{macrocode}
|
||||
\cs_set_eq:NN \@@_lazy:n \use:n
|
||||
% \end{macrocode}
|
||||
% \end{macro}
|
||||
%
|
||||
%
|
||||
% This ends the non-caching case.
|
||||
%
|
||||
% \begin{macrocode}
|
||||
}
|
||||
% \end{macrocode}
|
||||
%
|
||||
%
|
||||
%
|
||||
%
|
||||
%
|
||||
% \begin{macrocode}
|
||||
%</package>
|
||||
% \end{macrocode}
|
||||
|
|
Loading…
Reference in a new issue