summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3prg.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3prg.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3prg.dtx1829
1 files changed, 0 insertions, 1829 deletions
diff --git a/macros/latex/contrib/l3kernel/l3prg.dtx b/macros/latex/contrib/l3kernel/l3prg.dtx
deleted file mode 100644
index 8bbdd6a587..0000000000
--- a/macros/latex/contrib/l3kernel/l3prg.dtx
+++ /dev/null
@@ -1,1829 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: l3prg.dtx
-%
-% Copyright (C) 2005-2024 The LaTeX Project
-%
-% It may be distributed and/or modified under the conditions of the
-% LaTeX Project Public License (LPPL), either version 1.3c of this
-% license or (at your option) any later version. The latest version
-% of this license is in the file
-%
-% https://www.latex-project.org/lppl.txt
-%
-% This file is part of the "l3kernel bundle" (The Work in LPPL)
-% and all files in that bundle must be distributed together.
-%
-% -----------------------------------------------------------------------
-%
-% The development version of the bundle can be found at
-%
-% https://github.com/latex3/latex3
-%
-% for those people who are interested.
-%
-%<*driver>
-\documentclass[full,kernel]{l3doc}
-\begin{document}
- \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \title{^^A
-% The \pkg{l3prg} module\\ Control structures^^A
-% }
-%
-% \author{^^A
-% The \LaTeX{} Project\thanks
-% {^^A
-% E-mail:
-% \href{mailto:latex-team@latex-project.org}
-% {latex-team@latex-project.org}^^A
-% }^^A
-% }
-%
-% \date{Released 2024-03-14}
-%
-% \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 = 2022-11-01]
-% {
-% \prg_new_conditional:Npnn, \prg_set_conditional:Npnn, \prg_gset_conditional:Npnn,
-% \prg_new_conditional:Nnn, \prg_set_conditional:Nnn, \prg_gset_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_gset_protected_conditional:Npnn,
-% \prg_new_protected_conditional:Nnn, \prg_set_protected_conditional:Nnn, \prg_gset_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.
-%
-% The special case where the code of a conditional ends with
-% \cs{prg_return_true:} \cs{else:} \cs{prg_return_false:} \cs{fi:} is
-% optimized.
-%
-% \begin{function}[updated = 2023-05-26]
-% {
-% \prg_new_eq_conditional:NNn,
-% \prg_set_eq_conditional:NNn,
-% \prg_gset_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}[added = 2017-11-28]{\bool_const:Nn, \bool_const:cn}
-% \begin{syntax}
-% \cs{bool_const:Nn} \meta{boolean} \Arg{boolexpr}
-% \end{syntax}
-% Creates a new constant \meta{boolean} or raises an error if the name
-% is already taken. The value of the \meta{boolean} is set globally to
-% the result of evaluating the \meta{boolexpr}.
-% \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}[added = 2018-05-10]
-% {
-% \bool_set_inverse:N , \bool_set_inverse:c ,
-% \bool_gset_inverse:N, \bool_gset_inverse:c
-% }
-% \begin{syntax}
-% \cs{bool_set_inverse:N} \meta{boolean}
-% \end{syntax}
-% Toggles the \meta{boolean} from \texttt{true} to \texttt{false} and
-% conversely: sets it to the inverse of its current value.
-% \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}[EXP, added = 2021-11-01, updated = 2023-11-14]
-% {\bool_to_str:N, \bool_to_str:c, \bool_to_str:n}
-% \begin{syntax}
-% \cs{bool_to_str:N} \meta{boolean}
-% \cs{bool_to_str:n} \meta{boolean expression}
-% \end{syntax}
-% Expands to the string \texttt{true} or \texttt{false} depending on
-% the logical truth of the \meta{boolean} or \meta{boolean
-% expression}.
-% \end{function}
-%
-% \begin{function}[added = 2012-02-09, updated = 2021-04-29]{\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 = 2021-04-29]{\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}
-%
-% \subsection{Constant and scratch booleans}
-%
-% \begin{variable}{\c_true_bool, \c_false_bool}
-% Constants that represent |true| and |false|, respectively. Used to
-% implement predicates.
-% \end{variable}
-%
-% \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 first 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 first 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 first 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 first 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}
-%
-% \begin{function}[added = 2023-05-03, EXP, noTF]{\bool_case:n}
-% \begin{syntax}
-% \cs{bool_case:nTF} \\
-% ~~|{| \\
-% ~~~~\Arg{boolexpr case_1} \Arg{code case_1} \\
-% ~~~~\Arg{boolexpr case_2} \Arg{code case_2} \\
-% ~~~~\ldots \\
-% ~~~~\Arg{boolexpr case_n} \Arg{code case_n} \\
-% ~~|}| \\
-% ~~\Arg{true code}
-% ~~\Arg{false code}
-% \end{syntax}
-% Evaluates in turn each of the \meta{boolean expression cases} until
-% the first one that evaluates to \texttt{true}.
-% The \meta{code} associated to this first case is left in the input
-% stream, followed by the \meta{true code}, and other cases are
-% discarded. If none of the cases match then only the \meta{false
-% code} is inserted. The function \cs{bool_case:n},
-% which does nothing if there is no match, is
-% also available. For example
-% \begin{verbatim}
-% \bool_case:nF
-% {
-% { \dim_compare_p:n { \l__mypkg_wd_dim <= 10pt } }
-% { Fits }
-% { \int_compare_p:n { \l__mypkg_total_int >= 10 } }
-% { Many }
-% { \l__mypkg_special_bool }
-% { Special }
-% }
-% { No idea! }
-% \end{verbatim}
-% leaves \enquote{\texttt{Fits}} or \enquote{\texttt{Many}} or
-% \enquote{\texttt{Special}} or \enquote{\texttt{No idea!}} in the
-% input stream, in a way similar to some other language's
-% \enquote{\texttt{if} \ldots\ \texttt{elseif} \ldots\ \texttt{elseif} \ldots\
-% \texttt{else} \ldots}.
-% \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_p:}
-% \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
-% implementation of \cs{int_step_function:nnnN}), 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}
-%<*package>
-% \end{macrocode}
-%
-% \subsection{Primitive conditionals}
-%
-% \begin{macro}{\if_bool:N}
-% \begin{macro}{\if_predicate:w}
-% Those two primitive \TeX{} conditionals are synonyms.
-% \cs{if_bool:N} is defined in \pkg{l3basics}, as it's needed
-% earlier to define quark test functions.
-% \begin{macrocode}
-\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}[added = 2017-11-28]{\bool_const:Nn, \bool_const:cn}
-% A merger between \cs{tl_const:Nn} and \cs{bool_set:Nn}.
-% \begin{macrocode}
-\cs_new_protected:Npn \bool_const:Nn #1#2
- {
- \__kernel_chk_if_free_cs:N #1
- \tex_global:D \tex_chardef:D #1 = \bool_if_p:n {#2}
- }
-\cs_generate_variant:Nn \bool_const:Nn { 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}
-\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. 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}
-\cs_new_protected:Npn \bool_set:Nn #1#2
- {
- \exp_last_unbraced:NNNf
- \tex_chardef:D #1 = { \bool_if_p:n {#2} }
- }
-\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}[added = 2018-05-10]
-% {\bool_set_inverse:N, \bool_set_inverse:c, \bool_gset_inverse:N, \bool_gset_inverse:c}
-% Set to \texttt{false} or \texttt{true} locally or globally.
-% \begin{macrocode}
-\cs_new_protected:Npn \bool_set_inverse:N #1
- { \bool_if:NTF #1 { \bool_set_false:N } { \bool_set_true:N } #1 }
-\cs_generate_variant:Nn \bool_set_inverse:N { c }
-\cs_new_protected:Npn \bool_gset_inverse:N #1
- { \bool_if:NTF #1 { \bool_gset_false:N } { \bool_gset_true:N } #1 }
-\cs_generate_variant:Nn \bool_gset_inverse:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Internal auxiliaries}
-%
-% \begin{variable}{\q_@@_recursion_tail,\q_@@_recursion_stop}
-% Internal recursion quarks.
-% \begin{macrocode}
-\quark_new:N \q_@@_recursion_tail
-\quark_new:N \q_@@_recursion_stop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}[EXP]{\@@_use_i_delimit_by_q_recursion_stop:nw}
-% Functions to gobble up to a quark.
-% \begin{macrocode}
-\cs_new:Npn \@@_use_i_delimit_by_q_recursion_stop:nw
- #1 #2 \q_@@_recursion_stop {#1}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_if_recursion_tail_stop_do:nn}
-% Functions to query recursion quarks.
-% \begin{macrocode}
-\__kernel_quark_new_test:N \@@_if_recursion_tail_stop_do:nn
-% \end{macrocode}
-% \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}[EXP]{\bool_to_str:N, \bool_to_str:c, \bool_to_str:n}
-% Expands to string literal \texttt{true} or \texttt{false}.
-% \begin{macrocode}
-\cs_new:Npe \bool_to_str:N #1
- {
- \exp_not:N \bool_if:NTF #1
- { \tl_to_str:n { true } } { \tl_to_str:n { false } }
- }
-\cs_generate_variant:Nn \bool_to_str:N { c }
-\cs_new:Npe \bool_to_str:n #1
- {
- \exp_not:N \bool_if:nTF {#1}
- { \tl_to_str:n { true } } { \tl_to_str:n { false } }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\bool_show:n, \bool_log:n}
-% Show the truth value of the boolean.
-% \begin{macrocode}
-\cs_new_protected:Npn \bool_show:n
- { \__kernel_msg_show_eval:Nn \bool_to_str:n }
-\cs_new_protected:Npn \bool_log:n
- { \__kernel_msg_log_eval:Nn \bool_to_str:n }
-% \end{macrocode}
-% \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
- {
- \token_case_meaning:NnF #2
- {
- \c_true_bool { \exp_args:Ne #1 { \token_to_str:N #2 = true } }
- \c_false_bool { \exp_args:Ne #1 { \token_to_str:N #2 = false } }
- }
- {
- \msg_error:nneee { kernel } { bad-type }
- { \token_to_str:N #2 } { \token_to_meaning:N #2 } { bool }
- }
- }
- }
-% \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, then returns \cs{c_true_bool} or \cs{c_false_bool} as
-% appropriate. This extra work around is because in a
-% \cs{bool_set:Nn}, the underlying \tn{chardef} turns the bool being
-% set temporarily equal to \tn{relax}, thus assigning a boolean to
-% itself would fail (gh/1055). 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
- { \bool_if:NTF #2 \c_true_bool \c_false_bool }
-% \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
- {
- \@@_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
- {
- \@@_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}
-%
-% \begin{variable}{\s_@@_mark,\s_@@_stop}
-% Internal scan marks.
-% \begin{macrocode}
-\scan_new:N \s_@@_mark
-\scan_new:N \s_@@_stop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}[EXP, noTF]{\bool_case:n}
-% \begin{macro}{\@@_case:NnTF}
-% \begin{macro}{\@@_case:w,a\@@_case_end:nw}
-% For boolean cases the overall idea is the same as for
-% \cs{str_case:nnTF} as described in \pkg{l3str}.
-% \begin{macrocode}
-\cs_new:Npn \bool_case:nTF
- { \exp:w \@@_case:nTF }
-\cs_new:Npn \bool_case:nT #1#2
- { \exp:w \@@_case:nTF {#1} {#2} { } }
-\cs_new:Npn \bool_case:nF #1
- { \exp:w \@@_case:nTF {#1} { } }
-\cs_new:Npn \bool_case:n #1
- { \exp:w \@@_case:nTF {#1} { } { } }
-\cs_new:Npn \@@_case:nTF #1#2#3
- {
- \@@_case:w
- #1 \c_true_bool { } \s_@@_mark {#2} \s_@@_mark {#3} \s_@@_stop
- }
-\cs_new:Npn \@@_case:w #1#2
- {
- \bool_if:nTF {#1}
- { \@@_case_end:nw {#2} }
- { \@@_case:w }
- }
-\cs_new:Npn \@@_case_end:nw #1#2#3 \s_@@_mark #4#5 \s_@@_stop
- { \exp_end: #1 #4 }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \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:
- \msg_expandable_error:nn { prg } { 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 issue 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 behaviour documented only in Appendix~D of
-% \emph{The \TeX{}book}\dots
-% In short evaluating |`{| and |`}| as numbers will not change the counter
-% \TeX{} uses to keep track of its state in an alignment, whereas gobbling a
-% brace using \cs{if_false:} will affect \TeX's state without producing any
-% real group.
-% 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}
-\group_begin:
-\tex_catcode:D `\^^@ = 2 \exp_stop_f:
-\cs_new:Npn \group_align_safe_begin:
- { \exp:w \if_false: { \fi: `^^@ \exp_stop_f: }
-\tex_catcode:D `\^^@ = 1 \exp_stop_f:
-\cs_new:Npn \group_align_safe_end:
- { \exp:w `^^@ \if_false: } \fi: \exp_stop_f: }
-\group_end:
-% \end{macrocode}
-% \end{macro}
-%
-% \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}.
-% \end{macro}
-% \end{macro}
-%
-% \begin{macrocode}
-%</package>
-% \end{macrocode}
-%
-% \end{implementation}
-%
-% \PrintIndex