diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prg.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3prg.dtx | 107 |
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} % |