summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-02-28 00:40:17 +0000
committerKarl Berry <karl@freefriends.org>2012-02-28 00:40:17 +0000
commited49b3dfe19b91f9fd96ab70fe95dcda8fba24c8 (patch)
tree0eb59527efd68f813d629e7d0977fe31d8d6419f /Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx
parentb1436d6ee293a02df32a18832d21c54348335565 (diff)
l3experimental 3471 (26feb12)
git-svn-id: svn://tug.org/texlive/trunk@25523 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx301
1 files changed, 301 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx
new file mode 100644
index 00000000000..d3fa2d4e366
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx
@@ -0,0 +1,301 @@
+% \iffalse meta-comment
+%
+%% File: l3tl-build.dtx Copyright (C) 2011-2012 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 "l3experimental 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{expl3}
+\GetIdInfo$Id: l3tl-build.dtx 3039 2011-12-08 09:22:35Z bruno $
+ {L3 Experimental Build of Token lists}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\usepackage{amsmath}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+%
+% \title{^^A
+% The \textsf{l3tl-build} package: building token lists^^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}
+%
+% \section{\pkg{l3tl-build} documentation}
+%
+% This module provides no user function.
+%
+% There are two main ways of building token lists from individual
+% tokens. Either in one go within an \texttt{x}-expanding assignment, or
+% by repeatedly using \cs{tl_put_right:Nn}. The first method takes a
+% linear time, but only allows expandable operations. The second method
+% takes a time quadratic in the length of the token list, but allows
+% expandable and non-expandable operations.
+%
+% The goal of this module is to provide functions to build a token list
+% piece by piece in linear time, while allowing non-expandable
+% operations. This is achieved by abusing \tn{toks}: adding some tokens
+% to the token list is done by storing them in a free token register
+% (time $O(1)$ for each such operation). Those token registers are only
+% put together at the end, within an \texttt{x}-expanding assignment,
+% which takes a linear time.\footnote{If we run out of token registers,
+% then the currently filled-up \tn{toks} are put together in a
+% temporary token list, and cleared, and we ultimately use
+% \cs{tl_put_right:Nx} to put those chunks together. Hence the true
+% asymptotic is quadratic, with a very small constant.} Of course,
+% all this must be done in a group: we can't go and clobber the values
+% of legitimate \tn{toks} used by \LaTeXe{}.
+%
+% Since none of the current applications need the ability to insert
+% material on the left of the token list, I have not implemented
+% that. This could be done for instance by using odd-numbered \tn{toks}
+% for the left part, and even-numbered \tn{toks} for the right part.
+%
+% \subsection{Internal functions}
+%
+% \begin{function}
+% {
+% \tl_set_build:Nw, \tl_gset_build:Nw,
+% \tl_set_build_x:Nw, \tl_gset_build_x:Nw
+% }
+% \begin{syntax}
+% \cs{tl_set_build:Nw} \meta{tl~var} \texttt{\ldots{}}
+% \cs{tl_build_one:n} \Arg{tokens_1} \texttt{\ldots{}}
+% \cs{tl_build_one:n} \Arg{tokens_2} \texttt{\ldots{}}
+% \ldots{}
+% \cs{tl_build_end:}
+% \end{syntax}
+% Defines the \meta{tl~var} to contain the contens of \meta{tokens1}
+% followed by \meta{tokens2}, \emph{etc.} This is built in such a way
+% to be more efficient than repeatedly using \cs{tl_put_right:Nn}. The
+% code in \enquote{\texttt{\ldots{}}} does not need to be
+% expandable. The commands \cs{tl_set_build:Nw} and \cs{tl_build_end:}
+% start and end a group. The assignment to the \meta{tl~var} occurs
+% just after the end of that group, using \cs{tl_set:Nn},
+% \cs{tl_gset:Nn}, \cs{tl_set:Nx}, or \cs{tl_gset:Nx}.
+% \end{function}
+%
+% \begin{function}{\tl_build_one:n, \tl_build_one:o, \tl_build_one:x}
+% \begin{syntax}
+% \cs{tl_build_one:n} \Arg{tokens}
+% \end{syntax}
+% This function may only be used within the scope of a
+% \cs{tl_set_build:Nw} function. It adds the \meta{tokens} on the
+% right of the current token list.
+% \end{function}
+%
+% \begin{function}{\tl_build_end:}
+% Ends the scope started by \cs{tl_set_build:Nw}, and performs the
+% relevant assignment.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3tl-build} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+% \end{macrocode}
+%
+% \subsection{Variables and helper functions}
+%
+% \begin{variable}{\l_tl_build_start_index_int, \l_tl_build_index_int}
+% Integers pointing to the starting index (currently always starts at
+% zero), and the current index. The corresponding \tn{toks} are
+% accessed directly by number.
+% \begin{macrocode}
+\int_new:N \l_tl_build_start_index_int
+\int_new:N \l_tl_build_index_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_tl_build_result_tl}
+% The resulting token list is normally built in one go by unpacking
+% all \tn{toks} in some range. In the rare cases where there are too
+% many \cs{tl_build_one:n} commands, leading to the depletion of
+% registers, the contents of the current set of \tn{toks} is unpacked
+% into \cs{l_tl_build_result_tl}. This prevents overflow from
+% affecting the end-user (beyond an obvious performance hit).
+% \begin{macrocode}
+\tl_new:N \l_tl_build_result_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\tl_build_unpack:}
+% \begin{macro}[aux, EXP]{\tl_build_unpack_loop:w}
+% The various pieces of the token list are built in \tn{toks} from the
+% \texttt{start_index} (inclusive) to the (current) \texttt{index}
+% (excluded). Those \tn{toks} are unpacked and stored in order in the
+% \texttt{result} token list. Optimizations would be possible here,
+% for instance, unpacking $10$ \tn{toks} at a time with a macro
+% expanding to |\the\toks#10...\the\toks#19|, but this should be kept
+% for much later.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \tl_build_unpack:
+ {
+ \tl_put_right:Nx \l_tl_build_result_tl
+ {
+ \exp_after:wN \tl_build_unpack_loop:w
+ \int_use:N \l_tl_build_start_index_int ;
+ \prg_break_point:n { }
+ }
+ }
+\cs_new:Npn \tl_build_unpack_loop:w #1 ;
+ {
+ \if_num:w #1 = \l_tl_build_index_int
+ \exp_after:wN \prg_map_break:
+ \fi:
+ \tex_the:D \tex_toks:D #1 \exp_stop_f:
+ \exp_after:wN \tl_build_unpack_loop:w
+ \int_use:N \int_eval:w #1 + \c_one ;
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Building the token list}
+%
+% \begin{macro}
+% {
+% \tl_set_build:Nw , \tl_set_build_x:Nw ,
+% \tl_gset_build:Nw , \tl_gset_build_x:Nw
+% }
+% \begin{macro}[aux]{\tl_set_build_aux:NNw}
+% Similar to what is done for coffins: redefine some command, here
+% \cs{tl_build_end_aux:n} to hold the relevant assignment (see
+% \cs{tl_build_end:} for details). Then initialize the start index and
+% the current index at zero, and empty the \texttt{result} token list.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \tl_set_build:Nw
+ { \tl_set_build_aux:NNw \tl_set:Nn }
+\cs_new_protected_nopar:Npn \tl_set_build_x:Nw
+ { \tl_set_build_aux:NNw \tl_set:Nx }
+\cs_new_protected_nopar:Npn \tl_gset_build:Nw
+ { \tl_set_build_aux:NNw \tl_gset:Nn }
+\cs_new_protected_nopar:Npn \tl_gset_build_x:Nw
+ { \tl_set_build_aux:NNw \tl_gset:Nx }
+\cs_new_protected:Npn \tl_set_build_aux:NNw #1#2
+ {
+ \group_begin:
+ \cs_set_nopar:Npn \tl_build_end_assignment:n
+ { \group_end: #1 #2 }
+ \int_zero:N \l_tl_build_start_index_int
+ \int_zero:N \l_tl_build_index_int
+ \tl_clear:N \l_tl_build_result_tl
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\tl_build_end:}
+% \begin{macro}[aux]{\tl_build_end_assignment:n}
+% When we are done building a token list, unpack all \tn{toks} into
+% the \texttt{result} token list, and expand this list before closing
+% the group. The \cs{tl_build_end_assignment:n} function is defined by
+% \cs{tl_set_build_aux:NNw} to end the group and hold the relevant
+% assignment. Its value outside is irrelevant, but just in case, we
+% set it to a function which would clean up the contents of
+% \cs{l_tl_build_result_tl}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \tl_build_end:
+ {
+ \tl_build_unpack:
+ \exp_args:No
+ \tl_build_end_assignment:n \l_tl_build_result_tl
+ }
+\cs_new_eq:NN \tl_build_end_assignment:n \use_none:n
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\tl_build_one:n, \tl_build_one:o, \tl_build_one:x}
+% Store the tokens in a free \tn{toks}, then move the pointer to the
+% next one. If we overflow, unpack the current \tn{toks}, and reset
+% the current index, preparing to fill more \tn{toks}. This could be
+% optimized by avoiding to read |#1|, using \tn{afterassignment}.
+% \begin{macrocode}
+\cs_new_protected:Npn \tl_build_one:n #1
+ {
+ \tex_toks:D \l_tl_build_index_int {#1}
+ \tex_advance:D \l_tl_build_index_int \c_one
+ \if_num:w \l_tl_build_index_int > \c_max_register_int
+ \tl_build_unpack:
+ \l_tl_build_index_int \l_tl_build_start_index_int
+ \fi:
+ }
+\cs_new_protected:Npn \tl_build_one:o #1
+ {
+ \tex_toks:D \l_tl_build_index_int \exp_after:wN {#1}
+ \tex_advance:D \l_tl_build_index_int \c_one
+ \if_num:w \l_tl_build_index_int > \c_max_register_int
+ \tl_build_unpack:
+ \l_tl_build_index_int \l_tl_build_start_index_int
+ \fi:
+ }
+\cs_new_protected:Npn \tl_build_one:x #1
+ { \use:x { \tl_build_one:n {#1} } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex