summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-07-31 18:27:06 +0000
committerKarl Berry <karl@freefriends.org>2011-07-31 18:27:06 +0000
commitdac945b204407dae96f70ec228206516093156d7 (patch)
tree02ca182689947e45dec95e17ba08b503c959bd17 /Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
parentc1840548792cfbc7c9f746da1d53d89b94406e72 (diff)
l3kernel (5jun11)
git-svn-id: svn://tug.org/texlive/trunk@23282 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3quark.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3quark.dtx486
1 files changed, 486 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
new file mode 100644
index 00000000000..2326fd4519d
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
@@ -0,0 +1,486 @@
+% \iffalse meta-comment
+%
+%% File: l3quark.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: l3quark.dtx 2478 2011-06-19 21:34:23Z joseph $
+ {L3 Experimental quarks}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3quark} package\\ Quarks^^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}
+%
+% A special type of constants in \LaTeX3 are \enquote{quarks}. These are
+% control
+% sequences 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 is weird functions (for
+% example as the stop token (\emph{i.e.}~\cs{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
+% \cs{if_meaning:w}. 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_|.
+%
+% \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} will be defined globally, and an error message
+% will be 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 may 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 later
+% 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}. The branching
+% versions then leave either \meta{true code} or \meta{false code} in
+% the input stream, as appropriate to the truth of the test and the
+% variant of the function chosen. The logical truth of the test is
+% left in the input stream by the predicate version.
+% \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). The branching versions then leave either
+% \meta{true code} or \meta{false code} in the input stream, as
+% appropriate to the truth of the test and the variant of the
+% function chosen. The logical truth of the test is left in the input
+% stream by the predicate version.
+% \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}. The branching
+% versions then leave either \meta{true code} or \meta{false code} in
+% the input stream, as appropriate to the truth of the test and the
+% variant of the function chosen. The logical truth of the test is
+% left in the input stream by the predicate version.
+% \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). The branching
+% versions then leave either \meta{true code} or \meta{false code} in
+% the input stream, as appropriate to the truth of the test and the
+% variant of the function chosen. The logical truth of the test is
+% left in the input stream by the predicate version.
+% \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.
+%
+% \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}
+% \begin{syntax}
+% \cs{quark_if_recursion_tail_stop:N} \Arg{token}
+% \end{syntax}
+% Tests if \meta{token} contains only the marker
+% \cs{q_recursion_tail}, and if so terminates the recursion this is
+% part of using \cs{use_none_delimit_by_q_recursion_stop:w}. 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}
+% {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o}
+% \begin{syntax}
+% \cs{quark_if_recursion_tail_stop:n} \Arg{tokens}
+% \end{syntax}
+% Tests if \meta{tokens} consists of the single token
+% \cs{q_recursion_tail}, and if so terminates the recursion this is
+% part of using \cs{use_none_delimit_by_q_recursion_stop:w}. 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}{\quark_if_recursion_tail_stop_do:Nn}
+% \begin{syntax}
+% \cs{quark_if_recursion_tail_stop_do:nn} \Arg{token} \Arg{insertion}
+% \end{syntax}
+% Tests if \meta{token} contains only the marker
+% \cs{q_recursion_tail}, and if so terminates the recursion this is
+% part of using \cs{use_none_delimit_by_q_recursion_stop:w}. 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}
+% {\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{tokens} \Arg{insertion}
+% \end{syntax}
+% Tests if \meta{tokens} consists of the single token
+% \cs{q_recursion_tail}, and if so terminates the recursion this is
+% part of using \cs{use_none_delimit_by_q_recursion_stop:w}. 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}
+%
+% \section{Internal quark functions}
+%
+% \begin{function}{\use_none_delimit_by_q_recursion_stop:w}
+% \begin{syntax}
+% \cs{use_none_delimit_by_q_recursion_stop:w}
+% ~~\meta{tokens} \cs{q_recursion_stop}
+% \end{syntax}
+% Used to prematurely terminate a recursion using \cs{q_recursion_stop}
+% as the end marker, removing any remaining \meta{tokens} from the
+% input stream.
+% \end{function}
+%
+% \begin{function}{\use_i_delimit_by_q_recursion_stop:nw}
+% \begin{syntax}
+% \cs{use_i_delimit_by_q_recursion_stop:nw} \Arg{insertion}
+% ~~\meta{tokens} \cs{q_recursion_stop}
+% \end{syntax}
+% Used to prematurely terminate a recursion using \cs{q_recursion_stop}
+% as the end marker, removing any remaining \meta{tokens} from the
+% input stream. The \meta{insertion} is then made into the input
+% stream after the end of the recursion.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3quark} implementation}
+%
+% \TestFiles{m3quark001.lvt}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\package_check_loaded_expl:
+%</package>
+% \end{macrocode}
+%
+% \begin{macro}{\quark_new:N}
+% \UnitTested
+% Allocate a new quark.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \quark_new:N #1 { \tl_const:Nn #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{macro}{\quark_if_recursion_tail_stop:N}
+% \UnitTested
+% \begin{macro}{\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 #1 \q_recursion_tail
+ \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
+ \fi:
+ }
+\cs_new:Npn \quark_if_recursion_tail_stop_do:Nn #1#2
+ {
+ \if_meaning:w #1 \q_recursion_tail
+ \exp_after:wN \use_i_delimit_by_q_recursion_stop:nw
+ \else:
+ \exp_after:wN \use_none:n
+ \fi:
+ {#2}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {\quark_if_recursion_tail_stop:n,\quark_if_recursion_tail_stop:o}
+% \UnitTested
+% \begin{macro}
+% {\quark_if_recursion_tail_stop_do:nn,\quark_if_recursion_tail_stop_do:on}
+% \UnitTested
+% \begin{macro}[aux]{\quark_if_recursion_tail_aux:w}
+% The same idea applies when testing multiple tokens, but here a little more
+% care is needed. It is possible that |#1| might be something like
+% |{{{a}}}| or |{ab\iffalse}\fi|, which will therefore need to be tested
+% in a detokenized manner. The way that this is done is using
+% \cs{if_catcode:w}, with the idea being that this test will be \texttt{true}
+% provided the auxiliary function returns nothing at all. If the auxiliary
+% returns anything, it will be detokenized and so the test will be both
+% \texttt{false} and safe.
+% \begin{macrocode}
+\cs_new:Npn \quark_if_recursion_tail_stop:n #1
+ {
+ \if_catcode:w
+ A
+ \etex_detokenize:D \exp_after:wN
+ {
+ \quark_if_recursion_tail_aux:w #1 \q_recursion_stop
+ \q_recursion_tail \q_recursion_stop \q_stop
+ }
+ A
+ \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
+ \fi:
+ }
+\cs_new:Npn \quark_if_recursion_tail_stop_do:nn #1#2
+ {
+ \if_catcode:w
+ A
+ \etex_detokenize:D \exp_after:wN
+ {
+ \quark_if_recursion_tail_aux:w #1 \q_recursion_stop
+ \q_recursion_tail \q_recursion_stop \q_stop
+ }
+ A
+ \exp_after:wN \use_i_delimit_by_q_recursion_stop:nw
+ \else:
+ \exp_after:wN \use_none:n
+ \fi:
+ {#2}
+ }
+\cs_new:Npn \quark_if_recursion_tail_aux:w
+ #1 \q_recursion_tail #2 \q_recursion_stop #3 \q_stop
+ { #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}[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:Nnn \quark_if_nil:N { p, T , F , TF }
+ {
+ \if_meaning:w \q_nil #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\prg_new_conditional:Nnn \quark_if_no_value:N { p, T , F , TF }
+ {
+ \if_meaning:w \q_no_value #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_generate_variant:Nn \quark_if_no_value_p:N { c }
+\cs_generate_variant:Nn \quark_if_no_value:NT { c }
+\cs_generate_variant:Nn \quark_if_no_value:NF { c }
+\cs_generate_variant:Nn \quark_if_no_value:NTF { c }
+% \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
+% These are essentially \cs{str_if_eq:nn} tests but done directly.
+% \begin{macrocode}
+\prg_new_conditional:Nnn \quark_if_nil:n { p, T , F , TF }
+ {
+ \if_int_compare:w \pdftex_strcmp:D
+ { \exp_not:N \q_nil } { \exp_not:n {#1} } = \c_zero
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\prg_new_conditional:Nnn \quark_if_no_value:n { p, T , F , TF }
+ {
+ \if_int_compare:w \pdftex_strcmp:D
+ { \exp_not:N \q_no_value } { \exp_not:n {#1} } = \c_zero
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_generate_variant:Nn \quark_if_nil_p:n { V , o }
+\cs_generate_variant:Nn \quark_if_nil:nTF { V , o }
+\cs_generate_variant:Nn \quark_if_nil:nT { V , o }
+\cs_generate_variant:Nn \quark_if_nil:nF { V , o }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
+%
+% \endinput