diff options
author | Karl Berry <karl@freefriends.org> | 2018-04-30 22:39:09 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-04-30 22:39:09 +0000 |
commit | a28e1bfccd6fe522fcd296426e4d89c7fb4f19b6 (patch) | |
tree | b72347e08575b56fcfed87c4d837b48dcfd1e02a /Master/texmf-dist/source/latex/l3kernel/l3expan.dtx | |
parent | b40c37a9e22b8235ff9c0bc256d00f7af94304c3 (diff) |
l3 (30apr18)
git-svn-id: svn://tug.org/texlive/trunk@47516 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3expan.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3expan.dtx | 223 |
1 files changed, 167 insertions, 56 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx index 871763ed5fe..46c4acf4cec 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/03/05} +% \date{Released 2018-04-30} % % \maketitle % @@ -246,8 +246,14 @@ % \begin{quote} % |\example:f { \int_eval:n { 1 + 2 } , \int_eval:n { 3 + 4 } }| % \end{quote} -% results in the call |\example:n { 3 , \int_eval:n { 3 + 4 } }| -% while using |\example:x| instead results in |\example:n { 3 , 7 }| +% results in the call +% \begin{quote} +% |\example:n { 3 , \int_eval:n { 3 + 4 } }| +% \end{quote} +% while using |\example:x| instead results in +% \begin{quote} +% |\example:n { 3 , 7 }| +% \end{quote} % at the cost of being protected. % If you use this type of expansion in conditional processing then % you should stick to using |TF| type functions only as the expansion @@ -284,14 +290,20 @@ % \end{syntax} % This function absorbs two arguments (the \meta{function} name and % the \meta{tokens}). The \meta{tokens} are expanded until only characters -% remain, and are then turned into a control sequence. (An internal error -% occurs if non-characters remain, as the conversion is not possible.) +% remain, and are then turned into a control sequence. % The result is inserted into the input stream \emph{after} reinsertion % of the \meta{function}. Thus the \meta{function} may take more than % one argument: all others are left unchanged. % % The |:cc| variant constructs the \meta{function} name in the same % manner as described for the \meta{tokens}. +% \begin{texnote} +% Protected macros that appear in a \texttt{c}-type argument are +% expanded despite being protected; \cs{exp_not:n} also has no +% effect. An internal error occurs if non-characters or active +% characters remain after full expansion, as the conversion to a +% control sequence is not possible. +% \end{texnote} % \end{function} % % \begin{function}[EXP]{\exp_args:No} @@ -322,13 +334,19 @@ % \end{syntax} % This function absorbs two arguments (the \meta{function} name and % the \meta{tokens}). The \meta{tokens} are expanded until only characters -% remain, and are then turned into a control sequence. (An internal error -% occurs if non-characters remain, as the conversion is not possible.) +% remain, and are then turned into a control sequence. % This control sequence should % be the name of a \meta{variable}. The content of the \meta{variable} are % recovered and placed inside braces into the input stream \emph{after} % reinsertion of the \meta{function}. Thus the \meta{function} may take more % than one argument: all others are left unchanged. +% \begin{texnote} +% Protected macros that appear in a \texttt{v}-type argument are +% expanded despite being protected; \cs{exp_not:n} also has no +% effect. An internal error occurs if non-characters or active +% characters remain after full expansion, as the conversion to a +% control sequence is not possible. +% \end{texnote} % \end{function} % % \begin{function}[EXP]{\exp_args:Nf} @@ -587,10 +605,11 @@ % \begin{texnote} % This is the \TeX{} \tn{noexpand} primitive. It only prevents % expansion. At the beginning of an |f|-type argument, a space -% \meta{token} is removed despite \cs{exp_not:N}. In an -% |x|-expanding definition (\cs{cs_new:Npx}) a macro parameter -% \meta{token} (normally~|#|) denotes an argument despite -% \cs{exp_not:N} (see \cs{exp_not:n}). +% \meta{token} is removed even if it appears as \cs{exp_not:N} +% \cs{c_space_token}. In an |x|-expanding definition +% (\cs{cs_new:Npx}), a macro parameter introduces an argument even +% if it appears as \cs{exp_not:N} |#| |1|. This differs from +% \cs{exp_not:n}. % \end{texnote} % \end{function} % @@ -599,10 +618,16 @@ % \cs{exp_not:c} \Arg{tokens} % \end{syntax} % Expands the \meta{tokens} until only characters remain, and then -% converts this into a control sequence. (An internal error occurs if -% non-characters remain, as the conversion is not possible.) +% converts this into a control sequence. % Further expansion of this control sequence is then inhibited using % \cs{exp_not:N}. +% \begin{texnote} +% Protected macros that appear in a \texttt{c}-type argument are +% expanded despite being protected; \cs{exp_not:n} also has no +% effect. An internal error occurs if non-characters or active +% characters remain after full expansion, as the conversion to a +% control sequence is not possible. +% \end{texnote} % \end{function} % % \begin{function}[EXP]{\exp_not:n} @@ -610,13 +635,15 @@ % \cs{exp_not:n} \Arg{tokens} % \end{syntax} % Prevents expansion of the \meta{tokens} in an |x|-type argument. In -% other cases (input stream or |o| or |f| arguments) the \meta{tokens} -% continue being expanded. +% all other cases the \meta{tokens} continue to be expanded, for +% example in the input stream or in other types of arguments such as +% \texttt{c}, \texttt{f}, \texttt{v}. The argument of \cs{exp_not:n} +% \emph{must} be surrounded by braces. % \begin{texnote} -% This is the \eTeX{} \tn{unexpanded} primitive. Hence its argument -% \emph{must} be surrounded by braces. In an |x|-expanding -% definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#}| inserts a macro -% parameter character in the replacement text. +% This is the \eTeX{} \tn{unexpanded} primitive. In an +% |x|-expanding definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#1}| +% is equivalent to |##1| rather than to~|#1|, namely it inserts the +% two characters |#| and~|1|. % \end{texnote} % \end{function} % @@ -642,10 +669,16 @@ % \end{syntax} % Expands the \meta{tokens} until only characters remains, and then % converts this into a control sequence which should be a \meta{variable} -% name. (An internal error occurs if -% non-characters remain, as the conversion is not possible.) +% name. % The content of the \meta{variable} is recovered, and further % expansion in |x|-type arguments is prevented using \cs{exp_not:n}. +% \begin{texnote} +% Protected macros that appear in a \texttt{v}-type argument are +% expanded despite being protected; \cs{exp_not:n} also has no +% effect. An internal error occurs if non-characters or active +% characters remain after full expansion, as the conversion to a +% control sequence is not possible. +% \end{texnote} % \end{function} % % \begin{function}[EXP]{\exp_not:f} @@ -705,12 +738,12 @@ % \exp_end: % } % \begin{syntax} -% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end:} \\ +% \cs{exp:w} \meta{expandable tokens} \cs{exp_end:} \\ % \end{syntax} % Expands \meta{expandable-tokens} until reaching \cs{exp_end:} at % which point expansion stops. -% The full expansion of \meta{expandable-tokens} has to be empty. -% If any token in \meta{expandable-tokens} or any token generated by +% The full expansion of \meta{expandable tokens} has to be empty. +% If any token in \meta{expandable tokens} or any token generated by % expanding the tokens therein is not expandable the expansion will end % prematurely and as a result \cs{exp_end:} will be misinterpreted % later on.\footnotemark @@ -724,6 +757,11 @@ %\end{verbatim} % where somewhere during the expansion of |\@@_case:NnTF| the % \cs{exp_end:} gets generated. +% \begin{texnote} +% The current implementation uses \tn{romannumeral} hence ignores +% space tokens and explicit signs |+| and |-| in the expansion of the +% \meta{expandable tokens}, but this should not be relied upon. +% \end{texnote} % \end{function} % \footnotetext{Due to the implementation you might get the character % in position 0 in the current font (typically \enquote{\texttt{`}}) @@ -797,21 +835,26 @@ % braces will not terminate the \texttt{f}-type expansion. % \end{function} % -% \section{Internal functions and variables} -% -% \begin{variable}{\l__exp_internal_tl} -% The |\exp_| module has its private variable to temporarily store the -% result of |x|-type argument expansion. This is done to avoid interference -% with other functions using temporary variables. -% \end{variable} +% \section{Internal functions} % % \begin{function}{\::n, \::N, \::p, \::c, \::o, \::f, \::x, \::v, \::V, \:::} % \begin{syntax} -% |\cs_set:Npn \exp_args:Ncof { \::c \::o \::f \::: }| +% |\cs_new:Npn \exp_args:Ncof { \::c \::o \::f \::: }| % \end{syntax} % Internal forms for the base expansion types. These names do \emph{not} % conform to the general \LaTeX3 approach as this makes them more readily -% visible in the log and so forth. +% visible in the log and so forth. They should not be used outside this module. +% \end{function} +% +% \begin{function} +% {\::o_unbraced, \::f_unbraced, \::x_unbraced, \::v_unbraced, \::V_unbraced} +% \begin{syntax} +% |\cs_new:Npn \exp_last_unbraced:Nno { \::n \::o_unbraced \::: }| +% \end{syntax} +% Internal forms for the expansion types which leave the terminal argument +% unbraced. These names do \emph{not} +% conform to the general \LaTeX3 approach as this makes them more readily +% visible in the log and so forth. They should not be used outside this module. % \end{function} % % \end{documentation} @@ -828,6 +871,12 @@ %<@@=exp> % \end{macrocode} % +% \begin{variable}{\l_@@_internal_tl} +% The |\exp_| module has its private variable to temporarily store the +% result of |x|-type argument expansion. This is done to avoid interference +% with other functions using temporary variables. +% \end{variable} +% % \begin{macro}{\exp_after:wN} % \begin{macro}{\exp_not:N} % \begin{macro}{\exp_not:n} @@ -963,11 +1012,13 @@ % % \begin{macro}{\::x} % This function is used to expand an argument fully. +% We build in the expansion of \cs{@@_arg_next:nnn}. % \begin{macrocode} \cs_new_protected:Npn \::x #1 \::: #2#3 { - \cs_set_nopar:Npx \l_@@_internal_tl { {#3} } - \exp_after:wN \@@_arg_next:nnn \l_@@_internal_tl {#1} {#2} + \cs_set_nopar:Npx \l_@@_internal_tl + { \exp_not:n { #1 \::: } { \exp_not:n {#2} {#3} } } + \l_@@_internal_tl } % \end{macrocode} % \end{macro} @@ -1450,26 +1501,34 @@ % % \subsection{Preventing expansion} % +% \begin{macro}{\__kernel_exp_not:w} +% At the kernel level, we need the primitive behaviour to allow expansion +% \emph{before} the brace group. +% \begin{macrocode} +\cs_new_eq:NN \__kernel_exp_not:w \etex_unexpanded:D +% \end{macrocode} +% \end{macro} +% % \begin{macro}[EXP]{\exp_not:c} % \begin{macro}[EXP]{\exp_not:o} % \begin{macro}[EXP]{\exp_not:f} % \begin{macro}[EXP]{\exp_not:V} % \begin{macro}[EXP]{\exp_not:v} -% All these except \cs{exp_not:c} call the primitive -% \cs{etex_unexpanded:D} namely \cs{exp_not:n}. +% All these except \cs{exp_not:c} call the kernel-internal +% \cs{__kernel_exp_not:w} namely \tn{etex_unexpanded:D}. % \begin{macrocode} \cs_new:Npn \exp_not:c #1 { \exp_after:wN \exp_not:N \cs:w #1 \cs_end: } -\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} } +\cs_new:Npn \exp_not:o #1 { \__kernel_exp_not:w \exp_after:wN {#1} } \cs_new:Npn \exp_not:f #1 { \etex_unexpanded:D \exp_after:wN { \exp:w \exp_end_continue_f:w #1 } } \cs_new:Npn \exp_not:V #1 { - \etex_unexpanded:D \exp_after:wN + \__kernel_exp_not:w \exp_after:wN { \exp:w \@@_eval_register:N #1 } } \cs_new:Npn \exp_not:v #1 { - \etex_unexpanded:D \exp_after:wN + \__kernel_exp_not:w \exp_after:wN { \exp:w \@@_eval_register:c {#1} } } % \end{macrocode} @@ -1524,10 +1583,15 @@ % \end{macrocode} % If the above definition ever appears outside its proper context % the active character |^^@| will be executed so we turn this into an -% error. +% error. The test for existence covers the (unlikely) case that some +% other code has already defined |^^@|: this is true for example for +% \texttt{xmltex.tex}. % \begin{macrocode} - \cs_new:Npn ^^@ - { \__kernel_msg_expandable_error:nn { kernel } { bad-exp-end-f } } + \if_cs_exist:N ^^@ + \else: + \cs_new:Npn ^^@ + { \__kernel_msg_expandable_error:nn { kernel } { bad-exp-end-f } } + \fi: % \end{macrocode} % The same but grabbing an argument to remove spaces and braces. % \begin{macrocode} @@ -1565,11 +1629,15 @@ \cs_new_protected:Npn \cs_generate_variant:Nn #1#2 { \@@_generate_variant:N #1 - \exp_after:wN \@@_split_function:NN - \exp_after:wN #1 - \exp_after:wN \@@_generate_variant:nnNN - \exp_after:wN #1 - \tl_to_str:n {#2} , \scan_stop: , \q_recursion_stop + \use:x + { + \@@_generate_variant:nnNN + \cs_split_function:N #1 + \exp_not:N #1 + \tl_to_str:n {#2} , + \exp_not:N \scan_stop: , + \exp_not:N \q_recursion_stop + } } \cs_new_protected:Npn \cs_generate_variant:cn { \exp_args:Nc \cs_generate_variant:Nn } @@ -1872,7 +1940,8 @@ #5 } } -\cs_new:Npn \@@_generate_variant_loop_special:NNwNNnn #1#2#3 \q_stop #4#5#6#7 +\cs_new:Npn \@@_generate_variant_loop_special:NNwNNnn + #1#2#3 \q_stop #4#5#6#7 { #3 \q_stop #4 #5 {#6} {#7} \exp_not:n @@ -1969,12 +2038,9 @@ { : \exp_not:N \use_i:nn } } } -\use:x - { - \cs_new_protected:Npn \exp_not:N \@@_generate_internal_variant:wwnNwnn - ##1 \token_to_str:N x ##2 \exp_not:N \q_mark - ##3 ##4 ##5 \exp_not:N \q_stop ##6 ##7 - } +\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 { #3 \cs_if_free:cT {#6} { #4 {#6} {#7} } @@ -2009,7 +2075,13 @@ % } % \begin{macrocode} \cs_new_protected:Npn \prg_generate_conditional_variant:Nnn #1 - { \__cs_split_function:NN #1 \@@_generate_variant:nnNnn } + { + \use:x + { + \@@_generate_variant:nnNnn + \cs_split_function:N #1 + } + } \cs_new_protected:Npn \@@_generate_variant:nnNnn #1#2#3#4#5 { \if_meaning:w \c_false_bool #3 @@ -2051,6 +2123,45 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\exp_args_generate:n, \@@_args_generate:Nn} +% \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{:::}. +% \begin{macrocode} +\cs_new_protected:Npn \exp_args_generate:n #1 + { + \exp_args:No \clist_map_inline:nn { \tl_to_str:n {#1} } + { + \str_map_inline:nn {##1} + { + \str_if_in:nnF { NnpcofVvx } {####1} + { + \__kernel_msg_error:nnnn { kernel } { invalid-exp-args } + {####1} {##1} + \str_map_break:n { \use_none:nnnn } + } + } + \exp_args:Nc \@@_args_generate:Nn { exp_args:N ##1 } {##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} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} |