diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3expan.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3expan.dtx | 1378 |
1 files changed, 748 insertions, 630 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3expan.dtx b/Master/texmf-dist/source/latex/expl3/l3expan.dtx index 1efadb1dab3..7f2323b2e0c 100644 --- a/Master/texmf-dist/source/latex/expl3/l3expan.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3expan.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3expan.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3expan.dtx Copyright (C) 1990-2009 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 @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} %</driver|package> %\fi -\GetIdInfo$Id: l3expan.dtx 735 2008-01-14 22:31:02Z morten $ +\GetIdInfo$Id: l3expan.dtx 1376 2009-06-01 17:01:30Z morten $ {L3 Experimental Argument Expansion module} %\iffalse %<*driver> @@ -44,153 +44,37 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3expan.dtx} \end{document} %</driver> % \fi % % -% \title{The \textsf{l3expan} package\thanks{This file +% \title{The \pkg{l3expan} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ -% Controlling Expansion of Command Arguments} +% Controlling Expansion of Function Arguments} % \author{\Team} % \date{\filedate} % \maketitle % +% \begin{documentation} % -% \section{\LaTeX3 functions} +% \section{Brief overview} % -% All \LaTeX3 functions contain a colon in their -% name. Characters following the colon are used to denote the number and -% the ``type'' of arguments that the function takes. An uppercase "N" is -% used to denote an argument that consists of a single token and a -% lowercase "n" is used when the argument can consist of several tokens -% surrounded by braces. In case of "n" arguments that consist of a -% single token the surrounding braces can be omitted in nearly all -% situations---functions that force the use of braces even for single -% token arguments are explicitly mentioned. For example, "\seq_gpush:Nn" -% is a function that takes two arguments, the first is a single token -% (the sequence) and the second may consist of several tokens surrounded -% by braces. +% The functions in this module all have prefix |exp|. % -% This concept of argument specification makes it easy to read the code -% and should be followed when defining new functions. -% -% \subsection{Expanding arguments of functions} -% -% Within code it is often necessary to expand or partially expand -% arguments before passing it on to some function. For example, if the -% token list pointer "\l_tmpa_tlp" contains the current file -% that should be pushed onto some stack, we can not write -% \begin{quote} -% "\seq_gpush:Nn" \\ -% " \g_file_name_stack" \\ -% " \l_tmpa_tlp" -% \end{quote} -% since this would put the token "\l_tmpa_tlp" and not its -% contents on the stack. Instead a suitable number of "\exp_after:NN" -% would be necessary (together with extra braces) to change the order of -% execution, i.e. -% \begin{quote} -% "\exp_after:NN" \\ -% " \seq_gpush:Nn" \\ -% "\exp_after:NN" \\ -% " \g_file_name_stack" \\ -% "\exp_after:NN" \\ -% " {\l_tmpa_tlp}" -% \end{quote} -% -% The above example is probably the simplest case but is already shows -% how the code changes to something difficult to understand. Therefore -% \LaTeX3 provides the programmer with a general scheme that keeps the -% code compact and easy to understand. -% To denote that some argument to a function needs special treatment one -% just uses different letters in the argument part of the function to -% mark the desired behavior. In the above example one would write -% \begin{quote} -% "\seq_gpush:No" \\ -% " \g_file_name_stack" \\ -% " \l_tmpa_tlp" -% \end{quote} -% to achieve the desired effect. Here the "o" stands for expand this -% (the second) argument once before passing it to the function. -% -% The following letters can be used to denote special treatment of -% arguments before passing it to the basic function: -% \begin{description} -% \item[o] One time expanded token or token-list. In the latter case, -% effectively only the first token in the list gets expanded. Since -% the expansion might result in more than one token, the result is -% surrounded for further processing with braces. -% -% \item[x] Fully expanded token or token-list. Like "o" but the -% argument is expanded using "\def:Npx" before it is passed on. This means -% that expansion takes place until only unexpandable tokens are left. -% -% \item[f] Almost the same as the |x| type except here the token list -% is expanded fully until the first unexpandable token is found and -% the rest is left unchanged. Note that if this function finds a -% space at the beginning of the argument it will gobble it and not -% expand the next argument. -% -% \item[N,O,X] Like "n", "o", "x" but the argument must be a single -% token without any braces around it. -% -% \item[c] A character string or a token-list that ultimately expands -% to characters. This string (after expansion) is used to construct a -% command name that is eventually passed on. -% -% \item[C] A character string or a token-list that ultimately expands -% to characters. From this string (after expansion) a command name is -% constructed and then this command name is expanded once (like "o"). -% The result of this is eventually passed on. In other words -% \begin{quote} -% "\seq_gpush:NC" \\ -% " \g_file_name_stack" \\ -% " {l_tmpa_tlp}" -% \end{quote} -% Has the same effect as the example above. -% -% -% \end{description} -% -% Here are three new expansion types that may be useful but I'm not -% sure yet. Only time will tell\dots{} Proper documentation of these -% functions is postponed until later. -% \begin{description} -% \item[d] This is pretty much like the |o| type except the token list -% get's expanded twice before being passed on. (|d| is for double.) -% It is often useful in conjunction with a forced expansion. -% -% \item[E] Sometimes you need to unpack a token list or something else -% but you don't want it to add the braces that the |o| type -% does. This is where you usually wind up with a lot of -% |\exp_after:NN|s and we would like to avoid that. This type works -% quite well with the other syntax but it won't work in certain -% circumstances: Since the generic expansion functions read their -% arguments when the expanded code is shuffled around, this type -% will have a problem if the last token you want to expand once is -% |\token_to_str:N| \emph{and} you're in an argument expansion -% process involving arguments in braces such as the |n| and |o| type -% arguments. If you stick to functions invloving only |N| and |E| -% everything will work just fine. (|E| is for expanded, single -% token.) -% -% \item[e] Same as above but the argument must be given in braces. -% \end{description} -% -% Due to memory constraints 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. +% 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. +% % -% \subsection{Defining new variants} +% \section{Defining new variants} % % The definition of variant forms for base functions may be necessary % when writing new functions or when applying a kernel function in a @@ -202,11 +86,11 @@ % second are a single tokens the third argument gets % expanded once. If "\seq_gpush:No" wouldn't be defined the example % above could be coded in the following way: -% \begin{quote} -% "\exp_args:NNo\seq_gpush:Nn" \\ -% " \g_file_name_stack" \\ -% " \l_tmpa_tlp" -% \end{quote} +% \begin{verbatim} +% \exp_args:NNo\seq_gpush:Nn +% \g_file_name_stack +% \l_tmpa_tl +% \end{verbatim} % In other words, the first argument to "\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 @@ -215,85 +99,132 @@ % how the variants are defined. They just expand into the appropriate % "\exp_" function followed by the desired base function, e.g. % \begin{quote} -% "\def_new:Npn\seq_gpush:No{\exp_args:NNo\seq_gpush:Nn}" +% "\cs_new_nopar:Npn\seq_gpush:No{\exp_args:NNo\seq_gpush:Nn}" % \end{quote} % Providing variants in this way in style files is uncritical as the -% "\def_new:Npn" function will silently accept definitions whenever the +% "\cs_new_nopar:Npn" function will silently accept definitions whenever the % new definition is identical to an already given one. Therefore adding % such definition to later releases of the kernel will not make such % style files obsolete. % -% The |f| type is so special that it deserves an example. -% Let's pretend we want to set "\aaa" equal to the control sequence -% stemming from turning "b \l_tmpa_tlp b" into a control -% sequence. Furthermore we want to store the execution of it in a -% \m{toks} register. In this example we assume "\l_tmpa_tlp" contains -% the text string "lur". The straight forward approach is -% \begin{quote} -% "\toks_set:No \l_tmpa_toks {\let:Nc \aaa {b \l_tmpa_tlp b}}" -% \end{quote} -% Unfortunately this only puts -% "\exp_args:NNc \let:NN \aaa {b \l_tmpa_tlp b}" into "\l_tmpa_toks" -% and not "\let:NwN \aaa = \blurb" as we probably wanted. Using -% "\toks_set:Nx" is not an option as that will die horribly. Instead -% we can do a -% \begin{quote} -% "\toks_set:Nf \l_tmpa_toks {\let:Nc \aaa {b \l_tmpa_tlp b}}" -% \end{quote} -% which puts the desired result in "\l_tmpa_toks". It requires -% "\toks_set:Nf" to be defined as -% \begin{quote} -% "\def:Npn \toks_set:Nf {\exp_args:NNf \toks_set:Nn}" -% \end{quote} -% If you use this type of expansion in conditional processing then -% you should stick to using "TF" type functions only as it does not -% try to finish any "\if... \fi:" itself! -% -% -% -% -% -% The available internal functions for argument expansion come in to +% The steps above may be automated by using the function +% "\cs_generate_variant:Nn", described next. +% +% \subsection{Methods for defining variants} +% +% \begin{function}{\cs_generate_variant:Nn} +% \begin{syntax} +% "\cs_generate_variant:Nn" <function> <variant argument> +% "\cs_generate_variant:Nn " "\foo:Nn" "{c}" +% "\cs_generate_variant:Nn" "\foo:Nn" "{c,Nx,cx}" +% \end{syntax} +% This function greatly simplify the task of defining +% variantions on a base function with differing expansion control. +% The first example is equivalent to writing +% \begin{verbatim} +% \cs_set_nopar:Npn \foo:cn { \exp_args:Nc \foo:Nn } +% \end{verbatim} +% If used with a comma-separated list of variants, it does so for each +% variant form, i.e., the second example is equivalent to +% \begin{verbatim} +% \cs_set_nopar:Npn \foo:cn { \exp_args:Nc \foo:Nn } +% \cs_set_nopar:Npn \foo:Nx { \exp_args:NNx \foo:Nn } +% \cs_set_nopar:Npn \foo:cx { \exp_args:Ncx \foo:Nn } +% \end{verbatim} +% \end{function} +% +% \paragraph{Internal functions} \mbox{} +% +% \begin{function}{\cs_generate_internal_variant:n} +% \begin{syntax} +% "\cs_generate_internal_variant:n" \Arg{args} +% \end{syntax} +% Defines the appropriate "\exp_args:N"<args> function, if necessary, +% to perform the expansion control specified by <args>. +% \end{function} +% +% \section{Introducing the variants} +% +% The available internal functions for argument expansion come in two % flavours, some of them are faster then others. Therefore it is usually % best to follow the following guidelines when defining new functions % that are supposed to come with variant forms: % \begin{itemize} % \item % Arguments that might need expansion should come first in the list of -% arguments to make processing faster. +% arguments to make processing faster. % \item % Arguments that should consist of single tokens should come first. % \item % Arguments that need full expansion (i.e., are denoted with "x") -% should be avoided if possible as they can not be processed very fast. +% should be avoided if possible as they can not be processed very fast. % \item % In general "n", "x", and "o" (if not in the last position) will % need special processing which is not fast and not expandable, % i.e., functions of this type may not work correctly in arguments % that are itself subject to "x" expansion. Therefore it is best to % use the ``expandable'' functions (i.e., those that contain only -% "c", "N", "O", "o" or "f" in the last position) whenever possible. +% "c", "N", "o" or "f" in the last position) whenever possible. % \end{itemize} % +% The |V| type returns the value of a register, which can be one of +% |tl|, |num|, |int|, |skip|, |dim|, |toks|, 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. This recent addition to the argument specifiers may shake +% things up a bit as most places where |o| is used will be replaced by +% |V|. The documentation you are currently reading will therefore +% require a fair bit of re-writing. +% +% 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 |f| type is so special that it deserves an example. +% Let's pretend we want to set "\aaa" equal to the control sequence +% stemming from turning "b \l_tmpa_tl b" into a control +% sequence. Furthermore we want to store the execution of it in a +% \m{toks} register. In this example we assume "\l_tmpa_tl" contains +% the text string "lur". The straight forward approach is +% \begin{quote} +% "\toks_set:No \l_tmpa_toks {\cs_set_eq:Nc \aaa {b \l_tmpa_tl b}}" +% \end{quote} +% Unfortunately this only puts +% "\exp_args:NNc \cs_set_eq:NN \aaa {b \l_tmpa_tl b}" into "\l_tmpa_toks" +% and not "\cs_set_eq:NwN \aaa = \blurb" as we probably wanted. Using +% "\toks_set:Nx" is not an option as that will die horribly. Instead +% we can do a +% \begin{quote} +% "\toks_set:Nf \l_tmpa_toks {\cs_set_eq:Nc \aaa {b \l_tmpa_tl b}}" +% \end{quote} +% which puts the desired result in "\l_tmpa_toks". It requires +% "\toks_set:Nf" to be defined as +% \begin{quote} +% "\cs_set_nopar:Npn \toks_set:Nf {\exp_args:NNf \toks_set:Nn}" +% \end{quote} +% If you use this type of expansion in conditional processing then +% you should stick to using "TF" type functions only as it does not +% try to finish any "\if... \fi:" itself! +% % % When pdf\TeX\ 1.50 arrives, it will contain a primitive for % performing the equivalent of an "x" expansion after only one % expansion and most importantly: as an expandable operation. -% \begin{function}{% -% \exp_arg:x -% } +% \begin{function}{\exp_arg:x} % \begin{syntax} -% " \exp_arg:x" "{" <arg> "}" +% "\exp_arg:x" \Arg{arg} % \end{syntax} % <arg> is expanded fully using an "x" expansion. % \end{function} % % -% \subsection{Manipulating the first argument} % -% \begin{function}{% -% \exp_args:No -% } +% \section{Manipulating the first argument} +% +% \begin{function}{ \exp_args:No / (EXP) } % \begin{syntax} % " \exp_args:No" <funct> <arg1> <arg2> "..." % \end{syntax} @@ -302,9 +233,16 @@ % more than one argument---all others are passed unchanged. % \end{function} % -% \begin{function}{% -% \exp_args:Nc -% } +% \begin{function}{ \exp_args:Nd / (EXP) } +% \begin{syntax} +% " \exp_args:Nd" <funct> <arg1> <arg2> "..." +% \end{syntax} +% The first argument of <funct> (i.e., <arg1>) is expanded twice, the +% result is surrounded by braces and passed to <funct>. <funct> may have +% more than one argument---all others are passed unchanged. +% \end{function} +% +% \begin{function}{ \exp_args:Nc / (EXP) | \exp_args:cc / (EXP) } % \begin{syntax} % " \exp_args:Nc" <funct> <arg1> <arg2> "..." % \end{syntax} @@ -313,25 +251,32 @@ % result of this expansion.) Then the result is turned into a control % sequence and passed to <funct> as the first argument. <funct> may have % more than one argument---all others are passed unchanged. +% +% In the ":cc" variant, the <funct> control sequence itself is constructed +% (with the same process as described above) before <arg1> is turned into a +% control sequence and passed as its argument. % \end{function} % -% \begin{function}{% -% \exp_args:NC -% } +% \begin{function}{ \exp_args:NV / (EXP) } % \begin{syntax} -% " \exp_args:Nc" <funct> <arg1> <arg2> "..." +% " \exp_args:NV" <funct> <register> % \end{syntax} -% The first argument of <funct> (i.e., <arg1>) is expanded until only -% characters remain. (An internal error occurs if something else is the -% result of this expansion.) Then the result is turned into a control -% sequence which is then expanded once more. The result of this is then -% passed to <funct> as the first argument. <funct> may have more than -% one argument---all others are passed unchanged. +% The first argument of <funct> (i.e., <register>) is expanded to its +% value. By value we mean a number stored in an |int| or |num| +% register, the length value of a |dim|, |skip| or |muskip| register, the +% contents of a |toks| register or the unexpanded contents of a |tl var.| +% register. The value is passed onto <funct> in braces. % \end{function} % -% \begin{function}{% -% \exp_args:Nx -% } +% \begin{function}{ \exp_args:Nv / (EXP) } +% \begin{syntax} +% " \exp_args:Nv" <funct> \Arg{register} +% \end{syntax} +% Like the |V| type except the register is given by a list of +% characters from which a control sequence name is generated. +% \end{function} +% +% \begin{function}{ \exp_args:Nx } % \begin{syntax} % " \exp_args:Nx" <funct> <arg1> <arg2> "..." % \end{syntax} @@ -342,9 +287,7 @@ % As mentioned before, this type of function is relatively slow. % \end{function} % -% \begin{function}{% -% \exp_args:Nf -% } +% \begin{function}{ \exp_args:Nf / (EXP) } % \begin{syntax} % " \exp_args:Nf" <funct> <arg1> <arg2> "..." % \end{syntax} @@ -355,8 +298,7 @@ % Beware of its special behavior as explained above. % \end{function} % -% -% \subsection{Manipulating two arguments} +% \section{Manipulating two arguments} % % \begin{function}{% % \exp_args:NNx | @@ -374,16 +316,22 @@ % \end{function} % % \begin{function}{% -% \exp_args:NNo | -% \exp_args:NNf | -% \exp_args:Nno | -% \exp_args:NNc | -% \exp_args:Noo | -% \exp_args:NOo | -% \exp_args:NOc | -% \exp_args:Nco | -% \exp_args:Ncc | -% \exp_args:NNC | +% \exp_args:NNo / (EXP) | +% \exp_args:NNc / (EXP) | +% \exp_args:NNv / (EXP) | +% \exp_args:NNV / (EXP) | +% \exp_args:NNd / (EXP) | +% \exp_args:NNf / (EXP) | +% \exp_args:Nno / (EXP) | +% \exp_args:Nnf / (EXP) | +% \exp_args:Noo / (EXP) | +% \exp_args:Noc / (EXP) | +% \exp_args:Nco / (EXP) | +% \exp_args:Ncf / (EXP) | +% \exp_args:Ncc / (EXP) | +% \exp_args:Nff / (EXP) | +% \exp_args:Nfo / (EXP) | +% \exp_args:NVV / (EXP) | % } % \begin{syntax} % "\exp_args:NNo" <funct> <arg1> <arg2> "..." @@ -391,17 +339,20 @@ % These are the fast and expandable functions for the first two arguments. % \end{function} % -% \subsection{Manipulating three arguments} +% \section{Manipulating three arguments} % % So far not all possible functions are provided and even the selection % below may be reduced in the future as far as the non-expandable % functions are concerned. % % \begin{function}{% +% \exp_args:NNnx | +% \exp_args:NNox | % \exp_args:Nnnx | -% \exp_args:Noox | % \exp_args:Nnox | +% \exp_args:Noox | % \exp_args:Ncnx | +% \exp_args:Nccx | % } % \begin{syntax} % "\exp_args:Nnnx" <funct> <arg1> <arg2> <arg3> "..." @@ -410,44 +361,32 @@ % \end{function} % % \begin{function}{% -% \exp_args:NnnN | -% \exp_args:Nnno | -% \exp_args:NNOo | -% \exp_args:NOOo | -% \exp_args:Nccc | -% \exp_args:NcNc | -% \exp_args:Nnnc | -% \exp_args:NcNo | -% \exp_args:Ncco | +% \exp_args:NNNo / (EXP) | +% \exp_args:NNoo / (EXP) | +% \exp_args:NNno / (EXP) | +% \exp_args:Nnno / (EXP) | +% \exp_args:Nnnc / (EXP) | +% \exp_args:Nooo / (EXP) | +% \exp_args:Nccc / (EXP) | +% \exp_args:NcNc / (EXP) | +% \exp_args:NcNo / (EXP) | +% \exp_args:Ncco / (EXP) | % } % \begin{syntax} -% "\exp_args:NNOo" <funct> <arg1> <arg2> <arg3> "..." +% "\exp_args:NNoo" <funct> <arg1> <arg2> <arg3> "..." % \end{syntax} % These are the fast and expandable functions for the first three % arguments. % \end{function} % -% \subsection{Internal functions and variables} -% -% \begin{function}{\exp_after:NN} -% \begin{syntax} -% "\exp_after:NN" <token1> <token2> -% \end{syntax} -% This will expand <token2> once before processing <token1>. This is -% similar to "\exp_args:No" except that no braces are put around the -% result of expanding <token2>. -% \begin{texnote} -% This is the primitive \tn{expandafter} which was renamed to fit into -% the naming conventions of \LaTeX3. -% \end{texnote} -% \end{function} +% \section{Preventing expansion} % % \begin{function}{\exp_not:N | % \exp_not:c | % \exp_not:n } % \begin{syntax} % "\exp_not:N" <token> -% "\exp_not:n" "{" <token list> "}" +% "\exp_not:n" \Arg{token list} % \end{syntax} % This function will prohibit the expansion of <token> in situation % where <token> would otherwise be replaced by it definition, e.g., @@ -458,45 +397,40 @@ % \end{texnote} % \end{function} % -% % \begin{function}{\exp_not:o | % \exp_not:d | -% \exp_not:f} +% \exp_not:f } % \begin{syntax} -% "\exp_not:o" "{"<token list>"}" +% "\exp_not:o" \Arg{token list} % \end{syntax} % Same as "\exp_not:n" except <token list> is expanded once for the % "o" type and twice for the "d" type and the result of this expansion -% is then prohibited from being expanded further. +% is then prohibited from being expanded further. % \end{function} -% -% \begin{function}{\exp_not:E} +% +% \begin{function}{\exp_not:V | +% \exp_not:v } % \begin{syntax} -% "\exp_not:E" <token> +% "\exp_not:V" <register> +% "\exp_not:v" \Arg{token list} % \end{syntax} -% The name of this command is a lie. Perhaps it should be called -% ``"exp_perhaps_once"''. What it actually does is, it expands <token> -% and then issues an "\exp_not:N" to prohibit further expansion of the -% first token in the replacement text of <token>. This means that if -% the replacement text of <token> consists of more than one token all -% further tokens are still subject to full expansion. -% \begin{texnote} -% This command has no equivalent. -% \end{texnote} +% The value of <register> is retrieved and then passed on to +% "\exp_not:n" which will prohibit further expansion. The |v| type +% first creates a control sequence from <token list> but is otherwise +% identical to |V|. % \end{function} -% % -% \begin{function}{\exp_stop_f: } +% \begin{function}{\exp_stop_f:} % \begin{syntax} % <f expansion> ... "\exp_stop_f:" % \end{syntax} % This function stops an "f" type expansion. An example use is one such as % \begin{verbatim} -% \tlp_set:Nf \l_tmpa_tlp { +% \tl_set:Nf \l_tmpa_tl { % \if_case:w \l_tmpa_int -% \or: \use_arg_i_after_orelse:nw{\exp_stop_f: \textbullet} -% \or: \use_arg_i_after_orelse:nw{\exp_stop_f: \textendash} -% \else: \use_arg_i_after_orelse:nw{\exp_stop_f: else-item} +% \or: \use_i_after_orelse:nw {\exp_stop_f: \textbullet} +% \or: \use_i_after_orelse:nw {\exp_stop_f: \textendash} +% \else: \use_i_after_fi:nw {\exp_stop_f: else-item} % \fi: % } % \end{verbatim} @@ -508,46 +442,122 @@ % writing code. % \end{texnote} % \end{function} +% +% \section{Unbraced expansion} +% +% \begin{function}{ +% \exp_last_unbraced:Nf| +% \exp_last_unbraced:NV| +% \exp_last_unbraced:Nv| +% \exp_last_unbraced:NcV| +% \exp_last_unbraced:NNo| +% \exp_last_unbraced:NNV| +% \exp_last_unbraced:NNNo| +% } +% \begin{syntax} +% "\exp_last_unbraced:NV" <token> <variable name> +% \end{syntax} +% There are a small number of occasions where the last argument +% in an expansion run must be expanded unbraced. These functions +% should only be used inside functions, \emph{not} for creating +% variants. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} % +% \section{\pkg{l3expan} implementation} % -% \begin{variable}{\l_exp_tlp | } +% \subsection{Internal functions and variables} +% +% \begin{function}{\exp_after:wN} +% \begin{syntax} +% "\exp_after:wN" <token1> <token2> +% \end{syntax} +% This will expand <token2> once before processing <token1>. This is +% similar to "\exp_args:No" except that no braces are put around the +% result of expanding <token2>. +% \begin{texnote} +% This is the primitive \tn{expandafter} which was renamed to fit into +% the naming conventions of \LaTeX3. +% \end{texnote} +% \end{function} +% +% \begin{variable}{\l_exp_tl} % \begin{syntax}\end{syntax} % The "\exp_" module has its private variables to temporarily store % results of the argument expansion. This is done to avoid interference % with other functions using temporary variables. % \end{variable} % -% \StopEventually{} +% \begin{function}{ \exp_eval_register:N / (EXP) | +% \exp_eval_register:c / (EXP) } +% \begin{syntax} +% "\exp_eval_register:N" <register> +% \end{syntax} +% These functions evaluates a register as part of a "V" or "v" expansion +% (respectively). A register might exist as +% one of two things: A parameter-less non-long, non-protected macro +% or a built-in \TeX\ register such as |\count|. +% \end{function} +% +% \begin{function}{\::n|\::N|\::c|\::o|\::f|\::x|\::v|\::V|\::d|\:::} +% \begin{syntax} +% "\cs_set_nopar:Npn \exp_args:Ncof {\::c\::o\::f\:::}" +% \end{syntax} +% Internal forms for the base expansion types. +% \end{function} % -% \subsection {The Implementation} +% \subsection{Module code} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%<package>\ProvidesExplPackage -%<package> {\filename}{\filedate}{\fileversion}{\filedescription} -%<package>\RequirePackage{l3tlp} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +%</package> %<*initex|package> % \end{macrocode} % -% \subsubsection{General expansion} +% \begin{macro}{\exp_after:wN} +% \begin{macro}{\exp_not:N} +% \begin{macro}{\exp_not:n} +% These are defined in \pkg{l3basics}. +% \begin{macrocode} +%<*bootstrap> +\cs_set_eq:NwN \exp_after:wN \tex_expandafter:D +\cs_set_eq:NwN \exp_not:N \tex_noexpand:D +\cs_set_eq:NwN \exp_not:n \etex_unexpanded:D +%</bootstrap> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{General expansion} % % In this section a general mechanism for defining functions to handle % argument handling 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 |\def:Npx| at some point, and +% to use one of the \LaTeX3\ names for |\cs_set_nopar:Npx| at some point, and % so is never going to be expandable.\footnote{However, some % primitives have certain characteristics that means that their % arguments undergo an \texttt{x} type expansion but the primitive % is in fact still expandable. We shall make it very clear when such % a function is expandable.}) % -% In a later section some common cases are coded by a more direct -% method, typically using calls to |\exp_after:NN|. +% The definition of expansion functions with this technique happens +% in section~\ref{sec:gendef}. +% In section~\ref{sec:handtune} some common cases are coded by a more direct +% method for efficiency, typically using calls to |\exp_after:wN|. % -% \begin{macro}{\l_exp_tlp} -% We need a scratch token list pointer. +% \begin{macro}{\l_exp_tl} +% We need a scratch token list variable. +% We don't use "tl" methods so that \pkg{l3expan} can be loaded earlier. % \begin{macrocode} -\tlp_new:Nn\l_exp_tlp{} +\cs_new_nopar:Npn \l_exp_tl {} % \end{macrocode} % \end{macro} % @@ -555,20 +565,47 @@ % to perform the expansions. All macros are |long| as this turned out % to be desirable since the tokens undergoing expansion may be % arbitrary user input. -% \begin{macro}{\exp_arg_next:nnn} -% This is basically the same function as |\Dexp_arg_next:nnn|. +% +% An argument manipulator |\::|\meta{Z} always has signature |#1\:::#2#3| +% where |#1| holds the remaining argument manipulations to be performed, +% |\:::| 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. +% +% \begin{macro}[aux]{\exp_arg_next:nnn} +% \begin{macro}[aux]{\exp_arg_next_nobrace: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 auxilliary 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 will require +% 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 +% require a set of braces. % \begin{macrocode} -\def_long_new:Npn\exp_arg_next:nnn#1#2#3{ +\cs_new:Npn\exp_arg_next:nnn#1#2#3{ + #2\:::{#3{#1}} +} +\cs_new:Npn\exp_arg_next_nobrace:nnn#1#2#3{ #2\:::{#3#1} } % \end{macrocode} % \end{macro} +% \end{macro} +% +% \begin{macro}{\:::} +% The end marker is just another name for the identity function. +% \begin{macrocode} +\cs_new:Npn\:::#1{#1} +% \end{macrocode} +% \end{macro} % % \begin{macro}{\::n} % This function is used to skip an argument that doesn't need to % be expanded. % \begin{macrocode} -\def_long_new:Npn\::n#1\:::#2#3{ +\cs_new:Npn\::n#1\:::#2#3{ #1\:::{#2{#3}} } % \end{macrocode} @@ -577,9 +614,8 @@ % \begin{macro}{\::N} % This function is used to skip an argument that consists of a % single token and doesn't need to be expanded. -%^^A was \let_new:NN\::N\::n (changed to match \;N above. % \begin{macrocode} -\def_long_new:Npn\::N#1\:::#2#3{ +\cs_new:Npn\::N#1\:::#2#3{ #1\:::{#2#3} } % \end{macrocode} @@ -589,8 +625,8 @@ % This function is used to skip an argument that is turned into % as control sequence without expansion. % \begin{macrocode} -\def_long_new:Npn\::c#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn\cs:w #3\cs_end:{#1}{#2} +\cs_new:Npn\::c#1\:::#2#3{ + \exp_after:wN\exp_arg_next_nobrace:nnn\cs:w #3\cs_end:{#1}{#2} } % \end{macrocode} % \end{macro} @@ -598,8 +634,8 @@ % \begin{macro}{\::o} % This function is used to expand an argument once. % \begin{macrocode} -\def_long_new:Npn\::o#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn\exp_after:NN{\exp_after:NN{#3}}{#1}{#2} +\cs_new:Npn\::o#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn\exp_after:wN{#3}{#1}{#2} } % \end{macrocode} % \end{macro} @@ -608,7 +644,7 @@ % \begin{macro}{\::f} % \begin{macro}{\exp_stop_f:} % This function is used to expand a token list until the first -% unexpandable token is found. The underlying "\int_to_roman:w -`0" +% unexpandable token is found. The underlying "\tex_romannumeral:D -`0" % expands everything in its way to find something terminating the % number and thereby expands the function in front of it. This % scanning procedure is terminated once the expansion hits @@ -616,459 +652,541 @@ % to mark such an end of expansion marker; in case the scanner hits % a number, this number also terminates the scanning and is left % untouched. In the example shown earlier the scanning was stopped -% once \TeX{} had fully expanded "\let:Nc \aaa {b \l_tmpa_tlp b}" -% into "\let:NwN \aaa = \blurb" which then turned out to contain -% the non-expandable token "\let:NwN". Since the expansion of -% "\int_to_roman:w -`0" is \m{null}, we wind up with a fully +% once \TeX{} had fully expanded "\cs_set_eq:Nc \aaa {b \l_tmpa_tl b}" +% into "\cs_set_eq:NwN \aaa = \blurb" which then turned out to contain +% the non-expandable token "\cs_set_eq:NwN". Since the expansion of +% "\tex_romannumeral:D -`0" is \m{null}, we wind up with a fully % expanded list, only \TeX{} has not tried to execute any of the % non-expandable tokens. This is what differentiates this function % from the "x" argument type. % \begin{macrocode} -\def_long_new:Npn\::f#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn - \exp_after:NN{\exp_after:NN{\int_to_roman:w -`0 #3}} +\cs_new:Npn\::f#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{\tex_romannumeral:D -`0 #3} {#1}{#2} } -\def_new:Npn \exp_stop_f: {~} +\cs_new_nopar:Npn \exp_stop_f: {~} % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\::x} +% \begin{macro}{\::x,\exp_arg:x} % This function is used to expand an argument fully. If the % pdf\TeX\ primitive "\expanded" is present, we use it. % \begin{macrocode} -\let_new:NN \exp_arg:x \expanded % Move eventually. +\cs_new_eq:NN \exp_arg:x \expanded % Move eventually. \cs_if_free:NTF\exp_arg:x{ - \def_long_new:Npn\::x#1\:::#2#3{ - % \tlp_set:Nx\l_exp_tlp{{{#3}}} - \def:Npx \l_exp_tlp{{{#3}}} - \exp_after:NN\exp_arg_next:nnn\l_exp_tlp{#1}{#2}} + \cs_new:Npn\::x#1\:::#2#3{ + \cs_set_nopar:Npx \l_exp_tl{{#3}} + \exp_after:wN\exp_arg_next:nnn\l_exp_tl{#1}{#2}} } { - \def_long_new:Npn\::x#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn - \exp_after:NN{\exp_arg:x{{#3}}}{#1}{#2} + \cs_new:Npn\::x#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{\exp_arg:x{{#3}}}{#1}{#2} } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\:::} -% Just another name for the identity function. +% +% \begin{macro}{\::v} +% \begin{macro}{\::V} +% These functions return the value of a register, i.e., one of +% |tl|, |num|, |int|, |skip|, |dim| and |muskip|. The |V| version +% expects a single token whereas |v| like |c| creates a csname from +% its argument given in braces and then evaluates it as if it was a +% |V|. The sequence |\tex_romannumeral:D -`0| sets off an |f| type +% expansion. The argument is returned in braces. % \begin{macrocode} -\def_long_new:Npn\:::#1{#1} +\cs_new:Npn \::V#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{ + \tex_romannumeral:D -`0 + \exp_eval_register:N #3 + } + {#1}{#2} +} +\cs_new:Npn \::v#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{ + \tex_romannumeral:D -`0 + \exp_eval_register:c {#3} + } + {#1}{#2} +} % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\::C} -% This function creates a control sequence out of |#3| and expands -% that once before passing it on to |\exp_arg_next:nnn|. +% \begin{macro}{\exp_eval_register:N,\exp_eval_register:c} +% \begin{macro}{\exp_eval_error_msg:w} +% This function evaluates a register. Now a register might exist as +% one of two things: A parameter-less macro or a built-in \TeX\ +% register such as |\count|. For the \TeX\ registers we have to +% utilize a |\tex_the:D| whereas for the macros we merely have to +% expand them once. The trick is to find out when to use +% |\tex_the:D| and when not to. What we do here is try to find out +% whether the token will expand to something else when hit with +% |\exp_after:wN|. The technique is to compare the meaning of the +% register in question when it has been prefixed with |\exp_not:N| +% and the register itself. If it is a macro, the prefixed +% |\exp_not:N| will temporarily turn it into the primitive +% |\tex_relax:D|. % \begin{macrocode} -\def_long_new:Npn\::C#1\:::#2#3{ - \exp_after:NN\exp_C_aux:nnn\cs:w #3\cs_end:{#1}{#2}} +\cs_set_nopar:Npn \exp_eval_register:N #1{ + \exp_after:wN \if_meaning:w \exp_not:N #1#1 % \end{macrocode} -% \end{macro} -% -% \begin{macro}{\exp_C_aux:nnn} -% A helper function for |\::C| wich expands its argument before -% passing it on to |\exp_arg_next:nnn|. +% If the token was not a macro it may be a malformed variable from a +% |c| expansion in which case it is equal to the primitive +% |\tex_relax:D|. In that case we throw an error. We could let \TeX\ +% do it for us but that would result in the rather obscure +% \begin{quote} +% |! You can't use `\relax' after \the.| +% \end{quote} +% which while quite true doesn't give many hints as to what actually +% went wrong. We provide something more sensible. +% \begin{macrocode} + \if_meaning:w \tex_relax:D #1 + \exp_eval_error_msg:w + \fi: +% \end{macrocode} +% The next bit requires some explanation. The function must be +% initiated by the sequence |\tex_romannumeral:D -`0| and we want to +% terminate this expansion chain by inserting an |\exp_stop_f:| +% token. However, we have to expand the register |#1| before we do +% that. If it is a \TeX\ register, we need to execute the sequence +% |\exp_after:wN\exp_stop_f:\tex_the:D #1| and if it is a macro we +% need to execute |\exp_after:wN\exp_stop_f: #1|. We therefore issue +% the longer of the two sequences and if the register is a macro, we +% remove the |\tex_the:D|. % \begin{macrocode} -\def_long_new:Npn\exp_C_aux:nnn #1{ - \exp_after:NN - \exp_arg_next:nnn - \exp_after:NN - { - \exp_after:NN - {#1} - } + \else: + \exp_after:wN \use_i_ii:nnn + \fi: + \exp_after:wN \exp_stop_f: \tex_the:D #1 +} +\cs_set_nopar:Npn \exp_eval_register:c #1{ + \exp_after:wN\exp_eval_register:N\cs:w #1\cs_end: } % \end{macrocode} -% \end{macro} +% Clean up nicely, then call the undefined control sequence. The +% result is an error message looking like this: +% \begin{verbatim} +% ! Undefined control sequence. +% \exp_eval_error_msg:w ...erroneous variable used! +% +% l.55 \tl_set:Nv \l_tmpa_tl {undefined_tl} +% \end{verbatim} +% \begin{macrocode} +\group_begin:% +\tex_catcode:D`\!=11\tex_relax:D% +\tex_catcode:D`\ =11\tex_relax:D% +\cs_gset:Npn\exp_eval_error_msg:w#1\tex_the:D#2{% +\fi:\fi:\erroneous variable used!}% +\group_end:% +% \end{macrocode} +% \end{macro} +% \end{macro} +% % % Here are some that might not stay but let's see. -% \begin{macro}{\::E} -% This function is used to expand an argument once and return it -% \emph{without} braces. Use this only when you feel pretty -% comfortable about your input! Actually this is pretty much just -% generic wrapper for |\exp_after:NN|. +% +% \begin{macro}{\::d} +% This function is used to expand an argument twice. Mostly useful +% for |toks| type things. This is likely to vanish with |V| around. % \begin{macrocode} -\def_long_new:Npn\::E#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn \exp_after:NN{#3}{#1}{#2} +\cs_new:Npn\::d#1\:::#2#3{ + \exp_after:wN\exp_after:wN\exp_after:wN\exp_arg_next:nnn + \exp_after:wN\exp_after:wN\exp_after:wN{#3}{#1}{#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}{\::e} -% Same as |\::E| really but conceptually they are different. +% \subsection{Hand-tuned definitions} +% \label{sec:handtune} +% +% One of the most important features of these functions is that they +% are fully expandable and therefore allow to prefix them with +% |\pref_global:D| for example. This together with the fact that the +% `general' concept above is slower means that we should convert +% whenever possible and perhaps remove all remaining occurences by +% hand-encoding in the end. +% +% \begin{macro}{\exp_args:No} +% \begin{macro}{\exp_args:NNo} +% \begin{macro}{\exp_args:NNNo} % \begin{macrocode} -\def_long_new:Npn\::e#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn \exp_after:NN{#3}{#1}{#2} -} +\cs_new:Npn \exp_args:No #1#2{\exp_after:wN#1\exp_after:wN{#2}} +\cs_new:Npn \exp_args:NNo #1#2#3{\exp_after:wN#1\exp_after:wN#2 + \exp_after:wN{#3}} +\cs_new:Npn \exp_args:NNNo #1#2#3#4{\exp_after:wN#1\exp_after:wN#2 + \exp_after:wN#3\exp_after:wN{#4}} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\::d} -% This function is used to expand an argument twice. Mostly useful -% for |toks| type things. +% +% \begin{macro}{\exp_args:Nc,\exp_args:cc,\exp_args:NNc,\exp_args:Ncc,\exp_args:Nccc} +% Here are the functions that turn their argument into csnames but +% are expandable. % \begin{macrocode} -\def_long_new:Npn\::d#1\:::#2#3{ - \exp_after:NN\exp_after:NN\exp_after:NN\exp_arg_next:nnn - \exp_after:NN\exp_after:NN\exp_after:NN{ - \exp_after:NN\exp_after:NN\exp_after:NN{#3}}{#1}{#2} -} +\cs_set:Npn \exp_args:Nc #1#2{\exp_after:wN#1\cs:w#2\cs_end:} +\cs_new:Npn \exp_args:cc #1#2{\cs:w #1\exp_after:wN\cs_end:\cs:w #2\cs_end:} +\cs_new:Npn \exp_args:NNc #1#2#3{\exp_after:wN#1\exp_after:wN#2 + \cs:w#3\cs_end:} +\cs_new:Npn \exp_args:Ncc #1#2#3{\exp_after:wN#1 + \cs:w#2\exp_after:wN\cs_end:\cs:w#3\cs_end:} +\cs_new:Npn \exp_args:Nccc #1#2#3#4{\exp_after:wN#1 + \cs:w#2\exp_after:wN\cs_end:\cs:w#3\exp_after:wN + \cs_end:\cs:w #4\cs_end:} % \end{macrocode} % \end{macro} % -% We do most of them by hand here. This also means that we get a name -% for |\exp_after:NN| that fits with the rest of the code. +% \begin{macro}{\exp_args:Nco} +% If we force that the third argument +% always has braces, we could implement this function +% with less tokens and only two arguments. % \begin{macrocode} -\let:NN \exp_args:NE \exp_after:NN -\def:Npn \exp_args:NNE #1{\exp_args:NE#1\exp_args:NE} -\def:Npn \exp_args:NNNE #1#2{\exp_args:NE#1\exp_args:NE#2\exp_args:NE} -\def:Npn \exp_args:NEE #1{\exp_args:NE\exp_args:NE\exp_args:NE#1\exp_args:NE} -\def:Npn \exp_args:NcE #1#2{\exp_after:NN #1\cs:w #2\exp_after:NN\cs_end:} -\def:Npn \exp_args:Nd {\::d\:::} -\def:Npn \exp_args:NNd {\::N\::d\:::} +\cs_new:Npn \exp_args:Nco #1#2#3{\exp_after:wN#1\cs:w#2\exp_after:wN + \cs_end:\exp_after:wN{#3}} % \end{macrocode} +% \end{macro} +% +% \subsection{Definitions with the `general' technique} +% \label{sec:gendef} +% +% \begin{macro}{\exp_args:Nd,\exp_args:Nf,\exp_args:NV,\exp_args:Nv,\exp_args:Nx} +% \begin{macrocode} +\cs_set_nopar:Npn \exp_args:Nd {\::d\:::} +\cs_set_nopar:Npn \exp_args:Nf {\::f\:::} +\cs_set_nopar:Npn \exp_args:Nv {\::v\:::} +\cs_set_nopar:Npn \exp_args:NV {\::V\:::} +\cs_set_nopar:Npn \exp_args:Nx {\::x\:::} +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\exp_args:NC} -% \begin{macro}{\exp_args:Ncx} -% \begin{macro}{\exp_args:Ncco} -% \begin{macro}{\exp_args:Nccx} -% \begin{macro}{\exp_args:Ncnx} -% \begin{macro}{\exp_args:NcNc} -% \begin{macro}{\exp_args:Nf} -% \begin{macro}{\exp_args:NNf} -% \begin{macro}{\exp_args:Nfo} -% \begin{macro}{\exp_args:Nnf} -% \begin{macro}{\exp_args:NNno} -% \begin{macro}{\exp_args:NnnN} -% \begin{macro}{\exp_args:Nnno} -% \begin{macro}{\exp_args:Nnnx} -% \begin{macro}{\exp_args:Nno} -% \begin{macro}{\exp_args:Nnox} -% \begin{macro}{\exp_args:NNx} -% \begin{macro}{\exp_args:Nnx} -% \begin{macro}{\exp_args:Noo} -% \begin{macro}{\exp_args:Noox} -% \begin{macro}{\exp_args:Nox} -% \begin{macro}{\exp_args:Nx} -% \begin{macro}{\exp_args:Nxx} -% \begin{macro}{\exp_args:Nxx} -% \begin{macro}{\exp_args:NNC} -% \begin{macro}{\exp_args:Nnnc} -% \begin{macro}{\exp_args:NNnx} -% \begin{macro}{\exp_args:NNoo} -% \begin{macro}{\exp_args:NNox} +% \begin{macro}{\exp_args:NNV,\exp_args:NNv,\exp_args:NNd,\exp_args:NNf,\exp_args:NNx, +% \exp_args:NVV, +% \exp_args:Ncx, +% \exp_args:Nfo,\exp_args:Nff, +% \exp_args:Ncf,\exp_args:Nco, +% \exp_args:Nnf,\exp_args:Nno,\exp_args:Nnx, +% \exp_args:Noo,\exp_args:Noc,\exp_args:Nox, +% \exp_args:Nxo,\exp_args:Nxx} % Here are the actual function definitions, using the helper functions % above. % \begin{macrocode} -%\def:Npn \exp_args:NNNo {\::N\::N\::o\:::} -%\def:Npn \exp_args:NNOo {\::N\::O\::o\:::} -%\def:Npn \exp_args:NNc {\::N\::c\:::} -%\def:Npn \exp_args:NNo {\::N\::o\::\:::} -%\def:Npn \exp_args:NOOo {\::O\::O\::o\:::} -%\def:Npn \exp_args:NOc {\::O\::c\:::} -%\def:Npn \exp_args:NOo {\::O\::o\:::} -%\def:Npn \exp_args:Nc {\::c\:::} -%\def:Npn \exp_args:Ncc {\::c\::c\:::} -%\def:Npn \exp_args:Nccc {\::c\::c\::c\:::} -%\def:Npn \exp_args:Nco {\::c\::o\:::} -%\def:Npn \exp_args:No {\::o\:::} +\cs_set_nopar:Npn \exp_args:NNd {\::N\::d\:::} +\cs_set_nopar:Npn \exp_args:NNf {\::N\::f\:::} +\cs_set_nopar:Npn \exp_args:NNv {\::N\::v\:::} +\cs_set_nopar:Npn \exp_args:NNV {\::N\::V\:::} +\cs_set_nopar:Npn \exp_args:NNx {\::N\::x\:::} + +\cs_set_nopar:Npn \exp_args:Ncx {\::c\::x\:::} +\cs_set_nopar:Npn \exp_args:Nfo {\::f\::o\:::} +\cs_set_nopar:Npn \exp_args:Nff {\::f\::f\:::} +\cs_set_nopar:Npn \exp_args:Ncf {\::c\::f\:::} +\cs_set_nopar:Npn \exp_args:Nnf {\::n\::f\:::} +\cs_set_nopar:Npn \exp_args:Nno {\::n\::o\:::} +\cs_set_nopar:Npn \exp_args:Nnx {\::n\::x\:::} + +\cs_set_nopar:Npn \exp_args:Noc {\::o\::c\:::} +\cs_set_nopar:Npn \exp_args:Noo {\::o\::o\:::} +\cs_set_nopar:Npn \exp_args:Nox {\::o\::x\:::} -\def:Npn \exp_args:NC {\::C\:::} -\def:Npn \exp_args:NNC {\::N\::C\:::} -\def:Npn \exp_args:NNf {\::N\::f\:::} -\def:Npn \exp_args:NNno {\::N\::n\::o\:::} -\def:Npn \exp_args:NNnx {\::N\::n\::x\:::} % new -\def:Npn \exp_args:NNoo {\::N\::o\::o\:::} % new -\def:Npn \exp_args:NNox {\::N\::o\::x\:::} % new -\def:Npn \exp_args:NNx {\::N\::x\:::} -\def:Npn \exp_args:NcNc {\::c\::N\::c\:::} -\def:Npn \exp_args:NcNo {\::c\::N\::o\:::} -\def:Npn \exp_args:Ncco {\::c\::c\::o\:::} -\def:Npn \exp_args:Ncco {\::c\::c\::o\:::} -\def:Npn \exp_args:Nccx {\::c\::c\::x\:::} -\def:Npn \exp_args:Ncnx {\::c\::n\::x\:::} -\def:Npn \exp_args:Ncx {\::c\::x\:::} -\def:Npn \exp_args:Nf {\::f\:::} -\def:Npn \exp_args:Nfo{\::f\::o\:::} -\def:Npn \exp_args:Nnf {\::n\::f\:::} -\def:Npn \exp_args:NnnN {\::n\::n\::N\:::} %% Strange one this one... -\def:Npn \exp_args:Nnnc {\::n\::n\::c\:::} -\def:Npn \exp_args:Nnno {\::n\::n\::o\:::} -\def:Npn \exp_args:Nnnx {\::n\::n\::x\:::} -\def:Npn \exp_args:Nno {\::n\::o\:::} -\def:Npn \exp_args:Nnox {\::n\::o\::x\:::} -\def:Npn \exp_args:Nnx {\::n\::x\:::} -\def:Npn \exp_args:Noo {\::o\::o\:::} -\def:Npn \exp_args:Noox {\::o\::o\::x\:::} -\def:Npn \exp_args:Nox {\::o\::x\:::} -\def:Npn \exp_args:Nx {\::x\:::} -\def:Npn \exp_args:Nxo {\::x\::o\:::} -\def:Npn \exp_args:Nxx {\::x\::x\:::} +\cs_set_nopar:Npn \exp_args:NVV {\::V\::V\:::} + +\cs_set_nopar:Npn \exp_args:Nxo {\::x\::o\:::} +\cs_set_nopar:Npn \exp_args:Nxx {\::x\::x\:::} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} +% +% \begin{macro}{\exp_args:Ncco, +% \exp_args:Nccx, +% \exp_args:Ncnx, +% \exp_args:NcNc, +% \exp_args:NcNo, +% \exp_args:NNno, +% \exp_args:Nnno, +% \exp_args:Nnnx, +% \exp_args:Nnox, +% \exp_args:Nooo, +% \exp_args:Noox, +% \exp_args:Nnnc, +% \exp_args:NNnx, +% \exp_args:NNoo, +% \exp_args:NNox} +% \begin{macrocode} +\cs_set_nopar:Npn \exp_args:NNno {\::N\::n\::o\:::} +\cs_set_nopar:Npn \exp_args:NNnx {\::N\::n\::x\:::} +\cs_set_nopar:Npn \exp_args:NNoo {\::N\::o\::o\:::} +\cs_set_nopar:Npn \exp_args:NNox {\::N\::o\::x\:::} + +\cs_set_nopar:Npn \exp_args:Nnnc {\::n\::n\::c\:::} +\cs_set_nopar:Npn \exp_args:Nnno {\::n\::n\::o\:::} +\cs_set_nopar:Npn \exp_args:Nnnx {\::n\::n\::x\:::} +\cs_set_nopar:Npn \exp_args:Nnox {\::n\::o\::x\:::} + +\cs_set_nopar:Npn \exp_args:NcNc {\::c\::N\::c\:::} +\cs_set_nopar:Npn \exp_args:NcNo {\::c\::N\::o\:::} +\cs_set_nopar:Npn \exp_args:Ncco {\::c\::c\::o\:::} +\cs_set_nopar:Npn \exp_args:Ncco {\::c\::c\::o\:::} +\cs_set_nopar:Npn \exp_args:Nccx {\::c\::c\::x\:::} +\cs_set_nopar:Npn \exp_args:Ncnx {\::c\::n\::x\:::} + +\cs_set_nopar:Npn \exp_args:Noox {\::o\::o\::x\:::} +\cs_set_nopar:Npn \exp_args:Nooo {\::o\::o\::o\:::} +% \end{macrocode} % \end{macro} % % -% \subsubsection{Preventing expansion} +% \subsection{Preventing expansion} % % % \begin{macro}{\exp_not:o} % \begin{macro}{\exp_not:d} % \begin{macro}{\exp_not:f} +% \begin{macro}{\exp_not:v} +% \begin{macro}{\exp_not:V} % \begin{macrocode} -\def_long_new:Npn\exp_not:o#1{\exp_not:n\exp_after:NN{#1}} -\def_long_new:Npn\exp_not:d#1{ - \exp_not:n\exp_after:NN\exp_after:NN\exp_after:NN{#1} +\cs_new:Npn\exp_not:o#1{\exp_not:n\exp_after:wN{#1}} +\cs_new:Npn\exp_not:d#1{ + \exp_not:n\exp_after:wN\exp_after:wN\exp_after:wN{#1} +} +\cs_new:Npn\exp_not:f#1{ + \exp_not:n\exp_after:wN{\tex_romannumeral:D -`0 #1} +} +\cs_new:Npn\exp_not:v#1{ + \exp_not:n\exp_after:wN{\tex_romannumeral:D -`0 \exp_eval_register:c {#1}} } -\def_long_new:Npn\exp_not:f#1{ - \exp_not:n\exp_after:NN{\int_to_roman:w -`0 #1} +\cs_new:Npn\exp_not:V#1{ + \exp_not:n\exp_after:wN{\tex_romannumeral:D -`0 \exp_eval_register:N #1} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\exp_not:E} % \begin{macro}{\exp_not:c} -% Two helper functions, which we can probably live without it. +% A helper function. % \begin{macrocode} -\def_new:Npn\exp_not:E{\exp_after:NN\exp_not:N} -\def_long_new:Npn\exp_not:c#1{\exp_after:NN\exp_not:N\cs:w#1\cs_end:} +\cs_new:Npn\exp_not:c#1{\exp_after:wN\exp_not:N\cs:w#1\cs_end:} % \end{macrocode} % \end{macro} -% \end{macro} -% -% -% \subsubsection{Single token expansion} % -% Expansion for arguments that are single tokens is done with the -% functions below. I first thought of using a different module name -% but then I saw that this wouldn't do since I could then never -% determine for, say, |\seq_put:no| whether this means single, or -% general expansion. Therefore I decided to use uppercase `O' for -% single expansion. -% -% One of the most important features of these functions is that they -% are fully expandable and therefore allow to prefix them with -% |\pref_global:D| for example. This together with the fact that the -% above concept is much slower in general means that we should convert -% whenever possible and perhaps remove all remaining occurences by -% hand-encoding in the end. % -% \begin{macro}{\exp_args:No} -% \begin{macro}{\exp_args:NOo} -% \begin{macro}{\exp_args:NNo} -% \begin{macro}{\exp_args:NNO} -% \begin{macro}{\exp_args:NOOo} -% \begin{macro}{\exp_args:NNOo} -% \begin{macro}{\exp_args:NNNo} -% This looks somewhat horrible but it runs well with the other -% syntax. It is important to see that these functions really need -% single tokens as arguments whenever capital letters are used. +% \subsection{Defining function variants} +% +% +% \begin{macro}{\cs_generate_variant:Nn} +% \begin{macro}[aux]{\cs_generate_variant_aux:nnNn} +% \begin{macro}[aux]{\cs_generate_variant_aux:nnw} +% \begin{macro}[aux]{\cs_generate_variant_aux:N} +% \begin{arguments} +% \item Base form of a function; e.g., "\tl_set:Nn" +% \item One or more variant argument specifiers; e.g., "{Nx,c,cx}" +% \end{arguments} +% Split up the original base function to grab its name and signature +% consisting of $k$ letters. Then we wish to iterate through the list +% of variant argument specifiers, and for each one construct a new +% function name using the original base name, the variant signature +% consisting of $l$ letters and the last $k-l$ letters of the base +% signature. For example, for a base function "\tl_set:Nn" which +% needs a "c" variant form, we want the new signature to be "cn". % \begin{macrocode} -\def_long_new:Npn \exp_args:No #1#2{\exp_after:NN#1\exp_after:NN{#2}} -\def_long_new:Npn \exp_args:NOo #1#2#3{\exp_after:NN\exp_args:No \exp_after:NN#1 - \exp_after:NN#2\exp_after:NN{#3}} -\def_long_new:Npn \exp_args:NOOo #1#2#3#4{\exp_after:NN\exp_args:NOo - \exp_after:NN#1\exp_after:NN#2\exp_after:NN#3\exp_after:NN{#4}} -\def_long_new:Npn \exp_args:NNo #1#2#3{\exp_after:NN#1\exp_after:NN#2 - \exp_after:NN{#3}} -\def_long_new:Npn \exp_args:NNO #1#2#3 {\exp_after:NN#1 - \exp_after:NN#2 #3} -\def_long_new:Npn \exp_args:NNOo #1#2#3#4{\exp_after:NN\exp_args:NNo - \exp_after:NN#1\exp_after:NN#2\exp_after:NN#3\exp_after:NN{#4}} -\def_long_new:Npn \exp_args:NNNo #1#2#3#4{\exp_after:NN#1\exp_after:NN#2 - \exp_after:NN#3\exp_after:NN{#4}} +\cs_new:Npn \cs_generate_variant:Nn #1 { + \chk_if_exist_cs:N #1 + \cs_split_function:NN #1 \cs_generate_variant_aux:nnNn +} % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% -% \begin{macro}{\exp_args:Nc} -% \begin{macro}{\exp_args:NNc} -% \begin{macro}{\exp_args:NOc} -% \begin{macro}{\exp_args:Ncc} -% \begin{macro}{\exp_args:Nccc} -% Here are the functions that turn their argument into csnames but -% are expandable. +% We discard the boolean and then set off a loop through the desired +% variant forms. % \begin{macrocode} -\def_long_new:Npn \exp_args:Nc #1#2{\exp_after:NN#1\cs:w#2\cs_end:} -\def_long_new:Npn \exp_args:NNc #1#2#3{\exp_after:NN#1\exp_after:NN#2 - \cs:w#3\cs_end:} -\def_long_new:Npn \exp_args:NOc#1#2#3{\exp_after:NN\exp_args:No\exp_after:NN - #1\exp_after:NN#2\cs:w#3\cs_end:} -\def_long_new:Npn \exp_args:Ncc #1#2#3{\exp_after:NN#1 - \cs:w#2\exp_after:NN\cs_end:\cs:w#3\cs_end:} -\def_long_new:Npn \exp_args:Nccc #1#2#3#4{\exp_after:NN#1 - \cs:w#2\exp_after:NN\cs_end:\cs:w#3\exp_after:NN - \cs_end:\cs:w #4\cs_end:} +\cs_set:Npn \cs_generate_variant_aux:nnNn #1#2#3#4{ + \cs_generate_variant_aux:nnw {#1}{#2} #4,?,\q_recursion_stop +} +% \end{macrocode} +% Next is the real work to be done. We now have 1: base name, 2: base +% signature, 3: beginning of variant signature. To construct the new +% csname and the "\exp_args:Ncc" form, we need the variant signature. +% In our example, we wanted to discard the first two letters of the +% base signature because the variant form started with "cc". This is +% the same as putting first "cc" in the signature and then +% "\use_none:nn" followed by the base signature "NNn". We therefore +% call a small loop that outputs an "n" for each letter in the variant +% signature and use this to call the correct "\use_none:" variant. +% Firstly though, we check whether to terminate the loop. +% \begin{macrocode} +\cs_set:Npn \cs_generate_variant_aux:nnw #1 #2 #3, { + \if:w ? #3 + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: +% \end{macrocode} +% Then check if the variant form has already been defined. +% \begin{macrocode} + \cs_if_free:cTF { + #1:#3\use:c {use_none:\cs_generate_variant_aux:N #3 ?}#2 + } + { +% \end{macrocode} +% If not, then define it and then additionally check if +% the |\exp_args:N| form needed is defined. +% \begin{macrocode} + \cs_new_nopar:cpx { + #1:#3 \use:c{use_none:\cs_generate_variant_aux:N #3 ?}#2 + } + { + \exp_not:c { exp_args:N #3} \exp_not:c {#1:#2} + } + \cs_generate_internal_variant:n {#3} + } +% \end{macrocode} +% Otherwise tell that it was already defined. +% \begin{macrocode} + { + \iow_log:x{ + Variant~\token_to_str:c { + #1:#3\use:c {use_none:\cs_generate_variant_aux:N #3 ?}#2 + }~already~defined;~ not~ changing~ it~on~line~ + \tex_the:D \tex_inputlineno:D + } + } +% \end{macrocode} +% Recurse. +% \begin{macrocode} + \cs_generate_variant_aux:nnw{#1}{#2} +} +% \end{macrocode} +% The small loop for defining the required number of "n"s. Break when +% seeing a "?". +% \begin{macrocode} +\cs_set:Npn \cs_generate_variant_aux:N #1{ + \if:w ?#1 \exp_after:wN\use_none:nn \fi: n \cs_generate_variant_aux:N +} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% -% -% \begin{macro}{\exp_args:Nco} -% If we force that the third argument -% always has braces, we could implement this function -% with less tokens and only two arguments. -% \begin{macrocode} -\def_long_new:Npn \exp_args:Nco #1#2#3{\exp_after:NN#1\cs:w#2\exp_after:NN - \cs_end:\exp_after:NN{#3}} -% \end{macrocode} -% \end{macro} % % -% \begin{macro}{\exp_def_form:nnn} -% This command is a recent addition which was actually added -% when we wrote the article for TUGboat (while most of the other -% code goes way back to 1993). +% \begin{macro}{\cs_generate_internal_variant:n} +% Test if |exp_args:N #1| is already defined +% and if not define it via the +% |\::| commands using the chars in |#1| % \begin{macrocode} -\def:Npn\exp_def_form:nnn#1#2#3{ - \exp_after:NN - \def:Npn - \cs:w - #1:#3 - \exp_after:NN - \cs_end: - \exp_after:NN - { - \cs:w - exp_args:N#3 - \exp_after:NN - \cs_end: - \cs:w - #1:#2 - \cs_end: - } +\cs_new:Npn \cs_generate_internal_variant:n #1 { + \cs_if_free:cT { exp_args:N #1 }{ % \end{macrocode} -% We also have to test if |exp_args:N#3| is already defined -% and if not define it via the -% |\::| commands using the chars in |#3| +% We use "new" to log the definition if we have to make one. % \begin{macrocode} - \cs_if_free:cT - {exp_args:N#3} - {\def:cpx {exp_args:N#3} - {\exp_args_form_x:w #3 :} - } + \cs_new:cpx { exp_args:N #1 } + { \cs_generate_internal_variant_aux:n #1 : } + } } % \end{macrocode} % \end{macro} % -% -% \begin{macro}{\exp_args_form_x:w} +% \begin{macro}[aux]{\cs_generate_internal_variant_aux:n} % This command grabs char by char outputting |\::#1| (not expanded % further) until we see a |:|. That colon is in fact also turned into % |\:::| so that the required structure for |\exp_args...| commands % is correctly terminated. % \begin{macrocode} -\def_new:Npn\exp_args_form_x:w #1 { +\cs_new:Npn \cs_generate_internal_variant_aux:n #1 { \exp_not:c{::#1} - \if_meaning:NN #1 : - \else: - \exp_after:NN\exp_args_form_x:w - \fi:} + \if_meaning:w #1 : + \exp_after:wN \use_none:n + \fi: + \cs_generate_internal_variant_aux:n +} % \end{macrocode} % \end{macro} % -% Show token usage: +% \subsection{Last-unbraced versions} +% +%\begin{macro}[aux]{\exp_arg_last_unbraced:nn} +%\begin{macro}[aux]{\::f_unbraced} +%\begin{macro}[aux]{\::o_unbraced} +%\begin{macro}[aux]{\::V_unbraced} +%\begin{macro}[aux]{\::v_unbraced} +% There are a few places where the last argument needs to be available +% unbraced. First some helper macros. +% \begin{macrocode} +\cs_new:Npn \exp_arg_last_unbraced:nn #1#2 { #2#1 } +\cs_new:Npn \::f_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn + \exp_after:wN { \tex_romannumeral:D -`0 #2 } {#1} +} +\cs_new:Npn \::o_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn \exp_after:wN {#2 }{#1} +} +\cs_new:Npn \::V_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn + \exp_after:wN { \tex_romannumeral:D -`0 \exp_eval_register:N #2 } {#1} +} +\cs_new:Npn \::v_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn + \exp_after:wN { + \tex_romannumeral:D -`0 \exp_eval_register:c {#2} + } {#1} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\exp_last_unbraced:NV} +%\begin{macro}{\exp_last_unbraced:Nv} +%\begin{macro}{\exp_last_unbraced:Nf} +%\begin{macro}{\exp_last_unbraced:NcV} +%\begin{macro}{\exp_last_unbraced:NNo} +%\begin{macro}{\exp_last_unbraced:NNV} +%\begin{macro}{\exp_last_unbraced:NNNo} +% Now the business end. +% \begin{macrocode} +\cs_new_nopar:Npn \exp_last_unbraced:Nf { \::f_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:NV { \::V_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:Nv { \::v_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:NcV { + \::c \::V_unbraced \::: +} +\cs_new:Npn \exp_last_unbraced:NNo #1#2#3 { + \exp_after:wN #1 \exp_after:wN #2 #3 +} +\cs_new_nopar:Npn \exp_last_unbraced:NNV { + \::N \::V_unbraced \::: +} +\cs_new:Npn \exp_last_unbraced:NNNo #1#2#3#4 { + \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 #4 +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% % \begin{macrocode} %</initex|package> +% \end{macrocode} +% +% Show token usage: +% \begin{macrocode} %<*showmemory> \showMemUsage %</showmemory> % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.29 2006/07/30 15:43:38 morten -% Minor touch-up plus added functions needed by clist module -% -% Revision 1.28 2006/06/03 18:56:31 morten -% A few more functions -% -% Revision 1.27 2006/03/20 18:26:35 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.26 2006/02/17 23:01:47 braams -% Imported \exp_args:NNO from l3messages -% -% Revision 1.25 2005/12/27 10:00:45 morten -% Changed RCS information retrieval -% -% Revision 1.24 2005/12/22 13:56:03 morten -% Fixed error in \exp_args:NNd -% -% Revision 1.23 2005/12/21 20:44:30 morten -% Corrected typo. -% -% Revision 1.22 2005/12/06 15:34:46 morten -% Made \exp_not:o do what you'd expect -% -% Revision 1.21 2005/11/23 07:37:29 morten -% A few new expansion types, we shall see if they will be useful. -% -% Revision 1.20 2005/04/12 16:44:06 morten -% Fix to make it run as a package -% -% Revision 1.19 2005/04/12 13:24:07 morten -% Minor updates -% -% Revision 1.18 2005/04/09 21:06:46 morten -% Added yet another function. -% -% Revision 1.17 2005/04/06 21:38:10 morten -% Added more functions. -% -% Revision 1.16 2005/03/26 21:09:44 morten -% Added f argument type for "force expansion" -% -% Revision 1.15 2005/03/22 23:24:40 morten -% Fixed documentation error. -% -% Revision 1.14 2005/03/16 22:36:37 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.13 2005/03/11 21:37:37 braams -% Fixed the use of RCS information +% \end{implementation} +% \PrintIndex % +% \endinput |