diff options
author | Karl Berry <karl@freefriends.org> | 2008-08-06 23:37:15 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2008-08-06 23:37:15 +0000 |
commit | 7fe74d9b728f85523bb0a77b231fe16d379c6265 (patch) | |
tree | 4c55f17677758bd4ab08bb24a5fbcf58d3cb64f3 /Master/texmf-dist/source/latex/expl3/l3prg.dtx | |
parent | f26efa972afb0a49e7d84d043c942f138122752c (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.dtx | 167 |
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} % |