summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3prg.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/l3kernel/l3prg.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3prg.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3prg.dtx1625
1 files changed, 1625 insertions, 0 deletions
diff --git a/macros/latex/contrib/l3kernel/l3prg.dtx b/macros/latex/contrib/l3kernel/l3prg.dtx
new file mode 100644
index 0000000000..5e4fa7732c
--- /dev/null
+++ b/macros/latex/contrib/l3kernel/l3prg.dtx
@@ -0,0 +1,1625 @@
+% \iffalse meta-comment
+%
+%% File: l3prg.dtx
+%
+% Copyright (C) 2005-2019 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
+%
+% 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{l3prg} package\\ Control structures^^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 2019-08-25}
+%
+% \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
+% states returned are \meta{true} and \meta{false}.
+%
+% \LaTeX3 has two forms of conditional flow processing based
+% on these states. The first 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.
+%
+% \begin{texnote}
+% The arguments are executed after exiting the underlying
+% |\if...\fi:| structure.
+% \end{texnote}
+%
+% \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[no-index]{\meta{name}:\meta{arg spec}} \meta{parameters} \Arg{conditions} \Arg{code} \\
+% \cs{prg_new_conditional:Nnn} \cs[no-index]{\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 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[no-index]{\meta{name}:\meta{arg spec}} \meta{parameters} \Arg{conditions} \Arg{code} \\
+% \cs{prg_new_protected_conditional:Nnn} \cs[no-index]{\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 check for
+% existing definitions and perform assignments globally
+% (\emph{cf.}~\cs{cs_new:Npn}) whereas the \texttt{set} version do
+% 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[no-index]{\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 cannot be defined for \texttt{protected}
+% conditionals.
+% \item \cs[no-index]{\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[no-index]{\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[no-index]{\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[no-index]{\meta{name_1}:\meta{arg spec_1}} \cs[no-index]{\meta{name_2}:\meta{arg spec_2}} \Arg{conditions}
+% \end{syntax}
+% These functions copy a family of conditionals. The \texttt{new} version
+% checks for existing definitions (\emph{cf.}~\cs{cs_new_eq:NN}) whereas
+% the \texttt{set} version does not (\emph{cf.}~\cs{cs_set_eq:NN}). 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 \enquote{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 should be 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 \texttt{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}
+%
+% \begin{function}[added = 2017-12-12]{\prg_generate_conditional_variant:Nnn}
+% \begin{syntax}
+% \cs{prg_generate_conditional_variant:Nnn} \cs[no-index]{\meta{name}:\meta{arg spec}} \Arg{variant argument specifiers} \Arg{condition specifiers}
+% \end{syntax}
+% Defines argument-specifier variants of conditionals. This is
+% equivalent to running \cs{cs_generate_variant:Nn} \meta{conditional}
+% \Arg{variant argument specifiers} on each \meta{conditional}
+% described by the \meta{condition specifiers}. These base-form
+% \meta{conditionals} are obtained from the \meta{name} and \meta{arg
+% spec} as described for \cs{prg_new_conditional:Npnn}, and they
+% should be defined.
+% \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 generally
+% means being constructed from predicate functions and booleans, possibly nested).
+%
+% \begin{texnote}
+% The \texttt{bool} data type is not implemented using the
+% \tn{iffalse}/\tn{iftrue} primitives, in contrast to \tn{newif},
+% \emph{etc.}, in plain \TeX{}, \LaTeXe{} and so on. Programmers should
+% not base use of \texttt{bool} switches on any particular expectation
+% of the implementation.
+% \end{texnote}
+%
+% \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} is initially \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 \meta{boolean_1} to the current value of \meta{boolean_2}.
+% \end{function}
+%
+% \begin{function}[updated = 2017-07-15]
+% {\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:nTF}, and sets the \meta{boolean} variable to
+% the logical truth of this evaluation.
+% \end{function}
+%
+% \begin{function}[EXP,pTF, updated = 2017-07-15]{\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, updated = 2015-08-01]{\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 = 2017-07-15]{\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}[added = 2014-08-22, updated = 2015-08-03]{\bool_log:N, \bool_log:c}
+% \begin{syntax}
+% \cs{bool_log:N} \meta{boolean}
+% \end{syntax}
+% Writes the logical truth of the \meta{boolean} in the log file.
+% \end{function}
+%
+% \begin{function}[added = 2014-08-22, updated = 2017-07-15]{\bool_log:n}
+% \begin{syntax}
+% \cs{bool_log:n} \Arg{boolean expression}
+% \end{syntax}
+% Writes the logical truth of the \meta{boolean expression} in the log
+% file.
+% \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 |&&| and \verb"||" and prefix~|!|
+% with their usual precedences (namely, |&&| binds more tightly than
+% \verb"||"). 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 } ||
+% \str_if_eq_p:nn { abc } { def }
+% ) &&
+% ! \int_compare_p:n { 2 = 4 }
+% \end{verbatim}
+% is a valid boolean expression.
+%
+% Contrarily to some other programming languages, the operators |&&| and
+% \verb"||" evaluate both operands in all cases, even when the first
+% operand is enough to determine the result. This \enquote{eager}
+% evaluation should be contrasted with the \enquote{lazy} evaluation of
+% \cs[no-index]{bool_lazy_\ldots{}} functions.
+%
+% \begin{texnote}
+% The eager evaluation of boolean expressions is unfortunately
+% necessary in \TeX{}. Indeed, a lazy parser can get confused if |&&|
+% or \verb"||" or parentheses appear as (unbraced) arguments of some
+% predicates. For instance, the innocuous-looking expression below
+% would break (in a lazy parser) if |#1| were a closing parenthesis
+% and \cs[no-index]{l_tmpa_bool} were \texttt{true}.
+% \begin{verbatim}
+% ( \l_tmpa_bool || \token_if_eq_meaning_p:NN X #1 )
+% \end{verbatim}
+% \end{texnote}
+%
+% Minimal (lazy) evaluation can be obtained using the conditionals
+% \cs{bool_lazy_all:nTF}, \cs{bool_lazy_and:nnTF}, \cs{bool_lazy_any:nTF}, or
+% \cs{bool_lazy_or:nnTF}, which only evaluate their boolean expression
+% arguments when they are needed to determine the resulting truth
+% value. For example, when evaluating the boolean expression
+% \begin{verbatim}
+% \bool_lazy_and_p:nn
+% {
+% \bool_lazy_any_p:n
+% {
+% { \int_compare_p:n { 2 = 3 } }
+% { \int_compare_p:n { 4 <= 4 } }
+% { \int_compare_p:n { 1 = \error } } % skipped
+% }
+% }
+% { ! \int_compare_p:n { 2 = 4 } }
+% \end{verbatim}
+% the line marked with |skipped| is not expanded because the result
+% of \cs{bool_lazy_any_p:n} is known once the second boolean expression is
+% found to be logically \texttt{true}. On the other hand, the last
+% line is expanded because its logical value is needed to determine the
+% result of \cs{bool_lazy_and_p:nn}.
+%
+% \begin{function}[EXP, pTF, updated = 2017-07-15]{\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. The logical Not applies to
+% the next predicate or group.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15, updated = 2017-07-15]{\bool_lazy_all:n}
+% \begin{syntax}
+% \cs{bool_lazy_all_p:n} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \}
+% \cs{bool_lazy_all:nTF} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{And} operation on the \meta{boolean
+% expressions}, hence is \texttt{true} if all of them are
+% \texttt{true} and \texttt{false} if any of them is \texttt{false}.
+% Contrarily to the infix operator |&&|, only the \meta{boolean
+% expressions} which are needed to determine the result of
+% \cs{bool_lazy_all:nTF} are evaluated. See also \cs{bool_lazy_and:nnTF}
+% when there are only two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15, updated = 2017-07-15]{\bool_lazy_and:nn}
+% \begin{syntax}
+% \cs{bool_lazy_and_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
+% \cs{bool_lazy_and:nnTF} \Arg{boolexpr_1} \Arg{boolexpr_2} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{And} operation between two boolean
+% expressions, hence is \texttt{true} if both are \texttt{true}.
+% Contrarily to the infix operator |&&|, the \meta{boolexpr_2} is only
+% evaluated if it is needed to determine the result of
+% \cs{bool_lazy_and:nnTF}. See also \cs{bool_lazy_all:nTF} when there are more
+% than two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15, updated = 2017-07-15]{\bool_lazy_any:n}
+% \begin{syntax}
+% \cs{bool_lazy_any_p:n} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \}
+% \cs{bool_lazy_any:nTF} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{Or} operation on the \meta{boolean
+% expressions}, hence is \texttt{true} if any of them is
+% \texttt{true} and \texttt{false} if all of them are \texttt{false}.
+% Contrarily to the infix operator \verb"||", only the \meta{boolean
+% expressions} which are needed to determine the result of
+% \cs{bool_lazy_any:nTF} are evaluated. See also \cs{bool_lazy_or:nnTF}
+% when there are only two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15, updated = 2017-07-15]{\bool_lazy_or:nn}
+% \begin{syntax}
+% \cs{bool_lazy_or_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
+% \cs{bool_lazy_or:nnTF} \Arg{boolexpr_1} \Arg{boolexpr_2} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{Or} operation between two boolean
+% expressions, hence is \texttt{true} if either one is \texttt{true}.
+% Contrarily to the infix operator \verb"||", the \meta{boolexpr_2}
+% is only evaluated if it is needed to determine the result of
+% \cs{bool_lazy_or:nnTF}. See also \cs{bool_lazy_any:nTF} when there are more
+% than two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, updated = 2017-07-15]{\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, pTF, added = 2018-05-09]{\bool_xor:nn}
+% \begin{syntax}
+% \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
+% \cs{bool_xor:nnTF} \Arg{boolexpr_1} \Arg{boolexpr_2} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements an \enquote{exclusive or} operation between two boolean
+% expressions. There is no infix operation for this logical operation.
+% \end{function}
+%
+% \section{Logical loops}
+%
+% Loops using either boolean expressions or stored boolean values.
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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} is inserted into the input
+% stream again and the process loops until the \meta{boolean} is
+% \texttt{true}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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} is inserted into the input
+% stream again and the process loops until the \meta{boolean} is
+% \texttt{false}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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 then loops
+% until the \meta{boolean} is \texttt{true}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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 then loops
+% until the \meta{boolean} is \texttt{false}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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} is inserted into the input stream again and the
+% process loops until the \meta{boolean expression} evaluates to
+% \texttt{true}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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} is inserted into the input stream again and the
+% process loops until the \meta{boolean expression} evaluates to
+% \texttt{false}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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
+% then loops until the \meta{boolean expression} is \texttt{true}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2017-07-15]{\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
+% then loops 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}
+% \cs{if_predicate:w} \meta{predicate} \meta{true code} \cs{else:} \meta{false code} \cs{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 \meta{predicate} but to make the
+% coding clearer this should be done through \cs{if_bool:N}.)
+% \end{function}
+%
+% \begin{function}[EXP]{\if_bool:N}
+% \begin{syntax}
+% \cs{if_bool:N} \meta{boolean} \meta{true code} \cs{else:} \meta{false code} \cs{fi:}
+% \end{syntax}
+% This function takes a boolean variable and
+% branches according to the result.
+% \end{function}
+%
+% \section{Nestable recursions and mappings}
+%
+% There are a number of places where recursion or mapping constructs are used in
+% \pkg{expl3}. At a low-level, these typically require insertion of tokens
+% at the end of the content to allow \enquote{clean up}. To support such
+% mappings in a nestable form, the following functions are provided.
+%
+% \begin{function}[EXP, added = 2018-03-26]{\prg_break_point:Nn}
+% \begin{syntax}
+% \cs{prg_break_point:Nn} \cs[no-index]{\meta{type}_map_break:} \Arg{code}
+% \end{syntax}
+% Used to mark the end of a recursion or mapping: the functions
+% \cs[no-index]{\meta{type}_map_break:} and
+% \cs[no-index]{\meta{type}_map_break:n} use this to break out of the loop
+% (see \cs{prg_map_break:Nn} for how to set these up).
+% After the loop ends, the \meta{code} is 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, added = 2018-03-26]{\prg_map_break:Nn}
+% \begin{syntax}
+% \cs{prg_map_break:Nn} \cs[no-index]{\meta{type}_map_break:} \Arg{user code}
+% \ldots{}
+% \cs{prg_break_point:Nn} \cs[no-index]{\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[no-index]{\meta{type}_map_break:} argument
+% must be defined; it is simply used as a recognizable marker for the \meta{type}.
+%
+% For types with mappings defined in the kernel,
+% \cs[no-index]{\meta{type}_map_break:} and \cs[no-index]{\meta{type}_map_break:n}
+% are defined as \cs{prg_map_break:Nn} \cs[no-index]{\meta{type}_map_break:} |{}|
+% and the same with |{}| omitted.
+% \end{function}
+%
+% \subsection{Simple mappings}
+%
+% In addition to the more complex mappings above, non-nestable mappings are
+% used in a number of locations and support is provided for these.
+%
+% \begin{function}[EXP, added = 2018-03-27]{\prg_break_point:}
+% This copy of \cs{prg_do_nothing:} is used to mark the end of a fast
+% short-term recursion: the function \cs{prg_break:n} uses this to
+% break out of the loop.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2018-03-27]{\prg_break:, \prg_break:n}
+% \begin{syntax}
+% \cs{prg_break:n} \Arg{code} \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 the \meta{code} in the input stream.
+% \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} would 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}
+%
+% \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.
+% \begin{macrocode}
+\cs_new_eq:NN \if_bool:N \tex_ifodd:D
+\cs_new_eq:NN \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.
+% When \texttt{check-declarations} is active, the definitions are patched to
+% make sure the boolean exists. This is needed because booleans are
+% not based on token lists nor on \TeX{} registers.
+% \begin{macrocode}
+\__kernel_patch:nnNNpn { \__kernel_chk_var_local:N #1 } { }
+\cs_new_protected:Npn \bool_set_true:N #1
+ { \cs_set_eq:NN #1 \c_true_bool }
+\__kernel_patch:nnNNpn { \__kernel_chk_var_local:N #1 } { }
+\cs_new_protected:Npn \bool_set_false:N #1
+ { \cs_set_eq:NN #1 \c_false_bool }
+\__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { }
+\cs_new_protected:Npn \bool_gset_true:N #1
+ { \cs_gset_eq:NN #1 \c_true_bool }
+\__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { }
+\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. While it would be cleaner semantically to copy
+% the \cs{cs_set_eq:NN} family of functions, we copy \cs{tl_set_eq:NN}
+% because that has the correct checking code.
+% \begin{macrocode}
+\cs_new_eq:NN \bool_set_eq:NN \tl_set_eq:NN
+\cs_new_eq:NN \bool_gset_eq:NN \tl_gset_eq:NN
+\cs_generate_variant:Nn \bool_set_eq:NN { Nc, cN, cc }
+\cs_generate_variant:Nn \bool_gset_eq:NN { Nc, cN, 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}. Again,
+% we include some checking code. It is important to evaluate the
+% expression before applying the \tn{chardef} primitive, because that
+% primitive sets the left-hand side to \cs{scan_stop:} before looking
+% for the right-hand side.
+% \begin{macrocode}
+\__kernel_patch:nnNNpn { \__kernel_chk_var_local:N #1 } { }
+\cs_new_protected:Npn \bool_set:Nn #1#2
+ {
+ \exp_last_unbraced:NNNf
+ \tex_chardef:D #1 = { \bool_if_p:n {#2} }
+ }
+\__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { }
+\cs_new_protected:Npn \bool_gset:Nn #1#2
+ {
+ \exp_last_unbraced:NNNNf
+ \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}
+%
+% \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_bool:N #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\prg_generate_conditional_variant:Nnn \bool_if:N { c } { p , T , F , TF }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\bool_show:n, \bool_log:n}
+% \begin{macro}{\@@_to_str:n}
+% Show the truth value of the boolean, as \texttt{true} or
+% \texttt{false}.
+% \begin{macrocode}
+\cs_new_protected:Npn \bool_show:n
+ { \msg_show_eval:Nn \@@_to_str:n }
+\cs_new_protected:Npn \bool_log:n
+ { \msg_log_eval:Nn \@@_to_str:n }
+\cs_new:Npn \@@_to_str:n #1
+ { \bool_if:nTF {#1} { true } { false } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\bool_show:N, \bool_show:c, \bool_log:N, \bool_log:c, \@@_show:NN}
+% Show the truth value of the boolean, as \texttt{true} or
+% \texttt{false}.
+% \begin{macrocode}
+\cs_new_protected:Npn \bool_show:N { \@@_show:NN \tl_show:n }
+\cs_generate_variant:Nn \bool_show:N { c }
+\cs_new_protected:Npn \bool_log:N { \@@_show:NN \tl_log:n }
+\cs_generate_variant:Nn \bool_log:N { c }
+\cs_new_protected:Npn \@@_show:NN #1#2
+ {
+ \__kernel_chk_defined:NT #2
+ { \exp_args:Nx #1 { \token_to_str:N #2 = \@@_to_str:n {#2} } }
+ }
+% \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}. However, they perform eager evaluation.
+% 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 GetNext
+% function with the logic reversed.
+% \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 using the values of predicates within this
+% sub-expression until the next Close. Then return \meta{false}.
+% \item[\meta{true}Or] Current truth value is true, logical Or seen,
+% stop using the values of predicates within this sub-expression
+% until 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}
+% \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, \@@_if_p:n, \@@_if_p_aux:w}
+% To speed up the case of a single predicate, \texttt{f}-expand and
+% check whether the result is one token (possibly surrounded by
+% spaces), which must be \cs{c_true_bool} or \cs{c_false_bool}. We
+% use a version of \cs{tl_if_single:nTF} optimized for speed since we
+% know that an empty~|#1| is an error. The auxiliary
+% \cs{@@_if_p_aux:w} removes the trailing parenthesis and gets rid of
+% any space. For the general case, 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 group is closed after \cs{@@_get_next:NN} returns
+% \cs{c_true_bool} or \cs{c_false_bool}. That function requires the
+% trailing parenthesis to know where the expression ends.
+% \begin{macrocode}
+\cs_new:Npn \bool_if_p:n { \exp_args:Nf \@@_if_p:n }
+\cs_new:Npn \@@_if_p:n #1
+ {
+ \tl_if_empty:oT { \use_none:nn #1 . } { \@@_if_p_aux:w }
+ \group_align_safe_begin:
+ \exp_after:wN
+ \group_align_safe_end:
+ \exp:w \exp_end_continue_f:w % (
+ \@@_get_next:NN \use_i:nnnn #1 )
+ }
+\cs_new:Npn \@@_if_p_aux:w #1 \use_i:nnnn #2#3 {#2}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_next:NN}
+% The GetNext operation. Its first argument is \cs{use_i:nnnn},
+% \cs{use_ii:nnnn}, \cs{use_iii:nnnn}, or \cs{use_iv:nnnn} (we call
+% these \enquote{states}). In the first state, 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. For instance
+% \enquote{\cs{@@_get_next:NN} \cs{use_i:nnnn} \cs{c_true_bool}
+% \texttt{\&\&} \cs{c_true_bool} \texttt{)}} (including the closing
+% parenthesis) expands to \cs{c_true_bool}. In the second state
+% (after a |!|) the logic is reversed. We call these two states
+% \enquote{normal} and the next two \enquote{skipping}. In the third
+% state (after \cs{c_true_bool}\verb"||") it always returns
+% \cs{c_true_bool}. In the fourth state (after \cs{c_false_bool}|&&|)
+% it always returns \cs{c_false_bool} and also stops when encountering
+% \verb"||", not only parentheses. This code itself is a switch: if
+% what follows is neither |!| nor |(|, we assume it is a predicate.
+% \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}{\@@_!:Nw}
+% The Not operation reverses the logic: it discards the |!|~token and
+% calls the GetNext operation with the appropriate first argument.
+% Namely the first and second states are interchanged, but after
+% \cs{c_true_bool}\verb"||" or \cs{c_false_bool}|&&| the |!|~is
+% ignored.
+% \begin{macrocode}
+\cs_new:cpn { @@_!:Nw } #1#2
+ {
+ \exp_after:wN \@@_get_next:NN
+ #1 \use_ii:nnnn \use_i:nnnn \use_iii:nnnn \use_iv:nnnn
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_(:Nw}
+% The Open operation starts a sub-expression after discarding the open
+% parenthesis. This is done by calling GetNext (which eventually
+% discards the corresponding closing parenthesis), with a
+% post-processing step which looks for And, Or or Close after the
+% group.
+% \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:nnnn
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_p:Nw}
+% If what follows GetNext is neither |!| nor |(|, evaluate the
+% predicate using the primitive \cs{int_value:w}. The canonical
+% \texttt{true} and \texttt{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}{\@@_choose:NNN}
+% \begin{macro}+\@@_)_0:+
+% \begin{macro}+\@@_)_1:+
+% \begin{macro}+\@@_)_2:+
+% \begin{macro}+\@@_&_0:+
+% \begin{macro}+\@@_&_1:+
+% \begin{macro}+\@@_&_2:+
+% \begin{macro}+\@@_|_0:+
+% \begin{macro}+\@@_|_1:+
+% \begin{macro}+\@@_|_2:+
+% The arguments are |#1|: a function such as \cs{use_i:nnnn}, |#2|:
+% $0$ or $1$ encoding the current truth value, |#3|: the next
+% operation, And, Or or Close. We distinguish three cases according
+% to a combination of |#1| and |#2|. Case~2 is when |#1| is
+% \cs{use_iii:nnnn} (state~3), namely after
+% \cs{c_true_bool}~\verb"||". Case~1 is when |#1| is \cs{use_i:nnnn}
+% and |#2| is \texttt{true} or when |#1| is \cs{use_ii:nnnn} and |#2|
+% is \texttt{false}, for instance for |!|\cs{c_false_bool}. Case~0
+% includes the same with \texttt{true}/\texttt{false} interchanged and
+% the case where |#1| is \cs{use_iv:nnnn} namely after
+% \cs{c_false_bool}~|&&|.
+%
+% When seeing~|)| the current subexpression is done, leave the
+% appropriate boolean. When seeing~|&| in case~0 go into state~4,
+% equivalent to having seen \cs{c_false_bool}~|&&|. In case~1, namely
+% when the argument is \texttt{true} and we are in a normal state
+% continue in the normal state~1. In case~2, namely when skipping
+% alternatives in an Or, continue in the same state. When
+% seeing~\verb"|" in case~0, continue in a normal state; in particular
+% stop skipping for \cs{c_false_bool}~|&&| because that binds more
+% tightly than~\verb"||". In the other two cases start skipping for
+% \cs{c_true_bool}~\verb"||".
+% \begin{macrocode}
+\cs_new:Npn \@@_choose:NNN #1#2#3
+ {
+ \use:c
+ {
+ @@_ \token_to_str:N #3 _
+ #1 #2 { \if_meaning:w 0 #2 1 \else: 0 \fi: } 2 0 :
+ }
+ }
+\cs_new:cpn { @@_)_0: } { \c_false_bool }
+\cs_new:cpn { @@_)_1: } { \c_true_bool }
+\cs_new:cpn { @@_)_2: } { \c_true_bool }
+\cs_new:cpn { @@_&_0: } & { \@@_get_next:NN \use_iv:nnnn }
+\cs_new:cpn { @@_&_1: } & { \@@_get_next:NN \use_i:nnnn }
+\cs_new:cpn { @@_&_2: } & { \@@_get_next:NN \use_iii:nnnn }
+\cs_new:cpn { @@_|_0: } | { \@@_get_next:NN \use_i:nnnn }
+\cs_new:cpn { @@_|_1: } | { \@@_get_next:NN \use_iii:nnnn }
+\cs_new:cpn { @@_|_2: } | { \@@_get_next:NN \use_iii:nnnn }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_all:n}
+% \begin{macro}{\@@_lazy_all:n}
+% \UnitTested
+% Go through the list of expressions, stopping whenever an expression
+% is \texttt{false}. If the end is reached without finding any
+% \texttt{false} expression, then the result is \texttt{true}.
+% \begin{macrocode}
+\cs_new:Npn \bool_lazy_all_p:n #1
+ { \@@_lazy_all:n #1 \q_recursion_tail \q_recursion_stop }
+\prg_new_conditional:Npnn \bool_lazy_all:n #1 { T , F , TF }
+ {
+ \if_predicate:w \bool_lazy_all_p:n {#1}
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new:Npn \@@_lazy_all:n #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \c_true_bool }
+ \bool_if:nF {#1}
+ { \use_i_delimit_by_q_recursion_stop:nw { \c_false_bool } }
+ \@@_lazy_all:n
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_and:nn}
+% \UnitTested
+% Only evaluate the second expression if the first is \texttt{true}.
+% Note that |#2| must be removed as an argument, not just by skipping
+% to the \cs{else:} branch of the conditional since |#2| may contain
+% unbalanced \TeX{} conditionals.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_lazy_and:nn #1#2 { p , T , F , TF }
+ {
+ \if_predicate:w
+ \bool_if:nTF {#1} { \bool_if_p:n {#2} } { \c_false_bool }
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_any:n}
+% \begin{macro}{\@@_lazy_any:n}
+% \UnitTested
+% Go through the list of expressions, stopping whenever an expression
+% is \texttt{true}. If the end is reached without finding any
+% \texttt{true} expression, then the result is \texttt{false}.
+% \begin{macrocode}
+\cs_new:Npn \bool_lazy_any_p:n #1
+ { \@@_lazy_any:n #1 \q_recursion_tail \q_recursion_stop }
+\prg_new_conditional:Npnn \bool_lazy_any:n #1 { T , F , TF }
+ {
+ \if_predicate:w \bool_lazy_any_p:n {#1}
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new:Npn \@@_lazy_any:n #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \c_false_bool }
+ \bool_if:nT {#1}
+ { \use_i_delimit_by_q_recursion_stop:nw { \c_true_bool } }
+ \@@_lazy_any:n
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_or:nn}
+% \UnitTested
+% Only evaluate the second expression if the first is \texttt{false}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_lazy_or:nn #1#2 { p , T , F , TF }
+ {
+ \if_predicate:w
+ \bool_if:nTF {#1} { \c_true_bool } { \bool_if_p:n {#2} }
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \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}[pTF]{\bool_xor:nn}
+% \UnitTested
+% Exclusive or. If the boolean expressions have same truth value,
+% return \texttt{false}, otherwise return \texttt{true}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_xor:nn #1#2 { p , T , F , TF }
+ {
+ \bool_if:nT {#1} \reverse_if:N
+ \if_predicate:w \bool_if_p:n {#2}
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \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}{\@@_replicate:N, \@@_replicate_first:N}
+% \begin{macro}{\@@_replicate_}
+% \begin{macro}
+% {
+% \@@_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}
+% {
+% \@@_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{exp: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 severely affects 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{exp: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
+ {
+ \exp:w
+ \exp_after:wN \@@_replicate_first:N
+ \int_value:w \int_eval:n {#1}
+ \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
+ {
+ \exp_end:
+ \__kernel_msg_expandable_error:nn { kernel } { negative-replication }
+ }
+\cs_new:cpn { @@_replicate_first_0:n } #1 { \exp_end: }
+\cs_new:cpn { @@_replicate_first_1:n } #1 { \exp_end: #1 }
+\cs_new:cpn { @@_replicate_first_2:n } #1 { \exp_end: #1#1 }
+\cs_new:cpn { @@_replicate_first_3:n } #1 { \exp_end: #1#1#1 }
+\cs_new:cpn { @@_replicate_first_4:n } #1 { \exp_end: #1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_5:n } #1 { \exp_end: #1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_6:n } #1 { \exp_end: #1#1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_7:n } #1 { \exp_end: #1#1#1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_8:n } #1 { \exp_end: #1#1#1#1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_9:n } #1
+ { \exp_end: #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{exp_end:} 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,
+% this should be used only inside a non-expandable function.
+% \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}{\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 get some
+% sort of weird error message because the underlying
+% \tn{futurelet} stores 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:Npn \group_align_safe_begin:
+ { \if_int_compare:w \if_false: { \fi: `} = \c_zero_int \fi: }
+\cs_new:Npn \group_align_safe_end:
+ { \if_int_compare:w `{ = \c_zero_int } \fi: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<@@=prg>
+% \end{macrocode}
+%
+% \begin{variable}{\g__kernel_prg_map_int}
+% A nesting counter for mapping.
+% \begin{macrocode}
+\int_new:N \g__kernel_prg_map_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\prg_break_point:Nn}
+% \begin{macro}{\prg_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}{\prg_break_point:}
+% \begin{macro}{\prg_break:, \prg_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