summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prg.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx385
1 files changed, 130 insertions, 255 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
index b54376773d6..67af5299b7c 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
@@ -41,7 +41,7 @@
% }^^A
% }
%
-% \date{Released 2017/07/15}
+% \date{Released 2017/07/19}
%
% \maketitle
%
@@ -270,7 +270,7 @@
% Sets \meta{boolean_1} to the current value of \meta{boolean_2}.
% \end{function}
%
-% \begin{function}[updated = 2012-07-08]
+% \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}
@@ -296,7 +296,7 @@
% Displays the logical truth of the \meta{boolean} on the terminal.
% \end{function}
%
-% \begin{function}[added = 2012-02-09, updated = 2015-08-07]{\bool_show:n}
+% \begin{function}[added = 2012-02-09, updated = 2017-07-15]{\bool_show:n}
% \begin{syntax}
% \cs{bool_show:n} \Arg{boolean expression}
% \end{syntax}
@@ -311,7 +311,7 @@
% Writes the logical truth of the \meta{boolean} in the log file.
% \end{function}
%
-% \begin{function}[added = 2014-08-22, updated = 2015-08-07]{\bool_log:n}
+% \begin{function}[added = 2014-08-22, updated = 2017-07-15]{\bool_log:n}
% \begin{syntax}
% \cs{bool_log:n} \Arg{boolean expression}
% \end{syntax}
@@ -354,8 +354,7 @@
% \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
+% \verb"||"). In addition to this, parentheses can be used to isolate
% sub-expressions. For example,
% \begin{verbatim}
% \int_compare_p:n { 1 = 1 } &&
@@ -368,18 +367,22 @@
% \end{verbatim}
% is a valid boolean expression.
%
-% At present, the infix operators |&&| and \verb"||" perform lazy
-% evaluation, but this will change in the near future.
% Contrarily to some other programming languages, the operators |&&| and
-% \verb"||" will evaluate both operands in all cases, even when the first
+% \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. Indeed, a lazy parser can get confused if |&&| and
-% \verb"||" appear as (unbraced) arguments of some predicates.
+% 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
@@ -405,7 +408,7 @@
% 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 = 2012-07-08]{\bool_if:n}
+% \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}
@@ -418,8 +421,8 @@
% |!| (\enquote{Not}) and parentheses. The logical Not applies to
% the next predicate or group.
% \end{function}
-%
-% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_all:n}
+%
+% \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}
@@ -433,7 +436,7 @@
% when there are only two \meta{boolean expressions}.
% \end{function}
%
-% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_and:nn}
+% \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}
@@ -446,7 +449,7 @@
% than two \meta{boolean expressions}.
% \end{function}
%
-% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_any:n}
+% \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}
@@ -460,7 +463,7 @@
% when there are only two \meta{boolean expressions}.
% \end{function}
%
-% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_or:nn}
+% \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}
@@ -473,7 +476,7 @@
% than two \meta{boolean expressions}.
% \end{function}
%
-% \begin{function}[EXP, updated = 2012-07-08]{\bool_not_p:n}
+% \begin{function}[EXP, updated = 2017-07-15]{\bool_not_p:n}
% \begin{syntax}
% \cs{bool_not_p:n} \Arg{boolean expression}
% \end{syntax}
@@ -481,7 +484,7 @@
% expression.
% \end{function}
%
-% \begin{function}[EXP, updated = 2012-07-08]{\bool_xor_p:nn}
+% \begin{function}[EXP, updated = 2017-07-15]{\bool_xor_p:nn}
% \begin{syntax}
% \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
% \end{syntax}
@@ -538,7 +541,7 @@
% until the \meta{boolean} is \texttt{false}.
% \end{function}
%
-% \begin{function}[rEXP, updated = 2012-07-08]{\bool_do_until:nn}
+% \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}
@@ -550,7 +553,7 @@
% \texttt{true}.
% \end{function}
%
-% \begin{function}[rEXP, updated = 2012-07-08]{\bool_do_while:nn}
+% \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}
@@ -562,7 +565,7 @@
% \texttt{false}.
% \end{function}
%
-% \begin{function}[rEXP, updated = 2012-07-08]{\bool_until_do:nn}
+% \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}
@@ -574,7 +577,7 @@
% then loops until the \meta{boolean expression} is \texttt{true}.
% \end{function}
%
-% \begin{function}[rEXP, updated = 2012-07-08]{\bool_while_do:nn}
+% \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}
@@ -808,16 +811,16 @@
% make sure the boolean exists. This is needed because booleans are
% not based on token lists nor on \TeX{} registers.
% \begin{macrocode}
-\__debug_patch:nnNw { \__chk_if_exist_var:N #1 } { }
+\__debug_patch:nnNNpn { \__debug_chk_var_exist:N #1 } { }
\cs_new_protected:Npn \bool_set_true:N #1
{ \cs_set_eq:NN #1 \c_true_bool }
-\__debug_patch:nnNw { \__chk_if_exist_var:N #1 } { }
+\__debug_patch:nnNNpn { \__debug_chk_var_exist:N #1 } { }
\cs_new_protected:Npn \bool_set_false:N #1
{ \cs_set_eq:NN #1 \c_false_bool }
-\__debug_patch:nnNw { \__chk_if_exist_var:N #1 } { }
+\__debug_patch:nnNNpn { \__debug_chk_var_exist:N #1 } { }
\cs_new_protected:Npn \bool_gset_true:N #1
{ \cs_gset_eq:NN #1 \c_true_bool }
-\__debug_patch:nnNw { \__chk_if_exist_var:N #1 } { }
+\__debug_patch:nnNNpn { \__debug_chk_var_exist:N #1 } { }
\cs_new_protected:Npn \bool_gset_false:N #1
{ \cs_gset_eq:NN #1 \c_false_bool }
\cs_generate_variant:Nn \bool_set_true:N { c }
@@ -852,10 +855,10 @@
% argument the meaning \cs{c_true_bool} or \cs{c_false_bool}.
% Again, we include some checking code.
% \begin{macrocode}
-\__debug_patch:nnNw { \__chk_if_exist_var:N #1 } { }
+\__debug_patch:nnNNpn { \__debug_chk_var_exist:N #1 } { }
\cs_new_protected:Npn \bool_set:Nn #1#2
{ \tex_chardef:D #1 = \bool_if_p:n {#2} }
-\__debug_patch:nnNw { \__chk_if_exist_var:N #1 } { }
+\__debug_patch:nnNNpn { \__debug_chk_var_exist:N #1 } { }
\cs_new_protected:Npn \bool_gset:Nn #1#2
{ \tex_global:D \tex_chardef:D #1 = \bool_if_p:n {#2} }
\cs_generate_variant:Nn \bool_set:Nn { c }
@@ -871,7 +874,7 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \bool_if:N #1 { p , T , F , TF }
{
- \if_meaning:w \c_true_bool #1
+ \if_bool:N #1
\prg_return_true:
\else:
\prg_return_false:
@@ -942,7 +945,8 @@
% input syntax somewhat similar to the one found in other programming
% languages with |(| and |)| for grouping, |!| for logical
% \enquote{Not}, |&&| for logical \enquote{And} and \verb"||" for
-% logical \enquote{Or}. We shall use the terms Not, And, Or, Open and
+% 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
@@ -951,9 +955,8 @@
% \begin{itemize}
% \item If an Open is seen, start evaluating a new expression using
% the Eval function and call GetNext again.
-% \item If a Not is seen, remove the |!| and call a GetNotNext
-% function, which eventually reverses the logic compared to
-% GetNext.
+% \item If 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
@@ -968,11 +971,11 @@
% seen, continue with GetNext to examine truth value of next
% boolean (sub-)expression.
% \item[\meta{false}And] Current truth value is false, logical And
-% seen, stop evaluating the predicates within this sub-expression
-% and break to the nearest Close. Then return \meta{false}.
-% \item[\meta{true}Or] Current truth value is true, logical Or
-% seen, stop evaluating the predicates within this sub-expression
-% and break to the nearest Close. Then return \meta{true}.
+% 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.
@@ -981,15 +984,6 @@
% \item[\meta{false}Close] Current truth value is false, Close
% seen, return \meta{false}.
% \end{description}
-% We introduce an additional Stop operation with the same
-% semantics as the Close operation.
-% \begin{description}
-% \item[\meta{true}Stop] Current truth value is true, return
-% \meta{true}.
-% \item[\meta{false}Stop] Current truth value is false, return
-% \meta{false}.
-% \end{description}
-% The reasons for this follow below.
% \begin{macrocode}
\prg_new_conditional:Npnn \bool_if:n #1 { T , F , TF }
{
@@ -1003,82 +997,40 @@
% \end{macro}
%
% \begin{macro}[EXP]{\bool_if_p:n}
-% \begin{macro}[EXP, aux]
-% {
-% \@@_if_left_parentheses:wwwn ,
-% \@@_if_right_parentheses:wwwn ,
-% \@@_if_or:wwwn
-% }
-% First issue a \cs{group_align_safe_begin:} as we are using |&&|
-% as syntax shorthand for the And operation and we need to hide it for
-% \TeX{}. This is closed at the end of the expression parsing
-% (see |S| below).
-%
-% Minimal (\enquote{short-circuit}) evaluation of boolean expressions
-% requires skipping to the end of the current parenthesized group when
-% \meta{true}\verb"||" is seen, but to the next \verb"||" or closing
-% parenthesis when \meta{false}|&&| is seen. To avoid having separate
-% functions for the two cases, we transform the boolean expression by
-% doubling each parenthesis and adding parenthesis around each
-% \verb"||". This ensures that |&&| binds tighter than \verb"||".
-%
-% The replacement is done in three passes, for left and right
-% parentheses and for \verb"||". At each pass, the part of the
-% expression that has been transformed is stored before \cs{q_nil},
-% the rest lies until the first \cs{q_mark}, followed by an empty
-% brace group. A trailing marker ensures that the auxiliaries'
-% delimited arguments do not run-away. As long as the delimiter
-% matches inside the expression, material is moved before \cs{q_nil}
-% and we continue. Afterwards, the trailing marker is taken as a
-% delimiter, |#4| is the next auxiliary, immediately followed by a new
-% \cs{q_nil} delimiter, which indicates that nothing has been treated
-% at this pass. The last step calls \cs{@@_if_parse:NNNww} which
-% cleans up and triggers the evaluation of the expression itself.
+% 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 #1
{
\group_align_safe_begin:
- \@@_if_left_parentheses:wwwn \q_nil
- #1 \q_mark { }
- ( \q_mark { \@@_if_right_parentheses:wwwn \q_nil }
- ) \q_mark { \@@_if_or:wwwn \q_nil }
- || \q_mark \@@_if_parse:NNNww
- \q_stop
- }
-\cs_new:Npn \@@_if_left_parentheses:wwwn #1 \q_nil #2 ( #3 \q_mark #4
- { #4 \@@_if_left_parentheses:wwwn #1 #2 (( \q_nil #3 \q_mark {#4} }
-\cs_new:Npn \@@_if_right_parentheses:wwwn #1 \q_nil #2 ) #3 \q_mark #4
- { #4 \@@_if_right_parentheses:wwwn #1 #2 )) \q_nil #3 \q_mark {#4} }
-\cs_new:Npn \@@_if_or:wwwn #1 \q_nil #2 || #3 \q_mark #4
- { #4 \@@_if_or:wwwn #1 #2 )||( \q_nil #3 \q_mark {#4} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP, aux]{\@@_if_parse:NNNww}
-% After removing extra tokens from the transformation phase, start
-% evaluating. At the end, we need to finish the special
-% \texttt{align_safe} group before finally
-% returning a \cs{c_true_bool} or \cs{c_false_bool} as there might
-% otherwise be something left in front in the input stream. For this
-% we call the Stop operation, denoted simply by a |S| following the
-% last Close operation.
-% \begin{macrocode}
-\cs_new:Npn \@@_if_parse:NNNww #1#2#3#4 \q_mark #5 \q_stop
- {
- \__bool_get_next:NN \use_i:nn (( #4 )) S
+ \exp_after:wN
+ \group_align_safe_end:
+ \exp:w \exp_end_continue_f:w % (
+ \@@_get_next:NN \use_i:nnnn #1 )
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_get_next:NN}
-% The GetNext operation. This is a switch: if what follows is neither
-% |!| nor |(|, we assume it is a predicate. The first argument is
-% \cs{use_ii:nn} if the logic must eventually be reversed (after a
-% |!|), otherwise it is \cs{use_i:nn}. This function eventually
-% expand to the truth value \cs{c_true_bool} or \cs{c_false_bool} of
-% the expression which follows until the next unmatched closing
-% parenthesis.
+% 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
{
@@ -1094,23 +1046,31 @@
% \end{macro}
%
% \begin{macro}[aux]{\@@_!:Nw}
-% The Not operation reverses the logic: discard the |!| token and call
-% the GetNext operation with its first argument reversed.
+% 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:nn \use_i:nn }
+ {
+ \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}[aux]{\@@_(:Nw}
-% The Open operation starts a sub-expression after discarding the
-% token. This is done by calling GetNext, with a post-processing step
-% which looks for And, Or or Close afterwards.
+% 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:nn
+ \__int_value:w \@@_get_next:NN \use_i:nnnn
}
% \end{macrocode}
% \end{macro}
@@ -1118,8 +1078,8 @@
% \begin{macro}[aux]{\@@_p:Nw}
% If what follows GetNext is neither |!| nor |(|, evaluate the
% predicate using the primitive \cs{__int_value:w}. The canonical
-% true and false values have numerical values $1$ and $0$
-% respectively. Look for And, Or or Close afterwards.
+% \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 }
@@ -1127,149 +1087,63 @@
% \end{macro}
%
% \begin{macro}[aux]{\@@_choose:NNN}
-% Branching the eight-way switch. The arguments are 1: \cs{use_i:nn}
-% or \cs{use_ii:nn}, 2: $0$ or $1$ encoding the current truth value,
-% 3: the next operation, And, Or, Close or Stop. If |#1| is
-% \cs{use_ii:nn}, the logic of |#2| must be reversed.
+% \begin{macro}[aux]+\@@_)_0:+
+% \begin{macro}[aux]+\@@_)_1:+
+% \begin{macro}[aux]+\@@_)_2:+
+% \begin{macro}[aux]+\@@_&_0:+
+% \begin{macro}[aux]+\@@_&_1:+
+% \begin{macro}[aux]+\@@_&_2:+
+% \begin{macro}[aux]+\@@_|_0:+
+% \begin{macro}[aux]+\@@_|_1:+
+% \begin{macro}[aux]+\@@_|_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
{
- @@_ #3 _
- #1 #2 { \if_meaning:w 0 #2 1 \else: 0 \fi: }
- :w
+ @@_ \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}
-%
-% \begin{macro}[aux]
-% {
-% \@@_)_0:w,
-% \@@_)_1:w,
-% \@@_S_0:w,
-% \@@_S_1:w,
-% }
-% Closing a group is just about returning the result. The Stop
-% operation is similar except it closes the special alignment group
-% before returning the boolean.
-% \begin{macrocode}
-\cs_new:cpn { @@_)_0:w } { \c_false_bool }
-\cs_new:cpn { @@_)_1:w } { \c_true_bool }
-\cs_new:cpn { @@_S_0:w } { \group_align_safe_end: \c_false_bool }
-\cs_new:cpn { @@_S_1:w } { \group_align_safe_end: \c_true_bool }
-% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}[aux]+\@@_&_1:w+
-% \begin{macro}[aux]+\@@_|_0:w+
-% Two cases where we simply continue scanning. We must remove the
-% second |&| or \verb"|".
-% \begin{macrocode}
-\cs_new:cpn { @@_&_1:w } & { \@@_get_next:NN \use_i:nn }
-\cs_new:cpn { @@_|_0:w } | { \@@_get_next:NN \use_i:nn }
-% \end{macrocode}
% \end{macro}
% \end{macro}
-%
-% \begin{macro}[aux]+\@@_&_0:w+
-% \begin{macro}[aux]+\@@_|_1:w+
-% \begin{macro}[aux]
-% {
-% \@@_eval_skip_to_end_auxi:Nw,
-% \@@_eval_skip_to_end_auxii:Nw,
-% \@@_eval_skip_to_end_auxiii:Nw
-% }
-% When the truth value has already been decided, we have to throw away
-% the remainder of the current group as we are doing minimal
-% evaluation. This is slightly tricky as there are no braces so we
-% have to play match the |()| manually.
-% \begin{macrocode}
-\cs_new:cpn { @@_&_0:w } &
- { \@@_eval_skip_to_end_auxi:Nw \c_false_bool }
-\cs_new:cpn { @@_|_1:w } |
- { \@@_eval_skip_to_end_auxi:Nw \c_true_bool }
-% \end{macrocode}
-% There is always at least one |)| waiting, namely the outer
-% one. However, we are facing the problem that there may be more than
-% one that need to be finished off and we have to detect the correct
-% number of them. Here is a complicated example showing how this is
-% done. After evaluating the following, we realize we must skip
-% everything after the first And. Note the extra Close at the end.
-% \begin{quote}
-% |\c_false_bool && ((abc) && xyz) && ((xyz) && (def)))|
-% \end{quote}
-% First read up to the first Close. This gives us the list we first
-% read up until the first right parenthesis so we are looking at the
-% token list
-% \begin{quote}
-% |((abc|
-% \end{quote}
-% This contains two Open markers so we must remove two groups. Since
-% no evaluation of the contents is to be carried out, it doesn't
-% matter how we remove the groups as long as we wind up with the
-% correct result. We therefore first remove a |()| pair and what
-% preceded the Open -- but leave the contents as it may contain Open
-% tokens itself -- leaving
-% \begin{quote}
-% |(abc && xyz) && ((xyz) && (def)))|
-% \end{quote}
-% Another round of this gives us
-% \begin{quote}
-% |(abc && xyz|
-% \end{quote}
-% which still contains an Open so we remove another |()| pair, giving us
-% \begin{quote}
-% |abc && xyz && ((xyz) && (def)))|
-% \end{quote}
-% Again we read up to a Close and again find Open tokens:
-% \begin{quote}
-% |abc && xyz && ((xyz|
-% \end{quote}
-% Further reduction gives us
-% \begin{quote}
-% |(xyz && (def)))|
-% \end{quote}
-% and then
-% \begin{quote}
-% |(xyz && (def|
-% \end{quote}
-% with reduction to
-% \begin{quote}
-% |xyz && (def))|
-% \end{quote}
-% and ultimately we arrive at no Open tokens being skipped and we can
-% finally close the group nicely.
-% \begin{macrocode}
-%% (
-\cs_new:Npn \@@_eval_skip_to_end_auxi:Nw #1#2 )
- {
- \@@_eval_skip_to_end_auxii:Nw #1#2 ( % )
- \q_no_value \q_stop
- {#2}
- }
-% \end{macrocode}
-% If no right parenthesis, then |#3| is no_value and we are done, return
-% the boolean |#1|. If there is, we need to grab a |()| pair and then
-% recurse
-% \begin{macrocode}
-\cs_new:Npn \@@_eval_skip_to_end_auxii:Nw #1#2 ( #3#4 \q_stop #5 % )
- {
- \quark_if_no_value:NTF #3
- {#1}
- { \@@_eval_skip_to_end_auxiii:Nw #1 #5 }
- }
-% \end{macrocode}
-% Keep the boolean, throw away anything up to the |(| as it is
-% irrelevant, remove a |()| pair but remember to reinsert |#3| as it may
-% contain |(| tokens!
-% \begin{macrocode}
-\cs_new:Npn \@@_eval_skip_to_end_auxiii:Nw #1#2 ( #3 )
- { % (
- \@@_eval_skip_to_end_auxi:Nw #1#3 )
- }
-% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
@@ -1510,6 +1384,7 @@
% pool. Also, it is considerably slower than what we use here so the
% few extra csnames are well spent I would say.
% \begin{macrocode}
+\__debug_patch_args:nNNpn { { (#1) } }
\cs_new:Npn \prg_replicate:nn #1
{
\exp:w