diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3prg.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3prg.dtx | 1829 |
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 |