[latex3-commits] [git/LaTeX3-latex3-latex3] scan-quark: Add \__kernel_quark_conditional_generate:NNnn for branching quark conditionals (233b7d0b6)
PhelypeOleinik
tex.phelype at gmail.com
Thu Mar 19 15:50:35 CET 2020
Repository : https://github.com/latex3/latex3
On branch : scan-quark
Link : https://github.com/latex3/latex3/commit/233b7d0b634eb7e5baf06deaaf9a5b775ecd06b7
>---------------------------------------------------------------
commit 233b7d0b634eb7e5baf06deaaf9a5b775ecd06b7
Author: PhelypeOleinik <tex.phelype at gmail.com>
Date: Thu Mar 19 11:50:35 2020 -0300
Add \__kernel_quark_conditional_generate:NNnn for branching quark conditionals
>---------------------------------------------------------------
233b7d0b634eb7e5baf06deaaf9a5b775ecd06b7
l3kernel/l3quark.dtx | 301 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 188 insertions(+), 113 deletions(-)
diff --git a/l3kernel/l3quark.dtx b/l3kernel/l3quark.dtx
index 166d2e4be..61db72192 100644
--- a/l3kernel/l3quark.dtx
+++ b/l3kernel/l3quark.dtx
@@ -486,8 +486,95 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[pTF]{\quark_if_nil:N}
+% \UnitTested
+% \begin{macro}[pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
+% \UnitTested
+% Here we test if we found a special quark as the first argument.
+% We better start with \cs{q_no_value} as the first argument since
+% the whole thing may otherwise loop if |#1| is wrongly given
+% a string like |aabc| instead of a single token.\footnote{It may
+% still loop in special circumstances however!}
+% \begin{macrocode}
+\prg_new_conditional:Npnn \quark_if_nil:N #1 { p, T , F , TF }
+ {
+ \if_meaning:w \q_nil #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\prg_new_conditional:Npnn \quark_if_no_value:N #1 { p, T , F , TF }
+ {
+ \if_meaning:w \q_no_value #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\prg_generate_conditional_variant:Nnn \quark_if_no_value:N
+ { c } { p , T , F , TF }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\quark_if_nil:n, \quark_if_nil:V, \quark_if_nil:o}
+% \UnitTested
+% \begin{macro}[pTF]{\quark_if_no_value:n}
+% \UnitTested
+% \begin{macro}{\@@_if_nil:w, \@@_if_no_value:w}
+% \begin{macro}[EXP]{\@@_if_empty_if:o}
+% Let us explain |\quark_if_nil:n(TF)|. Expanding \cs{@@_if_nil:w}
+% once is safe thanks to the trailing \cs{q_nil} |??!|. The result of
+% expanding once is empty if and only if both delimited arguments |#1|
+% and~|#2| are empty and |#3|~is delimited by the last tokens~|?!|.
+% Thanks to the leading~|{}|, the argument~|#1| is empty if and only
+% if the argument of \cs{quark_if_nil:n} starts with \cs{q_nil}. The
+% argument~|#2| is empty if and only if this \cs{q_nil} is followed
+% immediately by~|?| or by~|{}?|, coming either from the trailing
+% tokens in the definition of \cs{quark_if_nil:n}, or from its
+% argument. In the first case, \cs{@@_if_nil:w} is followed by
+% |{}\q_nil| |{}?| |!\q_nil|~|??!|, hence |#3|~is delimited by the
+% final~|?!|, and the test returns \texttt{true} as wanted. In the
+% second case, the result is not empty since the first~|?!| in the
+% definition of \cs{quark_if_nil:n} stop~|#3|. The auxiliary here
+% is the same as \cs{__tl_if_empty_if:o}, with the same comments
+% applying.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \quark_if_nil:n #1 { p, T , F , TF }
+ {
+ \@@_if_empty_if:o
+ { \@@_if_nil:w {} #1 {} ? ! \q_nil ? ? ! }
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new:Npn \@@_if_nil:w #1 \q_nil #2 ? #3 ? ! { #1 #2 }
+\prg_new_conditional:Npnn \quark_if_no_value:n #1 { p, T , F , TF }
+ {
+ \@@_if_empty_if:o
+ { \@@_if_no_value:w {} #1 {} ? ! \q_no_value ? ? ! }
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new:Npn \@@_if_no_value:w #1 \q_no_value #2 ? #3 ? ! { #1 #2 }
+\prg_generate_conditional_variant:Nnn \quark_if_nil:n
+ { V , o } { p , TF , T , F }
+\cs_new:Npn \@@_if_empty_if:o #1
+ {
+ \exp_after:wN \if_meaning:w \exp_after:wN \q_nil
+ \__kernel_tl_to_str:w \exp_after:wN {#1} \q_nil
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}{\__kernel_quark_test_generate:NNNn}
-% \begin{macro}{\@@_test_generate_aux:nnNN, \@@_test_generate_choose:nN }
% The function \cs{__kernel_quark_test_generate:NNNn} defines |#1|
% in a similar way as \cs[no-index]{quark_if_recursion_tail_stop(_do):(N|n)(n)}.
% using |#2| (as \cs{q_recursion_tail}) as the test quark and |#3|
@@ -506,25 +593,46 @@
% \item[\texttt{:NN}:~] defines \cs{quark_if_recursion_tail_break:NN}
% \end{description}
% Any other signature causes an error, as does a function without signature.
+%
+% \begin{macro}{\__kernel_quark_conditional_generate:NNnn}
+% Similar to \cs{__kernel_quark_test_generate:NNNn}, but defines
+% quark branching conditionals like \cs{quark_if_nil:nTF}
+% using |#2| as the test quark, |#3| as the name-space to define
+% auxiliaries, and |#4| is the list of conditional variants to define.
+%
+% There are only two cases here:
+% \begin{description}
+% \item[\texttt{:n}:~] defines \cs[no-index]{quark_if_nil:n(TF)}
+% \item[\texttt{:N}:~] defines \cs[no-index]{quark_if_nil:N(TF)}
+% \end{description}
+% Any other signature causes an error, as does a function without signature.
+%
+% \begin{macro}{\@@_test_generate_aux:nnNN, \@@_test_generate_choose:nN }
% \begin{macrocode}
\cs_new_protected:Npn \__kernel_quark_test_generate:NNNn #1
{
\exp_last_unbraced:Nf \@@_test_generate_aux:nnNN
\cs_split_function:N #1
- #1
+ #1 { test }
+ }
+\cs_new_protected:Npn \__kernel_quark_conditional_generate:NNnn #1
+ {
+ \exp_last_unbraced:Nf \@@_test_generate_aux:nnNN
+ \cs_split_function:N #1
+ #1 { conditional }
}
\cs_new_protected:Npn \@@_test_generate_aux:nnNN #1 #2 #3 #4
{
\reverse_if:N \tex_ifodd:D #3
\__kernel_msg_error:nnx { kernel } { missing-colon }
{ \token_to_str:N #4 }
- \exp_after:wN \use_none:nnnnn
+ \exp_after:wN \use_none:nnnnnn
\fi:
\use:n { \@@_test_generate_choose:nN {#2} #4 }
}
-\cs_new_protected:Npn \@@_test_generate_choose:nN #1 #2
+\cs_new_protected:Npn \@@_test_generate_choose:nN #1 #2 #3
{
- \cs_if_exist_use:cTF { @@_test_generate_#1:NNNn } {#2}
+ \cs_if_exist_use:cTF { @@_#3_generate_#1:NNNn } {#2}
{
\__kernel_msg_error:nnxx { kernel } { invalid-quark-function }
{ \token_to_str:N #2 } {#1}
@@ -534,6 +642,7 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{
% \@@_test_generate_n:NNNn, \@@_test_generate_nn:NNNn,
@@ -543,39 +652,39 @@
% These macros implement the six possibilities mentioned above, passing
% the right arguments to \cs{@@_test_generate_aux_do:nNNnnnn},
% which defines some auxiliaries, and then to
-% \cs{@@_test_generate_define_tl:NNNNn} (|:n(n)| variants) or to
-% \cs{@@_test_generate_define_ifx:NNNNn} (|:N(n)|) which define the
+% \cs{@@_test_generate_define_tl:nNNNNN} (|:n(n)| variants) or to
+% \cs{@@_test_generate_define_ifx:nNNNNN} (|:N(n)|) which define the
% main conditionals.
% \begin{macrocode}
\cs_new_protected:Npn \@@_test_generate_n:NNNn #1 #2 #3 #4
{
\@@_test_generate_aux_do:nNNnnnn {#4} #2 #3 { none } { } { } { }
- \@@_test_generate_define_tl:NNNNn #1 { }
+ \@@_test_generate_define_tl:nNNNNN #1 { }
}
\cs_new_protected:Npn \@@_test_generate_nn:NNNn #1 #2 #3 #4
{
\@@_test_generate_aux_do:nNNnnnn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_test_generate_define_tl:NNNNn #1 { \use_none:n }
+ \@@_test_generate_define_tl:nNNNNN #1 { \use_none:n }
}
\cs_new_protected:Npn \@@_test_generate_nN:NNNn #1 #2 #3 #4
{
\@@_test_generate_aux_do:nNNnnnn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_test_generate_define_break_tl:NNNNn #1 { }
+ \@@_test_generate_define_break_tl:nNNNNN #1 { }
}
\cs_new_protected:Npn \@@_test_generate_N:NNNn #1 #2 #3 #4
{
\@@_test_generate_aux_do:nNNnnnn {#4} #2 #3 { none } { } { } { }
- \@@_test_generate_define_ifx:NNNNn #1 { }
+ \@@_test_generate_define_ifx:nNNNNN #1 { }
}
\cs_new_protected:Npn \@@_test_generate_Nn:NNNn #1 #2 #3 #4
{
\@@_test_generate_aux_do:nNNnnnn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_test_generate_define_ifx:NNNNn #1 { \use_none:n }
+ \@@_test_generate_define_ifx:nNNNNN #1 { \use_none:n }
}
\cs_new_protected:Npn \@@_test_generate_NN:NNNn #1 #2 #3 #4
{
\@@_test_generate_aux_do:nNNnnnn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_test_generate_define_break_ifx:NNNNn #1 { }
+ \@@_test_generate_define_break_ifx:nNNNNN #1 { }
}
% \end{macrocode}
% \end{macro}
@@ -586,8 +695,8 @@
% }
% \cs{@@_test_generate_aux_do:nNNnnnn} makes the conrol sequence names
% which will be used by \cs{@@_test_define_aux:NNNnnN}, and then later
-% by \cs{@@_test_generate_define_tl:NNNNn} or
-% \cs{@@_test_generate_define_ifx:NNNNn}. The control sequences defined
+% by \cs{@@_test_generate_define_tl:nNNNNN} or
+% \cs{@@_test_generate_define_ifx:nNNNNN}. The control sequences defined
% here are analogous to \cs{@@_if_recursion_tail:w} and to
% \cs[no-index]{use_(none|i)_delimit_by_q_recursion_stop:(|n)w}.
%
@@ -621,17 +730,17 @@
% \end{macro}
%
% \begin{macro}{
-% \@@_test_generate_define_tl:NNNNn,
-% \@@_test_generate_define_ifx:NNNNn
+% \@@_test_generate_define_tl:nNNNNN,
+% \@@_test_generate_define_ifx:nNNNNN
% }
% \begin{macro}{
-% \@@_test_generate_define_break_tl:NNNNn,
-% \@@_test_generate_define_break_ifx:NNNNn
+% \@@_test_generate_define_break_tl:nNNNNN,
+% \@@_test_generate_define_break_ifx:nNNNNN
% }
% Finally, these two macros define the main conditional function using
% what's been set up before.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_test_generate_define_tl:NNNNn #1 #2 #3 #4 #5 #6
+\cs_new_protected:Npn \@@_test_generate_define_tl:nNNNNN #1 #2 #3 #4 #5 #6
{
\cs_new:Npn #5 #1
{
@@ -640,7 +749,7 @@
{#3} {#6}
}
}
-\cs_new_protected:Npn \@@_test_generate_define_ifx:NNNNn #1 #2 #3 #4 #5 #6
+\cs_new_protected:Npn \@@_test_generate_define_ifx:nNNNNN #1 #2 #3 #4 #5 #6
{
\cs_new:Npx #5 #1
{
@@ -651,14 +760,68 @@
\exp_not:N \fi:
}
}
-\cs_new_protected:Npn \@@_test_generate_define_break_tl:NNNNn #1 #2 #3
- { \@@_test_generate_define_tl:NNNNn {##1##2} #2 {##2} }
-\cs_new_protected:Npn \@@_test_generate_define_break_ifx:NNNNn #1 #2 #3
- { \@@_test_generate_define_ifx:NNNNn {##1##2} #2 {##2} }
+\cs_new_protected:Npn \@@_test_generate_define_break_tl:nNNNNN #1 #2 #3
+ { \@@_test_generate_define_tl:nNNNNN {##1##2} #2 {##2} }
+\cs_new_protected:Npn \@@_test_generate_define_break_ifx:nNNNNN #1 #2 #3
+ { \@@_test_generate_define_ifx:nNNNNN {##1##2} #2 {##2} }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
+% \begin{macro}{
+% \@@_conditional_generate_n:NNNn,
+% \@@_conditional_generate_N:NNNn,
+% }
+% These macros implement the two possibilities for branching quark
+% conditionals, passing
+% the right arguments to \cs{@@_conditional_generate_aux_do:nN},
+% which defines some auxiliaries, and then to
+% \cs{@@_conditional_generate_define:nNNNNn} which defines the
+% main conditionals.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_conditional_generate_n:NNNn #1 #2 #3
+ {
+ \@@_conditional_generate_aux_do:nN {#3} #2
+ \@@_conditional_generate_define:nNNNNn #1 \use_i:nn
+ }
+\cs_new_protected:Npn \@@_conditional_generate_N:NNNn #1 #2 #3
+ {
+ \@@_conditional_generate_aux_do:nN {#3} #2
+ \@@_conditional_generate_define:nNNNNn #1 \use_ii:nn
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_conditional_generate_aux_do:nN,
+% \@@_conditional_define_aux:NN,
+% \@@_conditional_generate_define:nNNNNn
+% }
+% Similar to the previous macros, but branching conditionals only require
+% one auxiliary, so we take a shortcut.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_conditional_generate_aux_do:nN #1 #2
+ {
+ \exp_args:Nc \@@_conditional_define_aux:NN
+ { #1 _if_ \@@_get_name:N #2 :w } #2
+ }
+\cs_new_protected:Npn \@@_conditional_define_aux:NN #1 #2 #3
+ {
+ \cs_gset:Npn #1 ##1 #2 ##2 ? ##3 ?! { ##1 ##2 }
+ #3 {##1} #1 #2
+ }
+\cs_new_protected:Npn \@@_conditional_generate_define:nNNNNn #1 #2 #3 #4 #5 #6
+ {
+ \exp_args:Nno \use:n { \prg_new_conditional:Npnn #4 #1 {#6} }
+ {
+ #5 { \@@_if_empty_if:o { #2 {} ##1 {} ?! #3 ??! } }
+ { \if_meaning:w #3 ##1 }
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[EXP]{\@@_get_name:N}
% \begin{macro}[EXP]{
% \@@_get_name_aux:w,
@@ -696,94 +859,6 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[pTF]{\quark_if_nil:N}
-% \UnitTested
-% \begin{macro}[pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
-% \UnitTested
-% Here we test if we found a special quark as the first argument.
-% We better start with \cs{q_no_value} as the first argument since
-% the whole thing may otherwise loop if |#1| is wrongly given
-% a string like |aabc| instead of a single token.\footnote{It may
-% still loop in special circumstances however!}
-% \begin{macrocode}
-\prg_new_conditional:Npnn \quark_if_nil:N #1 { p, T , F , TF }
- {
- \if_meaning:w \q_nil #1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\prg_new_conditional:Npnn \quark_if_no_value:N #1 { p, T , F , TF }
- {
- \if_meaning:w \q_no_value #1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\prg_generate_conditional_variant:Nnn \quark_if_no_value:N
- { c } { p , T , F , TF }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\quark_if_nil:n, \quark_if_nil:V, \quark_if_nil:o}
-% \UnitTested
-% \begin{macro}[pTF]{\quark_if_no_value:n}
-% \UnitTested
-% \begin{macro}{\@@_if_nil:w, \@@_if_no_value:w}
-% \begin{macro}[EXP]{\@@_if_empty_if:o}
-% Let us explain |\quark_if_nil:n(TF)|. Expanding \cs{@@_if_nil:w}
-% once is safe thanks to the trailing \cs{q_nil} |??!|. The result of
-% expanding once is empty if and only if both delimited arguments |#1|
-% and~|#2| are empty and |#3|~is delimited by the last tokens~|?!|.
-% Thanks to the leading~|{}|, the argument~|#1| is empty if and only
-% if the argument of \cs{quark_if_nil:n} starts with \cs{q_nil}. The
-% argument~|#2| is empty if and only if this \cs{q_nil} is followed
-% immediately by~|?| or by~|{}?|, coming either from the trailing
-% tokens in the definition of \cs{quark_if_nil:n}, or from its
-% argument. In the first case, \cs{@@_if_nil:w} is followed by
-% |{}\q_nil| |{}?| |!\q_nil|~|??!|, hence |#3|~is delimited by the
-% final~|?!|, and the test returns \texttt{true} as wanted. In the
-% second case, the result is not empty since the first~|?!| in the
-% definition of \cs{quark_if_nil:n} stop~|#3|. The auxiliary here
-% is the same as \cs{__tl_if_empty_if:o}, with the same comments
-% applying.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \quark_if_nil:n #1 { p, T , F , TF }
- {
- \@@_if_empty_if:o
- { \@@_if_nil:w {} #1 {} ? ! \q_nil ? ? ! }
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\cs_new:Npn \@@_if_nil:w #1 \q_nil #2 ? #3 ? ! { #1 #2 }
-\prg_new_conditional:Npnn \quark_if_no_value:n #1 { p, T , F , TF }
- {
- \@@_if_empty_if:o
- { \@@_if_no_value:w {} #1 {} ? ! \q_no_value ? ? ! }
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\cs_new:Npn \@@_if_no_value:w #1 \q_no_value #2 ? #3 ? ! { #1 #2 }
-\prg_generate_conditional_variant:Nnn \quark_if_nil:n
- { V , o } { p , TF , T , F }
-\cs_new:Npn \@@_if_empty_if:o #1
- {
- \exp_after:wN \if_meaning:w \exp_after:wN \q_nil
- \__kernel_tl_to_str:w \exp_after:wN {#1} \q_nil
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
% \subsection{Scan marks}
%
% \begin{macrocode}
More information about the latex3-commits
mailing list.