summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/expl3/l3prg.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2008-08-06 23:37:15 +0000
committerKarl Berry <karl@freefriends.org>2008-08-06 23:37:15 +0000
commit7fe74d9b728f85523bb0a77b231fe16d379c6265 (patch)
tree4c55f17677758bd4ab08bb24a5fbcf58d3cb64f3 /Master/texmf-dist/source/latex/expl3/l3prg.dtx
parentf26efa972afb0a49e7d84d043c942f138122752c (diff)
expl3 update (6aug08)
git-svn-id: svn://tug.org/texlive/trunk@10123 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3prg.dtx')
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3prg.dtx167
1 files changed, 159 insertions, 8 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3prg.dtx b/Master/texmf-dist/source/latex/expl3/l3prg.dtx
index 72084e07132..b99caf822d7 100644
--- a/Master/texmf-dist/source/latex/expl3/l3prg.dtx
+++ b/Master/texmf-dist/source/latex/expl3/l3prg.dtx
@@ -36,7 +36,7 @@
\RequirePackage{l3names}
%</driver|package>
%\fi
-\GetIdInfo$Id: l3prg.dtx 697 2007-11-27 14:14:54Z morten $
+\GetIdInfo$Id: l3prg.dtx 768 2008-08-05 19:45:06Z morten $
{L3 Experimental control structures}
%\iffalse
%<*driver>
@@ -364,6 +364,71 @@
% \end{quote}
% ultimately returns \m{true}.
% \end{function}
+%
+% \subsubsection{Case switches}
+%
+%
+% \begin{function}{
+% \prg_case_int:nnn |
+%
+% }
+% \begin{syntax}
+% "\prg_case_int:nnn" "{"<integer expr>"}" "{"
+% " {"\m{integer expr$\sb 1$}"}""{"\m{code$\sb 1$}"}""{"\m{integer expr$\sb 2$}"}""{"\m{code$\sb 2$}"}"\\
+% " ...""{"\m{integer expr$\sb n$}"}""{"\m{code$\sb n$}"}"\\
+% "}" "{"\m{else case}"}"
+% \end{syntax}
+% This function evaluates the first \meta{integer expr} and then compares it
+% to the values found in the list. Thus the expression
+% \begin{verbatim}
+% \prg_case:nnn{2*5}{
+% {5}{Small} {4+6}{Medium} {-2*10}{Negative}
+% }{Other}
+% \end{verbatim}
+% evaluates first the term to look for and then tries to find this
+% value in the list of values. If the value is found, the code on its
+% right is executed after removing the remainder of the list. If the
+% value is not found, the \meta{else case} is executed. The example
+% above will return ``Medium''.
+%
+% The function is expandable and is written in such a way that
+% \texttt{f} style expansion can take place cleanly, i.e., no tokens
+% from within the function are left over.
+% \end{function}
+%
+% \begin{function}{
+% \prg_case_dim:nnn |
+%
+% }
+% \begin{syntax}
+% "\prg_case_int:nnn" "{"<dim expr>"}" "{"
+% " {"\m{dim expr$\sb 1$}"}""{"\m{code$\sb 1$}"}""{"\m{dim expr$\sb 2$}"}""{"\m{code$\sb 2$}"}"\\
+% " ...""{"\m{dim expr$\sb n$}"}""{"\m{code$\sb n$}"}"\\
+% "}" "{"\m{else case}"}"
+% \end{syntax}
+% This function works just like |\prg_case_int:nnn| except it works
+% for \meta{dim} registers.
+% \end{function}
+%
+% \begin{function}{
+% \prg_case_str:nnn |
+%
+% }
+% \begin{syntax}
+% "\prg_case_str:nnn" "{"<string>"}" "{"
+% " {"\m{string$\sb 1$}"}""{"\m{code$\sb 1$}"}""{"\m{string$\sb 2$}"}""{"\m{code$\sb 2$}"}"\\
+% " ...""{"\m{string$\sb n$}"}""{"\m{code$\sb n$}"}"\\
+% "}" "{"\m{else case}"}"
+% \end{syntax}
+% This function works just like |\prg_case_int:nnn| except it
+% compares strings. Each string is evaluated fully using \texttt{x}
+% style expansion.
+%
+% The function is expandable\footnote{Provided you use pdfTeX v1.30 or
+% later} and is written in such a way that
+% \texttt{f} style expansion can take place cleanly, i.e., no tokens
+% from within the function are left over.
+% \end{function}
%
% \subsubsection{Generic loops}
%
@@ -701,25 +766,26 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\l_prg_inline_level_int}
+% \begin{macro}{\g_prg_inline_level_int}
% \begin{macro}{\prg_stepwise_inline:nnnn}
% \begin{macro}{\prg_stepwise_inline_decr:nnnn}
% \begin{macro}{\prg_stepwise_inline_incr:nnnn}
% This function uses the same approach as for instance
% |\clist_map_inline:Nn| to allow arbitrary nesting. First construct
% the special function and then call an auxiliary one which just
-% carries the newly constructed csname.
+% carries the newly constructed csname. Must make assignments global
+% when we maintain our own stack.
% \begin{macrocode}
-\int_new:N\l_prg_inline_level_int
+\int_new:N\g_prg_inline_level_int
\def_long_new:NNn\prg_stepwise_inline:nnnn 4{
- \int_incr:N \l_prg_inline_level_int
- \def:cpn{prg_stepwise_inline_\int_use:N\l_prg_inline_level_int :n}##1{#4}
+ \int_gincr:N \g_prg_inline_level_int
+ \gdef:cpn{prg_stepwise_inline_\int_use:N\g_prg_inline_level_int :n}##1{#4}
\num_compare:nNnTF {#2}<\c_zero
{\exp_args:Nco \prg_stepwise_inline_decr:Nnnn }
{\exp_args:Nco \prg_stepwise_inline_incr:Nnnn }
- {prg_stepwise_inline_\int_use:N\l_prg_inline_level_int :n}
+ {prg_stepwise_inline_\int_use:N\g_prg_inline_level_int :n}
{\int_use:N\int_eval:n{#1}} {#2} {#3}
- \int_decr:N \l_prg_inline_level_int
+ \int_gdecr:N \g_prg_inline_level_int
}
\def_long_new:NNn \prg_stepwise_inline_incr:Nnnn 4{
\num_compare:nNnF {#2}>{#4}
@@ -1091,6 +1157,91 @@
% \end{macrocode}
% \end{macro}
%
+% \subsubsection{Case switch}
+%
+% \begin{macro}{\prg_case_int:nnn}
+% \begin{macro}{\prg_case_int_aux:nnn}
+% This case switch is in reality quite simple. It takes three arguments:
+% \begin{enumerate}
+% \item An integer expression you wish to find.
+% \item A list of pairs of "{"\meta{integer
+% expr}"}""{"\meta{code}"}". The list can be as long as is desired
+% and \meta{integer expr} can be negative.
+% \item The code to be executed if the value wasn't found.
+% \end{enumerate}
+% We don't need the else case here yet, so leave it dangling in the
+% input stream.
+% \begin{macrocode}
+\def_long:Npn \prg_case_int:nnn #1 #2 {
+% \end{macrocode}
+% We will be parsing on |#1| for each step so we might as well
+% evaluate it first in case it is complicated.
+% \begin{macrocode}
+ \exp_args:No \prg_case_int_aux:nnn {\num_value:w \int_eval:n{#1}} #2
+% \end{macrocode}
+% The \texttt{?} below is just so there are enough arguments when we
+% reach the end. And it made you look.~\texttt{;-)}
+% \begin{macrocode}
+ \q_recursion_tail ? \q_recursion_stop
+}
+\def_long_new:Npn \prg_case_int_aux:nnn #1#2#3{
+% \end{macrocode}
+% If we reach the end, return the else case. We just remove braces.
+% \begin{macrocode}
+ \quark_if_recursion_tail_stop_do:nn{#2}{\use_arg_i:n}
+% \end{macrocode}
+% Otherwise we compare (which evaluates |#2| for us)
+% \begin{macrocode}
+ \num_compare:nNnTF{#1}={#2}
+% \end{macrocode}
+% If true, we want to remove the remainder of the list, the else case
+% and then execute the code specified. Why not use |#3\use_none:n|?
+% Because if we are doing |f| style expansion, we will get
+% leftovers. If the test was false, we try the next pair, carrying the
+% |#1|.
+% \begin{macrocode}
+ { \use_arg_i_delimit_by_q_recursion_stop:nw {\use_arg_i:nn{#3}} }
+ { \prg_case_int_aux:nnn {#1}}
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\prg_case_dim:nnn}
+% \begin{macro}{\prg_case_dim_aux:nnn}
+% Same as |\prg_case_dim:nnn| except it is for \meta{dim} registers.
+% \begin{macrocode}
+\def_long:Npn \prg_case_dim:nnn #1 #2 {
+ \exp_args:No \prg_case_dim_aux:nnn {\dim_use:N \dim_eval:n{#1}} #2
+ \q_recursion_tail ? \q_recursion_stop
+}
+\def_long_new:Npn \prg_case_dim_aux:nnn #1#2#3{
+ \quark_if_recursion_tail_stop_do:nn{#2}{\use_arg_i:n}
+ \dim_compare:nNnTF{#1}={#2}
+ { \use_arg_i_delimit_by_q_recursion_stop:nw {\use_arg_i:nn{#3}} }
+ { \prg_case_dim_aux:nnn {#1}}
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\prg_case_str:nnn}
+% \begin{macro}{\prg_case_str_aux:nnn}
+% Same as |\prg_case_dim:nnn| except it is for strings.
+% \begin{macrocode}
+\def_long:Npn \prg_case_str:nnn #1 #2 {
+ \prg_case_str_aux:nnn {#1} #2
+ \q_recursion_tail ? \q_recursion_stop
+}
+\def_long_new:Npn \prg_case_str_aux:nnn #1#2#3{
+ \quark_if_recursion_tail_stop_do:nn{#2}{\use_arg_i:n}
+ \tlist_if_eq:xxTF{#1}{#2}
+ { \use_arg_i_delimit_by_q_recursion_stop:nw {\use_arg_i:nn{#3}} }
+ { \prg_case_str_aux:nnn {#1}}
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
%
% \subsubsection{Sorting}
%