diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3int.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3int.dtx | 208 |
1 files changed, 139 insertions, 69 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index db696612204..f0e0cca5938 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -7,7 +7,7 @@ % 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 +% https://www.latex-project.org/lppl.txt % % This file is part of the "l3kernel bundle" (The Work in LPPL) % and all files in that bundle must be distributed together. @@ -21,7 +21,7 @@ % for those people who are interested. % %<*driver> -\documentclass[full]{l3doc} +\documentclass[full,kernel]{l3doc} \begin{document} \DocInput{\jobname.dtx} \end{document} @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/11/14} +% \date{Released 2017/12/05} % % \maketitle % @@ -900,31 +900,46 @@ % % \section{Internal functions} % -% \begin{function}[EXP]{\__int_to_roman:w} +% \begin{function}[EXP]{\__int_value:w} % \begin{syntax} -% \cs{__int_to_roman:w} \meta{integer} \meta{space} \textit{or} \meta{non-expandable token} +% \cs{__int_value:w} \meta{integer} +% \cs{__int_value:w} \meta{integer denotation} \meta{optional space} % \end{syntax} -% Converts \meta{integer} to it lower case Roman representation. Expansion -% ends when a space or non-expandable token is found. -% Note that this function produces a string of letters with category code -% $12$ and that protected functions \emph{are} expanded by this -% process. Negative \meta{integer} values result in no output, although -% the function does not terminate expansion until a suitable endpoint -% is found in the same way as for positive numbers. +% Expands the following tokens until an \meta{integer} is formed, and +% leaves a normalized form (no leading sign except for negative +% numbers, no leading digit~|0| except for zero) in the input stream +% as category code $12$ (other) characters. The \meta{integer} can +% consist of any number of signs (with intervening spaces) followed +% by +% \begin{itemize} +% \item an integer variable (in fact, any \TeX{} register except +% \tn{toks}) or +% \item \cs{__int_eval:w} \meta{intexpr} \cs{__int_eval_end:} (or +% another \eTeX{} expression) or +% \item explicit digits (or by |'|\meta{octal digits} or |"|\meta{hexadecimal digits} or |`|\meta{character} +% \end{itemize} +% In this last case expansion stops once a non-digit is found; if that is a space it is removed as in \texttt{f}-expansion. +% Note that protected functions \emph{are} expanded by this process % \begin{texnote} -% This is the \TeX{} primitive \tn{romannumeral} renamed. +% This is the \TeX{} primitive \tn{number}. % \end{texnote} % \end{function} % -% \begin{function}[EXP]{\__int_value:w} +% \begin{function}[EXP]{\__int_to_roman:w} % \begin{syntax} -% \cs{__int_value:w} \meta{integer} -% \cs{__int_value:w} \meta{tokens} \meta{optional space} +% \cs{__int_to_roman:w} \meta{integer} +% \cs{__int_to_roman:w} \meta{integer denotation} \meta{optional space} % \end{syntax} -% Expands \meta{tokens} until an \meta{integer} is formed. One space may be -% gobbled in the process. +% Converts an \meta{integer} to lower case Roman representation. The +% \meta{integer} is found as in \cs{__int_value:w} by expanding what +% follows exhaustively. One (optional) space is lost if the +% \meta{integer} is given by explicit digits. Note that this function +% produces a string of letters with category code~$12$. Negative +% \meta{integer} values result in no output, although the function +% does not terminate expansion until a suitable endpoint is found in +% the same way as for positive numbers. % \begin{texnote} -% This is the \TeX{} primitive \tn{number}. +% This is the \TeX{} primitive \tn{romannumeral} renamed. % \end{texnote} % \end{function} % @@ -943,6 +958,16 @@ % \end{texnote} % \end{function} % +% \begin{function}[EXP]{\__int_eval:n} +% \begin{syntax} +% \cs{__int_eval:n} \Arg{intexpr} +% \end{syntax} +% By default this expands to \cs{__int_eval:w} \meta{intexpr} +% \cs{__int_eval_end:} but when debugging is enabled this expands to a +% more complicated construction that evaluates \meta{intexpr} with +% parentheses and within a brace group to detect early termination. +% \end{function} +% % \begin{function}{\__prg_compare_error:, \__prg_compare_error:Nw} % \begin{syntax} % \cs{__prg_compare_error:} @@ -1017,12 +1042,23 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_eval:n} +% Only differ from \cs{int_eval:n} by the absence of \cs{@@_value:w}, +% so as to produce an internal integer rather than expanding into +% characters. This is for use in other modules. +% \begin{macrocode} +\__debug_patch_args:nNNpn + { { \__debug_chk_expr:nNnN {#1} \@@_eval:w { } \@@_eval:n } } +\cs_new:Npn \@@_eval:n #1 { \@@_eval:w #1 \@@_eval_end: } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[EXP]{\int_abs:n} -% \begin{macro}[aux, EXP]{\@@_abs:N} +% \begin{macro}[EXP]{\@@_abs:N} % \UnitTested % \begin{macro}[EXP]{\int_max:nn} % \begin{macro}[EXP]{\int_min:nn} -% \begin{macro}[aux, EXP]{\@@_maxmin:wwN} +% \begin{macro}[EXP]{\@@_maxmin:wwN} % \UnitTested % \UnitTested % Functions for $\min$, $\max$, and absolute value with only one @@ -1086,8 +1122,8 @@ % \UnitTested % \begin{macro}[EXP]{\int_mod:nn} % \UnitTested -% \begin{macro}[aux, EXP]{\@@_div_truncate:NwNw} -% \begin{macro}[aux, EXP]{\@@_mod:ww} +% \begin{macro}[EXP]{\@@_div_truncate:NwNw} +% \begin{macro}[EXP]{\@@_mod:ww} % As \cs{@@_eval:w} rounds the result of a division we also provide a % version that truncates the result. We use an auxiliary to make sure % numerator and denominator are only evaluated once: this comes in @@ -1178,35 +1214,39 @@ % \end{macro} % % \begin{macro}{\int_const:Nn, \int_const:cn} -% \begin{macro}[aux]{\@@_constdef:Nw} +% \begin{macro}{\@@_constdef:Nw} % \begin{variable}{\c__max_constdef_int} % \UnitTested % As stated, most constants can be defined as \tn{chardef} or % \tn{mathchardef} but that's engine dependent. As a result, there is some % set up code to determine what can be done. No full engine testing just yet % so everything is a little awkward. +% We cannot use \cs{int_gset:Nn} because (when |check-declarations| is +% enabled) this runs some checks that constants would fail. % \begin{macrocode} -\__debug_patch_args:nNNpn +\__debug_patch_args:nnnNNpn + { \__debug_chk_var_scope:NN c #1 } + { } { {#1} { \__debug_chk_expr:nNnN {#2} \@@_eval:w { } \int_const:Nn } } \cs_new_protected:Npn \int_const:Nn #1#2 { \int_compare:nNnTF {#2} < \c_zero { \int_new:N #1 - \int_gset:Nn #1 {#2} + \tex_global:D } { \int_compare:nNnTF {#2} > \c__max_constdef_int { \int_new:N #1 - \int_gset:Nn #1 {#2} + \tex_global:D } { \__chk_if_free_cs:N #1 - \tex_global:D \@@_constdef:Nw #1 = - \@@_eval:w #2 \@@_eval_end: + \tex_global:D \@@_constdef:Nw } } + #1 = \@@_eval:w #2 \@@_eval_end: } \cs_generate_variant:Nn \int_const:Nn { c } \if_int_odd:w 0 @@ -1233,7 +1273,9 @@ % \UnitTested % Functions that reset an \meta{integer} register to zero. % \begin{macrocode} +\__debug_patch:nnNNpn { \__debug_chk_var_local:N #1 } { } \cs_new_protected:Npn \int_zero:N #1 { #1 = \c_zero } +\__debug_patch:nnNNpn { \__debug_chk_var_global:N #1 } { } \cs_new_protected:Npn \int_gzero:N #1 { \tex_global:D #1 = \c_zero } \cs_generate_variant:Nn \int_zero:N { c } \cs_generate_variant:Nn \int_gzero:N { c } @@ -1260,11 +1302,14 @@ % {\int_gset_eq:NN, \int_gset_eq:cN, \int_gset_eq:Nc, \int_gset_eq:cc} % \UnitTested % Setting equal means using one integer inside the set function of -% another. +% another. Check that assigned integer is local/global. No need to +% check that the other one is defined as \TeX{} does it for us. % \begin{macrocode} +\__debug_patch:nnNNpn { \__debug_chk_var_local:N #1 } { } \cs_new_protected:Npn \int_set_eq:NN #1#2 { #1 = #2 } \cs_generate_variant:Nn \int_set_eq:NN { c } \cs_generate_variant:Nn \int_set_eq:NN { Nc , cc } +\__debug_patch:nnNNpn { \__debug_chk_var_global:N #1 } { } \cs_new_protected:Npn \int_gset_eq:NN #1#2 { \tex_global:D #1 = #2 } \cs_generate_variant:Nn \int_gset_eq:NN { c } \cs_generate_variant:Nn \int_gset_eq:NN { Nc , cc } @@ -1284,6 +1329,22 @@ % % \subsection{Setting and incrementing integers} % +% Several functions here have a signature |:Nn| and are such that when +% debugging, the first argument should be checked to be a local/global +% variable and the second should be wrapped in code for an expression. +% The temporary function \cs{@@_tmp:w} finds the name |#3| of the +% function being redefined and writes the appropriate patch. +% \begin{macrocode} +\cs_set_protected:Npn \@@_tmp:w #1#2#3 + { + \__debug_patch_args:nnnNNpn + { #1 ##1 } + { } + { {##1} { \__debug_chk_expr:nNnN {##2} \@@_eval:w { } #3 } } + #2 #3 + } +% \end{macrocode} +% % \begin{macro}{\int_add:Nn, \int_add:cn} % \UnitTested % \begin{macro}{\int_gadd:Nn, \int_gadd:cn} @@ -1292,20 +1353,23 @@ % \UnitTested % \begin{macro}{\int_gsub:Nn, \int_gsub:cn} % \UnitTested -% Adding and subtracting to and from a counter \ldots +% Adding and subtracting to and from a counter. For each function, +% the debugging code produced by \cs{@@_tmp:w} checks that the +% assigned variable is correctly local/global and wraps the +% expression in some checking code. % \begin{macrocode} -\__debug_patch_args:nNNpn - { {#1} { \__debug_chk_expr:nNnN {#2} \@@_eval:w { } \int_add:Nn } } +\@@_tmp:w \__debug_chk_var_local:N \cs_new_protected:Npn \int_add:Nn #1#2 { \tex_advance:D #1 by \@@_eval:w #2 \@@_eval_end: } -\__debug_patch_args:nNNpn - { {#1} { \__debug_chk_expr:nNnN {#2} \@@_eval:w { } \int_sub:Nn } } +\@@_tmp:w \__debug_chk_var_local:N \cs_new_protected:Npn \int_sub:Nn #1#2 { \tex_advance:D #1 by - \@@_eval:w #2 \@@_eval_end: } -\cs_new_protected:Npn \int_gadd:Nn - { \tex_global:D \int_add:Nn } -\cs_new_protected:Npn \int_gsub:Nn - { \tex_global:D \int_sub:Nn } +\@@_tmp:w \__debug_chk_var_global:N +\cs_new_protected:Npn \int_gadd:Nn #1#2 + { \tex_global:D \tex_advance:D #1 by \@@_eval:w #2 \@@_eval_end: } +\@@_tmp:w \__debug_chk_var_global:N +\cs_new_protected:Npn \int_gsub:Nn #1#2 + { \tex_global:D \tex_advance:D #1 by - \@@_eval:w #2 \@@_eval_end: } \cs_generate_variant:Nn \int_add:Nn { c } \cs_generate_variant:Nn \int_gadd:Nn { c } \cs_generate_variant:Nn \int_sub:Nn { c } @@ -1327,14 +1391,18 @@ % Incrementing and decrementing of integer registers is done with % the following functions. % \begin{macrocode} +\__debug_patch:nnNNpn { \__debug_chk_var_local:N #1 } { } \cs_new_protected:Npn \int_incr:N #1 { \tex_advance:D #1 \c_one } +\__debug_patch:nnNNpn { \__debug_chk_var_local:N #1 } { } \cs_new_protected:Npn \int_decr:N #1 { \tex_advance:D #1 - \c_one } -\cs_new_protected:Npn \int_gincr:N - { \tex_global:D \int_incr:N } -\cs_new_protected:Npn \int_gdecr:N - { \tex_global:D \int_decr:N } +\__debug_patch:nnNNpn { \__debug_chk_var_global:N #1 } { } +\cs_new_protected:Npn \int_gincr:N #1 + { \tex_global:D \tex_advance:D #1 \c_one } +\__debug_patch:nnNNpn { \__debug_chk_var_global:N #1 } { } +\cs_new_protected:Npn \int_gdecr:N #1 + { \tex_global:D \tex_advance:D #1 - \c_one } \cs_generate_variant:Nn \int_incr:N { c } \cs_generate_variant:Nn \int_decr:N { c } \cs_generate_variant:Nn \int_gincr:N { c } @@ -1350,14 +1418,16 @@ % \begin{macro}{\int_gset:Nn, \int_gset:cn} % \UnitTested % As integers are register-based \TeX{} issues an error -% if they are not defined. Thus there is no need for the checking -% code seen with token list variables. +% if they are not defined. Thus there is no need to check their +% existence as for token list variables. However, the code that +% checks whether the assignment is local or global is still needed. % \begin{macrocode} -\__debug_patch_args:nNNpn - { {#1} { \__debug_chk_expr:nNnN {#2} \@@_eval:w { } \int_set:Nn } } +\@@_tmp:w \__debug_chk_var_local:N \cs_new_protected:Npn \int_set:Nn #1#2 { #1 ~ \@@_eval:w #2 \@@_eval_end: } -\cs_new_protected:Npn \int_gset:Nn { \tex_global:D \int_set:Nn } +\@@_tmp:w \__debug_chk_var_global:N +\cs_new_protected:Npn \int_gset:Nn #1#2 + { \tex_global:D #1 ~ \@@_eval:w #2 \@@_eval_end: } \cs_generate_variant:Nn \int_set:Nn { c } \cs_generate_variant:Nn \int_gset:Nn { c } % \end{macrocode} @@ -1381,7 +1451,7 @@ % % \subsection{Integer expression conditionals} % -% \begin{macro}[int, EXP]{\__prg_compare_error:, \__prg_compare_error:Nw} +% \begin{macro}[EXP]{\__prg_compare_error:, \__prg_compare_error:Nw} % Those functions are used for comparison tests which use a simple % syntax where only one set of braces is required and additional % operators such as |!=| and |>=| are supported. The tests first @@ -1414,9 +1484,9 @@ % \end{macro} % % \begin{macro}[pTF, EXP]{\int_compare:n} -% \begin{macro}[aux, EXP] +% \begin{macro}[EXP] % {\@@_compare:w, \@@_compare:Nw, \@@_compare:NNw, \@@_compare:nnN} -% \begin{macro}[aux, EXP] +% \begin{macro}[EXP] % { % \@@_compare_end_=:NNw, % \@@_compare_=:NNw, @@ -1577,8 +1647,8 @@ % \end{macro} % % \begin{macro}[EXP, noTF]{\int_case:nn} -% \begin{macro}[aux]{\@@_case:nnTF} -% \begin{macro}[aux]{\@@_case:nw, \@@_case_end:nw} +% \begin{macro}{\@@_case:nnTF} +% \begin{macro}{\@@_case:nw, \@@_case_end:nw} % For integer cases, the first task to fully expand the check % condition. The over all idea is then much the same as for % \cs{str_case:nn(TF)} as described in \pkg{l3basics}. @@ -1742,7 +1812,7 @@ % \subsection{Integer step functions} % % \begin{macro}{\int_step_function:nnnN} -% \begin{macro}[aux]{\@@_step:wwwN, \@@_step:NnnnN} +% \begin{macro}{\@@_step:wwwN, \@@_step:NnnnN} % Before all else, evaluate the initial value, step, and final value. % Repeating a function by steps first needs a check on the direction % of the steps. After that, do the function for the start value then @@ -1793,7 +1863,7 @@ % \begin{macro}{\int_step_inline:nnnn} % \begin{macro}{\int_step_variable:nnnNn} % \UnitTested -% \begin{macro}[aux]{\@@_step:NNnnnn} +% \begin{macro}{\@@_step:NNnnnn} % The approach here is to build a function, with a global integer % required to make the nesting safe (as seen in other in line % functions), and map that function using \cs{int_step_function:nnnN}. @@ -1845,7 +1915,7 @@ % % \begin{macro}{\int_to_symbols:nnn} % \UnitTested -% \begin{macro}[aux]{\@@_to_symbols:nnnn} +% \begin{macro}{\@@_to_symbols:nnnn} % For conversion of integers to arbitrary symbols the method is in % general as follows. The input number (|#1|) is compared to the total % number of symbols available at each place (|#2|). If the input is larger @@ -1954,9 +2024,9 @@ % % \begin{macro}{\int_to_base:nn, \int_to_Base:nn} % \UnitTested -% \begin{macro}[aux]{\@@_to_base:nn, \@@_to_Base:nn, +% \begin{macro}{\@@_to_base:nn, \@@_to_Base:nn, % \@@_to_base:nnN, \@@_to_Base:nnN, \@@_to_base:nnnN, \@@_to_Base:nnnN} -% \begin{macro}[aux]{\@@_to_letter:n, \@@_to_Letter:n} +% \begin{macro}{\@@_to_letter:n, \@@_to_Letter:n} % \UnitTested % Converting from base ten (|#1|) to a second base (|#2|) starts with % computing |#1|: if it is a complicated calculation, we shouldn't @@ -2129,8 +2199,8 @@ % % \begin{macro}{\int_to_roman:n, \int_to_Roman:n} % \UnitTested -% \begin{macro}[aux]{\@@_to_roman:N, \@@_to_roman:N} -% \begin{macro}[aux] +% \begin{macro}{\@@_to_roman:N, \@@_to_roman:N} +% \begin{macro} % { % \@@_to_roman_i:w, \@@_to_roman_v:w, \@@_to_roman_x:w, % \@@_to_roman_l:w, \@@_to_roman_c:w, \@@_to_roman_d:w, @@ -2189,7 +2259,7 @@ % % \subsection{Converting from other formats to integers} % -% \begin{macro}[aux,rEXP]{\@@_pass_signs:wn, \@@_pass_signs_end:wn} +% \begin{macro}[rEXP]{\@@_pass_signs:wn, \@@_pass_signs_end:wn} % Called as \cs{@@_pass_signs:wn} \meta{signs and digits} \cs{q_stop} % \Arg{code}, this function leaves in the input stream any sign it % finds, then inserts the \meta{code} before the first non-sign token @@ -2212,7 +2282,7 @@ % % \begin{macro}{\int_from_alph:n} % \UnitTested -% \begin{macro}[aux]{\@@_from_alph:nN, \@@_from_alph:N} +% \begin{macro}{\@@_from_alph:nN, \@@_from_alph:N} % First take care of signs then loop through the input using the % \texttt{recursion} quarks. The \cs{@@_from_alph:nN} auxiliary % collects in its first argument the value obtained so far, and the @@ -2242,7 +2312,7 @@ % % \begin{macro}{\int_from_base:nn} % \UnitTested -% \begin{macro}[aux]{\@@_from_base:nnN, \@@_from_base:N} +% \begin{macro}{\@@_from_base:nnN, \@@_from_base:N} % Leave the signs into the integer expression, then loop through % characters, collecting the value found so far in the first argument % of \cs{@@_from_base:nnN}. To convert a single character, @@ -2323,8 +2393,8 @@ % \begin{macro}{\int_from_roman:n} % \UnitTested % \TestMissing{boundary cases / wrong input?} -% \begin{macro}[aux]{\@@_from_roman:NN} -% \begin{macro}[aux]{\@@_from_roman_error:w} +% \begin{macro}{\@@_from_roman:NN} +% \begin{macro}{\@@_from_roman_error:w} % The method here is to iterate through the input, finding the % appropriate value for each letter and building up a sum. This is % then evaluated by \TeX{}. If any unknown letter is found, skip to @@ -2376,7 +2446,7 @@ % % \begin{macro}{\int_show:N, \int_show:c} % \UnitTested -% \begin{macro}[aux]{\@@_show:nN} +% \begin{macro}{\@@_show:nN} % Diagnostics. % \begin{macrocode} \cs_new_eq:NN \int_show:N \__kernel_register_show:N @@ -2391,7 +2461,7 @@ % expressions: this gives a more unified output. % \begin{macrocode} \cs_new_protected:Npn \int_show:n - { \__msg_show_wrap:Nn \int_eval:n } + { \msg_show_eval:Nn \int_eval:n } % \end{macrocode} % \end{macro} % @@ -2404,10 +2474,10 @@ % \end{macro} % % \begin{macro}{\int_log:n} -% Redirect output of \cs{int_show:n} to the log. +% Similar to \cs{int_show:n}. % \begin{macrocode} \cs_new_protected:Npn \int_log:n - { \__msg_log_next: \int_show:n } + { \msg_log_eval:Nn \int_eval:n } % \end{macrocode} % \end{macro} % |