diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3expan.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3expan.dtx | 1416 |
1 files changed, 1416 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx new file mode 100644 index 00000000000..5b37fd49aaf --- /dev/null +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -0,0 +1,1416 @@ +% \iffalse meta-comment +% +%% File: l3expan.dtx Copyright (C) 1990-2011 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 +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the "expl3 bundle" (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX3 Project. +%% +%% ----------------------------------------------------------------------- +% +%<*driver|package> +\RequirePackage{l3names} +\GetIdInfo$Id: l3expan.dtx 2480 2011-06-20 17:25:23Z bruno $ + {L3 Experimental argument expansion} +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \pkg{l3expan} package\\ Argument expansion^^A +% \thanks{This file describes v\ExplFileVersion, +% last revised \ExplFileDate.}^^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 \ExplFileDate} +% +% \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} +% +% 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 from the +% |\exp_| module. They all look alike, an example would be +% |\exp_args:NNo|. This function has three arguments, the first and the +% second are a single tokens the third argument gets +% expanded once. If |\seq_gpush:No| was not defined the example +% above 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 |\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_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 +% |\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 steps above may be automated by using the function +% |\cs_generate_variant:Nn|, described next. +% +% \section{Methods for defining variants} +% +% \begin{function}{\cs_generate_variant:Nn} +% \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} where these are not already +% defined. For each \meta{variant} given, a function is created +% which will expand its arguments as detailed and pass 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} +% will create a new function \cs{foo:cn} which will expand its first +% argument into a control sequence name and pass the result to +% \cs{foo:Nn}. Similarly +% \begin{verbatim} +% \cs_generate_variant:Nn \foo:Nn { NV , cV } +% \end{verbatim} +% would generate the functions \cs{foo:NV} and \cs{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 then the new sequence +% will also be protected. The \meta{variant} is created globally, as +% is any \cs{exp_args:N\meta{variant}} function needed to carry out +% the expansion. +% \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. +% \item +% Arguments that should consist of single tokens should come first. +% \item +% Arguments that need full expansion (\emph{i.e.}, are denoted +% with |x|) should be avoided if possible as they can not be +% processed expandably, \emph{i.e.}, functions of this type will +% not work correctly in arguments that are itself subject to |x| +% expansion. +% \item +% In general, unless in the last position, multi-token arguments +% |n|, |f|, and |o| will need special processing which is not fast. +% 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|, with possible trailing |N| or |n|, which are +% not expanded. +% \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 +% \meta{tl~var}. In this example we assume |\l_tmpa_tl| contains +% the text string |lur|. The straightforward approach is +% \begin{quote} +% |\tl_set:No \l_tmpb_tl {\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_tmpb_tl| +% and not |\cs_set_eq:NwN \aaa = \blurb| as we probably wanted. Using +% |\tl_set:Nx| is not an option as that will die horribly. Instead +% we can do a +% \begin{quote} +% |\tl_set:Nf \l_tmpb_tl {\cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }| +% \end{quote} +% which puts the desired result in |\l_tmpb_tl|. It requires +% |\toks_set:Nf| to be defined as +% \begin{quote} +% |\cs_set_nopar:Npn \tl_set:Nf { \exp_args:NNf \tl_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! +% +% \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:No} +% \begin{syntax} +% \cs{exp_args:No} \meta{function} \Arg{tokens} \Arg{tokens2} ... +% \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 will be left unchanged. +% \end{function} +% +% \begin{function}[EXP]{\exp_args:Nc, \exp_args:cc} +% \begin{syntax} +% \cs{exp_args:Nc} \meta{function} \Arg{tokens} \Arg{tokens2} ... +% \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. (An internal error +% will occur if such a conversion is not possible). 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 will be left unchanged. +% +% The |:cc| variant constructs the \meta{function} name in the same +% manner as described for the \meta{tokens}. +% \end{function} +% +% \begin{function}[EXP]{\exp_args:NV} +% \begin{syntax} +% \cs{exp_args:NV} \meta{function} \meta{variable} \Arg{tokens2} ... +% \end{syntax} +% This function absorbs two arguments (the names of the \meta{function} and +% the 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 will be left unchanged. +% \end{function} +% +% \begin{function}[EXP]{\exp_args:Nv} +% \begin{syntax} +% \cs{exp_args:Nv} \meta{function} \Arg{tokens} \Arg{tokens2} ... +% \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. (An internal error +% will occur if such a conversion is not possible). 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 will be left unchanged. +% \end{function} +% +% \begin{function}[EXP]{\exp_args:Nf} +% \begin{syntax} +% \cs{exp_args:Nf} \meta{function} \Arg{tokens} \Arg{tokens2} ... +% \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 or space is found, 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 will be left unchanged. +% \end{function} +% +% \begin{function}{\exp_args:Nx} +% \begin{syntax} +% \cs{exp_args:Nx} \meta{function} \Arg{tokens} \Arg{tokens2} ... +% \end{syntax} +% This function absorbs two arguments (the \meta{function} name and +% the \meta{tokens}) and exhaustively expands the \meta{tokens} +% second. 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 will be left unchanged. +% \end{function} +% +% \section{Manipulating two arguments} +% +% \begin{function}[EXP] +% { +% \exp_args:NNo, +% \exp_args:NNc, +% \exp_args:NNv, +% \exp_args:NNV, +% \exp_args:NNf, +% \exp_args:Nco, +% \exp_args:Ncf, +% \exp_args:Ncc, +% \exp_args:NVV +% } +% \begin{syntax} +% \cs{exp_args:NNc} \meta{token1} \meta{token2} \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] +% { +% \exp_args:Nno, +% \exp_args:NnV, +% \exp_args:Nnf, +% \exp_args:Noo, +% \exp_args:Noc, +% \exp_args:Nff, +% \exp_args:Nfo, +% \exp_args:Nnc +% } +% \begin{syntax} +% \cs{exp_args:Noo} \meta{token} \Arg{tokens1} \Arg{tokens2} +% \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 special (slower) processing. +% \end{function} +% +% \begin{function} +% { +% \exp_args:NNx, +% \exp_args:Nnx, +% \exp_args:Ncx, +% \exp_args:Nox, +% \exp_args:Nxo, +% \exp_args:Nxx +% } +% \begin{syntax} +% \cs{exp_args:NNx} \meta{token1} \meta{token2} \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. +% \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{token1} \meta{token2} \meta{token3} +% ~~\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:NNoo, +% \exp_args:NNno, +% \exp_args:Nnno, +% \exp_args:Nnnc, +% \exp_args:Nooo, +% } +% \begin{syntax} +% \cs{exp_args:NNNo} \meta{token1} \meta{token2} \meta{token3} +% ~~\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 special (slower) processing. +% \end{function} +% +% \begin{function} +% { +% \exp_args:NNnx, +% \exp_args:NNox, +% \exp_args:Nnnx, +% \exp_args:Nnox, +% \exp_args:Noox, +% \exp_args:Ncnx, +% \exp_args:Nccx +% } +% \begin{syntax} +% \cs{exp_args:NNnx} \meta{token1} \meta{token2} \meta{tokens1} +% ~~\Arg{tokens2} +% \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_last_unbraced:Nf, +% \exp_last_unbraced:NV, +% \exp_last_unbraced:No, +% \exp_last_unbraced:Nv, +% \exp_last_unbraced:NcV, +% \exp_last_unbraced:NNV, +% \exp_last_unbraced:NNo, +% \exp_last_unbraced:Nfo, +% \exp_last_unbraced:NNNV, +% \exp_last_unbraced:NNNo +% } +% \begin{syntax} +% \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens1} \meta{tokens2} +% \end{syntax} +% These functions absorb the number of arguments given by their +% specification, carry out the expansion +% indicated and leave the the results in the input stream, with the +% last argument not surrounded by the usual braces. +% Of these, \cs{exp_last_unbraced:Nfo} needs special (slower) processing. +% \end{function} +% +% \begin{function}[EXP]{\exp_last_two_unbraced:Noo} +% \begin{syntax} +% \cs{exp_last_two_unbraced:Noo} \meta{token} \meta{tokens1} \Arg{tokens2} +% \end{syntax} +% This function absorbs three arguments and expand 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{token1} \meta{token2} +% \end{syntax} +% Carries out a single expansion of \meta{token2} prior to expansion +% of \meta{token1}. If \meta{token2} is a \TeX{} primitive, it will +% be executed rather than expanded, while if \meta{token2} has not +% expansion (for example, if it is a character) then it will be left +% unchanged. It is important to notice that \meta{token1} may be +% \emph{any} single token, including group-opening and -closing +% tokens (|{| or |}"| assuming normal \TeX{} category codes). Unless +% specifically required, expansion should be carried out using an +% appropriate argument specifier variant or the appropriate +% \cs{exp_arg:N} function. +% \begin{texnote} +% This is the \TeX{} primitive \cs{expandafter} renamed. +% \end{texnote} +% \end{function} +% +% \section{Preventing expansion} +% +% \begin{function}{\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. +% \begin{texnote} +% This is the \TeX{} \cs{noexpand} primitive. +% \end{texnote} +% \end{function} +% +% \begin{function}{\exp_not:c} +% \begin{syntax} +% \cs{exp_not:c} \Arg{tokens} +% \end{syntax} +% Expands the \meta{tokens} until only unexpandable content remains, and then +% converts this into a control sequence. Further expansion of this control +% sequence is then inhibited. +% \end{function} +% +% \begin{function}{\exp_not:n} +% \begin{syntax} +% \cs{exp_not:n} \Arg{tokens} +% \end{syntax} +% Prevents expansion of the \meta{tokens} in a context where they would +% otherwise +% be expanded, for example an |x|-type argument. +% \begin{texnote} +% This is the \eTeX{} \cs{unexpanded} primitive. +% \end{texnote} +% \end{function} +% +% \begin{function}{\exp_not:V} +% \begin{syntax} +% \cs{exp_not:V} \meta{variable} +% \end{syntax} +% Recovers the content of the \meta{variable}, then prevents expansion +% of the this material in a context where it would otherwise +% be expanded, for example an |x|-type argument. +% \end{function} +% +% \begin{function}{\exp_not:v} +% \begin{syntax} +% \cs{exp_not:v} \Arg{tokens} +% \end{syntax} +% Expands the \meta{tokens} until only unexpandable content 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 is prevented in a context where it would otherwise +% be expanded, for example an |x|-type argument. +% \end{function} +% +% \begin{function}{\exp_not:o} +% \begin{syntax} +% \cs{exp_not:o} \Arg{tokens} +% \end{syntax} +% Expands the \meta{tokens} once, then prevents any further expansion in a +% context where they would otherwise +% be expanded, for example an |x|-type argument. +% \end{function} +% +% \begin{function}[EXP]{\exp_not:f} +% \begin{syntax} +% \cs{exp_not:f} \meta{tokens} +% \end{syntax} +% Expands \meta{tokens} fully until the first unexpandable token +% is found. Expansion then stops, and the result of the expansion +% (including any tokens which were not expanded) is protected from +% further expansion. +% \end{function} +% +% \begin{function}[EXP]{\exp_stop_f:} +% \begin{syntax} +% \cs{function:f} \meta{tokens} \cs{exp_stop_f:} \meta{more tokens} +% \end{syntax} +% This function terminates an \texttt{f}-type expansion. Thus if +% a function \cs{function:f} starts an \texttt{f}-type expansion +% and all of \meta{tokens} are expandable \cs{exp_stop:f} will +% terminate 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 will retain its +% form, but when typeset it produces the underlying space (\verb*| |). +% \end{function} +% +% \section{Internal functions and variables} +% +% \begin{variable}{\l_exp_tl} +% 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} +% +% \begin{function}[EXP]{\exp_eval_register:N, \exp_eval_register:c} +% \begin{syntax} +% \cs{exp_eval_register:N} \meta{variable} +% \end{syntax} +% These functions evaluates a \meta{variable} as part of a |V| or |v| +% expansion (respectively), preceeded by \cs{c_zero} which stops +% the expansion of a previous \cs{tex_romannumeral:D}. +% A \meta{variable} 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, \:::} +% \begin{syntax} +% |\cs_set_nopar: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. +% \end{function} +% +% \begin{function}{\cs_generate_internal_variant:n} +% \begin{syntax} +% \cs{cs_generate_internal_variant:n} \meta{arg~spec} +% \end{syntax} +% Tests if the function |\exp_args:N|\meta{arg~spec} exists, and defines it +% if it does not. The \meta{arg~spec} should be a series of one or more +% of the letters |N|, |c|, |n|, |o|, |V|, |v|, |f| and |x|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3expan} implementation} +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% We start by ensuring that the required packages are loaded. +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\package_check_loaded_expl: +%</package> +% \end{macrocode} +% +% \begin{macro}{\exp_after:wN} +% \begin{macro}{\exp_not:N} +% \begin{macro}{\exp_not:n} +% These are defined in \pkg{l3basics}. +% \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 |\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.}) +% +% 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{variable}{\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} +\cs_new_nopar:Npn \l_exp_tl { } +% \end{macrocode} +% \end{variable} +% +% This code uses internal functions with names that start with |\::| +% 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. +% +% 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 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 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} +\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}[int]{\:::} +% The end marker is just another name for the identity function. +% \begin{macrocode} +\cs_new:Npn \::: #1 {#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\::n} +% This function is used to skip an argument that doesn't need to +% be expanded. +% \begin{macrocode} +\cs_new:Npn \::n #1 \::: #2#3 { #1 \::: { #2 {#3} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\::N} +% This function is used to skip an argument that consists of a +% single token and doesn't need to be expanded. +% \begin{macrocode} +\cs_new:Npn \::N #1 \::: #2#3 { #1 \::: {#2#3} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\::c} +% This function is used to skip an argument that is turned into +% as control sequence without expansion. +% \begin{macrocode} +\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} +% +% \begin{macro}[int]{\::o} +% This function is used to expand an argument once. +% \begin{macrocode} +\cs_new:Npn \::o #1 \::: #2#3 + { \exp_after:wN \exp_arg_next:nnn \exp_after:wN {#3} {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% \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 |\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 +% something non-expandable or a space. We introduce |\exp_stop_f:| +% 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 |\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 \meta{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} +\cs_new:Npn \::f #1 \::: #2#3 + { + \exp_after:wN \exp_arg_next:nnn + \exp_after:wN { \tex_romannumeral:D -`0 #3 } + {#1} {#2} + } +\use:nn { \cs_new_eq:NN \exp_stop_f: } { ~ } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\::x} +% This function is used to expand an argument fully. +% \begin{macrocode} +\cs_new_protected: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} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\::v} +% \begin{macro}[int]{\::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 primitive \cs{tex_romannumeral:D} sets off an expansion +% similar to an |f| type expansion, which we will terminate using +% \cs{c_zero}. The argument is returned in braces. +% \begin{macrocode} +\cs_new:Npn \::V #1 \::: #2#3 + { + \exp_after:wN \exp_arg_next:nnn + \exp_after:wN { \tex_romannumeral:D \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 \exp_eval_register:c {#3} } + {#1} {#2} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\exp_eval_register:N, \exp_eval_register:c} +% \begin{macro}[aux]{\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 +% |\scan_stop:|. +% \begin{macrocode} +\cs_new_nopar:Npn \exp_eval_register:N #1 + { + \exp_after:wN \if_meaning:w \exp_not:N #1 #1 +% \end{macrocode} +% 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 +% |\scan_stop:|. 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 \scan_stop: #1 + \exp_eval_error_msg:w + \fi: +% \end{macrocode} +% The next bit requires some explanation. The function must be +% initiated by the primitive \cs{tex_romannumeral:D} and we want to +% terminate this expansion chain by inserting the \cs{c_zero} integer +% constant. 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 \c_zero \tex_the:D #1| and if it is a macro we +% need to execute |\exp_after:wN \c_zero #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} + \else: + \exp_after:wN \use_i_ii:nnn + \fi: + \exp_after:wN \c_zero \tex_the:D #1 + } +\cs_new_nopar:Npn \exp_eval_register:c #1 + { \exp_after:wN \exp_eval_register:N \cs:w #1 \cs_end: } +% \end{macrocode} +% 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\scan_stop:% +\tex_catcode:D`\ =11\scan_stop:% +\cs_new:Npn\exp_eval_error_msg:w#1\tex_the:D#2{% +\fi:\fi:\exp_after:wN\c_zero\erroneous variable used!}% +\group_end:% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \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. +% +% \begin{macro}{\exp_args:No} +% \begin{macro}{\exp_args:NNo} +% \begin{macro}{\exp_args:NNNo} +% Those lovely runs of expansion! +% \begin{macrocode} +\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}{\exp_args:Nc} +% In \pkg{l3basics} +%\end{macro} +% +% \begin{macro}{\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} +\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} +% +% \begin{macro}{\exp_args:Nf, \exp_args:NV, \exp_args:Nv, \exp_args:Nx} +% \begin{macrocode} +\cs_new:Npn \exp_args:Nf #1#2 + { \exp_after:wN #1 \exp_after:wN { \tex_romannumeral:D -`0 #2 } } +\cs_new:Npn \exp_args:Nv #1#2 + { + \exp_after:wN #1 \exp_after:wN + { \tex_romannumeral:D \exp_eval_register:c {#2} } + } +\cs_new:Npn \exp_args:NV #1#2 + { + \exp_after:wN #1 \exp_after:wN + { \tex_romannumeral:D \exp_eval_register:N #2 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\exp_args:NNV,\exp_args:NNv,\exp_args:NNf, +% \exp_args:NVV, +% \exp_args:Ncf,\exp_args:Nco} +% Some more hand-tuned function with three arguments. +% If we force that an |o| argument always has braces, +% we could implement \cs{exp_args:Nco} with less tokens +% and only two arguments. +% \begin{macrocode} +\cs_new:Npn \exp_args:NNf #1#2#3 + { + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN { \tex_romannumeral:D -`0 #3 } + } +\cs_new:Npn \exp_args:NNv #1#2#3 + { + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN { \tex_romannumeral:D \exp_eval_register:c {#3} } + } +\cs_new:Npn \exp_args:NNV #1#2#3 + { + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #3 } + } +\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} + } +\cs_new:Npn \exp_args:Ncf #1#2#3 + { + \exp_after:wN #1 + \cs:w #2 \exp_after:wN \cs_end: + \exp_after:wN { \tex_romannumeral:D -`0 #3 } + } +\cs_new_nopar:Npn \exp_args:NVV #1#2#3 + { + \exp_after:wN #1 + \exp_after:wN { \tex_romannumeral:D \exp_after:wN + \exp_eval_register:N \exp_after:wN #2 \exp_after:wN } + \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #3 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\exp_args:Ncco, +% \exp_args:NcNc, +% \exp_args:NcNo, +% \exp_args:NNNV} +% A few more that we can hand-tune. +% \begin{macrocode} +\cs_new:Npn \exp_args:NNNV #1#2#3#4 + { + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN #3 + \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #4 } + } +\cs_new:Npn \exp_args:NcNc #1#2#3#4 + { + \exp_after:wN #1 + \cs:w #2 \exp_after:wN \cs_end: + \exp_after:wN #3 + \cs:w #4 \cs_end: + } +\cs_new:Npn \exp_args:NcNo #1#2#3#4 + { + \exp_after:wN #1 + \cs:w #2 \exp_after:wN \cs_end: + \exp_after:wN #3 + \exp_after:wN {#4} + } +\cs_new:Npn \exp_args:Ncco #1#2#3#4 + { + \exp_after:wN #1 + \cs:w #2 \exp_after:wN \cs_end: + \cs:w #3 \exp_after:wN \cs_end: + \exp_after:wN {#4} + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Definitions with the automated technique} +% \label{sec:gendef} +% +% Some of these could be done more efficiently, but the complexity of +% coding then becomes an issue. Notice that the auto-generated functions +% are all not long: they don't actually take any arguments themselves. +% +% \begin{macro}{\exp_args:Nx} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \exp_args:Nx { \::x \::: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\exp_args:NNx, +% \exp_args:Nnc, +% \exp_args:Ncx, +% \exp_args:Nfo,\exp_args:Nff, +% \exp_args:Nnf,\exp_args:Nno,\exp_args:NnV,\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} +\cs_new_nopar:Npn \exp_args:Nnc { \::n \::c \::: } +\cs_new_nopar:Npn \exp_args:Nfo { \::f \::o \::: } +\cs_new_nopar:Npn \exp_args:Nff { \::f \::f \::: } +\cs_new_nopar:Npn \exp_args:Nnf { \::n \::f \::: } +\cs_new_nopar:Npn \exp_args:Nno { \::n \::o \::: } +\cs_new_nopar:Npn \exp_args:NnV { \::n \::V \::: } +\cs_new_nopar:Npn \exp_args:Noc { \::o \::c \::: } +\cs_new_nopar:Npn \exp_args:Noo { \::o \::o \::: } +\cs_new_protected_nopar:Npn \exp_args:NNx { \::N \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Ncx { \::c \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Nnx { \::n \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Nox { \::o \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Nxo { \::x \::o \::: } +\cs_new_protected_nopar:Npn \exp_args:Nxx { \::x \::x \::: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\exp_args:Nccx, +% \exp_args:Ncnx, +% \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_new_nopar:Npn \exp_args:NNno { \::N \::n \::o \::: } +\cs_new_nopar:Npn \exp_args:NNoo { \::N \::o \::o \::: } +\cs_new_nopar:Npn \exp_args:Nnnc { \::n \::n \::c \::: } +\cs_new_nopar:Npn \exp_args:Nnno { \::n \::n \::o \::: } +\cs_new_nopar:Npn \exp_args:Nooo { \::o \::o \::o \::: } +\cs_new_protected_nopar:Npn \exp_args:NNnx { \::N \::n \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:NNox { \::N \::o \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Nnnx { \::n \::n \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Nnox { \::n \::o \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Nccx { \::c \::c \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Ncnx { \::c \::n \::x \::: } +\cs_new_protected_nopar:Npn \exp_args:Noox { \::o \::o \::x \::: } +% \end{macrocode} +% \end{macro} +% +% \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 \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 \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:No} +% \begin{macro}{\exp_last_unbraced:NcV} +% \begin{macro}{\exp_last_unbraced:NNV} +% \begin{macro}{\exp_last_unbraced:NNo} +% \begin{macro}{\exp_last_unbraced:Noo} +% \begin{macro}{\exp_last_unbraced:Nfo} +% \begin{macro}{\exp_last_unbraced:NNNV} +% \begin{macro}{\exp_last_unbraced:NNNo} +% Now the business end: most of these are hand-tuned for speed, but the +% general system is in place. +% \begin{macrocode} +\cs_new:Npn \exp_last_unbraced:NV #1#2 + { \exp_after:wN #1 \tex_romannumeral:D \exp_eval_register:N #2 } +\cs_new:Npn \exp_last_unbraced:Nv #1#2 + { \exp_after:wN #1 \tex_romannumeral:D \exp_eval_register:c {#2} } +\cs_new:Npn \exp_last_unbraced:No #1#2 { \exp_after:wN #1 #2 } +\cs_new:Npn \exp_last_unbraced:Nf #1#2 + { \exp_after:wN #1 \tex_romannumeral:D -`0 #2 } +\cs_new:Npn \exp_last_unbraced:NcV #1#2#3 + { + \exp_after:wN #1 + \cs:w #2 \exp_after:wN \cs_end: + \tex_romannumeral:D \exp_eval_register:N #3 + } +\cs_new:Npn \exp_last_unbraced:NNV #1#2#3 + { + \exp_after:wN #1 + \exp_after:wN #2 + \tex_romannumeral:D \exp_eval_register:N #3 + } +\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:Noo { \::o \::o_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:Nfo { \::f \::o_unbraced \::: } +\cs_new:Npn \exp_last_unbraced:NNNV #1#2#3#4 + { + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN #3 + \tex_romannumeral:D \exp_eval_register:N #4 + } +\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} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\exp_last_two_unbraced:Noo} +% If |#2| is a single token then this can be implemented as +% \begin{verbatim} +% \cs_new:Npn \exp_last_two_unbraced:Noo #1 #2 #3 +% { \exp_after:wN \exp_after:wN \exp_after:wN #1 \exp_after:wN #2 #3 } +% \end{verbatim} +% However, for robustness this is not suitable. Instead, a bit of a +% shuffle is used to ensure that |#2| can be multiple tokens. +% \begin{macrocode} +\cs_new:Npn \exp_last_two_unbraced:Noo #1#2#3 + { \exp_after:wN \exp_last_two_unbraced_aux:nnN \exp_after:wN {#3} {#2} #1 } +\cs_new:Npn \exp_last_two_unbraced_aux:nnN #1#2#3 + { \exp_after:wN #3 #2 #1 } +% \end{macrocode} +% \end{macro} +% +% \subsection{Preventing expansion} +% +% \begin{macro}{\exp_not:o} +% \begin{macro}{\exp_not:f} +% \begin{macro}{\exp_not:V} +% \begin{macro}{\exp_not:v} +% \begin{macrocode} +\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} } +\cs_new:Npn \exp_not:f #1 + { \etex_unexpanded:D \exp_after:wN { \tex_romannumeral:D -`0 #1 } } +\cs_new:Npn \exp_not:V #1 + { + \etex_unexpanded:D \exp_after:wN + { \tex_romannumeral:D \exp_eval_register:N #1 } + } +\cs_new:Npn \exp_not:v #1 + { + \etex_unexpanded:D \exp_after:wN + { \tex_romannumeral:D \exp_eval_register:c {#1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\exp_not:c} +% A helper function. +% \begin{macrocode} +\cs_new:Npn \exp_not:c #1 { \exp_after:wN \exp_not:N \cs:w #1 \cs_end: } +% \end{macrocode} +% \end{macro} +% +% \subsection{Defining function variants} +% +% \begin{macro}{\cs_generate_variant:Nn} +% \begin{macro}[aux]{\cs_generate_variant_aux:nnNNn} +% \begin{macro}[aux]{\cs_generate_variant_aux:Nnnw} +% \begin{macro}[aux]{\cs_generate_variant_aux:NNn} +% \begin{macro}[aux]{\cs_generate_variant_aux:N} +% \begin{arguments} +% \item Base form of a function; \emph{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} +\cs_new_protected:Npn \cs_generate_variant:Nn #1 + { + \chk_if_exist_cs:N #1 + \cs_split_function:NN #1 \cs_generate_variant_aux:nnNNn + #1 + } +% \end{macrocode} +% We discard the boolean |#3| and then set off a loop through the desired +% variant forms. The original function is retained as |#4| for efficiency. +% \begin{macrocode} +\cs_new:Npn \cs_generate_variant_aux:nnNNn #1#2#3#4#5 + { \cs_generate_variant_aux:Nnnw #4 {#1}{#2} #5 , ? , \q_recursion_stop } +% \end{macrocode} +% Next is the real work to be done. We now have 1: original function, +% 2: base name, 3: base signature, 4: 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. +% Then build the variant function once, to avoid repeating this +% relatively expensive operation. Then recurse. +% \begin{macrocode} +\cs_new:Npn \cs_generate_variant_aux:Nnnw #1#2#3#4 , + { + \if:w ? #4 + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + \exp_args:NNc \cs_generate_variant_aux:NNn + #1 + { #2 : #4 \use:c { use_none: \cs_generate_variant_aux:N #4 ? } #3 } + {#4} + \cs_generate_variant_aux:Nnnw #1 {#2} {#3} + } +% \end{macrocode} +% Check if the variant form has already been defined. +% If not, then define it and then additionally check if +% the |\exp_args:N| form needed is defined. +% Otherwise tell that it was already defined. +% \begin{macrocode} +\cs_new:Npn \cs_generate_variant_aux:NNn #1 #2 #3 + { + \cs_if_free:NTF #2 + { + \cs_generate_variant_aux:NNpx #1 #2 + { \exp_not:c { exp_args:N #3 } \exp_not:N #1 } + \cs_generate_internal_variant:n {#3} + } + { + \iow_log:x + { + Variant~\token_to_str:N #2~% + already~defined;~ not~ changing~ it~on~line~% + \tex_the:D \tex_inputlineno:D + } + } + } +% \end{macrocode} +% The small loop for defining the required number of |n|s. Break when +% seeing a |?|. +% \begin{macrocode} +\cs_new: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}[aux]{\cs_generate_variant_aux:NNpx} +% \begin{macro}[aux]{\cs_generate_variant_aux:w} +% The idea here is to pick up protected parent functions, using the +% nature of the meaning string that they generate. The test here is +% almost the same as \cs{tl_if_empty:nTF}, but has to be hard-coded as +% that function is not yet available and because it has to match both +% long and short macros. +% \begin{macrocode} +\group_begin: + \tex_lccode:D `\Z = `\d \scan_stop: + \tex_lccode:D `\? =`\\ \scan_stop: + \tex_catcode:D `\P = 12 \scan_stop: + \tex_catcode:D `\R = 12 \scan_stop: + \tex_catcode:D `\O = 12 \scan_stop: + \tex_catcode:D `\T = 12 \scan_stop: + \tex_catcode:D `\E = 12 \scan_stop: + \tex_catcode:D `\C = 12 \scan_stop: + \tex_catcode:D `\Z = 12 \scan_stop: +\tex_lowercase:D + { + \group_end: + \cs_new_nopar:Npn \cs_generate_variant_aux:NNpx #1 + { + \exp_after:wN \cs_generate_variant_aux:w + \token_to_meaning:N #1 ? PROTECTEZ \q_stop + } + \cs_new:Npn \cs_generate_variant_aux:w #1 ? PROTECTEZ #2 \q_stop + { + \if_catcode:w a \etex_detokenize:D \exp_after:wN {#1} a + \exp_after:wN \cs_new_protected_nopar:Npx + \else: + \exp_after:wN \cs_new_nopar:Npx + \fi: + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\cs_generate_internal_variant:n} +% \begin{macro}[aux]{\cs_generate_internal_variant_aux: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} +\cs_new_protected:Npn \cs_generate_internal_variant:n #1 + { + \cs_if_free:cT { exp_args:N #1 } + { + \cs_new:cpx { exp_args:N #1 } + { \cs_generate_internal_variant_aux:N #1 : } + } + } +% \end{macrocode} +% 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} +\cs_new:Npn \cs_generate_internal_variant_aux:N #1 + { + \exp_not:c { :: #1 } + \if_meaning:w #1 : + \exp_after:wN \use_none:n + \fi: + \cs_generate_internal_variant_aux:N + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%\subsection{Variants which cannot be created earlier} +% +% \begin{macro}[pTF] +% {\str_if_eq:Vn, \str_if_eq:on, \str_if_eq:nV, \str_if_eq:no, \str_if_eq:VV} +% These cannot come earlier as they need \cs{cs_generate_variant:Nn}. +% \begin{macrocode} +\cs_generate_variant:Nn \str_if_eq_p:nn { V , o } +\cs_generate_variant:Nn \str_if_eq_p:nn { nV , no , VV } +\cs_generate_variant:Nn \str_if_eq:nnT { V , o } +\cs_generate_variant:Nn \str_if_eq:nnT { nV , no , VV } +\cs_generate_variant:Nn \str_if_eq:nnF { V , o } +\cs_generate_variant:Nn \str_if_eq:nnF { nV , no , VV } +\cs_generate_variant:Nn \str_if_eq:nnTF { V , o } +\cs_generate_variant:Nn \str_if_eq:nnTF { nV , no , VV } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex |