[latex3-commits] [latex3/latex2e] gh1189: Use a one-level indirection for optimized commands (a4dc0444)

github at latex-project.org github at latex-project.org
Fri Dec 1 12:33:29 CET 2023


Repository : https://github.com/latex3/latex2e
On branch  : gh1189
Link       : https://github.com/latex3/latex2e/commit/a4dc044424ea969169d0f4394a88f1a1c404129f

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

commit a4dc044424ea969169d0f4394a88f1a1c404129f
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Wed Nov 29 10:44:21 2023 +0000

    Use a one-level indirection for optimized commands
    
    This means that they still have "\foo code" and no args at the top level:
    that makes them easier to handle with patching, etc.
    
    Args are only grabbed once and we are looking at very simple expansion, so there is no real need
    to worry about performance.
    
    The marker \@@_start_optimized: is retained:
    we could just check for "\foo code" directly,
    but this way there is a clear single-token
    marker at the start of the def.


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

a4dc044424ea969169d0f4394a88f1a1c404129f
 base/ltcmd.dtx                       | 51 ++++++++++++++++++---------
 base/testfiles-ltcmd/github-1009.tlg | 56 +++++++++++++++++-------------
 base/testfiles-ltcmd/ltcmd001.tlg    | 67 +++++++++++++++++-------------------
 base/testfiles-ltcmd/ltcmd002.tlg    |  2 +-
 4 files changed, 99 insertions(+), 77 deletions(-)

diff --git a/base/ltcmd.dtx b/base/ltcmd.dtx
index a293750f..125122de 100644
--- a/base/ltcmd.dtx
+++ b/base/ltcmd.dtx
@@ -491,17 +491,29 @@
 %   The optimized version of commands just has to worry about whether to make
 %   them protected or long. The commands start with an expandable marker so
 %   that other parts of the kernel know these are set up by \pkg{ltcmd}.
+%   We need the two layers of redirection so that the \texttt{code} internal
+%   function has the same form as it would for any other document command.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_declare_cmd_optimized:Nnn #1#2#3
   {
-    \exp_args:NNc \cs_generate_from_arg_count:NNnn #1
+    \bool_if:NTF \l_@@_expandable_bool
+      { \cs_set_nopar:Npe }
+      { \cs_set_protected_nopar:Npe }
+        #1
+        {
+          \exp_not:N \@@_start_optimized:
+          \exp_not:c { \l_@@_function_tl \c_space_tl code }
+        }
+    \exp_args:Ncc \cs_generate_from_arg_count:NNnn
+      { \l_@@_function_tl \c_space_tl code }
       {
         cs_set
         \bool_if:NF \l_@@_expandable_bool { _protected }
         \bool_if:NF \l_@@_some_long_bool { _nopar }
         :Npn
       }
-      \l_@@_current_arg_int { \@@_start_optimized: #3 }
+      \l_@@_current_arg_int
+      {#3}
   }
 \cs_new:Npn \@@_start_optimized: { }
 %    \end{macrocode}
@@ -2247,10 +2259,20 @@
 %    \end{macrocode}
 %
 % \begin{macro}{\@@_copy_optimized:nnNN}
-%   Trivial copy.
+%   Copy the code, simply define the wrapper.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_copy_optimized:nnNN #1#2#3#4
-  { \cs_set_eq:NN #3 #4 }
+  {
+    \cs_set_eq:cc { #1 ~ code } { #2 ~ code }
+    \token_if_protected_macro:NTF #4
+      { \cs_set_protected_nopar:Npe }
+      { \cs_set_nopar:Npe }
+        #3
+        {
+          \exp_not:N \@@_start_optimized:
+          \exp_not:c { #1 ~ code }
+        }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -2604,6 +2626,12 @@
 % reconstruct the argument spec.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_show_optimized:N #1
+  {
+    \exp_args:Nc \@@_show_optimized:NN
+      { \cs_to_str:N #1 \c_space_tl code }
+      #1
+  }
+\cs_new_protected:Npn \@@_show_optimized:NN #1#2
   {
     \cs_set:Npe \@@_show_optimized_aux:N ##1
       {
@@ -2616,7 +2644,7 @@
       }
     \tl_show:e
       {
-        \token_to_str:N #1 =
+        \token_to_str:N #2 =
           \bool_lazy_or:nnF
             { \token_if_protected_macro_p:N #1 }
             { \token_if_protected_long_macro_p:N #1 }
@@ -2630,20 +2658,9 @@
           }
           \@@_show_optimized_aux:N
         ->
-        \use:e
-          {
-            \exp_not:N \@@_show_optimized_aux:w
-              \cs_replacement_spec:N #1
-          }
+        \cs_replacement_spec:N #1
       }
   }
-\cs_new:Npn \@@_show_optimized_aux:N #1 { }
-\use:e
-  {
-    \cs_new:Npn \exp_not:N \@@_show_optimized_aux:w
-      \token_to_str:N \@@_start_optimized: \c_space_tl
-  }
-  { }
 %    \end{macrocode}
 %
 %   We can reuse most of the above to show an environment, except that
diff --git a/base/testfiles-ltcmd/github-1009.tlg b/base/testfiles-ltcmd/github-1009.tlg
index 195cbc6d..24098de3 100644
--- a/base/testfiles-ltcmd/github-1009.tlg
+++ b/base/testfiles-ltcmd/github-1009.tlg
@@ -13,21 +13,25 @@ l. ...}
 ->.
 <recently read> }
 l. ...}
-> \foo=\protected macro:
-#1->\__cmd_start_optimized: .
-<argument> \foo 
+> \foo=document command:
+ #1:m
+->.
+<recently read> }
 l. ...}
-> \baz=\protected macro:
-#1->\__cmd_start_optimized: .
-<argument> \baz 
+> \baz=document command:
+ #1:m
+->.
+<recently read> }
 l. ...}
-> \foo=\protected\long macro:
-#1->\__cmd_start_optimized: .
-<argument> \foo 
+> \foo=document command:
+ #1:+m
+->.
+<recently read> }
 l. ...}
-> \baz=\protected\long macro:
-#1->\__cmd_start_optimized: .
-<argument> \baz 
+> \baz=document command:
+ #1:+m
+->.
+<recently read> }
 l. ...}
 > \foo=document command:
   #1:>{\foo }m
@@ -53,20 +57,24 @@ l. ...}
 ->.
 <recently read> }
 l. ...}
-> \foo=macro:
-#1->\__cmd_start_optimized: .
-<argument> \foo 
+> \foo=expandable document command:
+ #1:m
+->.
+<recently read> }
 l. ...}
-> \baz=macro:
-#1->\__cmd_start_optimized: .
-<argument> \baz 
+> \baz=expandable document command:
+ #1:m
+->.
+<recently read> }
 l. ...}
-> \foo=\long macro:
-#1->\__cmd_start_optimized: .
-<argument> \foo 
+> \foo=expandable document command:
+ #1:+m
+->.
+<recently read> }
 l. ...}
-> \baz=\long macro:
-#1->\__cmd_start_optimized: .
-<argument> \baz 
+> \baz=expandable document command:
+ #1:+m
+->.
+<recently read> }
 l. ...}
 ============================================================
diff --git a/base/testfiles-ltcmd/ltcmd001.tlg b/base/testfiles-ltcmd/ltcmd001.tlg
index 5e2b34f7..3d7d3a5d 100644
--- a/base/testfiles-ltcmd/ltcmd001.tlg
+++ b/base/testfiles-ltcmd/ltcmd001.tlg
@@ -17,73 +17,70 @@ For immediate help type H <return>.
 l. ...}
 You have used \RenewDocumentCommand with a command that was never defined.
 LaTeX will ignore this entire definition.
-> \foo=\protected macro:->\__cmd_start_optimized: First definition.
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:->First definition.
 <recently read> }
 l. ...}
 ============================================================
 ============================================================
 TEST 2: Commands with simple mandatory arguments
 ============================================================
-> \foo=\protected macro:#1->\__cmd_start_optimized: (#1).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1->(#1).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2->\__cmd_start_optimized: (#1)(#2).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1#2->(#1)(#2).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3->\__cmd_start_optimized: (#1)(#2)(#3).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1#2#3->(#1)(#2)(#3).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3#4->\__cmd_start_optimized: (#1)(#2)(#3)(#4).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1#2#3#4->(#1)(#2)(#3)(#4).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3#4#5->\__cmd_start_optimized:
-(#1)(#2)(#3)(#4)(#5).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1#2#3#4#5->(#1)(#2)(#3)(#4)(#5).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3#4#5#6->\__cmd_start_optimized:
-(#1)(#2)(#3)(#4)(#5)(#6).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1#2#3#4#5#6->(#1)(#2)(#3)(#4)(#5)(#6).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3#4#5#6#7->\__cmd_start_optimized:
-(#1)(#2)(#3)(#4)(#5)(#6)(#7).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected macro:#1#2#3#4#5#6#7->(#1)(#2)(#3)(#4)(#5)(#6)(#7).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3#4#5#6#7#8->\__cmd_start_optimized:
-(#1)(#2)(#3)(#4)(#5)(#6)(#7)(#8).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected
+macro:#1#2#3#4#5#6#7#8->(#1)(#2)(#3)(#4)(#5)(#6)(#7)(#8).
 <recently read> }
 l. ...}
-> \foo=\protected macro:#1#2#3#4#5#6#7#8#9->\__cmd_start_optimized:
-(#1)(#2)(#3)(#4)(#5)(#6)(#7)(#8)(#9).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected
+macro:#1#2#3#4#5#6#7#8#9->(#1)(#2)(#3)(#4)(#5)(#6)(#7)(#8)(#9).
 <recently read> }
 l. ...}
 ============================================================
@@ -107,10 +104,10 @@ l. ...}
 ============================================================
 TEST 4: Commands with one long mandatory argument
 ============================================================
-> \foo=\protected\long macro:#1->\__cmd_start_optimized: (#1).
+> \foo=\protected macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\protected\long macro:#1->(#1).
 <recently read> }
 l. ...}
 > \foo=\protected macro:->\__cmd_start_expandable:nNNNNn {m+m}\foo  \foo  
@@ -324,22 +321,22 @@ l. ...}
 ============================================================
 TEST 8: Some valid expandable functions
 ============================================================
-> \foo=macro:#1->\__cmd_start_optimized: (#1).
+> \foo=macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=macro:#1->(#1).
 <recently read> }
 l. ...}
-> \foo=\long macro:#1->\__cmd_start_optimized: (#1).
+> \foo=macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=\long macro:#1->(#1).
 <recently read> }
 l. ...}
-> \foo=macro:#1#2#3->\__cmd_start_optimized: (#1)(#2)(#3).
+> \foo=macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=macro:#1#2#3->(#1)(#2)(#3).
 <recently read> }
 l. ...}
 > \foo=macro:->\__cmd_start_expandable:nNNNNn {om}\foo  \foo  \foo code
@@ -697,10 +694,10 @@ l. ...}
 You have used \RenewExpandableDocumentCommand with a command that was never
 defined.
 LaTeX will ignore this entire definition.
-> \foo=macro:->\__cmd_start_optimized: First definition.
+> \foo=macro:->\__cmd_start_optimized: \foo code .
 <recently read> }
 l. ...}
-> \foo code=undefined.
+> \foo code=macro:->First definition.
 <recently read> }
 l. ...}
 ============================================================
diff --git a/base/testfiles-ltcmd/ltcmd002.tlg b/base/testfiles-ltcmd/ltcmd002.tlg
index 3a5fbeb9..cad76a7b 100644
--- a/base/testfiles-ltcmd/ltcmd002.tlg
+++ b/base/testfiles-ltcmd/ltcmd002.tlg
@@ -48,7 +48,7 @@ TEST 2: Nesting optional arguments
 TEST 3: Invalid arguments (types s, o m)
 ============================================================
 Runaway argument?
-! Paragraph ended before \foo was complete.
+! Paragraph ended before \foo code was complete.
 <to be read again> 
                    \par 
 l. ...}





More information about the latex3-commits mailing list.