From bbbe8128e7ae9d816a221377dbf5ff3969bb203b Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 30 Sep 2019 03:00:43 +0000 Subject: CTAN sync 201909300300 --- macros/latex/contrib/l3kernel/l3expan.dtx | 354 ++++++++++++++++++------------ 1 file changed, 213 insertions(+), 141 deletions(-) (limited to 'macros/latex/contrib/l3kernel/l3expan.dtx') diff --git a/macros/latex/contrib/l3kernel/l3expan.dtx b/macros/latex/contrib/l3kernel/l3expan.dtx index ab6ec3271b..ab72686865 100644 --- a/macros/latex/contrib/l3kernel/l3expan.dtx +++ b/macros/latex/contrib/l3kernel/l3expan.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-09-19} +% \date{Released 2019-09-28} % % \maketitle % @@ -1128,7 +1128,7 @@ \exp_after:wN { \exp:w \@@_eval_register:N #3 } {#1} {#2} } -\cs_new:Npn \::v # 1\::: #2#3 +\cs_new:Npn \::v #1 \::: #2#3 { \exp_after:wN \@@_arg_next:nnn \exp_after:wN { \exp:w \@@_eval_register:c {#3} } @@ -1400,99 +1400,13 @@ % \end{macrocode} % \end{macro} % -% \subsection{Definitions with the automated technique} -% \label{sec:l3expan:gendef} -% -% Some of these could be done more efficiently, but the complexity of -% coding then becomes an issue. Notice that the auto-generated functions -% actually take no arguments themselves. -% % \begin{macro}{\exp_args:Nx} % \begin{macrocode} -\cs_new_protected:Npn \exp_args:Nx { \::x \::: } +\cs_new_protected:Npn \exp_args:Nx #1#2 + { \use:x { \exp_not:N #1 {#2} } } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP] -% { -% \exp_args:Nnc, \exp_args:Nno, \exp_args:NnV, \exp_args:Nnv, \exp_args:Nne, \exp_args:Nnf, -% \exp_args:Noc, \exp_args:Noo, \exp_args:Nof, -% \exp_args:NVo, \exp_args:Nfo, \exp_args:Nff, -% } -% \begin{macro} -% { -% \exp_args:NNx, \exp_args:Ncx, \exp_args:Nnx, -% \exp_args:Nox, \exp_args:Nxo, \exp_args:Nxx, -% } -% Here are the actual function definitions, using the helper functions -% above. -% \begin{macrocode} -\cs_new:Npn \exp_args:Nnc { \::n \::c \::: } -\cs_new:Npn \exp_args:Nno { \::n \::o \::: } -\cs_new:Npn \exp_args:NnV { \::n \::V \::: } -\cs_new:Npn \exp_args:Nnv { \::n \::v \::: } -\cs_new:Npn \exp_args:Nne { \::n \::e \::: } -\cs_new:Npn \exp_args:Nnf { \::n \::f \::: } -\cs_new:Npn \exp_args:Noc { \::o \::c \::: } -\cs_new:Npn \exp_args:Noo { \::o \::o \::: } -\cs_new:Npn \exp_args:Nof { \::o \::f \::: } -\cs_new:Npn \exp_args:NVo { \::V \::o \::: } -\cs_new:Npn \exp_args:Nfo { \::f \::o \::: } -\cs_new:Npn \exp_args:Nff { \::f \::f \::: } -\cs_new_protected:Npn \exp_args:NNx { \::N \::x \::: } -\cs_new_protected:Npn \exp_args:Ncx { \::c \::x \::: } -\cs_new_protected:Npn \exp_args:Nnx { \::n \::x \::: } -\cs_new_protected:Npn \exp_args:Nox { \::o \::x \::: } -\cs_new_protected:Npn \exp_args:Nxo { \::x \::o \::: } -\cs_new_protected:Npn \exp_args:Nxx { \::x \::x \::: } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP] -% { -% \exp_args:NNNv, \exp_args:NNcf, -% \exp_args:NNno, \exp_args:NNnV, \exp_args:NNoo, \exp_args:NNVV, -% \exp_args:Ncno, \exp_args:NcnV, \exp_args:Ncoo, \exp_args:NcVV, -% \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nnnf, \exp_args:Nnff, -% \exp_args:Nooo, \exp_args:Noof, \exp_args:Nffo, -% } -% \begin{macro} -% { -% \exp_args:NNNx, \exp_args:NNnx, \exp_args:NNox, -% \exp_args:Nccx, \exp_args:Ncnx, -% \exp_args:Nnnx, \exp_args:Nnox, \exp_args:Noox, -% } -% \begin{macrocode} -\cs_new:Npn \exp_args:NNNv { \::N \::N \::v \::: } -\cs_new:Npn \exp_args:NNcf { \::N \::c \::f \::: } -\cs_new:Npn \exp_args:NNno { \::N \::n \::o \::: } -\cs_new:Npn \exp_args:NNnV { \::N \::n \::V \::: } -\cs_new:Npn \exp_args:NNoo { \::N \::o \::o \::: } -\cs_new:Npn \exp_args:NNVV { \::N \::V \::V \::: } -\cs_new:Npn \exp_args:Ncno { \::c \::n \::o \::: } -\cs_new:Npn \exp_args:NcnV { \::c \::n \::V \::: } -\cs_new:Npn \exp_args:Ncoo { \::c \::o \::o \::: } -\cs_new:Npn \exp_args:NcVV { \::c \::V \::V \::: } -\cs_new:Npn \exp_args:Nnnc { \::n \::n \::c \::: } -\cs_new:Npn \exp_args:Nnno { \::n \::n \::o \::: } -\cs_new:Npn \exp_args:Nnnf { \::n \::n \::f \::: } -\cs_new:Npn \exp_args:Nnff { \::n \::f \::f \::: } -\cs_new:Npn \exp_args:Nooo { \::o \::o \::o \::: } -\cs_new:Npn \exp_args:Noof { \::o \::o \::f \::: } -\cs_new:Npn \exp_args:Nffo { \::f \::f \::o \::: } -\cs_new_protected:Npn \exp_args:NNNx { \::N \::N \::x \::: } -\cs_new_protected:Npn \exp_args:NNnx { \::N \::n \::x \::: } -\cs_new_protected:Npn \exp_args:NNox { \::N \::o \::x \::: } -\cs_new_protected:Npn \exp_args:Nnnx { \::n \::n \::x \::: } -\cs_new_protected:Npn \exp_args:Nnox { \::n \::o \::x \::: } -\cs_new_protected:Npn \exp_args:Nccx { \::c \::c \::x \::: } -\cs_new_protected:Npn \exp_args:Ncnx { \::c \::n \::x \::: } -\cs_new_protected:Npn \exp_args:Noox { \::o \::o \::x \::: } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \subsection{Last-unbraced versions} % % \begin{macro}[EXP]{\@@_arg_last_unbraced:nn} @@ -2263,7 +2177,6 @@ % iterate through the comma list of variant argument specifiers, which % we first convert to a string: the reason is explained later. % \begin{macrocode} -\__kernel_patch:nnNNpn { \__kernel_chk_cs_exist:N #1 } { } \cs_new_protected:Npn \cs_generate_variant:Nn #1#2 { \@@_generate_variant:N #1 @@ -2598,9 +2511,9 @@ % \begin{macrocode} \cs_new:Npn \@@_generate_variant_same:N #1 { - \if:w N #1 N \else: - \if:w p #1 p \else: - n + \if:w N #1 #1 \else: + \if:w p #1 #1 \else: + \token_to_str:N n \if:w n #1 \else: \@@_generate_variant_loop_special:NNwNNnn #1#1 \fi: @@ -2618,18 +2531,6 @@ % \cs{cs_new_protected:Npx}. Then define the variant by % combining the |\exp_args:N #3| variant and the base function. % \begin{macrocode} -\__kernel_patch:nnNNpn - { - \cs_if_free:NF #4 - { - \__kernel_debug_log:x - { - Variant~\token_to_str:N #4~% - already~defined;~ not~ changing~ it~ \msg_line_context: - } - } - } - { } \cs_new_protected:Npn \@@_generate_variant:wwNN #1 \q_mark #2 \q_stop #3#4 { @@ -2646,38 +2547,129 @@ % \end{macro} % % \begin{macro}{\@@_generate_internal_variant:n} -% \begin{macro}{\@@_generate_internal_variant:wwnw} % \begin{macro}[rEXP]{\@@_generate_internal_variant_loop:n} -% Test if |\exp_args:N #1| is already defined and if not define it via -% the |\::| commands using the chars in |#1|. If |#1| contains an |x| -% (this is the place where having converted the original comma-list -% argument to a string is very important), the result should be -% protected, and the next variant to be defined using that internal -% variant should be protected. +% First test for the presence of |x| (this is where working with +% strings makes our lives easier), as the result should be protected, +% and the next variant to be defined using that internal variant +% should be protected (done by setting \cs{@@_tmp:w}). Then call +% \cs{@@_generate_internal_variant:NNn} with arguments +% \cs{cs_new_protected:cpn} \cs{use:x} (for protected) or +% \cs{cs_new:cpn} \cs{tex_expanded:D} (expandable) and the signature. If |p| +% appears in the signature, or if the function to be defined is +% expandable and the primitive \tn{expanded} is not available, call +% some fall-back code that just puts the appropriate |\::| commands. +% Otherwise, call \cs{@@_generate_internal_one_go:NNn} to construct +% the \cs[no-index]{exp_args:N\dots} function as a macro taking up to +% $9$~arguments and expanding them using \cs{use:x} or \cs{tex_expanded:D}. % \begin{macrocode} \cs_new_protected:Npx \@@_generate_internal_variant:n #1 { - \exp_not:N \@@_generate_internal_variant:wwnNwnn + \exp_not:N \@@_generate_internal_variant:wwnNwn #1 \exp_not:N \q_mark { \cs_set_eq:NN \exp_not:N \@@_tmp:w \cs_new_protected:Npx } - \cs_new_protected:cpx + \cs_new_protected:cpn + \use:x \token_to_str:N x \exp_not:N \q_mark { } - \cs_new:cpx + \cs_new:cpn + \exp_not:N \tex_expanded:D \exp_not:N \q_stop - { exp_args:N #1 } - { - \exp_not:N \@@_generate_internal_variant_loop:n #1 - { : \exp_not:N \use_i:nn } - } + {#1} } \exp_last_unbraced:NNNNo - \cs_new_protected:Npn \@@_generate_internal_variant:wwnNwnn #1 - { \token_to_str:N x } #2 \q_mark #3#4#5 \q_stop #6#7 + \cs_new_protected:Npn \@@_generate_internal_variant:wwnNwn #1 + { \token_to_str:N x } #2 \q_mark #3#4#5#6 \q_stop #7 { #3 - \cs_if_free:cT {#6} { #4 {#6} {#7} } + \cs_if_free:cT { exp_args:N #7 } + { \@@_generate_internal_variant:NNn #4 #5 {#7} } } +\cs_set_protected:Npn \@@_tmp:w #1 + { + \cs_new_protected:Npn \@@_generate_internal_variant:NNn ##1##2##3 + { + \@@_generate_internal_test:Nw ##2 ##3 + \q_mark + { + \use:x + { + ##1 { exp_args:N ##3 } + { \@@_generate_internal_variant_loop:n ##3 { : \use_i:nn } } + } + } + #1 + \q_mark + { \exp_not:n { \@@_generate_internal_one_go:NNn ##1 ##2 {##3} } } + \q_stop + } + \cs_new_protected:Npn \@@_generate_internal_test_aux:w + ##1 #1 ##2 \q_mark ##3 ##4 \q_stop {##3} + \cs_if_exist:NTF \tex_expanded:D + { + \cs_new_eq:NN \@@_generate_internal_test:Nw + \@@_generate_internal_test_aux:w + } + { + \cs_new_protected:Npn \@@_generate_internal_test:Nw ##1 + { + \if_meaning:w \tex_expanded:D ##1 + \exp_after:wN \@@_generate_internal_test_aux:w + \exp_after:wN #1 + \else: + \exp_after:wN \@@_generate_internal_test_aux:w + \fi: + } + } + } +\exp_args:No \@@_tmp:w { \token_to_str:N p } +\cs_new_protected:Npn \@@_generate_internal_one_go:NNn #1#2#3 + { + \@@_generate_internal_loop:nwnnw + { \exp_not:N ##1 } 1 . { } { } + #3 { ? \@@_generate_internal_end:w } X ; + 23456789 { ? \@@_generate_internal_long:w } ; + #1 #2 {#3} + } +\cs_new_protected:Npn \@@_generate_internal_loop:nwnnw #1#2 . #3#4#5#6 ; #7 + { + \use_none:n #5 + \use_none:n #7 + \cs_if_exist_use:cF { @@_generate_internal_#5:NN } + { \@@_generate_internal_other:NN } + #5 #7 + #7 . + { #3 #1 } { #4 ## #2 } + #6 ; + } +\cs_new_protected:Npn \@@_generate_internal_N:NN #1#2 + { \@@_generate_internal_loop:nwnnw { \exp_not:N ###2 } } +\cs_new_protected:Npn \@@_generate_internal_c:NN #1#2 + { \exp_args:No \@@_generate_internal_loop:nwnnw { \exp_not:c {###2} } } +\cs_new_protected:Npn \@@_generate_internal_n:NN #1#2 + { \@@_generate_internal_loop:nwnnw { { \exp_not:n {###2} } } } +\cs_new_protected:Npn \@@_generate_internal_x:NN #1#2 + { \@@_generate_internal_loop:nwnnw { {###2} } } +\cs_new_protected:Npn \@@_generate_internal_other:NN #1#2 + { + \exp_args:No \@@_generate_internal_loop:nwnnw + { + \exp_after:wN + { + \exp:w \exp_args:NNc \exp_after:wN \exp_end: + { exp_not:#1 } {###2} + } + } + } +\cs_new_protected:Npn \@@_generate_internal_end:w #1 . #2#3#4 ; #5 ; #6#7#8 + { #6 { exp_args:N #8 } #3 { #7 {#2} } } +\cs_new_protected:Npn \@@_generate_internal_long:w #1 N #2#3 . #4#5#6# + { + \exp_args:Nx \@@_generate_internal_long:nnnNNn + { \@@_generate_internal_variant_loop:n #2 #6 { : \use_i:nn } } + {#4} {#5} + } +\cs_new:Npn \@@_generate_internal_long:nnnNNn #1#2#3#4 ; ; #5#6#7 + { #5 { exp_args:N #7 } #3 { #6 { \exp_not:n {#1} {#2} } } } % \end{macrocode} % This command grabs char by char outputting |\::#1| (not expanded % further). We avoid tests by putting a trailing |: \use_i:nn|, which @@ -2693,7 +2685,6 @@ % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro} % { @@ -2756,15 +2747,12 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\exp_args_generate:n, \@@_args_generate:Nn} -% \begin{macro}[EXP]{\@@_args_generate:n} +% \begin{macro}{\exp_args_generate:n} % This function is not used in the kernel hence we can use functions % that are defined in later modules. It also does not need to be fast % so use inline mappings. For each requested variant we check that % there are no characters besides |NnpcofVvx|, in particular that -% there are no spaces. Then we loop through the variant specifier and -% convert each letter to \cs[no-index]{::\meta{variant letter}}, with a -% trailing \cs{:::}. +% there are no spaces. Then we just call the internal function. % \begin{macrocode} \cs_new_protected:Npn \exp_args_generate:n #1 { @@ -2776,21 +2764,105 @@ { \__kernel_msg_error:nnnn { kernel } { invalid-exp-args } {####1} {##1} - \str_map_break:n { \use_none:nnnn } + \str_map_break:n { \use_none:nn } } } - \exp_args:Nc \@@_args_generate:Nn { exp_args:N ##1 } {##1} + \@@_generate_internal_variant:n {##1} } } -\cs_new_protected:Npn \@@_args_generate:Nn #1#2 - { - \cs_if_exist:NF #1 - { - \str_if_in:nnTF {#2} { x } { \cs_new_protected:Npx } { \cs_new:Npx } - #1 { \tl_map_function:nN { #2 : } \@@_args_generate:n } - } - } -\cs_new:Npn \@@_args_generate:n #1 { \exp_not:c { :: #1 } } +% \end{macrocode} +% \end{macro} +% +% \subsection{Definitions with the automated technique} +% \label{sec:l3expan:gendef} +% +% Some of these could be done more efficiently, but the complexity of +% coding then becomes an issue. Notice that the auto-generated functions +% actually take no arguments themselves. +% +% \begin{macro}[EXP] +% { +% \exp_args:Nnc, \exp_args:Nno, \exp_args:NnV, \exp_args:Nnv, \exp_args:Nne, \exp_args:Nnf, +% \exp_args:Noc, \exp_args:Noo, \exp_args:Nof, +% \exp_args:NVo, \exp_args:Nfo, \exp_args:Nff, +% } +% \begin{macro} +% { +% \exp_args:NNx, \exp_args:Ncx, \exp_args:Nnx, +% \exp_args:Nox, \exp_args:Nxo, \exp_args:Nxx, +% } +% Here are the actual function definitions, using the helper +% functions above. The group is used because +% \cs{@@_generate_internal_variant:n} redefines \cs{@@_tmp:w} locally. +% \begin{macrocode} +\cs_set_protected:Npn \@@_tmp:w #1 + { + \group_begin: + \exp_args:No \@@_generate_internal_variant:n + { \tl_to_str:n {#1} } + \group_end: + } +\@@_tmp:w { nc } +\@@_tmp:w { no } +\@@_tmp:w { nV } +\@@_tmp:w { nv } +\@@_tmp:w { ne } +\@@_tmp:w { nf } +\@@_tmp:w { oc } +\@@_tmp:w { oo } +\@@_tmp:w { of } +\@@_tmp:w { Vo } +\@@_tmp:w { fo } +\@@_tmp:w { ff } +\@@_tmp:w { Nx } +\@@_tmp:w { cx } +\@@_tmp:w { nx } +\@@_tmp:w { ox } +\@@_tmp:w { xo } +\@@_tmp:w { xx } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP] +% { +% \exp_args:NNcf, +% \exp_args:NNno, \exp_args:NNnV, \exp_args:NNoo, \exp_args:NNVV, +% \exp_args:Ncno, \exp_args:NcnV, \exp_args:Ncoo, \exp_args:NcVV, +% \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nnnf, \exp_args:Nnff, +% \exp_args:Nooo, \exp_args:Noof, \exp_args:Nffo, +% } +% \begin{macro} +% { +% \exp_args:NNNx, \exp_args:NNnx, \exp_args:NNox, +% \exp_args:Nccx, \exp_args:Ncnx, +% \exp_args:Nnnx, \exp_args:Nnox, \exp_args:Noox, +% } +% \begin{macrocode} +\@@_tmp:w { Ncf } +\@@_tmp:w { Nno } +\@@_tmp:w { NnV } +\@@_tmp:w { Noo } +\@@_tmp:w { NVV } +\@@_tmp:w { cno } +\@@_tmp:w { cnV } +\@@_tmp:w { coo } +\@@_tmp:w { cVV } +\@@_tmp:w { nnc } +\@@_tmp:w { nno } +\@@_tmp:w { nnf } +\@@_tmp:w { nff } +\@@_tmp:w { ooo } +\@@_tmp:w { oof } +\@@_tmp:w { ffo } +\@@_tmp:w { NNx } +\@@_tmp:w { Nnx } +\@@_tmp:w { Nox } +\@@_tmp:w { nnx } +\@@_tmp:w { nox } +\@@_tmp:w { ccx } +\@@_tmp:w { cnx } +\@@_tmp:w { oox } % \end{macrocode} % \end{macro} % \end{macro} -- cgit v1.2.3