summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-05-13 21:56:47 +0000
committerKarl Berry <karl@freefriends.org>2018-05-13 21:56:47 +0000
commite6d38f40f0132914020c723840be3489c4b692f0 (patch)
treedac2c281e93cba461b3ff2c1e4b8e34aad401716 /Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
parent55be422dc01e60cfae781a9a4a310a96c9e99256 (diff)
l3 (13may18)
git-svn-id: svn://tug.org/texlive/trunk@47705 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prg.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx107
1 files changed, 77 insertions, 30 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
index 74accffcc5c..6717b23a484 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 2018-04-30}
+% \date{Released 2018-05-12}
%
% \maketitle
%
@@ -484,13 +484,13 @@
% expression.
% \end{function}
%
-% \begin{function}[EXP, updated = 2017-07-15]{\bool_xor_p:nn}
+% \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
-% operator.
+% expressions. There is no infix operation for this logical operation.
% \end{function}
%
% \section{Logical loops}
@@ -862,15 +862,24 @@
% \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.
+% argument the meaning \cs{c_true_bool} or \cs{c_false_bool}. Again,
+% we include some checking code. It is important to evaluate the
+% expression before applying the \tn{chardef} primitive, because that
+% primitive sets the left-hand side to \cs{scan_stop:} before looking
+% for the right-hand side.
% \begin{macrocode}
\__kernel_patch:nnNNpn { \__kernel_chk_var_local:N #1 } { }
\cs_new_protected:Npn \bool_set:Nn #1#2
- { \tex_chardef:D #1 = \bool_if_p:n {#2} }
+ {
+ \exp_last_unbraced:NNNf
+ \tex_chardef:D #1 = { \bool_if_p:n {#2} }
+ }
\__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { }
\cs_new_protected:Npn \bool_gset:Nn #1#2
- { \tex_global:D \tex_chardef:D #1 = \bool_if_p:n {#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}
@@ -1004,21 +1013,31 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP]{\bool_if_p:n}
-% First issue a \cs{group_align_safe_begin:} as we are using |&&| as
+% \begin{macro}[EXP]{\bool_if_p:n, \@@_if_p:n, \@@_if_p_aux:w}
+% To speed up the case of a single predicate, \texttt{f}-expand and
+% check whether the result is one token (possibly surrounded by
+% spaces), which must be \cs{c_true_bool} or \cs{c_false_bool}. We
+% use a version of \cs{tl_if_single:nTF} optimized for speed since we
+% know that an empty~|#1| is an error. The auxiliary
+% \cs{@@_if_p_aux:w} removes the trailing parenthesis and gets rid of
+% any space. For the general case, first issue a
+% \cs{group_align_safe_begin:} as we are using |&&| as
% syntax shorthand for the And operation and we need to hide it for
% \TeX{}. This group is closed after \cs{@@_get_next:NN} returns
% \cs{c_true_bool} or \cs{c_false_bool}. That function requires the
% trailing parenthesis to know where the expression ends.
% \begin{macrocode}
-\cs_new:Npn \bool_if_p:n #1
+\cs_new:Npn \bool_if_p:n { \exp_args:Nf \@@_if_p:n }
+\cs_new:Npn \@@_if_p:n #1
{
+ \tl_if_empty:oT { \use_none:nn #1 . } { \@@_if_p_aux:w }
\group_align_safe_begin:
\exp_after:wN
\group_align_safe_end:
\exp:w \exp_end_continue_f:w % (
\@@_get_next:NN \use_i:nnnn #1 )
}
+\cs_new:Npn \@@_if_p_aux:w #1 \use_i:nnnn #2#3 {#2}
% \end{macrocode}
% \end{macro}
%
@@ -1163,13 +1182,21 @@
% is \texttt{false}. If the end is reached without finding any
% \texttt{false} expression, then the result is \texttt{true}.
% \begin{macrocode}
-\prg_new_conditional:Npnn \bool_lazy_all:n #1 { p , T , F , TF }
+\cs_new:Npn \bool_lazy_all_p:n #1
{ \@@_lazy_all:n #1 \q_recursion_tail \q_recursion_stop }
+\prg_new_conditional:Npnn \bool_lazy_all:n #1 { T , F , TF }
+ {
+ \if_predicate:w \bool_lazy_all_p:n {#1}
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
\cs_new:Npn \@@_lazy_all:n #1
{
- \quark_if_recursion_tail_stop_do:nn {#1} { \prg_return_true: }
+ \quark_if_recursion_tail_stop_do:nn {#1} { \c_true_bool }
\bool_if:nF {#1}
- { \use_i_delimit_by_q_recursion_stop:nw { \prg_return_false: } }
+ { \use_i_delimit_by_q_recursion_stop:nw { \c_false_bool } }
\@@_lazy_all:n
}
% \end{macrocode}
@@ -1179,12 +1206,18 @@
% \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 }
{
- \bool_if:nTF {#1}
- { \bool_if:nTF {#2} { \prg_return_true: } { \prg_return_false: } }
- { \prg_return_false: }
+ \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}
@@ -1196,13 +1229,21 @@
% is \texttt{true}. If the end is reached without finding any
% \texttt{true} expression, then the result is \texttt{false}.
% \begin{macrocode}
-\prg_new_conditional:Npnn \bool_lazy_any:n #1 { p , T , F , TF }
+\cs_new:Npn \bool_lazy_any_p:n #1
{ \@@_lazy_any:n #1 \q_recursion_tail \q_recursion_stop }
+\prg_new_conditional:Npnn \bool_lazy_any:n #1 { T , F , TF }
+ {
+ \if_predicate:w \bool_lazy_any_p:n {#1}
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
\cs_new:Npn \@@_lazy_any:n #1
{
- \quark_if_recursion_tail_stop_do:nn {#1} { \prg_return_false: }
+ \quark_if_recursion_tail_stop_do:nn {#1} { \c_false_bool }
\bool_if:nT {#1}
- { \use_i_delimit_by_q_recursion_stop:nw { \prg_return_true: } }
+ { \use_i_delimit_by_q_recursion_stop:nw { \c_true_bool } }
\@@_lazy_any:n
}
% \end{macrocode}
@@ -1215,9 +1256,12 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \bool_lazy_or:nn #1#2 { p , T , F , TF }
{
- \bool_if:nTF {#1}
- { \prg_return_true: }
- { \bool_if:nTF {#2} { \prg_return_true: } { \prg_return_false: } }
+ \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}
@@ -1233,16 +1277,19 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\bool_xor_p:nn}
+% \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}
-\cs_new:Npn \bool_xor_p:nn #1#2
+\prg_new_conditional:Npnn \bool_xor:nn #1#2 { p , T , F , TF }
{
- \int_compare:nNnTF { \bool_if_p:n {#1} } = { \bool_if_p:n {#2} }
- \c_false_bool
- \c_true_bool
+ \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}
@@ -1523,9 +1570,9 @@
% are always brace balanced.
% \begin{macrocode}
\cs_new:Npn \group_align_safe_begin:
- { \if_int_compare:w \if_false: { \fi: `} = \c_zero \fi: }
+ { \if_int_compare:w \if_false: { \fi: `} = \c_zero_int \fi: }
\cs_new:Npn \group_align_safe_end:
- { \if_int_compare:w `{ = \c_zero } \fi: }
+ { \if_int_compare:w `{ = \c_zero_int } \fi: }
% \end{macrocode}
% \end{macro}
%