% \iffalse
%% File: l3quark.dtx Copyright (C) 1990-2006 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/cgi-bin/cvsweb.cgi/
%%
%% 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 LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<*driver|package>
\RequirePackage{l3names}
%</driver|package>
%\fi
\GetIdInfo$Id: l3quark.dtx 761 2008-08-04 21:35:13Z morten $
          {L3 Experimental Quark Commands}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass{l3doc}
\begin{document}
\DocInput{\filename.\filenameext}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3quark} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% ``Quarks''}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
%
% \section{Quarks}
%^^A \label{sec:quarks}
%
%
% A special type of constants in \LaTeX3 are `quarks'. These are control
% sequences that expand to themselves and should therefore NEVER be
% executed directly in the code. This would result in an endless loop!
%
% They are meant to be used as delimiter is weird functions (for
% example as the stop token (i.e., "\q_stop"). They also permit the
% following ingenious trick: when you pick up a token in a temporary,
% and you want to know whether you have picked up a particular quark,
% all you have to do is compare the temporary to the quark using
% "\if_meaning:NN". 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.
%
% By convention all constants of type quark start out with "\q_".
%
% The documentation needs some updating.
%
%
% \subsection{Functions}
%
% \begin{function}{%
%                  \quark_new:N |
% }
% \begin{syntax}
%    "\quark_new:N"   <quark>
% \end{syntax}
% Defines <quark> to be a new constant of type "quark".
% \end{function}
%
% \begin{function}{%
%                  \quark_if_no_value_p:n |
%                  \quark_if_no_value:nTF |
%                  \quark_if_no_value:nF  |
%                  \quark_if_no_value:nT  |
%                  \quark_if_no_value_p:N |
%                  \quark_if_no_value:NTF |
%                  \quark_if_no_value:NT  |
%                  \quark_if_no_value:NF  |
% }
% \begin{syntax}
%    "\quark_if_no_value:nTF" "{"<token list>"}"
%                          "   {"<true code>"}{"<false code>"}"
%    "\quark_if_no_value:NTF" <tlp>
%                          "   {"<true code>"}{"<false code>"}"
% \end{syntax}
% This tests whether or not <token list> contains only the quark
% "\q_no_value".
%
% If <token list> to be tested is stored in a token list pointer use
% "\quark_if_no_value:NTF", or "\quark_if_no_value:NF" or check the
% value directly with "\if_meaning:NN". All those cases are faster then
% "\quark_if_no_value:nTF" so should be preferred.\footnote{Clarify
% semantic of the ``n'' case \ldots{} i think it is not implement
% according to what we originally intended /FMi}
%
% \begin{texnote}
% But  be aware of the fact that "\if_meaning:NN" can result in an
% overflow of \TeX{}'s parameter stack since it leaves the corresponding
% "\fi:" on the input until the whole replacement text is processed. It
% is therefore better in recursions to use "\quark_if_no_value:NTF" as
% it will remove the conditional prior to processing the "T" or "F" case
% and so allows tail-recursion.
% \end{texnote}
% \end{function}
%
% \begin{function}{%
%                  \quark_if_nil_p:N |
%                  \quark_if_nil:NTF |
%                  \quark_if_nil:NT |
%                  \quark_if_nil:NF  |
% }
% \begin{syntax}
%    "\quark_if_nil:NTF" <token>
%                          "  {"<true code>"}{"<false code>"}"
% \end{syntax}
% This tests whether or not <token> is equal to the quark
% "\q_nil".
%
% This is a useful test for recursive loops which typically has 
% "\q_nil" as an end marker.
% \end{function}
%
%
% \begin{function}{%
%                  \quark_if_nil_p:n |
%                  \quark_if_nil:nTF |
%                  \quark_if_nil:nT |
%                  \quark_if_nil:nF  |
%                  \quark_if_nil_p:o |
%                  \quark_if_nil:oTF |
%                  \quark_if_nil:oT |
%                  \quark_if_nil:oF  |
% }
% \begin{syntax}
%    "\quark_if_nil:nTF" "{"<tokens>"}"
%                        "{"<true code>"}{"<false code>"}"
% \end{syntax}
% This tests whether or not <tokens> is equal to the quark
% "\q_nil".
%
% This is a useful test for recursive loops which typically has
% "\q_nil" as an end marker.
% \end{function}
%
% \subsection{Recursion}
%
% This module provides a uniform interface to intercepting and
% terminating loops as when one is doing tail recursion. The building
% blocks follow below.
% 
% \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}{%
%                  \quark_if_recursion_tail_stop:N |
%                  \quark_if_recursion_tail_stop:n |
%                  \quark_if_recursion_tail_stop:o |
% }
% \begin{syntax}
%    "\quark_if_recursion_tail_stop:n"  "{"<list element>"}" \\
%    "\quark_if_recursion_tail_stop:N" <list element>
% \end{syntax}
% This tests whether or not <list element> is equal to
% "\q_recursion_tail" and then exits, i.e., it gobbles the remainder of
% the list up to and including "\q_recursion_stop" which \emph{must}
% be present.
%
% If <list element> is not under your complete control it is advisable
% to use the "n". If you wish to use the "N" form you \emph{must}
% ensure it is really a single token such as if you have
% \begin{quote}
% "\tlp_set:Nn \l_tmpa_tlp {" <list element> "}"
% \end{quote}
% \end{function}
%
% \begin{function}{%
%                  \quark_if_recursion_tail_stop_do:Nn |
%                  \quark_if_recursion_tail_stop_do:nn |
%                  \quark_if_recursion_tail_stop_do:on |
% }
% \begin{syntax}
%   "\quark_if_recursion_tail_stop_do:nn"\\ 
%   "{"<list element>"}" "{" <post action> "}" 
%   "\quark_if_recursion_tail_stop_do:Nn"
%    <list element> "{" <post action> "}"
% \end{syntax}
% Same as "\quark_if_recursion_tail_stop:N" except here the second
% argument is executed after the recursion has been terminated.
% \end{function}
%
% \subsection{Constants}
%
% \begin{variable}{\q_no_value} The canonical `missing value quark'
% that is returned by certain functions to denote that a requested value
% is not found in the data structure.
% \end{variable}
%
% \begin{variable}{\q_stop}
% This constant is used as a a marker in parameter text. This allows a
% scanning function to find the end of some input string.
% \end{variable}
%
% \begin{variable}{\q_nil}
% This constant represent the nil pointer in pointer structures.
% \end{variable}
%
% \StopEventually{}
%
% \subsection{The Implementation}
%
%    We start by ensuring that the required packages are loaded.
%    We check for \texttt{l3expan} since this a basic package that is
%    essential for use of any higher-level package.
%    \begin{macrocode}
%<package>\ProvidesExplPackage
%<package>  {\filename}{\filedate}{\fileversion}{\filedescription}
%<package>\RequirePackage{l3expan}\par
%<*initex|package>
%    \end{macrocode}
%
% \begin{macro}{\quark_new:N}
%    Allocate a new quark.
%    \begin{macrocode}
\def_new:Npn \quark_new:N #1{\tlp_new:Nn #1{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\q_stop}
% \begin{macro}{\q_no_value}
% \begin{macro}{\q_nil}
%    |\q_stop| is often used as a marker in parameter text,
%    |\q_no_value| is the canonical missing value, and |\q_nil|
%    represents a nil pointer in some data structures.
%    \begin{macrocode}
\quark_new:N \q_stop
\quark_new:N \q_no_value
\quark_new:N \q_nil
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\q_error}
% \begin{macro}{\q_mark}
%    We need two additional quarks.  |\q_error| delimits the end of
%    the computation for purposes of error recovery.  |\q_mark| is
%    used in parameter text when we need a scanning boundary that is
%    distinct from |\q_stop|.
%    \begin{macrocode}
\quark_new:N\q_error
\quark_new:N\q_mark
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\q_recursion_tail}
% \begin{macro}{\q_recursion_stop}
%   Quarks for ending recursions. Only ever used there!
%   |\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.  |\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{macro}
% \end{macro}
%
% \begin{macro}{\quark_if_recursion_tail_stop:n}
% \begin{macro}{\quark_if_recursion_tail_stop:N}
% \begin{macro}{\quark_if_recursion_tail_stop:o}
%   When doing recursions it is easy to spend a lot of time testing if
%   we found the end marker. To avoid this, we use a recursion end
%   marker every time we do this kind of task. Also, if the recursion
%   end marker is found, we wrap things up and finish.
%    \begin{macrocode}
\def_long_new:Npn \quark_if_recursion_tail_stop:n #1 {
  \exp_after:NN\if_meaning:NN
    \quark_if_recursion_tail_aux:w #1?\q_nil\q_recursion_tail\q_recursion_tail
    \exp_after:NN \use_none_delimit_by_q_recursion_stop:w
  \fi:
}
\def_long_new:Npn \quark_if_recursion_tail_stop:N #1 {
  \if_meaning:NN#1\q_recursion_tail
    \exp_after:NN \use_none_delimit_by_q_recursion_stop:w
  \fi:
}
\def_new:Npn \quark_if_recursion_tail_stop:o{
  \exp_args:No\quark_if_recursion_tail_stop:n
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\quark_if_recursion_tail_stop_do:nn}
% \begin{macro}{\quark_if_recursion_tail_stop_do:Nn}
% \begin{macro}{\quark_if_recursion_tail_stop_do:on}
%    \begin{macrocode}
\def_long_new:Npn \quark_if_recursion_tail_stop_do:nn #1#2 {
  \exp_after:NN\if_meaning:NN
    \quark_if_recursion_tail_aux:w #1?\q_nil\q_recursion_tail\q_recursion_tail
    \exp_after:NN \use_arg_i_delimit_by_q_recursion_stop:nw
  \else:
    \exp_after:NN\use_none:n
  \fi:
  {#2}
}
\def_long_new:Npn \quark_if_recursion_tail_stop_do:Nn #1#2 {
  \if_meaning:NN #1\q_recursion_tail
    \exp_after:NN \use_arg_i_delimit_by_q_recursion_stop:nw
  \else:
    \exp_after:NN\use_none:n
  \fi:
  {#2}
}
\def_new:Npn \quark_if_recursion_tail_stop_do:on{
  \exp_args:No\quark_if_recursion_tail_stop_do:nn
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\quark_if_recursion_tail_aux:w}
% \begin{macro}{\use_none_delimit_by_q_recursion_stop:w}
% \begin{macro}{\use_arg_i_delimit_by_q_recursion_stop:nw}
%   Helper macros for picking up the first token of a list to see if
%   it is "\q_recursion_tail" and to stop the recursion.
%    \begin{macrocode}
\def_long_new:Npn \quark_if_recursion_tail_aux:w
  #1#2\q_nil\q_recursion_tail{#1}
\def_long_new:Npn\use_none_delimit_by_q_recursion_stop:w 
  #1\q_recursion_stop {}
\def_long_new:Npn\use_arg_i_delimit_by_q_recursion_stop:nw 
  #1#2\q_recursion_stop {#1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\quark_if_no_value_p:N}
% \begin{macro}{\quark_if_no_value:NTF}
% \begin{macro}{\quark_if_no_value:NT}
% \begin{macro}{\quark_if_no_value:NF}
% \begin{macro}{\quark_if_no_value_p:n}
% \begin{macro}{\quark_if_no_value:nTF}
% \begin{macro}{\quark_if_no_value:nT}
% \begin{macro}{\quark_if_no_value:nF}
% \begin{macro}{\quark_if_no_value:nFT}
%    Here we test if we found a special quark as the first argument.
%    \begin{macrocode}
\def_long_test_function_new:npn {quark_if_no_value:N} #1 {
%    \end{macrocode}
%    We better start with |\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}
     \if_meaning:NN\q_no_value#1}
\def_long_new:Npn \quark_if_no_value_p:N #1{
  \if_meaning:NN \q_no_value #1 \c_true
  \else: \c_false \fi:
}
%    \end{macrocode}
% We also provide an |n| type. If run under a sufficiently new
% pdf\eTeX, it uses a built-in primitive for string comparisons,
% otherwise it uses the slower |\str_if_eq_var_p:nf| function. In the
% latter case it would be faster to use a temporary token list pointer
% but it would render the function non-expandable. Using the pdf\eTeX\
% primitive is the preferred approach. Note that we have to add a
% manual space token in the first part of the comparison, otherwise it
% is gobbled by |\str_if_eq_var_p:nf|. The reason for using this
% function instead of |\str_if_eq_p:nn| is that a sequence like
% \verb*+ \q_no_value+ will test equal to |\q_no_value| using the
% latter test function and unfortunately this example turned up in one
% application.
%    \begin{macrocode}
\cs_if_really_free:cTF{pdf_strcmp:D}{
  \def_long_new:Npn \quark_if_no_value_p:n #1{
    \if:w \exp_args:No \str_if_eq_var_p:nf 
%<package>      {\token_to_string:N\q_no_value\space}
%<initex>      {\token_to_string:N\q_no_value\text_put_sp:}
      {\tlist_to_str:n{#1}}
      \c_true
    \else:
      \c_false
    \fi:
  }
}
{
  \def_long_new:Npn \quark_if_no_value_p:n #1{
    \if_num:w 
    \pdf_strcmp:D {\exp_not:N \q_no_value}{\exp_not:n{#1}}=\c_zero 
    \c_true \else: \c_false \fi:
  }
}
\def_long_test_function_new:npn {quark_if_no_value:n} #1 {
  \if:w \quark_if_no_value_p:n{#1}}
%    \end{macrocode}
% We also define a version where the true and false code is ordered
% differently.
%    \begin{macrocode}
\def_long:Npn \quark_if_no_value:nFT #1{
  \if:w \quark_if_no_value_p:n{#1}
      \exp_after:NN\use_arg_ii:nn
    \else:
      \exp_after:NN\use_arg_i:nn
    \fi:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\quark_if_nil_p:N}
% \begin{macro}{\quark_if_nil:NTF}
% \begin{macro}{\quark_if_nil:NT}
% \begin{macro}{\quark_if_nil:NF}
%    A function to check for the presence of |\q_nil|.
%    \begin{macrocode}
\def_long_new:Npn \quark_if_nil_p:N #1{
  \if_meaning:NN \q_nil #1 \c_true
  \else: \c_false \fi:
}
\def_long_test_function_new:npn {quark_if_nil:N}#1{
  \if_meaning:NN\q_nil#1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\quark_if_nil_p:n}
% \begin{macro}{\quark_if_nil:nTF}
% \begin{macro}{\quark_if_nil:nT}
% \begin{macro}{\quark_if_nil:nF}
% \begin{macro}{\quark_if_nil_p:o}
% \begin{macro}{\quark_if_nil:oTF}
% \begin{macro}{\quark_if_nil:oT}
% \begin{macro}{\quark_if_nil:oF}
%    A function to check for the presence of |\q_nil|.
%    \begin{macrocode}
\cs_if_really_free:cTF{pdf_strcmp:D}{
  \def_long_new:Npn \quark_if_nil_p:n #1{
    \if:w \exp_args:No \str_if_eq_var_p:nf 
%<package>      {\token_to_string:N\q_nil\space}
%<initex>      {\token_to_string:N\q_nil\text_put_sp:}
      {\tlist_to_str:n{#1}}
      \c_true
    \else:
      \c_false
    \fi:
  }
}
{
  \def_long_new:Npn \quark_if_nil_p:n #1{
    \if_num:w 
    \pdf_strcmp:D {\exp_not:N \q_nil}{\exp_not:n{#1}}=\c_zero 
    \c_true \else: \c_false \fi:
  }
}
\def_long_test_function_new:npn {quark_if_nil:n} #1 {
  \if:w \quark_if_nil_p:n{#1}}
\def_new:Npn \quark_if_nil_p:o{\exp_args:No\quark_if_nil_p:n}
\def_new:Npn \quark_if_nil:oTF{\exp_args:No\quark_if_nil:nTF}
\def_new:Npn \quark_if_nil:oT {\exp_args:No\quark_if_nil:nT}
\def_new:Npn \quark_if_nil:oF {\exp_args:No\quark_if_nil:nF}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    Show token usage:
%    \begin{macrocode}
%</initex|package>
%<*showmemory>
\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \endinput
%
% $Log$
% Revision 1.22  2006/07/30 14:39:02  morten
% Changed all quark functions to be expandable regardless of whether
% \pdfstrcmp is available.
%
% Revision 1.21  2006/07/25 15:34:21  morten
% Added the non-expandable \quark_if_nil:nTF plus variants.
%
% Revision 1.20  2006/07/23 13:43:47  morten
% Fixed minor bug in \quark_if_no_value_p:n
%
% Revision 1.19  2006/03/20 18:26:38  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.18  2006/01/04 01:18:31  morten
% Changed \quark_if_no_value:nTF to be expandable. Added a few predicate
% functions and updated documentation.
%
% Revision 1.17  2005/12/27 10:04:41  morten
% Minor changes plus changed RCS information retrieval
%
% Revision 1.16  2005/10/27 14:12:28  morten
% Added gobble-until-quark functions.
%
% Revision 1.15  2005/07/14 18:50:31  morten
% Added \quark_if_nil:NF
%
% Revision 1.14  2005/04/06 13:55:57  morten
% Fixed \quark_if_nil:NTF
%
% Revision 1.13  2005/03/16 22:35:57  braams
% Added the tweaks necessary to be able to load with initex
%
% Revision 1.12  2005/03/11 21:41:27  braams
% Fixed the use of RCS information; added \StopEventually
%
