summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3expan.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3expan.dtx804
1 files changed, 455 insertions, 349 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
index 249309ab8cf..5479105b596 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
@@ -7,7 +7,7 @@
% license or (at your option) any later version. The latest version
% of this license is in the file
%
-% http://www.latex-project.org/lppl.txt
+% https://www.latex-project.org/lppl.txt
%
% This file is part of the "l3kernel bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
@@ -21,7 +21,7 @@
% for those people who are interested.
%
%<*driver>
-\documentclass[full]{l3doc}
+\documentclass[full,kernel]{l3doc}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
@@ -41,7 +41,7 @@
% }^^A
% }
%
-% \date{Released 2017/11/14}
+% \date{Released 2017/12/05}
%
% \maketitle
%
@@ -74,7 +74,7 @@
% \begin{verbatim}
% \exp_args:NNo \seq_gpush:Nn
% \g_file_name_stack
-% \l_tmpa_tl
+% { \l_tmpa_tl }
% \end{verbatim}
% In other words, the first argument to \cs{exp_args:NNo} is the base
% function and the other arguments are preprocessed and then passed to
@@ -90,7 +90,7 @@
% \begin{quote}
% |\cs_new:Npn \seq_gpush:No { \exp_args:NNo \seq_gpush:Nn }|
% \end{quote}
-% Providing variants in this way in style files is uncritical as the
+% Providing variants in this way in style files is safe as the
% \cs{cs_generate_variant:Nn} function will only create new definitions if
% there is not already one available. Therefore adding
% such definition to later releases of the kernel will not make such
@@ -114,12 +114,13 @@
% once, |f|~expands fully the first token, |x|~expands fully all
% tokens at the price of being non-expandable.
% \item A few odd argument types remain: |T|~and |F|~for conditional
-% processing, otherwise identical to~|n|, |p|~for the parameter text
+% processing, otherwise identical to |n|-type arguments,
+% |p|~for the parameter text
% in definitions, |w|~for arguments with a specific syntax, and |D|~to
% denote primitives that should not be used directly.
% \end{itemize}
%
-% \begin{function}[updated = 2015-08-06]{\cs_generate_variant:Nn}
+% \begin{function}[updated = 2017-11-28]{\cs_generate_variant:Nn}
% \begin{syntax}
% \cs{cs_generate_variant:Nn} \meta{parent control sequence} \Arg{variant argument specifiers}
% \end{syntax}
@@ -129,9 +130,9 @@
% \meta{base name} and \meta{original argument specifier}. The
% comma-separated list of \meta{variant argument specifiers} is
% then used to define variants of the
-% \meta{original argument specifier} where these are not already
+% \meta{original argument specifier} if these are not already
% defined. For each \meta{variant} given, a function is created
-% which expands its arguments as detailed and passes them
+% that expands its arguments as detailed and passes them
% to the \meta{parent control sequence}. So for example
% \begin{verbatim}
% \cs_set:Npn \foo:Nn #1#2 { code here }
@@ -145,51 +146,71 @@
% \end{verbatim}
% generates the functions |\foo:NV| and |\foo:cV| in the same
% way. The \cs{cs_generate_variant:Nn} function can only be applied if
-% the \meta{parent control sequence} is already defined. Only |n|~and
-% |N| arguments can be changed to other types. If the \meta{parent
+% the \meta{parent control sequence} is already defined. If the \meta{parent
% control sequence} is protected or if the \meta{variant} involves
% |x|~arguments, then the \meta{variant control sequence} is also
% protected. The \meta{variant} is created globally, as is any
% \cs[no-index]{exp_args:N\meta{variant}} function needed to carry out the
% expansion.
%
-% While \cs{cs_generate_variant:Nn} |\foo:N { o }| is currently
-% allowed, one must know that it will break if the result of the
-% expansion is more than one token or if |\foo:N| requires its
-% argument not to be braced.
+% Only |n|~and |N| arguments can be changed to other types. The only
+% allowed changes are
+% \begin{itemize}
+% \item |c|~variant of an |N|~parent;
+% \item |o|, |V|, |v|, |f|, or~|x| variant of an |n|~parent;
+% \item |N|, |n|, |T|, |F|, or |p| argument unchanged.
+% \end{itemize}
+% This means the \meta{parent} of a \meta{variant} form is always
+% unambiguous, even in cases where both an |n|-type parent and an
+% |N|-type parent exist, such as for \cs{tl_count:n} and
+% \cs{tl_count:N}.
+%
+% For backward compatibility it is currently possible to make |n|,
+% |o|, |V|, |v|, |f|, or |x|-type variants of an |N|-type argument or
+% |N| or |c|-type variants of an |n|-type argument. Both are
+% deprecated. The first because passing more than one token to an
+% |N|-type argument will typically break the parent function's code.
+% The second because programmers who use that most often want to
+% access the value of a variable given its name, hence should use a
+% |V|-type or |v|-type variant instead of |c|-type. In those cases,
+% using the lower-level \cs{exp_args:No} or \cs{exp_args:Nc}
+% functions explicitly is preferred to defining confusing variants.
% \end{function}
%
% \section{Introducing the variants}
%
-% The available internal functions for argument expansion come in two
-% flavours, some of them are faster then others. Therefore
-% (when speed is important) it is usually
-% best to follow the following guidelines when defining new functions
-% that are supposed to come with variant forms:
+% It is usually best to follow the following guidelines when defining
+% new functions that are supposed to come with variant forms.
% \begin{itemize}
% \item
-% Arguments that might need expansion should come first in the list of
-% arguments to make processing faster.
-% \item
-% Arguments that should consist of single tokens should come first.
-% \item
% Arguments that need full expansion (\emph{i.e.}, are denoted
% with |x|) should be avoided if possible as they can not be
% processed expandably, \emph{i.e.}, functions of this type
% cannot work correctly in arguments that are themselves subject to |x|
% expansion.
+% \end{itemize}
+% When speed is essential (for functions that do very little work and
+% are used numerous times in a document) the following applies because
+% internal functions for argument expansion come in two flavours, some
+% faster than others.
+% \begin{itemize}
% \item
-% In general, unless in the last position, multi-token arguments
-% |n|, |f|, and |o| need special processing when more than
-% one argument is being expanded. This special processing is not fast.
-% Therefore it is best to use the optimized functions, namely
-% those that contain only |N|, |c|, |V|, and |v|, and, in the last
-% position, |o|, |f|, with possible trailing |N| or |n|, which are
-% not expanded.
+% Arguments that might need expansion should come first in the list of
+% arguments.
+% \item
+% Arguments that should consist of single tokens |N|, |c|, |V|, or
+% |v| should come first among these.
+% \item
+% Arguments that appear after the first multi-token argument |n|, |f|
+% or |o| require slightly slower special processing to be expanded.
+% Therefore it is best to use the optimized functions,
+% namely those that contain only |N|, |c|, |V|, and |v|, and, in the
+% last position, |o|, |f|, with possible trailing |N| or |n| or |T|
+% or |F|, which are not expanded.
% \end{itemize}
%
% The |V| type returns the value of a register, which can be one of
-% |tl|, |int|, |skip|, |dim|, |toks|, or built-in \TeX{}
+% |tl|, |clist|, |int|, |skip|, |dim|, |muskip|, or built-in \TeX{}
% registers. The |v| type is the same except it first creates a
% control sequence out of its argument before returning the
% value.
@@ -228,10 +249,10 @@
% while using |\example:x| instead results in |\example:n { 3 , 7 }|
% 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 it does not
-% try to finish any |\if... \fi:| itself!
+% you should stick to using |TF| type functions only as the expansion
+% does not finish any |\if... \fi:| itself!
%
-% If is important to note that both \texttt{f}- and \texttt{o}-type
+% It is important to note that both \texttt{f}- and \texttt{o}-type
% expansion are concerned with the expansion of tokens from left to
% right in their arguments. In particular, \texttt{o}-type expansion
% applies to the first \emph{token} in the argument it receives: it
@@ -239,7 +260,7 @@
% \begin{verbatim}
% \exp_after:wN <base function> \exp_after:wN { <argument> }
% \end{verbatim}
-% At the same time, \texttt{f}-type expansion stops at the emph{first}
+% At the same time, \texttt{f}-type expansion stops at the \emph{first}
% non-expandable token. This means for example that both
% \begin{verbatim}
% \tl_set:No \l_tmpa_tl { { \g_tmpb_tl } }
@@ -256,17 +277,6 @@
% These functions are described in detail: expansion of multiple tokens follows
% the same rules but is described in a shorter fashion.
%
-% \begin{function}[EXP]{\exp_args:No}
-% \begin{syntax}
-% \cs{exp_args:No} \meta{function} \Arg{tokens} ...
-% \end{syntax}
-% This function absorbs two arguments (the \meta{function} name and
-% the \meta{tokens}). The \meta{tokens} are expanded once, and the result
-% is inserted in 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.
-% \end{function}
-%
% \begin{function}[EXP]{\exp_args:Nc, \exp_args:cc}
% \begin{syntax}
% \cs{exp_args:Nc} \meta{function} \Arg{tokens}
@@ -274,8 +284,8 @@
% 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 such a conversion is not possible). The result
-% is inserted into the input stream \emph{after} reinsertion
+% occurs if non-characters remain, as the conversion is not possible.)
+% 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.
%
@@ -283,6 +293,17 @@
% manner as described for the \meta{tokens}.
% \end{function}
%
+% \begin{function}[EXP]{\exp_args:No}
+% \begin{syntax}
+% \cs{exp_args:No} \meta{function} \Arg{tokens} ...
+% \end{syntax}
+% This function absorbs two arguments (the \meta{function} name and
+% the \meta{tokens}). The \meta{tokens} are expanded once, and the result
+% is inserted in 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.
+% \end{function}
+%
% \begin{function}[EXP]{\exp_args:NV}
% \begin{syntax}
% \cs{exp_args:NV} \meta{function} \meta{variable}
@@ -301,8 +322,8 @@
% 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 such a conversion is not possible). This control sequence
-% should
+% occurs if non-characters remain, as the conversion is not possible.)
+% 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
@@ -315,7 +336,8 @@
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are fully expanded until the
-% first non-expandable token or space is found, and the result
+% first non-expandable token is found (if that is a space it is
+% removed), and the result
% is inserted in 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.
@@ -326,8 +348,8 @@
% \cs{exp_args:Nx} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
-% the \meta{tokens}) and exhaustively expands the \meta{tokens}
-% second. The result is inserted in braces into the input stream
+% the \meta{tokens}) and exhaustively expands the \meta{tokens}.
+% The result is inserted in 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.
@@ -337,14 +359,16 @@
%
% \begin{function}[EXP]
% {
-% \exp_args:NNo,
% \exp_args:NNc,
-% \exp_args:NNv,
+% \exp_args:NNo,
% \exp_args:NNV,
+% \exp_args:NNv,
% \exp_args:NNf,
+% \exp_args:Ncc,
% \exp_args:Nco,
+% \exp_args:NcV,
+% \exp_args:Ncv,
% \exp_args:Ncf,
-% \exp_args:Ncc,
% \exp_args:NVV
% }
% \begin{syntax}
@@ -358,15 +382,17 @@
%
% \begin{function}[EXP, updated = 2012-01-14]
% {
+% \exp_args:Nnc,
% \exp_args:Nno,
% \exp_args:NnV,
+% \exp_args:Nnv,
% \exp_args:Nnf,
+% \exp_args:Noc,
% \exp_args:Noo,
% \exp_args:Nof,
-% \exp_args:Noc,
-% \exp_args:Nff,
+% \exp_args:NVo,
% \exp_args:Nfo,
-% \exp_args:Nnc
+% \exp_args:Nff,
% }
% \begin{syntax}
% \cs{exp_args:Noo} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
@@ -375,14 +401,14 @@
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments.
-% These functions need special (slower) processing.
+% These functions need slower processing.
% \end{function}
%
% \begin{function}
% {
% \exp_args:NNx,
-% \exp_args:Nnx,
% \exp_args:Ncx,
+% \exp_args:Nnx,
% \exp_args:Nox,
% \exp_args:Nxo,
% \exp_args:Nxx
@@ -394,7 +420,7 @@
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments. These functions
-% are not expandable.
+% are not expandable due to their |x|-type argument.
% \end{function}
%
% \section{Manipulating three arguments}
@@ -419,11 +445,22 @@
%
% \begin{function}[EXP]
% {
-% \exp_args:NNoo,
+% \exp_args:NNcf,
% \exp_args:NNno,
-% \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{syntax}
% \cs{exp_args:NNoo} \meta{token_1} \meta{token_2} \Arg{token_3} \Arg{tokens}
@@ -432,7 +469,7 @@
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc}.
-% These functions need special (slower) processing.
+% These functions need slower processing.
% \end{function}
%
% \begin{function}[added = 2015-08-12]
@@ -440,11 +477,11 @@
% \exp_args:NNNx,
% \exp_args:NNnx,
% \exp_args:NNox,
+% \exp_args:Nccx,
+% \exp_args:Ncnx,
% \exp_args:Nnnx,
% \exp_args:Nnox,
% \exp_args:Noox,
-% \exp_args:Ncnx,
-% \exp_args:Nccx
% }
% \begin{syntax}
% \cs{exp_args:NNnx} \meta{token_1} \meta{token_2} \Arg{tokens_1} \Arg{tokens_2}
@@ -459,21 +496,22 @@
%
% \begin{function}[EXP, updated = 2012-02-12]
% {
-% \exp_last_unbraced:NV,
-% \exp_last_unbraced:Nf,
% \exp_last_unbraced:No,
+% \exp_last_unbraced:NV,
% \exp_last_unbraced:Nv,
+% \exp_last_unbraced:Nf,
+% \exp_last_unbraced:NNo,
+% \exp_last_unbraced:NNV,
% \exp_last_unbraced:Nco,
% \exp_last_unbraced:NcV,
-% \exp_last_unbraced:NNV,
-% \exp_last_unbraced:NNo,
% \exp_last_unbraced:Nno,
% \exp_last_unbraced:Noo,
% \exp_last_unbraced:Nfo,
-% \exp_last_unbraced:NNNV,
% \exp_last_unbraced:NNNo,
-% \exp_last_unbraced:NnNo
-% }
+% \exp_last_unbraced:NNNV,
+% \exp_last_unbraced:NnNo,
+% \exp_last_unbraced:NNNNo,
+% }
% \begin{syntax}
% \cs{exp_last_unbraced:Nno} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
@@ -481,8 +519,8 @@
% specification, carry out the expansion
% indicated and leave the results in the input stream, with the
% last argument not surrounded by the usual braces.
-% Of these, the \texttt{:Nno}, \texttt{:Noo}, and \texttt{:Nfo}
-% variants need special (slower) processing.
+% Of these, the |:Nno|, |:Noo|, |:Nfo| and |:NnNo|
+% variants need slower processing.
% \begin{texnote}
% As an optimization, the last argument is unbraced by some
% of those functions before expansion. This can cause problems
@@ -496,8 +534,8 @@
% \begin{syntax}
% \cs{exp_last_unbraced:Nx} \meta{function} \Arg{tokens}
% \end{syntax}
-% This functions fully expands the \meta{tokens} and leaves
-% the result in the input stream after reinsertion of \meta{function}.
+% This function fully expands the \meta{tokens} and leaves the result
+% in the input stream after reinsertion of the \meta{function}.
% This function is not expandable.
% \end{function}
%
@@ -505,7 +543,7 @@
% \begin{syntax}
% \cs{exp_last_two_unbraced:Noo} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
-% This function absorbs three arguments and expand the second and third
+% This function absorbs three arguments and expands the second and third
% once. The first argument of the function is then the next item on the
% input stream, followed by the expansion of the second and third arguments,
% which are not wrapped in braces.
@@ -522,9 +560,9 @@
% unchanged. It is important to notice that \meta{token_1} may be
% \emph{any} single token, including group-opening and -closing
% tokens (|{| or |}| assuming normal \TeX{} category codes). Unless
-% specifically required, expansion should be carried out using an
+% specifically required this should be avoided: expansion should be carried out using an
% appropriate argument specifier variant or the appropriate
-% \cs{exp_arg:N} function.
+% \cs[no-index]{exp_arg:N} function.
% \begin{texnote}
% This is the \TeX{} primitive \tn{expandafter} renamed.
% \end{texnote}
@@ -542,10 +580,16 @@
% \begin{syntax}
% \cs{exp_not:N} \meta{token}
% \end{syntax}
-% Prevents expansion of the \meta{token} in a context where it would otherwise
-% be expanded, for example an |x|-type argument.
+% Prevents expansion of the \meta{token} in a context where it would
+% otherwise be expanded, for example an |x|-type argument or the first
+% token in an |o| or |f| argument.
% \begin{texnote}
-% This is the \TeX{} \tn{noexpand} primitive.
+% 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}).
% \end{texnote}
% \end{function}
%
@@ -553,60 +597,65 @@
% \begin{syntax}
% \cs{exp_not:c} \Arg{tokens}
% \end{syntax}
-% Expands the \meta{tokens} until only unexpandable content remains, and then
-% converts this into a control sequence. Further expansion of this control
-% sequence is then inhibited.
+% 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.)
+% Further expansion of this control sequence is then inhibited using
+% \cs{exp_not:N}.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:n}
% \begin{syntax}
% \cs{exp_not:n} \Arg{tokens}
% \end{syntax}
-% Prevents expansion of the \meta{tokens} in a context where they
-% would otherwise be expanded, for example an |x|-type argument.
+% 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.
% \begin{texnote}
% This is the \eTeX{} \tn{unexpanded} primitive. Hence its argument
-% \emph{must} be surrounded by braces.
+% \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.
% \end{texnote}
% \end{function}
%
+% \begin{function}[EXP]{\exp_not:o}
+% \begin{syntax}
+% \cs{exp_not:o} \Arg{tokens}
+% \end{syntax}
+% Expands the \meta{tokens} once, then prevents any further expansion
+% in |x|-type arguments using \cs{exp_not:n}.
+% \end{function}
+%
% \begin{function}[EXP]{\exp_not:V}
% \begin{syntax}
% \cs{exp_not:V} \meta{variable}
% \end{syntax}
% Recovers the content of the \meta{variable}, then prevents expansion
-% of this material in a context where it would otherwise
-% be expanded, for example an |x|-type argument.
+% of this material in |x|-type arguments using \cs{exp_not:n}.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:v}
% \begin{syntax}
% \cs{exp_not:v} \Arg{tokens}
% \end{syntax}
-% Expands the \meta{tokens} until only unexpandable content remains, and then
-% converts this into a control sequence (which should be a \meta{variable}
-% name). The content of the \meta{variable} is recovered, and further
-% expansion is prevented in a context where it would otherwise
-% be expanded, for example an |x|-type argument.
-% \end{function}
-%
-% \begin{function}[EXP]{\exp_not:o}
-% \begin{syntax}
-% \cs{exp_not:o} \Arg{tokens}
-% \end{syntax}
-% Expands the \meta{tokens} once, then prevents any further expansion in a
-% context where they would otherwise
-% be expanded, for example an |x|-type argument.
+% 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.)
+% The content of the \meta{variable} is recovered, and further
+% expansion in |x|-type arguments is prevented using \cs{exp_not:n}.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:f}
% \begin{syntax}
% \cs{exp_not:f} \Arg{tokens}
% \end{syntax}
-% Expands \meta{tokens} fully until the first unexpandable token
-% is found. Expansion then stops, and the result of the expansion
-% (including any tokens which were not expanded) is protected from
-% further expansion.
+% Expands \meta{tokens} fully until the first unexpandable token is
+% found (if it is a space it is removed). Expansion then stops, and
+% the result of the expansion (including any tokens which were not
+% expanded) is protected from further expansion in |x|-type arguments
+% using \cs{exp_not:n}.
% \end{function}
%
% \begin{function}[updated = 2011-06-03, EXP]{\exp_stop_f:}
@@ -710,7 +759,7 @@
% in |#2|. For technical reasons this has to happen using two tokens
% (if they would be hidden inside another command \cs{exp_after:wN}
% would only expand the command but not trigger any additional
-% f-expansion).
+% |f|-expansion).
%
% You might wonder why there are two different approaches available,
% after all the effect of
@@ -740,18 +789,18 @@
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end_continue_f:nw} \meta{further-tokens}
% \end{syntax}
% The difference to \cs{exp_end_continue_f:w} is that we first we pick
-% up an argument which is then returned to the input stream. If
-% \meta{further-tokens} starts with a brace group then the braces
-% are removed. If on the other hand it starts with space tokens then
-% these space tokens are removed while searching for the
-% argument. Thus such space tokens will not terminate the \texttt{f}-type expansion.
+% up an argument which is then returned to the input stream. If
+% \meta{further-tokens} starts with space tokens then these space
+% tokens are removed while searching for the argument. If it starts
+% with a brace group then the braces are removed. Thus such spaces or
+% 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 variables to temporarily store
-% results of the argument expansion. This is done to avoid interference
+% 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}
%
@@ -781,15 +830,16 @@
% \begin{macro}{\exp_after:wN}
% \begin{macro}{\exp_not:N}
% \begin{macro}{\exp_not:n}
-% These are defined in \pkg{l3basics}.
+% These are defined in \pkg{l3basics}, as they are needed
+% \enquote{early}. This is just a reminder of that fact!
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{General expansion}
%
-% In this section a general mechanism for defining functions to handle
-% argument handling is defined. These general expansion functions are
+% In this section a general mechanism for defining functions that handle
+% arguments is defined. These general expansion functions are
% expandable unless |x| is used. (Any version of |x| is going to have
% to use one of the \LaTeX3 names for \cs{cs_set:Npx} at some
% point, and so is never going to be expandable.)
@@ -800,15 +850,12 @@
% method for efficiency, typically using calls to \cs{exp_after:wN}.
%
% \begin{variable}{\l_@@_internal_tl}
-% This scratch token list variable is defined in \pkg{l3basics}, as it
-% is needed \enquote{early}. This is just a reminder that is the
-% case!
+% This scratch token list variable is defined in \pkg{l3basics}.
% \end{variable}
%
-% This code uses internal functions with names that start with |\::|
-% to perform the expansions. All macros are |long| as this turned out
-% to be desirable since the tokens undergoing expansion may be
-% arbitrary user input.
+% This code uses internal functions with names that start with |\::| to
+% perform the expansions. All macros are |long| since the tokens
+% undergoing expansion may be arbitrary user input.
%
% An argument manipulator |\::|\meta{Z} always has signature |#1\:::#2#3|
% where |#1| holds the remaining argument manipulations to be performed,
@@ -818,8 +865,8 @@
% One exception to this rule is \cs{::p}, which has to grab an argument
% delimited by a left brace.
%
-% \begin{macro}[aux, EXP]{\@@_arg_next:nnn}
-% \begin{macro}[aux, EXP]{\@@_arg_next:Nnn}
+% \begin{macro}[EXP]{\@@_arg_next:nnn}
+% \begin{macro}[EXP]{\@@_arg_next:Nnn}
% |#1| is the result of an expansion step, |#2| is the remaining
% argument manipulations and |#3| is the current result of the
% expansion chain. This auxiliary function moves |#1| back after
@@ -836,14 +883,14 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\:::}
+% \begin{macro}{\:::}
% The end marker is just another name for the identity function.
% \begin{macrocode}
\cs_new:Npn \::: #1 {#1}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::n}
+% \begin{macro}[EXP]{\::n}
% This function is used to skip an argument that doesn't need to
% be expanded.
% \begin{macrocode}
@@ -851,7 +898,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::N}
+% \begin{macro}[EXP]{\::N}
% This function is used to skip an argument that consists of a
% single token and doesn't need to be expanded.
% \begin{macrocode}
@@ -859,16 +906,16 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::p}
+% \begin{macro}[EXP]{\::p}
% This function is used to skip an argument that is delimited by a
-% left brace and doesn't need to be expanded. It should not be
+% left brace and doesn't need to be expanded. It is not
% wrapped in braces in the result.
% \begin{macrocode}
\cs_new:Npn \::p #1 \::: #2#3# { #1 \::: {#2#3} }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::c}
+% \begin{macro}[EXP]{\::c}
% This function is used to skip an argument that is turned into
% a control sequence without expansion.
% \begin{macrocode}
@@ -877,7 +924,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::o}
+% \begin{macro}[EXP]{\::o}
% This function is used to expand an argument once.
% \begin{macrocode}
\cs_new:Npn \::o #1 \::: #2#3
@@ -885,23 +932,22 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::f}
+% \begin{macro}[EXP]{\::f}
% \begin{macro}{\exp_stop_f:}
% This function is used to expand a token list until the first
% unexpandable token is found. This is achieved through \cs{exp:w}
-% \cs{exp_end_continue_f:w} that
-% expands everything in its way following it. This
-% scanning procedure is terminated once the expansion hits
-% something non-expandable or a space. We introduce \cs{exp_stop_f:}
-% to mark such an end of expansion marker.
-% In the example shown earlier the scanning was stopped
-% once \TeX{} had fully expanded |\cs_set_eq:Nc \aaa { b \l_tmpa_tl b }|
-% into |\cs_set_eq:NN \aaa = \blurb| which then turned out to contain
-% the non-expandable token \cs{cs_set_eq:NN}. Since the expansion of
-% \cs{exp:w} \cs{exp_end_continue_f:w} is \meta{null}, we wind up with a fully
-% expanded list, only \TeX{} has not tried to execute any of the
-% non-expandable tokens. This is what differentiates this function
-% from the |x| argument type.
+% \cs{exp_end_continue_f:w} that expands everything in its way
+% following it. This scanning procedure is terminated once the
+% expansion hits something non-expandable (if that is a space it is
+% removed). We introduce \cs{exp_stop_f:} to mark such an
+% end-of-expansion marker. For example, |f|-expanding
+% |\cs_set_eq:Nc \aaa { b \l_tmpa_tl b }| where |\l_tmpa_tl| contains
+% the characters |lur| gives |\tex_let:D \aaa = \blurb| which then
+% turns out to start with the non-expandable token |\tex_let:D|.
+% Since the expansion of \cs{exp:w} \cs{exp_end_continue_f:w} is
+% empty, we wind up with a fully expanded list, only \TeX{} has not
+% tried to execute any of the non-expandable tokens. This is what
+% differentiates this function from the |x| argument type.
% \begin{macrocode}
\cs_new:Npn \::f #1 \::: #2#3
{
@@ -914,7 +960,7 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\::x}
+% \begin{macro}{\::x}
% This function is used to expand an argument fully.
% \begin{macrocode}
\cs_new_protected:Npn \::x #1 \::: #2#3
@@ -925,10 +971,11 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\::v}
-% \begin{macro}[int, EXP]{\::V}
+% \begin{macro}[EXP]{\::v}
+% \begin{macro}[EXP]{\::V}
% These functions return the value of a register, i.e., one of
-% |tl|, |clist|, |int|, |skip|, |dim| and |muskip|. The |V| version
+% |tl|, |clist|, |int|, |skip|, |dim|, |muskip|, or built-in
+% \TeX{} register. The |V| version
% expects a single token whereas |v| like |c| creates a csname from
% its argument given in braces and then evaluates it as if it was a
% |V|. The \cs{exp:w} sets off an expansion
@@ -951,8 +998,8 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\@@_eval_register:N, \@@_eval_register:c}
-% \begin{macro}[aux, EXP]{\@@_eval_error_msg:w}
+% \begin{macro}[EXP]{\@@_eval_register:N, \@@_eval_register:c}
+% \begin{macro}[EXP]{\@@_eval_error_msg:w}
% This function evaluates a register. Now a register might exist as
% one of two things: A parameter-less macro or a built-in \TeX{}
% register such as |\count|. For the \TeX{} registers we have to
@@ -1027,23 +1074,7 @@
% \label{sec:l3expan:handtune}
%
% One of the most important features of these functions is that they
-% are fully expandable and therefore allow to prefix them with
-% \cs{tex_global:D} for example.
-%
-% \begin{macro}[EXP]{\exp_args:No}
-% \begin{macro}[EXP]{\exp_args:NNo}
-% \begin{macro}[EXP]{\exp_args:NNNo}
-% Those lovely runs of expansion!
-% \begin{macrocode}
-\cs_new:Npn \exp_args:No #1#2 { \exp_after:wN #1 \exp_after:wN {#2} }
-\cs_new:Npn \exp_args:NNo #1#2#3
- { \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN {#3} }
-\cs_new:Npn \exp_args:NNNo #1#2#3#4
- { \exp_after:wN #1 \exp_after:wN#2 \exp_after:wN #3 \exp_after:wN {#4} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% are fully expandable.
%
% \begin{macro}[EXP]{\exp_args:Nc, \exp_args:cc}
% In \pkg{l3basics}.
@@ -1067,6 +1098,21 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[EXP]{\exp_args:No}
+% \begin{macro}[EXP]{\exp_args:NNo}
+% \begin{macro}[EXP]{\exp_args:NNNo}
+% Those lovely runs of expansion!
+% \begin{macrocode}
+\cs_new:Npn \exp_args:No #1#2 { \exp_after:wN #1 \exp_after:wN {#2} }
+\cs_new:Npn \exp_args:NNo #1#2#3
+ { \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN {#3} }
+\cs_new:Npn \exp_args:NNNo #1#2#3#4
+ { \exp_after:wN #1 \exp_after:wN#2 \exp_after:wN #3 \exp_after:wN {#4} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}[EXP]{\exp_args:Nf, \exp_args:NV, \exp_args:Nv}
% \begin{macrocode}
\cs_new:Npn \exp_args:Nf #1#2
@@ -1087,19 +1133,19 @@
% \begin{macro}[EXP]
% {
% \exp_args:NNV, \exp_args:NNv, \exp_args:NNf,
+% \exp_args:Nco, \exp_args:NcV, \exp_args:Ncv, \exp_args:Ncf,
% \exp_args:NVV,
-% \exp_args:Ncf, \exp_args:Nco
% }
% Some more hand-tuned function with three arguments.
% If we forced that an |o| argument always has braces,
% we could implement \cs{exp_args:Nco} with less tokens
% and only two arguments.
% \begin{macrocode}
-\cs_new:Npn \exp_args:NNf #1#2#3
+\cs_new:Npn \exp_args:NNV #1#2#3
{
\exp_after:wN #1
\exp_after:wN #2
- \exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
+ \exp_after:wN { \exp:w \@@_eval_register:N #3 }
}
\cs_new:Npn \exp_args:NNv #1#2#3
{
@@ -1107,11 +1153,11 @@
\exp_after:wN #2
\exp_after:wN { \exp:w \@@_eval_register:c {#3} }
}
-\cs_new:Npn \exp_args:NNV #1#2#3
+\cs_new:Npn \exp_args:NNf #1#2#3
{
\exp_after:wN #1
\exp_after:wN #2
- \exp_after:wN { \exp:w \@@_eval_register:N #3 }
+ \exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
}
\cs_new:Npn \exp_args:Nco #1#2#3
{
@@ -1119,6 +1165,18 @@
\cs:w #2 \exp_after:wN \cs_end:
\exp_after:wN {#3}
}
+\cs_new:Npn \exp_args:NcV #1#2#3
+ {
+ \exp_after:wN #1
+ \cs:w #2 \exp_after:wN \cs_end:
+ \exp_after:wN { \exp:w \@@_eval_register:N #3 }
+ }
+\cs_new:Npn \exp_args:Ncv #1#2#3
+ {
+ \exp_after:wN #1
+ \cs:w #2 \exp_after:wN \cs_end:
+ \exp_after:wN { \exp:w \@@_eval_register:c {#3} }
+ }
\cs_new:Npn \exp_args:Ncf #1#2#3
{
\exp_after:wN #1
@@ -1137,8 +1195,8 @@
%
% \begin{macro}[EXP]
% {
-% \exp_args:Ncco, \exp_args:NcNc, \exp_args:NcNo,
-% \exp_args:NNNV
+% \exp_args:NNNV, \exp_args:NcNc, \exp_args:NcNo,
+% \exp_args:Ncco,
% }
% A few more that we can hand-tune.
% \begin{macrocode}
@@ -1178,7 +1236,7 @@
%
% Some of these could be done more efficiently, but the complexity of
% coding then becomes an issue. Notice that the auto-generated functions
-% are all not long: they don't actually take any arguments themselves.
+% actually take no arguments themselves.
%
% \begin{macro}{\exp_args:Nx}
% \begin{macrocode}
@@ -1188,9 +1246,9 @@
%
% \begin{macro}[EXP]
% {
-% \exp_args:Nnc, \exp_args:Nfo, \exp_args:Nff, \exp_args:Nnf,
-% \exp_args:Nno, \exp_args:NnV, \exp_args:Noo, \exp_args:Nof,
-% \exp_args:Noc
+% \exp_args:Nnc, \exp_args:Nno, \exp_args:NnV, \exp_args:Nnv, \exp_args:Nnf,
+% \exp_args:Noc, \exp_args:Noo, \exp_args:Nof,
+% \exp_args:NVo, \exp_args:Nfo, \exp_args:Nff,
% }
% \begin{macro}
% {
@@ -1201,14 +1259,16 @@
% above.
% \begin{macrocode}
\cs_new:Npn \exp_args:Nnc { \::n \::c \::: }
-\cs_new:Npn \exp_args:Nfo { \::f \::o \::: }
-\cs_new:Npn \exp_args:Nff { \::f \::f \::: }
-\cs_new:Npn \exp_args:Nnf { \::n \::f \::: }
\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: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:Noc { \::o \::c \::: }
+\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 \::: }
@@ -1221,21 +1281,35 @@
%
% \begin{macro}[EXP]
% {
-% \exp_args:NNno, \exp_args:NNoo,
-% \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nooo,
+% \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:Nnnx, \exp_args:Nnox,
-% \exp_args:Nccx, \exp_args:Ncnx, \exp_args:Noox,
+% \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: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 \::: }
@@ -1250,21 +1324,16 @@
%
% \subsection{Last-unbraced versions}
%
-% \begin{macro}[aux, EXP]{\@@_arg_last_unbraced:nn}
-% \begin{macro}[aux, EXP]{\::f_unbraced}
-% \begin{macro}[aux, EXP]{\::o_unbraced}
-% \begin{macro}[aux, EXP]{\::V_unbraced}
-% \begin{macro}[aux, EXP]{\::v_unbraced}
-% \begin{macro}[aux, EXP]{\::x_unbraced}
+% \begin{macro}[EXP]{\@@_arg_last_unbraced:nn}
+% \begin{macro}[EXP]{\::o_unbraced}
+% \begin{macro}[EXP]{\::V_unbraced}
+% \begin{macro}[EXP]{\::v_unbraced}
+% \begin{macro}[EXP]{\::f_unbraced}
+% \begin{macro}[EXP]{\::x_unbraced}
% There are a few places where the last argument needs to be available
% unbraced. First some helper macros.
% \begin{macrocode}
\cs_new:Npn \@@_arg_last_unbraced:nn #1#2 { #2#1 }
-\cs_new:Npn \::f_unbraced \::: #1#2
- {
- \exp_after:wN \@@_arg_last_unbraced:nn
- \exp_after:wN { \exp:w \exp_end_continue_f:w #2 } {#1}
- }
\cs_new:Npn \::o_unbraced \::: #1#2
{ \exp_after:wN \@@_arg_last_unbraced:nn \exp_after:wN {#2} {#1} }
\cs_new:Npn \::V_unbraced \::: #1#2
@@ -1277,6 +1346,11 @@
\exp_after:wN \@@_arg_last_unbraced:nn
\exp_after:wN { \exp:w \@@_eval_register:c {#2} } {#1}
}
+\cs_new:Npn \::f_unbraced \::: #1#2
+ {
+ \exp_after:wN \@@_arg_last_unbraced:nn
+ \exp_after:wN { \exp:w \exp_end_continue_f:w #2 } {#1}
+ }
\cs_new_protected:Npn \::x_unbraced \::: #1#2
{
\cs_set_nopar:Npx \l_@@_internal_tl { \exp_not:n {#1} #2 }
@@ -1290,47 +1364,53 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\exp_last_unbraced:NV}
-% \begin{macro}[EXP]{\exp_last_unbraced:Nv}
-% \begin{macro}[EXP]{\exp_last_unbraced:Nf}
-% \begin{macro}[EXP]{\exp_last_unbraced:No}
-% \begin{macro}[EXP]{\exp_last_unbraced:Nco}
-% \begin{macro}[EXP]{\exp_last_unbraced:NcV}
-% \begin{macro}[EXP]{\exp_last_unbraced:NNV}
-% \begin{macro}[EXP]{\exp_last_unbraced:NNo}
-% \begin{macro}[EXP]{\exp_last_unbraced:NNNV}
-% \begin{macro}[EXP]{\exp_last_unbraced:NNNo}
-% \begin{macro}[EXP]{\exp_last_unbraced:Nno}
-% \begin{macro}[EXP]{\exp_last_unbraced:Noo}
-% \begin{macro}[EXP]{\exp_last_unbraced:Nfo}
-% \begin{macro}[EXP]{\exp_last_unbraced:NnNo}
+% \begin{macro}[EXP]
+% {
+% \exp_last_unbraced:No,
+% \exp_last_unbraced:NV,
+% \exp_last_unbraced:Nv,
+% \exp_last_unbraced:Nf,
+% \exp_last_unbraced:NNo,
+% \exp_last_unbraced:NNV,
+% \exp_last_unbraced:Nco,
+% \exp_last_unbraced:NcV,
+% \exp_last_unbraced:NNNo,
+% \exp_last_unbraced:NNNV,
+% \exp_last_unbraced:Nno,
+% \exp_last_unbraced:Noo,
+% \exp_last_unbraced:Nfo,
+% \exp_last_unbraced:NnNo,
+% \exp_last_unbraced:NNNNo,
+% }
% \begin{macro}{\exp_last_unbraced:Nx}
% Now the business end: most of these are hand-tuned for speed, but the
% general system is in place.
% \begin{macrocode}
+\cs_new:Npn \exp_last_unbraced:No #1#2 { \exp_after:wN #1 #2 }
\cs_new:Npn \exp_last_unbraced:NV #1#2
{ \exp_after:wN #1 \exp:w \@@_eval_register:N #2 }
\cs_new:Npn \exp_last_unbraced:Nv #1#2
{ \exp_after:wN #1 \exp:w \@@_eval_register:c {#2} }
-\cs_new:Npn \exp_last_unbraced:No #1#2 { \exp_after:wN #1 #2 }
\cs_new:Npn \exp_last_unbraced:Nf #1#2
{ \exp_after:wN #1 \exp:w \exp_end_continue_f:w #2 }
-\cs_new:Npn \exp_last_unbraced:Nco #1#2#3
- { \exp_after:wN #1 \cs:w #2 \exp_after:wN \cs_end: #3 }
-\cs_new:Npn \exp_last_unbraced:NcV #1#2#3
+\cs_new:Npn \exp_last_unbraced:NNo #1#2#3
+ { \exp_after:wN #1 \exp_after:wN #2 #3 }
+\cs_new:Npn \exp_last_unbraced:NNV #1#2#3
{
\exp_after:wN #1
- \cs:w #2 \exp_after:wN \cs_end:
+ \exp_after:wN #2
\exp:w \@@_eval_register:N #3
}
-\cs_new:Npn \exp_last_unbraced:NNV #1#2#3
+\cs_new:Npn \exp_last_unbraced:Nco #1#2#3
+ { \exp_after:wN #1 \cs:w #2 \exp_after:wN \cs_end: #3 }
+\cs_new:Npn \exp_last_unbraced:NcV #1#2#3
{
\exp_after:wN #1
- \exp_after:wN #2
+ \cs:w #2 \exp_after:wN \cs_end:
\exp:w \@@_eval_register:N #3
}
-\cs_new:Npn \exp_last_unbraced:NNo #1#2#3
- { \exp_after:wN #1 \exp_after:wN #2 #3 }
+\cs_new:Npn \exp_last_unbraced:NNNo #1#2#3#4
+ { \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 #4 }
\cs_new:Npn \exp_last_unbraced:NNNV #1#2#3#4
{
\exp_after:wN #1
@@ -1338,32 +1418,19 @@
\exp_after:wN #3
\exp:w \@@_eval_register:N #4
}
-\cs_new:Npn \exp_last_unbraced:NNNo #1#2#3#4
- { \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 #4 }
\cs_new:Npn \exp_last_unbraced:Nno { \::n \::o_unbraced \::: }
\cs_new:Npn \exp_last_unbraced:Noo { \::o \::o_unbraced \::: }
\cs_new:Npn \exp_last_unbraced:Nfo { \::f \::o_unbraced \::: }
\cs_new:Npn \exp_last_unbraced:NnNo { \::n \::N \::o_unbraced \::: }
+\cs_new:Npn \exp_last_unbraced:NNNNo #1#2#3#4#5
+ { \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 \exp_after:wN #4 #5 }
\cs_new_protected:Npn \exp_last_unbraced:Nx { \::x_unbraced \::: }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
% \begin{macro}[EXP]{\exp_last_two_unbraced:Noo}
-% \begin{macro}[EXP, aux]{\@@_last_two_unbraced:noN}
+% \begin{macro}[EXP]{\@@_last_two_unbraced:noN}
% If |#2| is a single token then this can be implemented as
% \begin{verbatim}
% \cs_new:Npn \exp_last_two_unbraced:Noo #1 #2 #3
@@ -1382,14 +1449,16 @@
%
% \subsection{Preventing expansion}
%
-% \begin{macro}[EXP]{\exp_not:o}
% \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}.
% \begin{macrocode}
-\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} }
\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:f #1
{ \etex_unexpanded:D \exp_after:wN { \exp:w \exp_end_continue_f:w #1 } }
\cs_new:Npn \exp_not:V #1
@@ -1415,57 +1484,54 @@
% \begin{macro}{\exp_end:}
% \begin{macro}{\exp_end_continue_f:w}
% \begin{macro}{\exp_end_continue_f:nw}
-%
-% To trigger a sequence of \enquote{arbitrary} many expansions we need a
-% method to invoke \TeX's expansion mechanism in such a way that a)
-% we are able to stop it in a controlled manner and b) that the
-% result of what triggered the expansion in the first place is
-% null, i.e., that we do not get any unwanted side effects. There
-% aren't that many possibilities in \TeX{}; in fact the one
-% explained below might well be the only one (as normally the
-% result of expansion is not null).
-%
-% The trick here is to make use of the fact that
-% \cs{tex_romannumeral:D} expands the tokens following it when
-% looking for a number and that its expansion is null if that
-% number turns out to be zero or negative. So we use that to start
-% the expansion sequence.
+% To trigger a sequence of \enquote{arbitrarily} many expansions we
+% need a method to invoke \TeX's expansion mechanism in such a way
+% that (a) we are able to stop it in a controlled manner and (b) the
+% result of what triggered the expansion in the first place is null,
+% i.e.\@, that we do not get any unwanted side effects. There aren't
+% that many possibilities in \TeX{}; in fact the one explained below
+% might well be the only one (as normally the result of expansion is
+% not null).
+%
+% The trick here is to make use of the fact that
+% \cs{tex_romannumeral:D} expands the tokens following it when looking
+% for a number and that its expansion is null if that number turns out
+% to be zero or negative. So we use that to start the expansion
+% sequence: \cs{exp:w} is set equal to \cs{tex_romannumeral:D} in
+% \pkg{l3basics}. To stop the expansion sequence in a controlled way
+% all we need to provide is a constant integer zero as part of
+% expanded tokens. As this is an integer constant it immediately stops
+% \cs{tex_romannumeral:D}'s search for a number. Again, the
+% definition of \cs{exp_end:} as the integer constant zero is in
+% \pkg{l3basics}. (Note that according to our specification all
+% tokens we expand initiated by \cs{exp:w} are supposed to be
+% expandable (as well as their replacement text in the expansion) so
+% we will not encounter a \enquote{number} that actually result in a
+% roman numeral being generated. Or if we do then the programmer made
+% a mistake.)
+%
+% If on the other hand we want to stop the initial expansion sequence
+% but continue with an \texttt{f}-type expansion we provide the
+% alphabetic constant |`^^@| that also represents |0| but this time
+% \TeX's syntax for a \meta{number} continues searching for an
+% optional space (and it continues expansion doing that) --- see
+% \TeX{}book page~269 for details.
% \begin{macrocode}
-%\cs_new_eq:NN \exp:w \tex_romannumeral:D
-% \end{macrocode}
-% So to stop the expansion sequence in a controlled way all we need
-% to provide is a constant integer zero as part of expanded tokens. As this is
-% an integer constant it immediately stops
-% \cs{tex_romannumerl:D}'s search for a number.
-% \begin{macrocode}
-%\int_const:Nn \exp_end: { 0 }
-% \end{macrocode}
-% (Note that according to our specification all tokens we expand
-% initiated by \cs{exp:w} are supposed to be expandable (as well as
-% their replacement text in the expansion) so we will not encounter
-% a \enquote{number} that actually result in a roman numeral being
-% generated. Or if we do then the programmer made a mistake.)
-%
-% If on the other hand we want to stop the initial expansion
-% sequence but continue with an \texttt{f}-type expansion we provide the
-% alphabetic constant |`^^@| that also represents |0| but this time
-% \TeX's syntax for a \meta{number} continues searching for an
-% optional space (and it continues expansion doing that) ---
-% see \TeX{}book page~269 for details.
-% \begin{macrocode}
-\tex_catcode:D `\^^@=13
-\cs_new_protected:Npn \exp_end_continue_f:w {`^^@}
+\group_begin:
+ \tex_catcode:D `\^^@ = 13
+ \cs_new_protected:Npn \exp_end_continue_f:w { `^^@ }
% \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.\footnote{Need to get a real error message.}
+% error.
% \begin{macrocode}
-\cs_new:Npn ^^@{\expansionERROR}
+ \cs_new:Npn ^^@
+ { \__msg_kernel_expandable_error:nn { kernel } { bad-exp-end-f } }
% \end{macrocode}
-%
+% The same but grabbing an argument to remove spaces and braces.
% \begin{macrocode}
-\cs_new:Npn \exp_end_continue_f:nw #1 { `^^@ #1 }
-\tex_catcode:D `\^^@=15
+ \cs_new:Npn \exp_end_continue_f:nw #1 { `^^@ #1 }
+\group_end:
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1507,13 +1573,13 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\@@_generate_variant:N}
-% \begin{macro}[aux]{\@@_generate_variant:ww, \@@_generate_variant:wwNw}
+% \begin{macro}{\@@_generate_variant:N}
+% \begin{macro}{\@@_generate_variant:ww, \@@_generate_variant:wwNw}
% The goal here is to pick up protected parent functions. There are
% four cases: the parent function can be a primitive or a macro, and
% can be expandable or not. For non-expandable primitives, all
% variants should be protected; skipping the \cs{else:} branch is safe
-% because all primitive \TeX{} conditionals are expandable.
+% because non-expandable primitives cannot be \TeX{} conditionals.
%
% The other case where variants should be protected is when the parent
% function is a protected macro: then |protected| appears in the
@@ -1546,24 +1612,19 @@
\exp_not:N \q_stop
\exp_not:N \fi:
}
-\use:x
- {
- \cs_new_protected:Npn \exp_not:N \@@_generate_variant:ww
- ##1 \tl_to_str:n { ma } ##2 \exp_not:N \q_mark
- }
- { \@@_generate_variant:wwNw #1 }
-\use:x
- {
- \cs_new_protected:Npn \exp_not:N \@@_generate_variant:wwNw
- ##1 \tl_to_str:n { pr } ##2 \exp_not:N \q_mark
- ##3 ##4 \exp_not:N \q_stop
- }
- { \cs_set_eq:NN \@@_tmp:w #3 }
+\exp_last_unbraced:NNNNo
+ \cs_new_protected:Npn \@@_generate_variant:ww
+ #1 { \tl_to_str:n { ma } } #2 \q_mark
+ { \@@_generate_variant:wwNw #1 }
+\exp_last_unbraced:NNNNo
+ \cs_new_protected:Npn \@@_generate_variant:wwNw
+ #1 { \tl_to_str:n { pr } } #2 \q_mark #3 #4 \q_stop
+ { \cs_set_eq:NN \@@_tmp:w #3 }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\@@_generate_variant:nnNN}
+% \begin{macro}{\@@_generate_variant:nnNN}
% \begin{arguments}
% \item Base name.
% \item Base signature.
@@ -1587,7 +1648,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\@@_generate_variant:Nnnw}
+% \begin{macro}{\@@_generate_variant:Nnnw}
% \begin{arguments}
% \item Base function.
% \item Base name.
@@ -1603,32 +1664,34 @@
%
% There are further subtleties:
% \begin{itemize}
-% \item In \cs{cs_generate_variant:Nn} |\foo:nnTF| |{xxTF}|, it
-% would be better to define |\foo:xxTF| using |\exp_args:Nxx|,
+% \item In \cs{cs_generate_variant:Nn} |\foo:nnTF| |{xxTF}|, we must define
+% |\foo:xxTF| using |\exp_args:Nxx|,
% rather than a hypothetical |\exp_args:NxxTF|. Thus, we wish to
% trim a common trailing part from the base signature and the
% variant signature.
% \item In \cs{cs_generate_variant:Nn} |\foo:on| |{ox}|, the
-% function |\foo:ox| should be defined using |\exp_args:Nnx|, not
+% function |\foo:ox| must be defined using |\exp_args:Nnx|, not
% |\exp_args:Nox|, to avoid double |o| expansion.
-% \item Lastly, \cs{cs_generate_variant:Nn} |\foo:on| |{xn}| should
+% \item Lastly, \cs{cs_generate_variant:Nn} |\foo:on| |{xn}| must
% trigger an error, because we do not have a means to replace
% |o|-expansion by |x|-expansion.
+% More generally, we can only convert |N| to |c|, or convert |n|
+% to |V|, |v|, |o|, |f|, |x|.
% \end{itemize}
% All this boils down to a few rules. Only |n| and |N|-type
% arguments can be replaced by \cs{cs_generate_variant:Nn}. Other
% argument types are allowed to be passed unchanged from the base
% form to the variant: in the process they are changed to |n|
-% (except for two cases: |N| and |p|-type arguments). A common
-% trailing part is ignored.
+% except for |N| and |p|-type arguments. A common trailing
+% part is ignored.
%
% We compare the base and variant signatures one character at a time
% within |x|-expansion. The result is given to
-% \cs{@@_generate_variant:wwNN} in the form \meta{processed variant
-% signature} \cs{q_mark} \meta{errors} \cs{q_stop} \meta{base
-% function} \meta{new function}. If all went well, \meta{errors}
-% is empty; otherwise, it is a kernel error message, followed by
-% some clean-up code (\cs{use_none:nnn}).
+% \cs{@@_generate_variant:wwNN} (defined later) in the form
+% \meta{processed variant signature} \cs{q_mark} \meta{errors}
+% \cs{q_stop} \meta{base function} \meta{new function}. If all went
+% well, \meta{errors} is empty; otherwise, it is a kernel error
+% message and some clean-up code.
%
% Note the space after |#3| and after the following brace group.
% Those are ignored by \TeX{} when fetching the last argument for
@@ -1658,17 +1721,20 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux, EXP]
+% \begin{macro}[rEXP]
% {
% \@@_generate_variant_loop:nNwN,
+% \@@_generate_variant_loop_base:N,
% \@@_generate_variant_loop_same:w,
% \@@_generate_variant_loop_end:nwwwNNnn,
% \@@_generate_variant_loop_long:wNNnn,
% \@@_generate_variant_loop_invalid:NNwNNnn,
+% \@@_generate_variant_loop_special:NNwNNnn,
+% \@@_generate_variant_loop_warning:nnxxxx
% }
% \begin{arguments}
-% \item Last few (consecutive) letters common between the base
-% and variant (in fact, \cs{@@_generate_variant_same:N}
+% \item Last few consecutive letters common between the base and
+% variant (more precisely, \cs{@@_generate_variant_same:N}
% \meta{letter} for each letter).
% \item Next variant letter.
% \item Remainder of variant form.
@@ -1680,15 +1746,16 @@
% two letters are different: if the loop ends before, the argument is
% dropped, which means that trailing common letters are ignored.
%
-% The case where the two letters are different is only allowed with a
-% base letter of |N| or |n|. Otherwise, call
+% The case where the two letters are different is only allowed if the
+% base is |N| and the variant is |c|, or when the base is |n| and the
+% variant is |o|, |V|, |v|, |f| or |x|. Otherwise, call
% \cs{@@_generate_variant_loop_invalid:NNwNNnn} to remove the end of
% the loop, get arguments at the end of the loop, and place an
% appropriate error message as a second argument of
-% \cs{@@_generate_variant:wwNN}. If the letters are distinct and
-% the base letter is indeed |n| or |N|, leave in the input stream
-% whatever argument was collected, and the next variant letter |#2|,
-% then loop by calling \cs{@@_generate_variant_loop:nNwN}.
+% \cs{@@_generate_variant:wwNN}. If the letters are distinct and the
+% base letter is indeed |n| or |N|, leave in the input stream whatever
+% argument |#1| was collected, and the next variant letter |#2|, then
+% loop by calling \cs{@@_generate_variant_loop:nNwN}.
%
% The loop can stop in three ways.
% \begin{itemize}
@@ -1706,8 +1773,9 @@
% \cs{@@_generate_variant:wwNN}.
% \item The loop can be interrupted early if the requested expansion
% is unavailable, namely when the variant and base letters differ
-% and the base is neither |n| nor |N|. Again, an error is placed
-% as the second argument of \cs{@@_generate_variant:wwNN}.
+% and the base is not the right one (|n| or |N| to support the
+% variant). In that case too an error is placed as the second
+% argument of \cs{@@_generate_variant:wwNN}.
% \end{itemize}
% Note that if the variant form has the same length as the base form,
% |#2| is as described in the first point, and |#4| as described in
@@ -1715,14 +1783,23 @@
% breaking function takes the empty brace group in |#4| as its first
% argument: this empty brace group produces the correct signature for
% the full variant.
+%
+% Since people seem to have tried generating |N| or |c|-type variants
+% of |n|-type arguments, and |n|, |o|, |V|, |v|, |f|, |x| variants of
+% |N|-type arguments, in those cases we only produce a warning.
% \begin{macrocode}
\cs_new:Npn \@@_generate_variant_loop:nNwN #1#2#3 \q_mark #4
{
\if:w #2 #4
\exp_after:wN \@@_generate_variant_loop_same:w
\else:
- \if:w N #4 \else:
- \if:w n #4 \else:
+ \if:w #4 \@@_generate_variant_loop_base:N #2 \else:
+ \if:w 0
+ \if:w N #4 \else: \if:w n #4 \else: 1 \fi: \fi:
+ \if:w \scan_stop: \@@_generate_variant_loop_base:N #2 1 \fi:
+ 0
+ \@@_generate_variant_loop_special:NNwNNnn #4#2
+ \else:
\@@_generate_variant_loop_invalid:NNwNNnn #4#2
\fi:
\fi:
@@ -1732,11 +1809,29 @@
#2
\@@_generate_variant_loop:nNwN { } #3 \q_mark
}
-\cs_new:Npn \@@_generate_variant_loop_same:w
- #1 \prg_do_nothing: #2#3#4
+\cs_new:Npn \@@_generate_variant_loop_base:N #1
{
- #3 { #1 \@@_generate_variant_same:N #2 }
+ \if:w c #1 N \else:
+ \if:w o #1 n \else:
+ \if:w V #1 n \else:
+ \if:w v #1 n \else:
+ \if:w f #1 n \else:
+ \if:w x #1 n \else:
+ \if:w n #1 n \else:
+ \if:w N #1 N \else:
+ \scan_stop:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
}
+\cs_new:Npn \@@_generate_variant_loop_same:w
+ #1 \prg_do_nothing: #2#3#4
+ { #3 { #1 \@@_generate_variant_same:N #2 } }
\cs_new:Npn \@@_generate_variant_loop_end:nwwwNNnn
#1#2 \q_mark #3 ~ #4 \q_stop #5#6#7#8
{
@@ -1774,31 +1869,42 @@
#5
}
}
+\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
+ {
+ \@@_generate_variant_loop_warning:nnxxxx { kernel } { invalid-variant }
+ {#7} { \token_to_str:N #5 } {#1} {#2}
+ }
+ }
+\cs_new_protected:Npn \@@_generate_variant_loop_warning:nnxxxx
+ { \__msg_kernel_warning:nnxxxx }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux, rEXP]{\@@_generate_variant_same:N}
+% \begin{macro}[rEXP]{\@@_generate_variant_same:N}
% When the base and variant letters are identical, don't do any
% expansion. For most argument types, we can use the |n|-type
% no-expansion, but the |N| and |p| types require a slightly different
-% behaviour with respect to braces.
+% behaviour with respect to braces. For |V|-type this function could
+% output |N| to avoid adding useless braces but that is not a problem.
% \begin{macrocode}
\cs_new:Npn \@@_generate_variant_same:N #1
{
- \if:w N #1
- N
- \else:
- \if:w p #1
- p
- \else:
+ \if:w N #1 N \else:
+ \if:w p #1 p \else:
n
+ \if:w n #1 \else:
+ \@@_generate_variant_loop_special:NNwNNnn #1#1
+ \fi:
\fi:
\fi:
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\@@_generate_variant:wwNN}
+% \begin{macro}{\@@_generate_variant:wwNN}
% If the variant form has already been defined, log its existence
% (provided \texttt{log-functions} is active).
% Otherwise, make sure that the |\exp_args:N #3| form is defined, and
@@ -1833,9 +1939,9 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\@@_generate_internal_variant:n}
-% \begin{macro}[aux]{\@@_generate_internal_variant:wwnw}
-% \begin{macro}[aux, rEXP]{\@@_generate_internal_variant_loop:n}
+% \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