diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3seq.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3seq.dtx | 230 |
1 files changed, 125 insertions, 105 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index 95dddce8afa..0a8c475fd57 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3seq.dtx Copyright (C) 1990-2017 The LaTeX3 Project +%% File: l3seq.dtx Copyright (C) 1990-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/03/05} +% \date{Released 2018-04-30} % % \maketitle % @@ -855,40 +855,6 @@ % Writes the entries in the \meta{sequence} in the log file. % \end{function} % -% \section{Internal sequence functions} -% -% \begin{variable}{\s__seq} -% This scan mark (equal to \cs{scan_stop:}) marks the beginning of a -% sequence variable. -% \end{variable} -% -% \begin{function}[EXP]{\__seq_item:n} -% \begin{syntax} -% \cs{__seq_item:n} \Arg{item} -% \end{syntax} -% The internal token used to begin each sequence entry. If expanded -% outside of a mapping or manipulation function, an error is -% raised. The definition should always be set globally. -% \end{function} -% -% \begin{function}{\__seq_push_item_def:n, \__seq_push_item_def:x} -% \begin{syntax} -% \cs{__seq_push_item_def:n} \Arg{code} -% \end{syntax} -% Saves the definition of \cs{__seq_item:n} and redefines it to -% accept one parameter and expand to \meta{code}. This function -% should always be balanced by use of \cs{__seq_pop_item_def:}. -% \end{function} -% -% \begin{function}{\__seq_pop_item_def:} -% \begin{syntax} -% \cs{__seq_pop_item_def:} -% \end{syntax} -% Restores the definition of \cs{__seq_item:n} most recently saved by -% \cs{__seq_push_item_def:n}. This function should always be used in -% a balanced pair with \cs{__seq_push_item_def:n}. -% \end{function} -% % \end{documentation} % % \begin{implementation} @@ -913,10 +879,40 @@ % \meta{item_1} \cs{seq_elt_end:} \ldots \cs{seq_elt:w} \meta{item_n} % \cs{seq_elt_end:}}. This allowed rapid searching using a delimited % function, but was not suitable for items containing |{|, |}| and |#| -% tokens, and also lead to the loss of surrounding braces around items. +% tokens, and also lead to the loss of surrounding braces around items +% +% \begin{function}[EXP]{\@@_item:n} +% \begin{syntax} +% \cs{@@_item:n} \Arg{item} +% \end{syntax} +% The internal token used to begin each sequence entry. If expanded +% outside of a mapping or manipulation function, an error is +% raised. The definition should always be set globally. +% \end{function} +% +% \begin{function}{\@@_push_item_def:n, \@@_push_item_def:x} +% \begin{syntax} +% \cs{@@_push_item_def:n} \Arg{code} +% \end{syntax} +% Saves the definition of \cs{@@_item:n} and redefines it to +% accept one parameter and expand to \meta{code}. This function +% should always be balanced by use of \cs{@@_pop_item_def:}. +% \end{function} +% +% \begin{function}{\@@_pop_item_def:} +% \begin{syntax} +% \cs{@@_pop_item_def:} +% \end{syntax} +% Restores the definition of \cs{@@_item:n} most recently saved by +% \cs{@@_push_item_def:n}. This function should always be used in +% a balanced pair with \cs{@@_push_item_def:n}. +% \end{function} % % \begin{variable}{\s_@@} -% The variable is defined in the \pkg{l3quark} module, loaded later. +% This private scan mark. +% \begin{macrocode} +\scan_new:N \s_@@ +% \end{macrocode} % \end{variable} % % \begin{macro}{\@@_item:n} @@ -962,7 +958,7 @@ % \begin{macrocode} \cs_new_protected:Npn \seq_new:N #1 { - \__chk_if_free_cs:N #1 + \__kernel_chk_if_free_cs:N #1 \cs_gset_eq:NN #1 \c_empty_seq } \cs_generate_variant:Nn \seq_new:N { c } @@ -1451,10 +1447,10 @@ #1 \group_end: \prg_return_false: - \__prg_break_point: + \prg_break_point: } \cs_new:Npn \@@_if_in: - { \__prg_break:n { \group_end: \prg_return_true: } } + { \prg_break:n { \group_end: \prg_return_true: } } \prg_generate_conditional_variant:Nnn \seq_if_in:Nn { NV , Nv , No , Nx , c , cV , cv , co , cx } { T , F , TF } % \end{macrocode} @@ -1542,30 +1538,29 @@ % % \begin{macro}{\seq_get_right:NN, \seq_get_right:cN} % \UnitTested -% \begin{macro}{\@@_get_right_loop:nn} -% First remove \cs{s_@@} and prepend \cs{q_no_value}, then take two -% arguments at a time. Before the right-hand end of the sequence, -% this is a brace group followed by \cs{@@_item:n}, both removed by -% \cs{use_none:nn}. At the end of the sequence, the two question -% marks are taken by \cs{use_none:nn}, and the assignment is placed -% before the right-most item. In the next iteration, -% \cs{@@_get_right_loop:nn} receives two empty arguments, and -% \cs{use_none:nn} stops the loop. +% \begin{macro}[EXP]{\@@_get_right_loop:nw, \@@_get_right_end:NnN} +% First remove \cs{s_@@} and prepend \cs{q_no_value}. The first +% argument of \cs{@@_get_right_loop:nw} is the last item found, and +% the second argument is empty until the end of the loop, where it is +% code that applies \cs{exp_not:n} to the last item and ends the loop. % \begin{macrocode} \cs_new_protected:Npn \seq_get_right:NN #1#2 { - \exp_after:wN \use_i_ii:nnn - \exp_after:wN \@@_get_right_loop:nn - \exp_after:wN \q_no_value - #1 - { ?? \tl_set:Nn #2 } - { } { } + \tl_set:Nx #2 + { + \exp_after:wN \use_i_ii:nnn + \exp_after:wN \@@_get_right_loop:nw + \exp_after:wN \q_no_value + #1 + \@@_get_right_end:NnN \@@_item:n + } } -\cs_new_protected:Npn \@@_get_right_loop:nn #1#2 +\cs_new:Npn \@@_get_right_loop:nw #1#2 \@@_item:n { - \use_none:nn #2 {#1} - \@@_get_right_loop:nn + #2 \use_none:n {#1} + \@@_get_right_loop:nw } +\cs_new:Npn \@@_get_right_end:NnN #1#2#3 { \exp_not:n {#2} } \cs_generate_variant:Nn \seq_get_right:NN { c } % \end{macrocode} % \end{macro} @@ -1646,18 +1641,26 @@ % \begin{macro}[TF]{\seq_gpop_right:NN, \seq_gpop_right:cN} % More or less the same for popping. % \begin{macrocode} -\prg_new_protected_conditional:Npnn \seq_pop_left:NN #1#2 { T , F , TF } +\prg_new_protected_conditional:Npnn \seq_pop_left:NN #1#2 + { T , F , TF } { \@@_pop_TF:NNNN \@@_pop_left:NNN \tl_set:Nn #1 #2 } -\prg_new_protected_conditional:Npnn \seq_gpop_left:NN #1#2 { T , F , TF } +\prg_new_protected_conditional:Npnn \seq_gpop_left:NN #1#2 + { T , F , TF } { \@@_pop_TF:NNNN \@@_pop_left:NNN \tl_gset:Nn #1 #2 } -\prg_new_protected_conditional:Npnn \seq_pop_right:NN #1#2 { T , F , TF } +\prg_new_protected_conditional:Npnn \seq_pop_right:NN #1#2 + { T , F , TF } { \@@_pop_TF:NNNN \@@_pop_right:NNN \tl_set:Nx #1 #2 } -\prg_new_protected_conditional:Npnn \seq_gpop_right:NN #1#2 { T , F , TF } +\prg_new_protected_conditional:Npnn \seq_gpop_right:NN #1#2 + { T , F , TF } { \@@_pop_TF:NNNN \@@_pop_right:NNN \tl_gset:Nx #1 #2 } -\prg_generate_conditional_variant:Nnn \seq_pop_left:NN { c } { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_gpop_left:NN { c } { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_pop_right:NN { c } { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_gpop_right:NN { c } { T , F , TF } +\prg_generate_conditional_variant:Nnn \seq_pop_left:NN { c } + { T , F , TF } +\prg_generate_conditional_variant:Nnn \seq_gpop_left:NN { c } + { T , F , TF } +\prg_generate_conditional_variant:Nnn \seq_pop_right:NN { c } + { T , F , TF } +\prg_generate_conditional_variant:Nnn \seq_gpop_right:NN { c } + { T , F , TF } % \end{macrocode} % \end{macro} % \end{macro} @@ -1665,21 +1668,21 @@ % \end{macro} % % \begin{macro}{\seq_item:Nn, \seq_item:cn} -% \begin{macro}{\@@_item:wNn, \@@_item:nN, \@@_item:nnn} +% \begin{macro}{\@@_item:wNn, \@@_item:nN, \@@_item:nwn} % The idea here is to find the offset of the item from the left, then use % a loop to grab the correct item. If the resulting offset is too large, -% then the stop code |{ ? \__prg_break: } { }| is used by the auxiliary, -% terminating the loop and returning nothing at all. +% then the argument delimited by \cs{@@_item:n} is \cs{prg_break:} instead +% of being empty, terminating the loop and returning nothing at all. % \begin{macrocode} \cs_new:Npn \seq_item:Nn #1 { \exp_after:wN \@@_item:wNn #1 \q_stop #1 } \cs_new:Npn \@@_item:wNn \s_@@ #1 \q_stop #2#3 { - \exp_args:Nf \@@_item:nnn + \exp_args:Nf \@@_item:nwn { \exp_args:Nf \@@_item:nN { \int_eval:n {#3} } #2 } #1 - { ? \__prg_break: } { } - \__prg_break_point: + \prg_break: \@@_item:n { } + \prg_break_point: } \cs_new:Npn \@@_item:nN #1#2 { @@ -1687,12 +1690,12 @@ { \int_eval:n { \seq_count:N #2 + 1 + #1 } } {#1} } -\cs_new:Npn \@@_item:nnn #1#2#3 +\cs_new:Npn \@@_item:nwn #1#2 \@@_item:n #3 { - \use_none:n #2 + #2 \int_compare:nNnTF {#1} = 1 - { \__prg_break:n { \exp_not:n {#3} } } - { \exp_args:Nf \@@_item:nnn { \int_eval:n { #1 - 1 } } } + { \prg_break:n { \exp_not:n {#3} } } + { \exp_args:Nf \@@_item:nwn { \int_eval:n { #1 - 1 } } } } \cs_generate_variant:Nn \seq_item:Nn { c } % \end{macrocode} @@ -1705,14 +1708,14 @@ % \UnitTested % \begin{macro}{\seq_map_break:n} % \UnitTested -% To break a function, the special token \cs{__prg_break_point:Nn} is +% To break a function, the special token \cs{prg_break_point:Nn} is % used to find the end of the code. Any ending code is then inserted % before the return value of \cs{seq_map_break:n} is inserted. % \begin{macrocode} \cs_new:Npn \seq_map_break: - { \__prg_map_break:Nn \seq_map_break: { } } + { \prg_map_break:Nn \seq_map_break: { } } \cs_new:Npn \seq_map_break:n - { \__prg_map_break:Nn \seq_map_break: } + { \prg_map_break:Nn \seq_map_break: } % \end{macrocode} % \end{macro} % \end{macro} @@ -1721,26 +1724,26 @@ % \UnitTested % \begin{macro}[rEXP]{\@@_map_function:NNn} % The idea here is to apply the code of |#2| to each item in the -% sequence without altering the definition of \cs{@@_item:n}. This -% is done as by noting that every odd token in the sequence must be -% \cs{@@_item:n}, which can be gobbled by \cs{use_none:n}. At the end of -% the loop, |#2| is instead |? \seq_map_break:|, which therefore breaks the -% loop without needing to do a (relatively-expensive) quark test. +% sequence without altering the definition of \cs{@@_item:n}. The +% argument delimited by \cs{@@_item:n} is almost always empty, except +% at the end of the loop where it is \cs{prg_break:}. This allows to +% break the loop without needing to do a (relatively-expensive) quark +% test. % \begin{macrocode} \cs_new:Npn \seq_map_function:NN #1#2 { \exp_after:wN \use_i_ii:nnn - \exp_after:wN \@@_map_function:NNn + \exp_after:wN \@@_map_function:Nw \exp_after:wN #2 #1 - { ? \seq_map_break: } { } - \__prg_break_point:Nn \seq_map_break: { } + \prg_break: \@@_item:n { } \prg_break_point: + \prg_break_point:Nn \seq_map_break: { } } -\cs_new:Npn \@@_map_function:NNn #1#2#3 +\cs_new:Npn \@@_map_function:Nw #1#2 \@@_item:n #3 { - \use_none:n #2 + #2 #1 {#3} - \@@_map_function:NNn #1 + \@@_map_function:Nw #1 } \cs_generate_variant:Nn \seq_map_function:NN { c } % \end{macrocode} @@ -1766,15 +1769,15 @@ } \cs_new_protected:Npn \@@_push_item_def: { - \int_gincr:N \g__prg_map_int - \cs_gset_eq:cN { __prg_map_ \int_use:N \g__prg_map_int :w } + \int_gincr:N \g__kernel_prg_map_int + \cs_gset_eq:cN { @@_map_ \int_use:N \g__kernel_prg_map_int :w } \@@_item:n } \cs_new_protected:Npn \@@_pop_item_def: { \cs_gset_eq:Nc \@@_item:n - { __prg_map_ \int_use:N \g__prg_map_int :w } - \int_gdecr:N \g__prg_map_int + { @@_map_ \int_use:N \g__kernel_prg_map_int :w } + \int_gdecr:N \g__kernel_prg_map_int } % \end{macrocode} % \end{macro} @@ -1791,7 +1794,7 @@ { \@@_push_item_def:n {#2} #1 - \__prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: } + \prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: } } \cs_generate_variant:Nn \seq_map_inline:Nn { c } % \end{macrocode} @@ -1815,7 +1818,7 @@ \exp_not:n {#3} } #1 - \__prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: } + \prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: } } \cs_generate_variant:Nn \seq_map_variable:NNn { Nc } \cs_generate_variant:Nn \seq_map_variable:NNn { c , cc } @@ -1823,20 +1826,37 @@ % \end{macro} % % \begin{macro}{\seq_count:N, \seq_count:c} -% \begin{macro}{\@@_count:n} -% Counting the items in a sequence is done using the same approach as for -% other count functions: turn each entry into a \texttt{+1} then use -% integer evaluation to actually do the mathematics. +% \begin{macro}{\@@_count:w, \@@_count_end:w} +% Since counting the items in a sequence is quite common, we optimize +% it by grabbing $8$~items at a time and correspondingly adding $8$ to +% an integer expression. At the end of the loop, |#9| is +% \cs{@@_count_end:w} instead of being empty. It removes |8+| and +% instead places the number of \cs{@@_item:n} that \cs{@@_count:w} +% grabbed before reaching the end of the sequence. % \begin{macrocode} \cs_new:Npn \seq_count:N #1 { \int_eval:n { - 0 - \seq_map_function:NN #1 \@@_count:n + \exp_after:wN \use_i:nn + \exp_after:wN \@@_count:w + #1 + \@@_count_end:w \@@_item:n 7 + \@@_count_end:w \@@_item:n 6 + \@@_count_end:w \@@_item:n 5 + \@@_count_end:w \@@_item:n 4 + \@@_count_end:w \@@_item:n 3 + \@@_count_end:w \@@_item:n 2 + \@@_count_end:w \@@_item:n 1 + \@@_count_end:w \@@_item:n 0 + \prg_break_point: } } -\cs_new:Npn \@@_count:n #1 { + 1 } +\cs_new:Npn \@@_count:w + #1 \@@_item:n #2 \@@_item:n #3 \@@_item:n #4 \@@_item:n + #5 \@@_item:n #6 \@@_item:n #7 \@@_item:n #8 #9 \@@_item:n + { #9 8 + \@@_count:w } +\cs_new:Npn \@@_count_end:w 8 + \@@_count:w #1#2 \prg_break_point: {#1} \cs_generate_variant:Nn \seq_count:N { c } % \end{macrocode} % \end{macro} @@ -1983,7 +2003,7 @@ \cs_generate_variant:Nn \seq_log:N { c } \cs_new_protected:Npn \@@_show:NN #1#2 { - \__kernel_check_defined:NT #2 + \__kernel_chk_defined:NT #2 { #1 { LaTeX/kernel } { show-seq } { \token_to_str:N #2 } |