% \iffalse meta-comment
%
%% File: l3prg.dtx Copyright (C) 2005-2014 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the "l3kernel bundle" (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX3 Project.
%%
%% -----------------------------------------------------------------------
%
%<*driver>
\documentclass[full]{l3doc}
%</driver>
%<*driver|package>
\GetIdInfo$Id: l3prg.dtx 5354 2014-08-23 01:35:39Z bruno $
  {L3 Control structures}
%</driver|package>
%<*driver>
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3prg} package\\ Control structures^^A
%   \thanks{This file describes v\ExplFileVersion,
%      last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  The \LaTeX3 Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% Conditional processing in \LaTeX3 is defined as something that
% performs a series of tests, possibly involving assignments and
% calling other functions that do not read further ahead in the input
% stream. After processing the input, a \emph{state} is returned. The
% typical states returned are \meta{true} and \meta{false} but other
% states are possible, say an \meta{error} state for erroneous
% input, \emph{e.g.}, text as input in a function comparing integers.
%
% \LaTeX3 has two forms of conditional flow processing based
% on these states. The firs form is predicate functions that turn the
% returned state into a boolean \meta{true} or \meta{false}. For
% example, the function \cs{cs_if_free_p:N} checks whether the control
% sequence given as its argument is free and then returns the boolean
% \meta{true} or \meta{false} values to be used in testing with
% \cs{if_predicate:w} or in functions to be described below.  The second form
% is the kind of functions choosing a particular argument from the
% input stream based on the result of the testing as in
% \cs{cs_if_free:NTF} which also takes one argument (the |N|) and then
% executes either \texttt{true} or \texttt{false} depending on the
% result. Important to note here is that the arguments are executed
% after exiting the underlying |\if...\fi:| structure.
%
% \section{Defining a set of conditional functions}
% \label{sec:l3prg:new-conditional-functions}
%
% \begin{function}[updated = 2012-02-06]
%   {
%     \prg_new_conditional:Npnn, \prg_set_conditional:Npnn,
%     \prg_new_conditional:Nnn,  \prg_set_conditional:Nnn
%    }
%   \begin{syntax}
%     \cs{prg_new_conditional:Npnn} \cs{\meta{name}:\meta{arg spec}} \meta{parameters} \Arg{conditions} \Arg{code} \\
%     \cs{prg_new_conditional:Nnn} \cs{\meta{name}:\meta{arg spec}} \Arg{conditions} \Arg{code}
%   \end{syntax}
%   These functions create a family of conditionals using the same
%   \Arg{code} to perform the test created. Those conditionals are
%   expandable if \meta{code} is. The \texttt{new} versions will check
%   for existing definitions and perform assignments globally
%   (\emph{cf.}~\cs{cs_new:Npn}) whereas the \texttt{set} versions do no
%   check and perform assignments locally (\emph{cf.}~\cs{cs_set:Npn}).
%   The conditionals created are dependent on the comma-separated list
%   of \meta{conditions}, which should be one or more of \texttt{p},
%   \texttt{T}, \texttt{F} and \texttt{TF}.
% \end{function}
%
% \begin{function}[updated = 2012-02-06]
%   {
%     \prg_new_protected_conditional:Npnn, \prg_set_protected_conditional:Npnn,
%     \prg_new_protected_conditional:Nnn,  \prg_set_protected_conditional:Nnn
%   }
%   \begin{syntax}
%     \cs{prg_new_protected_conditional:Npnn} \cs{\meta{name}:\meta{arg spec}} \meta{parameters} \Arg{conditions} \Arg{code} \\
%     \cs{prg_new_protected_conditional:Nnn} \cs{\meta{name}:\meta{arg spec}} \Arg{conditions} \Arg{code}
%   \end{syntax}
%   These functions create a family of protected conditionals using the
%   same \Arg{code} to perform the test created. The \meta{code} does
%   not need to be expandable.  The \texttt{new} version will check for
%   existing definitions and perform assignments globally
%   (\emph{cf.}~\cs{cs_new:Npn}) whereas the \texttt{set} version will
%   not (\emph{cf.}~\cs{cs_set:Npn}). The conditionals created are
%   depended on the comma-separated list of \meta{conditions}, which
%   should be one or more of \texttt{T}, \texttt{F} and \texttt{TF} (not
%   \texttt{p}).
% \end{function}
%
% The conditionals are defined by \cs{prg_new_conditional:Npnn} and
% friends as:
% \begin{itemize}
%   \item \cs{\meta{name}_p:\meta{arg spec}} --- a predicate function
%     which will supply either a logical \texttt{true} or logical
%     \texttt{false}. This function is intended for use in cases where
%     one or more logical tests are combined to lead to a final outcome.
%     This function will not work properly for \texttt{protected}
%     conditionals.
%   \item \cs{\meta{name}:\meta{arg spec}T} --- a function with one more
%     argument than the original \meta{arg spec} demands. The \meta{true
%       branch} code in this additional argument will be left on the
%     input stream only if the test is \texttt{true}.
%   \item \cs{\meta{name}:\meta{arg spec}F} --- a function with one more
%     argument than the original \meta{arg spec} demands. The
%     \meta{false branch} code in this additional argument will be left
%     on the input stream only if the test is \texttt{false}.
%   \item \cs{\meta{name}:\meta{arg spec}TF} --- a function with two
%     more argument than the original \meta{arg spec} demands. The
%     \meta{true branch} code in the first additional argument will be
%     left on the input stream if the test is \texttt{true}, while the
%     \meta{false branch} code in the second argument will be left on
%     the input stream if the test is \texttt{false}.
% \end{itemize}
% The \meta{code} of the test may use \meta{parameters} as specified by
% the second argument to \cs{prg_set_conditional:Npnn}: this should
% match the \meta{argument specification} but this is not enforced.  The
% |Nnn| versions infer the number of arguments from the argument
% specification given (\emph{cf.}~\cs{cs_new:Nn}, \emph{etc.}).  Within
% the \meta{code}, the functions \cs{prg_return_true:} and
% \cs{prg_return_false:} are used to indicate the logical outcomes of
% the test.
%
% An example can easily clarify matters here:
% \begin{verbatim}
%   \prg_set_conditional:Npnn \foo_if_bar:NN #1#2 { p , T , TF }
%     {
%       \if_meaning:w \l_tmpa_tl #1
%         \prg_return_true:
%       \else:
%         \if_meaning:w \l_tmpa_tl #2
%           \prg_return_true:
%         \else:
%           \prg_return_false:
%         \fi:
%       \fi:
%     }
% \end{verbatim}
% This defines the function |\foo_if_bar_p:NN|, |\foo_if_bar:NNTF| and
% |\foo_if_bar:NNT| but not |\foo_if_bar:NNF| (because |F| is missing
% from the \meta{conditions} list). The return statements take care of
% resolving the remaining \cs{else:} and \cs{fi:} before returning the
% state. There must be a return statement for each branch; failing to do
% so will result in erroneous output if that branch is executed.
%
% \begin{function}{\prg_new_eq_conditional:NNn, \prg_set_eq_conditional:NNn}
%   \begin{syntax}
%     \cs{prg_new_eq_conditional:NNn} \cs{\meta{name_1}:\meta{arg spec_1}} \cs{\meta{name_2}:\meta{arg spec_2}} \Arg{conditions}
%   \end{syntax}
%   These functions copies a family of conditionals. The \texttt{new} version
%   will check for existing definitions (\emph{cf.}~\cs{cs_new:Npn}) whereas
%   the \texttt{set} version will not (\emph{cf.}~\cs{cs_set:Npn}). The
%   conditionals copied are depended on the comma-separated list of
%   \meta{conditions}, which should be one or more of \texttt{p}, \texttt{T},
%   \texttt{F} and \texttt{TF}.
% \end{function}
%
% \begin{function}[EXP]{\prg_return_true:, \prg_return_false:}
%   \begin{syntax}
%     \cs{prg_return_true:}
%     \cs{prg_return_false:}
%   \end{syntax}
%   These `return' functions define the logical state of a conditional statement.
%   They appear within the code for a conditional
%   function generated by \cs{prg_set_conditional:Npnn}, \emph{etc}, to indicate
%   when a true or false branch has been taken.
%   While they may appear multiple times each within the code of such conditionals,
%   the execution of the conditional must result in the expansion of one of these
%   two functions \emph{exactly once}.
%
%   The return functions trigger what is internally an f-expansion process to complete
%   the evaluation of the conditional. Therefore, after \cs{prg_return_true:} or \cs{prg_return_false:}
%   there must be no non-expandable material in the input stream for the remainder of
%   the expansion of the conditional code. This includes other instances of either of these functions.
% \end{function}
%
% \section{The boolean data type}
%
% This section describes a boolean data type which is closely
% connected to conditional processing as sometimes you want to
% execute some code depending on the value of a switch
% (\emph{e.g.},~draft/final) and other times you perhaps want to use it as a
% predicate function in an \cs{if_predicate:w} test. The problem of the
% primitive \cs{if_false:} and \cs{if_true:} tokens is that it is not
% always safe to pass them around as they may interfere with scanning
% for termination of primitive conditional processing. Therefore, we
% employ two canonical booleans: \cs{c_true_bool} or
% \cs{c_false_bool}. Besides preventing problems as described above, it
% also allows us to implement a simple boolean parser supporting the
% logical operations And, Or, Not, \emph{etc.}\ which can then be used on
% both the boolean type and predicate functions.
%
% All conditional |\bool_| functions except assignments are expandable
% and expect the input to also be fully expandable (which will generally
% mean being constructed from predicate functions, possibly nested).
%
% \begin{function}{\bool_new:N, \bool_new:c}
%   \begin{syntax}
%     \cs{bool_new:N} \meta{boolean}
%   \end{syntax}
%   Creates a new \meta{boolean} or raises an error if the
%   name is already taken. The declaration is global. The
%   \meta{boolean} will initially be \texttt{false}.
% \end{function}
%
% \begin{function}
%   {
%     \bool_set_false:N , \bool_set_false:c ,
%     \bool_gset_false:N, \bool_gset_false:c
%   }
%   \begin{syntax}
%     \cs{bool_set_false:N} \meta{boolean}
%   \end{syntax}
%   Sets \meta{boolean} logically \texttt{false}.
% \end{function}
%
% \begin{function}
%   {
%     \bool_set_true:N , \bool_set_true:c ,
%     \bool_gset_true:N , \bool_gset_true:c
%   }
%   \begin{syntax}
%     \cs{bool_set_true:N} \meta{boolean}
%   \end{syntax}
%   Sets \meta{boolean} logically \texttt{true}.
% \end{function}
%
% \begin{function}
%   {
%     \bool_set_eq:NN , \bool_set_eq:cN , \bool_set_eq:Nc , \bool_set_eq:cc ,
%     \bool_gset_eq:NN, \bool_gset_eq:cN, \bool_gset_eq:Nc, \bool_gset_eq:cc
%   }
%   \begin{syntax}
%     \cs{bool_set_eq:NN} \meta{boolean_1} \meta{boolean_2}
%   \end{syntax}
%   Sets the content of \meta{boolean_1} equal to that of \meta{boolean_2}.
% \end{function}
%
% \begin{function}[updated = 2012-07-08]
%   {\bool_set:Nn, \bool_set:cn, \bool_gset:Nn, \bool_gset:cn}
%   \begin{syntax}
%     \cs{bool_set:Nn} \meta{boolean} \Arg{boolexpr}
%   \end{syntax}
%   Evaluates the \meta{boolean expression} as described for
%   \cs{bool_if:n(TF)}, and sets the \meta{boolean} variable to
%   the logical truth of this evaluation.
% \end{function}
%
% \begin{function}[EXP,pTF]{\bool_if:N, \bool_if:c}
%   \begin{syntax}
%     \cs{bool_if_p:N} \meta{boolean}
%     \cs{bool_if:NTF} \meta{boolean} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests the current truth of \meta{boolean}, and continues expansion
%   based on this result.
% \end{function}
%
% \begin{function}[added = 2012-02-09]{\bool_show:N, \bool_show:c}
%   \begin{syntax}
%     \cs{bool_show:N} \meta{boolean}
%   \end{syntax}
%   Displays the logical truth of the \meta{boolean} on the terminal.
% \end{function}
%
% \begin{function}[added = 2012-02-09, updated = 2012-07-08]{\bool_show:n}
%   \begin{syntax}
%     \cs{bool_show:n} \Arg{boolean expression}
%   \end{syntax}
%   Displays the logical truth of the \meta{boolean expression} on the
%   terminal.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
%   {\bool_if_exist:N, \bool_if_exist:c}
%   \begin{syntax}
%     \cs{bool_if_exist_p:N} \meta{boolean}
%     \cs{bool_if_exist:NTF} \meta{boolean} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests whether the \meta{boolean} is currently defined.  This does not
%   check that the \meta{boolean} really is a boolean variable.
% \end{function}
%
% \begin{variable}{\l_tmpa_bool, \l_tmpb_bool}
%   A scratch boolean for local assignment. It is never used by
%   the kernel code, and so is safe for use with any \LaTeX3-defined
%   function. However, it may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \begin{variable}{\g_tmpa_bool, \g_tmpb_bool}
%   A scratch boolean for global assignment. It is never used by
%   the kernel code, and so is safe for use with any \LaTeX3-defined
%   function. However, it may be overwritten by other non-kernel
%   code and so should only be used for short-term storage.
% \end{variable}
%
% \section{Boolean expressions}
%
% As we have a boolean datatype and predicate functions returning
% boolean \meta{true} or \meta{false} values, it seems only fitting
% that we also provide a parser for \meta{boolean expressions}.
%
% A boolean expression is an expression which given input in the form
% of predicate functions and boolean variables, return boolean
% \meta{true} or \meta{false}. It supports the logical operations And,
% Or and Not as the well-known infix operators |&&|, \verb"||" and |!|
% with their usual precedences. In
% addition to this, parentheses can be used to isolate
% sub-expressions. For example,
% \begin{verbatim}
%     \int_compare_p:n { 1 = 1 } &&
%       (
%         \int_compare_p:n { 2 = 3 } ||
%         \int_compare_p:n { 4 = 4 } ||
%         \int_compare_p:n { 1 = \error } % is skipped
%       ) &&
%     ! ( \int_compare_p:n { 2 = 4 } )
% \end{verbatim}
% is a valid boolean expression. Note that minimal evaluation is
% carried out whenever possible so that whenever a truth value cannot
% be changed any more, the remaining tests within the current group
% are skipped.
%
% \begin{function}[EXP, pTF, updated = 2012-07-08]{\bool_if:n}
%   \begin{syntax}
%     \cs{bool_if_p:n} \Arg{boolean expression}
%     \cs{bool_if:nTF} \Arg{boolean expression} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests the current truth of \meta{boolean expression}, and
%   continues expansion based on this result. The
%   \meta{boolean expression} should consist of a series of predicates
%   or boolean variables with the logical relationship between these
%   defined using |&&| (\enquote{And}), \verb"||" (\enquote{Or}),
%   |!| (\enquote{Not}) and parentheses. Minimal evaluation is used
%   in the processing, so that once a result is defined there is
%   not further expansion of the tests. For example
%   \begin{verbatim}
%     \bool_if_p:n
%       {
%        \int_compare_p:nNn { 1 } = { 1 }
%        &&
%        (
%          \int_compare_p:nNn { 2 } = { 3 } ||
%          \int_compare_p:nNn { 4 } = { 4 } ||
%          \int_compare_p:nNn { 1 } = { \error } % is skipped
%        )
%        &&
%        ! \int_compare_p:nNn { 2 } = { 4 }
%     }
%   \end{verbatim}
%   will be \texttt{true} and will not evaluate
%   |\int_compare_p:nNn { 1 } = { \error }|. The logical Not applies to
%   the next predicate or group.
% \end{function}
%
% \begin{function}[EXP, updated = 2012-07-08]{\bool_not_p:n}
%   \begin{syntax}
%      \cs{bool_not_p:n} \Arg{boolean expression}
%   \end{syntax}
%   Function version of |!(|\meta{boolean expression}|)| within a boolean
%   expression.
% \end{function}
%
% \begin{function}[EXP, updated = 2012-07-08]{\bool_xor_p:nn}
%   \begin{syntax}
%     \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
%   \end{syntax}
%   Implements an \enquote{exclusive or} operation between two boolean
%   expressions. There is no infix operation for this logical
%   operator.
% \end{function}
%
% \section{Logical loops}
%
% Loops using either boolean expressions or stored boolean values.
%
% \begin{function}[rEXP]{\bool_do_until:Nn, \bool_do_until:cn}
%   \begin{syntax}
%     \cs{bool_do_until:Nn} \meta{boolean} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process,
%   and then checks the logical value of the \meta{boolean}.  If it is
%   \texttt{false} then the \meta{code} will be inserted into the input
%   stream again and the process will loop until the \meta{boolean} is
%   \texttt{true}.
% \end{function}
%
% \begin{function}[rEXP]{\bool_do_while:Nn, \bool_do_while:cn}
%   \begin{syntax}
%     \cs{bool_do_while:Nn} \meta{boolean} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process,
%   and then checks the logical value of the \meta{boolean}.  If it is
%   \texttt{true} then the \meta{code} will be inserted into the input
%   stream again and the process will loop until the \meta{boolean} is
%   \texttt{false}.
% \end{function}
%
% \begin{function}[rEXP]{\bool_until_do:Nn, \bool_until_do:cn}
%   \begin{syntax}
%     \cs{bool_until_do:Nn} \meta{boolean} \Arg{code}
%   \end{syntax}
%   This function firsts checks the logical value of the \meta{boolean}.
%   If it is \texttt{false} the \meta{code} is placed in the input stream
%   and expanded. After the completion of the \meta{code} the truth
%   of the \meta{boolean} is re-evaluated. The process will then loop
%   until the \meta{boolean} is \texttt{true}.
% \end{function}
%
% \begin{function}[rEXP]{\bool_while_do:Nn, \bool_while_do:cn}
%   \begin{syntax}
%     \cs{bool_while_do:Nn} \meta{boolean} \Arg{code}
%   \end{syntax}
%   This function firsts checks the logical value of the \meta{boolean}.
%   If it is \texttt{true} the \meta{code} is placed in the input stream
%   and expanded. After the completion of the \meta{code} the truth
%   of the \meta{boolean} is re-evaluated. The process will then loop
%   until the \meta{boolean} is \texttt{false}.
% \end{function}
%
% \begin{function}[rEXP, updated = 2012-07-08]{\bool_do_until:nn}
%   \begin{syntax}
%     \cs{bool_do_until:nn} \Arg{boolean expression} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process,
%   and then checks the logical value of the \meta{boolean expression}
%   as described for \cs{bool_if:nTF}.  If it is \texttt{false} then the
%   \meta{code} will be inserted into the input stream again and the
%   process will loop until the \meta{boolean expression} evaluates to
%   \texttt{true}.
% \end{function}
%
% \begin{function}[rEXP, updated = 2012-07-08]{\bool_do_while:nn}
%   \begin{syntax}
%     \cs{bool_do_while:nn} \Arg{boolean expression} \Arg{code}
%   \end{syntax}
%   Places the \meta{code} in the input stream for \TeX{} to process,
%   and then checks the logical value of the \meta{boolean expression}
%   as described for \cs{bool_if:nTF}.  If it is \texttt{true} then the
%   \meta{code} will be inserted into the input stream again and the
%   process will loop until the \meta{boolean expression} evaluates to
%   \texttt{false}.
% \end{function}
%
% \begin{function}[rEXP, updated = 2012-07-08]{\bool_until_do:nn}
%   \begin{syntax}
%     \cs{bool_until_do:nn} \Arg{boolean expression} \Arg{code}
%   \end{syntax}
%   This function firsts checks the logical value of the
%   \meta{boolean expression} (as described for \cs{bool_if:nTF}).
%   If it is \texttt{false} the \meta{code} is placed in the input stream
%   and expanded. After the completion of the \meta{code} the truth
%   of the \meta{boolean expression} is re-evaluated. The process will
%   then loop until the \meta{boolean expression} is \texttt{true}.
% \end{function}
%
% \begin{function}[rEXP, updated = 2012-07-08]{\bool_while_do:nn}
%   \begin{syntax}
%     \cs{bool_while_do:nn} \Arg{boolean expression} \Arg{code}
%   \end{syntax}
%   This function firsts checks the logical value of the
%   \meta{boolean expression} (as described for \cs{bool_if:nTF}).
%   If it is \texttt{true} the \meta{code} is placed in the input stream
%   and expanded. After the completion of the \meta{code} the truth
%   of the \meta{boolean expression} is re-evaluated. The process will
%   then loop until the \meta{boolean expression} is \texttt{false}.
% \end{function}
%
% \section{Producing multiple copies}
%
% \begin{function}[updated = 2011-07-04, EXP]{\prg_replicate:nn}
%   \begin{syntax}
%     \cs{prg_replicate:nn} \Arg{integer expression} \Arg{tokens}
%   \end{syntax}
%   Evaluates the \meta{integer expression} (which should be
%   zero or positive) and creates the resulting number of copies
%   of the \meta{tokens}. The function is both expandable and safe for
%   nesting. It yields its result after two expansion steps.
% \end{function}
%
% \section{Detecting \TeX{}'s mode}
%
% \begin{function}[EXP,pTF]{\mode_if_horizontal:}
%   \begin{syntax}
%     \cs{mode_if_horizontal_p:}
%     \cs{mode_if_horizontal:TF} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Detects if \TeX{} is currently in horizontal mode.
% \end{function}
%
% \begin{function}[EXP,pTF]{\mode_if_inner:}
%   \begin{syntax}
%     \cs{mode_if_inner_p:}
%     \cs{mode_if_inner:TF} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Detects if \TeX{} is currently in inner mode.
% \end{function}
%
% \begin{function}[updated = 2011-09-05, EXP,pTF]{\mode_if_math:}
%   \begin{syntax}
%     \cs{mode_if_math:TF} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Detects if \TeX{} is currently in maths mode.
% \end{function}
%
% \begin{function}[EXP,pTF]{\mode_if_vertical:}
%   \begin{syntax}
%     \cs{mode_if_vertical_p:}
%     \cs{mode_if_vertical:TF} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Detects if \TeX{} is currently in vertical mode.
% \end{function}
%
% \section{Primitive conditionals}
%
% \begin{function}[EXP]{\if_predicate:w}
%   \begin{syntax}
%     "\if_predicate:w" <predicate> <true code> "\else:" <false code> "\fi:"
%   \end{syntax}
%   This function takes a predicate function and
%   branches according to the result.  (In practice this function would also
%   accept a single boolean variable in place of the <predicate> but to make the
%   coding clearer this should be done through "\if_bool:N".)
% \end{function}
%
% \begin{function}[EXP]{\if_bool:N}
%   \begin{syntax}
%     "\if_bool:N" <boolean> <true code> "\else:" <false code> "\fi:"
%   \end{syntax}
%   This function takes a boolean variable and
%   branches according to the result.
% \end{function}
%
% \section{Internal programming functions}
%
% \begin{function}[updated = 2011-08-11, EXP]
%   {\group_align_safe_begin:, \group_align_safe_end:}
%   \begin{syntax}
%     \cs{group_align_safe_begin:}
%     \ldots
%     \cs{group_align_safe_end:}
%   \end{syntax}
%   These functions are used to enclose material in a \TeX{} alignment
%   environment within a specially-constructed group. This group is
%   designed in such a way that it does not add brace groups to the
%   output but does act as a group for the |&| token inside
%   \tn{halign}. This is necessary to allow grabbing of tokens
%   for testing purposes, as \TeX{} uses group level to determine the
%   effect of alignment tokens. Without the special grouping, the use of
%   a function such as \cs{peek_after:Nw} will result in a forbidden
%   comparison of the internal \tn{endtemplate} token, yielding a
%    fatal error. Each \cs{group_align_safe_begin:} must be matched by a
%   \cs{group_align_safe_end:}, although this does not have to occur
%   within the same function.
% \end{function}
%
% \begin{function}[updated = 2011-09-06]{\scan_align_safe_stop:}
%   \begin{syntax}
%     \cs{scan_align_safe_stop:}
%   \end{syntax}
%   Stops \TeX{}'s scanner looking for expandable control sequences at
%   the beginning of an alignment cell. This function is required, for
%   example, to obtain the expected output when testing \cs{mode_if_math:TF}
%   at the start of a math array cell: placing
%   \cs{scan_align_safe_stop:} before \cs{mode_if_math:TF} will give the
%   correct result. This function does not destroy any kerning if used in
%   other locations, but \emph{does} render functions non-expandable.
%   \begin{texnote}
%     This is a protected version of \cs{prg_do_nothing:}, which therefore
%     stops \TeX{}'s scanner in the circumstances described without producing
%     any affect on the output.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\__prg_variable_get_scope:N}
%   \begin{syntax}
%     \cs{__prg_variable_get_scope:N} \meta{variable}
%   \end{syntax}
%   Returns the scope (\texttt{g} for global, blank otherwise) for the
%   \meta{variable}.
% \end{function}
%
% \begin{function}[EXP]{\__prg_variable_get_type:N}
%   \begin{syntax}
%     \cs{__prg_variable_get_type:N} \meta{variable}
%   \end{syntax}
%   Returns the type of \meta{variable} (\texttt{tl}, \texttt{int},
%   \emph{etc.})
% \end{function}
%
% \begin{function}[EXP]{\__prg_break_point:Nn}
%   \begin{syntax}
%     \cs{__prg_break_point:Nn} \cs{\meta{type}_map_break:} \meta{tokens}
%   \end{syntax}
%   Used to mark the end of a recursion or mapping: the functions
%   \cs{\meta{type}_map_break:} and \cs{\meta{type}_map_break:n} use
%   this to break out of the loop. After the loop ends, the
%   \meta{tokens} are inserted into the input stream. This occurs even
%   if the break functions are \emph{not} applied:
%   \cs{__prg_break_point:Nn} is functionally-equivalent in these cases
%   to \cs{use_ii:nn}.
% \end{function}
%
% \begin{function}[EXP]{\__prg_map_break:Nn}
%   \begin{syntax}
%     \cs{__prg_map_break:Nn} \cs{\meta{type}_map_break:} \Arg{user code}
%     \ldots{}
%     \cs{__prg_break_point:Nn} \cs{\meta{type}_map_break:} \Arg{ending code}
%   \end{syntax}
%   Breaks a recursion in mapping contexts, inserting in the input
%   stream the \meta{user code} after the \meta{ending code} for the
%   loop.  The function breaks loops, inserting their \meta{ending
%     code}, until reaching a loop with the same \meta{type} as its
%   first argument.  This \cs{\meta{type}_map_break:} argument is simply
%   used as a recognizable marker for the \meta{type}.
% \end{function}
%
% \begin{variable}{\g__prg_map_int}
%   This integer is used by non-expandable mapping functions to track
%   the level of nesting in force.  The functions \cs{__prg_map_1:w},
%   \cs{__prg_map_2:w}, \emph{etc.}, labelled by \cs{g__prg_map_int}
%   hold functions to be mapped over various list datatypes in inline
%   and variable mappings.
% \end{variable}
%
% \begin{function}[EXP]{\__prg_break_point:}
%   This copy of \cs{prg_do_nothing:} is used to mark the end of a fast
%   short-term recursions: the function \cs{__prg_break:n} uses this to
%   break out of the loop.
% \end{function}
%
% \begin{function}[EXP]{\__prg_break:, \__prg_break:n}
%   \begin{syntax}
%     \cs{__prg_break:n} \Arg{tokens} \ldots{} \cs{__prg_break_point:}
%   \end{syntax}
%   Breaks a recursion which has no \meta{ending code} and which is not
%   a user-breakable mapping (see for instance \cs{prop_get:Nn}), and
%   inserts \meta{tokens} in the input stream.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3prg} implementation}
%
% \TestFiles{m3prg001.lvt,m3prg002.lvt,m3prg003.lvt}
%%
%    \begin{macrocode}
%<*initex|package>
%    \end{macrocode}
%
% \subsection{Primitive conditionals}
%
% \begin{macro}{\if_bool:N}
% \begin{macro}{\if_predicate:w}
%   Those two primitive \TeX{} conditionals are synonyms.
%   They should not be used outside the kernel code.
%    \begin{macrocode}
\tex_let:D \if_bool:N          \tex_ifodd:D
\tex_let:D \if_predicate:w     \tex_ifodd:D
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Defining a set of conditional functions}
%
% \begin{macro}
%   {
%     \prg_set_conditional:Npnn,
%     \prg_new_conditional:Npnn,
%     \prg_set_protected_conditional:Npnn,
%     \prg_new_protected_conditional:Npnn
%   }
% \begin{macro}
%   {
%     \prg_set_conditional:Nnn,
%     \prg_new_conditional:Nnn,
%     \prg_set_protected_conditional:Nnn,
%     \prg_new_protected_conditional:Nnn
%   }
% \begin{macro}{\prg_set_eq_conditional:NNn, \prg_new_eq_conditional:NNn}
% \begin{macro}{\prg_return_true:}
% \TestMissing
%   {This function is implicitly tested with all other conditionals!}
% \begin{macro}{\prg_return_false:}
% \TestMissing
%   {This function is also implicitly tested with all other conditionals!}
%   These are all defined in \pkg{l3basics}, as they are needed
%   \enquote{early}. This is just a reminder!
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{The boolean data type}
%
%    \begin{macrocode}
%<@@=bool>
%    \end{macrocode}
%
% \begin{macro}{\bool_new:N, \bool_new:c}
% \UnitTested
%   Boolean variables have to be initiated when they are created. Other
%   than that there is not much to say here.
%    \begin{macrocode}
\cs_new_protected:Npn \bool_new:N #1 { \cs_new_eq:NN #1 \c_false_bool }
\cs_generate_variant:Nn \bool_new:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \bool_set_true:N,   \bool_set_true:c,
%     \bool_gset_true:N,  \bool_gset_true:c,
%     \bool_set_false:N,  \bool_set_false:c,
%     \bool_gset_false:N, \bool_gset_false:c
%   }
% \UnitTested
%   Setting is already pretty easy.
%    \begin{macrocode}
\cs_new_protected:Npn \bool_set_true:N #1
  { \cs_set_eq:NN #1 \c_true_bool }
\cs_new_protected:Npn \bool_set_false:N #1
  { \cs_set_eq:NN #1 \c_false_bool }
\cs_new_protected:Npn \bool_gset_true:N #1
  { \cs_gset_eq:NN #1 \c_true_bool }
\cs_new_protected:Npn \bool_gset_false:N #1
  { \cs_gset_eq:NN #1 \c_false_bool }
\cs_generate_variant:Nn \bool_set_true:N   { c }
\cs_generate_variant:Nn \bool_set_false:N  { c }
\cs_generate_variant:Nn \bool_gset_true:N  { c }
\cs_generate_variant:Nn \bool_gset_false:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \bool_set_eq:NN,  \bool_set_eq:cN,
%     \bool_set_eq:Nc,  \bool_set_eq:cc,
%     \bool_gset_eq:NN, \bool_gset_eq:cN,
%     \bool_gset_eq:Nc, \bool_gset_eq:cc
%   }
% \UnitTested
%   The usual copy code.
%    \begin{macrocode}
\cs_new_eq:NN \bool_set_eq:NN  \cs_set_eq:NN
\cs_new_eq:NN \bool_set_eq:Nc  \cs_set_eq:Nc
\cs_new_eq:NN \bool_set_eq:cN  \cs_set_eq:cN
\cs_new_eq:NN \bool_set_eq:cc  \cs_set_eq:cc
\cs_new_eq:NN \bool_gset_eq:NN \cs_gset_eq:NN
\cs_new_eq:NN \bool_gset_eq:Nc \cs_gset_eq:Nc
\cs_new_eq:NN \bool_gset_eq:cN \cs_gset_eq:cN
\cs_new_eq:NN \bool_gset_eq:cc \cs_gset_eq:cc
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\bool_set:Nn,\bool_set:cn}
% \begin{macro}{\bool_gset:Nn,\bool_gset:cn}
%   This function evaluates a boolean expression and assigns the first
%   argument the meaning \cs{c_true_bool} or \cs{c_false_bool}.
%    \begin{macrocode}
\cs_new_protected:Npn \bool_set:Nn #1#2
  { \tex_chardef:D #1 = \bool_if_p:n {#2} }
\cs_new_protected:Npn \bool_gset:Nn #1#2
  { \tex_global:D \tex_chardef:D #1 = \bool_if_p:n {#2} }
\cs_generate_variant:Nn \bool_set:Nn  { c }
\cs_generate_variant:Nn \bool_gset:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%  Booleans are not based on token lists but do need checking: this
%  code complements similar material in \pkg{l3tl}.
%    \begin{macrocode}
%<*package>
\tex_ifodd:D \l@expl@check@declarations@bool
  \cs_set_protected:Npn \bool_set_true:N #1
    {
      \__chk_if_exist_var:N #1
      \cs_set_eq:NN #1 \c_true_bool
    }
  \cs_set_protected:Npn \bool_set_false:N #1
    {
      \__chk_if_exist_var:N #1
      \cs_set_eq:NN #1 \c_false_bool
    }
  \cs_set_protected:Npn \bool_gset_true:N #1
    {
      \__chk_if_exist_var:N #1
      \cs_gset_eq:NN #1 \c_true_bool
    }
  \cs_set_protected:Npn \bool_gset_false:N #1
    {
      \__chk_if_exist_var:N #1
      \cs_gset_eq:NN #1 \c_false_bool
    }
  \cs_set_protected:Npn \bool_set_eq:NN  #1
    {
      \__chk_if_exist_var:N #1
      \cs_set_eq:NN #1
    }
  \cs_set_protected:Npn \bool_gset_eq:NN  #1
    {
      \__chk_if_exist_var:N #1
      \cs_gset_eq:NN #1
    }
  \cs_set_protected:Npn \bool_set:Nn #1#2
    {
      \__chk_if_exist_var:N #1
      \tex_chardef:D #1 = \bool_if_p:n {#2}
    }
  \cs_set_protected:Npn \bool_gset:Nn #1#2
    {
      \__chk_if_exist_var:N #1
      \tex_global:D \tex_chardef:D #1 = \bool_if_p:n {#2}
    }
\tex_fi:D
%</package>
%    \end{macrocode}
%
% \begin{macro}[pTF]{\bool_if:N, \bool_if:c}
% \UnitTested
%  Straight forward here. We could optimize here if we wanted to as
%  the boolean can just be input directly.
%    \begin{macrocode}
\prg_new_conditional:Npnn \bool_if:N #1 { p , T , F , TF }
  {
    \if_meaning:w \c_true_bool #1
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\cs_generate_variant:Nn \bool_if_p:N { c }
\cs_generate_variant:Nn \bool_if:NT  { c }
\cs_generate_variant:Nn \bool_if:NF  { c }
\cs_generate_variant:Nn \bool_if:NTF { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\bool_show:N, \bool_show:c, \bool_show:n}
%   Show the truth value of the boolean, as \texttt{true} or
%   \texttt{false}. We use \cs{__msg_show_variable:n} to get a better
%   output; this function requires its argument to start with |>~|.
%    \begin{macrocode}
\cs_new_protected:Npn \bool_show:N #1
  {
    \bool_if_exist:NTF #1
      { \bool_show:n {#1} }
      {
        \__msg_kernel_error:nnx { kernel } { variable-not-defined }
          { \token_to_str:N #1 }
      }
  }
\cs_new_protected:Npn \bool_show:n #1
  {
    \bool_if:nTF {#1}
      { \__msg_show_variable:n { > ~ true } }
      { \__msg_show_variable:n { > ~ false } }
  }
\cs_generate_variant:Nn \bool_show:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_tmpa_bool, \l_tmpb_bool, \g_tmpa_bool, \g_tmpb_bool}
%    A few booleans just if you need them.
%    \begin{macrocode}
\bool_new:N \l_tmpa_bool
\bool_new:N \l_tmpb_bool
\bool_new:N \g_tmpa_bool
\bool_new:N \g_tmpb_bool
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}[pTF]{\bool_if_exist:N, \bool_if_exist:c}
%   Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \bool_if_exist:N \cs_if_exist:N
  { TF , T , F , p }
\prg_new_eq_conditional:NNn \bool_if_exist:c \cs_if_exist:c
  { TF , T , F , p }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Boolean expressions}
%
% \begin{macro}[pTF]{\bool_if:n}
% \UnitTested
%   Evaluating the truth value of a list of predicates is done using an
%   input syntax somewhat similar to the one found in other programming
%   languages with |(| and |)| for grouping, |!| for logical
%   \enquote{Not}, |&&| for logical \enquote{And} and \verb"||" for
%   logical \enquote{Or}.  We shall use the terms Not, And, Or, Open and
%   Close for these operations.
%
%   Any expression is terminated by a Close operation. Evaluation
%   happens from left to right in the following manner using a GetNext
%   function:
%   \begin{itemize}
%     \item If an Open is seen, start evaluating a new expression using
%       the Eval function and call GetNext again.
%     \item If a Not is seen, remove the |!| and call a GetNotNext
%       function, which eventually reverses the logic compared to
%       GetNext.
%     \item If none of the above, reinsert the token found (this is
%       supposed to be a predicate function) in front of an Eval
%       function, which evaluates it to the boolean value \meta{true} or
%       \meta{false}.
%   \end{itemize}
%   The Eval function then contains a post-processing operation which
%   grabs the instruction following the predicate.  This is either And,
%   Or or Close.  In each case the truth value is used to determine
%   where to go next.  The following situations can arise:
%   \begin{description}
%     \item[\meta{true}And] Current truth value is true, logical And
%       seen, continue with GetNext to examine truth value of next
%       boolean (sub-)expression.
%     \item[\meta{false}And] Current truth value is false, logical And
%       seen, stop evaluating the predicates within this sub-expression
%       and break to the nearest Close. Then return \meta{false}.
%     \item[\meta{true}Or] Current truth value is true, logical Or
%       seen, stop evaluating the predicates within this sub-expression
%       and break to the nearest Close. Then return \meta{true}.
%     \item[\meta{false}Or] Current truth value is false, logical Or
%       seen, continue with GetNext to examine truth value of next
%       boolean (sub-)expression.
%     \item[\meta{true}Close] Current truth value is true, Close
%       seen, return \meta{true}.
%     \item[\meta{false}Close] Current truth value is false, Close
%       seen, return \meta{false}.
%   \end{description}
%   We introduce an additional Stop operation with the same
%   semantics as the Close operation.
%   \begin{description}
%     \item[\meta{true}Stop] Current truth value is true, return
%       \meta{true}.
%     \item[\meta{false}Stop] Current truth value is false, return
%       \meta{false}.
%   \end{description}
%   The reasons for this follow below.
%    \begin{macrocode}
\prg_new_conditional:Npnn \bool_if:n #1 { T , F , TF }
  {
    \if_predicate:w \bool_if_p:n {#1}
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\bool_if_p:n}
% \begin{macro}[EXP, aux]
%   {
%     \@@_if_left_parentheses:wwwn ,
%     \@@_if_right_parentheses:wwwn ,
%     \@@_if_or:wwwn
%   }
%   First issue a \cs{group_align_safe_begin:} as we are using |&&|
%   as syntax shorthand for the And operation and we need to hide it for
%   \TeX{}.  This will be closed at the end of the expression parsing
%   (see |S| below).
%
%   Minimal (\enquote{short-circuit}) evaluation of boolean expressions
%   requires skipping to the end of the current parenthesized group when
%   \meta{true}\verb"||" is seen, but to the next \verb"||" or closing
%   parenthesis when \meta{false}|&&| is seen.  To avoid having separate
%   functions for the two cases, we transform the boolean expression by
%   doubling each parenthesis and adding parenthesis around each
%   \verb"||".  This ensures that |&&| will bind tighter than \verb"||".
%
%   The replacement is done in three passes, for left and right
%   parentheses and for \verb"||".  At each pass, the part of the
%   expression that has been transformed is stored before \cs{q_nil},
%   the rest lies until the first \cs{q_mark}, followed by an empty
%   brace group.  A trailing marker ensures that the auxiliaries'
%   delimited arguments will not run-away.  As long as the delimiter
%   matches inside the expression, material is moved before \cs{q_nil}
%   and we continue.  Afterwards, the trailing marker is taken as a
%   delimiter, |#4| is the next auxiliary, immediately followed by a new
%   \cs{q_nil} delimiter, which indicates that nothing has been treated
%   at this pass.  The last step calls \cs{@@_if_parse:NNNww} which
%   cleans up and triggers the evaluation of the expression itself.
%    \begin{macrocode}
\cs_new:Npn \bool_if_p:n #1
  {
    \group_align_safe_begin:
    \@@_if_left_parentheses:wwwn \q_nil
      #1 \q_mark { }
      (  \q_mark { \@@_if_right_parentheses:wwwn \q_nil }
      )  \q_mark { \@@_if_or:wwwn \q_nil }
      || \q_mark \@@_if_parse:NNNww
    \q_stop
  }
\cs_new:Npn \@@_if_left_parentheses:wwwn #1 \q_nil #2 ( #3 \q_mark #4
  { #4 \@@_if_left_parentheses:wwwn #1 #2 (( \q_nil #3 \q_mark {#4} }
\cs_new:Npn \@@_if_right_parentheses:wwwn #1 \q_nil #2 ) #3 \q_mark #4
  { #4 \@@_if_right_parentheses:wwwn #1 #2 )) \q_nil #3 \q_mark {#4} }
\cs_new:Npn \@@_if_or:wwwn #1 \q_nil #2 || #3 \q_mark #4
  { #4 \@@_if_or:wwwn #1 #2 )||( \q_nil #3 \q_mark {#4} }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP, aux]{\@@_if_parse:NNNww}
%   After removing extra tokens from the transformation phase, start
%   evaluating.  At the end, we will need to finish the special
%   \texttt{align_safe} group before finally
%   returning a \cs{c_true_bool} or \cs{c_false_bool} as there might
%   otherwise be something left in front in the input stream. For this
%   we call the Stop operation, denoted simply by a |S| following the
%   last Close operation.
%    \begin{macrocode}
\cs_new:Npn \@@_if_parse:NNNww #1#2#3#4 \q_mark #5 \q_stop
  {
    \__bool_get_next:NN \use_i:nn (( #4 )) S
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_get_next:NN}
%   The GetNext operation.  This is a switch: if what follows is neither
%   |!| nor |(|, we assume it is a predicate.  The first argument is
%   \cs{use_ii:nn} if the logic must eventually be reversed (after a
%   |!|), otherwise it is \cs{use_i:nn}.  This function eventually
%   expand to the truth value \cs{c_true_bool} or \cs{c_false_bool} of
%   the expression which follows until the next unmatched closing
%   parenthesis.
%    \begin{macrocode}
\cs_new:Npn \@@_get_next:NN #1#2
  {
    \use:c
      {
        @@_
        \if_meaning:w !#2 ! \else: \if_meaning:w (#2 ( \else: p \fi: \fi:
        :Nw
      }
      #1 #2
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_!:Nw}
%   The Not operation reverses the logic: discard the |!| token and call
%   the GetNext operation with its first argument reversed.
%    \begin{macrocode}
\cs_new:cpn { @@_!:Nw } #1#2
  { \exp_after:wN \@@_get_next:NN #1 \use_ii:nn \use_i:nn }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_(:Nw}
%   The Open operation starts a sub-expression after discarding the
%   token.  This is done by calling GetNext, with a post-processing step
%   which looks for And, Or or Close afterwards.
%    \begin{macrocode}
\cs_new:cpn { @@_(:Nw } #1#2
  {
    \exp_after:wN \@@_choose:NNN \exp_after:wN #1
    \__int_value:w \@@_get_next:NN \use_i:nn
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_p:Nw}
%   If what follows GetNext is neither |!| nor |(|, evaluate the
%   predicate using the primitive \cs{__int_value:w}.  The canonical
%   true and false values have numerical values $1$ and $0$
%   respectively.  Look for And, Or or Close afterwards.
%    \begin{macrocode}
\cs_new:cpn { @@_p:Nw } #1
  { \exp_after:wN \@@_choose:NNN \exp_after:wN #1 \__int_value:w }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_choose:NNN}
%   Branching the eight-way switch.  The arguments are 1: \cs{use_i:nn}
%   or \cs{use_ii:nn}, 2: $0$ or $1$ encoding the current truth value,
%   3: the next operation, And, Or, Close or Stop.  If |#1| is
%   \cs{use_ii:nn}, the logic of |#2| must be reversed.
%    \begin{macrocode}
\cs_new:Npn \@@_choose:NNN #1#2#3
  {
    \use:c
      {
        @@_ #3 _
        #1 #2 { \if_meaning:w 0 #2 1 \else: 0 \fi: }
        :w
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]
%   {
%     \@@_)_0:w,
%     \@@_)_1:w,
%     \@@_S_0:w,
%     \@@_S_1:w,
%   }
%   Closing a group is just about returning the result. The Stop
%   operation is similar except it closes the special alignment group
%   before returning the boolean.
%    \begin{macrocode}
\cs_new_nopar:cpn { @@_)_0:w } { \c_false_bool }
\cs_new_nopar:cpn { @@_)_1:w } { \c_true_bool }
\cs_new_nopar:cpn { @@_S_0:w } { \group_align_safe_end: \c_false_bool }
\cs_new_nopar:cpn { @@_S_1:w } { \group_align_safe_end: \c_true_bool }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]+\@@_&_1:w+
% \begin{macro}[aux]+\@@_|_0:w+
%   Two cases where we simply continue scanning.  We must remove the
%   second "&" or \verb"|".
%    \begin{macrocode}
\cs_new_nopar:cpn { @@_&_1:w } & { \@@_get_next:NN \use_i:nn }
\cs_new_nopar:cpn { @@_|_0:w } | { \@@_get_next:NN \use_i:nn }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[aux]+\@@_&_0:w+
% \begin{macro}[aux]+\@@_|_1:w+
% \begin{macro}[aux]
%   {
%     \@@_eval_skip_to_end_auxi:Nw,
%     \@@_eval_skip_to_end_auxii:Nw,
%     \@@_eval_skip_to_end_auxiii:Nw
%   }
%   When the truth value has already been decided, we have to throw away
%   the remainder of the current group as we are doing minimal
%   evaluation. This is slightly tricky as there are no braces so we
%   have to play match the |()| manually.
%    \begin{macrocode}
\cs_new_nopar:cpn { @@_&_0:w } &
  { \@@_eval_skip_to_end_auxi:Nw \c_false_bool }
\cs_new_nopar:cpn { @@_|_1:w } |
  { \@@_eval_skip_to_end_auxi:Nw \c_true_bool }
%    \end{macrocode}
%   There is always at least one |)| waiting, namely the outer
%   one. However, we are facing the problem that there may be more than
%   one that need to be finished off and we have to detect the correct
%   number of them. Here is a complicated example showing how this is
%   done. After evaluating the following, we realize we must skip
%   everything after the first And. Note the extra Close at the end.
%   \begin{quote}
%     |\c_false_bool  && ((abc) && xyz) && ((xyz) && (def)))|
%   \end{quote}
%   First read up to the first Close. This gives us the list we first
%   read up until the first right parenthesis so we are looking at the
%   token list
%   \begin{quote}
%     |((abc|
%   \end{quote}
%   This contains two Open markers so we must remove two groups. Since
%   no evaluation of the contents is to be carried out, it doesn't
%   matter how we remove the groups as long as we wind up with the
%   correct result. We therefore first remove a |()| pair and what
%   preceded the Open -- but leave the contents as it may contain Open
%   tokens itself -- leaving
%   \begin{quote}
%     |(abc && xyz) && ((xyz) && (def)))|
%   \end{quote}
%   Another round of this gives us
%   \begin{quote}
%     |(abc && xyz|
%   \end{quote}
%   which still contains an Open so we remove another |()| pair, giving us
%   \begin{quote}
%     |abc && xyz && ((xyz) && (def)))|
%   \end{quote}
%   Again we read up to a Close and again find Open tokens:
%   \begin{quote}
%     |abc && xyz && ((xyz|
%   \end{quote}
%   Further reduction gives us
%   \begin{quote}
%     |(xyz && (def)))|
%   \end{quote}
%   and then
%   \begin{quote}
%     |(xyz && (def|
%   \end{quote}
%   with reduction to
%   \begin{quote}
%     |xyz && (def))|
%   \end{quote}
%   and ultimately we arrive at no Open tokens being skipped and we can
%   finally close the group nicely.
%    \begin{macrocode}
%% (
\cs_new:Npn \@@_eval_skip_to_end_auxi:Nw #1#2 )
  {
    \@@_eval_skip_to_end_auxii:Nw #1#2 ( % )
    \q_no_value \q_stop
    {#2}
  }
%    \end{macrocode}
%   If no right parenthesis, then |#3| is no_value and we are done, return
%   the boolean |#1|.  If there is, we need to grab a |()| pair and then
%   recurse
%    \begin{macrocode}
\cs_new:Npn \@@_eval_skip_to_end_auxii:Nw #1#2 ( #3#4 \q_stop #5 % )
  {
    \quark_if_no_value:NTF #3
    {#1}
    { \@@_eval_skip_to_end_auxiii:Nw #1 #5 }
  }
%    \end{macrocode}
%   Keep the boolean, throw away anything up to the |(| as it is
%   irrelevant, remove a |()| pair but remember to reinsert |#3| as it may
%   contain |(| tokens!
%    \begin{macrocode}
\cs_new:Npn \@@_eval_skip_to_end_auxiii:Nw #1#2 ( #3 )
  { % (
    \@@_eval_skip_to_end_auxi:Nw #1#3 )
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\bool_not_p:n}
% \UnitTested
%   The Not variant just reverses the outcome of \cs{bool_if_p:n}. Can
%   be optimized but this is nice and simple and according to the
%   implementation plan. Not even particularly useful to have it when
%   the infix notation is easier to use.
%    \begin{macrocode}
\cs_new:Npn \bool_not_p:n #1 { \bool_if_p:n { ! ( #1 ) } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\bool_xor_p:nn}
% \UnitTested
%    Exclusive or. If the boolean expressions have same truth value,
%    return false, otherwise return true.
%    \begin{macrocode}
\cs_new:Npn \bool_xor_p:nn #1#2
  {
    \int_compare:nNnTF { \bool_if_p:n {#1} } = { \bool_if_p:n {#2} }
      \c_false_bool
      \c_true_bool
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Logical loops}
%
% \begin{macro}{\bool_while_do:Nn,\bool_while_do:cn}
% \UnitTested
% \begin{macro}{\bool_until_do:Nn,\bool_until_do:cn}
% \UnitTested
%   A |while| loop where the boolean is tested before executing the
%   statement. The \enquote{while} version executes the code as long as the
%   boolean is true; the \enquote{until} version executes the code as
%   long as the boolean is false.
%    \begin{macrocode}
\cs_new:Npn \bool_while_do:Nn #1#2
  { \bool_if:NT #1 { #2 \bool_while_do:Nn #1 {#2} } }
\cs_new:Npn \bool_until_do:Nn #1#2
  { \bool_if:NF #1 { #2 \bool_until_do:Nn #1 {#2} } }
\cs_generate_variant:Nn \bool_while_do:Nn { c }
\cs_generate_variant:Nn \bool_until_do:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\bool_do_while:Nn,\bool_do_while:cn}
% \UnitTested
% \begin{macro}{\bool_do_until:Nn,\bool_do_until:cn}
% \UnitTested
%   A |do-while| loop where the body is performed at least once and the
%   boolean is tested after executing the body. Otherwise identical to
%   the above functions.
%    \begin{macrocode}
\cs_new:Npn \bool_do_while:Nn #1#2
  { #2 \bool_if:NT #1 { \bool_do_while:Nn #1 {#2} } }
\cs_new:Npn \bool_do_until:Nn #1#2
  { #2 \bool_if:NF #1 { \bool_do_until:Nn #1 {#2} } }
\cs_generate_variant:Nn \bool_do_while:Nn { c }
\cs_generate_variant:Nn \bool_do_until:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \bool_while_do:nn, \bool_do_while:nn ,
%     \bool_until_do:nn, \bool_do_until:nn
%   }
%   \UnitTested
%   Loop functions with the test either before or after the first body
%   expansion.
%    \begin{macrocode}
\cs_new:Npn \bool_while_do:nn #1#2
  {
    \bool_if:nT {#1}
      {
        #2
        \bool_while_do:nn {#1} {#2}
      }
  }
\cs_new:Npn \bool_do_while:nn #1#2
  {
    #2
    \bool_if:nT {#1} { \bool_do_while:nn {#1} {#2} }
  }
\cs_new:Npn \bool_until_do:nn #1#2
  {
    \bool_if:nF {#1}
      {
        #2
        \bool_until_do:nn {#1} {#2}
      }
  }
\cs_new:Npn \bool_do_until:nn #1#2
  {
    #2
    \bool_if:nF {#1} { \bool_do_until:nn {#1} {#2}  }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Producing multiple copies}
%
%    \begin{macrocode}
%<@@=prg>
%    \end{macrocode}
%
% \begin{macro}{\prg_replicate:nn}
% \UnitTested
% \begin{macro}[aux]{\@@_replicate:N, \@@_replicate_first:N}
% \begin{macro}[aux]{\@@_replicate_}
% \begin{macro}[aux]
%   {
%     \@@_replicate_0:n,
%     \@@_replicate_1:n,
%     \@@_replicate_2:n,
%     \@@_replicate_3:n,
%     \@@_replicate_4:n,
%     \@@_replicate_5:n,
%     \@@_replicate_6:n,
%     \@@_replicate_7:n,
%     \@@_replicate_8:n,
%     \@@_replicate_9:n
%   }
% \begin{macro}[aux]
%   {
%     \@@_replicate_first_-:n,
%     \@@_replicate_first_0:n,
%     \@@_replicate_first_1:n,
%     \@@_replicate_first_2:n,
%     \@@_replicate_first_3:n,
%     \@@_replicate_first_4:n,
%     \@@_replicate_first_5:n,
%     \@@_replicate_first_6:n,
%     \@@_replicate_first_7:n,
%     \@@_replicate_first_8:n,
%     \@@_replicate_first_9:n
%   }
%   This function uses a cascading csname technique by David Kastrup
%   (who else :-)
%
%   The idea is to make the input |25| result in first adding five, and
%   then 20 copies of the code to be replicated. The technique uses
%   cascading csnames which means that we start building several csnames
%   so we end up with a list of functions to be called in reverse
%   order. This is important here (and other places) because it means
%   that we can for instance make the function that inserts five copies
%   of something to also hand down ten to the next function in
%   line. This is exactly what happens here: in the example with |25|
%   then the next function is the one that inserts two copies but it
%   sees the ten copies handed down by the previous function. In order
%   to avoid the last function to insert say, $100$ copies of the original
%   argument just to gobble them again we define separate functions to
%   be inserted first. These functions also close the expansion of
%   \cs{__int_to_roman:w}, which ensures that \cs{prg_replicate:nn} only
%   requires two steps of expansion.
%
%   This function has one flaw though: Since it constantly passes down
%   ten copies of its previous argument it will severely affect the main
%   memory once you start demanding hundreds of thousands of copies. Now
%   I don't think this is a real limitation for any ordinary use, and if
%   necessary, it is possible to write \cs{prg_replicate:nn} |{1000}|
%   |{| \cs{prg_replicate:nn} |{1000}| \Arg{code}~|}|. An
%   alternative approach is to create a string of |m|'s with
%   \cs{__int_to_roman:w} which can be done with just four macros but that
%   method has its own problems since it can exhaust the string
%   pool. Also, it is considerably slower than what we use here so the
%   few extra csnames are well spent I would say.
%    \begin{macrocode}
\cs_new:Npn \prg_replicate:nn #1
  {
    \__int_to_roman:w
      \exp_after:wN \@@_replicate_first:N
        \__int_value:w \__int_eval:w #1 \__int_eval_end:
      \cs_end:
  }
\cs_new:Npn \@@_replicate:N #1
  { \cs:w @@_replicate_#1 :n \@@_replicate:N }
\cs_new:Npn \@@_replicate_first:N #1
  { \cs:w @@_replicate_first_ #1 :n \@@_replicate:N }
%    \end{macrocode}
%   Then comes all the functions that do the hard work of inserting all
%   the copies.  The first function takes |:n| as a parameter.
%    \begin{macrocode}
\cs_new:Npn \@@_replicate_ :n #1 { \cs_end: }
\cs_new:cpn { @@_replicate_0:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} }
\cs_new:cpn { @@_replicate_1:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1 }
\cs_new:cpn { @@_replicate_2:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1 }
\cs_new:cpn { @@_replicate_3:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1 }
\cs_new:cpn { @@_replicate_4:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1 }
\cs_new:cpn { @@_replicate_5:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1 }
\cs_new:cpn { @@_replicate_6:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1 }
\cs_new:cpn { @@_replicate_7:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1#1 }
\cs_new:cpn { @@_replicate_8:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1#1#1 }
\cs_new:cpn { @@_replicate_9:n } #1
  { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1#1#1#1 }
%    \end{macrocode}
%    Users shouldn't ask for something to be replicated once or even
%    not at all but\dots
%    \begin{macrocode}
\cs_new:cpn { @@_replicate_first_-:n } #1
  {
    \c_zero
    \__msg_kernel_expandable_error:nn { kernel } { negative-replication }
  }
\cs_new:cpn { @@_replicate_first_0:n } #1 { \c_zero }
\cs_new:cpn { @@_replicate_first_1:n } #1 { \c_zero #1 }
\cs_new:cpn { @@_replicate_first_2:n } #1 { \c_zero #1#1 }
\cs_new:cpn { @@_replicate_first_3:n } #1 { \c_zero #1#1#1 }
\cs_new:cpn { @@_replicate_first_4:n } #1 { \c_zero #1#1#1#1 }
\cs_new:cpn { @@_replicate_first_5:n } #1 { \c_zero #1#1#1#1#1 }
\cs_new:cpn { @@_replicate_first_6:n } #1 { \c_zero #1#1#1#1#1#1 }
\cs_new:cpn { @@_replicate_first_7:n } #1 { \c_zero #1#1#1#1#1#1#1 }
\cs_new:cpn { @@_replicate_first_8:n } #1 { \c_zero #1#1#1#1#1#1#1#1 }
\cs_new:cpn { @@_replicate_first_9:n } #1 { \c_zero #1#1#1#1#1#1#1#1#1 }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Detecting \TeX{}'s mode}
%
% \begin{macro}[pTF]{\mode_if_vertical:}
% \UnitTested
%   For testing vertical mode. Strikes me here on the bus with David,
%   that as long as we are just talking about returning true and
%   false states, we can just use the primitive conditionals for this
%   and gobbling the \cs{c_zero} in the input stream. However this
%   requires knowledge of the implementation so we keep things nice
%   and clean and use the return statements.
%    \begin{macrocode}
\prg_new_conditional:Npnn \mode_if_vertical: { p , T , F , TF }
  { \if_mode_vertical: \prg_return_true: \else: \prg_return_false: \fi: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\mode_if_horizontal:}
% \UnitTested
%   For testing horizontal mode.
%    \begin{macrocode}
\prg_new_conditional:Npnn \mode_if_horizontal: { p , T , F , TF }
  { \if_mode_horizontal: \prg_return_true: \else: \prg_return_false: \fi: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\mode_if_inner:}
% \UnitTested
%   For testing inner mode.
%    \begin{macrocode}
\prg_new_conditional:Npnn \mode_if_inner: { p , T , F , TF }
  { \if_mode_inner: \prg_return_true: \else: \prg_return_false: \fi: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\mode_if_math:}
% \UnitTested
%   For testing math mode. At the beginning of an alignment cell,
%   the programmer should insert \cs{scan_align_safe_stop:} before
%   the test.
%    \begin{macrocode}
\prg_new_conditional:Npnn \mode_if_math: { p , T , F , TF }
  { \if_mode_math: \prg_return_true: \else: \prg_return_false: \fi: }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Internal programming functions}
%
% \begin{macro}[int]{\group_align_safe_begin:, \group_align_safe_end:}
%   \TeX{}'s alignment structures present many problems. As Knuth says
%   himself in \emph{\TeX : The Program}: \enquote{It's sort of a miracle
%   whenever \tn{halign} or \tn{valign} work, [\ldots]} One problem relates
%   to commands that internally issues a \tn{cr} but also peek ahead for
%   the next character for use in, say, an optional argument. If the
%   next token happens to be a |&| with category code~4 we will get some
%   sort of weird error message because the underlying
%   \tn{futurelet} will store the token at the end of the alignment
%   template. This could be a |&|$_4$ giving a message like
%   |! Misplaced \cr.| or even worse: it could be the \tn{endtemplate}
%   token causing even more trouble! To solve this we have to open a
%   special group so that \TeX{} still thinks it's on safe ground but at
%   the same time we don't want to introduce any brace group that may
%   find its way to the output. The following functions help with this
%   by using code documented only in Appendix~D of
%   \emph{The \TeX{}book}\dots
%   We place the \cs{if_false:} |{| \cs{fi:} part at that place so
%   that the successive expansions of \cs{group_align_safe_begin/end:}
%   are always brace balanced.
%    \begin{macrocode}
\cs_new_nopar:Npn \group_align_safe_begin:
  { \if_int_compare:w \if_false: { \fi: `} = \c_zero \fi: }
\cs_new_nopar:Npn \group_align_safe_end:
  { \if_int_compare:w `{ = \c_zero } \fi: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[int]{\scan_align_safe_stop:}
%   When \TeX{} is in the beginning of an align cell (right after the
%   \tn{cr} or |&|) it is in a somewhat strange mode as it is looking
%   ahead to find an \tn{omit} or \tn{noalign} and hasn't looked at the
%   preamble yet.  Thus an \tn{ifmmode} test at the start of an array
%   cell (where math mode is introduced by the preamble, not in the cell
%   itself) will always fail unless we stop \TeX{} from scanning ahead.
%   With \eTeX{}'s first version, this required inserting
%   \cs{scan_stop:}, but not in all cases (see below).  This is no
%   longer needed with a newer \eTeX{}, since protected macros are not
%   expanded anymore at the beginning of an alignment cell.  We can thus
%   use an empty protected macro to stop \TeX{}.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \scan_align_safe_stop: { }
%    \end{macrocode}
%   Let us now explain the earlier version.  We don't want to insert
%   a \cs{scan_stop:} every time as that will
%   destroy kerning between letters\footnote{Unless we enforce an extra
%   pass with an appropriate value of \tn{pretolerance}.}
%   Unfortunately there is no way to detect if we're in the beginning of
%   an alignment cell as they have different characteristics depending
%   on column number, \emph{etc.} However we \emph{can} detect if we're in an
%   alignment cell by checking the current group type and we can also
%   check if the previous node was a character or ligature. What is done
%   here is that \cs{scan_stop:} is only inserted if an only
%   if a)~we're in the outer part of an alignment cell and b)~the last node
%   \emph{wasn't} a char node or a ligature node. Thus an older definition
%   here was
%   \begin{verbatim}
%     \cs_new_nopar:Npn \scan_align_safe_stop:
%       {
%         \int_compare:nNnT \etex_currentgrouptype:D = \c_six
%           {
%             \int_compare:nNnF \etex_lastnodetype:D = \c_zero
%               {
%                 \int_compare:nNnF \etex_lastnodetype:D = \c_seven
%                   { \scan_stop: }
%               }
%           }
%      }
%    \end{verbatim}
%   However, this is not truly expandable, as there are places where the
%   \cs{scan_stop:} ends up in the result.
% \end{macro}
%
%    \begin{macrocode}
%<@@=prg>
%    \end{macrocode}
%
% \begin{macro}[int]{\@@_variable_get_scope:N}
% \begin{macro}[aux]{\@@_variable_get_scope:w}
% \begin{macro}[int]{\@@_variable_get_type:N}
% \begin{macro}[aux]{\@@_variable_get_type:w}
%   Expandable functions to find the type of a variable, and to
%   return \texttt{g} if the variable is global. The trick for
%   \cs{@@_variable_get_scope:N} is the same as that in
%   \cs{__cs_split_function:NN}, but it can be simplified as the
%   requirements here are less complex.
%    \begin{macrocode}
\group_begin:
  \tex_lccode:D `* = `g \scan_stop:
  \tex_catcode:D `* = \c_twelve
\tl_to_lowercase:n
  {
    \group_end:
    \cs_new:Npn \@@_variable_get_scope:N #1
      {
        \exp_after:wN \exp_after:wN
        \exp_after:wN \@@_variable_get_scope:w
          \cs_to_str:N #1 \exp_stop_f: \q_stop
      }
    \cs_new:Npn \@@_variable_get_scope:w #1#2 \q_stop
      { \token_if_eq_meaning:NNT * #1 { g } }
  }
\group_begin:
  \tex_lccode:D `* = `_ \scan_stop:
  \tex_catcode:D `* = \c_twelve
\tl_to_lowercase:n
  {
    \group_end:
    \cs_new:Npn \@@_variable_get_type:N #1
      {
        \exp_after:wN \@@_variable_get_type:w
          \token_to_str:N #1 * a \q_stop
      }
    \cs_new:Npn \@@_variable_get_type:w #1 * #2#3 \q_stop
      {
        \token_if_eq_meaning:NNTF a #2
          {#1}
          { \@@_variable_get_type:w #2#3 \q_stop }
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{variable}{\g_@@_map_int}
%   A nesting counter for mapping.
%    \begin{macrocode}
\int_new:N \g_@@_map_int
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\@@_break_point:Nn}
% \begin{macro}{\@@_map_break:Nn}
%   These are defined in \pkg{l3basics}, as they are needed
%   \enquote{early}. This is just a reminder that is the case!
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_break_point:}
% \begin{macro}{\@@_break:, \@@_break:n}
%   Also done in \pkg{l3basics} as in format mode these are needed within
%   \pkg{l3alloc}.
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
