% \iffalse meta-comment
%
%% File: l3expan.dtx Copyright (C) 1990-2016 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
%% 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
%%
%% This file is part of the "l3kernel bundle" (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX3 Project.
%%
%% -----------------------------------------------------------------------
%
%<*driver>
\documentclass[full]{l3doc}
%</driver>
%<*driver|package>
\GetIdInfo$Id: l3expan.dtx 6684 2016-08-19 15:21:49Z bruno $
  {L3 Argument expansion}
%</driver|package>
%<*driver>
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3expan} package\\ Argument expansion^^A
%   \thanks{This file describes v\ExplFileVersion,
%      last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  The \LaTeX3 Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% This module provides generic methods for expanding \TeX{} arguments in a
% systematic manner. The functions in this module all have prefix |exp|.
%
% Not all possible variations are implemented for every base
% function. Instead only those that are used within the \LaTeX3 kernel
% or otherwise seem to be of general interest are implemented.
% Consult the module description to find out which functions are
% actually defined. The next section explains how to define missing
% variants.
%
% \section{Defining new variants}
% \label{sec:l3expan:defining-variants}
%
% The definition of variant forms for base functions may be necessary
% when writing new functions or when applying a kernel function in a
% situation that we haven't thought of before.
%
% Internally preprocessing of arguments is done with functions from the
% |\exp_| module.  They all look alike, an example would be
% \cs{exp_args:NNo}. This function has three arguments, the first and the
% second are a single tokens, while the third argument should be given
% in braces. Applying \cs{exp_args:NNo} will expand the content of third
% argument once before any expansion of the first and second arguments.
% If \cs{seq_gpush:No} was not defined it could be coded in the following way:
% \begin{verbatim}
%   \exp_args:NNo \seq_gpush:Nn
%      \g_file_name_stack
%      \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
% this base function. In the example the first argument to the base
% function should be a single token which is left unchanged while the
% second argument is expanded once. From this example we can also see
% how the variants are defined. They just expand into the appropriate
% |\exp_| function followed by the desired base function, \emph{e.g.}
% \begin{quote}
%   |\cs_generate_variant:Nn \seq_gpush:Nn { No } |
% \end{quote}
% results in the definition of |\seq_gpush:No|
% \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
% \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
% style files obsolete.
%
% The steps above may be automated by using the function
% \cs{cs_generate_variant:Nn}, described next.
%
% \section{Methods for defining variants}
% \label{sec:l3expan:variants-method}
%
% ^^A Bruno: Should we put a table of variant types (N, c, n, V, v, o, f, x) for reference here?
%
% ^^A Bruno: Should \cs_generate_variant:Nn \foo:n { c } and \foo:N { o } really be ok?
%
% \begin{function}[updated = 2015-08-06]{\cs_generate_variant:Nn}
%   \begin{syntax}
%     \cs{cs_generate_variant:Nn} \meta{parent control sequence} \Arg{variant argument specifiers}
%   \end{syntax}
%   This function is used to define argument-specifier variants of the
%   \meta{parent control sequence} for \LaTeX3 code-level macros. The
%   \meta{parent control sequence} is first separated into the
%   \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
%   defined. For each \meta{variant} given, a function is created
%   which will expand its arguments as detailed and pass them
%   to the \meta{parent control sequence}. So for example
%   \begin{verbatim}
%     \cs_set:Npn \foo:Nn #1#2 { code here }
%     \cs_generate_variant:Nn \foo:Nn { c }
%   \end{verbatim}
%   will create a new function |\foo:cn| which will expand its first
%   argument into a control sequence name and pass the result to
%   |\foo:Nn|. Similarly
%   \begin{verbatim}
%     \cs_generate_variant:Nn \foo:Nn { NV , cV }
%   \end{verbatim}
%   would generate 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
%   control sequence} is protected or if the \meta{variant} involves
%   |x|~arguments, then the \meta{variant control sequence} will also be
%   protected.  The \meta{variant} is created globally, as is any
%   \cs{exp_args:N\meta{variant}} function needed to carry out the
%   expansion.
% \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:
% \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 will
%     not work correctly in arguments that are themselves subject to |x|
%     expansion.
%   \item
%     In general, unless in the last position, multi-token arguments
%     |n|, |f|, and |o| will 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.
% \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{}
% registers. The |v| type is the same except it first creates a
% control sequence out of its argument before returning the
% value.
%
% In general, the programmer should not need to be concerned with
% expansion control. When simply using the content of a variable,
% functions with a |V| specifier should be used. For those referred to by
% (cs)name, the |v| specifier is available for the same purpose. Only when
% specific expansion steps are needed, such as when using delimited
% arguments, should the lower-level functions with |o| specifiers be employed.
%
% The |f| type is so special that it deserves an example.  It is
% typically used in contexts where only expandable commands are allowed.
% Then |x|-expansion cannot be used, and |f|-expansion provides an
% alternative that expands as much as can be done in such contexts.  For
% instance, say that we want to evaluate the integer expression $3 + 4$
% and pass the result $7$ as an argument to an expandable function
% |\example:n|.  For this, one should define a variant using
% \cs{cs_generate_variant:Nn} |\example:n| |{| |f| |}|, then do
% \begin{quote}
%   |\example:f { \int_eval:n { 3 + 4 } }|
% \end{quote}
% Note that |x|-expansion would also expand \cs{int_eval:n} fully to its
% result~$7$, but the variant |\example:x| cannot be expandable.  Note
% also that |o|-expansion would not expand \cs{int_eval:n} fully to its
% result since that function requires several expansions.  Besides the
% fact that |x|-expansion is protected rather than expandable, another
% difference between |f|-expansion and |x|-expansion is that
% |f|-expansion expands tokens from the beginning and stops as soon as a
% non-expandable token is encountered, while |x|-expansion continues
% expanding further tokens.  Thus, for instance
% \begin{quote}
%   |\example:f { \int_eval:n { 1 + 2 } , \int_eval:n { 3 + 4 } }|
% \end{quote}
% will result in the call |\example:n { 3 , \int_eval:n { 3 + 4 } }|
% 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!
%
% If 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
% is conceptually similar to
% \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}
% non-expandable token. This means for example that both
% \begin{verbatim}
%    \tl_set:No \l_tmpa_tl { { \g_tmpb_tl } }
% \end{verbatim}
% and
% \begin{verbatim}
%    \tl_set:Nf \l_tmpa_tl { { \g_tmpb_tl } }
% \end{verbatim}
% leave |\g_tmpb_tl| unchanged: |{| is the first token in the
% argument and is non-expandable.
%
% \section{Manipulating the first argument}
%
% 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 will be left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nc, \exp_args:cc}
%   \begin{syntax}
%     \cs{exp_args:Nc} \meta{function} \Arg{tokens}
%   \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
%   will occur if such a 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 will be left unchanged.
%
%   The |:cc| variant constructs the \meta{function} name in the same
%   manner as described for the \meta{tokens}.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:NV}
%   \begin{syntax}
%     \cs{exp_args:NV} \meta{function} \meta{variable}
%   \end{syntax}
%   This function absorbs two arguments (the names of the \meta{function} and
%   the \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 will be left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nv}
%   \begin{syntax}
%     \cs{exp_args:Nv} \meta{function} \Arg{tokens}
%   \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
%   will occur if such a 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
%   than one argument: all others will be left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nf}
%   \begin{syntax}
%     \cs{exp_args:Nf} \meta{function} \Arg{tokens}
%   \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
%   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 will be left unchanged.
% \end{function}
%
% \begin{function}{\exp_args:Nx}
%   \begin{syntax}
%     \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
%   \emph{after} reinsertion of the \meta{function}.
%   Thus the \meta{function} may take more
%   than one argument: all others will be left unchanged.
% \end{function}
%
% \section{Manipulating two arguments}
%
% \begin{function}[EXP]
%   {
%     \exp_args:NNo,
%     \exp_args:NNc,
%     \exp_args:NNv,
%     \exp_args:NNV,
%     \exp_args:NNf,
%     \exp_args:Nco,
%     \exp_args:Ncf,
%     \exp_args:Ncc,
%     \exp_args:NVV
%   }
%   \begin{syntax}
%     \cs{exp_args:NNc} \meta{token_1} \meta{token_2} \Arg{tokens}
%   \end{syntax}
%   These optimized functions absorb three arguments and expand the second and
%   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.
% \end{function}
%
% \begin{function}[EXP, updated = 2012-01-14]
%   {
%     \exp_args:Nno,
%     \exp_args:NnV,
%     \exp_args:Nnf,
%     \exp_args:Noo,
%     \exp_args:Nof,
%     \exp_args:Noc,
%     \exp_args:Nff,
%     \exp_args:Nfo,
%     \exp_args:Nnc
%   }
%   \begin{syntax}
%     \cs{exp_args:Noo} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
%   \end{syntax}
%   These functions absorb three arguments and expand the second and
%   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.
% \end{function}
%
% \begin{function}
%   {
%     \exp_args:NNx,
%     \exp_args:Nnx,
%     \exp_args:Ncx,
%     \exp_args:Nox,
%     \exp_args:Nxo,
%     \exp_args:Nxx
%   }
%   \begin{syntax}
%     \cs{exp_args:NNx} \meta{token_1} \meta{token_2} \Arg{tokens}
%   \end{syntax}
%   These functions absorb three arguments and expand the second and
%   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.
% \end{function}
%
% \section{Manipulating three arguments}
%
% \begin{function}[EXP]
%   {
%     \exp_args:NNNo,
%     \exp_args:NNNV,
%     \exp_args:Nccc,
%     \exp_args:NcNc,
%     \exp_args:NcNo,
%     \exp_args:Ncco
%   }
%   \begin{syntax}
%     \cs{exp_args:NNNo} \meta{token_1} \meta{token_2} \meta{token_3} \Arg{tokens}
%   \end{syntax}
%   These optimized functions absorb four arguments and expand the second, third
%   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}.
% \end{function}
%
% \begin{function}[EXP]
%   {
%     \exp_args:NNoo,
%     \exp_args:NNno,
%     \exp_args:Nnno,
%     \exp_args:Nnnc,
%     \exp_args:Nooo,
%   }
%   \begin{syntax}
%     \cs{exp_args:NNoo} \meta{token_1} \meta{token_2} \Arg{token_3} \Arg{tokens}
%   \end{syntax}
%   These functions absorb four arguments and expand the second, third
%   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.
% \end{function}
%
% \begin{function}[added = 2015-08-12]
%   {
%     \exp_args:NNNx,
%     \exp_args:NNnx,
%     \exp_args:NNox,
%     \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}
%   \end{syntax}
%   These functions absorb four arguments and expand the second, third
%   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.}
% \end{function}
%
% \section{Unbraced expansion}
%
% \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: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
%     }
%   \begin{syntax}
%     \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens_1} \meta{tokens_2}
%   \end{syntax}
%   These functions absorb the number of arguments given by their
%   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.
%   \begin{texnote}
%     As an optimization, the last argument is unbraced by some
%     of those functions before expansion. This can cause problems
%     if the argument is empty: for instance,
%     \cs{exp_last_unbraced:Nf} |\foo_bar:w| |{ }| \cs{q_stop}
%     leads to an infinite loop, as the quark is \texttt{f}-expanded.
%   \end{texnote}
% \end{function}
%
% \begin{function}{\exp_last_unbraced:Nx}
%   \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 is not expandable.
% \end{function}
%
% \begin{function}[EXP]{\exp_last_two_unbraced:Noo}
%   \begin{syntax}
%     \cs{exp_last_two_unbraced:Noo} \meta{token} \meta{tokens_1} \Arg{tokens_2}
%   \end{syntax}
%   This function absorbs three arguments and expand 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.
%   This function needs special (slower) processing.
% \end{function}
%
% \begin{function}[EXP]{\exp_after:wN}
%   \begin{syntax}
%     \cs{exp_after:wN} \meta{token_1} \meta{token_2}
%   \end{syntax}
%   Carries out a single expansion of \meta{token_2} (which may consume
%   arguments) prior to the expansion
%   of \meta{token_1}. If \meta{token_2} is a \TeX{} primitive, it will
%   be executed rather than expanded, while if \meta{token_2} has not
%   expansion (for example, if it is a character) then it will be left
%   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
%   appropriate argument specifier variant or the appropriate
%   \cs{exp_arg:N} function.
%   \begin{texnote}
%     This is the \TeX{} primitive \tn{expandafter} renamed.
%   \end{texnote}
% \end{function}
%
%
% \section{Preventing expansion}
%
% Despite the fact that the following functions are all about preventing
% expansion, they're designed to be used in an expandable context and hence
% are all marked as being `expandable' since they themselves will not appear
% after the expansion has completed.
%
% \begin{function}[EXP]{\exp_not:N}
%   \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.
%   \begin{texnote}
%     This is the \TeX{} \tn{noexpand} primitive.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:c}
%   \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.
% \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.
%   \begin{texnote}
%     This is the \eTeX{} \tn{unexpanded} primitive.  Hence its argument
%     \emph{must} be surrounded by braces.
%   \end{texnote}
% \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.
% \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.
% \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.
% \end{function}
%
% \begin{function}[updated = 2011-06-03, EXP]{\exp_stop_f:}
%   \begin{syntax}
%     |\foo_bar:f| \{ \meta{tokens} \cs{exp_stop_f:} \meta{more tokens} \}
%   \end{syntax}
%   This function terminates an \texttt{f}-type expansion. Thus if
%   a function |\foo_bar:f| starts an \texttt{f}-type expansion
%   and all of \meta{tokens} are expandable \cs{exp_stop_f:} will
%   terminate the expansion of tokens even if \meta{more tokens}
%   are also expandable. The function itself is an implicit space
%   token. Inside an \texttt{x}-type expansion, it will retain its
%   form, but when typeset it produces the underlying space (\verb*| |).
% \end{function}
%
%
% \section{Controlled expansion}
%
% The \pkg{expl3} language makes all efforts to hide the complexity of
% \TeX{} expansion from the programmer by providing concepts that
% evaluate/expand arguments of functions prior to calling the \enquote{base}
% functions. Thus, instead of using many \tn{expandafter} calls and
% other trickery it is usually a matter of choosing the right variant
% of a function to achieve a desired result.
%
% Of course, deep down \TeX{} is using expansion as always and there
% are cases where a programmer needs to control that expansion
% directly; typical situations are basic data manipulation tools. This
% section documents the functions for that level. You will find these
% commands used throughout the kernel code, but we hope that outside
% the kernel there will be little need to resort to them. Instead the
% argument manipulation methods document above should usually be sufficient.
%
% While \cs{exp_after:wN} expands one token (out of order) it is
% sometimes necessary to expand several tokens in one go. The next set
% of commands provide this functionality. Be aware that it is
% absolutely required that the programmer has full control over the
% tokens to be expanded, i.e., it is not possible to use these
% functions to expand unknown input as part of
% \meta{expandable-tokens} as that will break badly if unexpandable
% tokens are encountered in that place!
%
% \begin{function}[added=2015-08-23,EXP]
%       {
%         \exp:w ,
%         \exp_end:
%       }
%   \begin{syntax}
%     \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
%   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
%
%   In typical use cases the \cs{exp_end:} will be  hidden somewhere
%   in the replacement text of \meta{expandable-tokens} rather than
%   being on the same expansion level than \cs{exp:w}, e.g., you may
%   see code such as
%\begin{verbatim}
%    \exp:w \@@_case:NnTF #1 {#2} { } { }
%\end{verbatim}
%   where somewhere during the expansion of |\@@_case:NnTF| the
%   \cs{exp_end:} gets generated.
% \end{function}
% \footnotetext{Due to the implementation you might get the character
%   in position 0 in the current font (typically \enquote{\texttt{`}})
%   in the output without any error message!}
%
% \begin{function}[added=2015-08-23, EXP, label = \exp_end_continue_f:w]
%       {
%         \exp:w ,
%         \exp_end_continue_f:w
%       }
%   \begin{syntax}
%     \cs{exp:w} \meta{expandable-tokens} \cs{exp_end_continue_f:w} \meta{further-tokens}
%   \end{syntax}
%   Expands \meta{expandable-tokens} until reaching \cs{exp_end_continue_f:w} at
%   which point expansion continues as an f-type expansion expanding
%   \meta{further-tokens} until an unexpandable token is encountered (or
%   the f-type expansion is explicitly terminated by
%   \cs{exp_stop_f:}). As with all f-type expansions a space ending
%   the expansion will get removed.
%
%   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_continue_f:w} will be misinterpreted
%   later on.\footnotemark
%
%
%   In typical use cases  \meta{expandable-tokens} contains no tokens at all,
%   e.g., you will see code such as
%\begin{verbatim}
%    \exp_after:wN { \exp:w \exp_end_continue_f:w #2 }
%\end{verbatim}
%   where the \cs{exp_after:wN} triggers an f-expansion of the tokens
%   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).
%
%   You might wonder why there are two different approaches available,
%   after all the effect of
%   \begin{quote}
%     \cs{exp:w} \meta{expandable-tokens} \cs{exp_end:}
%   \end{quote}
%   can be alternatively achieved through an f-type expansion by using
%   \cs{exp_stop_f:}, i.e.
%   \begin{quote}
%     \cs{exp:w} \cs{exp_end_continue_f:w} \meta{expandable-tokens} \cs{exp_stop_f:}
%   \end{quote}
%   The reason is simply that the first approach is slightly faster
%   (one less token to parse and less expansion internally)
%   so in places where such performance really matters and where we
%   want to explicitly stop the expansion at a defined point the first
%   form is preferable.
% \end{function}
% \footnotetext{In this particular case you may get a character into
%    the output as well as an error message.}
%
% \begin{function}[added=2015-08-23, EXP, label = \exp_end_continue_f:nw]
%       {
%         \exp:w ,
%         \exp_end_continue_f:nw
%       }
%   \begin{syntax}
%     \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 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
%   with other functions using temporary variables.
% \end{variable}
%
% \begin{function}{\::n, \::N, \::p, \::c, \::o, \::f, \::x, \::v, \::V, \:::}
%   \begin{syntax}
%     |\cs_set: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.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3expan} implementation}
%
%    \begin{macrocode}
%<*initex|package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<@@=exp>
%    \end{macrocode}
%
% \begin{macro}{\exp_after:wN}
% \begin{macro}{\exp_not:N}
% \begin{macro}{\exp_not:n}
%   These are defined in \pkg{l3basics}.
% \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
% 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.)
%
% The definition of expansion functions with this technique happens
% in section~\ref{sec:l3expan:gendef}.
% In section~\ref{sec:l3expan:handtune} some common cases are coded by a more direct
% 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!
% \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.
%
% An argument manipulator |\::|\meta{Z} always has signature |#1\:::#2#3|
% where |#1| holds the remaining argument manipulations to be performed,
% \cs{:::} serves as an end marker for the list of manipulations, |#2|
% is the carried over result of the previous expansion steps and |#3| is
% the argument about to be processed.
% 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}
%   |#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
%   |#3| in the input stream and checks if any expansion is left to
%   be done by calling |#2|. In by far the most cases we will require
%   to add a set of braces to the result of an argument manipulation
%   so it is more effective to do it directly here. Actually, so far
%   only the |c| of the final argument manipulation variants does not
%   require a set of braces.
%    \begin{macrocode}
\cs_new:Npn \@@_arg_next:nnn #1#2#3 { #2 \::: { #3 {#1} } }
\cs_new:Npn \@@_arg_next:Nnn #1#2#3 { #2 \::: { #3 #1 } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[int]{\:::}
%   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}
%   This function is used to skip an argument that doesn't need to
%   be expanded.
%    \begin{macrocode}
\cs_new:Npn \::n #1 \::: #2#3 { #1 \::: { #2 {#3} } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, 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}
\cs_new:Npn \::N #1 \::: #2#3 { #1 \::: {#2#3} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, 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
%   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}
%   This function is used to skip an argument that is turned into
%   a control sequence without expansion.
%    \begin{macrocode}
\cs_new:Npn \::c #1 \::: #2#3
  { \exp_after:wN \@@_arg_next:Nnn \cs:w #3 \cs_end: {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::o}
%   This function is used to expand an argument once.
%    \begin{macrocode}
\cs_new:Npn \::o #1 \::: #2#3
  { \exp_after:wN \@@_arg_next:nnn \exp_after:wN {#3} {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, 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.
%    \begin{macrocode}
\cs_new:Npn \::f #1 \::: #2#3
  {
    \exp_after:wN \@@_arg_next:nnn
      \exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
      {#1} {#2}
  }
\use:nn { \cs_new_eq:NN \exp_stop_f: } { ~ }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[int]{\::x}
%   This function is used to expand an argument fully.
%    \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}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::v}
% \begin{macro}[int, EXP]{\::V}
%   These functions return the value of a register, i.e., one of
%   |tl|, |clist|, |int|, |skip|, |dim| and |muskip|. 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
%   similar to an |f| type expansion, which we will terminate using
%   \cs{exp_end:}. The argument is returned in braces.
%    \begin{macrocode}
\cs_new:Npn \::V #1 \::: #2#3
  {
    \exp_after:wN \@@_arg_next:nnn
      \exp_after:wN { \exp:w \@@_eval_register:N #3 }
      {#1} {#2}
}
\cs_new:Npn \::v # 1\::: #2#3
  {
    \exp_after:wN \@@_arg_next:nnn
      \exp_after:wN { \exp:w \@@_eval_register:c {#3} }
      {#1} {#2}
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[int, EXP]{\@@_eval_register:N, \@@_eval_register:c}
% \begin{macro}[aux, 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
%   utilize a \tn{the} whereas for the macros we merely have to
%   expand them once. The trick is to find out when to use
%   \tn{the} and when not to. What we do here is try to find out
%   whether the token will expand to something else when hit with
%   \cs{exp_after:wN}. The technique is to compare the meaning of the
%   register in question when it has been prefixed with \cs{exp_not:N}
%   and the register itself. If it is a macro, the prefixed
%   \cs{exp_not:N} will temporarily turn it into the primitive
%   \cs{scan_stop:}.
%    \begin{macrocode}
\cs_new:Npn \@@_eval_register:N #1
  {
    \exp_after:wN \if_meaning:w \exp_not:N #1 #1
%    \end{macrocode}
%   If the token was not a macro it may be a malformed variable from a
%   |c| expansion in which case it is equal to the primitive
%   \cs{scan_stop:}. In that case we throw an error. We could let \TeX{}
%   do it for us but that would result in the rather obscure
%   \begin{quote}
%     |! You can't use `\relax' after \the.|
%   \end{quote}
%   which while quite true doesn't give many hints as to what actually
%   went wrong. We provide something more sensible.
%    \begin{macrocode}
      \if_meaning:w \scan_stop: #1
        \@@_eval_error_msg:w
      \fi:
%    \end{macrocode}
%   The next bit requires some explanation. The function must be
%   initiated by \cs{exp:w} and we want to
%   terminate this expansion chain by inserting the \cs{exp_end:}
%    token.
%   However, we have to expand the register |#1| before we do
%   that. If it is a \TeX{} register, we need to execute the sequence
%   |\exp_after:wN \exp_end: \tex_the:D #1| and if it is a macro we
%   need to execute |\exp_after:wN \exp_end: #1|. We therefore issue
%   the longer of the two sequences and if the register is a macro, we
%   remove the \cs{tex_the:D}.
%    \begin{macrocode}
    \else:
      \exp_after:wN \use_i_ii:nnn
    \fi:
    \exp_after:wN \exp_end: \tex_the:D #1
  }
\cs_new:Npn \@@_eval_register:c #1
  { \exp_after:wN \@@_eval_register:N \cs:w #1 \cs_end: }
%    \end{macrocode}
%   Clean up nicely, then call the undefined control sequence. The
%   result is an error message looking like this:
%   \begin{verbatim}
%     ! Undefined control sequence.
%     <argument> \LaTeX3 error:
%                               Erroneous variable used!
%     l.55 \tl_set:Nv \l_tmpa_tl {undefined_tl}
%   \end{verbatim}
%    \begin{macrocode}
\cs_new:Npn \@@_eval_error_msg:w #1 \tex_the:D #2
  {
      \fi:
    \fi:
    \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#2}
    \exp_end:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Hand-tuned definitions}
% \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}
%
% \begin{macro}[EXP]{\exp_args:Nc, \exp_args:cc}
%   In \pkg{l3basics}.
% \end{macro}
%
% \begin{macro}[EXP]{\exp_args:NNc, \exp_args:Ncc, \exp_args:Nccc}
%   Here are the functions that turn their argument into csnames but are
%   expandable.
%    \begin{macrocode}
\cs_new:Npn \exp_args:NNc #1#2#3
  { \exp_after:wN #1 \exp_after:wN #2 \cs:w # 3\cs_end: }
\cs_new:Npn \exp_args:Ncc #1#2#3
  { \exp_after:wN #1 \cs:w #2 \exp_after:wN \cs_end: \cs:w #3 \cs_end: }
\cs_new:Npn \exp_args:Nccc #1#2#3#4
  {
    \exp_after:wN #1
      \cs:w #2 \exp_after:wN \cs_end:
      \cs:w #3 \exp_after:wN \cs_end:
      \cs:w #4 \cs_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_args:Nf, \exp_args:NV, \exp_args:Nv}
%    \begin{macrocode}
\cs_new:Npn \exp_args:Nf #1#2
  { \exp_after:wN #1 \exp_after:wN { \exp:w \exp_end_continue_f:w #2 } }
\cs_new:Npn \exp_args:Nv #1#2
  {
    \exp_after:wN #1 \exp_after:wN
      { \exp:w \@@_eval_register:c {#2} }
  }
\cs_new:Npn \exp_args:NV #1#2
  {
    \exp_after:wN #1 \exp_after:wN
      { \exp:w \@@_eval_register:N #2 }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {
%     \exp_args:NNV, \exp_args:NNv, \exp_args:NNf,
%     \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
  {
    \exp_after:wN #1
    \exp_after:wN #2
    \exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
  }
\cs_new:Npn \exp_args:NNv #1#2#3
  {
    \exp_after:wN #1
    \exp_after:wN #2
    \exp_after:wN { \exp:w \@@_eval_register:c {#3} }
  }
\cs_new:Npn \exp_args:NNV #1#2#3
  {
    \exp_after:wN #1
    \exp_after:wN #2
    \exp_after:wN { \exp:w \@@_eval_register:N #3 }
  }
\cs_new:Npn \exp_args:Nco #1#2#3
  {
    \exp_after:wN #1
    \cs:w #2 \exp_after:wN \cs_end:
    \exp_after:wN {#3}
  }
\cs_new:Npn \exp_args:Ncf #1#2#3
  {
    \exp_after:wN #1
    \cs:w #2 \exp_after:wN \cs_end:
    \exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
  }
\cs_new:Npn \exp_args:NVV #1#2#3
  {
    \exp_after:wN #1
    \exp_after:wN { \exp:w \exp_after:wN
      \@@_eval_register:N \exp_after:wN #2 \exp_after:wN }
    \exp_after:wN { \exp:w \@@_eval_register:N #3 }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {
%     \exp_args:Ncco, \exp_args:NcNc, \exp_args:NcNo,
%     \exp_args:NNNV
%   }
%   A few more that we can hand-tune.
%    \begin{macrocode}
\cs_new:Npn \exp_args:NNNV #1#2#3#4
  {
    \exp_after:wN #1
    \exp_after:wN #2
    \exp_after:wN #3
    \exp_after:wN { \exp:w \@@_eval_register:N #4 }
  }
\cs_new:Npn \exp_args:NcNc #1#2#3#4
  {
    \exp_after:wN #1
    \cs:w #2 \exp_after:wN \cs_end:
    \exp_after:wN #3
    \cs:w #4 \cs_end:
  }
\cs_new:Npn \exp_args:NcNo #1#2#3#4
  {
    \exp_after:wN #1
    \cs:w #2 \exp_after:wN \cs_end:
    \exp_after:wN #3
    \exp_after:wN {#4}
  }
\cs_new:Npn \exp_args:Ncco #1#2#3#4
  {
    \exp_after:wN #1
    \cs:w #2 \exp_after:wN \cs_end:
    \cs:w #3 \exp_after:wN \cs_end:
    \exp_after:wN {#4}
  }
%    \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
% are all not long: they don't actually take any arguments themselves.
%
% \begin{macro}{\exp_args:Nx}
%    \begin{macrocode}
\cs_new_protected:Npn \exp_args:Nx { \::x \::: }
%    \end{macrocode}
% \end{macro}
%
% \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
%   }
% \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: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:Noo { \::o \::o \::: }
\cs_new:Npn \exp_args:Nof { \::o \::f \::: }
\cs_new:Npn \exp_args:Noc { \::o \::c \::: }
\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:NNno, \exp_args:NNoo,
%     \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nooo,
%   }
% \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,
%   }
%    \begin{macrocode}
\cs_new:Npn \exp_args:NNno { \::N \::n \::o \::: }
\cs_new:Npn \exp_args:NNoo { \::N \::o \::o \::: }
\cs_new:Npn \exp_args:Nnnc { \::n \::n \::c \::: }
\cs_new:Npn \exp_args:Nnno { \::n \::n \::o \::: }
\cs_new:Npn \exp_args:Nooo { \::o \::o \::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}[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}
%   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
  {
    \exp_after:wN \@@_arg_last_unbraced:nn
      \exp_after:wN { \exp:w \@@_eval_register:N #2 } {#1}
  }
\cs_new:Npn \::v_unbraced \::: #1#2
  {
    \exp_after:wN \@@_arg_last_unbraced:nn
      \exp_after:wN { \exp:w \@@_eval_register:c {#2} } {#1}
  }
\cs_new_protected:Npn \::x_unbraced \::: #1#2
  {
    \cs_set_nopar:Npx \l_@@_internal_tl { \exp_not:n {#1} #2 }
    \l_@@_internal_tl
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \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_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: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
  {
    \exp_after:wN #1
    \cs:w #2 \exp_after:wN \cs_end:
    \exp:w \@@_eval_register:N #3
  }
\cs_new:Npn \exp_last_unbraced:NNV #1#2#3
  {
    \exp_after:wN #1
    \exp_after:wN #2
    \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:NNNV #1#2#3#4
  {
    \exp_after:wN #1
    \exp_after:wN #2
    \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_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}
%   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
%      { \exp_after:wN \exp_after:wN \exp_after:wN #1 \exp_after:wN #2 #3 }
%   \end{verbatim}
%   However, for robustness this is not suitable. Instead, a bit of a
%   shuffle is used to ensure that |#2| can be multiple tokens.
%    \begin{macrocode}
\cs_new:Npn \exp_last_two_unbraced:Noo #1#2#3
  { \exp_after:wN \@@_last_two_unbraced:noN \exp_after:wN {#3} {#2} #1 }
\cs_new:Npn \@@_last_two_unbraced:noN #1#2#3
   { \exp_after:wN #3 #2 #1 }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Preventing expansion}
%
% \begin{macro}[EXP]{\exp_not:o}
% \begin{macro}[EXP]{\exp_not:c}
% \begin{macro}[EXP]{\exp_not:f}
% \begin{macro}[EXP]{\exp_not:V}
% \begin{macro}[EXP]{\exp_not:v}
%    \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: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
      { \exp:w \@@_eval_register:N #1 }
  }
\cs_new:Npn \exp_not:v #1
  {
    \etex_unexpanded:D \exp_after:wN
      { \exp:w \@@_eval_register:c {#1} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Controlled expansion}
%
% \begin{macro}{\exp:w}
% \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.
%    \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 \cs{c_zero} as part of expanded tokens. As this is
%    an integer constant it will immediately stop
%    \cs{tex_romannumerl:D}'s search for a number.
%    \begin{macrocode}
%\cs_new_eq:NN \exp_end: \c_zero
%    \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 f-type expansion we provide the
%    alphabetic constant |`^^@| that also represents |0| but this time
%    \TeX's syntax for a \meta{number} will continue searching for an
%    optional space (and it will continue 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 {`^^@}
%    \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.}
%    \begin{macrocode}
\cs_new:Npn ^^@{\expansionERROR}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Npn \exp_end_continue_f:nw #1 { `^^@ #1 }
\tex_catcode:D `\^^@=15
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \subsection{Defining function variants}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% \begin{macro}{\cs_generate_variant:Nn}
%   \begin{arguments}
%     \item Base form of a function; \emph{e.g.},~\cs{tl_set:Nn}
%     \item One or more variant argument specifiers; e.g., |{Nx,c,cx}|
%   \end{arguments}
%   After making sure that the base form exists, test whether it is
%   protected or not and define \cs{@@_tmp:w} as either
%   \cs{cs_new:Npx} or \cs{cs_new_protected:Npx}, which is
%   then used to define all the variants (except those involving
%   \texttt{x}-expansion, always protected).  Split up the original base
%   function only once, to grab its name and signature.  Then we wish to
%   iterate through the comma list of variant argument specifiers, which
%   we first convert to a string: the reason is explained later.
%    \begin{macrocode}
\cs_new_protected:Npn \cs_generate_variant:Nn #1#2
  {
    \__chk_if_exist_cs:N #1
    \@@_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
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:N}
% \begin{macro}[aux]{\@@_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.
%
%   The other case where variants should be protected is when the parent
%   function is a protected macro: then |protected| appears in the
%   meaning before the fist occurrence of |macro|.  The |ww| auxiliary
%   removes everything in the meaning string after the first |ma|.  We
%   use |ma| rather than the full |macro| because the meaning of the
%   \tn{firstmark} primitive (and four others) can contain an arbitrary
%   string after a leading |firstmark:|.  Then, look for |pr| in the
%   part we extracted: no need to look for anything longer: the only
%   strings we can have are an empty string, \verb*|\long |,
%   \verb*|\protected |, \verb*|\protected\long |, |\first|, |\top|,
%   |\bot|, |\splittop|, or |\splitbot|, with |\| replaced by the
%   appropriate escape character.  If |pr| appears in the part before
%   |ma|, the first \cs{q_mark} is taken as an argument of the |wwNw|
%   auxiliary, and |#3| is \cs{cs_new_protected:Npx}, otherwise it
%   is \cs{cs_new:Npx}.
%    \begin{macrocode}
\cs_new_protected:Npx \@@_generate_variant:N #1
  {
    \exp_not:N \exp_after:wN \exp_not:N \if_meaning:w
      \exp_not:N \exp_not:N #1 #1
      \cs_set_eq:NN \exp_not:N \@@_tmp:w \cs_new_protected:Npx
    \exp_not:N \else:
      \exp_not:N \exp_after:wN \exp_not:N \@@_generate_variant:ww
        \exp_not:N \token_to_meaning:N #1 \tl_to_str:n { ma }
          \exp_not:N \q_mark
        \exp_not:N \q_mark \cs_new_protected:Npx
        \tl_to_str:n { pr }
        \exp_not:N \q_mark \cs_new:Npx
        \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 }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:nnNN}
%   \begin{arguments}
%     \item Base name.
%     \item Base signature.
%     \item Boolean.
%     \item Base function.
%   \end{arguments}
%   If the boolean is \cs{c_false_bool}, the base function has no colon
%   and we abort with an error; otherwise, set off a loop through the
%   desired variant forms. The original function is retained as |#4| for
%   efficiency.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_generate_variant:nnNN #1#2#3#4
  {
    \if_meaning:w \c_false_bool #3
      \__msg_kernel_error:nnx { kernel } { missing-colon }
        { \token_to_str:c {#1} }
      \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
    \fi:
    \@@_generate_variant:Nnnw #4 {#1}{#2}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:Nnnw}
%   \begin{arguments}
%     \item Base function.
%     \item Base name.
%     \item Base signature.
%     \item Beginning of variant signature.
%   \end{arguments}
%   First check whether to terminate the loop over variant forms.  Then,
%   for each variant form, construct a new function name using the
%   original base name, the variant signature consisting of $l$ letters
%   and the last $k-l$ letters of the base signature (of length $k$).
%   For example, for a base function \cs{prop_put:Nnn} which needs a
%   |cV| variant form, we want the new signature to be |cVn|.
%
%   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|,
%       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
%       |\exp_args:Nox|, to avoid double |o| expansion.
%     \item Lastly, \cs{cs_generate_variant:Nn} |\foo:on| |{xn}| should
%       trigger an error, because we do not have a means to replace
%       |o|-expansion by |x|-expansion.
%     \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.
%
%     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:nnnn}).
%
%     Note the space after |#3| and after the following brace group.
%     Those are ignored by \TeX{} when fetching the last argument for
%     \cs{@@_generate_variant_loop:nNwN}, but can be used as a delimiter
%     for \cs{@@_generate_variant_loop_end:nwwwNNnn}.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_generate_variant:Nnnw #1#2#3#4 ,
  {
    \if_meaning:w \scan_stop: #4
      \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
    \fi:
    \use:x
      {
        \exp_not:N \@@_generate_variant:wwNN
        \@@_generate_variant_loop:nNwN { }
          #4
          \@@_generate_variant_loop_end:nwwwNNnn
          \q_mark
          #3 ~
          { ~ { } \fi: \@@_generate_variant_loop_long:wNNnn } ~
          { }
          \q_stop
        \exp_not:N #1 {#2} {#4}
      }
    \@@_generate_variant:Nnnw #1 {#2} {#3}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux, EXP]
%   {
%     \@@_generate_variant_loop:nNwN,
%     \@@_generate_variant_loop_same:w,
%     \@@_generate_variant_loop_end:nwwwNNnn,
%     \@@_generate_variant_loop_long:wNNnn,
%     \@@_generate_variant_loop_invalid:NNwNNnn,
%   }
%   \begin{arguments}
%     \item Last few (consecutive) letters common between the base
%       and variant (in fact, \cs{@@_generate_variant_same:N}
%       \meta{letter} for each letter).
%     \item Next variant letter.
%     \item Remainder of variant form.
%     \item Next base letter.
%   \end{arguments}
%   The first argument is populated by
%   \cs{@@_generate_variant_loop_same:w} when a variant letter and a
%   base letter match.  It is flushed into the input stream whenever the
%   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
%   \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}.
%
%   The loop can stop in three ways.
%   \begin{itemize}
%     \item If the end of the variant form is encountered first, |#2| is
%       \cs{@@_generate_variant_loop_end:nwwwNNnn} (expanded by the
%       conditional \cs{if:w}), which inserts some tokens to end the
%       conditional; grabs the \meta{base name} as |#7|, the
%       \meta{variant signature} |#8|, the \meta{next base letter} |#1|
%       and the part |#3| of the base signature that wasn't read yet;
%       and combines those into the \meta{new function} to be defined.
%     \item If the end of the base form is encountered first, |#4| is
%       |~{}\fi:| which ends the conditional (with an empty expansion),
%       followed by \cs{@@_generate_variant_loop_long:wNNnn}, which
%       places an error as the second argument of
%       \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}.
%   \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
%   the second point above.  The \cs{@@_generate_variant_loop_end:nwwwNNnn}
%   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.
%    \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:
          \@@_generate_variant_loop_invalid:NNwNNnn #4#2
        \fi:
      \fi:
    \fi:
    #1
    \prg_do_nothing:
    #2
    \@@_generate_variant_loop:nNwN { } #3 \q_mark
  }
\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
  {
    \scan_stop: \scan_stop: \fi:
    \exp_not:N \q_mark
    \exp_not:N \q_stop
    \exp_not:N #6
    \exp_not:c { #7 : #8 #1 #3 }
  }
\cs_new:Npn \@@_generate_variant_loop_long:wNNnn #1 \q_stop #2#3#4#5
  {
    \exp_not:n
      {
        \q_mark
        \__msg_kernel_error:nnxx { kernel } { variant-too-long }
          {#5} { \token_to_str:N #3 }
        \use_none:nnnn
        \q_stop
        #3
        #3
      }
  }
\cs_new:Npn \@@_generate_variant_loop_invalid:NNwNNnn
    #1#2 \fi: \fi: \fi: #3 \q_stop #4#5#6#7
  {
    \fi: \fi: \fi:
    \exp_not:n
      {
        \q_mark
        \__msg_kernel_error:nnxxxx { kernel } { invalid-variant }
          {#7} { \token_to_str:N #5 } {#1} {#2}
        \use_none:nnnn
        \q_stop
        #5
        #5
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux, 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.
%    \begin{macrocode}
\cs_new:Npn \@@_generate_variant_same:N #1
  {
    \if:w N #1
      N
    \else:
      \if:w p #1
        p
      \else:
        n
      \fi:
    \fi:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:wwNN}
%   If the variant form has already been defined, log its existence.
%   Otherwise, make sure that the |\exp_args:N #3| form is defined, and
%   if it contains |x|, change \cs{@@_tmp:w} locally to
%   \cs{cs_new_protected:Npx}.  Then define the variant by
%   combining the |\exp_args:N #3| variant and the base function.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_generate_variant:wwNN
    #1 \q_mark #2 \q_stop #3#4
  {
    #2
    \cs_if_free:NTF #4
      {
        \group_begin:
          \@@_generate_internal_variant:n {#1}
          \@@_tmp:w #4 { \exp_not:c { exp_args:N #1 } \exp_not:N #3 }
        \group_end:
      }
      {
        \__chk_log:x
          {
            Variant~\token_to_str:N #4~%
            already~defined;~ not~ changing~ it~ \msg_line_context:
          }
      }
  }
%    \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}
%   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.
%    \begin{macrocode}
\cs_new_protected:Npx \@@_generate_internal_variant:n #1
  {
    \exp_not:N \@@_generate_internal_variant:wwnNwnn
      #1 \exp_not:N \q_mark
        { \cs_set_eq:NN \exp_not:N \@@_tmp:w \cs_new_protected:Npx }
        \cs_new_protected:cpx
      \token_to_str:N x \exp_not:N \q_mark
        { }
        \cs_new:cpx
    \exp_not:N \q_stop
      { exp_args:N #1 }
      {
        \exp_not:N \@@_generate_internal_variant_loop:n #1
          { : \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
  }
  {
    #3
    \cs_if_free:cT {#6} { #4 {#6} {#7} }
  }
%    \end{macrocode}
%   This command grabs char by char outputting |\::#1| (not expanded
%   further).  We avoid tests by putting a trailing |: \use_i:nn|, which
%   leaves \cs{cs_end:} and removes the looping macro.  The colon is in
%   fact also turned into \cs{:::} so that the required structure for
%   |\exp_args:N...| commands is correctly terminated.
%    \begin{macrocode}
\cs_new:Npn \@@_generate_internal_variant_loop:n #1
  {
    \exp_after:wN \exp_not:N \cs:w :: #1 \cs_end:
    \@@_generate_internal_variant_loop:n
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
