implement caching in groupthm

This commit is contained in:
Maximilian Keßler 2022-02-02 22:34:39 +01:00
parent 64fbca35dd
commit f1dacf4a5d

View file

@ -23,7 +23,7 @@
% https://www.latex-project.org/lppl.txt % 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> %<*driver>
\documentclass[full,kernel]{l3doc} \documentclass[full,kernel]{l3doc}
@ -846,25 +846,16 @@
% %
% This is just a private wrapper around \cs{declaretheorem} of the \pkg{thmtools} package. % This is just a private wrapper around \cs{declaretheorem} of the \pkg{thmtools} package.
% %
% We additionally cache
%
% \begin{macrocode} % \begin{macrocode}
\cs_new:Npn \@@_thmtools_declare_theorem:nn #1 #2 \cs_new:Npn \@@_thmtools_declare_theorem:nn #1 #2
{ {
\tl_log:n { Declaring ~ thmtools ~ theorem ~ #2 } \tl_log:n { Declaring ~ thmtools ~ theorem ~ #2 }
\declaretheorem [ #1 ] { #2 } \declaretheorem [ #1 ] { #2 }
\bool_if:NT \g_@@_cache_bool \@@_cache:n
{ {
\hook_gput_code:nnn { enddocument / afterlastpage } { groupthm } \csname @@_thmtools_declare_theorem:nn \endcsname { #1 } { #2 }
{
\iow_now:cn { @auxout }
{
\ExplSyntaxOn
\hook_gput_code:nnn { @@ / auxfile define cached } { groupthm }
{
\@@_thmtools_declare_theorem:nn { #1 } { #2 }
}
\ExplSyntaxOff
}
}
} }
} }
\cs_generate_variant:Nn \@@_thmtools_declare_theorem:nn { V n } \cs_generate_variant:Nn \@@_thmtools_declare_theorem:nn { V n }
@ -982,10 +973,6 @@
\hook_new:n { @@/thmtools } \hook_new:n { @@/thmtools }
% \end{macrocode} % \end{macrocode}
% \begin{macrocode} % \begin{macrocode}
\hook_new:n { @@/document define cached }
\hook_new:n { @@/auxfile define cached }
% \end{macrocode}
% \begin{macrocode}
\hook_new:n { @@/groupsort } \hook_new:n { @@/groupsort }
% \end{macrocode} % \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} % \subsection{Key interface}
% As mentioned, all keys will set their corresponding local variables % As mentioned, all keys will set their corresponding local variables
% (containing \enquote{\texttt{_key_}} in their name) and store the % (containing \enquote{\texttt{_key_}} in their name) and store the
@ -1799,7 +1816,7 @@
{ \@@_Declarator: TheoremGroup } { \@@_Declarator: TheoremGroup }
{ O{} m } { O{} m }
{ {
\groupthm_do_cached:n \@@_lazy:n
{ {
\use:c { groupthm_#1 _group:nn } { ##1 } { ##2 } \use:c { groupthm_#1 _group:nn } { ##1 } { ##2 }
} }
@ -1857,7 +1874,7 @@
% \begin{macrocode} % \begin{macrocode}
\NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m } \NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m }
{ {
\groupthm_do_cached:n \@@_lazy:n
{ {
\groupthm_declare_group_rule:nnnn {#1} {#2} {#3} {#4} \groupthm_declare_group_rule:nnnn {#1} {#2} {#3} {#4}
} }
@ -1896,7 +1913,7 @@
% \begin{macrocode} % \begin{macrocode}
\NewDocumentCommand { \AddTheoremGroupParent } { m m } \NewDocumentCommand { \AddTheoremGroupParent } { m m }
{ {
\groupthm_do_cached:n \@@lazy:n
{ {
\groupthm_add_parent:nn { #1 } { #2 } \groupthm_add_parent:nn { #1 } { #2 }
} }
@ -1986,7 +2003,8 @@
% \begin{macrocode} % \begin{macrocode}
\NewDocumentCommand { \AppendToTheoremGroup } { O{} m } \NewDocumentCommand { \AppendToTheoremGroup } { O{} m }
{ {
\groupthm_do_cached:n { \@@lazy:n
{
\groupthm_append_to_group:nn { #1 } { #2 } \groupthm_append_to_group:nn { #1 } { #2 }
} }
} }
@ -2304,7 +2322,7 @@
{ \@@_Declarator: GroupedTheorem } { \@@_Declarator: GroupedTheorem }
{ s O{} m } { s O{} m }
{ {
\groupthm_do_cached:n \@@_lazy:n
{ {
\use:c { groupthm_#1_theorem:nnn } \use:c { groupthm_#1_theorem:nnn }
{ ##2 } { ##2 }
@ -2457,7 +2475,7 @@
{ \@@_Declarator: GroupedTheoremFamily } { \@@_Declarator: GroupedTheoremFamily }
{ s O{} m } { s O{} m }
{ {
\groupthm_do_cached:n \@@_lazy:n
{ {
\use:c { groupthm_#1_family:nnn } \use:c { groupthm_#1_family:nnn }
{ ##2 } { ##2 }
@ -2581,21 +2599,15 @@
\@@_sort_group_names: \@@_sort_group_names:
\end { __#1__groups_ \clist_use:Nn \l_@@_group_clist { _ } } \end { __#1__groups_ \clist_use:Nn \l_@@_group_clist { _ } }
} }
\bool_if:NT \g_@@_cache_bool % \end{macrocode}
{ %
\hook_gput_code:nnn { enddocument / afterlastpage } { groupthm } % Cache this definition for re-runs of \LaTeX.
{ %
\iow_now:cn { @auxout } % \begin{macrocode}
{ \@@_cache:n
\ExplSyntaxOn
\hook_gput_code:nnn { @@ / auxfile define cached } { groupthm }
{ {
\@@_define_family_options:nnnn { #1 } { #2 } { #3 } { #4 } \@@_define_family_options:nnnn { #1 } { #2 } { #3 } { #4 }
} }
\ExplSyntaxOff
}
}
}
} }
% \end{macrocode} % \end{macrocode}
% \end{macro} % \end{macro}
@ -2658,7 +2670,7 @@
{ \@@_Declarator: GroupedTheoremFamilyOptions } { \@@_Declarator: GroupedTheoremFamilyOptions }
{ s O{} m m m } { 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 } { starred ~ version }
\keys_set:nn { groupthm / theorem ~ family ~ options } { ##2 } \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} % \begin{macrocode}
\cs_new:Npn \groupthm_do_cached:n
{
\bool_if:NTF \g_@@_cache_bool \bool_if:NTF \g_@@_cache_bool
{ {
\hook_gput_code:nnn {@@/document define cached} { groupthm } % \end{macrocode}
} %
%
% \begin{macro}{\@@_write_auxout:n, \@@_write_auxout:x}
%
% Immediate write to aux file.
%
% \begin{macrocode}
\cs_new:Npn \@@_write_auxout:n
{ {
\use:n \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
{
\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{macrocode}
% \end{macro} % \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 % \begin{macro}{\@@_cache:n}
% problems when \LaTeX rereads the aux file a second time at the end % \begin{syntax}
% of the document, since we want no declarations there % \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}
\cs_new:Npn \@@_cache:n #1
{
\tl_set:Nn \l_tmpa_tl
{
{ #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} % \begin{macrocode}
\hook_gput_code:nnn { begindocument } { groupthm } \hook_gput_code:nnn { begindocument } { groupthm }
{ {
\bool_if:nTF \int_compare:nNnTF
{
\g_@@_cache_bool
&&
\int_compare_p:n
{
\g_@@_cache_version_aux_int < \g_@@_cache_version_document_int \g_@@_cache_version_aux_int < \g_@@_cache_version_document_int
} {
\tl_use:N \g_@@_lazy_document_tl
} }
{ {
\hook_use:n { @@ / document define cached } \tl_use:N \g_@@_lazy_auxfile_tl
}
{
\hook_use:n { @@ / auxfile define cached }
} }
} }
% \end{macrocode} % \end{macrocode}
% %
% %
% This code makes sure that in the next run of \LaTeX, when reading in the aux-file, % It remains to handle the non-caching case, in which
% before processing the rest of the groupthm aux file macros, % we only have to define \cs{@@_cache:n} and \cs{@@_lazy:n} to be simple
% we set the depth of the document cache version available so that we can % wrappers.
% query this value in the next run as soon as possible.
% %
% \begin{macrocode} % \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} % \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} % \begin{macrocode}
%</package> %</package>
% \end{macrocode} % \end{macrocode}