-
Notifications
You must be signed in to change notification settings - Fork 177
/
l3expan.dtx
2918 lines (2918 loc) · 105 KB
/
l3expan.dtx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% \iffalse meta-comment
%
%% File: l3expan.dtx
%
% Copyright (C) 1990-2020 The LaTeX3 Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version. The latest version
% of this license is in the file
%
% https://www.latex-project.org/lppl.txt
%
% This file is part of the "l3kernel bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
% https://github.com/latex3/latex3
%
% for those people who are interested.
%
%<*driver>
\documentclass[full,kernel]{l3doc}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
% The \pkg{l3expan} package\\ Argument expansion^^A
% }
%
% \author{^^A
% The \LaTeX3 Project\thanks
% {^^A
% E-mail:
% \href{mailto:latex-team@latex-project.org}
% {latex-team@latex-project.org}^^A
% }^^A
% }
%
% \date{Released 2020-03-06}
%
% \maketitle
%
% \begin{documentation}
%
% This module provides generic methods for expanding \TeX{} arguments in a
% systematic manner. The functions in this module all have prefix |exp|.
%
% Not all possible variations are implemented for every base
% function. Instead only those that are used within the \LaTeX3 kernel
% or otherwise seem to be of general interest are implemented.
% Consult the module description to find out which functions are
% actually defined. The next section explains how to define missing
% variants.
%
% \section{Defining new variants}
% \label{sec:l3expan:defining-variants}
%
% The definition of variant forms for base functions may be necessary
% when writing new functions or when applying a kernel function in a
% situation that we haven't thought of before.
%
% Internally preprocessing of arguments is done with functions of the form
% \cs[no-index]{exp_\ldots{}}. They all look alike, an example would be
% \cs{exp_args:NNo}. This function has three arguments, the first and the
% second are a single tokens, while the third argument should be given
% in braces. Applying \cs{exp_args:NNo} expands the content of third
% argument once before any expansion of the first and second arguments.
% If \cs{seq_gpush:No} was not defined it could be coded in the following way:
% \begin{verbatim}
% \exp_args:NNo \seq_gpush:Nn
% \g_file_name_stack
% { \l_tmpa_tl }
% \end{verbatim}
% In other words, the first argument to \cs{exp_args:NNo} is the base
% function and the other arguments are preprocessed and then passed to
% this base function. In the example the first argument to the base
% function should be a single token which is left unchanged while the
% second argument is expanded once. From this example we can also see
% how the variants are defined. They just expand into the appropriate
% |\exp_| function followed by the desired base function, \emph{e.g.}
% \begin{quote}
% |\cs_generate_variant:Nn \seq_gpush:Nn { No } |
% \end{quote}
% results in the definition of |\seq_gpush:No|
% \begin{quote}
% |\cs_new:Npn \seq_gpush:No { \exp_args:NNo \seq_gpush:Nn }|
% \end{quote}
% Providing variants in this way in style files is safe as the
% \cs{cs_generate_variant:Nn} function will only create new definitions if
% there is not already one available. Therefore adding
% such definition to later releases of the kernel will not make such
% style files obsolete.
%
% The steps above may be automated by using the function
% \cs{cs_generate_variant:Nn}, described next.
%
% \section{Methods for defining variants}
% \label{sec:l3expan:variants-method}
%
% We recall the set of available argument specifiers.
% \begin{itemize}
% \item |N|~is used for single-token arguments while |c|~constructs a
% control sequence from its name and passes it to a parent function as
% an |N|-type argument.
% \item Many argument types extract or expand some tokens and provide it
% as an |n|-type argument, namely a braced multiple-token argument:
% |V|~extracts the value of a variable, |v|~extracts the value from
% the name of a variable, |n|~uses the argument as it is, |o|~expands
% once, |f|~expands fully the front of the token list, |e| and
% |x|~expand fully all tokens (differences are explained later).
% \item A few odd argument types remain: |T|~and |F|~for conditional
% processing, otherwise identical to |n|-type arguments,
% |p|~for the parameter text
% in definitions, |w|~for arguments with a specific syntax, and |D|~to
% denote primitives that should not be used directly.
% \end{itemize}
%
% \begin{function}[updated = 2017-11-28]
% {\cs_generate_variant:Nn, \cs_generate_variant:cn}
% \begin{syntax}
% \cs{cs_generate_variant:Nn} \meta{parent control sequence} \Arg{variant argument specifiers}
% \end{syntax}
% This function is used to define argument-specifier variants of the
% \meta{parent control sequence} for \LaTeX3 code-level macros. The
% \meta{parent control sequence} is first separated into the
% \meta{base name} and \meta{original argument specifier}. The
% comma-separated list of \meta{variant argument specifiers} is
% then used to define variants of the
% \meta{original argument specifier} if these are not already
% defined. For each \meta{variant} given, a function is created
% that expands its arguments as detailed and passes them
% to the \meta{parent control sequence}. So for example
% \begin{verbatim}
% \cs_set:Npn \foo:Nn #1#2 { code here }
% \cs_generate_variant:Nn \foo:Nn { c }
% \end{verbatim}
% creates a new function |\foo:cn| which expands its first
% argument into a control sequence name and passes the result to
% |\foo:Nn|. Similarly
% \begin{verbatim}
% \cs_generate_variant:Nn \foo:Nn { NV , cV }
% \end{verbatim}
% generates the functions |\foo:NV| and |\foo:cV| in the same
% way. The \cs{cs_generate_variant:Nn} function can only be applied if
% the \meta{parent control sequence} is already defined. If the \meta{parent
% control sequence} is protected or if the \meta{variant} involves any
% |x|~argument, then the \meta{variant control sequence} is also
% protected. The \meta{variant} is created globally, as is any
% \cs[no-index]{exp_args:N\meta{variant}} function needed to carry out the
% expansion.
%
% Only |n|~and |N| arguments can be changed to other types. The only
% allowed changes are
% \begin{itemize}
% \item |c|~variant of an |N|~parent;
% \item |o|, |V|, |v|, |f|, |e|, or~|x| variant of an |n|~parent;
% \item |N|, |n|, |T|, |F|, or |p| argument unchanged.
% \end{itemize}
% This means the \meta{parent} of a \meta{variant} form is always
% unambiguous, even in cases where both an |n|-type parent and an
% |N|-type parent exist, such as for \cs{tl_count:n} and
% \cs{tl_count:N}.
%
% For backward compatibility it is currently possible to make |n|,
% |o|, |V|, |v|, |f|, |e|, or |x|-type variants of an |N|-type argument or
% |N| or |c|-type variants of an |n|-type argument. Both are
% deprecated. The first because passing more than one token to an
% |N|-type argument will typically break the parent function's code.
% The second because programmers who use that most often want to
% access the value of a variable given its name, hence should use a
% |V|-type or |v|-type variant instead of |c|-type. In those cases,
% using the lower-level \cs{exp_args:No} or \cs{exp_args:Nc}
% functions explicitly is preferred to defining confusing variants.
% \end{function}
%
% \section{Introducing the variants}
%
% The |V| type returns the value of a register, which can be one of
% |tl|, |clist|, |int|, |skip|, |dim|, |muskip|, or built-in \TeX{}
% registers. The |v| type is the same except it first creates a
% control sequence out of its argument before returning the
% value.
%
% In general, the programmer should not need to be concerned with
% expansion control. When simply using the content of a variable,
% functions with a |V| specifier should be used. For those referred to by
% (cs)name, the |v| specifier is available for the same purpose. Only when
% specific expansion steps are needed, such as when using delimited
% arguments, should the lower-level functions with |o| specifiers be employed.
%
% The |e| type expands all tokens fully, starting from the first. More
% precisely the expansion is identical to that of \TeX{}'s \tn{message}
% (in particular |#| needs not be doubled). It was added in May 2018.
% In recent enough engines (starting around 2019) it relies on the
% primitive \tn{expanded} hence is fast. In older engines it is very
% much slower. As a result it should only be used in performance
% critical code if typical users will have a recent installation of the
% \TeX{} ecosystem.
%
% The |x| type expands all tokens fully, starting from the first. In
% contrast to |e|, all macro parameter characters |#| must be doubled,
% and omitting this leads to low-level errors. In addition this type of
% expansion is not expandable, namely functions that have |x| in their
% signature do not themselves expand when appearing inside |x| or |e|
% expansion.
%
% The |f| type is so special that it deserves an example. It is
% typically used in contexts where only expandable commands are allowed.
% Then |x|-expansion cannot be used, and |f|-expansion provides an
% alternative that expands the front of the token list
% as much as can be done in such contexts. For
% instance, say that we want to evaluate the integer expression $3 + 4$
% and pass the result $7$ as an argument to an expandable function
% |\example:n|. For this, one should define a variant using
% \cs{cs_generate_variant:Nn} |\example:n| |{| |f| |}|, then do
% \begin{quote}
% |\example:f { \int_eval:n { 3 + 4 } }|
% \end{quote}
% Note that |x|-expansion would also expand \cs{int_eval:n} fully to its
% result~$7$, but the variant |\example:x| cannot be expandable. Note
% also that |o|-expansion would not expand \cs{int_eval:n} fully to its
% result since that function requires several expansions. Besides the
% fact that |x|-expansion is protected rather than expandable, another
% difference between |f|-expansion and |x|-expansion is that
% |f|-expansion expands tokens from the beginning and stops as soon as a
% non-expandable token is encountered, while |x|-expansion continues
% expanding further tokens. Thus, for instance
% \begin{quote}
% |\example:f { \int_eval:n { 1 + 2 } , \int_eval:n { 3 + 4 } }|
% \end{quote}
% results in the call
% \begin{quote}
% |\example:n { 3 , \int_eval:n { 3 + 4 } }|
% \end{quote}
% while using |\example:x| or |\example:e| instead results in
% \begin{quote}
% |\example:n { 3 , 7 }|
% \end{quote}
% at the cost of being protected (for |x| type) or very much slower in
% old engines (for |e| type).
% If you use |f| type expansion in conditional processing then
% you should stick to using |TF| type functions only as the expansion
% does not finish any |\if... \fi:| itself!
%
% It is important to note that both \texttt{f}- and \texttt{o}-type
% expansion are concerned with the expansion of tokens from left to
% right in their arguments. In particular, \texttt{o}-type expansion
% applies to the first \emph{token} in the argument it receives: it
% is conceptually similar to
% \begin{verbatim}
% \exp_after:wN <base function> \exp_after:wN { <argument> }
% \end{verbatim}
% At the same time, \texttt{f}-type expansion stops at the \emph{first}
% non-expandable token. This means for example that both
% \begin{verbatim}
% \tl_set:No \l_tmpa_tl { { \g_tmpb_tl } }
% \end{verbatim}
% and
% \begin{verbatim}
% \tl_set:Nf \l_tmpa_tl { { \g_tmpb_tl } }
% \end{verbatim}
% leave |\g_tmpb_tl| unchanged: |{| is the first token in the
% argument and is non-expandable.
%
% It is usually best to keep the following in mind when using variant
% forms.
% \begin{itemize}
% \item
% Variants with |x|-type arguments (that are fully expanded before
% being passed to the |n|-type base function) are never expandable
% even when the base function is. Such variants cannot work
% correctly in arguments that are themselves subject to expansion.
% Consider using |f| or |e| expansion.
% \item
% In contrast, |e|~expansion (full expansion, almost like~|x| except
% for the treatment of~|#|) does not prevent variants from being
% expandable (if the base function is). The drawback is that
% |e|~expansion is very much slower in old engines (before 2019).
% Consider using |f|~expansion if that type of expansion is
% sufficient to perform the required expansion, or |x|~expansion if
% the variant will not itself need to be expandable.
% \item
% Finally |f|~expansion only expands the front of the token list,
% stopping at the first non-expandable token. This may fail to
% fully expand the argument.
% \end{itemize}
%
% When speed is essential (for functions that do very little work and
% whose variants are used numerous times in a document) the following
% considerations apply because internal functions for argument expansion
% come in two flavours, some faster than others.
% \begin{itemize}
% \item
% Arguments that might need expansion should come first in the list
% of arguments.
% \item
% Arguments that should consist of single tokens |N|, |c|, |V|, or
% |v| should come first among these.
% \item
% Arguments that appear after the first multi-token argument |n|,
% |f|, |e|, or |o| require slightly slower special processing to be
% expanded. Therefore it is best to use the optimized functions,
% namely those that contain only |N|, |c|, |V|, and |v|, and, in the
% last position, |o|, |f|, |e|, with possible trailing |N| or |n| or
% |T| or |F|, which are not expanded. Any |x|-type argument causes
% slightly slower processing.
% \end{itemize}
%
% \section{Manipulating the first argument}
%
% These functions are described in detail: expansion of multiple tokens follows
% the same rules but is described in a shorter fashion.
%
% \begin{function}[EXP]{\exp_args:Nc, \exp_args:cc}
% \begin{syntax}
% \cs{exp_args:Nc} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are expanded until only characters
% remain, and are then turned into a control sequence.
% The result is inserted into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others are left unchanged.
%
% The |:cc| variant constructs the \meta{function} name in the same
% manner as described for the \meta{tokens}.
% \begin{texnote}
% Protected macros that appear in a \texttt{c}-type argument are
% expanded despite being protected; \cs{exp_not:n} also has no
% effect. An internal error occurs if non-characters or active
% characters remain after full expansion, as the conversion to a
% control sequence is not possible.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_args:No}
% \begin{syntax}
% \cs{exp_args:No} \meta{function} \Arg{tokens} ...
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are expanded once, and the result
% is inserted in braces into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others are left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:NV}
% \begin{syntax}
% \cs{exp_args:NV} \meta{function} \meta{variable}
% \end{syntax}
% This function absorbs two arguments (the names of the \meta{function} and
% the \meta{variable}). The content of the \meta{variable} are recovered
% and placed inside braces into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others are left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nv}
% \begin{syntax}
% \cs{exp_args:Nv} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are expanded until only characters
% remain, and are then turned into a control sequence.
% This control sequence should
% be the name of a \meta{variable}. The content of the \meta{variable} are
% recovered and placed inside braces into the input stream \emph{after}
% reinsertion of the \meta{function}. Thus the \meta{function} may take more
% than one argument: all others are left unchanged.
% \begin{texnote}
% Protected macros that appear in a \texttt{v}-type argument are
% expanded despite being protected; \cs{exp_not:n} also has no
% effect. An internal error occurs if non-characters or active
% characters remain after full expansion, as the conversion to a
% control sequence is not possible.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP, added = 2018-05-15]{\exp_args:Ne}
% \begin{syntax}
% \cs{exp_args:Ne} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}) and exhaustively expands the \meta{tokens}.
% The result is inserted in braces into the input stream
% \emph{after} reinsertion of the \meta{function}.
% Thus the \meta{function} may take more
% than one argument: all others are left unchanged.
% \begin{texnote}
% This relies on the \tn{expanded} primitive when available (in
% \LuaTeX{} and starting around 2019 in other engines). Otherwise
% it uses some fall-back code that is very much slower. As a result
% it should only be used in performance-critical code if typical
% users have a recent installation of the \TeX{} ecosystem.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nf}
% \begin{syntax}
% \cs{exp_args:Nf} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are fully expanded until the
% first non-expandable token is found (if that is a space it is
% removed), and the result
% is inserted in braces into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others are left unchanged.
% \end{function}
%
% \begin{function}{\exp_args:Nx}
% \begin{syntax}
% \cs{exp_args:Nx} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}) and exhaustively expands the \meta{tokens}.
% The result is inserted in braces into the input stream
% \emph{after} reinsertion of the \meta{function}.
% Thus the \meta{function} may take more
% than one argument: all others are left unchanged.
% \end{function}
%
% \section{Manipulating two arguments}
%
% \begin{function}[EXP, updated = 2018-05-15]
% {
% \exp_args:NNc,
% \exp_args:NNo,
% \exp_args:NNV,
% \exp_args:NNv,
% \exp_args:NNe,
% \exp_args:NNf,
% \exp_args:Ncc,
% \exp_args:Nco,
% \exp_args:NcV,
% \exp_args:Ncv,
% \exp_args:Ncf,
% \exp_args:NVV
% }
% \begin{syntax}
% \cs{exp_args:NNc} \meta{token_1} \meta{token_2} \Arg{tokens}
% \end{syntax}
% These optimized functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments.
% \end{function}
%
% \begin{function}[EXP, updated = 2018-05-15]
% {
% \exp_args:Nnc,
% \exp_args:Nno,
% \exp_args:NnV,
% \exp_args:Nnv,
% \exp_args:Nne,
% \exp_args:Nnf,
% \exp_args:Noc,
% \exp_args:Noo,
% \exp_args:Nof,
% \exp_args:NVo,
% \exp_args:Nfo,
% \exp_args:Nff,
% \exp_args:Nee,
% }
% \begin{syntax}
% \cs{exp_args:Noo} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% These functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments.
% These functions need slower processing.
% \end{function}
%
% \begin{function}
% {
% \exp_args:NNx,
% \exp_args:Ncx,
% \exp_args:Nnx,
% \exp_args:Nox,
% \exp_args:Nxo,
% \exp_args:Nxx
% }
% \begin{syntax}
% \cs{exp_args:NNx} \meta{token_1} \meta{token_2} \Arg{tokens}
% \end{syntax}
% These functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments. These functions
% are not expandable due to their |x|-type argument.
% \end{function}
%
% \section{Manipulating three arguments}
%
% \begin{function}[EXP]
% {
% \exp_args:NNNo,
% \exp_args:NNNV,
% \exp_args:Nccc,
% \exp_args:NcNc,
% \exp_args:NcNo,
% \exp_args:Ncco
% }
% \begin{syntax}
% \cs{exp_args:NNNo} \meta{token_1} \meta{token_2} \meta{token_3} \Arg{tokens}
% \end{syntax}
% These optimized functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc}.
% \end{function}
%
% \begin{function}[EXP]
% {
% \exp_args:NNcf,
% \exp_args:NNno,
% \exp_args:NNnV,
% \exp_args:NNoo,
% \exp_args:NNVV,
% \exp_args:Ncno,
% \exp_args:NcnV,
% \exp_args:Ncoo,
% \exp_args:NcVV,
% \exp_args:Nnnc,
% \exp_args:Nnno,
% \exp_args:Nnnf,
% \exp_args:Nnff,
% \exp_args:Nooo,
% \exp_args:Noof,
% \exp_args:Nffo,
% \exp_args:Neee
% }
% \begin{syntax}
% \cs{exp_args:NNoo} \meta{token_1} \meta{token_2} \Arg{token_3} \Arg{tokens}
% \end{syntax}
% These functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc}.
% These functions need slower processing.
% \end{function}
%
% \begin{function}[added = 2015-08-12]
% {
% \exp_args:NNNx,
% \exp_args:NNnx,
% \exp_args:NNox,
% \exp_args:Nccx,
% \exp_args:Ncnx,
% \exp_args:Nnnx,
% \exp_args:Nnox,
% \exp_args:Noox,
% }
% \begin{syntax}
% \cs{exp_args:NNnx} \meta{token_1} \meta{token_2} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% These functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc.}
% \end{function}
%
% \section{Unbraced expansion}
%
% \begin{function}[EXP, updated = 2018-05-15]
% {
% \exp_last_unbraced:No,
% \exp_last_unbraced:NV,
% \exp_last_unbraced:Nv,
% \exp_last_unbraced:Ne,
% \exp_last_unbraced:Nf,
% \exp_last_unbraced:NNo,
% \exp_last_unbraced:NNV,
% \exp_last_unbraced:NNf,
% \exp_last_unbraced:Nco,
% \exp_last_unbraced:NcV,
% \exp_last_unbraced:Nno,
% \exp_last_unbraced:Noo,
% \exp_last_unbraced:Nfo,
% \exp_last_unbraced:NNNo,
% \exp_last_unbraced:NNNV,
% \exp_last_unbraced:NNNf,
% \exp_last_unbraced:NnNo,
% \exp_last_unbraced:NNNNo,
% \exp_last_unbraced:NNNNf,
% }
% \begin{syntax}
% \cs{exp_last_unbraced:Nno} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% These functions absorb the number of arguments given by their
% specification, carry out the expansion
% indicated and leave the results in the input stream, with the
% last argument not surrounded by the usual braces.
% Of these, the |:Nno|, |:Noo|, |:Nfo| and |:NnNo|
% variants need slower processing.
% \begin{texnote}
% As an optimization, the last argument is unbraced by some
% of those functions before expansion. This can cause problems
% if the argument is empty: for instance,
% \cs{exp_last_unbraced:Nf} |\foo_bar:w| |{ }| \cs{q_stop}
% leads to an infinite loop, as the quark is \texttt{f}-expanded.
% \end{texnote}
% \end{function}
%
% \begin{function}{\exp_last_unbraced:Nx}
% \begin{syntax}
% \cs{exp_last_unbraced:Nx} \meta{function} \Arg{tokens}
% \end{syntax}
% This function fully expands the \meta{tokens} and leaves the result
% in the input stream after reinsertion of the \meta{function}.
% This function is not expandable.
% \end{function}
%
% \begin{function}[EXP]{\exp_last_two_unbraced:Noo}
% \begin{syntax}
% \cs{exp_last_two_unbraced:Noo} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% This function absorbs three arguments and expands the second and third
% once. The first argument of the function is then the next item on the
% input stream, followed by the expansion of the second and third arguments,
% which are not wrapped in braces.
% This function needs special (slower) processing.
% \end{function}
%
% \begin{function}[EXP]{\exp_after:wN}
% \begin{syntax}
% \cs{exp_after:wN} \meta{token_1} \meta{token_2}
% \end{syntax}
% Carries out a single expansion of \meta{token_2} (which may consume
% arguments) prior to the expansion of \meta{token_1}. If \meta{token_2} has
% no expansion (for example, if it is a character) then it is left
% unchanged. It is important to notice that \meta{token_1} may be
% \emph{any} single token, including group-opening and -closing
% tokens (|{| or |}| assuming normal \TeX{} category codes). Unless
% specifically required this should be avoided: expansion should be carried out using an
% appropriate argument specifier variant or the appropriate
% \cs[no-index]{exp_arg:N} function.
% \begin{texnote}
% This is the \TeX{} primitive \tn{expandafter} renamed.
% \end{texnote}
% \end{function}
%
%
% \section{Preventing expansion}
%
% Despite the fact that the following functions are all about preventing
% expansion, they're designed to be used in an expandable context and hence
% are all marked as being `expandable' since they themselves disappear
% after the expansion has completed.
%
% \begin{function}[EXP]{\exp_not:N}
% \begin{syntax}
% \cs{exp_not:N} \meta{token}
% \end{syntax}
% Prevents expansion of the \meta{token} in a context where it would
% otherwise be expanded, for example an |x|-type argument or the first
% token in an |o| or |e| or |f| argument.
% \begin{texnote}
% This is the \TeX{} \tn{noexpand} primitive. It only prevents
% expansion. At the beginning of an |f|-type argument, a space
% \meta{token} is removed even if it appears as \cs{exp_not:N}
% \cs{c_space_token}. In an |x|-expanding definition
% (\cs{cs_new:Npx}), a macro parameter introduces an argument even
% if it appears as \cs{exp_not:N} |#| |1|. This differs from
% \cs{exp_not:n}.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:c}
% \begin{syntax}
% \cs{exp_not:c} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} until only characters remain, and then
% converts this into a control sequence.
% Further expansion of this control sequence is then inhibited using
% \cs{exp_not:N}.
% \begin{texnote}
% Protected macros that appear in a \texttt{c}-type argument are
% expanded despite being protected; \cs{exp_not:n} also has no
% effect. An internal error occurs if non-characters or active
% characters remain after full expansion, as the conversion to a
% control sequence is not possible.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:n}
% \begin{syntax}
% \cs{exp_not:n} \Arg{tokens}
% \end{syntax}
% Prevents expansion of the \meta{tokens} in an |e| or |x|-type argument. In
% all other cases the \meta{tokens} continue to be expanded, for
% example in the input stream or in other types of arguments such as
% \texttt{c}, \texttt{f}, \texttt{v}. The argument of \cs{exp_not:n}
% \emph{must} be surrounded by braces.
% \begin{texnote}
% This is the \eTeX{} \tn{unexpanded} primitive. In an
% |x|-expanding definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#1}|
% is equivalent to |##1| rather than to~|#1|, namely it inserts the
% two characters |#| and~|1|. In an |e|-type argument
% \cs{exp_not:n}~|{#}| is equivalent to |#|, namely it inserts the
% character~|#|.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:o}
% \begin{syntax}
% \cs{exp_not:o} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} once, then prevents any further expansion
% in |x|-type or \texttt{e}-type arguments using \cs{exp_not:n}.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:V}
% \begin{syntax}
% \cs{exp_not:V} \meta{variable}
% \end{syntax}
% Recovers the content of the \meta{variable}, then prevents expansion
% of this material in |x|-type or \texttt{e}-type arguments using \cs{exp_not:n}.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:v}
% \begin{syntax}
% \cs{exp_not:v} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} until only characters remains, and then
% converts this into a control sequence which should be a \meta{variable}
% name.
% The content of the \meta{variable} is recovered, and further
% expansion in |x|-type or \texttt{e}-type arguments is prevented using \cs{exp_not:n}.
% \begin{texnote}
% Protected macros that appear in a \texttt{v}-type argument are
% expanded despite being protected; \cs{exp_not:n} also has no
% effect. An internal error occurs if non-characters or active
% characters remain after full expansion, as the conversion to a
% control sequence is not possible.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:e}
% \begin{syntax}
% \cs{exp_not:e} \Arg{tokens}
% \end{syntax}
% Expands \meta{tokens} exhaustively, then protects the result of the
% expansion (including any tokens which were not expanded) from
% further expansion in |e| or |x|-type arguments using \cs{exp_not:n}.
% This is very rarely useful but is provided for consistency.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:f}
% \begin{syntax}
% \cs{exp_not:f} \Arg{tokens}
% \end{syntax}
% Expands \meta{tokens} fully until the first unexpandable token is
% found (if it is a space it is removed). Expansion then stops, and
% the result of the expansion (including any tokens which were not
% expanded) is protected from further expansion in |x|-type or \texttt{e}-type arguments
% using \cs{exp_not:n}.
% \end{function}
%
% \begin{function}[updated = 2011-06-03, EXP]{\exp_stop_f:}
% \begin{syntax}
% |\foo_bar:f| \{ \meta{tokens} \cs{exp_stop_f:} \meta{more tokens} \}
% \end{syntax}
% This function terminates an \texttt{f}-type expansion. Thus if
% a function |\foo_bar:f| starts an \texttt{f}-type expansion
% and all of \meta{tokens} are expandable \cs{exp_stop_f:}
% terminates the expansion of tokens even if \meta{more tokens}
% are also expandable. The function itself is an implicit space
% token. Inside an \texttt{x}-type expansion, it retains its
% form, but when typeset it produces the underlying space (\verb*| |).
% \end{function}
%
%
% \section{Controlled expansion}
%
% The \pkg{expl3} language makes all efforts to hide the complexity of
% \TeX{} expansion from the programmer by providing concepts that
% evaluate/expand arguments of functions prior to calling the \enquote{base}
% functions. Thus, instead of using many \tn{expandafter} calls and
% other trickery it is usually a matter of choosing the right variant
% of a function to achieve a desired result.
%
% Of course, deep down \TeX{} is using expansion as always and there
% are cases where a programmer needs to control that expansion
% directly; typical situations are basic data manipulation tools. This
% section documents the functions for that level. These
% commands are used throughout the kernel code, but we hope that outside
% the kernel there will be little need to resort to them. Instead the
% argument manipulation methods document above should usually be sufficient.
%
% While \cs{exp_after:wN} expands one token (out of order) it is
% sometimes necessary to expand several tokens in one go. The next set
% of commands provide this functionality. Be aware that it is
% absolutely required that the programmer has full control over the
% tokens to be expanded, i.e., it is not possible to use these
% functions to expand unknown input as part of
% \meta{expandable-tokens} as that will break badly if unexpandable
% tokens are encountered in that place!
%
% \begin{function}[added=2015-08-23,EXP]
% {
% \exp:w ,
% \exp_end:
% }
% \begin{syntax}
% \cs{exp:w} \meta{expandable tokens} \cs{exp_end:} \\
% \end{syntax}
% Expands \meta{expandable-tokens} until reaching \cs{exp_end:} at
% which point expansion stops.
% The full expansion of \meta{expandable tokens} has to be empty.
% If any token in \meta{expandable tokens} or any token generated by
% expanding the tokens therein is not expandable the expansion will end
% prematurely and as a result \cs{exp_end:} will be misinterpreted
% later on.\footnotemark
%
% In typical use cases the \cs{exp_end:} is hidden somewhere
% in the replacement text of \meta{expandable-tokens} rather than
% being on the same expansion level than \cs{exp:w}, e.g., you may
% see code such as
%\begin{verbatim}
% \exp:w \@@_case:NnTF #1 {#2} { } { }
%\end{verbatim}
% where somewhere during the expansion of |\@@_case:NnTF| the
% \cs{exp_end:} gets generated.
% \begin{texnote}
% The current implementation uses \tn{romannumeral} hence ignores
% space tokens and explicit signs |+| and |-| in the expansion of the
% \meta{expandable tokens}, but this should not be relied upon.
% \end{texnote}
% \end{function}
% \footnotetext{Due to the implementation you might get the character
% in position 0 in the current font (typically \enquote{\texttt{`}})
% in the output without any error message!}
%
% \begin{function}[added=2015-08-23, EXP, label = \exp_end_continue_f:w]
% {
% \exp:w ,
% \exp_end_continue_f:w
% }
% \begin{syntax}
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end_continue_f:w} \meta{further-tokens}
% \end{syntax}
% Expands \meta{expandable-tokens} until reaching \cs{exp_end_continue_f:w} at
% which point expansion continues as an \texttt{f}-type expansion expanding
% \meta{further-tokens} until an unexpandable token is encountered (or
% the \texttt{f}-type expansion is explicitly terminated by
% \cs{exp_stop_f:}). As with all \texttt{f}-type expansions a space ending
% the expansion gets removed.
%
% The full expansion of \meta{expandable-tokens} has to be empty.
% If any token in \meta{expandable-tokens} or any token generated by
% expanding the tokens therein is not expandable the expansion will end
% prematurely and as a result \cs{exp_end_continue_f:w} will be misinterpreted
% later on.\footnotemark
%
%
% In typical use cases \meta{expandable-tokens} contains no tokens at all,
% e.g., you will see code such as
%\begin{verbatim}
% \exp_after:wN { \exp:w \exp_end_continue_f:w #2 }
%\end{verbatim}
% where the \cs{exp_after:wN} triggers an \texttt{f}-expansion of the tokens
% in |#2|. For technical reasons this has to happen using two tokens
% (if they would be hidden inside another command \cs{exp_after:wN}
% would only expand the command but not trigger any additional
% |f|-expansion).
%
% You might wonder why there are two different approaches available,
% after all the effect of
% \begin{quote}
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end:}
% \end{quote}
% can be alternatively achieved through an \texttt{f}-type expansion by using
% \cs{exp_stop_f:}, i.e.
% \begin{quote}
% \cs{exp:w} \cs{exp_end_continue_f:w} \meta{expandable-tokens} \cs{exp_stop_f:}
% \end{quote}
% The reason is simply that the first approach is slightly faster
% (one less token to parse and less expansion internally)
% so in places where such performance really matters and where we
% want to explicitly stop the expansion at a defined point the first
% form is preferable.
% \end{function}
% \footnotetext{In this particular case you may get a character into
% the output as well as an error message.}
%
% \begin{function}[added=2015-08-23, EXP, label = \exp_end_continue_f:nw]
% {
% \exp:w ,
% \exp_end_continue_f:nw
% }
% \begin{syntax}
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end_continue_f:nw} \meta{further-tokens}
% \end{syntax}
% The difference to \cs{exp_end_continue_f:w} is that we first we pick
% up an argument which is then returned to the input stream. If
% \meta{further-tokens} starts with space tokens then these space
% tokens are removed while searching for the argument. If it starts
% with a brace group then the braces are removed. Thus such spaces or
% braces will not terminate the \texttt{f}-type expansion.
% \end{function}
%
% \section{Internal functions}
%
% \begin{function}{\::n, \::N, \::p, \::c, \::o, \::e, \::f, \::x, \::v, \::V, \:::}
% \begin{syntax}
% |\cs_new:Npn \exp_args:Ncof { \::c \::o \::f \::: }|
% \end{syntax}
% Internal forms for the base expansion types. These names do \emph{not}
% conform to the general \LaTeX3 approach as this makes them more readily
% visible in the log and so forth. They should not be used outside this module.
% \end{function}
%
% \begin{function}
% {\::o_unbraced, \::e_unbraced, \::f_unbraced, \::x_unbraced, \::v_unbraced, \::V_unbraced}
% \begin{syntax}
% |\cs_new:Npn \exp_last_unbraced:Nno { \::n \::o_unbraced \::: }|
% \end{syntax}
% Internal forms for the expansion types which leave the terminal argument
% unbraced. These names do \emph{not}
% conform to the general \LaTeX3 approach as this makes them more readily
% visible in the log and so forth. They should not be used outside this module.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3expan} implementation}
%
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
%
% \begin{macrocode}
%<@@=exp>
% \end{macrocode}
%
% \begin{variable}{\l_@@_internal_tl}
% The |\exp_| module has its private variable to temporarily store the
% result of |x|-type argument expansion. This is done to avoid interference
% with other functions using temporary variables.
% \end{variable}
%
% \begin{macro}{\exp_after:wN}
% \begin{macro}{\exp_not:N}
% \begin{macro}{\exp_not:n}
% These are defined in \pkg{l3basics}, as they are needed
% \enquote{early}. This is just a reminder of that fact!
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{General expansion}
%
% In this section a general mechanism for defining functions that handle
% arguments is defined. These general expansion functions are
% expandable unless |x| is used. (Any version of |x| is going to have
% to use one of the \LaTeX3 names for \cs{cs_set:Npx} at some
% point, and so is never going to be expandable.)
%
% The definition of expansion functions with this technique happens
% in section~\ref{sec:l3expan:gendef}.
% In section~\ref{sec:l3expan:handtune} some common cases are coded by a more direct
% method for efficiency, typically using calls to \cs{exp_after:wN}.
%
% \begin{variable}{\l_@@_internal_tl}
% This scratch token list variable is defined in \pkg{l3basics}.
% \end{variable}
%
% This code uses internal functions with names that start with |\::| to
% perform the expansions. All macros are |long| since the tokens
% undergoing expansion may be arbitrary user input.
%
% An argument manipulator |\::|\meta{Z} always has signature |#1\:::#2#3|
% where |#1| holds the remaining argument manipulations to be performed,
% \cs{:::} serves as an end marker for the list of manipulations, |#2|
% is the carried over result of the previous expansion steps and |#3| is
% the argument about to be processed.
% One exception to this rule is \cs{::p}, which has to grab an argument
% delimited by a left brace.
%
% \begin{macro}[EXP]{\@@_arg_next:nnn}
% \begin{macro}[EXP]{\@@_arg_next:Nnn}
% |#1| is the result of an expansion step, |#2| is the remaining
% argument manipulations and |#3| is the current result of the
% expansion chain. This auxiliary function moves |#1| back after
% |#3| in the input stream and checks if any expansion is left to
% be done by calling |#2|. In by far the most cases we need
% to add a set of braces to the result of an argument manipulation
% so it is more effective to do it directly here. Actually, so far
% only the |c| of the final argument manipulation variants does not