[latex3-commits] [git/LaTeX3-latex3-latex3] scan-quark: Enhance \__kernel_quark_test_generate:NNNn (1955297ea)

PhelypeOleinik tex.phelype at gmail.com
Thu Mar 12 03:29:01 CET 2020


Repository : https://github.com/latex3/latex3
On branch  : scan-quark
Link       : https://github.com/latex3/latex3/commit/1955297ea18733197d7ae974909b2f63505d3730

>---------------------------------------------------------------

commit 1955297ea18733197d7ae974909b2f63505d3730
Author: PhelypeOleinik <tex.phelype at gmail.com>
Date:   Wed Mar 11 23:29:01 2020 -0300

    Enhance \__kernel_quark_test_generate:NNNn


>---------------------------------------------------------------

1955297ea18733197d7ae974909b2f63505d3730
 l3kernel/l3msg.dtx   |   9 +++
 l3kernel/l3quark.dtx | 203 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 173 insertions(+), 39 deletions(-)

diff --git a/l3kernel/l3msg.dtx b/l3kernel/l3msg.dtx
index 68264ca6d..c244d06fa 100644
--- a/l3kernel/l3msg.dtx
+++ b/l3kernel/l3msg.dtx
@@ -1798,6 +1798,15 @@
 \__kernel_msg_new:nnnn { kernel } { quote-in-shell }
   { Quotes~in~shell~command~'#1'. }
   { Shell~commands~cannot~contain~quotes~("). }
+\__kernel_msg_new:nnnn { kernel } { invalid-quark-function }
+  { Quark~test~function~'#1'~is~invalid. }
+  {
+    \c__msg_coding_error_text_tl
+    LaTeX~has~been~asked~to~create~quark~test~function~'#1'~
+    with~signature~'#2',~but~that~signature~is~not~valid.
+  }
+\__kernel_msg_new:nnn { kernel } { invalid-quark }
+  { Invalid~quark~variable~'#1'. }
 \__kernel_msg_new:nnnn { kernel } { scanmark-already-defined }
   { Scan~mark~#1~already~defined. }
   {
diff --git a/l3kernel/l3quark.dtx b/l3kernel/l3quark.dtx
index fe37c251c..1c6214475 100644
--- a/l3kernel/l3quark.dtx
+++ b/l3kernel/l3quark.dtx
@@ -464,60 +464,185 @@
 % \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|
+%   (as \cs{q_recursion_stop}) as the delimiter quark. |#4| is the name-space
+%   to be used (for example |__quark|).
+%
+%   There are four possible function types which this funciton can define,
+%   and which is defined depends on the signature of the function being
+%   defined:
+%   \begin{description}
+%     \item[\texttt{:n}:~]  defines \cs{quark_if_recursion_tail_stop:n}
+%     \item[\texttt{:nn}:~] defines \cs{quark_if_recursion_tail_stop_do:nn}
+%     \item[\texttt{:N}:~]  defines \cs{quark_if_recursion_tail_stop:N}
+%     \item[\texttt{:Nn}:~] defines \cs{quark_if_recursion_tail_stop_do:Nn}
+%   \end{description}
+%   Any other signature causes an error, as does a function without signature.
+%    \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
+  }
+\cs_new_protected:Npn \@@_test_generate_aux:nnNN #1 #2 #3 #4
+  {
+    \reverse_if:N \if_int_odd:w #3
+      \__kernel_msg_error:nnx { kernel } { missing-colon }
+        { \token_to_str:N #4 }
+      \exp_after:wN \use_none:nnnnn
+    \fi:
+    \use:n { \@@_test_generate_choose:nN {#2} #4 }
+  }
+\cs_new_protected:Npn \@@_test_generate_choose:nN #1 #2
+  {
+    \cs_if_exist_use:cTF { @@_test_generate_#1:NNNn } {#2}
+      {
+        \__kernel_msg_error:nnxx { kernel } { invalid-quark-function }
+          { \token_to_str:N #2 } {#1}
+        \use_none:nnn
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \begin{macro}{
-%     \__kernel_quark_new_recursion_tail_stop:n,
-%     \__kernel_quark_new_recursion_tail_stop_do:n,
+%     \@@_test_generate_n:NNNn, \@@_test_generate_nn:NNNn,
+%     \@@_test_generate_N:NNNn, \@@_test_generate_Nn:NNNn,
 %   }
+%   These macros implement the four 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
+%   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 { }
+  }
+\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 }
+  }
+\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 { }
+  }
+\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 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+%     \@@_test_generate_aux_do:nNNnnnn,
+%     \@@_test_define_aux:NNNnnN
+%   }
+%   \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
+%   here are analogous to \cs{@@_if_recursion_tail:w} and to
+%   \cs[no-index]{use_(none|i)_delimit_by_q_recursion_stop:(|n)w}.
+%
+%   The name is composed by the name-space and the name of the quarks.
+%   Suppose \cs{__kernel_quark_test_generate:NNNn} was used with:
+%   \begin{verbatim}
+%     \__kernel_quark_test_generate:NNNn \__test_quark_tail:n
+%       \q__test_tail \q__test_stop { __test }
+%   \end{verbatim}
+%   then the first auxiliary will be \cs[no-index]{__test_if_test_tail:w},
+%   and the second one will be
+%   \cs[no-index]{__test_use_none_delimit_by_q_test_stop:w}.
+%
+%   Note that the actual quarks are \emph{not} defined here. They should
+%   be defined separately using \cs{quark_new:N}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_test_generate_aux_do:nNNnnnn #1 #2 #3 #4 #5
+  {
+    \exp_args:Ncc \@@_test_define_aux:NNNnnN
+      { #1 _if_ \@@_get_name:N #2 :w }
+      { #1 _use_ #4 _delimit_by_q_ \@@_get_name:N #3 : #5 w }
+      #2 #3
+  }
+\cs_new_protected:Npn \@@_test_define_aux:NNNnnN #1 #2 #3 #4 #5 #6 #7
+  {
+    \cs_gset:Npn #1  ##1 #3 ##2 ? ##3 ?! { ##1 ##2 }
+    \cs_gset:Npn #2  ##1 #6 #4 {#5}
+    #7 #1 #2 #3
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{
-%     \@@_new_recursion_tail_auxi:nnNNn,
-%     \@@_new_recursion_tail_auxii:NNNNNN,
+%     \@@_test_generate_define_tl:NNNNn,
+%     \@@_test_generate_define_ifx:NNNNn
 %   }
-%   Basically the same as above, but generic so that it is possible to
-%   define \cs[no-index]{quark_if_recursion_tail...} functions on-the-fly,
-%   for each module which needs them.
-%
-%   \cs{__kernel_quark_new_recursion_tail_stop:n}|{ __mod }| defines the
-%   top-level \cs[no-index]{__mod_quark_if_recursion_tail_stop:n}, and
-%   the auxiliaries \cs[no-index]{__mod_quark_if_recursion_tail:w} and
-%   \cs[no-index]{__mod_use_none_delimit_by_q_recursion_stop:w}.
-%
-%   \cs{__kernel_quark_new_recursion_tail_stop_do:n}|{ __mod }| defines the
-%   top-level \cs[no-index]{__mod_quark_if_recursion_tail_stop_do:nn}, and
-%   the auxiliaries \cs[no-index]{__mod_quark_if_recursion_tail:w} and
-%   \cs[no-index]{__mod_use_i_delimit_by_q_recursion_stop:nw}.
-%
-%   In either case, the corresponding \cs[no-index]{q__mod_recursion_tail}
-%   and \cs[no-index]{q__mod_recursion_stop} have to be manually defined.
+%   Finally, these two macros define the main conditional function using
+%   what's been set up before.
 %    \begin{macrocode}
-\cs_new_protected:Npn \__kernel_quark_new_recursion_tail_stop:n #1
+\cs_new_protected:Npn \@@_test_generate_define_tl:NNNNn #1 #2 #3 #4 #5
   {
-    \@@_new_recursion_tail_auxi:nnNNn {#1} { stop:n }
-      \use_none_delimit_by_q_recursion_stop:w \use_none:n { }
+    \cs_new:Npn #4 ##1
+      {
+        \tl_if_empty:oTF
+          { #1 {} ##1 {} ?! #3 ??! }
+          {#2} {#5}
+      }
   }
-\cs_new_protected:Npn \__kernel_quark_new_recursion_tail_stop_do:n #1
+\cs_new_protected:Npn \@@_test_generate_define_ifx:NNNNn #1 #2 #3 #4 #5
   {
-    \@@_new_recursion_tail_auxi:nnNNn {#1} { stop_do:nn }
-      \use_i_delimit_by_q_recursion_stop:nw \use:n { \use_none:n }
+    \cs_new:Npx #4 ##1
+      {
+        \exp_not:N \if_meaning:w \exp_not:N #3 ##1
+          \exp_not:n { \exp_after:wN #2 }
+          \tl_if_empty:nF {#5}
+            { \exp_not:n { \else: \exp_after:wN #5 } }
+        \exp_not:N \fi:
+      }
   }
-\cs_new_protected:Npn \@@_new_recursion_tail_auxi:nnNNn #1 #2 #3
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_name:N}
+% \begin{macro}{
+%     \@@_get_name_aux:w,
+%     \@@_remove_underscore:w, \@@_remove_underscore_end:w
+%   }
+%   \cs{@@_get_name:N} takes a quark and removes the leading |q| and
+%   possibly |_|, so that \cs{@@_get_name:N}\cs{q__test_tail} expands
+%   to |test_tail|.
+%    \begin{macrocode}
+\cs_new:Npn \@@_get_name:N #1
+  { \exp_last_unbraced:Nf \@@_get_name_aux:w { \cs_to_str:N #1 } \s_@@ }
+\cs_new:Npn \@@_get_name_aux:w #1 #2 \s_@@
   {
-    \use:x
+    \str_if_eq:nnTF {#1} { q }
+      { \@@_remove_underscore:w #2 \s_@@ }
       {
-        \@@_new_recursion_tail_auxii:NNNNNNn
-          \exp_not:c { #1_quark_if_recursion_tail_#2 }
-          \exp_not:c { #1_quark_if_recursion_tail:w }
-          \exp_not:c { q #1 _recursion_tail }
-          \exp_not:c { q #1 _recursion_stop }
-          \exp_not:c { #1_\cs_to_str:N #3 }
+        \__kernel_msg_expandable_error:nnf
+          { kernel } { invalid-quark } { \c_backslash_str #1 #2 }
       }
   }
-\cs_new_protected:Npn \@@_new_recursion_tail_auxii:NNNNNNn #1 #2 #3 #4 #5 #6 #7
+\cs_new:Npn \@@_remove_underscore:w #1 #2 \s_@@
   {
-    \cs_new:Npn #1  ##1
-      { \tl_if_empty:oTF { #2 {} ##1 {} ?! #3 ??! } {#5} {#7} }
-    \cs_gset:Npn #2  ##1 #3 ##2 ? ##3 ?! { ##1 ##2 }
-    \use:e { \cs_gset:Npn \exp_not:N #5 ##1 #6 {##2} \exp_not:N #4 { #6{##1} } }
+    \str_if_eq:nnTF {#1} { _ }
+      { \@@_remove_underscore:w }
+      { \@@_remove_underscore_end:w #1 }
+    #2 \s_@@
   }
+\cs_new:Npn \@@_remove_underscore_end:w #1 \s_@@ {#1}
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}





More information about the latex3-commits mailing list.