% \iffalse %% File: l3seq.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. %% %% ----------------------------------------------------------------------- % %\RequirePackage{l3names} %<*dtx> %\fi \def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{% \def\fileversion{#2}% \def\filedate{#3/#4/#5}% \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]% } %\iffalse % %\fi \GetIdInfo$Id: l3seq.dtx 573 2006-08-21 20:59:37Z morten $ {L3 Experimental sequences and stacks} % % % \iffalse %<*driver> \documentclass{l3doc} \begin{document} \DocInput{l3seq.dtx} \end{document} % % \fi % % % \title{The \textsf{l3seq} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Sequences} % \author{\Team} % \date{\filedate} % \maketitle % % % % \section{Sequences} % % \LaTeX3 implements a data type called `sequences'. These are special % token lists that can be accessed via special function on the `left'. % Appending tokens is possible at both ends. Appended token lists can be % accessed only as a union. The token lists that form the individual % items of a sequence might contain any tokens except two internal % functions that are used to structure sequences (see section internal % functions below). It is also possible to map functions on such % sequences so that they are executed for every item on the sequence. % % All functions that return items from a sequence in some \m{tlp} assume % that the \m{tlp} is local. See remarks below if you need a global % returned value. % % The defined functions are not orthogonal in the sense that every % possible variation possible is actually available. If you need a new % variant use the expansion functions described in the package % \texttt{l3expan} to build it. % % Adding items to the left of a sequence can currently be done with % either something like "\seq_put_left:Nn" or with a ``stack'' function % like "\seq_push:Nn" which has the same effect. Maybe one should % therefore remove the ``left'' functions totally. % % \subsection{Functions} % % \begin{function}{% % \seq_new:N | % \seq_new:c | % } % \begin{syntax} % "\seq_new:N" % \end{syntax} % Defines to be a variable of type sequences. % \end{function} % % \begin{function}{% % \seq_clear:N | % \seq_clear:c | % \seq_gclear:N | % \seq_gclear:c | % } % \begin{syntax} % "\seq_clear:N" % \end{syntax} % These functions locally or globally clear . % \end{function} % % \begin{function}{% % \seq_put_left:Nn | % \seq_put_left:No | % \seq_put_left:Nx | % \seq_put_left:cn | % \seq_put_right:Nn | % \seq_put_right:No | % \seq_put_right:Nx | % } % \begin{syntax} % "\seq_put_left:Nn" % \end{syntax} % Locally appends as a single item to the left % or right of . might get expanded before % appending. % \end{function} % % \begin{function}{% % \seq_gput_left:Nn | % \seq_gput_right:Nn | % \seq_gput_right:Nc | % \seq_gput_right:No | % \seq_gput_right:cn | % \seq_gput_right:co | % \seq_gput_right:cc | % } % \begin{syntax} % "\seq_gput_left:Nn" % \end{syntax} % Globally appends as a single item to the left % or right of . % \end{function} % % \begin{function}{% % \seq_get:NN | % \seq_get:cN | % } % \begin{syntax} % "\seq_get:NN" % \end{syntax} % Functions that locally assign the left-most item of to the % token list pointer . Item is not removed from ! If you % need a global return value you need to code something like this: % \begin{quote} % "\seq_get:NN" "\l_tmpa_tlp" \\ % "\tlp_gset_eq:NN" "\l_tmpa_tlp" % \end{quote} % But if this kind of construction is used often enough a separate % function should be provided. % \end{function} % % \begin{function}{% % \seq_set_eq:NN % } % \begin{syntax} % "\seq_set_eq:NN" % \end{syntax} % Function that locally makes identical to . % \end{function} % % % % \begin{function}{% % \seq_gset_eq:NN | % \seq_gset_eq:cN | % \seq_gset_eq:Nc | % \seq_gset_eq:cc % } % \begin{syntax} % "\seq_gset_eq:NN" % \end{syntax} % Function that globally makes identical to . % \end{function} % % \begin{function}{% % \seq_gconcat:NNN | % \seq_gconcat:ccc | % } % \begin{syntax} % "\seq_gconcat:NNN" % \end{syntax} % Function that conatenates and and globally assigns the % result to . % \end{function} % % \begin{function}{\seq_map_variable:NNn | % \seq_map_variable:cNn % } % \begin{syntax} % "\seq_map_variable:NNn" "{" "}" % \end{syntax} % Every element in is assigned to and then is executed. The operation is not expandable which means % that it can't be used within write operations etc. However, this % function can be nested which the others can't. % \end{function} % % \begin{function}{\seq_map:NN} % \begin{syntax} % "\seq_map:NN" % \end{syntax} % This function applies (which must be a function with one % argument) to every item of . is not executed % within a sub-group so that side effects can be achieved locally. The % operation is not expandable which means that it can't be used within % write operations etc. % % In the current implementation the next functions are more efficient and % should be preferred. % \end{function} % % \begin{function}{\seq_map_inline:Nn | % \seq_map_inline:cn % } % \begin{syntax} % "\seq_map_inline:Nn" "{" "}" % \end{syntax} % Applies (which should be the direct coding for a % function with one argument (i.e.\ use "##1" as the place holder for % this argument)) to every item of . is not % executed within a sub-group so that side effects can be achieved locally. % The operation is not expandable which means that it can't be used % within write operations etc. % \end{function} % % \subsection{Predicates and conditionals} % % \begin{function}{\seq_if_empty_p:N} % \begin{syntax} % "\seq_if_empty_p:N" % \end{syntax} % This predicate returns `true' if is `empty' i.e., doesn't % contain any tokens. % \end{function} % % \begin{function}{% % \seq_if_empty:NTF | % \seq_if_empty:cTF | % \seq_if_empty:NF | % \seq_if_empty:cF | % } % \begin{syntax} % "\seq_if_empty:NTF" "{" "}{" "}" % \end{syntax} % Set of conditionals that test whether or not a particular % is empty and if so executes either or . % \end{function} % % \begin{function}{% % \seq_if_in:NnTF | % \seq_if_in:cnTF | % \seq_if_in:coTF | % \seq_if_in:cxTF | % \seq_if_in:NnF | % \seq_if_in:cnF | % } % \begin{syntax} % "\seq_if_in:NnTF" "{" "}{" "}{" "}" % \end{syntax} % Function that tests if is in . Depending on the result % either or is executed. % \end{function} % % \subsection{Internal functions} % % \begin{function}{\seq_if_empty_err:N} % \begin{syntax} % "\seq_if_empty_err:N" % \end{syntax} % Signals an \LaTeX3 error if is empty. % \end{function} % % \begin{function}{\seq_pop_aux:nnNN} % \begin{syntax} % "\seq_pop_aux:nnNN" % \end{syntax} % Function that assigns the left-most item of to using % and assigns the tail to using . This % function could be used to implement a global return function. % \end{function} % % \begin{function}{% % \seq_get_aux:w | % \seq_pop_aux:w | % \seq_put_aux:Nnn | % \seq_put_aux:w | % } % Functions used to implement put and get operations. They are not for % meant for direct use. % \end{function} % % \begin{function}{% % \seq_elt:w | % \seq_elt_end: } % Functions (usually used as constants) that separates items within a % sequence. They might get special meaning during mapping operations and % are not supposed to show up as tokens within an item appended to a % sequence. % \end{function} % % \section{Sequence Stacks} % % Special sequences in \LaTeX3 are `stacks' with their usual operations % of`push', `pop', and `top'. They are internally implemented as % sequences and share some of the functions (like "\seq_new:N" etc.) % % \subsection{Functions} % % \begin{function}{% % \seq_push:Nn | % \seq_push:No | % \seq_push:cn | % \seq_gpush:Nn | % \seq_gpush:No | % \seq_gpush:cn | % } % \begin{syntax} % "\seq_push:Nn" "{" "}" % \end{syntax} % Locally or globally pushes as a single item onto the % . might get expanded before the operation. % \end{function} % % \begin{function}{% % \seq_pop:NN | % \seq_pop:cN | % \seq_gpop:NN | % \seq_gpop:cN | % } % \begin{syntax} % "\seq_pop:NN" % \end{syntax} % Functions that assign the top item of to the token % list pointer and removes it from ! % \end{function} % % \begin{function}{% % \seq_top:NN | % \seq_top:cN | % } % \begin{syntax} % "\seq_top:NN" % \end{syntax} % Functions that locally assign the top item of to the token % list pointer . Item is not removed from ! % \end{function} % % \subsection{Predicates and conditionals} % % Use "seq" functions. % % \StopEventually{} % % \subsection {Implementation} % % % We start by ensuring that the required packages are loaded. % \begin{macrocode} %\RequirePackage{l3quark} %\RequirePackage{l3tlp} %\RequirePackage{l3chk} %\RequirePackage{l3expan} % \end{macrocode} % % A sequence is a control sequence whose top-level expansion is of the % form `|\seq_elt:w| \m{text$\sb1$} |\seq_elt_end:| \ldots{} % |\seq_elt:w| \zv{text$\sb{n}$} \ldots'. We use explicit delimiters % instead of braces around \m{text} to allow efficient searching for % an item in the sequence. % % \begin{macro}{\seq_elt:w} % \begin{macro}{\seq_elt_end:} % We allocate the delimiters and make them errors if executed. % \begin{macrocode} %<*initex|package> \let_new:NN \seq_elt:w \ERROR \let_new:NN \seq_elt_end: \ERROR % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\seq_new:N} % \begin{macro}{\seq_new:c} % Sequences are implemented using token lists. % \begin{macrocode} \def_new:Npn \seq_new:N #1{\tlp_new:Nn #1{}} \def_new:Npn \seq_new:c {\exp_args:Nc \seq_new:N} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_clear:N} % \begin{macro}{\seq_clear:c} % \begin{macro}{\seq_gclear:N} % \begin{macro}{\seq_gclear:c} % Clearing a sequence is the same as clearing a token list. % \begin{macrocode} \let_new:NN \seq_clear:N \tlp_clear:N \let_new:NN \seq_clear:c \tlp_clear:c \let_new:NN \seq_gclear:N \tlp_gclear:N \let_new:NN \seq_gclear:c \tlp_gclear:c % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_clear_new:N} % \begin{macro}{\seq_clear_new:c} % \begin{macro}{\seq_gclear_new:N} % \begin{macro}{\seq_gclear_new:c} % Clearing a sequence is the same as clearing a token list. % \begin{macrocode} \let_new:NN \seq_clear_new:N \tlp_clear_new:N \let_new:NN \seq_clear_new:c \tlp_clear_new:c \let_new:NN \seq_gclear_new:N \tlp_gclear_new:N \let_new:NN \seq_gclear_new:c \tlp_gclear_new:c % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_if_empty_p:N} % A predicate which evaluates to |\c_true| iff the sequence is empty. % \begin{macrocode} \let_new:NN \seq_if_empty_p:N \tlp_if_empty_p:N % \end{macrocode} % \end{macro} % % \begin{macro}{\seq_if_empty:NTF} % \begin{macro}{\seq_if_empty:cTF} % \begin{macro}{\seq_if_empty:NF} % \begin{macro}{\seq_if_empty:cF} % |\seq_if_empty:NTF|\m{seq}\m{true~case}\m{false~case} will check % whether the \m{seq} is empty and then select one of the other % arguments. |seq_if_empty:cTF| turns its first argument into a % control sequence to get the name of the sequence. % \begin{macrocode} \let_new:NN \seq_if_empty:NTF \tlp_if_empty:NTF \def_new:Npn \seq_if_empty:cTF {\exp_args:Nc\seq_if_empty:NTF} % \end{macrocode} % A variant of this, is only to do something if the sequence is % \emph{not} empty. % \begin{macrocode} \let_new:NN \seq_if_empty:NF \tlp_if_empty:NF \def_new:Npn \seq_if_empty:cF {\exp_args:Nc\seq_if_empty:NF} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\seq_if_empty_err:N} % Signals an error if the sequence is empty. % \begin{macrocode} \def_new:Npn \seq_if_empty_err:N #1{\if_meaning:NN#1\c_empty_tlp % \end{macrocode} % As I said before, I don't think we need to provide checks for this % kind of error, since it is a severe internal macro package error % that can not be produced by the user directly. Can it? So the % next line of code should be probably removed. % \begin{macrocode} \tlp_clear:N \l_testa_tlp % catch prefixes \err_latex_bug:x{Empty~sequence~`\token_to_string:N#1'}\fi:} % \end{macrocode} % \end{macro} % % \begin{macro}{\seq_get:NN} % \begin{macro}{\seq_get:cN} % |\seq_get:NN |\zz{sequence}\zz{cmd} defines \zz{cmd} to be the % left_most element of \zz{sequence}. % \begin{macrocode} \def_new:Npn \seq_get:NN #1{ \seq_if_empty_err:N #1 \exp_after:NN\seq_get_aux:w #1\q_stop} \def_new:Npn \seq_get_aux:w \seq_elt:w #1\seq_elt_end: #2\q_stop #3{\tlp_set:Nn #3{#1}} \def_new:Npn \seq_get:cN {\exp_args:Nc \seq_get:NN} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_pop_aux:nnNN} % \begin{macro}{\seq_pop_aux:w} % |\seq_pop_aux:nnNN| \zz{def$\sb1$} \zz{def$\sb2$} \zz{sequence} % \zz{cmd} assigns the left_most element of \zz{sequence} to % \zz{cmd} using \zz{def$\sb2$}, and assigns the tail of % \zz{sequence} to \zz{sequence} using \zz{def$\sb1$}. % \begin{macrocode} \def_new:Npn \seq_pop_aux:nnNN #1#2#3{ \seq_if_empty_err:N #3 \exp_after:NN\seq_pop_aux:w #3\q_stop #1#2#3} \def_new:Npn \seq_pop_aux:w \seq_elt:w #1\seq_elt_end: #2\q_stop #3#4#5#6{#3#5{#2}#4#6{#1}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_put_aux:Nnn} % |\seq_put_aux:Nnn| \zz{sequence} \zv{left} \zv{right} adds the % elements specified by \zv{left} to the left of \zz{sequence}, and % those specified by \zv{right} to the right. % \begin{macrocode} \def_new:Npn \seq_put_aux:Nnn #1{ \exp_after:NN\seq_put_aux:w #1\q_stop #1} \def_new:Npn \seq_put_aux:w #1\q_stop #2#3#4{\tlp_set:Nn #2{#3#1#4}} % \end{macrocode} % \end{macro} % % \begin{macro}{\seq_put_left:Nn} % \begin{macro}{\seq_put_left:No} % \begin{macro}{\seq_put_left:Nx} % \begin{macro}{\seq_put_left:cn} % \begin{macro}{\seq_put_right:Nn} % \begin{macro}{\seq_put_right:No} % \begin{macro}{\seq_put_right:Nx} % Here are the usual operations for adding to the left and right. % \begin{macrocode} \def_new:Npn \seq_put_left:Nn #1#2{ % \end{macrocode} % We can't put in a |\use_noop:| instead of |{}| since this argument is % passed literally (and we would end up with many |\use_noop:|s inside % the sequences. % \begin{macrocode} \seq_put_aux:Nnn #1{\seq_elt:w #2\seq_elt_end:}{}} \def_new:Npn \seq_put_left:cn {\exp_args:Nc\seq_put_left:Nn} \def_new:Npn \seq_put_left:No {\exp_args:NNo\seq_put_left:Nn} \def_new:Npn \seq_put_left:Nx {\exp_args:Nnx\seq_put_left:Nn} \def_new:Npn \seq_put_right:Nn #1#2{ \seq_put_aux:Nnn #1{}{\seq_elt:w #2\seq_elt_end:}} \def_new:Npn \seq_put_right:No {\exp_args:NNo\seq_put_right:Nn} \def_new:Npn \seq_put_right:Nx {\exp_args:NNx\seq_put_right:Nn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_gput_left:Nn} % \begin{macro}{\seq_gput_right:Nn} % \begin{macro}{\seq_gput_right:Nc} % \begin{macro}{\seq_gput_right:No} % \begin{macro}{\seq_gput_right:cn} % \begin{macro}{\seq_gput_right:co} % \begin{macro}{\seq_gput_right:cc} % An here the global variants. % \begin{macrocode} \def_new:Npn \seq_gput_left:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \seq_put_left:Nn} \def_new:Npn \seq_gput_right:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \seq_put_right:Nn} \def_new:Npn \seq_gput_right:No {\exp_args:NNo \seq_gput_right:Nn} \def_new:Npn \seq_gput_right:Nc {\exp_args:NNc \seq_gput_right:Nn} \def_new:Npn \seq_gput_right:cn {\exp_args:Nc \seq_gput_right:Nn} \def_new:Npn \seq_gput_right:co {\exp_args:Nco \seq_gput_right:Nn} \def_new:Npn \seq_gput_right:cc {\exp_args:Ncc \seq_gput_right:Nn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_map_variable:NNn} % \begin{macro}{\seq_map_variable:cNn} % \begin{macro}{\seq_map_variable_aux:nw} % \begin{macro}{\seq_map_break:w} % Nothing spectacular here. The shuffling of the arguments in % |\seq_map_variable:NNn| below could also be done with % |\exp_args:NNnE|. % \begin{macrocode} \def_new:Npn \seq_map_variable_aux:Nnw #1#2\seq_elt:w#3\seq_elt_end:{ \tlp_set:Nn #1{#3} \quark_if_nil:NT #1 \seq_map_break:w #2 \seq_map_variable_aux:Nnw #1{#2} } \def_new:Npn \seq_map_variable:NNn #1#2#3{ \tlp_set:Nx #2 {\exp_not:n{\seq_map_variable_aux:Nnw #2{#3}}} \exp_after:NN #2 #1 \seq_elt:w \q_nil\seq_elt_end: \q_stop } \def_new:Npn \seq_map_variable:cNn{\exp_args:Nc\seq_map_variable:Nn} \let_new:NN \seq_map_break:w \use_none_delimit_by_q_stop:w % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_map:NN} % |\seq_map:NN| \zz{sequence} \zz{cmd} applies \zz{cmd} to each % element of \zz{sequence}, from left to right. Since we don't have % braces, this implementation is not very efficient. It might be % better to say that \zz{cmd} must be a function with one argument % that is delimited by |\seq_elt_end:|. % \begin{macrocode} \def_new:Npn \seq_map:NN #1#2{ \def:Npn \seq_elt:w ##1\seq_elt_end: {#2{##1}}#1 \let:NN \seq_elt:w \ERROR } % \end{macrocode} % \end{macro} % % \begin{macro}{\seq_map_inline:Nn} % \begin{macro}{\seq_map_inline:cn} % When no braces are used, this version of mapping seems more % natural. % \begin{macrocode} \def_new:Npn \seq_map_inline:Nn #1#2{ \def:Npn \seq_elt:w ##1\seq_elt_end: {#2}#1 \let:NN \seq_elt:w \ERROR } \def_new:Npn \seq_map_inline:cn{\exp_args:Nc\seq_map_inline:Nn} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_set_eq:NN} % \begin{macro}{\seq_set_eq:Nc} % We can set one seq equal to another. % \begin{macrocode} \let_new:NN \seq_set_eq:NN \let:NN \def_new:Npn \seq_set_eq:Nc {\exp_args:NNc \seq_set_eq:NN} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\seq_gset_eq:NN} % \begin{macro}{\seq_gset_eq:cN} % \begin{macro}{\seq_gset_eq:Nc} % \begin{macro}{\seq_gset_eq:cc} % An of course globally which seems to be needed far more % often.\footnote{To save a bit of space these functions could be made % identical to those from the tlp or clist module.} % \begin{macrocode} \let_new:NN \seq_gset_eq:NN \glet:NN \def_new:Npn \seq_gset_eq:cN {\exp_args:Nc \seq_gset_eq:NN} \def_new:Npn \seq_gset_eq:Nc {\exp_args:NNc \seq_gset_eq:NN} \def_new:Npn \seq_gset_eq:cc {\exp_args:Ncc \seq_gset_eq:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_gconcat:NNN} % \begin{macro}{\seq_gconcat:ccc} % |\seq_gconcat:NNN| \m{seq~1} \m{seq~2} \m{seq~3} will globally % assign \m{seq~1} the concatenation of \m{seq~2} and \m{seq~3}. % \begin{macrocode} \def_new:Npn \seq_gconcat:NNN #1#2#3{ \tlp_gset:Nx #1 {\exp_not:o{#2}\exp_not:o{#3}} } \def_new:Npn \seq_gconcat:ccc{\exp_args:Nccc\seq_gconcat:NNN} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_if_in:NnTF} % \begin{macro}{\seq_if_in:cnTF} % \begin{macro}{\seq_if_in:coTF} % \begin{macro}{\seq_if_in:cxTF} % \begin{macro}{\seq_if_in:NnF} % \begin{macro}{\seq_if_in:cnF} % |\seq_if_in:NnTF| \m{seq}\m{item} \m{true~case} \m{false~case} % will check whether \m{item} is in \m{seq} and then either execute % the \m{true~case} or the \m{false~case}. \m{true~case} and % \m{false~case} may contain incomplete |\if_charcode:w| % statements. % \begin{macrocode} \def_new:Npn \seq_if_in:NnTF #1#2{ \def:Npn\tmp:w ##1\seq_elt:w #2\seq_elt_end: ##2##3\q_stop{ % \end{macrocode} % Note that |##2| contains exactly one token which we can compare % with |\q_no_value|. % \begin{macrocode} \if_meaning:NN\q_no_value##2 \exp_after:NN\use_arg_ii:nn \else: \exp_after:NN\use_arg_i:nn \fi: } \exp_after:NN \tmp:w #1\seq_elt:w #2\seq_elt_end: \q_no_value \q_stop} \def_new:Npn \seq_if_in:coTF {\exp_args:Nco \seq_if_in:NnTF} \def_new:Npn \seq_if_in:cnTF {\exp_args:Nc \seq_if_in:NnTF} \def_new:Npn \seq_if_in:cxTF {\exp_args:Ncx \seq_if_in:NnTF} % \end{macrocode} % % \begin{macrocode} \def_new:Npn \seq_if_in:NnF #1#2 { \seq_if_in:NnTF #1{#2}\use_noop: } \def_new:Npn \seq_if_in:cnF {\exp_args:Nc \seq_if_in:NnF} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \subsubsection{Stack operations} % % We build stacks from sequences, but here we put the % specific functions together. % % % \begin{macro}{\seq_push:Nn} % \begin{macro}{\seq_push:No} % \begin{macro}{\seq_push:cn} % \begin{macro}{\seq_pop:NN} % \begin{macro}{\seq_pop:cN} % Since sequences can be used as stacks, we ought to have both % `push' and `pop'. In most cases they are nothing more then new % names for old functions. % \begin{macrocode} \let_new:NN \seq_push:Nn \seq_put_left:Nn \let_new:NN \seq_push:No \seq_put_left:No \let_new:NN \seq_push:cn \seq_put_left:cn \def_new:Npn \seq_pop:NN {\seq_pop_aux:nnNN \tlp_set:Nn \tlp_set:Nn} \def_new:Npn \seq_pop:cN {\exp_args:Nc \seq_pop:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \begin{macro}{\seq_gpush:Nn} % \begin{macro}{\seq_gpush:No} % \begin{macro}{\seq_gpush:cn} % \begin{macro}{\seq_gpush:NC} % \begin{macro}{\seq_gpop:NN} % \begin{macro}{\seq_gpop:cN} % I don't agree with Denys that one needs only local stacks, % actually I believe that one will probably need the functions % here more often. In case of |\seq_gpop:NN| the value is % nevertheless returned locally. % \begin{macrocode} \let_new:NN \seq_gpush:Nn \seq_gput_left:Nn \def_new:Npn \seq_gpush:No {\exp_args:NNo \seq_gpush:Nn} \def_new:Npn \seq_gpush:cn {\exp_args:Nc \seq_gpush:Nn} \def_new:Npn \seq_gpush:NC {\exp_args:NNC \seq_gpush:Nn} \def_new:Npn \seq_gpop:NN {\seq_pop_aux:nnNN \tlp_gset:Nn \tlp_set:Nn} \def_new:Npn \seq_gpop:cN {\exp_args:Nc \seq_gpop:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\seq_top:NN} % \begin{macro}{\seq_top:cN} % Looking at the top element of the stack without removing it is % done with this operation. % \begin{macrocode} \let_new:NN \seq_top:NN \seq_get:NN \let_new:NN \seq_top:cN \seq_get:cN % \end{macrocode} % \end{macro} % \end{macro} % % % Show token usage: % \begin{macrocode} % %<*showmemory> %\showMemUsage % % \end{macrocode} % % \endinput % % $Log$ % Revision 1.23 2006/08/09 21:12:50 morten % Minor change in \seq_gconcat:NNN % % Revision 1.22 2006/03/20 18:26:39 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.21 2005/12/29 01:28:29 morten % Added a new mapping function (needed in xparse) % % Revision 1.20 2005/12/27 10:06:10 morten % Minor changes plus changed RCS information retrieval % % Revision 1.19 2005/04/06 21:36:08 morten % Removed dependency on l3toks and added an if_in variant % % Revision 1.18 2005/03/22 23:28:05 morten % Fix coding as Benjamin pointed out % % Revision 1.17 2005/03/16 22:35:51 braams % Added the tweaks necessary to be able to load with initex % % Revision 1.16 2005/03/11 21:42:10 braams % Fixed the use of RCS information; added \StopEventually % Fixed a few documentation typos %