summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3quark.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-05-01 03:00:54 +0000
committerNorbert Preining <norbert@preining.info>2024-05-01 03:00:54 +0000
commit6ac3dbed4b71022bd6bb0cc25e8fc3df81198498 (patch)
tree74689e5368262d351f68fb5d1f0fbea88a3af701 /macros/latex/contrib/l3kernel/l3quark.dtx
parent3bb814fe836cd59db56f2f5d07f69cb531ed25e0 (diff)
CTAN sync 202405010300
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3quark.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3quark.dtx1008
1 files changed, 0 insertions, 1008 deletions
diff --git a/macros/latex/contrib/l3kernel/l3quark.dtx b/macros/latex/contrib/l3kernel/l3quark.dtx
deleted file mode 100644
index 000063bc00..0000000000
--- a/macros/latex/contrib/l3kernel/l3quark.dtx
+++ /dev/null
@@ -1,1008 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: l3quark.dtx
-%
-% Copyright (C) 1990-2024 The LaTeX Project
-%
-% It may be distributed and/or modified under the conditions of the
-% LaTeX Project Public License (LPPL), either version 1.3c of this
-% license or (at your option) any later version. The latest version
-% of this license is in the file
-%
-% https://www.latex-project.org/lppl.txt
-%
-% This file is part of the "l3kernel bundle" (The Work in LPPL)
-% and all files in that bundle must be distributed together.
-%
-% -----------------------------------------------------------------------
-%
-% The development version of the bundle can be found at
-%
-% https://github.com/latex3/latex3
-%
-% for those people who are interested.
-%
-%<*driver>
-\documentclass[full,kernel]{l3doc}
-\begin{document}
- \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \title{^^A
-% The \pkg{l3quark} module\\ Quarks and scan marks^^A
-% }
-%
-% \author{^^A
-% The \LaTeX{} Project\thanks
-% {^^A
-% E-mail:
-% \href{mailto:latex-team@latex-project.org}
-% {latex-team@latex-project.org}^^A
-% }^^A
-% }
-%
-% \date{Released 2024-03-14}
-%
-% \maketitle
-%
-% \begin{documentation}
-%
-% Two special types of constants in \LaTeX3 are \enquote{quarks} and
-% \enquote{scan marks}. By convention all constants of type quark
-% start out with |\q_|, and scan marks start with |\s_|.
-%
-% \section{Quarks}
-%
-% Quarks are control sequences (and in fact, token lists) that expand
-% to themselves and should
-% therefore \emph{never} be executed directly in the code.
-% This would result in an endless loop!
-%
-% They are meant to be used as delimiter in weird functions, the most
-% common use case being the `stop token' (\emph{i.e.}~\cs{q_stop}).
-% For example, when writing a macro to parse a user-defined date
-% \begin{verbatim}
-% \date_parse:n {19/June/1981}
-% \end{verbatim}
-% one might write a command such as
-% \begin{verbatim}
-% \cs_new:Npn \date_parse:n #1 { \date_parse_aux:w #1 \q_stop }
-% \cs_new:Npn \date_parse_aux:w #1 / #2 / #3 \q_stop
-% { <do something with the date> }
-% \end{verbatim}
-%
-% Quarks are sometimes also used as error return values for functions
-% that receive erroneous input.
-% For example, in the function \cs{prop_get:NnN} to retrieve a value stored
-% in some key of a property list, if the key does not exist then the return value
-% is the quark \cs{q_no_value}.
-% As mentioned above, such quarks are extremely fragile and it is imperative
-% when using such functions that code is carefully written to check for
-% pathological cases to avoid leakage of a quark into an uncontrolled
-% environment.
-%
-% Quarks also permit the
-% following ingenious trick when parsing tokens:
-% when you pick up a token in a temporary variable
-% and you want to know whether you have picked up a particular quark,
-% all you have to do is compare the temporary variable to the quark using
-% \cs{tl_if_eq:NNTF}. A set of special quark testing functions is set up
-% below. All the quark testing functions are expandable although the
-% ones testing only single tokens are much faster.
-%
-% \section{Defining quarks}
-%
-% \begin{function}{\quark_new:N}
-% \begin{syntax}
-% \cs{quark_new:N} \meta{quark}
-% \end{syntax}
-% Creates a new \meta{quark} which expands only to \meta{quark}.
-% The \meta{quark} is defined globally, and an error message
-% is raised if the name was already taken.
-% \end{function}
-%
-% \begin{variable}{\q_stop}
-% Used as a marker for delimited arguments, such as
-% \begin{verbatim}
-% \cs_set:Npn \tmp:w #1#2 \q_stop {#1}
-% \end{verbatim}
-% \end{variable}
-%
-% \begin{variable}{\q_mark}
-% Used as a marker for delimited arguments when \cs{q_stop} is
-% already in use.
-% \end{variable}
-%
-% \begin{variable}{\q_nil}
-% Quark to mark a null value in structured variables or functions. Used
-% as an end delimiter when this may itself need to be tested
-% (in contrast to \cs{q_stop}, which is only ever used as a delimiter).
-% \end{variable}
-%
-% \begin{variable}{\q_no_value}
-% A canonical value for a missing value, when one is requested from
-% a data structure. This is therefore used as a \enquote{return} value
-% by functions such as \cs{prop_get:NnN} if there is no data to
-% return.
-% \end{variable}
-%
-% \section{Quark tests}
-%
-% The method used to define quarks means that the single token (\texttt{N})
-% tests are faster than the multi-token (\texttt{n}) tests. The latter
-% should therefore only be used when the argument can definitely take
-% more than a single token.
-%
-% \begin{function}[EXP,pTF]{\quark_if_nil:N}
-% \begin{syntax}
-% \cs{quark_if_nil_p:N} \meta{token}
-% \cs{quark_if_nil:NTF} \meta{token} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{token} is equal to \cs{q_nil}.
-% \end{function}
-%
-% \begin{function}[EXP,pTF]{\quark_if_nil:n, \quark_if_nil:o, \quark_if_nil:V}
-% \begin{syntax}
-% \cs{quark_if_nil_p:n} \Arg{token list} \\
-% \cs{quark_if_nil:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{token list} contains only \cs{q_nil} (distinct
-% from \meta{token list} being empty or containing \cs{q_nil} plus one
-% or more other tokens).
-% \end{function}
-%
-% \begin{function}[EXP,pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
-% \begin{syntax}
-% \cs{quark_if_no_value_p:N} \meta{token} \\
-% \cs{quark_if_no_value:NTF} \meta{token} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{token} is equal to \cs{q_no_value}.
-% \end{function}
-%
-% \begin{function}[EXP,pTF]{\quark_if_no_value:n}
-% \begin{syntax}
-% \cs{quark_if_no_value_p:n} \Arg{token list} \\
-% \cs{quark_if_no_value:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{token list} contains only \cs{q_no_value}
-% (distinct from \meta{token list} being empty or containing
-% \cs{q_no_value} plus one or more other tokens).
-% \end{function}
-%
-% \section{Recursion}
-%
-% This module provides a uniform interface to intercepting and
-% terminating loops as when one is doing tail recursion. The building
-% blocks follow below and an example is shown in
-% Section~\ref{sec:l3quark:quark-example}.
-%
-% \begin{variable}{\q_recursion_tail}
-% This quark is appended to the data structure in question and
-% appears as a real element there. This means it gets any list
-% separators around it.
-% \end{variable}
-%
-% \begin{variable}{\q_recursion_stop}
-% This quark is added \emph{after} the data structure. Its purpose
-% is to make it possible to terminate the recursion at any point
-% easily.
-% \end{variable}
-%
-% \begin{function}[EXP]{\quark_if_recursion_tail_stop:N}
-% \begin{syntax}
-% \cs{quark_if_recursion_tail_stop:N} \meta{token}
-% \end{syntax}
-% Tests if \meta{token} contains only the marker
-% \cs{q_recursion_tail}, and if so uses
-% \cs{use_none_delimit_by_q_recursion_stop:w} to terminate the
-% recursion that this belongs to. The
-% recursion input must include the marker tokens \cs{q_recursion_tail}
-% and \cs{q_recursion_stop} as the last two items.
-% \end{function}
-%
-% \begin{function}[EXP,updated = 2011-09-06]
-% {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o}
-% \begin{syntax}
-% \cs{quark_if_recursion_tail_stop:n} \Arg{token list}
-% \end{syntax}
-% Tests if the \meta{token list} contains only
-% \cs{q_recursion_tail}, and if so uses
-% \cs{use_none_delimit_by_q_recursion_stop:w} to terminate the
-% recursion that this belongs to. The
-% recursion input must include the marker tokens \cs{q_recursion_tail}
-% and \cs{q_recursion_stop} as the last two items.
-% \end{function}
-%
-% \begin{function}[EXP]{\quark_if_recursion_tail_stop_do:Nn}
-% \begin{syntax}
-% \cs{quark_if_recursion_tail_stop_do:Nn} \meta{token} \Arg{insertion}
-% \end{syntax}
-% Tests if \meta{token} contains only the marker
-% \cs{q_recursion_tail}, and if so uses
-% \cs{use_i_delimit_by_q_recursion_stop:w} to terminate the
-% recursion that this belongs to. The
-% recursion input must include the marker tokens \cs{q_recursion_tail}
-% and \cs{q_recursion_stop} as the last two items. The \meta{insertion}
-% code is then added to the input stream after the recursion has
-% ended.
-% \end{function}
-%
-% \begin{function}[EXP,updated = 2011-09-06]
-% {\quark_if_recursion_tail_stop_do:nn, \quark_if_recursion_tail_stop_do:on}
-% \begin{syntax}
-% \cs{quark_if_recursion_tail_stop_do:nn} \Arg{token list} \Arg{insertion}
-% \end{syntax}
-% Tests if the \meta{token list} contains only
-% \cs{q_recursion_tail}, and if so uses
-% \cs{use_i_delimit_by_q_recursion_stop:w} to terminate the
-% recursion that this belongs to. The
-% recursion input must include the marker tokens \cs{q_recursion_tail}
-% and \cs{q_recursion_stop} as the last two items. The \meta{insertion}
-% code is then added to the input stream after the recursion has
-% ended.
-% \end{function}
-%
-%
-% \begin{function}[EXP,added = 2018-04-10]
-% {
-% \quark_if_recursion_tail_break:NN,
-% \quark_if_recursion_tail_break:nN
-% }
-% \begin{syntax}
-% \cs{quark_if_recursion_tail_break:nN} \Arg{token list} \cs[no-index]{\meta{type}_map_break:}
-% \end{syntax}
-% Tests if \meta{token list} contains only \cs{q_recursion_tail}, and
-% if so terminates the recursion using \cs[no-index]{\meta{type}_map_break:}.
-% The recursion end should be marked by \cs{prg_break_point:Nn}
-% \cs[no-index]{\meta{type}_map_break:}.
-% \end{function}
-%
-% \subsection{An example of recursion with quarks}
-% \label{sec:l3quark:quark-example}
-%
-% Quarks are mainly used internally in the \pkg{expl3} code to define
-% recursion functions such as \cs{tl_map_inline:nn} and so on.
-% Here is a small example to demonstrate how to use quarks in this fashion.
-% We shall define a command called |\my_map_dbl:nn| which takes a token list
-% and applies an operation to every \emph{pair} of tokens.
-% For example, |\my_map_dbl:nn {abcd} {[--#1--#2--]~}| would produce
-% \enquote{\ttfamily [--a--b--]~[--c--d--]~}.
-% Using quarks to define such functions simplifies their logic and ensures
-% robustness in many cases.
-%
-%
-% Here's the definition of |\my_map_dbl:nn|.
-% First of all, define the function that does the processing based on the
-% inline function argument |#2|.
-% Then initiate the recursion using an internal function.
-% The token list |#1| is terminated using \cs{q_recursion_tail}, with
-% delimiters according to the type of recursion (here a pair of
-% \cs{q_recursion_tail}), concluding with \cs{q_recursion_stop}.
-% These quarks are used to mark the end of the token list being operated upon.
-%\begin{verbatim}
-% \cs_new:Npn \my_map_dbl:nn #1#2
-% {
-% \cs_set:Npn \__my_map_dbl_fn:nn ##1 ##2 {#2}
-% \__my_map_dbl:nn #1 \q_recursion_tail \q_recursion_tail
-% \q_recursion_stop
-% }
-%\end{verbatim}
-%
-% The definition of the internal recursion function follows.
-% First check if either of the input tokens are the termination quarks.
-% Then, if not, apply the inline function to the two arguments.
-%\begin{verbatim}
-% \cs_new:Nn \__my_map_dbl:nn
-% {
-% \quark_if_recursion_tail_stop:n {#1}
-% \quark_if_recursion_tail_stop:n {#2}
-% \__my_map_dbl_fn:nn {#1} {#2}
-%\end{verbatim}
-% Finally, recurse:
-%\begin{verbatim}
-% \__my_map_dbl:nn
-% }
-%\end{verbatim}
-% Note that contrarily to \LaTeX3 built-in mapping functions, this
-% mapping function cannot be nested, since the second map would overwrite
-% the definition of |\__my_map_dbl_fn:nn|.
-%
-% \section{Scan marks}
-%
-% Scan marks are control sequences set equal to \cs{scan_stop:},
-% hence never expand in an expansion context and are (largely)
-% invisible if they are encountered in a typesetting context.
-%
-% Like quarks, they can be used as delimiters in weird functions
-% and are often safer to use for this purpose.
-% Since they are harmless when executed by \TeX{} in non-expandable
-% contexts, they can be used to mark the end of a set of instructions.
-% This allows to skip to that point if the end of the instructions
-% should not be performed (see \pkg{l3regex}).
-%
-% \begin{function}[added = 2018-04-01]{\scan_new:N}
-% \begin{syntax}
-% \cs{scan_new:N} \meta{scan mark}
-% \end{syntax}
-% Creates a new \meta{scan mark} which is set equal to \cs{scan_stop:}.
-% The \meta{scan mark} is defined globally, and an error message
-% is raised if the name was already taken by another scan mark.
-% \end{function}
-%
-% \begin{variable}[added = 2018-04-01]{\s_stop}
-% Used at the end of a set of instructions, as a marker
-% that can be jumped to using \cs{use_none_delimit_by_s_stop:w}.
-% \end{variable}
-%
-% \begin{function}[EXP,added = 2018-04-01]{\use_none_delimit_by_s_stop:w}
-% \begin{syntax}
-% \cs{use_none_delimit_by_s_stop:w} \meta{tokens} \cs{s_stop}
-% \end{syntax}
-% Removes the \meta{tokens} and \cs{s_stop} from the input stream.
-% This leads to a low-level \TeX{} error if \cs{s_stop} is absent.
-% \end{function}
-%
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \section{\pkg{l3quark} implementation}
-%
-% \TestFiles{m3quark001.lvt}
-%
-% \begin{macrocode}
-%<*package>
-% \end{macrocode}
-%
-% \subsection{Quarks}
-%
-% \begin{macrocode}
-%<@@=quark>
-% \end{macrocode}
-%
-% \begin{macro}{\quark_new:N}
-% \UnitTested
-% Allocate a new quark.
-% \begin{macrocode}
-\cs_new_protected:Npn \quark_new:N #1
- {
- \__kernel_chk_if_free_cs:N #1
- \cs_gset_nopar:Npn #1 {#1}
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{variable}{\q_nil, \q_mark, \q_no_value, \q_stop}
-% Some \enquote{public} quarks. \cs{q_stop} is an \enquote{end of
-% argument} marker, \cs{q_nil} is a empty value and \cs{q_no_value}
-% marks an empty argument.
-% \begin{macrocode}
-\quark_new:N \q_nil
-\quark_new:N \q_mark
-\quark_new:N \q_no_value
-\quark_new:N \q_stop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\q_recursion_tail, \q_recursion_stop}
-% Quarks for ending recursions. Only ever used there!
-% \cs{q_recursion_tail} is appended to whatever list structure we are
-% doing recursion on, meaning it is added as a proper list item with
-% whatever list separator is in use. \cs{q_recursion_stop} is placed
-% directly after the list.
-% \begin{macrocode}
-\quark_new:N \q_recursion_tail
-\quark_new:N \q_recursion_stop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\s_@@}
-% Private scan mark used in \pkg{l3quark}. We don't have \pkg{l3scan}
-% yet, so we declare the scan mark here and add it to the scan mark pool
-% later.
-% \begin{macrocode}
-\cs_new_eq:NN \s_@@ \scan_stop:
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\q_@@_nil}
-% Private quark use for some tests.
-% \begin{macrocode}
-\quark_new:N \q_@@_nil
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}[EXP]{\quark_if_recursion_tail_stop:N}
-% \UnitTested
-% \begin{macro}[EXP]{\quark_if_recursion_tail_stop_do:Nn}
-% \UnitTested
-% When doing recursions, it is easy to spend a lot of time testing if the
-% end marker has been found. To avoid this, a dedicated end marker is used
-% each time a recursion is set up. Thus if the marker is found everything
-% can be wrapper up and finished off. The simple case is when the test
-% can guarantee that only a single token is being tested. In this case,
-% there is just a dedicated copy of the standard quark test. Both a gobbling
-% version and one inserting end code are provided.
-% \begin{macrocode}
-\cs_new:Npn \quark_if_recursion_tail_stop:N #1
- {
- \if_meaning:w \q_recursion_tail #1
- \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
- \fi:
- }
-\cs_new:Npn \quark_if_recursion_tail_stop_do:Nn #1
- {
- \if_meaning:w \q_recursion_tail #1
- \exp_after:wN \use_i_delimit_by_q_recursion_stop:nw
- \else:
- \exp_after:wN \use_none:n
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]
-% {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o}
-% \UnitTested
-% \begin{macro}[EXP]
-% {\quark_if_recursion_tail_stop_do:nn, \quark_if_recursion_tail_stop_do:on}
-% \UnitTested
-% \begin{macro}[EXP]{\@@_if_recursion_tail:w}
-% See \cs{quark_if_nil:nTF} for the details. Expanding
-% \cs{@@_if_recursion_tail:w} once in front of the tokens chosen here
-% gives an empty result if and only if |#1|~is exactly
-% \cs{q_recursion_tail}.
-% \begin{macrocode}
-\cs_new:Npn \quark_if_recursion_tail_stop:n #1
- {
- \tl_if_empty:oTF
- { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
- { \use_none_delimit_by_q_recursion_stop:w }
- { }
- }
-\cs_new:Npn \quark_if_recursion_tail_stop_do:nn #1
- {
- \tl_if_empty:oTF
- { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
- { \use_i_delimit_by_q_recursion_stop:nw }
- { \use_none:n }
- }
-\cs_new:Npn \@@_if_recursion_tail:w
- #1 \q_recursion_tail #2 ? #3 ?! { #1 #2 }
-\cs_generate_variant:Nn \quark_if_recursion_tail_stop:n { o }
-\cs_generate_variant:Nn \quark_if_recursion_tail_stop_do:nn { o }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\quark_if_recursion_tail_break:NN}
-% \begin{macro}[EXP]{\quark_if_recursion_tail_break:nN}
-% Analogues of the \cs[index=quark_if_recursion_tail_stop:n]
-% {quark_if_recursion_tail_stop\ldots{}} functions.
-% Break the mapping using |#2|.
-% \begin{macrocode}
-\cs_new:Npn \quark_if_recursion_tail_break:NN #1#2
- {
- \if_meaning:w \q_recursion_tail #1
- \exp_after:wN #2
- \fi:
- }
-\cs_new:Npn \quark_if_recursion_tail_break:nN #1#2
- {
- \tl_if_empty:oT
- { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! }
- {#2}
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\quark_if_nil:N}
-% \UnitTested
-% \begin{macro}[pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
-% \UnitTested
-% Here we test if we found a special quark as the first argument.
-% We better start with \cs{q_no_value} as the first argument since
-% the whole thing may otherwise loop if |#1| is wrongly given
-% a string like |aabc| instead of a single token.\footnote{It may
-% still loop in special circumstances however!}
-% \begin{macrocode}
-\prg_new_conditional:Npnn \quark_if_nil:N #1 { p, T , F , TF }
- {
- \if_meaning:w \q_nil #1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\prg_new_conditional:Npnn \quark_if_no_value:N #1 { p, T , F , TF }
- {
- \if_meaning:w \q_no_value #1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\prg_generate_conditional_variant:Nnn \quark_if_no_value:N
- { c } { p , T , F , TF }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\quark_if_nil:n, \quark_if_nil:V, \quark_if_nil:o}
-% \UnitTested
-% \begin{macro}[pTF]{\quark_if_no_value:n}
-% \UnitTested
-% \begin{macro}{\@@_if_nil:w, \@@_if_no_value:w}
-% \begin{macro}[EXP]{\@@_if_empty_if:o}
-% Let us explain \cs{quark_if_nil:nTF}. Expanding \cs{@@_if_nil:w}
-% once is safe thanks to the trailing \cs{q_nil} |??!|. The result of
-% expanding once is empty if and only if both delimited arguments |#1|
-% and~|#2| are empty and |#3|~is delimited by the last tokens~|?!|.
-% Thanks to the leading~|{}|, the argument~|#1| is empty if and only
-% if the argument of \cs{quark_if_nil:n} starts with \cs{q_nil}. The
-% argument~|#2| is empty if and only if this \cs{q_nil} is followed
-% immediately by~|?| or by~|{}?|, coming either from the trailing
-% tokens in the definition of \cs{quark_if_nil:n}, or from its
-% argument. In the first case, \cs{@@_if_nil:w} is followed by
-% |{}\q_nil| |{}?| |!\q_nil|~|??!|, hence |#3|~is delimited by the
-% final~|?!|, and the test returns \texttt{true} as wanted. In the
-% second case, the result is not empty since the first~|?!| in the
-% definition of \cs{quark_if_nil:n} stop~|#3|. The auxiliary here
-% is the same as \cs{__tl_if_empty_if:o}, with the same comments
-% applying.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \quark_if_nil:n #1 { p, T , F , TF }
- {
- \@@_if_empty_if:o
- { \@@_if_nil:w {} #1 {} ? ! \q_nil ? ? ! }
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\cs_new:Npn \@@_if_nil:w #1 \q_nil #2 ? #3 ? ! { #1 #2 }
-\prg_new_conditional:Npnn \quark_if_no_value:n #1 { p, T , F , TF }
- {
- \@@_if_empty_if:o
- { \@@_if_no_value:w {} #1 {} ? ! \q_no_value ? ? ! }
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-\cs_new:Npn \@@_if_no_value:w #1 \q_no_value #2 ? #3 ? ! { #1 #2 }
-\prg_generate_conditional_variant:Nnn \quark_if_nil:n
- { V , o } { p , TF , T , F }
-\cs_new:Npn \@@_if_empty_if:o #1
- {
- \exp_after:wN \if_meaning:w \exp_after:wN \q_nil
- \__kernel_tl_to_str:w \exp_after:wN {#1} \q_nil
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\__kernel_quark_new_test:N}
-% The function \cs{__kernel_quark_new_test:N} defines |#1| in a
-% similar way as \cs[no-index]{quark_if_recursion_tail_...} functions
-% (as described below), using
-% \cs[no-index]{q__\meta{namespace}_recursion_tail} as the test quark
-% and \cs[no-index]{q__\meta{namespace}_recursion_stop} as the
-% delimiter quark, where the \meta{namespace} is determined as the
-% first |_|-delimited part in~|#1|.
-%
-% There are six possible function types which this function can define,
-% and which is defined depends on the signature of the function being
-% defined:
-% \begin{description}
-% \def\makelabel#1{\texttt{:#1}~}
-% \item[n] gives an analogue of \cs{quark_if_recursion_tail_stop:n}
-% \item[nn] gives an analogue of \cs{quark_if_recursion_tail_stop_do:nn}
-% \item[nN] gives an analogue of \cs{quark_if_recursion_tail_break:nN}
-% \item[N] gives an analogue of \cs{quark_if_recursion_tail_stop:N}
-% \item[Nn] gives an analogue of \cs{quark_if_recursion_tail_stop_do:Nn}
-% \item[NN] gives an analogue of \cs{quark_if_recursion_tail_break:NN}
-% \end{description}
-% Any other signature causes an error, as does a function without signature.
-%
-% \begin{macro}{\__kernel_quark_new_conditional:Nn}
-% Similar to \cs{__kernel_quark_new_test:N}, but defines quark
-% branching conditionals like \cs{quark_if_nil:nTF} that test for the
-% quark \cs[no-index]{q__\meta{namespace}_\meta{name}}.
-% The \meta{namespace} and \meta{name} are determined from the
-% conditional~|#1|, which must take the rather rigid form
-% \cs[no-index]{__\meta{namespace}_quark_if_\meta{name}:\meta{arg spec}}.
-% There are only two cases for the \meta{arg spec} here:
-% \begin{description}
-% \def\makelabel#1{\texttt{:#1}~}
-% \item[n] gives an analogue of \cs{quark_if_nil:nTF}
-% \item[N] gives an analogue of \cs{quark_if_nil:NTF}
-% \end{description}
-% Any other signature causes an error, as does a function without signature.
-% We use low-level emptiness tests as \pkg{l3tl} is not available yet when these
-% functions are used; thankfully we only care about whether strings
-% are empty so a simple \cs{if_meaning:w} \cs{q_nil} \meta{string}
-% \cs{q_nil} suffices.
-%
-% \begin{macro}{\@@_new_test:NNNn, \@@_new_test:Nccn,
-% \@@_new_test_aux:nnNNnnnn}
-% \begin{macro}{\@@_new_conditional:Nnnn, \@@_new_conditional:Neen}
-% \begin{macrocode}
-\cs_new_protected:Npn \__kernel_quark_new_test:N #1
- { \@@_new_test_aux:Ne #1 { \@@_module_name:N #1 } }
-\cs_new_protected:Npn \@@_new_test_aux:Nn #1 #2
- {
- \if_meaning:w \q_nil #2 \q_nil
- \msg_error:nne { quark } { invalid-function }
- { \token_to_str:N #1 }
- \else:
- \@@_new_test:Nccn #1
- { q__#2_recursion_tail } { q__#2_recursion_stop } { __#2 }
- \fi:
- }
-\cs_generate_variant:Nn \@@_new_test_aux:Nn { Ne }
-\cs_new_protected:Npn \@@_new_test:NNNn #1
- {
- \exp_last_unbraced:Nf \@@_new_test_aux:nnNNnnnn
- { \cs_split_function:N #1 }
- #1 { test }
- }
-\cs_generate_variant:Nn \@@_new_test:NNNn { Ncc }
-\cs_new_protected:Npn \__kernel_quark_new_conditional:Nn #1
- {
- \@@_new_conditional:Neen #1
- { \@@_quark_conditional_name:N #1 }
- { \@@_module_name:N #1 }
- }
-\cs_new_protected:Npn \@@_new_conditional:Nnnn #1#2#3#4
- {
- \if_meaning:w \q_nil #2 \q_nil
- \msg_error:nne { quark } { invalid-function }
- { \token_to_str:N #1 }
- \else:
- \if_meaning:w \q_nil #3 \q_nil
- \msg_error:nne { quark } { invalid-function }
- { \token_to_str:N #1 }
- \else:
- \exp_last_unbraced:Nf \@@_new_test_aux:nnNNnnnn
- { \cs_split_function:N #1 }
- #1 { conditional }
- {#2} {#3} {#4}
- \fi:
- \fi:
- }
-\cs_generate_variant:Nn \@@_new_conditional:Nnnn { Nee }
-\cs_new_protected:Npn \@@_new_test_aux:nnNNnnnn #1 #2 #3 #4 #5
- {
- \cs_if_exist_use:cTF { @@_new_#5_#2:Nnnn } { #4 }
- {
- \msg_error:nnee { quark } { invalid-function }
- { \token_to_str:N #4 } {#2}
- \use_none:nnn
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{
-% \@@_new_test_n:Nnnn, \@@_new_test_nn:Nnnn,
-% \@@_new_test_N:Nnnn, \@@_new_test_Nn:Nnnn,
-% \@@_new_test_NN:Nnnn, \@@_new_test_NN:Nnnn,
-% }
-% These macros implement the six possibilities mentioned above, passing
-% the right arguments to \cs{@@_new_test_aux_do:nNNnnnnNNn},
-% which defines some auxiliaries, and then to
-% \cs{@@_new_test_define_tl:nNnNNn} (|:n(n)| variants) or to
-% \cs{@@_new_test_define_ifx:nNnNNn} (|:N(n)|) which define the
-% main conditionals.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_new_test_n:Nnnn #1 #2 #3 #4
- {
- \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { none } { } { } { }
- \@@_new_test_define_tl:nNnNNn #1 { }
- }
-\cs_new_protected:Npn \@@_new_test_nn:Nnnn #1 #2 #3 #4
- {
- \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_new_test_define_tl:nNnNNn #1 { \use_none:n }
- }
-\cs_new_protected:Npn \@@_new_test_nN:Nnnn #1 #2 #3 #4
- {
- \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_new_test_define_break_tl:nNNNNn #1 { }
- }
-\cs_new_protected:Npn \@@_new_test_N:Nnnn #1 #2 #3 #4
- {
- \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { none } { } { } { }
- \@@_new_test_define_ifx:nNnNNn #1 { }
- }
-\cs_new_protected:Npn \@@_new_test_Nn:Nnnn #1 #2 #3 #4
- {
- \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_new_test_define_ifx:nNnNNn #1
- { \else: \exp_after:wN \use_none:n }
- }
-\cs_new_protected:Npn \@@_new_test_NN:Nnnn #1 #2 #3 #4
- {
- \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2}
- \@@_new_test_define_break_ifx:nNNNNn #1 { }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{
-% \@@_new_test_aux_do:nNNnnnnNNn,
-% \@@_test_define_aux:NNNNnnNNn
-% }
-% \cs{@@_new_test_aux_do:nNNnnnnNNn} makes the control sequence names
-% which will be used by \cs{@@_test_define_aux:NNNNnnNNn}, and then later
-% by \cs{@@_new_test_define_tl:nNnNNn} or
-% \cs{@@_new_test_define_ifx:nNnNNn}. The control sequences defined
-% here are analogous to \cs{@@_if_recursion_tail:w} and to
-% \cs[no-index]{use_(none|i)_delimit_by_q_recursion_stop:(|n)w}.
-%
-% The name is composed by the name-space and the name of the quarks.
-% Suppose \cs{__kernel_quark_new_test:N} was used with:
-% \begin{verbatim}
-% \__kernel_quark_new_test:N \__test_quark_tail:n
-% \end{verbatim}
-% then the first auxiliary will be \cs[no-index]{__test_quark_recursion_tail:w},
-% and the second one will be
-% \cs[no-index]{__test_use_none_delimit_by_q_recursion_stop:w}.
-%
-% Note that the actual quarks are \emph{not} defined here. They should
-% be defined separately using \cs{quark_new:N}.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_new_test_aux_do:nNNnnnnNNn #1 #2 #3 #4 #5
- {
- \exp_args:Ncc \@@_test_define_aux:NNNNnnNNn
- { #1 _quark_recursion_tail:w }
- { #1 _use_ #4 _delimit_by_q_recursion_stop: #5 w }
- #2 #3
- }
-\cs_new_protected:Npn \@@_test_define_aux:NNNNnnNNn #1 #2 #3 #4 #5 #6 #7
- {
- \cs_gset:Npn #1 ##1 #3 ##2 ? ##3 ?! { ##1 ##2 }
- \cs_gset:Npn #2 ##1 #6 #4 {#5}
- #7 {##1} #1 #2 #3
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{
-% \@@_new_test_define_tl:nNnNNn,
-% \@@_new_test_define_ifx:nNnNNn
-% }
-% \begin{macro}{
-% \@@_new_test_define_break_tl:nNNNNn,
-% \@@_new_test_define_break_ifx:nNNNNn
-% }
-% Finally, these two macros define the main conditional function using
-% what's been set up before.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_new_test_define_tl:nNnNNn #1 #2 #3 #4 #5 #6
- {
- \cs_new:Npn #5 #1
- {
- \tl_if_empty:oTF
- { #2 {} ##1 {} ?! #4 ??! }
- {#3} {#6}
- }
- }
-\cs_new_protected:Npn \@@_new_test_define_ifx:nNnNNn #1 #2 #3 #4 #5 #6
- {
- \cs_new:Npn #5 #1
- {
- \if_meaning:w #4 ##1
- \exp_after:wN #3
- #6
- \fi:
- }
- }
-\cs_new_protected:Npn \@@_new_test_define_break_tl:nNNNNn #1 #2 #3
- { \@@_new_test_define_tl:nNnNNn {##1##2} #2 {##2} }
-\cs_new_protected:Npn \@@_new_test_define_break_ifx:nNNNNn #1 #2 #3
- { \@@_new_test_define_ifx:nNnNNn {##1##2} #2 {##2} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{
-% \@@_new_conditional_n:Nnnn,
-% \@@_new_conditional_N:Nnnn,
-% \@@_new_conditional_n_aux:NNNn,
-% \@@_new_conditional_N_aux:NNNn
-% }
-% These macros implement the two possibilities for branching quark
-% conditionals. To avoid constructing without defining the
-% \cs[no-index]{__\meta{type}_if_quark_\meta{name}:w} helper,
-% \texttt{N}-type function accepts a \cs{prg_do_nothing:} as
-% a placeholder.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_new_conditional_n:Nnnn #1 #2 #3
- {
- \exp_args:Ncc \@@_new_conditional_n_aux:NNNn
- { __ #3 _if_quark_ #2 :w } { q__ #3 _ #2 } #1
- }
-\cs_new_protected:Npn \@@_new_conditional_N:Nnnn #1 #2 #3
- {
- \exp_args:NNc \@@_new_conditional_N_aux:NNNn
- \prg_do_nothing: { q__ #3 _ #2 } #1
- }
-\cs_new_protected:Npn \@@_new_conditional_n_aux:NNNn #1 #2 #3 #4
- {
- \cs_gset:Npn #1 ##1 #2 ##2 ? ##3 ?! { ##1##2 }
- \prg_new_conditional:Npnn #3 ##1 {#4}
- {
- \@@_if_empty_if:o { #1 {} ##1 {} ?! #2 ??! }
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
- }
-\cs_new_protected:Npn \@@_new_conditional_N_aux:NNNn #1 #2 #3 #4
- {
- \prg_new_conditional:Npnn #3 ##1 {#4}
- {
- \if_meaning:w #2 ##1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_module_name:N}
-% \begin{macro}[EXP]{
-% \@@_module_name:w,
-% \@@_module_name_loop:w,
-% \@@_module_name_end:w
-% }
-% \cs{@@_module_name:N} takes a control sequence and returns its
-% \meta{module} name, determined as the first non-empty
-% non-single-character word, separated by |_| or~|:|. These rules
-% give the correct result for public functions
-% \cs[no-index]{\meta{module}_\ldots{}}, private functions
-% \cs[no-index]{__\meta{module}_\ldots{}}, and variables such as
-% \cs[no-index]{l_\meta{module}_\ldots{}}. If no valid module is
-% found the result is an empty string. The approach is to first cut
-% off everything after the (first) |:| if any is present, then
-% repeatedly grab |_|-delimited words until finding one of length at
-% least~$2$ (we use low-level tests as \pkg{l3tl} is not fully
-% available when \cs{__kernel_quark_new_test:N} is first used.
-% If no \meta{module} is found (such as in \cs{::n}) we
-% get the trailing marker \cs{use_none:n} |{}|, which expands to
-% nothing.
-% \begin{macrocode}
-\cs_set:Npn \@@_tmp:w #1#2
- {
- \cs_new:Npn \@@_module_name:N ##1
- {
- \exp_last_unbraced:Nf \@@_module_name:w
- { \cs_to_str:N ##1 } #1 \s_@@
- }
- \cs_new:Npn \@@_module_name:w ##1 #1 ##2 \s_@@
- { \@@_module_name_loop:w ##1 #2 \use_none:n { } #2 \s_@@ }
- \cs_new:Npn \@@_module_name_loop:w ##1 #2
- {
- \use_i_ii:nnn \if_meaning:w \prg_do_nothing:
- ##1 \prg_do_nothing: \prg_do_nothing:
- \exp_after:wN \@@_module_name_loop:w
- \else:
- \@@_module_name_end:w ##1
- \fi:
- }
- \cs_new:Npn \@@_module_name_end:w
- ##1 \fi: ##2 \s_@@ { \fi: ##1 }
- }
-\exp_after:wN \@@_tmp:w \tl_to_str:n { : _ }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_quark_conditional_name:N, \@@_quark_conditional_name:w}
-% \cs{@@_quark_conditional_name:N} determines the quark name that the quark
-% conditional function~|##1| queries, as the part of the function name
-% between |_quark_if_| and the trailing~|:|. Again we define it
-% through \cs{@@_tmp:w}, which receives |:| as |#1| and |_quark_if_|
-% as |#2|. The auxiliary \cs{@@_quark_conditional_name:w} returns the part
-% between the first |_quark_if_| and the next~|:|, and we apply this
-% auxiliary to the function name followed by |:| (in case the function
-% name is lacking a signature), and |_quark_if_:| so that
-% \cs{@@_quark_conditional_name:N} returns an empty string if |_quark_if_| is
-% not present.
-% \begin{macrocode}
-\cs_set:Npn \@@_tmp:w #1 #2 \s_@@
- {
- \cs_new:Npn \@@_quark_conditional_name:N ##1
- {
- \exp_last_unbraced:Nf \@@_quark_conditional_name:w
- { \cs_to_str:N ##1 } #1 #2 #1 \s_@@
- }
- \cs_new:Npn \@@_quark_conditional_name:w
- ##1 #2 ##2 #1 ##3 \s_@@ {##2}
- }
-\exp_after:wN \@@_tmp:w \tl_to_str:n { : _quark_if_ } \s_@@
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Scan marks}
-%
-% \begin{macrocode}
-%<@@=scan>
-% \end{macrocode}
-%
-% \begin{macro}{\scan_new:N}
-% \UnitTested
-% Check whether the variable is already a scan mark,
-% then declare it to be equal to \cs{scan_stop:} globally.
-% \begin{macrocode}
-\cs_new_protected:Npn \scan_new:N #1
- {
- \tl_if_in:NnTF \g_@@_marks_tl { #1 }
- {
- \msg_error:nne { scanmark } { already-defined }
- { \token_to_str:N #1 }
- }
- {
- \tl_gput_right:Nn \g_@@_marks_tl {#1}
- \cs_new_eq:NN #1 \scan_stop:
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{variable}{\s_stop}
-% \begin{variable}{\g_@@_marks_tl}
-% \UnitTested
-% We only declare one scan mark here, more can be defined
-% by specific modules.
-% Can't use \cs{scan_new:N} yet because \pkg{l3tl} isn't loaded,
-% so define \cs{s_stop} by hand and add it to \cs{g_@@_marks_tl}.
-% We also add the scan marks declared earlier to the pool here.
-% Since they lives in a different namespace, a little \pkg{DocStrip}
-% cheating is necessary.
-% \begin{macrocode}
-\cs_new_eq:NN \s_stop \scan_stop:
-\cs_gset_nopar:Npn \g_@@_marks_tl
- {
- \s_stop
-%<@@=quark>
- \s_@@
-%<@@=cs>
- \s_@@_mark
- \s_@@_stop
-%<@@=scan>
- }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \begin{macro}[EXP]{\use_none_delimit_by_s_stop:w}
-% \UnitTested
-% Similar to \cs{use_none_delimit_by_q_stop:w}.
-% \begin{macrocode}
-\cs_new:Npn \use_none_delimit_by_s_stop:w #1 \s_stop { }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macrocode}
-%</package>
-% \end{macrocode}
-%
-% \end{implementation}
-%
-% \PrintIndex