% \iffalse meta-comment
%
%% File: l3basics.dtx
%
% Copyright (C) 1990-2026 The LaTeX 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
%
%    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.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/latex3
%
% for those people who are interested.
%
%<*driver>
\documentclass[full,kernel]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3basics} module\\ Basic definitions^^A
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2026-08-10}
%
% \maketitle
%
% \begin{documentation}
%
% As the name suggests, this module holds some basic definitions which
% are needed by most or all other modules in this set.
%
% Here we describe those functions that are used all over the place.
% By that, we mean functions dealing with the construction and testing of
% control sequences. Furthermore the basic parts of conditional
% processing are covered; conditional processing dealing with specific
% data types is described in the modules specific for the respective
% data types.
%
% \section{No operation functions}
%
% \begin{function}[EXP]{\prg_do_nothing:}
%   \begin{syntax}
%     \cs{prg_do_nothing:}
%   \end{syntax}
%   An expandable function which does nothing at all: leaves nothing
%   in the input stream after a single expansion.
% \end{function}
%
% \begin{function}{\scan_stop:}
%   \begin{syntax}
%     \cs{scan_stop:}
%   \end{syntax}
%   A non-expandable function which does nothing. Does not vanish on
%   expansion but produces no typeset output.
% \end{function}
%
% \section{Grouping material}
%
% \begin{function}{\group_begin:, \group_end:}
%   \begin{syntax}
%     \cs{group_begin:}
%     \cs{group_end:}
%   \end{syntax}
%   These functions begin and end a group for definition purposes.
%   Assignments are local to groups unless carried out in a global
%   manner. (A small number of exceptions to this rule will be noted
%   as necessary elsewhere in this document.) Each \cs{group_begin:}
%   must be matched by a \cs{group_end:}, although this does not have
%   to occur within the same function. Indeed, it is often necessary
%   to start a group within one function and finish it within another,
%   for example when seeking to use non-standard category codes.
%   \begin{texnote}
%     These are the \TeX{} primitives \tn{begingroup} and \tn{endgroup}.
%   \end{texnote}
% \end{function}
%
% \begin{function}{\group_insert_after:N}
%   \begin{syntax}
%     \cs{group_insert_after:N} \meta{token}
%   \end{syntax}
%   Adds \meta{token} to the list of \meta{tokens} to be inserted
%   when the current group level ends. The list of \meta{tokens} to be
%   inserted is empty at the beginning of a group: multiple
%   applications of \cs{group_insert_after:N} may be used to build
%   the inserted list one \meta{token} at a time. The current group
%   level may be closed by a \cs{group_end:} function or by a token
%   with category code $2$ (close-group), namely a ^^A{
%   |}| if standard category codes apply.
%   \begin{texnote}
%     This is the \TeX{} primitive \tn{aftergroup}.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2021-05-11]{\group_show_list:, \group_log_list:}
%   \begin{syntax}
%     \cs{group_show_list:}
%     \cs{group_log_list:}
%   \end{syntax}
%   Display (to the terminal or log file) a list of the groups that are
%   currently opened.  This is intended for tracking down problems.
%   \begin{texnote}
%     This is a wrapper around the \eTeX{} primitive \tn{showgroups}.
%   \end{texnote}
% \end{function}
%
% \section{Control sequences and functions}
%
% As \TeX{} is a macro language, creating new functions means
% creating macros. At point of use, a function is replaced by
% the replacement text (\enquote{code}) in which each parameter
% in the code (|#1|, |#2|, etc.) is replaced the appropriate
% arguments absorbed by the function. In the following, \meta{code}
% is therefore used as a shorthand for \enquote{replacement text}.
%
% Functions which are not \enquote{protected} are fully expanded
% inside an \texttt{e}-type or \texttt{x}-type expansion.
% In contrast, \enquote{protected} functions are not expanded within
% \texttt{e} and \texttt{x} expansions.
%
% \subsection{Defining functions}
%
% Functions can be created with no requirement that they are declared
% first (in contrast to variables, which must always be declared).
% Declaring a function before setting up the code means that the name
% chosen is checked and an error raised if it is already in use.
% The name of a function can be checked at the point of definition using
% the \cs[no-index]{cs_new\ldots} functions: this is recommended for all
% functions which are defined for the first time.
%
% There are three ways to define new functions.
% All classes define a function to expand to the substitution text.
% Within the substitution text the actual parameters are substituted
% for the formal parameters (|#1|, |#2|, \ldots).
% \begin{description}
%   \item[\texttt{new}]
%     Create a new function with the \texttt{new} scope,
%     such as \cs{cs_new:Npn}.  The definition is global and results in
%     an error if it is already defined.
%   \item[\texttt{set}]
%     Create a new function with the \texttt{set} scope,
%     such as \cs{cs_set:Npn}. The definition is restricted to the current
%     \TeX{} group and does not result in an error if the function is already
%     defined.
%   \item[\texttt{gset}]
%     Create a new function with the \texttt{gset} scope,
%     such as \cs{cs_gset:Npn}. The definition is global and
%     does not result in an error if the function is already defined.
% \end{description}
%
% Within each set of scope there are different ways to define a function.
% The differences depend on restrictions on the actual parameters and
% the expandability of the resulting function.
% \begin{description}
%   \item[\texttt{nopar}]
%      Create a new function with the \texttt{nopar} restriction,
%      such as \cs{cs_set_nopar:Npn}. The parameter may not contain
%      \cs{par} tokens.
%   \item[\texttt{protected}]
%      Create a new function with the \texttt{protected} restriction,
%      such as \cs{cs_set_protected:Npn}. The parameter may contain
%      \cs{par} tokens but the function will not expand within an
%      \texttt{e}-type or \texttt{x}-type expansion.
% \end{description}
%
% Finally, the functions in
% Subsections~\ref{sec:l3basics:defining-new-function-1}~and
% \ref{sec:l3basics:defining-new-function-2} are primarily meant to define
% \emph{base functions} only. Base functions can only have the following
% argument specifiers:
% \begin{description}
%   \item[|N| and |n|] No manipulation.
%   \item[|T| and |F|] Functionally equivalent to |n| (you are actually
%     encouraged to use the family of |\prg_new_conditional:| functions
%     described in Section~\ref{sec:l3prg:new-conditional-functions}).
%   \item[|p| and |w|] These are special cases.
% \end{description}
%
% The |\cs_new:| functions below (and friends) do not stop you from using
% other argument specifiers in your function names, but they do not handle
% expansion for you. You should define the base function and then use
% \cs{cs_generate_variant:Nn} to generate custom variants as described in
% Section~\ref{sec:l3expan:variants-method}.
%
% \subsection{Defining new functions using parameter text}
% \label{sec:l3basics:defining-new-function-1}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new:Npn, \cs_new:cpn,
%     \cs_new:Npe, \cs_new:cpe,
%     \cs_new:Npx, \cs_new:cpx
%   }
%   \begin{syntax}
%     \cs{cs_new:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   The definition is global and an error results if the
%   \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new_nopar:Npn, \cs_new_nopar:cpn,
%     \cs_new_nopar:Npe, \cs_new_nopar:cpe,
%     \cs_new_nopar:Npx, \cs_new_nopar:cpx
%   }
%   \begin{syntax}
%     \cs{cs_new_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   When the \meta{function} is used the \meta{parameters} absorbed
%   cannot contain \cs{par} tokens. The definition is global and
%   an error results if the \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new_protected:Npn, \cs_new_protected:cpn,
%     \cs_new_protected:Npe, \cs_new_protected:cpe,
%     \cs_new_protected:Npx, \cs_new_protected:cpx
%   }
%   \begin{syntax}
%     \cs{cs_new_protected:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   The \meta{function} will not expand within an \texttt{e}-type or
%   or \texttt{x}-type
%   argument. The definition is global and an error results if the
%   \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new_protected_nopar:Npn, \cs_new_protected_nopar:cpn ,
%     \cs_new_protected_nopar:Npe, \cs_new_protected_nopar:cpe ,
%     \cs_new_protected_nopar:Npx, \cs_new_protected_nopar:cpx
%   }
%   \begin{syntax}
%     \cs{cs_new_protected_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   When the \meta{function} is used the \meta{parameters} absorbed
%   cannot contain \cs{par} tokens. The \meta{function} will not
%   expand within an \texttt{e}-type or \texttt{x}-type argument. The definition is global
%   and an error results if the \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set:Npn, \cs_set:cpn,
%     \cs_set:Npe, \cs_set:cpe,
%     \cs_set:Npx, \cs_set:cpx
%   }
%   \begin{syntax}
%     \cs{cs_set:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   The assignment of a meaning to the \meta{function} is restricted to
%   the current \TeX{} group level.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set_nopar:Npn, \cs_set_nopar:cpn,
%     \cs_set_nopar:Npe, \cs_set_nopar:cpe,
%     \cs_set_nopar:Npx, \cs_set_nopar:cpx
%   }
%   \begin{syntax}
%     \cs{cs_set_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   When the \meta{function} is used the \meta{parameters} absorbed
%   cannot contain \cs{par} tokens. The assignment of a meaning
%   to the \meta{function} is restricted to the current \TeX{} group
%   level.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set_protected:Npn, \cs_set_protected:cpn,
%     \cs_set_protected:Npe, \cs_set_protected:cpe,
%     \cs_set_protected:Npx, \cs_set_protected:cpx
%   }
%   \begin{syntax}
%     \cs{cs_set_protected:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   The assignment of a meaning to the \meta{function} is restricted to
%   the current \TeX{} group level. The \meta{function} will
%   not expand within an \texttt{e}-type or \texttt{x}-type argument.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set_protected_nopar:Npn, \cs_set_protected_nopar:cpn ,
%     \cs_set_protected_nopar:Npe, \cs_set_protected_nopar:cpe ,
%     \cs_set_protected_nopar:Npx, \cs_set_protected_nopar:cpx ,
%   }
%   \begin{syntax}
%     \cs{cs_set_protected_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   When the \meta{function} is used the \meta{parameters} absorbed
%   cannot contain \cs{par} tokens. The assignment of a meaning
%   to the \meta{function} is restricted to the current \TeX{} group
%   level. The \meta{function} will not expand within an
%   \texttt{e}-type or \texttt{x}-type argument.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset:Npn, \cs_gset:cpn,
%     \cs_gset:Npe, \cs_gset:cpe,
%     \cs_gset:Npx, \cs_gset:cpx
%   }
%   \begin{syntax}
%     \cs{cs_gset:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Globally sets \meta{function} to expand to \meta{code} as replacement
%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   The assignment of a meaning to the \meta{function} is \emph{not}
%   restricted to the current \TeX{} group level: the assignment is
%   global.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset_nopar:Npn, \cs_gset_nopar:cpn,
%     \cs_gset_nopar:Npe, \cs_gset_nopar:cpe,
%     \cs_gset_nopar:Npx, \cs_gset_nopar:cpx
%   }
%   \begin{syntax}
%     \cs{cs_gset_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Globally sets \meta{function} to expand to \meta{code} as replacement
%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   When the \meta{function} is used the \meta{parameters} absorbed
%   cannot contain \cs{par} tokens. The assignment of a meaning to the
%   \meta{function} is \emph{not} restricted to the current \TeX{}
%   group level: the assignment is global.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset_protected:Npn, \cs_gset_protected:cpn,
%     \cs_gset_protected:Npe, \cs_gset_protected:cpe,
%     \cs_gset_protected:Npx, \cs_gset_protected:cpx
%   }
%   \begin{syntax}
%     \cs{cs_gset_protected:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Globally sets \meta{function} to expand to \meta{code} as replacement
%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   The assignment of a meaning to the \meta{function} is \emph{not}
%   restricted to the current \TeX{} group level: the assignment is
%   global. The \meta{function} will not expand within an
%   \texttt{e}-type or \texttt{x}-type argument.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset_protected_nopar:Npn, \cs_gset_protected_nopar:cpn,
%     \cs_gset_protected_nopar:Npe, \cs_gset_protected_nopar:cpe,
%     \cs_gset_protected_nopar:Npx, \cs_gset_protected_nopar:cpx
%   }
%   \begin{syntax}
%     \cs{cs_gset_protected_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Globally sets \meta{function} to expand to \meta{code} as replacement
%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   etc.) will be replaced by those absorbed by the function.
%   When the \meta{function} is used the \meta{parameters} absorbed
%   cannot contain \cs{par} tokens. The assignment of a meaning to the
%   \meta{function} is \emph{not} restricted to the current \TeX{}
%   group level: the assignment is global. The \meta{function} will
%   not expand within an \texttt{e}-type or \texttt{x}-type argument.
% \end{function}
%
% \subsection{Defining new functions using the signature}
% \label{sec:l3basics:defining-new-function-2}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new:Nn, \cs_new:cn,
%     \cs_new:Ne, \cs_new:ce
%   }
%   \begin{syntax}
%     \cs{cs_new:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function. The definition is global and
%   an error results if the \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new_nopar:Nn, \cs_new_nopar:cn,
%     \cs_new_nopar:Ne, \cs_new_nopar:ce
%   }
%   \begin{syntax}
%     \cs{cs_new_nopar:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.  When the \meta{function} is used the \meta{parameters}
%   absorbed cannot contain \cs{par} tokens. The definition is global and
%   an error results if the \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new_protected:Nn, \cs_new_protected:cn,
%     \cs_new_protected:Ne, \cs_new_protected:ce
%   }
%   \begin{syntax}
%     \cs{cs_new_protected:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function. The \meta{function} will not expand within an \texttt{e}-type
%   or \texttt{x}-type argument. The definition is global and
%   an error results if the \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_new_protected_nopar:Nn, \cs_new_protected_nopar:cn,
%     \cs_new_protected_nopar:Ne, \cs_new_protected_nopar:ce
%   }
%   \begin{syntax}
%     \cs{cs_new_protected_nopar:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Creates \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.  When the \meta{function} is used the \meta{parameters}
%   absorbed cannot contain \cs{par} tokens. The \meta{function} will not
%   expand within an \texttt{e}-type or \texttt{x}-type argument. The definition is global and
%   an error results if the \meta{function} is already defined.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set:Nn, \cs_set:cn,
%     \cs_set:Ne, \cs_set:ce
%   }
%   \begin{syntax}
%     \cs{cs_set:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.
%   The assignment of a meaning to the \meta{function} is restricted to
%   the current \TeX{} group level.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set_nopar:Nn, \cs_set_nopar:cn,
%     \cs_set_nopar:Ne, \cs_set_nopar:ce
%   }
%   \begin{syntax}
%     \cs{cs_set_nopar:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.  When the \meta{function} is used the \meta{parameters}
%   absorbed cannot contain \cs{par} tokens.
%   The assignment of a meaning to the \meta{function} is restricted to
%   the current \TeX{} group level.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set_protected:Nn, \cs_set_protected:cn,
%     \cs_set_protected:Ne, \cs_set_protected:ce
%   }
%   \begin{syntax}
%     \cs{cs_set_protected:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function. The \meta{function} will not expand within an \texttt{e}-type
%   or \texttt{x}-type argument.
%   The assignment of a meaning to the \meta{function} is restricted to
%   the current \TeX{} group level.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_set_protected_nopar:Nn, \cs_set_protected_nopar:cn,
%     \cs_set_protected_nopar:Ne, \cs_set_protected_nopar:ce
%   }
%   \begin{syntax}
%     \cs{cs_set_protected_nopar:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.  When the \meta{function} is used the \meta{parameters}
%   absorbed cannot contain \cs{par} tokens. The \meta{function} will not
%   expand within an \texttt{e}-type or \texttt{x}-type argument.
%   The assignment of a meaning to the \meta{function} is restricted to
%   the current \TeX{} group level.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset:Nn, \cs_gset:cn,
%     \cs_gset:Ne, \cs_gset:ce
%   }
%   \begin{syntax}
%     \cs{cs_gset:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.
%   The assignment of a meaning to the \meta{function} is  global.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset_nopar:Nn, \cs_gset_nopar:cn,
%     \cs_gset_nopar:Ne, \cs_gset_nopar:ce
%   }
%   \begin{syntax}
%     \cs{cs_gset_nopar:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.  When the \meta{function} is used the \meta{parameters}
%   absorbed cannot contain \cs{par} tokens.
%   The assignment of a meaning to the \meta{function} is global.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset_protected:Nn, \cs_gset_protected:cn,
%     \cs_gset_protected:Ne, \cs_gset_protected:ce
%   }
%   \begin{syntax}
%     \cs{cs_gset_protected:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function. The \meta{function} will not expand within an \texttt{e}-type
%   or \texttt{x}-type argument.
%   The assignment of a meaning to the \meta{function} is  global.
% \end{function}
%
% \begin{function}[updated = 2023-09-27]
%   {
%     \cs_gset_protected_nopar:Nn, \cs_gset_protected_nopar:cn,
%     \cs_gset_protected_nopar:Ne, \cs_gset_protected_nopar:ce
%   }
%   \begin{syntax}
%     \cs{cs_gset_protected_nopar:Nn} \meta{function} \Arg{code}
%   \end{syntax}
%   Sets \meta{function} to expand to \meta{code} as replacement text.
%   Within the \meta{code}, the number of \meta{parameters} is detected
%   automatically from the function signature. These \meta{parameters}
%   (|#1|, |#2|, etc.) will be replaced by those absorbed by the
%   function.  When the \meta{function} is used the \meta{parameters}
%   absorbed cannot contain \cs{par} tokens. The \meta{function} will not
%   expand within an \texttt{e}-type or \texttt{x}-type argument.
%   The assignment of a meaning to the \meta{function} is global.
% \end{function}
%
% \begin{function}[updated = 2012-01-14]
%   {
%     \cs_generate_from_arg_count:NNnn,
%     \cs_generate_from_arg_count:NNno,
%     \cs_generate_from_arg_count:cNnn,
%     \cs_generate_from_arg_count:Ncnn
%   }
%   \begin{syntax}
%     \cs{cs_generate_from_arg_count:NNnn} \meta{function} \meta{creator} \Arg{number} \Arg{code}
%   \end{syntax}
%   Uses the \meta{creator} function (which should have signature
%   |Npn|, for example \cs{cs_new:Npn}) to define a \meta{function}
%   which takes \meta{number} arguments and has \meta{code} as
%   replacement text. The \meta{number} of arguments is an integer expression,
%   evaluated as detailed for \cs{int_eval:n}.
% \end{function}
%
% \subsection{Copying control sequences}
%
% Control sequences (not just functions as defined above) can
% be set to have the same meaning using the functions described
% here. Making two control sequences equivalent means that the
% second control sequence is a \emph{copy} of the first (rather than
% a pointer to it). Thus the old and new control sequence are not
% tied together: changes to one are not reflected in the other.
%
% In the following text \enquote{cs} is used as an abbreviation for
% \enquote{control sequence}.
%
% \begin{function}
%   {\cs_new_eq:NN, \cs_new_eq:Nc, \cs_new_eq:cN, \cs_new_eq:cc}
%   \begin{syntax}
%     \cs{cs_new_eq:NN} \meta{cs_1} \meta{cs_2}
%     \cs{cs_new_eq:NN} \meta{cs_1} \meta{token}
%   \end{syntax}
%   Globally creates \meta{control sequence_1} and sets it to have the same
%   meaning as \meta{control sequence_2} or <token>.
%   The second control sequence may
%   subsequently be altered without affecting the copy.
% \end{function}
%
% \begin{function}
%   {\cs_set_eq:NN, \cs_set_eq:Nc, \cs_set_eq:cN, \cs_set_eq:cc}
%   \begin{syntax}
%     \cs{cs_set_eq:NN} \meta{cs_1} \meta{cs_2}
%     \cs{cs_set_eq:NN} \meta{cs_1} \meta{token}
%   \end{syntax}
%   Sets \meta{control sequence_1} to have the same meaning as
%   \meta{control sequence_2} (or <token>).
%   The second control sequence may subsequently be
%   altered without affecting the copy. The assignment of a meaning
%   to the \meta{control sequence_1} is restricted to the current
%   \TeX{} group level.
% \end{function}
%
% \begin{function}
%   {\cs_gset_eq:NN, \cs_gset_eq:Nc, \cs_gset_eq:cN, \cs_gset_eq:cc}
%   \begin{syntax}
%     \cs{cs_gset_eq:NN} \meta{cs_1} \meta{cs_2}
%     \cs{cs_gset_eq:NN} \meta{cs_1} \meta{token}
%   \end{syntax}
%   Globally sets \meta{control sequence_1} to have the same meaning as
%   \meta{control sequence_2} (or <token>).
%   The second control sequence may subsequently be
%   altered without affecting the copy. The assignment of a meaning to
%   the \meta{control sequence_1} is \emph{not} restricted to the current
%   \TeX{} group level: the assignment is global.
% \end{function}
%
% \subsection{Deleting control sequences}
%
% There are occasions where control sequences need to be deleted.
% This is handled in a very simple manner.
%
% \begin{function}[updated = 2011-09-15]{\cs_undefine:N, \cs_undefine:c}
%   \begin{syntax}
%     \cs{cs_undefine:N} \meta{control sequence}
%   \end{syntax}
%   Sets \meta{control sequence} to be globally undefined.
% \end{function}
%
% \subsection{Showing control sequences}
%
% \begin{function}[EXP, updated = 2011-12-22]{\cs_meaning:N, \cs_meaning:c}
%   \begin{syntax}
%     \cs{cs_meaning:N} \meta{control sequence}
%   \end{syntax}
%   This function expands to the \emph{meaning} of the \meta{control sequence}
%   control sequence. For a macro, this includes the \meta{replacement text}.
%   \begin{texnote}
%     This is the \TeX{} primitive \tn{meaning}.
%     For tokens that are not control sequences, it is more logical to
%     use \cs{token_to_meaning:N}.
%     The \texttt{c} variant correctly reports undefined arguments.
%   \end{texnote}
% \end{function}
%
% \begin{function}[updated = 2017-02-14]{\cs_show:N, \cs_show:c}
%   \begin{syntax}
%     \cs{cs_show:N} \meta{control sequence}
%   \end{syntax}
%   Displays the definition of the \meta{control sequence} on the
%   terminal.
%   \begin{texnote}
%     This is similar to the \TeX{} primitive \tn{show}, wrapped to a
%     fixed number of characters per line.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2014-08-22, updated = 2017-02-14]{\cs_log:N, \cs_log:c}
%   \begin{syntax}
%     \cs{cs_log:N} \meta{control sequence}
%   \end{syntax}
%   Writes the definition of the \meta{control sequence} in the log
%   file.  See also \cs{cs_show:N} which displays the result in the
%   terminal.
% \end{function}
%
% \subsection{Converting to and from control sequences}
%
% \begin{function}[EXP]{\use:c}
%   \begin{syntax}
%     \cs{use:c} \Arg{control sequence name}
%   \end{syntax}
%   Expands the \meta{control sequence name} until only characters
%   remain, and then converts this into a control sequence. This process
%   requires two expansions.  As in other \texttt{c}-type arguments the
%   \meta{control sequence name} must, when fully expanded, consist of
%   character tokens, typically a mixture of category code $10$ (space),
%   $11$ (letter) and $12$ (other).
% \end{function}
%
% As an example of the \cs{use:c} function, both
%   \begin{verbatim}
%     \use:c { a b c }
%   \end{verbatim}
%   and
%   \begin{verbatim}
%     \tl_new:N  \l_my_tl
%     \tl_set:Nn \l_my_tl { a b c }
%     \use:c { \tl_use:N \l_my_tl }
%   \end{verbatim}
%   would be equivalent to
%   \begin{verbatim}
%     \abc
%   \end{verbatim}
%   after two expansions of \cs{use:c}.
%
% \begin{function}[noTF, EXP, added = 2011-10-10]
%   {\cs_if_exist_use:N, \cs_if_exist_use:c}
%   \begin{syntax}
%     \cs{cs_if_exist_use:N} \meta{control sequence}
%     \cs{cs_if_exist_use:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests whether the \meta{control sequence} is currently defined
%   according to the conditional \cs{cs_if_exist:NTF}
%   (whether as a function or another control sequence type), and if it
%   is inserts the  \meta{control sequence} into the input stream followed
%   by the \meta{true code}.  Otherwise the \meta{false code} is used.
% \end{function}
%
% \begin{function}[EXP]{\cs:w, \cs_end:}
%   \begin{syntax}
%     \cs{cs:w} \meta{control sequence name} \cs{cs_end:}
%   \end{syntax}
%   Converts the given \meta{control sequence name} into a single
%   control sequence token. This process requires one expansion.
%   The content for \meta{control sequence name} may be literal
%   material or from other expandable functions. The
%   \meta{control sequence name} must, when fully expanded, consist
%   of character tokens which are not active: typically
%   of category code $10$ (space), $11$ (letter)
%   or $12$ (other), or a mixture of these.
%   \begin{texnote}
%     These are the \TeX{} primitives \tn{csname} and \tn{endcsname}.
%   \end{texnote}
% \end{function}
%
% As an example of the \cs{cs:w} and \cs{cs_end:} functions, both
%   \begin{verbatim}
%     \cs:w a b c \cs_end:
%   \end{verbatim}
%   and
%   \begin{verbatim}
%     \tl_new:N  \l_my_tl
%     \tl_set:Nn \l_my_tl { a b c }
%     \cs:w \tl_use:N \l_my_tl \cs_end:
%   \end{verbatim}
%   would be equivalent to
%   \begin{verbatim}
%     \abc
%   \end{verbatim}
%   after one expansion of \cs{cs:w}.
%
% \begin{function}[EXP]{\cs_to_str:N}
%   \begin{syntax}
%     \cs{cs_to_str:N} \meta{control sequence}
%   \end{syntax}
%   Converts the given \meta{control sequence} into a series of
%   characters with category code $12$ (other), except spaces,
%   of category code $10$. The result does \emph{not} include
%   the current escape token, contrarily to \cs{token_to_str:N}.
%   Full expansion of this function requires exactly $2$ expansion
%   steps, and so an \texttt{e}-type or \texttt{x}-type expansion, or two
%   \texttt{o}-type expansions are required to
%   convert the \meta{control sequence} to a sequence of characters
%   in the input stream. In most cases, an \texttt{f}-expansion
%   is correct as well, but this loses a space at the start
%   of the result.
% \end{function}
%
% \section{Analyzing control sequences}
%
% \begin{function}[EXP, added = 2018-04-06]{\cs_split_function:N}
%   \begin{syntax}
%     \cs{cs_split_function:N} \meta{function}
%   \end{syntax}
%   Splits the \meta{function} into the \meta{name} (i.e., the part
%   before the colon) and the \meta{signature} (i.e., after the colon).
%   This information is then placed in the input stream
%   in three parts: the \meta{name}, the
%   \meta{signature} and a logic token indicating if a colon was found
%   (to differentiate variables from function names). The \meta{name}
%   does not include the escape character, and both the \meta{name} and
%   \meta{signature} are made up of tokens with category code $12$
%   (other).
% \end{function}
%
% The next three functions decompose \TeX{} macros into their
% constituent parts: if the \meta{token} passed is not a macro then no
% decomposition can occur. In the latter case, all three functions leave
% \cs{scan_stop:} in the input stream.
%
% \begin{function}[EXP, added = 2019-02-27]{\cs_prefix_spec:N}
%   \begin{syntax}
%     \cs{cs_prefix_spec:N} \meta{token}
%   \end{syntax}
%   If the \meta{token} is a macro, this function leaves the applicable
%   \TeX{} prefixes in input stream as a string of tokens of category
%   code $12$ (with spaces having category code $10$). Thus for example
%   \begin{verbatim}
%     \cs_set:Npn \next:nn #1#2 { x #1~y #2 }
%     \cs_prefix_spec:N \next:nn
%   \end{verbatim}
%   leaves |\long| in the input stream. If the \meta{token} is
%   not a macro then \cs{scan_stop:} is left in the input stream.
%   \begin{texnote}
%     The prefix can be empty, |\long|, |\protected| or
%     |\protected\long| with backslash replaced by the current escape
%     character.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP, added = 2022-06-24]{\cs_parameter_spec:N}
%   \begin{syntax}
%     \cs{cs_parameter_spec:N} \meta{token}
%   \end{syntax}
%   If the \meta{token} is a macro, this function leaves the primitive
%   \TeX{} parameter specification in input stream as a string of
%   character tokens of category code $12$ (with spaces having category
%   code $10$). Thus for example
%   \begin{verbatim}
%     \cs_set:Npn \next:nn #1#2 { x #1 y #2 }
%     \cs_parameter_spec:N \next:nn
%   \end{verbatim}
%   leaves |#1#2| in the input stream. If the \meta{token} is
%   not a macro then \cs{scan_stop:} is left in the input stream.
%   \begin{texnote}
%     If the parameter specification contains the string |->|, then the
%     function produces incorrect results.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP, added = 2019-02-27]{\cs_replacement_spec:N, \cs_replacement_spec:c}
%   \begin{syntax}
%     \cs{cs_replacement_spec:N} \meta{token}
%   \end{syntax}
%   If the \meta{token} is a macro, this function leaves the replacement
%   text in input stream as a string of character tokens of category
%   code $12$ (with spaces having category code $10$). Thus for example
%   \begin{verbatim}
%     \cs_set:Npn \next:nn #1#2 { x #1~y #2 }
%     \cs_replacement_spec:N \next:nn
%   \end{verbatim}
%   leaves \verb*|x#1 y#2| in the input stream. If the \meta{token} is
%   not a macro then \cs{scan_stop:} is left in the input stream.
%   \begin{texnote}
%     If the parameter specification contains the string |->|, then the
%     function produces incorrect results.
%   \end{texnote}
% \end{function}
%
% \section{Using or removing tokens and arguments}
%
% Tokens in the input can be read and used or read and discarded.
% If one or more tokens are wrapped in braces then when absorbing them
% the outer set is removed. At the same time, the category code
% of each token is set when the token is read by a function (if it
% is read more than once, the category code is determined by
% the situation in force when first function absorbs the token).
%
% \begin{function}[EXP]{\use:n, \use:nn, \use:nnn, \use:nnnn}
%   \begin{syntax}
%     \cs{use:n}    \Arg{group_1}
%     \cs{use:nn}   \Arg{group_1} \Arg{group_2}
%     \cs{use:nnn}  \Arg{group_1} \Arg{group_2} \Arg{group_3}
%     \cs{use:nnnn} \Arg{group_1} \Arg{group_2} \Arg{group_3} \Arg{group_4}
%   \end{syntax}
%   As illustrated, these functions absorb between one and four
%   arguments, as indicated by the argument specifier. The braces
%   surrounding each argument are removed and the remaining tokens are
%   left in the input stream. The category code of these tokens is
%   also fixed by this process (if it has not already been by some
%   other absorption). All of these functions require only a single
%   expansion to operate, so that one expansion of
%   \begin{verbatim}
%     \use:nn { abc } { { def } }
%   \end{verbatim}
%   results in the input stream containing
%   \begin{verbatim}
%     abc { def }
%   \end{verbatim}
%   i.e. only the outer braces are removed.
%   \begin{texnote}
%     The \cs{use:n} function is equivalent to \LaTeXe{}'s \tn{@firstofone}.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]
%   {
%     \use_i:nn, \use_ii:nn ,
%     \use_i:nnn , \use_ii:nnn , \use_iii:nnn ,
%     \use_i:nnnn, \use_ii:nnnn, \use_iii:nnnn, \use_iv:nnnn  ,
%     \use_i:nnnnn, \use_ii:nnnnn, \use_iii:nnnnn, \use_iv:nnnnn ,
%       \use_v:nnnnn ,
%     \use_i:nnnnnn, \use_ii:nnnnnn, \use_iii:nnnnnn, \use_iv:nnnnnn ,
%       \use_v:nnnnnn , \use_vi:nnnnnn ,
%     \use_i:nnnnnnn, \use_ii:nnnnnnn, \use_iii:nnnnnnn, \use_iv:nnnnnnn ,
%       \use_v:nnnnnnn , \use_vi:nnnnnnn , \use_vii:nnnnnnn ,
%     \use_i:nnnnnnnn, \use_ii:nnnnnnnn, \use_iii:nnnnnnnn, \use_iv:nnnnnnnn ,
%       \use_v:nnnnnnnn , \use_vi:nnnnnnnn , \use_vii:nnnnnnnn , \use_viii:nnnnnnnn ,
%     \use_i:nnnnnnnnn, \use_ii:nnnnnnnnn, \use_iii:nnnnnnnnn, \use_iv:nnnnnnnnn ,
%       \use_v:nnnnnnnnn , \use_vi:nnnnnnnnn , \use_vii:nnnnnnnnn , \use_viii:nnnnnnnnn ,
%       \use_ix:nnnnnnnnn
%   }
%    \begin{syntax}
%     \cs{use_i:nn} \Arg{arg_1} \Arg{arg_2}
%     \cs{use_i:nnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3}
%     \cs{use_i:nnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4}
%     \cs{use_i:nnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5}
%     \cs{use_i:nnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6}
%     \cs{use_i:nnnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6} \Arg{arg_7}
%     \cs{use_i:nnnnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6} \Arg{arg_7} \Arg{arg_8}
%     \cs{use_i:nnnnnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6} \Arg{arg_7} \Arg{arg_8} \Arg{arg_9}
%   \end{syntax}
%   These functions absorb a number ($n$) arguments from the input stream.
%   They then discard all arguments other than that indicated by the roman
%   numeral, which is left in the input stream. For example, \cs{use_i:nn}
%   discards the second argument, and leaves the content of the first
%   argument in the input stream.
%   The category code
%   of these tokens is also fixed (if it has not already been by
%   some other absorption). A single expansion is needed for the
%   functions to take effect.
% \end{function}
%
% \begin{function}[EXP]{\use_i_ii:nnn}
%   \begin{syntax}
%     \cs{use_i_ii:nnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3}
%   \end{syntax}
%   This function absorbs three arguments and leaves the content of the
%   first and second in the input stream. The category code of
%   these tokens is also fixed (if it has not already been by
%   some other absorption). A single expansion is needed for the
%   function to take effect. An example:
%   \begin{verbatim}
%     \use_i_ii:nnn { abc } { { def } } { ghi }
%   \end{verbatim}
%   results in the input stream containing
%   \begin{verbatim}
%     abc { def }
%   \end{verbatim}
%   i.e. the outer braces are removed and the third group
%   is removed.
% \end{function}
%
% \begin{function}[EXP, added = 2019-06-02]{\use_ii_i:nn}
%   \begin{syntax}
%     \cs{use_ii_i:nn} \Arg{arg_1} \Arg{arg_2}
%   \end{syntax}
%   This function absorbs two arguments and leaves the content of the
%   second and first in the input stream. The category code of
%   these tokens is also fixed (if it has not already been by
%   some other absorption). A single expansion is needed for the
%   function to take effect.
% \end{function}
%
% \begin{function}[EXP]
%   {
%     \use_none:n         ,
%     \use_none:nn        ,
%     \use_none:nnn       ,
%     \use_none:nnnn      ,
%     \use_none:nnnnn     ,
%     \use_none:nnnnnn    ,
%     \use_none:nnnnnnn   ,
%     \use_none:nnnnnnnn  ,
%     \use_none:nnnnnnnnn
%   }
%   \begin{syntax}
%     \cs{use_none:n} \Arg{group_1}
%   \end{syntax}
%   These functions absorb between one and nine groups from the
%   input stream, leaving nothing on the resulting input stream.
%   These functions work after a single expansion. One or more of the
%   \texttt{n} arguments may be an unbraced single token
%   (i.e., an \texttt{N} argument).
%   \begin{texnote}
%     These are equivalent to \LaTeXe{}'s \tn{@gobble}, \tn{@gobbletwo},
%     etc.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP, added = 2018-06-18, updated = 2023-07-05]{\use:e}
%   \begin{syntax}
%     \cs{use:e} \Arg{expandable tokens}
%   \end{syntax}
%   Fully expands the \meta{token list} in an \texttt{e}-type manner,
%   in which parameter character (usually~|#|) need not be doubled, \emph{and}
%   the function remains fully expandable.
%   \begin{texnote}
%     \cs{use:e} is a wrapper around the primitive \tn{expanded}.
%     It requires two expansions to complete its action.
%   \end{texnote}
% \end{function}
%
% \subsection{Selecting tokens from delimited arguments}
%
% A different kind of function for selecting tokens from the token
% stream are those that use delimited arguments.
%
% \begin{function}[EXP]
%   {
%     \use_none_delimit_by_q_nil:w,
%     \use_none_delimit_by_q_stop:w,
%     \use_none_delimit_by_q_recursion_stop:w
%   }
%   \begin{syntax}
%    \cs{use_none_delimit_by_q_nil:w} \meta{balanced text} \cs{q_nil}
%    \cs{use_none_delimit_by_q_stop:w} \meta{balanced text} \cs{q_stop}
%    \cs{use_none_delimit_by_q_recursion_stop:w} \meta{balanced text} \cs{q_recursion_stop}
%   \end{syntax}
%   Absorb the \meta{balanced text} from the input stream delimited by
%   the marker given in the function name, leaving nothing in the
%   input stream.
% \end{function}
%
% \begin{function}[EXP]
%   {
%     \use_i_delimit_by_q_nil:nw,
%     \use_i_delimit_by_q_stop:nw,
%     \use_i_delimit_by_q_recursion_stop:nw
%   }
%   \begin{syntax}
%    \cs{use_i_delimit_by_q_nil:nw} \Arg{inserted tokens} \meta{balanced text} \cs{q_nil}
%    \cs{use_i_delimit_by_q_stop:nw} \Arg{inserted tokens} \meta{balanced text} \cs{q_stop}
%    \cs{use_i_delimit_by_q_recursion_stop:nw} \Arg{inserted tokens} \meta{balanced text} \cs{q_recursion_stop}
%   \end{syntax}
%   Absorb the \meta{balanced text} from the input stream delimited by
%   the marker given in the function name, leaving \meta{inserted tokens}
%   in the input stream for further processing.
% \end{function}
%
% \section{Predicates and conditionals}
%
% \LaTeX3 has three concepts for conditional flow processing:
% \begin{description}
%   \item[Branching conditionals]
%     Functions that carry out a test and then execute, depending on its
%     result, either the code supplied as the \meta{true code} or the
%     \meta{false code}.
%     These arguments are denoted with |T| and |F|, respectively. An
%     example would be
%     \begin{quote}
%      |\cs_if_free:cTF {abc}| \Arg{true code} \Arg{false code}
%     \end{quote}
%     a function that turns the first argument into a control sequence
%     (since it's marked as |c|) then checks whether this control sequence
%     is still free and then depending on the result carries out the code in
%     the second argument (true case) or in the third argument (false
%     case).
%
%     These type of functions are known as \enquote{conditionals};
%     whenever a |TF| function is defined it is usually accompanied by
%     |T| and |F| functions as well. These are provided for convenience when
%     the branch only needs to go a single way. Package writers are free to
%     choose which types to define but the kernel definitions always
%     provide all three versions.
%
%     Important to note is that these branching conditionals with \meta{true
%     code} and/or \meta{false code} are always defined in a way that the
%     code of the chosen alternative can operate on following tokens in
%     the input stream.
%
%     These conditional functions may or may not be fully expandable, but if
%     they are expandable they are accompanied by a \enquote{predicate}
%     for the same test as described below.
%
%   \item[Predicates]
%     \enquote{Predicates} are functions that return a special type of
%     boolean value which can be tested by the boolean expression parser.
%     All functions of this type
%     are expandable and have names that end with |_p| in the
%     description part.  For example,
%     \begin{quote}
%       \cs{cs_if_free_p:N}
%     \end{quote}
%     would be a predicate function for the same type of test as the
%     conditional described above. It would return \enquote{true} if its
%     argument (a single token denoted by |N|) is still free for definition.
%     It would be used in constructions like
%     \begin{quote}
%       "\bool_if:nTF" \\
%       "  { \cs_if_free_p:N \l_tmpz_tl || \cs_if_free_p:N \g_tmpz_tl }" \\
%       "  "\Arg{true code} \Arg{false code}
%     \end{quote}
%
%     For each predicate defined, a \enquote{branching conditional}
%     also exists that behaves like a conditional described above.
%
%   \item[Primitive conditionals]
%      There is a third variety of conditional, which is the original
%      concept used in plain \TeX{} and \LaTeXe{}. Their use is discouraged
%      in \pkg{expl3} (although still used in low-level definitions)
%      because they are more fragile and in many cases require more
%      expansion control (hence more code) than the two types of
%      conditionals described above.
% \end{description}
%
% \subsection{Tests on control sequences}
%
% \begin{function}[EXP,pTF]{\cs_if_eq:NN, \cs_if_eq:Nc, \cs_if_eq:cN, \cs_if_eq:cc}
%   \begin{syntax}
%     \cs{cs_if_eq_p:NN} \meta{cs_1} \meta{cs_2}
%     \cs{cs_if_eq:NNTF} \meta{cs_1} \meta{cs_2} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Compares the definition of two \meta{control sequences} and
%   is logically \texttt{true} if they are the same, i.e., if they have exactly
%   the same definition when examined with \cs{cs_show:N}.
% \end{function}
%
% \begin{function}[EXP,pTF]{\cs_if_exist:N, \cs_if_exist:c}
%   \begin{syntax}
%     \cs{cs_if_exist_p:N} \meta{control sequence}
%     \cs{cs_if_exist:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests whether the \meta{control sequence} is currently defined
%   (whether as a function or another control sequence type),
%   and its meaning is not the primitive \tn{relax} token.
%   This is different from \cs{if_cs_exist:N}, which evaluates to
%   \texttt{true} if passed the token \tn{relax} as an argument.
% \end{function}
%
% \begin{function}[EXP,pTF]{\cs_if_free:N, \cs_if_free:c}
%   \begin{syntax}
%     \cs{cs_if_free_p:N} \meta{control sequence}
%     \cs{cs_if_free:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   This test is the negation of the above \cs{cs_if_exist:NTF}.
% \end{function}
%
% \subsection{Primitive conditionals}
%
% The \eTeX{} engine itself provides many different conditionals. Some
% expand whatever comes after them and others don't. Hence the names
% for these underlying functions often contains a |:w| part but
% higher level functions are often available. See for instance
% \cs{int_compare_p:nNn} which is a wrapper for \cs{if_int_compare:w}.
%
% Certain conditionals deal with specific data types like boxes and
% fonts and are described there. The ones described below are either
% the universal conditionals or deal with control sequences. We
% prefix primitive conditionals with |\if_|, except for \cs{if:w}.
%
% \begin{function}[EXP]
%   {\if_true:, \if_false:, \else:, \fi:, \reverse_if:N}
%   \begin{syntax}
%     "\if_true:" <true code> "\else:" <false code> "\fi:" \\
%     "\if_false:" <true code> "\else:" <false code> "\fi:" \\
%     "\reverse_if:N" <primitive conditional>
%   \end{syntax}
%   "\if_true:" always executes <true code>, while "\if_false:" always
%   executes <false code>. "\reverse_if:N" reverses any two-way primitive
%   conditional. "\else:" and "\fi:" delimit the branches of the
%   conditional. The function "\or:" is documented in \pkg{l3int} and
%   used in case switches.
%   \begin{texnote}
%     \cs{if_true:} and \cs{if_false:} are equivalent to their corresponding
%     \TeX{} primitive conditionals \tn{iftrue} and \tn{iffalse};
%     \cs{else:} and \cs{fi:} are the \TeX{} primitives \tn{else} and \tn{fi};
%     \cs{reverse_if:N} is the \eTeX{} primitive \tn{unless}.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\if_meaning:w}
%   \begin{syntax}
%     "\if_meaning:w" <arg_1> <arg_2> <true code> "\else:" <false code> "\fi:"
%   \end{syntax}
%   "\if_meaning:w" executes <true code> when <arg_1> and <arg_2> are the same,
%   otherwise it executes <false code>.
%   <arg_1> and <arg_2> could be functions, variables, tokens; in all cases the
%   \emph{unexpanded} definitions are compared.
%   \begin{texnote}
%     This is the \TeX{} primitive \tn{ifx}.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\if:w, \if_charcode:w, \if_catcode:w}
%   \begin{syntax}
%     "\if:w" <token(s)> <true code> "\else:" <false code> "\fi:" \\
%     "\if_catcode:w" <token(s)> <true code> "\else:" <false code> "\fi:"
%   \end{syntax}
%   "\if_charcode:w" is an alternative name for "\if:w".
%   These conditionals expand \meta{token(s)} until two
%   unexpandable tokens \meta{token_1} and \meta{token_2} are found;
%   any further tokens up to the next unbalanced "\else:" are the true branch,
%   ending with \meta{true code}. It is executed if the condition is fulfilled,
%   otherwise \meta{false code} is executed.
%   You can omit "\else:" when just in front of "\fi:" and
%   you can nest "\if...\else:...\fi:" constructs inside the true branch or the
%   \meta{false code}.
%   With "\exp_not:N", you can prevent the expansion of a token. 
%
%   "\if_catcode:w"
%   tests if \meta{token_1} and \meta{token_2} have the same category code whereas
%   "\if:w" and \cs{if_charcode:w} test if they have the same character code.
%   \begin{texnote}
%     \cs{if:w} and \cs{if_charcode:w} are both the \TeX{} primitive \tn{if}.
%     \cs{if_catcode:w} is the \TeX{} primitive \tn{ifcat}.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\if_cs_exist:N, \if_cs_exist:w}
%   \begin{syntax}
%     "\if_cs_exist:N" <cs> <true code> "\else:" <false code> "\fi:" \\
%     "\if_cs_exist:w" <tokens> "\cs_end:" <true code> "\else:" <false code> "\fi:"
%   \end{syntax}
%   Check if <cs> appears in the hash table or if the control sequence
%   that can be formed from <tokens> appears in the hash table. The
%   latter function does not turn the control sequence in question into
%   the primitive \tn{relax} token. This can be useful when dealing with control
%   sequences which cannot be entered as a single token.
%   \begin{texnote}
%     These are the \TeX{} primitives \tn{ifdefined} and \tn{ifcsname}.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]
%   {
%     \if_mode_horizontal:, \if_mode_vertical:,
%     \if_mode_math:, \if_mode_inner:
%   }
%   \begin{syntax}
%     "\if_mode_horizontal:" <true code> "\else:" <false code> "\fi:"
%   \end{syntax}
%   Execute <true code> if currently in horizontal mode, otherwise
%   execute <false code>. Similar for the other functions.
%   \begin{texnote}
%     These are the \TeX{} primitives \tn{ifhmode}, \tn{ifvmode}, \tn{ifmmode},
%     and~\tn{ifinner}.
%   \end{texnote}
% \end{function}
%
% \section{Starting a paragraph}
%
% \begin{function}[added = 2017-07-04]{\mode_leave_vertical:}
%   \begin{syntax}
%     \cs{mode_leave_vertical:}
%   \end{syntax}
%   Ensures that \TeX{} is not in vertical (inter-paragraph) mode. In
%   horizontal or math mode this command has no effect, in vertical mode it
%   switches to horizontal mode, and inserts a box of width
%   \tn{parindent}, followed by the \tn{everypar} token list.
%   \begin{texnote}
%     This results in the contents of the \tn{everypar} token register being
%     inserted, after \cs{mode_leave_vertical:} is complete. Notice that in
%     contrast to the \LaTeXe{} \tn{leavevmode} approach, no box is used
%     by the method implemented here.
%   \end{texnote}
% \end{function}
%
% \section{Debugging support}
%
% \begin{function}[added = 2017-07-16, updated = 2023-05-23]{\debug_on:n, \debug_off:n}
%   \begin{syntax}
%     \cs{debug_on:n} \Arg{comma-separated list}
%     \cs{debug_off:n} \Arg{comma-separated list}
%   \end{syntax}
%   Turn on and off within a group various debugging code, some of which
%   is also available as \pkg{expl3} load-time options.  The items that
%   can be used in the \meta{list} are
%   \begin{itemize}
%     \item \texttt{check-assertions} that checks the invariants declared in
%       \cs{debug_assert:nn} and friends;
%     \item \texttt{check-declarations} that checks all \pkg{expl3}
%       variables used were previously declared and that local/global
%       variables (based on their name or on their first assignment) are
%       only locally/globally assigned;
%     \item \texttt{check-expressions} that checks integer, dimension,
%       skip, and muskip expressions are not terminated prematurely;
%     \item \texttt{deprecation} that makes deprecated commands produce errors;
%     \item \texttt{log-functions} that logs function definitions and
%       variable declarations;
%     \item \texttt{all} that does all of the above.
%   \end{itemize}
%   Providing these as switches rather than options allows testing code
%   even if it relies on other packages: load all other packages, call
%   \cs{debug_on:n}, and load the code that one is interested in
%   testing.
% \end{function}
%
% \begin{function}[added = 2017-11-28]{\debug_suspend:, \debug_resume:}
%   \begin{syntax}
%     \cs{debug_suspend:} \ldots{} \cs{debug_resume:}
%   \end{syntax}
%   Suppress (locally) errors and logging from \texttt{debug} commands,
%   except for the \texttt{deprecation} errors.  These pairs
%   of commands can be nested.  This can be used around pieces of code
%   that are known to fail checks, if such failures should be ignored.
%   See for instance \pkg{l3cctab} and \pkg{l3coffins}.
% \end{function}
%
% \begin{function}[added = 2026-03-06, EXP]
%   {
%     \debug_assert:nN,
%     \debug_assert:nn,
%     \debug_assert:nNn, \debug_assert:nNe,
%     \debug_assert:nnn, \debug_assert:nne
%   }
%   \begin{syntax}
%     \cs{debug_assert:nN} \Arg{module} \meta{boolean}
%     \cs{debug_assert:nn} \Arg{module} \Arg{boolean expression}
%     \cs{debug_assert:nNn} \Arg{module} \meta{boolean} \Arg{message text}
%     \cs{debug_assert:nnn} \Arg{module} \Arg{boolean expression} \Arg{message text}
%   \end{syntax}
%   Assert that the invariant specified by \meta{boolean} or \meta{boolean
%   expression} is |true| at this point in the code.
%
%   When assertion checking has been enabled with \cs{debug_on:n}
%   |{check-assertions}|, a violation of the invariant will produce an error
%   with a message formed from \meta{module} and the optional
%   \meta{message text}.
%
%   The invariant will \emph{only} be evaluated when assertion checking has
%   been enabled. Therefore, assertions can be used liberally throughout the
%   code without significant performance impact outside debugging.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3basics} implementation}
%
%    \begin{macrocode}
%<*code>
%    \end{macrocode}
%
% \subsection{Renaming some \TeX{} primitives (again)}
%
% Having given all the \TeX{} primitives a consistent name, we need to
% give sensible names to the ones we actually want to use.
% These will be defined as needed in the appropriate modules, but we
% do a few now, just to get started.\footnote{This renaming gets expensive
% in terms of csname usage, an alternative scheme would be to just use
% the \cs[no-index]{tex_\ldots:D} name in the cases where no good alternative exists.}
%
% \begin{macro}[EXP]
%   {
%     \if_true:, \if_false:, \or:, \else:, \fi:, \reverse_if:N,
%     \if:w, \if_charcode:w, \if_catcode:w, \if_meaning:w
%   }
%   Then some conditionals.
%    \begin{macrocode}
\tex_global:D \tex_let:D \if_true:           \tex_iftrue:D
\tex_global:D \tex_let:D \if_false:          \tex_iffalse:D
\tex_global:D \tex_let:D \or:                \tex_or:D
\tex_global:D \tex_let:D \else:              \tex_else:D
\tex_global:D \tex_let:D \fi:                \tex_fi:D
\tex_global:D \tex_let:D \reverse_if:N       \tex_unless:D
\tex_global:D \tex_let:D \if:w               \tex_if:D
\tex_global:D \tex_let:D \if_charcode:w      \tex_if:D
\tex_global:D \tex_let:D \if_catcode:w       \tex_ifcat:D
\tex_global:D \tex_let:D \if_meaning:w       \tex_ifx:D
\tex_global:D \tex_let:D \if_bool:N          \tex_ifodd:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {
%     \if_mode_math:,
%     \if_mode_horizontal:,
%     \if_mode_vertical:,
%     \if_mode_inner:
%   }
%   \TeX{} lets us detect some if its modes.
%    \begin{macrocode}
\tex_global:D \tex_let:D \if_mode_math:       \tex_ifmmode:D
\tex_global:D \tex_let:D \if_mode_horizontal: \tex_ifhmode:D
\tex_global:D \tex_let:D \if_mode_vertical:   \tex_ifvmode:D
\tex_global:D \tex_let:D \if_mode_inner:      \tex_ifinner:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\if_cs_exist:N, \if_cs_exist:w, \cs:w, \cs_end:}
%   Building csnames and testing if control sequences exist.
%    \begin{macrocode}
\tex_global:D \tex_let:D \if_cs_exist:N      \tex_ifdefined:D
\tex_global:D \tex_let:D \if_cs_exist:w      \tex_ifcsname:D
\tex_global:D \tex_let:D \cs:w               \tex_csname:D
\tex_global:D \tex_let:D \cs_end:            \tex_endcsname:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_after:wN, \exp_not:N, \exp_not:n}
%    The five |\exp_| functions are used in the \pkg{l3expan} module
%    where they are described.
%    \begin{macrocode}
\tex_global:D \tex_let:D \exp_after:wN       \tex_expandafter:D
\tex_global:D \tex_let:D \exp_not:N          \tex_noexpand:D
\tex_global:D \tex_let:D \exp_not:n          \tex_unexpanded:D
\tex_global:D \tex_let:D \exp:w              \tex_romannumeral:D
\tex_global:D \tex_chardef:D \exp_end:  = 0 ~
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\token_to_meaning:N, \cs_meaning:N}
%   Examining a control sequence or token.
%    \begin{macrocode}
\tex_global:D \tex_let:D \token_to_meaning:N \tex_meaning:D
\tex_global:D \tex_let:D \cs_meaning:N       \tex_meaning:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\tl_to_str:n, \token_to_str:N, \__kernel_tl_to_str:w}
%   Making strings.
%    \begin{macrocode}
\tex_global:D \tex_let:D \tl_to_str:n          \tex_detokenize:D
\tex_global:D \tex_let:D \token_to_str:N       \tex_string:D
\tex_global:D \tex_let:D \__kernel_tl_to_str:w \tex_detokenize:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\scan_stop:, \group_begin:, \group_end:}
%    The next three are basic functions for which there also exist
%    versions that are safe inside alignments. These safe versions are
%    defined in the \pkg{l3prg} module.
%    \begin{macrocode}
\tex_global:D \tex_let:D \scan_stop:         \tex_relax:D
\tex_global:D \tex_let:D \group_begin:       \tex_begingroup:D
\tex_global:D \tex_let:D \group_end:         \tex_endgroup:D
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%<@@=int>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\if_int_compare:w, \@@_to_roman:w}
%   For integers.
%    \begin{macrocode}
\tex_global:D \tex_let:D \if_int_compare:w   \tex_ifnum:D
\tex_global:D \tex_let:D \@@_to_roman:w     \tex_romannumeral:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\group_insert_after:N}
%   Adding material after the end of a group.
%    \begin{macrocode}
\tex_global:D \tex_let:D \group_insert_after:N \tex_aftergroup:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_args:Nc, \exp_args:cc}
%   Discussed in \pkg{l3expan}, but needed much earlier.
%    \begin{macrocode}
\tex_long:D \tex_gdef:D \exp_args:Nc #1#2
  { \exp_after:wN #1 \cs:w #2 \cs_end: }
\tex_long:D \tex_gdef:D \exp_args:cc #1#2
  { \cs:w #1 \exp_after:wN \cs_end: \cs:w #2 \cs_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP, documented-as=\token_to_meaning:N]
%   {\token_to_meaning:c, \token_to_str:c, \cs_meaning:c}
%   A small number of variants defined by hand.
%   Some of the necessary functions
%   (\cs{use_i:nn}, \cs{use_ii:nn}, and \cs{exp_args:NNc}) are not
%   defined at that point yet, but will be defined before those variants
%   are used.  The \cs{cs_meaning:c} command must check for an undefined
%   control sequence to avoid defining it mistakenly.
%    \begin{macrocode}
\tex_gdef:D \token_to_str:c { \exp_args:Nc \token_to_str:N }
\tex_long:D \tex_gdef:D \cs_meaning:c #1
  {
    \if_cs_exist:w #1 \cs_end:
      \exp_after:wN \use_i:nn
    \else:
      \exp_after:wN \use_ii:nn
    \fi:
    { \exp_args:Nc \cs_meaning:N {#1} }
    { \tl_to_str:n {undefined} }
  }
\tex_global:D \tex_let:D \token_to_meaning:c = \cs_meaning:c
%    \end{macrocode}
% \end{macro}
%
% \subsection{Defining some constants}
%
% \begin{variable}{\c_zero_int}
%   We need the constant \cs{c_zero_int}
%   which is used by some functions in current module. The
%   rest are defined in the \pkg{l3int} module -- at least for the
%   ones that can be defined with \cs{tex_chardef:D} or
%   \cs{tex_mathchardef:D}. For other constants the \pkg{l3int} module is
%   required but it can't be used until the allocation has been set
%   up properly!
%    \begin{macrocode}
\tex_global:D \tex_chardef:D \c_zero_int    = 0 ~
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_max_register_int}
%   This is here as this particular integer is needed in modules
%   loaded before \pkg{l3int}, and is documented in \pkg{l3int}.
%   \LuaTeX{} and those which contain parts of the Omega extensions have
%   more registers available than \eTeX{}.
%    \begin{macrocode}
\tex_ifdefined:D \tex_luatexversion:D
  \tex_global:D \tex_chardef:D \c_max_register_int = 65 535 ~
\tex_else:D
  \tex_ifdefined:D \tex_omathchardef:D
    \tex_global:D \tex_omathchardef:D \c_max_register_int = 65535 ~
  \tex_else:D
    \tex_global:D \tex_mathchardef:D \c_max_register_int = 32767 ~
  \tex_fi:D
\tex_fi:D
%    \end{macrocode}
% \end{variable}
%
% \subsection{Defining functions}
%
% We start by providing functions for the typical definition
% functions. First the global ones.
%
% \begin{macro}
%   {
%     \cs_gset_nopar:Npn           , \cs_gset_nopar:Npe           , \cs_gset_nopar:Npx           ,
%     \cs_gset:Npn                 , \cs_gset:Npe                 , \cs_gset:Npx                 ,
%     \cs_gset_protected_nopar:Npn , \cs_gset_protected_nopar:Npe , \cs_gset_protected_nopar:Npx ,
%     \cs_gset_protected:Npn       , \cs_gset_protected:Npe       , \cs_gset_protected:Npx
%   }
%   All assignment functions in \LaTeX3 should be naturally protected;
%   after all, the \TeX{} primitives for assignments are and it can be
%   a cause of problems if others aren't.
%    \begin{macrocode}
\tex_global:D \tex_let:D \cs_gset_nopar:Npn           \tex_gdef:D
\tex_global:D \tex_let:D \cs_gset_nopar:Npe           \tex_xdef:D
\tex_global:D \tex_let:D \cs_gset_nopar:Npx           \tex_xdef:D
\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset:Npn
  { \tex_long:D \tex_gdef:D }
\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset:Npe
  { \tex_long:D \tex_xdef:D }
\tex_global:D \tex_let:D \cs_gset:Npx \cs_gset:Npe
\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected_nopar:Npn
  { \tex_protected:D \tex_gdef:D }
\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected_nopar:Npe
  { \tex_protected:D \tex_xdef:D }
\tex_global:D \tex_let:D \cs_gset_protected_nopar:Npx \cs_gset_protected_nopar:Npe
\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected:Npn
  { \tex_protected:D \tex_long:D \tex_gdef:D }
\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected:Npe
  { \tex_protected:D \tex_long:D \tex_xdef:D }
\tex_global:D \tex_let:D \cs_gset_protected:Npx \cs_gset_protected:Npe
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \cs_set_nopar:Npn           , \cs_set_nopar:Npe           , \cs_set_nopar:Npx           ,
%     \cs_set:Npn                 , \cs_set:Npe                 , \cs_set:Npx                 ,
%     \cs_set_protected_nopar:Npn , \cs_set_protected_nopar:Npe , \cs_set_protected_nopar:Npx ,
%     \cs_set_protected:Npn       , \cs_set_protected:Npe       , \cs_set_protected:Npx
%   }
%   Local versions of the above functions.
%    \begin{macrocode}
\tex_global:D \tex_let:D \cs_set_nopar:Npn           \tex_def:D
\tex_global:D \tex_let:D \cs_set_nopar:Npe           \tex_edef:D
\tex_global:D \tex_let:D \cs_set_nopar:Npx           \tex_edef:D
\cs_gset_protected:Npn \cs_set:Npn
  { \tex_long:D \tex_def:D }
\cs_gset_protected:Npn \cs_set:Npe
  { \tex_long:D \tex_edef:D }
\tex_global:D \tex_let:D \cs_set:Npx \cs_set:Npe
\cs_gset_protected:Npn \cs_set_protected_nopar:Npn
  { \tex_protected:D \tex_def:D }
\cs_gset_protected:Npn \cs_set_protected_nopar:Npe
  { \tex_protected:D \tex_edef:D }
\tex_global:D \tex_let:D \cs_set_protected_nopar:Npx \cs_set_protected_nopar:Npe
\cs_gset_protected:Npn \cs_set_protected:Npn
  { \tex_protected:D \tex_long:D \tex_def:D }
\cs_gset_protected:Npn \cs_set_protected:Npe
  { \tex_protected:D \tex_long:D \tex_edef:D }
\tex_global:D \tex_let:D \cs_set_protected:Npx \cs_set_protected:Npe
%    \end{macrocode}
% \end{macro}
%
% \subsection{Selecting tokens}
%
%    \begin{macrocode}
%<@@=exp>
%    \end{macrocode}
%
% \begin{variable}{\l_@@_tmp_tl}
%   Scratch token list variable for \pkg{l3expan}, used by \cs{use:x},
%   used in defining conditionals.  We don't use |tl| methods because
%   \pkg{l3basics} is loaded earlier.
%    \begin{macrocode}
\cs_gset_nopar:Npn \l_@@_tmp_tl { }
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}[EXP]{\use:c}
%    This macro grabs its argument and returns a csname from it.
%    \begin{macrocode}
\cs_gset:Npn \use:c #1 { \cs:w #1 \cs_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[deprecated]{\use:x}
%   Fully expands its argument and passes it to the input stream. Uses
%   the reserved \cs{l_@@_tmp_tl} which we've set up above.
%    \begin{macrocode}
\cs_gset_protected:Npn \use:x #1
  {
    \cs_set_nopar:Npx \l_@@_tmp_tl {#1}
    \l_@@_tmp_tl
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%<@@=use>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\use:e}
%    \begin{macrocode}
\cs_gset:Npn \use:e #1 { \tex_expanded:D {#1} }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%<@@=exp>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\use:n, \use:nn, \use:nnn, \use:nnnn}
%    These macros grab their arguments and return them back to the input
%    (with outer braces removed).
%    \begin{macrocode}
\cs_gset:Npn \use:n    #1       {#1}
\cs_gset:Npn \use:nn   #1#2     {#1#2}
\cs_gset:Npn \use:nnn  #1#2#3   {#1#2#3}
\cs_gset:Npn \use:nnnn #1#2#3#4 {#1#2#3#4}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\use_i:nn, \use_ii:nn}
%    The equivalent to \LaTeXe{}'s \tn{@firstoftwo} and \tn{@secondoftwo}.
%    \begin{macrocode}
\cs_gset:Npn \use_i:nn  #1#2 {#1}
\cs_gset:Npn \use_ii:nn #1#2 {#2}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {
%     \use_i:nnn , \use_ii:nnn , \use_iii:nnn ,
%     \use_i:nnnn, \use_ii:nnnn, \use_iii:nnnn, \use_iv:nnnn  ,
%     \use_i:nnnnn, \use_ii:nnnnn, \use_iii:nnnnn, \use_iv:nnnnn ,
%       \use_v:nnnnn ,
%     \use_i:nnnnnn, \use_ii:nnnnnn, \use_iii:nnnnnn, \use_iv:nnnnnn ,
%       \use_v:nnnnnn , \use_vi:nnnnnn ,
%     \use_i:nnnnnnn, \use_ii:nnnnnnn, \use_iii:nnnnnnn, \use_iv:nnnnnnn ,
%       \use_v:nnnnnnn , \use_vi:nnnnnnn , \use_vii:nnnnnnn ,
%     \use_i:nnnnnnnn, \use_ii:nnnnnnnn, \use_iii:nnnnnnnn, \use_iv:nnnnnnnn ,
%       \use_v:nnnnnnnn , \use_vi:nnnnnnnn , \use_vii:nnnnnnnn , \use_viii:nnnnnnnn ,
%     \use_i:nnnnnnnnn, \use_ii:nnnnnnnnn, \use_iii:nnnnnnnnn, \use_iv:nnnnnnnnn ,
%       \use_v:nnnnnnnnn , \use_vi:nnnnnnnnn , \use_vii:nnnnnnnnn , \use_viii:nnnnnnnnn ,
%       \use_ix:nnnnnnnnn
%   }
%   We also need something for picking up arguments from a longer list.
%    \begin{macrocode}
\cs_gset:Npn \use_i:nnn    #1#2#3 {#1}
\cs_gset:Npn \use_ii:nnn   #1#2#3 {#2}
\cs_gset:Npn \use_iii:nnn  #1#2#3 {#3}
\cs_gset:Npn \use_i:nnnn   #1#2#3#4 {#1}
\cs_gset:Npn \use_ii:nnnn  #1#2#3#4 {#2}
\cs_gset:Npn \use_iii:nnnn #1#2#3#4 {#3}
\cs_gset:Npn \use_iv:nnnn  #1#2#3#4 {#4}
\cs_gset:Npn \use_i:nnnnn   #1#2#3#4#5 {#1}
\cs_gset:Npn \use_ii:nnnnn  #1#2#3#4#5 {#2}
\cs_gset:Npn \use_iii:nnnnn #1#2#3#4#5 {#3}
\cs_gset:Npn \use_iv:nnnnn  #1#2#3#4#5 {#4}
\cs_gset:Npn \use_v:nnnnn   #1#2#3#4#5 {#5}
\cs_gset:Npn \use_i:nnnnnn   #1#2#3#4#5#6 {#1}
\cs_gset:Npn \use_ii:nnnnnn  #1#2#3#4#5#6 {#2}
\cs_gset:Npn \use_iii:nnnnnn #1#2#3#4#5#6 {#3}
\cs_gset:Npn \use_iv:nnnnnn  #1#2#3#4#5#6 {#4}
\cs_gset:Npn \use_v:nnnnnn   #1#2#3#4#5#6 {#5}
\cs_gset:Npn \use_vi:nnnnnn  #1#2#3#4#5#6 {#6}
\cs_gset:Npn \use_i:nnnnnnn   #1#2#3#4#5#6#7 {#1}
\cs_gset:Npn \use_ii:nnnnnnn  #1#2#3#4#5#6#7 {#2}
\cs_gset:Npn \use_iii:nnnnnnn #1#2#3#4#5#6#7 {#3}
\cs_gset:Npn \use_iv:nnnnnnn  #1#2#3#4#5#6#7 {#4}
\cs_gset:Npn \use_v:nnnnnnn   #1#2#3#4#5#6#7 {#5}
\cs_gset:Npn \use_vi:nnnnnnn  #1#2#3#4#5#6#7 {#6}
\cs_gset:Npn \use_vii:nnnnnnn #1#2#3#4#5#6#7 {#7}
\cs_gset:Npn \use_i:nnnnnnnn    #1#2#3#4#5#6#7#8 {#1}
\cs_gset:Npn \use_ii:nnnnnnnn   #1#2#3#4#5#6#7#8 {#2}
\cs_gset:Npn \use_iii:nnnnnnnn  #1#2#3#4#5#6#7#8 {#3}
\cs_gset:Npn \use_iv:nnnnnnnn   #1#2#3#4#5#6#7#8 {#4}
\cs_gset:Npn \use_v:nnnnnnnn    #1#2#3#4#5#6#7#8 {#5}
\cs_gset:Npn \use_vi:nnnnnnnn   #1#2#3#4#5#6#7#8 {#6}
\cs_gset:Npn \use_vii:nnnnnnnn  #1#2#3#4#5#6#7#8 {#7}
\cs_gset:Npn \use_viii:nnnnnnnn #1#2#3#4#5#6#7#8 {#8}
\cs_gset:Npn \use_i:nnnnnnnnn    #1#2#3#4#5#6#7#8#9 {#1}
\cs_gset:Npn \use_ii:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#2}
\cs_gset:Npn \use_iii:nnnnnnnnn  #1#2#3#4#5#6#7#8#9 {#3}
\cs_gset:Npn \use_iv:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#4}
\cs_gset:Npn \use_v:nnnnnnnnn    #1#2#3#4#5#6#7#8#9 {#5}
\cs_gset:Npn \use_vi:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#6}
\cs_gset:Npn \use_vii:nnnnnnnnn  #1#2#3#4#5#6#7#8#9 {#7}
\cs_gset:Npn \use_viii:nnnnnnnnn #1#2#3#4#5#6#7#8#9 {#8}
\cs_gset:Npn \use_ix:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#9}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\use_i_ii:nnn}
%    \begin{macrocode}
\cs_gset:Npn \use_i_ii:nnn #1#2#3 {#1#2}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\use_ii_i:nn}
%    \begin{macrocode}
\cs_gset:Npn \use_ii_i:nn #1#2 { #2 #1 }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[EXP]
%   {
%     \use_none_delimit_by_q_nil:w  ,
%     \use_none_delimit_by_q_stop:w ,
%     \use_none_delimit_by_q_recursion_stop:w
%   }
%   Functions that gobble everything until they see either \cs{q_nil},
%   \cs{q_stop}, or \cs{q_recursion_stop}, respectively.
%    \begin{macrocode}
\cs_gset:Npn \use_none_delimit_by_q_nil:w  #1 \q_nil  { }
\cs_gset:Npn \use_none_delimit_by_q_stop:w #1 \q_stop { }
\cs_gset:Npn \use_none_delimit_by_q_recursion_stop:w #1 \q_recursion_stop { }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {
%     \use_i_delimit_by_q_nil:nw  ,
%     \use_i_delimit_by_q_stop:nw ,
%     \use_i_delimit_by_q_recursion_stop:nw
%   }
%   Same as above but execute first argument after gobbling. Very useful
%   when you need to skip the rest of a mapping sequence but want an
%   easy way to control what should be expanded next.
%    \begin{macrocode}
\cs_gset:Npn \use_i_delimit_by_q_nil:nw  #1#2 \q_nil  {#1}
\cs_gset:Npn \use_i_delimit_by_q_stop:nw #1#2 \q_stop {#1}
\cs_gset:Npn \use_i_delimit_by_q_recursion_stop:nw
  #1#2 \q_recursion_stop {#1}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Gobbling tokens from input}
%
% \begin{macro}[EXP]
%   {
%     \use_none:n,
%     \use_none:nn,
%     \use_none:nnn,
%     \use_none:nnnn,
%     \use_none:nnnnn,
%     \use_none:nnnnnn,
%     \use_none:nnnnnnn,
%     \use_none:nnnnnnnn,
%     \use_none:nnnnnnnnn
%   }
%   To gobble tokens from the input we use a standard naming convention:
%   the number of tokens gobbled is given by the number of |n|'s
%   following the |:| in the name. Although we could define functions to
%   remove ten arguments or more using separate calls of
%   \cs{use_none:nnnnn}, this is very non-intuitive to the programmer
%   who will assume that expanding such a function once takes care
%   of gobbling all the tokens in one go.
%    \begin{macrocode}
\cs_gset:Npn \use_none:n         #1                 { }
\cs_gset:Npn \use_none:nn        #1#2               { }
\cs_gset:Npn \use_none:nnn       #1#2#3             { }
\cs_gset:Npn \use_none:nnnn      #1#2#3#4           { }
\cs_gset:Npn \use_none:nnnnn     #1#2#3#4#5         { }
\cs_gset:Npn \use_none:nnnnnn    #1#2#3#4#5#6       { }
\cs_gset:Npn \use_none:nnnnnnn   #1#2#3#4#5#6#7     { }
\cs_gset:Npn \use_none:nnnnnnnn  #1#2#3#4#5#6#7#8   { }
\cs_gset:Npn \use_none:nnnnnnnnn #1#2#3#4#5#6#7#8#9 { }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Debugging and patching later definitions}
%
%    \begin{macrocode}
%<@@=debug>
%    \end{macrocode}
%
% \begin{macro}{\__kernel_if_debug:TF}
%   A more meaningful test of whether debugging is enabled than messing
%   up with guards.  We can also more easily change the logic in one
%   place then. This is needed primarily for deprecations.
%    \begin{macrocode}
\cs_gset_protected:Npn \__kernel_if_debug:TF #1#2 {#2}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\debug_on:n, \debug_off:n}
%   Stubs.
%    \begin{macrocode}
\cs_gset_protected:Npn \debug_on:n #1
  {
    \sys_load_debug:
    \cs_if_exist:NT \@@_all_on:
      { \debug_on:n {#1} }
  }
\cs_gset_protected:Npn \debug_off:n #1
  {
    \sys_load_debug:
    \cs_if_exist:NT \@@_all_on:
      { \debug_off:n {#1} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\debug_suspend:, \debug_resume:}
%    \begin{macrocode}
\cs_gset_protected:Npn \debug_suspend: { }
\cs_gset_protected:Npn \debug_resume: { }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {
%     \debug_assert:nN,
%     \debug_assert:nn,
%     \debug_assert:nNn,
%     \debug_assert:nnn
%   }
%    \begin{macrocode}
\cs_gset:Npn \debug_assert:nN  #1#2   { }
\cs_gset:Npn \debug_assert:nn  #1#2   { }
\cs_gset:Npn \debug_assert:nNn #1#2#3 { }
\cs_gset:Npn \debug_assert:nnn #1#2#3 { }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_deprecation_code:nn}
% \begin{variable}{\g_@@_deprecation_on_tl, \g_@@_deprecation_off_tl}
%   Make deprecated commands throw errors if the user requests it.
%   This relies on two token lists, filled up in \pkg{l3deprecation}.
%    \begin{macrocode}
\cs_gset_nopar:Npn \g_@@_deprecation_on_tl { }
\cs_gset_nopar:Npn \g_@@_deprecation_off_tl { }
\cs_gset_protected:Npn \__kernel_deprecation_code:nn #1#2
  {
    \tl_gput_right:Nn \g_@@_deprecation_on_tl {#1}
    \tl_gput_right:Nn \g_@@_deprecation_off_tl {#2}
  }
%    \end{macrocode}
% \end{variable}
% \end{macro}
%
% \subsection{Conditional processing and definitions}
%
%    \begin{macrocode}
%<@@=prg>
%    \end{macrocode}
%
% Underneath any predicate function (|_p|) or other conditional forms
% (|TF|, etc.) is a built-in logic saying that it after all of the
% testing and processing must return the \meta{state} this leaves
% \TeX{} in. Therefore, a simple user interface could be something like
% \begin{verbatim}
%   \if_meaning:w #1#2
%     \prg_return_true:
%   \else:
%     \if_meaning:w #1#3
%       \prg_return_true:
%     \else:
%       \prg_return_false:
%     \fi:
%   \fi:
% \end{verbatim}
% Usually, a \TeX{} programmer would have to insert a number of
% \cs{exp_after:wN}s to ensure the state value is returned at exactly
% the point where the last conditional is finished.  However, that
% obscures the code and forces the \TeX{} programmer to prove that
% he/she knows the $2^{n}-1$ table.  We therefore provide the simpler
% interface.
%
% \begin{macro}[EXP]{\prg_return_true:, \prg_return_false:}
%   The idea here is that \cs{exp:w} expands fully any
%   \cs{else:} and \cs{fi:} that are waiting to be discarded,
%   before reaching the \cs{exp_end:} which leaves an empty expansion.
%   The code can then leave either the first or second argument in the
%   input stream. This means that all of the branching code has to contain
%   at least two tokens: see how the logical tests are actually implemented
%   to see this.
%    \begin{macrocode}
\cs_gset:Npn \prg_return_true:
  { \exp_after:wN \use_i:nn  \exp:w }
\cs_gset:Npn \prg_return_false:
  { \exp_after:wN \use_ii:nn \exp:w}
%    \end{macrocode}
%   An extended state space could be implemented by including a more
%   elaborate function in place of \cs{use_i:nn}/\cs{use_ii:nn}. Provided
%   two arguments are absorbed then the code would work.
% \end{macro}
%
% \begin{macro}[EXP]{\@@_use_none_delimit_by_q_recursion_stop:w}
%   Private version of \cs{use_none_delimit_by_q_recursion_stop:w}.
%    \begin{macrocode}
\cs_gset:Npn \@@_use_none_delimit_by_q_recursion_stop:w
  #1 \q_@@_recursion_stop { }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \prg_set_conditional:Npnn           ,
%     \prg_gset_conditional:Npnn          ,
%     \prg_new_conditional:Npnn           ,
%     \prg_set_protected_conditional:Npnn ,
%     \prg_gset_protected_conditional:Npnn,
%     \prg_new_protected_conditional:Npnn
%   }
% \begin{macro}{\@@_generate_conditional_parm:NNNpnn}
%   The user functions for the types using parameter text from the
%   programmer. The various functions only differ by which function is
%   used for the assignment. For those |Npnn| type functions, we must
%   grab the parameter text, reading everything up to a left brace
%   before continuing. Then split the base function into name and
%   signature, and feed \Arg{name} \Arg{signature} \meta{boolean}
%   \Arg{set~or~new} \Arg{maybe~protected} \Arg{parameters} |{TF,...}|
%   \Arg{code} to the auxiliary function responsible for defining all
%   conditionals.
%   Note that |e| stands for expandable and |p| for protected.
%    \begin{macrocode}
\cs_gset_protected:Npn \prg_set_conditional:Npnn
  { \@@_generate_conditional_parm:NNNpnn \cs_set:Npn e }
\cs_gset_protected:Npn \prg_gset_conditional:Npnn
  { \@@_generate_conditional_parm:NNNpnn \cs_gset:Npn e }
\cs_gset_protected:Npn \prg_new_conditional:Npnn
  { \@@_generate_conditional_parm:NNNpnn \cs_new:Npn e }
\cs_gset_protected:Npn \prg_set_protected_conditional:Npnn
  { \@@_generate_conditional_parm:NNNpnn \cs_set_protected:Npn p }
\cs_gset_protected:Npn \prg_gset_protected_conditional:Npnn
  { \@@_generate_conditional_parm:NNNpnn \cs_gset_protected:Npn p }
\cs_gset_protected:Npn \prg_new_protected_conditional:Npnn
  { \@@_generate_conditional_parm:NNNpnn \cs_new_protected:Npn p }
\cs_gset_protected:Npn \@@_generate_conditional_parm:NNNpnn #1#2#3#4#
  {
    \use:e
      {
        \@@_generate_conditional:nnNNNnnn
          \cs_split_function:N #3
      }
      #1 #2 {#4}
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \prg_set_conditional:Nnn           ,
%     \prg_gset_conditional:Nnn          ,
%     \prg_new_conditional:Nnn           ,
%     \prg_set_protected_conditional:Nnn ,
%     \prg_gset_protected_conditional:Nnn,
%     \prg_new_protected_conditional:Nnn
%   }
% \begin{macro}
%   {
%     \@@_generate_conditional_count:NNNnn ,
%     \@@_generate_conditional_count:nnNNNnn
%   }
%   The user functions for the types automatically inserting the correct
%   parameter text based on the signature. The various functions only
%   differ by which function is used for the assignment. Split the base
%   function into name and signature.  The second auxiliary generates
%   the parameter text from the number of letters in the signature.
%   Then feed \Arg{name} \Arg{signature} \meta{boolean} \Arg{set~or~new}
%   \Arg{maybe~protected} \Arg{parameters} |{TF,...}| \Arg{code} to the
%   auxiliary function responsible for defining all conditionals.  If
%   the \meta{signature} has more than $9$ letters, the definition is
%   aborted since \TeX{} macros have at most $9$ arguments.  The
%   erroneous case where the function name contains no colon is captured
%   later.
%    \begin{macrocode}
\cs_gset_protected:Npn \prg_set_conditional:Nnn
  { \@@_generate_conditional_count:NNNnn \cs_set:Npn e }
\cs_gset_protected:Npn \prg_gset_conditional:Nnn
  { \@@_generate_conditional_count:NNNnn \cs_gset:Npn e }
\cs_gset_protected:Npn \prg_new_conditional:Nnn
  { \@@_generate_conditional_count:NNNnn \cs_new:Npn e }
\cs_gset_protected:Npn \prg_set_protected_conditional:Nnn
  { \@@_generate_conditional_count:NNNnn \cs_set_protected:Npn p }
\cs_gset_protected:Npn \prg_gset_protected_conditional:Nnn
  { \@@_generate_conditional_count:NNNnn \cs_gset_protected:Npn p }
\cs_gset_protected:Npn \prg_new_protected_conditional:Nnn
  { \@@_generate_conditional_count:NNNnn \cs_new_protected:Npn p }
\cs_gset_protected:Npn \@@_generate_conditional_count:NNNnn #1#2#3
  {
    \use:e
      {
        \@@_generate_conditional_count:nnNNNnn
        \cs_split_function:N #3
      }
      #1 #2
  }
\cs_gset_protected:Npn \@@_generate_conditional_count:nnNNNnn #1#2#3#4#5
  {
    \__kernel_cs_parm_from_arg_count:nnF
      { \@@_generate_conditional:nnNNNnnn {#1} {#2} #3 #4 #5 }
      { \tl_count:n {#2} }
      {
        \msg_error:nnee { kernel } { bad-number-of-arguments }
          { \token_to_str:c { #1 : #2 } }
          { \tl_count:n {#2} }
        \use_none:nn
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \@@_generate_conditional:nnNNNnnn,
%     \@@_generate_conditional:NNnnnnNw,
%     \@@_generate_conditional_test:w,
%     \@@_generate_conditional_fast:nw,
%   }
%   The workhorse here is going through a list of desired forms, i.e.,
%   |p|, |TF|, |T| and |F|. The first three arguments come from splitting up
%   the base form of the conditional, which gives the name, signature
%   and a boolean to signal whether or not there was a colon in the
%   name. In the absence of a colon, we throw an error and don't define
%   any conditional. The fourth and fifth arguments build up the
%   defining function.  The sixth is the parameters to use (possibly
%   empty), the seventh is the list of forms to define, the eighth is the
%   replacement text which we will augment when defining the forms.
%   The use of \cs{tl_to_str:n} makes the later loop more robust.
%
%   A large number of our low-level conditionals look like \meta{code}
%   \cs{prg_return_true:} \cs{else:} \cs{prg_return_false:} \cs{fi:} so
%   we optimize this special case by calling
%   \cs{@@_generate_conditional_fast:nw} \Arg{code}.  This passes
%   \cs{use_i:nn} instead of \cs{use_i_ii:nnn} to functions such as
%   \cs{@@_generate_p_form:wNNnnnnN}.
%    \begin{macrocode}
\cs_gset_protected:Npn \@@_generate_conditional:nnNNNnnn #1#2#3#4#5#6#7#8
  {
    \if_meaning:w \c_false_bool #3
      \msg_error:nne { kernel } { missing-colon }
        { \token_to_str:c {#1} }
      \exp_after:wN \use_none:nn
    \fi:
    \use:e
      {
        \exp_not:N \@@_generate_conditional:NNnnnnNw
        \exp_not:n { #4 #5 {#1} {#2} {#6} }
        \@@_generate_conditional_test:w
          #8 \s_@@_mark
            \@@_generate_conditional_fast:nw
          \prg_return_true: \else: \prg_return_false: \fi: \s_@@_mark
            \use_none:n
        \exp_not:n { {#8} \use_i_ii:nnn }
        \tl_to_str:n {#7}
        \exp_not:n { , \q_@@_recursion_tail , \q_@@_recursion_stop }
      }
  }
\cs_gset:Npn \@@_generate_conditional_test:w
    #1 \prg_return_true: \else: \prg_return_false: \fi: \s_@@_mark #2
  { #2 {#1} }
\cs_gset:Npn \@@_generate_conditional_fast:nw #1#2 \exp_not:n #3
  { \exp_not:n { {#1} \use_i:nn } }
%    \end{macrocode}
%   Looping through the list of desired forms.  First are six arguments
%   and seventh is the form.  Use the form to call the
%   correct type.  If the form does not exist, the \cs{use:c}
%   construction results in \tn{relax}, and the error message is
%   displayed (unless the form is empty, to allow for |{T, , F}|),
%   then \cs{use_none:nnnnnnnn} cleans up.  Otherwise, the
%   error message is removed by the variant form.
%    \begin{macrocode}
\cs_gset_protected:Npn \@@_generate_conditional:NNnnnnNw #1#2#3#4#5#6#7#8 ,
  {
    \if_meaning:w \q_@@_recursion_tail #8
      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
    \fi:
    \use:c { @@_generate_ #8 _form:wNNnnnnN }
        \tl_if_empty:nF {#8}
          {
            \msg_error:nnee
              { kernel } { conditional-form-unknown }
              {#8} { \token_to_str:c { #3 : #4 } }
          }
        \use_none:nnnnnnnn
      \s_@@_stop
      #1 #2 {#3} {#4} {#5} {#6} #7
    \@@_generate_conditional:NNnnnnNw #1 #2 {#3} {#4} {#5} {#6} #7
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \@@_generate_p_form:wNNnnnnN,
%     \@@_generate_TF_form:wNNnnnnN,
%     \@@_generate_T_form:wNNnnnnN,
%     \@@_generate_F_form:wNNnnnnN
%   }
% \begin{macro}[EXP]{\@@_p_true:w, \@@_T_true:w, \@@_F_true:w, \@@_TF_true:w}
%   How to generate the various forms. Those functions take the
%   following arguments: 1: junk, 2: \cs{cs_set:Npn} or similar, 3: |p|
%   (for protected conditionals) or |e|, 4: function name, 5: signature,
%   6: parameter text, 7: replacement (possibly trimmed by
%   \cs{@@_generate_conditional_fast:nw}), 8: \cs{use_i_ii:nnn} or
%   \cs{use_i:nn} (for \enquote{fast} conditionals).  Remember that the
%   logic-returning functions expect two arguments to be present after
%   \cs{exp_end:}: notice the construction of the different variants
%   relies on this, and that the |TF| and |F| variants will be slightly
%   faster than the |T| version.  The |p| form is only valid for
%   expandable tests, we check for that by making sure that the second
%   argument is empty.  For \enquote{fast} conditionals, |#7| has an
%   extra \cs[no-index]{if_\ldots{}}.  To optimize a bit further we
%   don't use \cs{exp_after:wN} \cs{use_ii:nnn} and similar but instead use
%   \cs{@@_TF_true:w} and similar to swap out the macro after \cs{fi:}. It would
%   be a tiny bit faster if we directly grabbed the |T| and |F| arguments there,
%   but if those are actually missing, the recovery from the runaway argument
%   would not insert \cs{fi:} back, messing up nesting of conditionals.
%    \begin{macrocode}
\cs_gset_protected:Npn \@@_generate_p_form:wNNnnnnN
    #1 \s_@@_stop #2#3#4#5#6#7#8
  {
    \if_meaning:w e #3
      \exp_after:wN \use_i:nn
    \else:
      \exp_after:wN \use_ii:nn
    \fi:
      {
        #8
          { \exp_args:Nc #2 { #4 _p: #5 } #6 }
          { { #7 \exp_end: \c_true_bool \c_false_bool } }
          { #7 \@@_p_true:w \fi: \c_false_bool }
      }
      {
        \msg_error:nne { kernel } { protected-predicate }
          { \token_to_str:c { #4 _p: #5 } }
      }
  }
\cs_gset_protected:Npn \@@_generate_T_form:wNNnnnnN
    #1 \s_@@_stop #2#3#4#5#6#7#8
  {
    #8
      { \exp_args:Nc #2 { #4 : #5 T } #6 }
      { { #7 \exp_end: \use:n \use_none:n } }
      { #7 \@@_T_true:w \fi: \use_none:n }
  }
\cs_gset_protected:Npn \@@_generate_F_form:wNNnnnnN
    #1 \s_@@_stop #2#3#4#5#6#7#8
  {
    #8
      { \exp_args:Nc #2 { #4 : #5 F } #6 }
      { { #7 \exp_end: { } } }
      { #7 \@@_F_true:w \fi: \use:n }
  }
\cs_gset_protected:Npn \@@_generate_TF_form:wNNnnnnN
    #1 \s_@@_stop #2#3#4#5#6#7#8
  {
    #8
      { \exp_args:Nc #2 { #4 : #5 TF } #6 }
      { { #7 \exp_end: } }
      { #7 \@@_TF_true:w \fi: \use_ii:nn }
  }
\cs_gset:Npn \@@_p_true:w  \fi: \c_false_bool { \fi: \c_true_bool }
\cs_gset:Npn \@@_T_true:w  \fi: \use_none:n   { \fi: \use:n }
\cs_gset:Npn \@@_F_true:w  \fi: \use:n        { \fi: \use_none:n }
\cs_gset:Npn \@@_TF_true:w \fi: \use_ii:nn    { \fi: \use_i:nn }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \prg_set_eq_conditional:NNn ,
%     \prg_gset_eq_conditional:NNn,
%     \prg_new_eq_conditional:NNn
%   }
% \begin{macro}{\@@_set_eq_conditional:NNNn}
%   The setting-equal functions.  Split both functions and feed
%   \Arg{name_1} \Arg{signature_1} \meta{boolean_1}
%   \Arg{name_2} \Arg{signature_2} \meta{boolean_2}
%   \meta{copying~function} \meta{conditions} |,| \cs{q_@@_recursion_tail}
%   |,| \cs{q_@@_recursion_stop}
%   to a first auxiliary.
%    \begin{macrocode}
\cs_gset_protected:Npn \prg_set_eq_conditional:NNn
  { \@@_set_eq_conditional:NNNn \cs_set_eq:cc }
\cs_gset_protected:Npn \prg_gset_eq_conditional:NNn
  { \@@_set_eq_conditional:NNNn \cs_gset_eq:cc }
\cs_gset_protected:Npn \prg_new_eq_conditional:NNn
  { \@@_set_eq_conditional:NNNn \cs_new_eq:cc }
\cs_gset_protected:Npn \@@_set_eq_conditional:NNNn #1#2#3#4
  {
    \use:e
      {
        \exp_not:N \@@_set_eq_conditional:nnNnnNNw
          \cs_split_function:N #2
          \cs_split_function:N #3
          \exp_not:N #1
          \tl_to_str:n {#4}
          \exp_not:n { , \q_@@_recursion_tail , \q_@@_recursion_stop }
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \@@_set_eq_conditional:nnNnnNNw ,
%     \@@_set_eq_conditional_loop:nnnnNw
%   }
% \begin{macro}[EXP]
%   {
%     \@@_set_eq_conditional_p_form:nnn  ,
%     \@@_set_eq_conditional_TF_form:nnn ,
%     \@@_set_eq_conditional_T_form:nnn  ,
%     \@@_set_eq_conditional_F_form:nnn  ,
%   }
%   Split the function to be defined, and setup a manual clist loop over
%   argument |#6| of the first auxiliary.  The second auxiliary receives
%   twice three arguments coming from splitting the function to be
%   defined and the function to copy.  Make sure that both functions
%   contained a colon, otherwise we don't know how to build
%   conditionals, hence abort.  Call the looping macro, with arguments
%   \Arg{name_1} \Arg{signature_1} \Arg{name_2} \Arg{signature_2}
%   \meta{copying~function} and followed by the comma list.  At each
%   step in the loop, make sure that the conditional form we copy is
%   defined, and copy it, otherwise abort.
%    \begin{macrocode}
\cs_gset_protected:Npn \@@_set_eq_conditional:nnNnnNNw #1#2#3#4#5#6
  {
    \if_meaning:w \c_false_bool #3
      \msg_error:nne { kernel } { missing-colon }
        { \token_to_str:c {#1} }
      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
    \fi:
    \if_meaning:w \c_false_bool #6
      \msg_error:nne { kernel } { missing-colon }
        { \token_to_str:c {#4} }
      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
    \fi:
    \@@_set_eq_conditional_loop:nnnnNw {#1} {#2} {#4} {#5}
  }
\cs_gset_protected:Npn \@@_set_eq_conditional_loop:nnnnNw #1#2#3#4#5#6 ,
  {
    \if_meaning:w \q_@@_recursion_tail #6
      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
    \fi:
    \use:c { @@_set_eq_conditional_ #6 _form:wNnnnn }
        \tl_if_empty:nF {#6}
          {
            \msg_error:nnee
              { kernel } { conditional-form-unknown }
              {#6} { \token_to_str:c { #1 : #2 } }
          }
        \use_none:nnnnnn
      \s_@@_stop
      #5 {#1} {#2} {#3} {#4}
    \@@_set_eq_conditional_loop:nnnnNw {#1} {#2} {#3} {#4} #5
  }
\cs_gset:Npn \@@_set_eq_conditional_p_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
  { #2 { #3 _p : #4    }    { #5 _p : #6    } }
\cs_gset:Npn \@@_set_eq_conditional_TF_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
  { #2 { #3    : #4 TF }    { #5    : #6 TF } }
\cs_gset:Npn \@@_set_eq_conditional_T_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
  { #2 { #3    : #4 T  }    { #5    : #6 T  } }
\cs_gset:Npn \@@_set_eq_conditional_F_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
  { #2 { #3    : #4  F }    { #5    : #6  F } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% All that is left is to define the canonical boolean true and false.
% I think Michael originated the idea of expandable boolean tests.  At
% first these were supposed to expand into either \texttt{TT} or
% \texttt{TF} to be tested using \cs{if:w} but this was later changed to
% |00| and |01|, so they could be used in logical
% operations. Later again they were changed to being numerical
% constants with values of $1$ for true and $0$ for false. We need
% this from the get-go.
%
% \begin{variable}{\c_true_bool, \c_false_bool}
%    Here are the canonical boolean values.
%    \begin{macrocode}
\tex_global:D \tex_chardef:D \c_true_bool  = 1 ~
\tex_global:D \tex_chardef:D \c_false_bool = 0 ~
%    \end{macrocode}
% \end{variable}
%
% \subsection{Dissecting a control sequence}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% \begin{function}[EXP]{\@@_count_signature:N}
%   \begin{syntax}
%     \cs{@@_count_signature:N} \meta{function}
%   \end{syntax}
%   Splits the \meta{function} into the \meta{name} (i.e., the part
%   before the colon) and the \meta{signature} (i.e., after the colon).
%   The \meta{number} of tokens in the \meta{signature} is then left in
%   the input stream. If there was no \meta{signature} then the result is
%   the marker value $-1$.
% \end{function}
%
% \begin{function}{\@@_tmp:w}
%   Function used for various short-term usages, for instance defining
%   functions whose definition involves tokens which are hard to insert
%   normally (spaces, characters with category other).
% \end{function}
%
% \begin{macro}[EXP]{\cs_to_str:N}
% \begin{macro}[EXP]{\@@_to_str:N, \@@_to_str:w}
%   This converts a control sequence into the character string of its
%   name, removing the leading escape character. This turns out to be
%   a non-trivial matter as there a different cases:
%   \begin{itemize}
%     \item The usual case of a printable escape character;
%     \item the case of a non-printable escape characters, e.g., when
%     the value of the \tn{escapechar} is negative;
%     \item when the escape character is a space.
%   \end{itemize}
%   One approach to solve this is to test how many tokens result from
%   |\token_to_str:N \a|. If there are two tokens, then the escape
%   character is printable, while if it is non-printable then only
%   one is present.
%
%   However, there is an additional complication: the control
%   sequence itself may start with a space. Clearly that should \emph{not} be
%   lost in the process of converting to a string. So the approach adopted is
%   a little more intricate still. When the escape character is printable,
%   \verb*|\token_to_str:N \ | yields the escape character itself and a space.
%   The character codes are different, thus the \cs{if:w} test is false,
%   and \TeX{} reads \cs{@@_to_str:N} after turning the following
%   control sequence into a string; this auxiliary removes the escape
%   character, and stops the expansion of the initial \cs{tex_romannumeral:D}.
%   The second case is that the escape character is not printable. Then
%   the \cs{if:w} test is unfinished after reading a the space from
%   \verb*|\token_to_str:N \ |, and the auxiliary \cs{@@_to_str:w}
%   is expanded, feeding |-| as a second character for the test;
%   the test is false, and \TeX{} skips to \cs{fi:}, then performs
%   \cs{token_to_str:N}, and stops the \cs{tex_romannumeral:D} with \cs{c_zero_int}.
%   The last case is that the escape character is itself a space. In this
%   case, the \cs{if:w} test is true, and the auxiliary \cs{@@_to_str:w}
%   comes into play, inserting |-\int_value:w|, which expands \cs{c_zero_int}
%   to the character |0|. The initial \cs{tex_romannumeral:D} then sees
%   |0|, which is not a terminated number, followed by the escape character,
%   a space, which is removed, terminating the expansion of
%   \cs{tex_romannumeral:D}.
%   In all three cases, \cs{cs_to_str:N} takes two expansion steps
%   to be fully expanded.
%    \begin{macrocode}
\cs_gset:Npn \cs_to_str:N
  {
%    \end{macrocode}
%    We implement the expansion scheme using \cs{tex_romannumeral:D}
%    terminating it with \cs{c_zero_int} rather than using \cs{exp:w} and
%    \cs{exp_end:} as we normally do. The reason is that the code
%    heavily depends on terminating the expansion with \cs{c_zero_int} so
%    we make this dependency explicit.
%    \begin{macrocode}
    \tex_romannumeral:D
      \if:w \token_to_str:N \ \@@_to_str:w \fi:
      \exp_after:wN \@@_to_str:N \token_to_str:N
  }
\cs_gset:Npn \@@_to_str:N #1 { \c_zero_int }
\cs_gset:Npn \@@_to_str:w #1 \@@_to_str:N
  { - \int_value:w \fi: \exp_after:wN \c_zero_int }
%    \end{macrocode}
%   If speed is a concern we could use \tn{csstring} in \LuaTeX{}.  For
%   the empty csname that primitive gives an empty result while the
%   current \cs{cs_to_str:N} gives incorrect results in all engines
%   (this is impossible to fix without huge performance hit).
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\cs_split_function:N}
% \begin{macro}[EXP]
%   {\@@_split_function_auxi:w, \@@_split_function_auxii:w}
%   This function takes a function name and splits it into name with
%   the escape char removed and argument specification. In addition to
%   this, a third argument, a boolean \meta{true} or \meta{false} is
%   returned with \meta{true} for when there is a colon in the function
%   and \meta{false} if there is not.
%
%   First ensure that we actually get a properly evaluated string by
%   expanding \cs{cs_to_str:N} twice.  If the function contained a
%   colon, the auxiliary takes as |#1| the function name, delimited by
%   the first colon, then the signature |#2|, delimited by \cs{s_@@_mark},
%   then \cs{c_true_bool} as |#3|, and |#4| cleans up until \cs{s_@@_stop}.
%   Otherwise, the |#1| contains the function name and \cs{s_@@_mark}
%   \cs{c_true_bool}, |#2| is empty, |#3| is \cs{c_false_bool}, and |#4|
%   cleans up.  The second
%   auxiliary trims the trailing \cs{s_@@_mark} from the function name if
%   present (that is, if the original function had no colon).
%    \begin{macrocode}
\cs_gset_protected:Npn \@@_tmp:w #1
  {
    \cs_gset:Npn \cs_split_function:N ##1
      {
        \exp_after:wN \exp_after:wN \exp_after:wN
        \@@_split_function_auxi:w
          \cs_to_str:N ##1 \s_@@_mark \c_true_bool
          #1 \s_@@_mark \c_false_bool \s_@@_stop
      }
    \cs_gset:Npn \@@_split_function_auxi:w
        ##1 #1 ##2 \s_@@_mark ##3##4 \s_@@_stop
      { \@@_split_function_auxii:w ##1 \s_@@_mark \s_@@_stop {##2} ##3 }
    \cs_gset:Npn \@@_split_function_auxii:w ##1 \s_@@_mark ##2 \s_@@_stop
      { {##1} }
  }
\exp_after:wN \@@_tmp:w \token_to_str:N :
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Exist or free}
%
% A control sequence is said to \emph{exist} (to be used) if it has an entry in
% the hash table and its meaning is different from the primitive
% \tn{relax} token. A control sequence is said to be \emph{free}
% (to be defined) if it does not already exist.
%
% \begin{macro}[pTF, EXP]{\cs_if_exist:N, \cs_if_exist:c}
% \begin{macro}{\@@_if_exist_c_aux:,\@@_if_exist_c_aux:w}
%   Two versions for checking existence. For the |N| form we firstly
%   check for \cs{scan_stop:} and then if it is in the hash
%   table. There is no problem when inputting something like \cs{else:}
%   or \cs{fi:} as \TeX{} will only ever skip input in case the token
%   tested against is \cs{scan_stop:}.
%
%   In both the |N| and |c| form we use the way \cs{prg_set_conditional:Npnn}
%   optimizes the conditionals to negate the tests using \cs{else:} (the
%   \cs{else:} in the top level functions will be removed by the optimization,
%   and this usage of \cs{else:} will be fine).
%    \begin{macrocode}
\prg_gset_conditional:Npnn \cs_if_exist:N #1 { p , T , F , TF }
  {
    \if_meaning:w #1 \scan_stop:
      \use_i:nnnn
    \else:
    \fi:
    \if_cs_exist:N #1
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
%    \end{macrocode}
%   For the |c| form we firstly check if it is in the hash table and
%   then for \cs{scan_stop:} so that we do not add it to the hash table
%   unless it was already there. Here we have to be careful as the text
%   to be skipped if the first test is false may contain tokens that
%   disturb the scanner. Therefore, we ensure that the second test is
%   performed after the first one has concluded completely.
%    \begin{macrocode}
\cs_if_exist:NTF \tex_lastnamedcs:D
  {
    \prg_gset_conditional:Npnn \cs_if_exist:c #1 { p , T , F , TF }
      {
        \if_cs_exist:w #1 \cs_end:
          \@@_if_exist_c_aux:
          \prg_return_true:
        \else:
          \prg_return_false:
        \fi:
      }
    \cs_gset:Npn \@@_if_exist_c_aux:
      { \fi: \exp_after:wN \if_meaning:w \tex_lastnamedcs:D \scan_stop: \else: }
  }
  {
    \prg_gset_conditional:Npnn \cs_if_exist:c #1 { p , T , F , TF }
      {
        \if_cs_exist:w #1 \cs_end:
          \@@_if_exist_c_aux:w
        \fi:
        \use_none:n {#1}
        \if_false:
          \prg_return_true:
        \else:
          \prg_return_false:
        \fi:
      }
    \cs_gset:Npn \@@_if_exist_c_aux:w \fi: \use_none:n #1 \if_false:
      { \fi: \exp_after:wN \if_meaning:w \cs:w #1 \cs_end: \scan_stop: \else: }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[pTF, EXP]{\cs_if_free:N, \cs_if_free:c}
%   The logical reversal of the above.
%    \begin{macrocode}
\prg_gset_conditional:Npnn \cs_if_free:N #1 { p , T , F , TF }
  {
    \if_cs_exist:N #1
    \else:
      \use_none:nnnn
    \fi:
    \if_meaning:w #1 \scan_stop:
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\cs_if_exist:NTF \tex_lastnamedcs:D
  {
    \prg_gset_conditional:Npnn \cs_if_free:c #1 { p , T , F , TF }
      {
        \if_cs_exist:w #1 \cs_end:
          \@@_if_free_c_aux:w
        \fi:
        \if_true:
          \prg_return_true:
        \else:
          \prg_return_false:
        \fi:
      }
    \cs_gset:Npn \@@_if_free_c_aux:w \fi: \if_true:
      { \fi: \exp_after:wN \if_meaning:w \tex_lastnamedcs:D \scan_stop: }
  }
  {
    \prg_gset_conditional:Npnn \cs_if_free:c #1 { p , T , F , TF }
      {
        \if_cs_exist:w #1 \cs_end:
          \@@_if_free_c_aux:w
        \fi:
        \use_none:n {#1}
        \if_true:
          \prg_return_true:
        \else:
          \prg_return_false:
        \fi:
      }
    \cs_gset:Npn \@@_if_free_c_aux:w \fi: \use_none:n #1 \if_true:
      { \fi: \exp_after:wN \if_meaning:w \cs:w #1 \cs_end: \scan_stop: }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP,noTF]
%   {\cs_if_exist_use:N, \cs_if_exist_use:c}
% \begin{macro}{\@@_if_exist_use_aux:w, \@@_if_exist_use_aux:Nnn}
%   The \cs[index=cs_if_exist_use:N]{cs_if_exist_use:\ldots{}}
%   functions cannot be implemented
%   as conditionals because the true branch must leave both the control
%   sequence itself and the true code in the input stream.
%   For the \texttt{c} variants, we are careful not to put the control
%   sequence in the hash table if it does not exist.
%   If available we use the \tn{lastnamedcs} primitive.
%    \begin{macrocode}
\cs_gset:Npn \cs_if_exist_use:NTF #1#2
  { \cs_if_exist:NTF #1 { #1 #2 } }
\cs_gset:Npn \cs_if_exist_use:NF #1
  { \cs_if_exist:NTF #1 #1 }
\cs_gset:Npn \cs_if_exist_use:NT #1 #2
  { \cs_if_exist:NT #1 { #1 #2 } }
\cs_gset:Npn \cs_if_exist_use:N #1
  { \cs_if_exist:NT #1 #1 }
\cs_if_exist:NTF \tex_lastnamedcs:D
  {
    \cs_gset:Npn \cs_if_exist_use:cTF #1
      {
        \if_cs_exist:w #1 \cs_end:
          \@@_if_exist_use_aux:w
        \fi:
        \use_ii:nn
      }
    \cs_gset:Npn \@@_if_exist_use_aux:w \fi: \use_ii:nn
      { \fi: \exp_after:wN \@@_if_exist_use_aux:Nnn \tex_lastnamedcs:D }
  }
  {
    \cs_gset:Npn \cs_if_exist_use:cTF #1
      {
        \if_cs_exist:w #1 \cs_end:
          \@@_if_exist_use_aux:w
        \fi:
        \use_iii:nnn {#1}
      }
    \cs_gset:Npn \@@_if_exist_use_aux:w \fi: \use_iii:nnn #1
      { \fi: \exp_after:wN \@@_if_exist_use_aux:Nnn \cs:w #1 \cs_end: }
  }
\cs_gset:Npn \@@_if_exist_use_aux:Nnn #1#2
  {
    \if_meaning:w #1 \scan_stop:
      \exp_after:wN \use_iii:nnn
    \fi:
    \use_i:nn { #1 #2 }
  }
\cs_gset:Npn \cs_if_exist_use:cF #1
  { \cs_if_exist_use:cTF {#1} {} }
\cs_gset:Npn \cs_if_exist_use:cT #1#2
  { \cs_if_exist_use:cTF {#1} {#2} {} }
\cs_gset:Npn \cs_if_exist_use:c #1
  { \cs_if_exist_use:cTF {#1} {} {} }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Preliminaries for new functions}
%
%    We provide two kinds of functions that can be used to define
%    control sequences. On the one hand we have functions that check
%    if their argument doesn't already exist, they are called
%    |\..._new|. The second type of defining functions doesn't check
%    if the argument is already defined.
%
%    Before we can define them, we need some auxiliary macros that allow
%    us to generate error messages. The next few definitions here are
%    only temporary, they will be redefined later on.
%
% \begin{macro}[documented-as = \msg_error:nnnn]
%   {\msg_error:nnee, \msg_error:nne, \msg_error:nn}
%   If an internal error occurs before \LaTeX3 has loaded \pkg{l3msg} then
%   the code should issue a usable if terse error message and halt. This
%   can only happen if a coding error is made by the team, so this is
%   a reasonable response.  Setting the \tn{newlinechar} is needed, to
%   turn |^^J| into a proper line break in plain \TeX{}.
%    \begin{macrocode}
\cs_gset_protected:Npn \msg_error:nnee #1#2#3#4
  {
    \tex_newlinechar:D = `\^^J \scan_stop:
    \tex_errmessage:D
      {
        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~! ^^J
        Argh,~internal~LaTeX3~error! ^^J ^^J
        Module ~ #1 , ~ message~name~"#2": ^^J
        Arguments~'#3'~and~'#4' ^^J ^^J
        This~is~one~for~The~LaTeX3~Project:~bailing~out
      }
    \tex_end:D
  }
\cs_gset_protected:Npn \msg_error:nne #1#2#3
  { \msg_error:nnee {#1} {#2} {#3} { } }
\cs_gset_protected:Npn \msg_error:nn #1#2
  { \msg_error:nnee {#1} {#2} { } { } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[rEXP]{\msg_line_context:}
%   Another one from \pkg{l3msg} which will be altered later.
%    \begin{macrocode}
\cs_gset:Npn \msg_line_context:
  { on~line~ \tex_the:D \tex_inputlineno:D }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__kernel_chk_if_free_cs:N, \__kernel_chk_if_free_cs:c}
%   This command is called by \cs{cs_new_nopar:Npn} and \cs{cs_new_eq:NN}
%   etc.\
%   to make sure that the argument sequence is not already in use. If
%   it is, an error is signaled.  It checks if \meta{csname} is
%   undefined or \cs{scan_stop:}. Otherwise an error message is
%   issued. We have to make sure we don't put the argument into the
%   conditional processing since it may be an |\if...| type function!
%    \begin{macrocode}
\cs_gset_protected:Npn \__kernel_chk_if_free_cs:N #1
  {
    \cs_if_free:NF #1
      {
        \msg_error:nnee { kernel } { command-already-defined }
          { \token_to_str:N #1 } { \token_to_meaning:N #1 }
      }
  }
\cs_gset_protected:Npn \__kernel_chk_if_free_cs:c
  { \exp_args:Nc \__kernel_chk_if_free_cs:N }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Defining new functions}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% \begin{macro}
%   {
%     \cs_new_nopar:Npn           , \cs_new_nopar:Npe           , \cs_new_nopar:Npx           ,
%     \cs_new:Npn                 , \cs_new:Npe                 , \cs_new:Npx                 ,
%     \cs_new_protected_nopar:Npn , \cs_new_protected_nopar:Npe , \cs_new_protected_nopar:Npx ,
%     \cs_new_protected:Npn       , \cs_new_protected:Npe       , \cs_new_protected:Npx
%   }
% \begin{macro}{\@@_tmp:w}
%   Function which check that the control sequence is free before
%   defining it.
%     \begin{macrocode}
\cs_set:Npn \@@_tmp:w #1#2
  {
    \cs_gset_protected:Npn #1 ##1
      {
        \__kernel_chk_if_free_cs:N ##1
        #2 ##1
      }
  }
\@@_tmp:w \cs_new_nopar:Npn           \cs_gset_nopar:Npn
\@@_tmp:w \cs_new_nopar:Npe           \cs_gset_nopar:Npe
\@@_tmp:w \cs_new_nopar:Npx           \cs_gset_nopar:Npx
\@@_tmp:w \cs_new:Npn                 \cs_gset:Npn
\@@_tmp:w \cs_new:Npe                 \cs_gset:Npe
\@@_tmp:w \cs_new:Npx                 \cs_gset:Npx
\@@_tmp:w \cs_new_protected_nopar:Npn \cs_gset_protected_nopar:Npn
\@@_tmp:w \cs_new_protected_nopar:Npe \cs_gset_protected_nopar:Npe
\@@_tmp:w \cs_new_protected_nopar:Npx \cs_gset_protected_nopar:Npx
\@@_tmp:w \cs_new_protected:Npn       \cs_gset_protected:Npn
\@@_tmp:w \cs_new_protected:Npe       \cs_gset_protected:Npe
\@@_tmp:w \cs_new_protected:Npx       \cs_gset_protected:Npx
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[documented-as=\cs_set_nopar:Npn]
%   {
%     \cs_set_nopar:cpn  , \cs_set_nopar:cpe  , \cs_set_nopar:cpx  ,
%     \cs_gset_nopar:cpn , \cs_gset_nopar:cpe , \cs_gset_nopar:cpx ,
%     \cs_new_nopar:cpn  , \cs_new_nopar:cpe  , \cs_new_nopar:cpx
%   }
%   Like \cs{cs_set_nopar:Npn} and \cs{cs_new_nopar:Npn}, except that the
%   first argument consists of the sequence of characters that should
%   be used to form the name of the desired control sequence (the |c|
%   stands for csname argument, see the expansion module). Global
%   versions are also provided.
%
%   \cs{cs_set_nopar:cpn}\meta{string}\meta{rep-text} turns \meta{string}
%   into a csname and then assigns \meta{rep-text} to it by using
%   \cs{cs_set_nopar:Npn}.  This means that there might be a parameter
%   string between the two arguments.
%    \begin{macrocode}
\cs_set:Npn \@@_tmp:w #1#2
  { \cs_new_protected_nopar:Npn #1 { \exp_args:Nc #2 } }
\@@_tmp:w \cs_set_nopar:cpn  \cs_set_nopar:Npn
\@@_tmp:w \cs_set_nopar:cpe  \cs_set_nopar:Npe
\@@_tmp:w \cs_set_nopar:cpx  \cs_set_nopar:Npx
\@@_tmp:w \cs_gset_nopar:cpn \cs_gset_nopar:Npn
\@@_tmp:w \cs_gset_nopar:cpe \cs_gset_nopar:Npe
\@@_tmp:w \cs_gset_nopar:cpx \cs_gset_nopar:Npx
\@@_tmp:w \cs_new_nopar:cpn  \cs_new_nopar:Npn
\@@_tmp:w \cs_new_nopar:cpe  \cs_new_nopar:Npe
\@@_tmp:w \cs_new_nopar:cpx  \cs_new_nopar:Npx
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[documented-as=\cs_set:Npn]
%   {
%     \cs_set:cpn  , \cs_set:cpe  , \cs_set:cpx  ,
%     \cs_gset:cpn , \cs_gset:cpe , \cs_gset:cpx ,
%     \cs_new:cpn  , \cs_new:cpe  , \cs_new:cpx
%   }
%   Variants of the \cs{cs_set:Npn} versions which make a csname out
%   of the first arguments. We may also do this globally.
%    \begin{macrocode}
\@@_tmp:w \cs_set:cpn  \cs_set:Npn
\@@_tmp:w \cs_set:cpe  \cs_set:Npe
\@@_tmp:w \cs_set:cpx  \cs_set:Npx
\@@_tmp:w \cs_gset:cpn \cs_gset:Npn
\@@_tmp:w \cs_gset:cpe \cs_gset:Npe
\@@_tmp:w \cs_gset:cpx \cs_gset:Npx
\@@_tmp:w \cs_new:cpn  \cs_new:Npn
\@@_tmp:w \cs_new:cpe  \cs_new:Npe
\@@_tmp:w \cs_new:cpx  \cs_new:Npx
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[documented-as=\cs_set_protected_nopar:Npn]
%   {
%     \cs_set_protected_nopar:cpn  , \cs_set_protected_nopar:cpe  , \cs_set_protected_nopar:cpx  ,
%     \cs_gset_protected_nopar:cpn , \cs_gset_protected_nopar:cpe , \cs_gset_protected_nopar:cpx ,
%     \cs_new_protected_nopar:cpn  , \cs_new_protected_nopar:cpe  , \cs_new_protected_nopar:cpx
%   }
%   Variants of the \cs{cs_set_protected_nopar:Npn} versions which make
%   a csname out of the first arguments. We may also do this globally.
%    \begin{macrocode}
\@@_tmp:w \cs_set_protected_nopar:cpn  \cs_set_protected_nopar:Npn
\@@_tmp:w \cs_set_protected_nopar:cpe  \cs_set_protected_nopar:Npe
\@@_tmp:w \cs_set_protected_nopar:cpx  \cs_set_protected_nopar:Npx
\@@_tmp:w \cs_gset_protected_nopar:cpn \cs_gset_protected_nopar:Npn
\@@_tmp:w \cs_gset_protected_nopar:cpe \cs_gset_protected_nopar:Npe
\@@_tmp:w \cs_gset_protected_nopar:cpx \cs_gset_protected_nopar:Npx
\@@_tmp:w \cs_new_protected_nopar:cpn  \cs_new_protected_nopar:Npn
\@@_tmp:w \cs_new_protected_nopar:cpe  \cs_new_protected_nopar:Npe
\@@_tmp:w \cs_new_protected_nopar:cpx  \cs_new_protected_nopar:Npx
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[documented-as=\cs_set_protected:Npn]
%   {
%     \cs_set_protected:cpn  , \cs_set_protected:cpe  , \cs_set_protected:cpx  ,
%     \cs_gset_protected:cpn , \cs_gset_protected:cpe , \cs_gset_protected:cpx ,
%     \cs_new_protected:cpn  , \cs_new_protected:cpe  , \cs_new_protected:cpx
%   }
%   Variants of the \cs{cs_set_protected:Npn} versions which make a csname
%   out of the first arguments. We may also do this globally.
%    \begin{macrocode}
\@@_tmp:w \cs_set_protected:cpn  \cs_set_protected:Npn
\@@_tmp:w \cs_set_protected:cpe  \cs_set_protected:Npe
\@@_tmp:w \cs_set_protected:cpx  \cs_set_protected:Npx
\@@_tmp:w \cs_gset_protected:cpn \cs_gset_protected:Npn
\@@_tmp:w \cs_gset_protected:cpe \cs_gset_protected:Npe
\@@_tmp:w \cs_gset_protected:cpx \cs_gset_protected:Npx
\@@_tmp:w \cs_new_protected:cpn  \cs_new_protected:Npn
\@@_tmp:w \cs_new_protected:cpe  \cs_new_protected:Npe
\@@_tmp:w \cs_new_protected:cpx  \cs_new_protected:Npx
%    \end{macrocode}
% \end{macro}
%
% \subsection{Copying definitions}
%
% \begin{macro}
%   {
%     \cs_set_eq:NN  , \cs_set_eq:cN  , \cs_set_eq:Nc  , \cs_set_eq:cc  ,
%     \cs_gset_eq:NN , \cs_gset_eq:cN , \cs_gset_eq:Nc , \cs_gset_eq:cc ,
%     \cs_new_eq:NN  , \cs_new_eq:cN  , \cs_new_eq:Nc  , \cs_new_eq:cc
%   }
%   These macros allow us to copy the definition of a control sequence
%   to another control sequence.
%
%   The |=| sign allows us to define funny char tokens like |=| itself
%   or \verb*| | with this function. For the definition of
%   |\c_space_char{~}| to work we need the |~| after the |=|.
%
%   \cs{cs_set_eq:NN} is long to avoid problems with a literal argument
%   of \cs{par}.  While \cs{cs_new_eq:NN} will probably never be correct
%   with a first argument of \cs{par}, define it long in order to throw
%   an \enquote{already defined} error rather than
%   \enquote{runaway argument}.
%    \begin{macrocode}
\cs_new_protected:Npn \cs_set_eq:NN #1 { \tex_let:D #1 =~ }
\cs_new_protected:Npn \cs_set_eq:cN { \exp_args:Nc  \cs_set_eq:NN }
\cs_new_protected:Npn \cs_set_eq:Nc { \exp_args:NNc \cs_set_eq:NN }
\cs_new_protected:Npn \cs_set_eq:cc { \exp_args:Ncc \cs_set_eq:NN }
\cs_new_protected:Npn \cs_gset_eq:NN { \tex_global:D  \cs_set_eq:NN }
\cs_new_protected:Npn \cs_gset_eq:Nc { \exp_args:NNc  \cs_gset_eq:NN }
\cs_new_protected:Npn \cs_gset_eq:cN { \exp_args:Nc   \cs_gset_eq:NN }
\cs_new_protected:Npn \cs_gset_eq:cc { \exp_args:Ncc  \cs_gset_eq:NN }
\cs_new_protected:Npn \cs_new_eq:NN #1
  {
    \__kernel_chk_if_free_cs:N #1
    \tex_global:D \cs_set_eq:NN #1
  }
\cs_new_protected:Npn \cs_new_eq:cN { \exp_args:Nc  \cs_new_eq:NN }
\cs_new_protected:Npn \cs_new_eq:Nc { \exp_args:NNc \cs_new_eq:NN }
\cs_new_protected:Npn \cs_new_eq:cc { \exp_args:Ncc \cs_new_eq:NN }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Undefining functions}
%
% \begin{macro}{\cs_undefine:N, \cs_undefine:c}
%   The following function is used to free the main memory from the
%   definition of some function that isn't in use any longer.
%   The \texttt{c} variant is careful not to add the control sequence
%   to the hash table if it isn't there yet, and it also avoids nesting
%   \TeX{} conditionals in case |#1| is unbalanced in this matter.
%   We optimize the case where the command exists by reducing as much as
%   possible the tokens in the conditional.
%    \begin{macrocode}
\cs_new_protected:Npn \cs_undefine:N #1
  { \cs_gset_eq:NN #1 \tex_undefined:D }
\cs_new_protected:Npn \cs_undefine:c #1
  {
    \if_cs_exist:w #1 \cs_end:
    \else:
      \use_i:nnnn
    \fi:
    \exp_args:Nc \cs_undefine:N {#1}
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Generating parameter text from argument count}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% \begin{macro}{\__kernel_cs_parm_from_arg_count:nnF}
% \begin{macro}{\@@_parm_from_arg_count_test:nnF}
%   \LaTeX3 provides shorthands to define control sequences and
%   conditionals with a simple parameter text, derived directly from the
%   signature, or more generally from knowing the number of arguments,
%   between~$0$ and~$9$.  This function expands to its first argument,
%   untouched, followed by a brace group containing the parameter text
%   |{#|$1$\ldots{}|#|$n$|}|, where $n$ is the result of evaluating the
%   second argument (as described in \cs{int_eval:n}).  If the second
%   argument gives a result outside the range $[0,9]$, the third
%   argument is returned instead, normally an error message.  Some of
%   the functions use here are not defined yet, but will be defined
%   before this function is called.
%    \begin{macrocode}
\cs_new_protected:Npn \__kernel_cs_parm_from_arg_count:nnF #1#2
  {
    \exp_args:Ne \@@_parm_from_arg_count_test:nnF
      {
        \exp_after:wN \exp_not:n
        \if_case:w \int_eval:n {#2}
             { }
        \or: { ##1 }
        \or: { ##1##2 }
        \or: { ##1##2##3 }
        \or: { ##1##2##3##4 }
        \or: { ##1##2##3##4##5 }
        \or: { ##1##2##3##4##5##6 }
        \or: { ##1##2##3##4##5##6##7 }
        \or: { ##1##2##3##4##5##6##7##8 }
        \or: { ##1##2##3##4##5##6##7##8##9 }
        \else: { \c_false_bool }
        \fi:
      }
      {#1}
  }
\cs_new_protected:Npn \@@_parm_from_arg_count_test:nnF #1#2
  {
    \if_meaning:w \c_false_bool #1
      \exp_after:wN \use_ii:nn
    \else:
      \exp_after:wN \use_i:nn
    \fi:
    { #2 {#1} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Defining functions from a given number of arguments}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\@@_count_signature:N, \@@_count_signature:c}
% \begin{macro}[EXP]{\@@_count_signature:n}
% \begin{macro}[EXP]{\@@_count_signature:nnN}
%   Counting the number of tokens in the signature, i.e., the
%   number of arguments the function should take.  Since this is not
%   used in any time-critical function, we simply use \cs{tl_count:n} if
%   there is a signature, otherwise $-1$ arguments to signal an error.
%   We need a variant form right away.
%    \begin{macrocode}
\cs_new:Npn \@@_count_signature:N #1
  { \exp_args:Nf \@@_count_signature:n { \cs_split_function:N #1 } }
\cs_new:Npn \@@_count_signature:n #1
  { \int_eval:n { \@@_count_signature:nnN #1 } }
\cs_new:Npn \@@_count_signature:nnN #1#2#3
  {
    \if_meaning:w \c_true_bool #3
      \tl_count:n {#2}
    \else:
      -1
    \fi:
  }
\cs_new:Npn \@@_count_signature:c
  { \exp_args:Nc \@@_count_signature:N }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \cs_generate_from_arg_count:NNnn,
%     \cs_generate_from_arg_count:cNnn,
%     \cs_generate_from_arg_count:Ncnn
%   }
%   We provide a constructor function for defining functions with a
%   given number of arguments.  For this we need to choose the correct
%   parameter text and then use that when defining.  Since \TeX{}
%   supports from zero to nine arguments, we use a simple switch to
%   choose the correct parameter text, ensuring the result is returned
%   after finishing the conditional.  If it is not between zero and
%   nine, we throw an error.
%
%   1: function to define, 2: with what to define it, 3: the number of
%   args it requires and 4: the replacement text
%    \begin{macrocode}
\cs_new_protected:Npn \cs_generate_from_arg_count:NNnn #1#2#3#4
  {
    \__kernel_cs_parm_from_arg_count:nnF { \use:nnn #2 #1 } {#3}
      {
        \msg_error:nnee { kernel } { bad-number-of-arguments }
          { \token_to_str:N #1 } { \int_eval:n {#3} }
        \use_none:n
      }
      {#4}
  }
%    \end{macrocode}
%   A variant form we need right away, plus one which is used elsewhere but
%   which is most logically created here.
%    \begin{macrocode}
\cs_new_protected:Npn \cs_generate_from_arg_count:cNnn
  { \exp_args:Nc \cs_generate_from_arg_count:NNnn }
\cs_new_protected:Npn \cs_generate_from_arg_count:Ncnn
  { \exp_args:NNc \cs_generate_from_arg_count:NNnn }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Using the signature to define functions}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% We can now combine some of the tools we have to provide a simple
% interface for defining functions, where the number of arguments is
% read from the signature.  For instance,
% |\cs_set:Nn \foo_bar:nn {#1,#2}|.
%
% \begin{macro}
%   {
%     \cs_set:Nn                  , \cs_set:Ne                  , \cs_set:Nx                  ,
%     \cs_set_nopar:Nn            , \cs_set_nopar:Ne            , \cs_set_nopar:Nx            ,
%     \cs_set_protected:Nn        , \cs_set_protected:Ne        , \cs_set_protected:Nx        ,
%     \cs_set_protected_nopar:Nn  , \cs_set_protected_nopar:Ne  , \cs_set_protected_nopar:Nx  ,
%     \cs_gset:Nn                 , \cs_gset:Ne                 , \cs_gset:Nx                 ,
%     \cs_gset_nopar:Nn           , \cs_gset_nopar:Ne           , \cs_gset_nopar:Nx           ,
%     \cs_gset_protected:Nn       , \cs_gset_protected:Ne       , \cs_gset_protected:Nx       ,
%     \cs_gset_protected_nopar:Nn , \cs_gset_protected_nopar:Ne , \cs_gset_protected_nopar:Nx ,
%     \cs_new:Nn                  , \cs_new:Ne                  , \cs_new:Nx                  ,
%     \cs_new_nopar:Nn            , \cs_new_nopar:Ne            , \cs_new_nopar:Nx            ,
%     \cs_new_protected:Nn        , \cs_new_protected:Ne        , \cs_new_protected:Nx        ,
%     \cs_new_protected_nopar:Nn  , \cs_new_protected_nopar:Ne  , \cs_new_protected_nopar:Nx  ,
%   }
%   We want to define \cs{cs_set:Nn} as
%   \begin{verbatim}
%     \cs_set_protected:Npn \cs_set:Nn #1#2
%       {
%         \cs_generate_from_arg_count:NNnn #1 \cs_set:Npn
%           { \@@_count_signature:N #1 } {#2}
%       }
%   \end{verbatim}
%   In short, to define \cs{cs_set:Nn} we need just use \cs{cs_set:Npn},
%   everything else is the same for each variant.  Therefore, we can
%   make it simpler by temporarily defining a function to do this for
%   us.
%    \begin{macrocode}
\cs_set:Npn \@@_tmp:w #1#2#3
  {
    \cs_new_protected:cpx { cs_ #1 : #2 }
      {
        \exp_not:N \@@_generate_from_signature:NNn
        \exp_after:wN \exp_not:N \cs:w cs_ #1 : #3 \cs_end:
      }
  }
\cs_new_protected:Npn \@@_generate_from_signature:NNn #1#2
  {
    \use:e
      {
        \@@_generate_from_signature:nnNNNn
        \cs_split_function:N #2
      }
      #1 #2
  }
\cs_new_protected:Npn \@@_generate_from_signature:nnNNNn #1#2#3#4#5#6
  {
    \bool_if:NTF #3
      {
        \cs_set_nopar:Npx \@@_tmp:w
          { \tl_map_function:nN {#2} \@@_generate_from_signature:n }
        \tl_if_empty:oF \@@_tmp:w
          {
            \msg_error:nneee { kernel } { non-base-function }
              { \token_to_str:N #5 } {#2} { \@@_tmp:w }
          }
        \cs_generate_from_arg_count:NNnn
          #5 #4 { \tl_count:n {#2} } {#6}
      }
      {
        \msg_error:nne { kernel } { missing-colon }
          { \token_to_str:N #5 }
      }
  }
\cs_new:Npn \@@_generate_from_signature:n #1
  {
    \if:w n #1 \else: \if:w N #1 \else:
    \if:w T #1 \else: \if:w F #1 \else: #1 \fi: \fi: \fi: \fi:
  }
%    \end{macrocode}
%   Then we define the 24 variants beginning with |N|.
%    \begin{macrocode}
\@@_tmp:w { set }                  { Nn } { Npn }
\@@_tmp:w { set }                  { Ne } { Npe }
\@@_tmp:w { set }                  { Nx } { Npx }
\@@_tmp:w { set_nopar }            { Nn } { Npn }
\@@_tmp:w { set_nopar }            { Ne } { Npe }
\@@_tmp:w { set_nopar }            { Nx } { Npx }
\@@_tmp:w { set_protected }        { Nn } { Npn }
\@@_tmp:w { set_protected }        { Ne } { Npe }
\@@_tmp:w { set_protected }        { Nx } { Npx }
\@@_tmp:w { set_protected_nopar }  { Nn } { Npn }
\@@_tmp:w { set_protected_nopar }  { Ne } { Npe }
\@@_tmp:w { set_protected_nopar }  { Nx } { Npx }
\@@_tmp:w { gset }                 { Nn } { Npn }
\@@_tmp:w { gset }                 { Ne } { Npe }
\@@_tmp:w { gset }                 { Nx } { Npx }
\@@_tmp:w { gset_nopar }           { Nn } { Npn }
\@@_tmp:w { gset_nopar }           { Ne } { Npe }
\@@_tmp:w { gset_nopar }           { Nx } { Npx }
\@@_tmp:w { gset_protected }       { Nn } { Npn }
\@@_tmp:w { gset_protected }       { Ne } { Npe }
\@@_tmp:w { gset_protected }       { Nx } { Npx }
\@@_tmp:w { gset_protected_nopar } { Nn } { Npn }
\@@_tmp:w { gset_protected_nopar } { Ne } { Npe }
\@@_tmp:w { gset_protected_nopar } { Nx } { Npx }
\@@_tmp:w { new }                  { Nn } { Npn }
\@@_tmp:w { new }                  { Ne } { Npe }
\@@_tmp:w { new }                  { Nx } { Npx }
\@@_tmp:w { new_nopar }            { Nn } { Npn }
\@@_tmp:w { new_nopar }            { Ne } { Npe }
\@@_tmp:w { new_nopar }            { Nx } { Npx }
\@@_tmp:w { new_protected }        { Nn } { Npn }
\@@_tmp:w { new_protected }        { Ne } { Npe }
\@@_tmp:w { new_protected }        { Nx } { Npx }
\@@_tmp:w { new_protected_nopar }  { Nn } { Npn }
\@@_tmp:w { new_protected_nopar }  { Ne } { Npe }
\@@_tmp:w { new_protected_nopar }  { Nx } { Npx }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[documented-as=\cs_set:Nn]
%   {
%     \cs_set:cn                  , \cs_set:ce                  , \cs_set:cx                  ,
%     \cs_set_nopar:cn            , \cs_set_nopar:ce            , \cs_set_nopar:cx            ,
%     \cs_set_protected:cn        , \cs_set_protected:ce        , \cs_set_protected:cx        ,
%     \cs_set_protected_nopar:cn  , \cs_set_protected_nopar:ce  , \cs_set_protected_nopar:cx  ,
%     \cs_gset:cn                 , \cs_gset:ce                 , \cs_gset:cx                 ,
%     \cs_gset_nopar:cn           , \cs_gset_nopar:ce           , \cs_gset_nopar:cx           ,
%     \cs_gset_protected:cn       , \cs_gset_protected:ce       , \cs_gset_protected:cx       ,
%     \cs_gset_protected_nopar:cn , \cs_gset_protected_nopar:ce , \cs_gset_protected_nopar:cx ,
%     \cs_new:cn                  , \cs_new:ce                  , \cs_new:cx                  ,
%     \cs_new_nopar:cn            , \cs_new_nopar:ce            , \cs_new_nopar:cx            ,
%     \cs_new_protected:cn        , \cs_new_protected:ce        , \cs_new_protected:cx        ,
%     \cs_new_protected_nopar:cn  , \cs_new_protected_nopar:ce  , \cs_new_protected_nopar:cx  ,
%   }
%   The 24 |c| variants simply use \cs{exp_args:Nc}.
%    \begin{macrocode}
\cs_set:Npn \@@_tmp:w #1#2
  {
    \cs_new_protected:cpx { cs_ #1 : c #2 }
      {
        \exp_not:N \exp_args:Nc
        \exp_after:wN \exp_not:N \cs:w cs_ #1 : N #2 \cs_end:
      }
  }
\@@_tmp:w { set }                  { n }
\@@_tmp:w { set }                  { e }
\@@_tmp:w { set }                  { x }
\@@_tmp:w { set_nopar }            { n }
\@@_tmp:w { set_nopar }            { e }
\@@_tmp:w { set_nopar }            { x }
\@@_tmp:w { set_protected }        { n }
\@@_tmp:w { set_protected }        { e }
\@@_tmp:w { set_protected }        { x }
\@@_tmp:w { set_protected_nopar }  { n }
\@@_tmp:w { set_protected_nopar }  { e }
\@@_tmp:w { set_protected_nopar }  { x }
\@@_tmp:w { gset }                 { n }
\@@_tmp:w { gset }                 { e }
\@@_tmp:w { gset }                 { x }
\@@_tmp:w { gset_nopar }           { n }
\@@_tmp:w { gset_nopar }           { e }
\@@_tmp:w { gset_nopar }           { x }
\@@_tmp:w { gset_protected }       { n }
\@@_tmp:w { gset_protected }       { e }
\@@_tmp:w { gset_protected }       { x }
\@@_tmp:w { gset_protected_nopar } { n }
\@@_tmp:w { gset_protected_nopar } { e }
\@@_tmp:w { gset_protected_nopar } { x }
\@@_tmp:w { new }                  { n }
\@@_tmp:w { new }                  { e }
\@@_tmp:w { new }                  { x }
\@@_tmp:w { new_nopar }            { n }
\@@_tmp:w { new_nopar }            { e }
\@@_tmp:w { new_nopar }            { x }
\@@_tmp:w { new_protected }        { n }
\@@_tmp:w { new_protected }        { e }
\@@_tmp:w { new_protected }        { x }
\@@_tmp:w { new_protected_nopar }  { n }
\@@_tmp:w { new_protected_nopar }  { e }
\@@_tmp:w { new_protected_nopar }  { x }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Checking control sequence equality}
%
% \begin{macro}[pTF, EXP]
%   {\cs_if_eq:NN, \cs_if_eq:cN, \cs_if_eq:Nc, \cs_if_eq:cc}
%   Check if two control sequences are identical.
%    \begin{macrocode}
\prg_new_conditional:Npnn \cs_if_eq:NN #1#2 { p , T , F , TF }
  {
    \if_meaning:w #1#2
      \prg_return_true: \else: \prg_return_false: \fi:
  }
\cs_new:Npn \cs_if_eq_p:cN { \exp_args:Nc  \cs_if_eq_p:NN }
\cs_new:Npn \cs_if_eq:cNTF { \exp_args:Nc  \cs_if_eq:NNTF }
\cs_new:Npn \cs_if_eq:cNT  { \exp_args:Nc  \cs_if_eq:NNT }
\cs_new:Npn \cs_if_eq:cNF  { \exp_args:Nc  \cs_if_eq:NNF }
\cs_new:Npn \cs_if_eq_p:Nc { \exp_args:NNc \cs_if_eq_p:NN }
\cs_new:Npn \cs_if_eq:NcTF { \exp_args:NNc \cs_if_eq:NNTF }
\cs_new:Npn \cs_if_eq:NcT  { \exp_args:NNc \cs_if_eq:NNT }
\cs_new:Npn \cs_if_eq:NcF  { \exp_args:NNc \cs_if_eq:NNF }
\cs_new:Npn \cs_if_eq_p:cc { \exp_args:Ncc \cs_if_eq_p:NN }
\cs_new:Npn \cs_if_eq:ccTF { \exp_args:Ncc \cs_if_eq:NNTF }
\cs_new:Npn \cs_if_eq:ccT  { \exp_args:Ncc \cs_if_eq:NNT }
\cs_new:Npn \cs_if_eq:ccF  { \exp_args:Ncc \cs_if_eq:NNF }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Diagnostic functions}
%
%    \begin{macrocode}
%<@@=kernel>
%    \end{macrocode}
%
% \begin{macro}{\@@_chk_defined:NT}
%   Error if the variable |#1| is not defined.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_chk_defined:NT #1#2
  {
    \cs_if_exist:NTF #1
      {#2}
      {
        \msg_error:nne { kernel } { variable-not-defined }
          { \token_to_str:N #1 }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {\@@_register_show:N, \@@_register_show:c, \@@_register_log:N, \@@_register_log:c}
% \begin{macro}{\@@_register_show_aux:NN, \@@_register_show_aux:nNN}
%   Simply using the \tn{showthe} primitive does not allow for
%   line-wrapping, so instead use \cs{tl_show:n} and \cs{tl_log:n} (defined
%   in \pkg{l3tl} and that performs line-wrapping).  This displays
%   |>~|\meta{variable}|=|\meta{value}.  We expand the value before-hand
%   as otherwise some integers (such as \tn{currentgrouplevel} or
%   \tn{currentgrouptype}) altered by the line-wrapping code would show
%   wrong values.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_register_show:N
  { \@@_register_show_aux:NN \tl_show:n }
\cs_new_protected:Npn \@@_register_show:c
  { \exp_args:Nc \@@_register_show:N }
\cs_new_protected:Npn \@@_register_log:N
  { \@@_register_show_aux:NN \tl_log:n }
\cs_new_protected:Npn \@@_register_log:c
  { \exp_args:Nc \@@_register_log:N }
\cs_new_protected:Npn \@@_register_show_aux:NN #1#2
  {
    \@@_chk_defined:NT #2
      {
        \exp_args:No \@@_register_show_aux:nNN
          { \tex_the:D #2 } #2 #1
      }
  }
\cs_new_protected:Npn \@@_register_show_aux:nNN #1#2#3
  { \exp_args:No #3 { \token_to_str:N #2 = #1 } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\cs_show:N, \cs_show:c, \cs_log:N, \cs_log:c, \@@_show:NN}
%   Some control sequences have a very long name or meaning.  Thus,
%   simply using \TeX{}'s primitive \tn{show} could lead to overlong
%   lines.  The output of this primitive is mimicked to some extent,
%   then the re-built string is given to \cs{tl_show:n} or \cs{tl_log:n} for
%   line-wrapping.  We must expand the meaning before passing it to the
%   wrapping code as otherwise we would wrongly see the definitions that
%   are in place there.  To get correct escape characters, set the
%   \tn{escapechar} in a group; this also localizes the assignment
%   performed by \texttt{e}-expansion.  The \cs{cs_show:c} and \cs{cs_log:c} commands
%   convert their argument to a control sequence within a group to avoid
%   showing \tn{relax} for undefined control sequences.
%    \begin{macrocode}
\cs_new_protected:Npn \cs_show:N { \@@_show:NN \tl_show:n }
\cs_new_protected:Npn \cs_show:c
  { \group_begin: \exp_args:NNc \group_end: \cs_show:N }
\cs_new_protected:Npn \cs_log:N { \@@_show:NN \tl_log:n }
\cs_new_protected:Npn \cs_log:c
  { \group_begin: \exp_args:NNc \group_end: \cs_log:N }
\cs_new_protected:Npn \@@_show:NN #1#2
  {
    \group_begin:
      \int_set:Nn \tex_escapechar:D { `\\ }
      \exp_args:NNe
    \group_end:
    #1 { \token_to_str:N #2 = \cs_meaning:N #2 }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\group_show_list:, \group_log_list:, \@@_group_show:NN}
%   Wrapper around \tn{showgroups}.  Getting \TeX{} to write to the log
%   without interruption the run is done by altering the interaction
%   mode.
%    \begin{macrocode}
\cs_new_protected:Npn \group_show_list:
  { \@@_group_show:NN \use_none:n 1 }
\cs_new_protected:Npn \group_log_list:
  { \@@_group_show:NN \int_gzero:N 0 }
\cs_new_protected:Npn \@@_group_show:NN #1#2
  {
    \use:e
      {
        #1 \tex_interactionmode:D
        \int_set:Nn \tex_tracingonline:D  {#2}
        \int_set:Nn \tex_errorcontextlines:D { -1 }
        \exp_not:N \exp_after:wN \scan_stop:
        \tex_showgroups:D
        \int_gset:Nn \tex_interactionmode:D
          { \int_use:N \tex_interactionmode:D }
        \int_set:Nn \tex_tracingonline:D
          { \int_use:N \tex_tracingonline:D }
        \int_set:Nn \tex_errorcontextlines:D
          { \int_use:N \tex_errorcontextlines:D }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Decomposing a macro definition}
%
%    \begin{macrocode}
%<@@=cs>
%    \end{macrocode}
%
% \begin{macro}{\cs_prefix_spec:N}
% \begin{macro}{\cs_parameter_spec:N}
% \begin{macro}{\cs_replacement_spec:N}
% \begin{macro}{\@@_prefix_arg_replacement:wN}
% \begin{macro}{\@@_macro_prefix_spec:N}
% \begin{macro}{\@@_macro_parameter_spec:N}
% \begin{macro}{\@@_macro_replacement_spec:N}
%   We sometimes want to test if a control sequence can be expanded to
%   reveal a hidden value. However, we cannot just expand the macro
%   blindly as it may have arguments and none might be
%   present. Therefore we define these functions to pick either the
%   prefix(es), the parameter specification, or the replacement text from
%   a macro. All of this information is returned as characters with
%   catcode~$12$. If the token in question isn't a macro, the token
%   \cs{scan_stop:} is returned instead.
%
%   Since LuaMeta\TeX{}'s version of \tn{meaning} doesn't give the same
%   output as the classical one, we are implementing the core of these
%   macros in Lua instead.
%    \begin{macrocode}
\use:e
  {
    \exp_not:n { \cs_new:Npn \@@_prefix_arg_replacement:wN #1 }
    \tl_to_str:n { macro : } \exp_not:n { #2 -> #3 \s_@@_stop #4 }
  }
  { #4 {#1} {#2} {#3} }

\cs_if_exist:NTF \@@_macro_prefix_spec:N
  {
    \cs_new:Npn \cs_prefix_spec:N #1
      {
        \token_if_macro:NTF #1
          { \@@_macro_prefix_spec:N #1 }
          { \scan_stop: }
      }
  }
  {
    \cs_new:Npn \cs_prefix_spec:N #1
      {
        \token_if_macro:NTF #1
          {
            \exp_after:wN \@@_prefix_arg_replacement:wN
              \token_to_meaning:N #1 \s_@@_stop \use_i:nnn
          }
          { \scan_stop: }
      }
  }
  \cs_if_exist:NTF \@@_macro_parameter_spec:N
  {
    \cs_new:Npn \cs_parameter_spec:N #1
      {
        \token_if_macro:NTF #1
        { \@@_macro_parameter_spec:N #1 }
          { \scan_stop: }
      }
  }
  {
    \cs_new:Npn \cs_parameter_spec:N #1
      {
        \token_if_macro:NTF #1
          {
            \exp_after:wN \@@_prefix_arg_replacement:wN
              \token_to_meaning:N #1 \s_@@_stop \use_ii:nnn
          }
          { \scan_stop: }
      }
  }
\cs_if_exist:NTF \@@_macro_replacement_spec:N
  {
    \cs_new:Npn \cs_replacement_spec:N #1
      {
        \token_if_macro:NTF #1
          { \@@_macro_replacement_spec:N #1 }
          { \scan_stop: }
      }
  }
  {
    \cs_new:Npn \cs_replacement_spec:N #1
      {
        \token_if_macro:NTF #1
          {
            \exp_after:wN \@@_prefix_arg_replacement:wN
              \token_to_meaning:N #1 \s_@@_stop \use_iii:nnn
          }
          { \scan_stop: }
      }
  }
%</code>
%    \end{macrocode}
%   This is a modified version of code suggested by Max Chernoff
%   (\url{https://chat.stackexchange.com/transcript/message/67947633#67947633}).
%   We aim to provide the classical \TeX{}82 appearance but covering \eTeX{}:
%   due to changes in the engine, the only useful prefix here is |\protected|
%   at present. (This may need to be revisited once the engine is more stable.)
%   This does not cover tokens other than control sequences, so we only use
%   it for the internal needed here.
%    \begin{macrocode}
%<*lua>
if status.luatex_engine == 'luametatex' then
  local function scan_full_csname()
    local t = get_next()
    local csname = get_csname(t)
    return t.active and active_prefix .. csname or csname, t
  end
  luacmd('@@_macro_prefix_spec:N', function()
    local token = get_next()
    if get_protected(token) then
      sprint(-2, "\\protected ")
    end
  end, 'global')
  luacmd('@@_macro_parameter_spec:N', function()
    local csname, token = scan_full_csname(true)
    if token.parameters == 0 then return end
    sprint(-2, get_macro(csname, false, true))
  end, 'global')
  luacmd('@@_macro_replacement_spec:N', function()
    local csname = scan_full_csname(true)
    sprint(-2, get_macro(csname, false, false))
  end, 'global')
end
%</lua>
%<*code>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Doing nothing functions}
%
% \begin{macro}[EXP]{\prg_do_nothing:}
%   This does not fit anywhere else!
%    \begin{macrocode}
\cs_new:Npn \prg_do_nothing: { }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Breaking out of mapping functions}
%
%    \begin{macrocode}
%<@@=prg>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\prg_break_point:Nn, \prg_map_break:Nn}
%   In inline mappings, the nesting level must be reset
%   at the end of the mapping, even when the user decides
%   to break out. This is done by putting the code that
%   must be performed as an argument of \cs{@@_break_point:Nn}.
%   The breaking functions are then defined to jump to
%   that point and perform the argument of \cs{@@_break_point:Nn},
%   before the user's code (if any).  There is a check that we close the
%   correct loop, otherwise we continue breaking.
%    \begin{macrocode}
\cs_new_eq:NN \prg_break_point:Nn \use_ii:nn
\cs_new:Npn \prg_map_break:Nn #1#2#3 \prg_break_point:Nn #4#5
  {
    #5
    \if_meaning:w #1 #4
      \exp_after:wN \use_iii:nnn
    \fi:
    \prg_map_break:Nn #1 {#2}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prg_break_point:}
% \begin{macro}{\prg_break:, \prg_break:n}
%   Very simple analogues of \cs{prg_break_point:Nn} and
%   \cs{prg_map_break:Nn}, for use in fast short-term recursions which
%   are not mappings, do not need to support nesting, and in which
%   nothing has to be done at the end of the loop.
%    \begin{macrocode}
\cs_new_eq:NN \prg_break_point: \prg_do_nothing:
\cs_new:Npn \prg_break: #1 \prg_break_point: { }
\cs_new:Npn \prg_break:n #1#2 \prg_break_point: {#1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Starting a paragraph}
%
% \begin{macro}{\mode_leave_vertical:}
%   The approach here is different to that used by \LaTeXe{} or plain \TeX{},
%   which unbox a void box to force horizontal mode. That inserts the
%   \tn{everypar} tokens \emph{before} the re-inserted unboxing tokens. The
%   approach here uses a protected macro, equivalent to the \tn{quitvmode}
%   primitive. In vertical mode, the \tn{indent} primitive is inserted:
%   this will switch to horizontal mode and insert \tn{everypar} tokens and
%   nothing else. Unlike the \LaTeXe{} version, the availability of \eTeX{}
%   means using a mode test can be done at for example the start of an
%   \tn{halign}.
%    \begin{macrocode}
\cs_new_protected:Npn \mode_leave_vertical:
  {
    \if_mode_vertical:
      \exp_after:wN \tex_indent:D
    \fi:
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</code>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
