summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3int.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3int.dtx219
1 files changed, 150 insertions, 69 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
index e67616a2f7d..dcea709ebbc 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3int.dtx Copyright (C) 1990-2012 The LaTeX3 Project
+%% File: l3int.dtx Copyright (C) 1990-2013 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
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{l3bootstrap}
-\GetIdInfo$Id: l3int.dtx 4237 2012-09-26 10:18:58Z bruno $
+\GetIdInfo$Id: l3int.dtx 4444 2013-01-13 20:27:20Z bruno $
{L3 Integers}
%</driver|package>
%<*driver>
@@ -300,16 +300,36 @@
% \end{center}
% \end{function}
%
-% \begin{function}[EXP,pTF]{\int_compare:n}
+% \begin{function}[updated = 2013-01-13, EXP, pTF]{\int_compare:n}
% \begin{syntax}
-% \cs{int_compare_p:n} \{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \\
+% \cs{int_compare_p:n} \\
+% ~~\{ \\
+% ~~~~\meta{intexpr_1} \meta{relation_1} \\
+% ~~~~\ldots{} \\
+% ~~~~\meta{intexpr_N} \meta{relation_N} \\
+% ~~~~\meta{intexpr_{N+1}} \\
+% ~~\} \\
% \cs{int_compare:nTF}
-% ~~\{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \}
+% ~~\{ \\
+% ~~~~\meta{intexpr_1} \meta{relation_1} \\
+% ~~~~\ldots{} \\
+% ~~~~\meta{intexpr_N} \meta{relation_N} \\
+% ~~~~\meta{intexpr_{N+1}} \\
+% ~~\} \\
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
-% This function first evaluates each of the \meta{integer expressions}
-% as described for \cs{int_eval:n}. The two results are then
-% compared using the \meta{relation}:
+% This function evaluates the \meta{integer expressions} as described
+% for \cs{int_eval:n} and compares consecutive result using the
+% corresponding \meta{relation}, namely it compares \meta{intexpr_1}
+% and \meta{intexpr_2} using the \meta{relation_1}, then
+% \meta{intexpr_2} and \meta{intexpr_3} using the \meta{relation_2},
+% until finally comparing \meta{intexpr_N} and \meta{intexpr_{N+1}}
+% using the \meta{relation_N}. The test yields \texttt{true} if all
+% comparisons are \texttt{true}. Each \meta{integer expression} is
+% evaluated only once, and the evaluation is lazy, in the sense that
+% if one comparison is \texttt{false}, then no other \meta{integer
+% expression} is evaluated and no other comparison is performed.
+% The \meta{relations} can be any of the following:
% \begin{center}
% \begin{tabular}{ll}
% Equal & |=| or |==| \\
@@ -413,35 +433,35 @@
% \texttt{false}.
% \end{function}
%
-% \begin{function}[rEXP]{\int_do_until:nn}
+% \begin{function}[updated = 2013-01-13, rEXP]{\int_do_until:nn}
% \begin{syntax}
-% \cs{int_do_until:nn} \{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
+% \cs{int_do_until:nn} \Arg{integer relation} \Arg{code}
% \end{syntax}
% Places the \meta{code} in the input stream for \TeX{} to process, and
-% then evaluates the relationship between the two
-% \meta{integer expressions} as described for \cs{int_compare:nTF}.
+% then evaluates the \meta{integer relation}
+% as described for \cs{int_compare:nTF}.
% If the test is \texttt{false} then the \meta{code} will be inserted
% into the input stream again and a loop will occur until the
% \meta{relation} is \texttt{true}.
% \end{function}
%
-% \begin{function}[rEXP]{\int_do_while:nn}
+% \begin{function}[updated = 2013-01-13, rEXP]{\int_do_while:nn}
% \begin{syntax}
-% \cs{int_do_while:nn} \{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
+% \cs{int_do_while:nn} \Arg{integer relation} \Arg{code}
% \end{syntax}
% Places the \meta{code} in the input stream for \TeX{} to process, and
-% then evaluates the relationship between the two
-% \meta{integer expressions} as described for \cs{int_compare:nTF}.
+% then evaluates the \meta{integer relation}
+% as described for \cs{int_compare:nTF}.
% If the test is \texttt{true} then the \meta{code} will be inserted
% into the input stream again and a loop will occur until the
% \meta{relation} is \texttt{false}.
% \end{function}
%
-% \begin{function}[rEXP]{\int_until_do:nn}
+% \begin{function}[updated = 2013-01-13, rEXP]{\int_until_do:nn}
% \begin{syntax}
-% \cs{int_until_do:nn} \{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
+% \cs{int_until_do:nn} \Arg{integer_relation} \Arg{code}
% \end{syntax}
-% Evaluates the relationship between the two \meta{integer expressions}
+% Evaluates the \meta{integer relation}
% as described for \cs{int_compare:nTF}, and then places the
% \meta{code} in the input stream if the \meta{relation} is
% \texttt{false}. After the \meta{code} has been processed by \TeX{} the
@@ -449,11 +469,11 @@
% \texttt{true}.
% \end{function}
%
-% \begin{function}[rEXP]{\int_while_do:nn}
+% \begin{function}[updated = 2013-01-13, rEXP]{\int_while_do:nn}
% \begin{syntax}
-% \cs{int_while_do:nn} \{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
+% \cs{int_while_do:nn} \Arg{integer relation} \Arg{code}
% \end{syntax}
-% Evaluates the relationship between the two \meta{integer expressions}
+% Evaluates the \meta{integer relation}
% as described for \cs{int_compare:nTF}, and then places the
% \meta{code} in the input stream if the \meta{relation} is
% \texttt{true}. After the \meta{code} has been processed by \TeX{} the
@@ -591,7 +611,7 @@
%
% \begin{function}[updated = 2011-09-17, EXP]{\int_to_hexadecimal:n}
% \begin{syntax}
-% \cs{int_to_binary:n} \Arg{integer expression}
+% \cs{int_to_hexadecimal:n} \Arg{integer expression}
% \end{syntax}
% Calculates the value of the \meta{integer expression} and places
% the hexadecimal (base~$16$) representation of the result in the
@@ -1167,14 +1187,8 @@
% \begin{macro}[pTF]{\int_if_exist:N, \int_if_exist:c}
% Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
% \begin{macrocode}
-\cs_new_eq:NN \int_if_exist:NTF \cs_if_exist:NTF
-\cs_new_eq:NN \int_if_exist:NT \cs_if_exist:NT
-\cs_new_eq:NN \int_if_exist:NF \cs_if_exist:NF
-\cs_new_eq:NN \int_if_exist_p:N \cs_if_exist_p:N
-\cs_new_eq:NN \int_if_exist:cTF \cs_if_exist:cTF
-\cs_new_eq:NN \int_if_exist:cT \cs_if_exist:cT
-\cs_new_eq:NN \int_if_exist:cF \cs_if_exist:cF
-\cs_new_eq:NN \int_if_exist_p:c \cs_if_exist_p:c
+\prg_new_eq_conditional:NNn \int_if_exist:N \cs_if_exist:N { TF , T , F , p }
+\prg_new_eq_conditional:NNn \int_if_exist:c \cs_if_exist:c { TF , T , F , p }
% \end{macrocode}
% \end{macro}
%
@@ -1288,8 +1302,10 @@
\__prg_compare_error:
}
\cs_new:Npn \__prg_compare_error:Nw
- #1#2 \prg_return_true: \else: \prg_return_false: \fi:
+ #1#2 \q_stop
{
+ { }
+ \c_zero \fi:
\__msg_kernel_expandable_error:nnn
{ kernel } { unknown-comparison } {#1}
\prg_return_false:
@@ -1298,9 +1314,11 @@
% \end{macro}
%
% \begin{macro}[pTF, EXP]{\int_compare:n}
-% \begin{macro}[aux, EXP]{\@@_compare_aux:Nw, \@@_compare_aux:NNw}
+% \begin{macro}[aux, EXP]
+% {\@@_compare:w, \@@_compare:Nw, \@@_compare:NNw, \@@_compare:nnN}
% \begin{macro}[aux, EXP]
% {
+% \@@_compare_end_=:NNw,
% \@@_compare_=:NNw,
% \@@_compare_<:NNw,
% \@@_compare_>:NNw,
@@ -1310,67 +1328,122 @@
% \@@_compare_>=:NNw
% }
% Comparison tests using a simple syntax where only one set of braces
-% is required and additional operators such as |!=| and |>=| are
-% supported. We can start evaluating from the left using
-% \cs{@@_eval:w}, and we know that since the relation symbols |<|,
-% |>|, |=| and |!| are not allowed in such expressions, they will
-% terminate the expression. Therefore, we first let \TeX{} evaluate
-% this left hand side of the (in)equality. We also insert at that
-% stage the end of the test: \cs{@@_eval_end:} will end the
-% evaluation of the right-hand side.
+% is required, additional operators such as |!=| and |>=| are
+% supported, and multiple comparisons can be performed at once, for
+% instance |0 < 5 <= 1|. The idea is to loop through the argument,
+% finding one operand at a time, and comparing it to the previous one.
+% The looping auxiliary \cs{@@_compare:Nw} reads one \meta{operand}
+% and one \meta{comparison} symbol, and leaves roughly
+% \begin{quote}
+% \meta{operand} \cs{prg_return_false:} \cs{fi:} \\
+% \cs{reverse_if:N} \cs{if_int_compare:w} \meta{operand} \meta{comparison} \\
+% \cs{@@_compare:Nw}
+% \end{quote}
+% in the input stream. Each call to this auxiliary provides the
+% second operand of the last call's \cs{if_int_compare:w}. If one of
+% the \meta{comparisons} is \texttt{false}, the \texttt{true} branch
+% of the \TeX{} conditional is taken (because of \cs{reverse_if:N}),
+% immediately returning \texttt{false} as the result of the test.
+% There is no \TeX{} conditional waiting the first operand, so we add
+% an \cs{if_false:} and expand by hand with \cs{@@_value:w}, thus
+% skipping \cs{prg_return_false:} on the first iteration.
+%
+% Before starting the loop, the first step is to make sure that there
+% is at least one relation symbol. We first let \TeX{} evaluate this
+% left hand side of the (in)equality using \cs{@@_eval:w}. Since the
+% relation symbols |<|, |>|, |=| and |!| are not allowed in integer
+% expressions, they will terminate it. If the argument contains no
+% relation symbol, \cs{__prg_compare_error:} is expanded,
+% inserting~|=| and itself after an error. In all cases,
+% \cs{@@_compare:w} receives as its argument an integer, a relation
+% symbol, and some more tokens. We then setup the loop, which will be
+% ended by the two odd-looking items |e| and |{=nd_}|, with a trailing
+% \cs{q_stop} used to grab the entire argument when necessary.
% \begin{macrocode}
\prg_new_conditional:Npnn \int_compare:n #1 { p , T , F , TF }
{
- \exp_after:wN \@@_compare_aux:Nw \int_use:N \@@_eval:w #1
- \__prg_compare_error: \@@_eval_end:
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
+ \exp_after:wN \@@_compare:w
+ \int_use:N \@@_eval:w #1 \__prg_compare_error:
+ }
+\cs_new:Npn \@@_compare:w #1 \__prg_compare_error:
+ {
+ \exp_after:wN \if_false: \@@_value:w
+ \@@_compare:Nw #1 e { = nd_ } \q_stop
}
% \end{macrocode}
-% We have just evaluated the left-hand side. To access the relation
-% symbol, we remove the number by applying \cs{@@_to_roman:w}, after
-% making sure that the argument becomes non-positive: its roman
-% numeral representation is then empty. The \cs{@@_compare_aux:NNw}
-% auxiliary then probes the first two tokens to determine the relation
-% symbol, building a control sequence from it. All the extended forms
-% have an extra |=| hence the test for that as a second token. If the
-% relation symbol is unknown, then the control sequence is turned by
-% \TeX{} into \cs{scan_stop:}, and \cs{__prg_compare_error:Nw}
-% raises an error.
+% The goal here is to find an \meta{operand} and a \meta{comparison}.
+% The \meta{operand} is already evaluated, but we cannot yet grab it
+% as an argument. To access the following relation symbol, we remove
+% the number by applying \cs{@@_to_roman:w}, after making sure that
+% the argument becomes non-positive: its roman numeral representation
+% is then empty. Then probe the first two tokens with
+% \cs{@@_compare:NNw} to determine the relation symbol, building a
+% control sequence from it. All the extended forms have an extra |=|
+% hence the test for that as a second token. If the relation symbol
+% is unknown, then the control sequence is turned by \TeX{} into
+% \cs{scan_stop:}, ignored thanks to \tn{unexpanded}, and
+% \cs{__prg_compare_error:Nw} raises an error.
% \begin{macrocode}
-\cs_new:Npn \@@_compare_aux:Nw #1#2 \__prg_compare_error:
+\cs_new:Npn \@@_compare:Nw #1#2 \q_stop
{
- \exp_after:wN \@@_compare_aux:NNw
- \@@_to_roman:w - 0 #2 ?? \q_mark
- #1#2
+ \exp_after:wN \@@_compare:NNw
+ \@@_to_roman:w - 0 #2 \q_mark
+ #1#2 \q_stop
}
-\cs_new:Npn \@@_compare_aux:NNw #1#2#3 \q_mark
+\cs_new:Npn \@@_compare:NNw #1#2#3 \q_mark
{
+ \etex_unexpanded:D
\use:c { @@_compare_ #1 \if_meaning:w = #2 = \fi: :NNw }
\__prg_compare_error:Nw #1
}
% \end{macrocode}
+% When the last \meta{operand} is seen, \cs{@@_compare:NNw} receives
+% |e| and |=nd_| as arguments, hence calling
+% \cs{@@_compare_end_=:NNw} to end the loop: return the result of the
+% last comparison (involving the operand that we just found). When a
+% normal relation is found, the appropriate auxiliary calls
+% \cs{@@_compare:nnN} where |#1| is \cs{if_int_compare:w} or
+% \cs{reverse_if:N} \cs{if_int_compare:w}, |#2| is the \meta{operand},
+% and |#3| is one of |<|, |=|, or~|>|. As announced earlier, we leave
+% the \meta{operand} for the previous conditional. If this
+% conditional is true the result of the test is known, so we remove
+% all tokens and return \texttt{false}. Otherwise, we apply the
+% conditional |#1| to the \meta{operand} |#2| and the comparison |#3|,
+% and call \cs{@@_compare:Nw} to look for additional operands, after
+% evaluating the following expression.
+% \begin{macrocode}
+\cs_new:cpn { @@_compare_end_=:NNw } #1#2#3 e #4 \q_stop
+ {
+ {#3} \exp_stop_f:
+ \prg_return_false: \else: \prg_return_true: \fi:
+ }
+\cs_new:Npn \@@_compare:nnN #1#2#3
+ {
+ {#2} \exp_stop_f:
+ \prg_return_false: \exp_after:wN \use_none_delimit_by_q_stop:w
+ \fi:
+ #1 #2 #3 \exp_after:wN \@@_compare:Nw \@@_value:w \@@_eval:w
+ }
+% \end{macrocode}
% The actual comparisons are then simple function calls, using the
% relation as delimiter for a delimited argument and discarding
% \cs{__prg_compare_error:Nw} \meta{token} responsible for error
% detection.
% \begin{macrocode}
\cs_new:cpn { @@_compare_=:NNw } #1#2#3 =
- { \if_int_compare:w #3 = \@@_eval:w }
+ { \@@_compare:nnN { \reverse_if:N \if_int_compare:w } {#3} = }
\cs_new:cpn { @@_compare_<:NNw } #1#2#3 <
- { \if_int_compare:w #3 < \@@_eval:w }
+ { \@@_compare:nnN { \reverse_if:N \if_int_compare:w } {#3} < }
\cs_new:cpn { @@_compare_>:NNw } #1#2#3 >
- { \if_int_compare:w #3 > \@@_eval:w }
+ { \@@_compare:nnN { \reverse_if:N \if_int_compare:w } {#3} > }
\cs_new:cpn { @@_compare_==:NNw } #1#2#3 ==
- { \if_int_compare:w #3 = \@@_eval:w }
+ { \@@_compare:nnN { \reverse_if:N \if_int_compare:w } {#3} = }
\cs_new:cpn { @@_compare_!=:NNw } #1#2#3 !=
- { \reverse_if:N \if_int_compare:w #3 = \@@_eval:w }
+ { \@@_compare:nnN { \if_int_compare:w } {#3} = }
\cs_new:cpn { @@_compare_<=:NNw } #1#2#3 <=
- { \reverse_if:N \if_int_compare:w #3 > \@@_eval:w }
+ { \@@_compare:nnN { \if_int_compare:w } {#3} > }
\cs_new:cpn { @@_compare_>=:NNw } #1#2#3 >=
- { \reverse_if:N \if_int_compare:w #3 < \@@_eval:w }
+ { \@@_compare:nnN { \if_int_compare:w } {#3} < }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2335,29 +2408,37 @@
% \begin{macro}{\if_num:w}
% Deprecated 2012-05-30 for removal after 2012-11-30.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \if_num:w \if_int_compare:w
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_tmpc_int}
% Deprecated 2012-07-04 for removal after 2012-12-31.
% \begin{macrocode}
+%<*deprecated>
\int_new:N \l_tmpc_int
+%</deprecated>
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\int_eval:w, \int_eval_end:}
% Deprecated 2012-07-13 for removal after 2012-12-31.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \int_eval:w \@@_eval:w
\cs_new_eq:NN \int_eval_end: \@@_eval_end:
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\int_value:w}
% Deprecated 2012-07-14 for removal after 2012-12-31.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \int_value:w \@@_value:w
+%</deprecated>
% \end{macrocode}
% \end{macro}
%