diff options
90 files changed, 1478 insertions, 598 deletions
diff --git a/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md b/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md index a889c04c8c4..53a9a1ae39e 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md +++ b/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md @@ -7,6 +7,15 @@ this project uses date-based 'snapshot' version identifiers. ## [Unreleased] +## [2021-11-22] + +### Added +- Support for legacy `if` switches in `l3keys` + +### Changed +- Documentation improvements +- Implementation of `intarray` data tyep with LuaTeX + ## [2021-11-12] ### Fixed @@ -984,7 +993,8 @@ this project uses date-based 'snapshot' version identifiers. - Step functions have been added for dim variables, e.g. `\dim_step_inline:nnnn` -[Unreleased]: https://github.com/latex3/latex3/compare/2021-11-12...HEAD +[Unreleased]: https://github.com/latex3/latex3/compare/2021-11-22...HEAD +[2021-11-22]: https://github.com/latex3/latex3/compare/2021-11-12...2021-11-22 [2021-11-12]: https://github.com/latex3/latex3/compare/2021-10-18...2021-11-12 [2021-10-18]: https://github.com/latex3/latex3/compare/2021-10-17...2021-10-18 [2021-10-17]: https://github.com/latex3/latex3/compare/2021-10-12...2021-10-17 diff --git a/Master/texmf-dist/doc/latex/l3kernel/README.md b/Master/texmf-dist/doc/latex/l3kernel/README.md index 027c1c96363..77d5204b401 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/README.md +++ b/Master/texmf-dist/doc/latex/l3kernel/README.md @@ -1,7 +1,7 @@ LaTeX3 Programming Conventions ============================== -Release 2021-11-12 +Release 2021-11-22 Overview -------- diff --git a/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf b/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf Binary files differindex 92b32349e67..d474bf6c3ff 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf b/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf Binary files differindex eee082fa60d..e478d744a76 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/interface3.tex b/Master/texmf-dist/doc/latex/l3kernel/interface3.tex index f64cd3abbbb..c1f20d955f9 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/interface3.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/interface3.tex @@ -54,7 +54,7 @@ for those people who are interested. {latex-team@latex-project.org}% }% } -\date{Released 2021-11-12} +\date{Released 2021-11-22} \pagenumbering{roman} \maketitle diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf Binary files differindex 2a9399305e9..f49d2374244 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf Binary files differindex e1c52b5cc37..befc45d0efc 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf Binary files differindex 1b6dc0fbe33..67f3c2859fd 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf Binary files differindex 28c71948587..058c3263aec 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf Binary files differindex a52b994d207..d80bb50b83e 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf Binary files differindex dcaa766fd78..ac9eda59d77 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf Binary files differindex 5110b7df1a4..c39fc69f016 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf Binary files differindex 7f5bd08342f..27ec18702f4 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf Binary files differindex 57e35fbd7cf..1772b262835 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf Binary files differindex 28c0de51a54..ede1cc84f3c 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf Binary files differindex 571f491b28f..bd439b80504 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf Binary files differindex d0239237a27..b30bfd1a14a 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf Binary files differindex e5cc04782c8..bc4097ea8e3 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf Binary files differindex b6195360165..306dab5abf8 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf Binary files differindex 06fe96aef03..3a346360374 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf Binary files differindex e8ec9a0b73d..383e2b5f339 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex index 07f81058249..5c36e4d6475 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex @@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2021-11-12} +\date{Released 2021-11-22} \begin{document} diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf Binary files differindex c0043ad4b1a..cc2d9146596 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex index 035b9117fc0..50d639996a5 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex @@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2021-11-12} +\date{Released 2021-11-22} \newcommand{\TF}{\textit{(TF)}} diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf Binary files differindex 33d947829f0..f3025a3d5f1 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex index 88221a01dab..ef67f022139 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex @@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2021-11-12} +\date{Released 2021-11-22} \newcommand{\TF}{\textit{(TF)}} diff --git a/Master/texmf-dist/doc/latex/l3kernel/source3.pdf b/Master/texmf-dist/doc/latex/l3kernel/source3.pdf Binary files differindex 8d919c1a263..79f625cf942 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/source3.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/source3.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/source3.tex b/Master/texmf-dist/doc/latex/l3kernel/source3.tex index 56c5f487d7a..99f8aca9d8c 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/source3.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/source3.tex @@ -53,7 +53,7 @@ for those people who are interested. {latex-team@latex-project.org}% }% } -\date{Released 2021-11-12} +\date{Released 2021-11-22} \pagenumbering{roman} \maketitle diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index 01a2dbf0fb4..21b528db1e3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -24,7 +24,7 @@ % %<*driver|generic|package|2ekernel> %</driver|generic|package|2ekernel> -\def\ExplFileDate{2021-11-12}% +\def\ExplFileDate{2021-11-22}% %<*driver> \documentclass[full]{l3doc} \usepackage{graphicx} @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3.ins b/Master/texmf-dist/source/latex/l3kernel/l3.ins index 34a46aaed5e..265fde8ac9e 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3.ins +++ b/Master/texmf-dist/source/latex/l3kernel/l3.ins @@ -78,7 +78,7 @@ and all files in that bundle must be distributed together. \from{l3file.dtx} {package} \from{l3skip.dtx} {package} \from{l3keys.dtx} {package} - \from{l3intarray.dtx} {package} + \from{l3intarray.dtx} {package,tex} \from{l3fp.dtx} {package} \from{l3fp-aux.dtx} {package} \from{l3fp-traps.dtx} {package} @@ -171,6 +171,7 @@ and all files in that bundle must be distributed together. \from{l3names.dtx}{package,lua} \from{l3sys.dtx}{package,lua} \from{l3token.dtx}{package,lua} + \from{l3intarray.dtx}{package,lua} }} \endbatchfile diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx index 5b810b393d6..9b2e96aa901 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -2052,7 +2052,7 @@ % \@@_generate_T_form:wNNnnnnN, % \@@_generate_F_form:wNNnnnnN % } -% \begin{macro}[EXP]{\@@_p_true:w} +% \begin{macro}[EXP]{\@@_p_true:w, \@@_T_true:w, \@@_F_true:w, \@@_TF_true:w} % How to generate the various forms. Those functions take the % following arguments: 1: junk, 2: \cs{cs_set:Npn} or similar, 3: |p| % (for protected conditionals) or |e|, 4: function name, 5: signature, @@ -2066,11 +2066,11 @@ % expandable tests, we check for that by making sure that the second % argument is empty. For \enquote{fast} conditionals, |#7| has an % extra \cs[no-index]{if_\ldots{}}. To optimize a bit further we -% could replace \cs{exp_after:wN} \cs{use_ii:nnn} and similar by a -% single macro similar to \cs{@@_p_true:w}. The drawback is that if -% the |T| or |F| arguments are actually missing, the recovery from -% the runaway argument would not insert \cs{fi:} back, messing up -% nesting of conditionals. +% don't use \cs{exp_after:wN} \cs{use_ii:nnn} and similar but instead use +% \cs{@@_TF_true:w} and similar to swap out the macro after \cs{fi:}. It would +% be a tiny bit faster if we directly grabbed the |T| and |F| arguments there, +% but if those are actually missing, the recovery from the runaway argument +% would not insert \cs{fi:} back, messing up nesting of conditionals. % \begin{macrocode} \cs_set_protected:Npn \@@_generate_p_form:wNNnnnnN #1 \s_@@_stop #2#3#4#5#6#7#8 diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index 7cf40957e74..5303ec59431 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -189,18 +189,12 @@ % \end{macrocode} % For \LuaTeX{} we make sure the basic support is loaded: % this is only necessary in plain. -% -% Additionally we just ensure that \TeX{} has seen the csnames \cs{prg_return_true:} -% and \cs{prg_return_false:} before the Lua code builds these tokens. % \begin{macrocode} \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname newcatcodetable\endcsname\relax \input{ltluatex}% \fi - \begingroup\edef\ignored{% - \expandafter\noexpand\csname prg_return_true:\endcsname - \expandafter\noexpand\csname prg_return_false:\endcsname - }\endgroup + \ifdefined\newluabytecode\newluabytecode\@expl@luadata@bytecode\fi \directlua{require("expl3")}% % \end{macrocode} % As the user might be making a custom format, no assumption is made about diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx index c71f489712f..d0d647be84a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index ebfb71b81e7..a9c9dee7f09 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx b/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx index 4669bcc875a..b8202b75348 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index 718c75d07a0..a8231410547 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx index ca112398ab8..56c296c1759 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx index b3f10132d3a..f77304a0a5c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx b/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx index 39c210f013f..e9bf590f29e 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx index c4ac6b343f6..903c8280bc4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx index 3926f4298bb..dfbb2abbf30 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx @@ -79,7 +79,7 @@ and all files in that bundle must be distributed together. % % \title{The \cls{l3doc} class} % \author{\Team} -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % \maketitle % \tableofcontents % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx index 56d569dc863..1f4c4061daf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx index ff7dafb0948..12e55bfc509 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index 59322d5c92e..07dffc2904b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx index 86e6f65a9bd..668cded03b5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx index 18ed230b7f8..4f8573e2661 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx index edae5678c28..9df90f504b0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx index 759a6e1c928..dd34a0e6d71 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx index 0ae265ad823..db755b39477 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx index 89769f7ad82..d28f28258a0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx index ee1a7dfbede..7ce778ccffa 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx index 64f25bcd703..5145278e6b6 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx index e2648f74fac..cc255e06f84 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx index 2edef81d72e..a25e8fbfee3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx index f261a87690f..5bcd63e93a7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx index 41736a6c92a..9a66600ace7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx index 4ae3c33f4b7..7f32c26d5e2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx index ed3468a0766..d5be93e21b7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx @@ -49,7 +49,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx index 5afd5f774a3..f03c04bb4eb 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index 749de68557b..fedb4617f9b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -59,6 +59,63 @@ % % \section{Integer expressions} % +% Throughout this module, (almost) all \texttt{n}-type argument allow +% for an \meta{intexpr} argument with the following syntax. The +% \meta{integer expression} should consist, +% after expansion, of \texttt{+}, \texttt{-}, \texttt{*}, \texttt{/}, +% \texttt{(}, \texttt{)} and of course integer operands. The result +% is calculated by applying standard mathematical rules with the +% following peculiarities: +% \begin{itemize} +% \item \texttt{/} denotes division rounded to the closest integer with +% ties rounded away from zero; +% \item there is an error and the overall expression evaluates to zero +% whenever the absolute value of any intermediate result exceeds +% $2^{31}-1$, except in the case of scaling operations +% $a$\texttt{*}$b$\texttt{/}$c$, for which $a$\texttt{*}$b$ may be +% arbitrarily large (but the operands $a$, $b$, $c$ are still +% constrained to an absolute value at most $2^{31}-1$); +% \item parentheses may not appear after unary \texttt{+} or +% \texttt{-}, namely placing \texttt{+(} or \texttt{-(} at the start +% of an expression or after \texttt{+}, \texttt{-}, \texttt{*}, +% \texttt{/} or~\texttt{(} leads to an error. +% \end{itemize} +% Each integer operand can be either an integer variable (with no need +% for \cs{int_use:N}) or an integer denotation. For example both +% \begin{verbatim} +% \int_show:n { 5 + 4 * 3 - ( 3 + 4 * 5 ) } +% \end{verbatim} +% and +% \begin{verbatim} +% \tl_new:N \l_my_tl +% \tl_set:Nn \l_my_tl { 5 } +% \int_new:N \l_my_int +% \int_set:Nn \l_my_int { 4 } +% \int_show:n { \l_my_tl + \l_my_int * 3 - ( 3 + 4 * 5 ) } +% \end{verbatim} +% show the same result $-6$ because \cs[no-index]{l_my_tl} expands to +% the integer denotation~|5| while the integer variable \cs{l_my_int} +% takes the value~$4$. As the \meta{integer expression} is fully +% expanded from left to right during evaluation, fully expandable and +% restricted-expandable functions can both be used, and \cs{exp_not:n} +% and its variants have no effect while \cs{exp_not:N} may incorrectly +% interrupt the expression. +% \begin{texnote} +% Exactly two expansions are needed to evaluate \cs{int_eval:n}. +% The result is \emph{not} an \meta{internal integer}, and therefore +% should be terminated by a space if used in \cs{int_value:w} or in +% a \TeX{}-style integer assignment. +% +% As all \TeX{} integers, integer operands can also be: +% \tn{value}\Arg{\LaTeXe{} counter}; dimension or skip variables, +% converted to integers in~\texttt{sp}; the character code of some +% character given as \texttt{`}\meta{char} or +% \texttt{`\textbackslash}\meta{char}; octal numbers given as +% \texttt{'} followed by digits from \texttt{0} to \texttt{7}; or +% hexadecimal numbers given as |"| followed by digits and upper case +% letters from \texttt{A} to~\texttt{F}. +% \end{texnote} +% % \begin{function}[EXP]{\int_eval:n} % \begin{syntax} % \cs{int_eval:n} \Arg{integer expression} @@ -67,57 +124,7 @@ % input stream as an integer denotation: for positive results an % explicit sequence of decimal digits not starting with~\texttt{0}, % for negative results \texttt{-}~followed by such a sequence, and -% \texttt{0}~for zero. The \meta{integer expression} should consist, -% after expansion, of \texttt{+}, \texttt{-}, \texttt{*}, \texttt{/}, -% \texttt{(}, \texttt{)} and of course integer operands. The result -% is calculated by applying standard mathematical rules with the -% following peculiarities: -% \begin{itemize} -% \item \texttt{/} denotes division rounded to the closest integer with -% ties rounded away from zero; -% \item there is an error and the overall expression evaluates to zero -% whenever the absolute value of any intermediate result exceeds -% $2^{31}-1$, except in the case of scaling operations -% $a$\texttt{*}$b$\texttt{/}$c$, for which $a$\texttt{*}$b$ may be -% arbitrarily large; -% \item parentheses may not appear after unary \texttt{+} or -% \texttt{-}, namely placing \texttt{+(} or \texttt{-(} at the start -% of an expression or after \texttt{+}, \texttt{-}, \texttt{*}, -% \texttt{/} or~\texttt{(} leads to an error. -% \end{itemize} -% Each integer operand can be either an integer variable (with no need -% for \cs{int_use:N}) or an integer denotation. For example both -% \begin{verbatim} -% \int_eval:n { 5 + 4 * 3 - ( 3 + 4 * 5 ) } -% \end{verbatim} -% and -% \begin{verbatim} -% \tl_new:N \l_my_tl -% \tl_set:Nn \l_my_tl { 5 } -% \int_new:N \l_my_int -% \int_set:Nn \l_my_int { 4 } -% \int_eval:n { \l_my_tl + \l_my_int * 3 - ( 3 + 4 * 5 ) } -% \end{verbatim} -% evaluate to $-6$ because \cs[no-index]{l_my_tl} expands to the -% integer denotation~|5|. As the \meta{integer expression} is fully -% expanded from left to right during evaluation, fully expandable and -% restricted-expandable functions can both be used, and \cs{exp_not:n} -% and its variants have no effect while \cs{exp_not:N} may incorrectly -% interrupt the expression. -% \begin{texnote} -% Exactly two expansions are needed to evaluate \cs{int_eval:n}. -% The result is \emph{not} an \meta{internal integer}, and therefore -% requires suitable termination if used in a \TeX{}-style integer -% assignment. -% -% As all \TeX{} integers, integer operands can also be dimension or -% skip variables, converted to integers in~\texttt{sp}, or octal -% numbers given as \texttt{'} followed by digits other than -% \texttt{8} and \texttt{9}, or hexadecimal numbers given as -% |"| followed by digits or upper case letters from -% \texttt{A} to~\texttt{F}, or the character code of some character -% or one-character control sequence, given as \texttt{`}\meta{char}. -% \end{texnote} +% \texttt{0}~for zero. % \end{function} % % \begin{function}[EXP, added = 2018-03-30]{\int_eval:w} @@ -130,7 +137,8 @@ % token is \cs{scan_stop:} it is removed, otherwise not. Spaces do % \emph{not} terminate the expression. However, spaces terminate % explict integers, and this may terminate the expression: for -% instance, \cs{int_eval:w} \verb*|1 + 1 9| expands to \texttt{29} +% instance, \cs{int_eval:w} \verb*|1 + 1 9| (with explicit space +% tokens inserted using |~| in a code setting) expands to \texttt{29} % since the digit~\texttt{9} is not part of the expression. % \end{function} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx index 3d95e6e04b3..8f0976fb25d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -173,15 +173,15 @@ %<@@=intarray> % \end{macrocode} % -% \subsection{Allocating arrays} +% There are two implementations for this module: One \cs{fontdimen} based one +% for more traditional \TeX\ engines and a Lua based one for engines with Lua support. % -% \begin{macro}{\@@_entry:w, \@@_count:w} -% We use these primitives quite a lot in this module. +% Both versions do not allow negative array sizes. % \begin{macrocode} -\cs_new_eq:NN \@@_entry:w \tex_fontdimen:D -\cs_new_eq:NN \@@_count:w \tex_hyphenchar:D +%<*tex> +\msg_new:nnn { kernel } { negative-array-size } + { Size~of~array~may~not~be~negative:~#1 } % \end{macrocode} -% \end{macro} % % \begin{variable}{\l_@@_loop_int} % A loop index. @@ -190,25 +190,433 @@ % \end{macrocode} % \end{variable} % +% \subsection{Lua implementation} +% First, let's look at the Lua variant: +% +% We select the Lua version if the Lua helpers were defined. This can be detected by +% the presence of \cs{@@_gset_count:Nw}. +% +% \begin{macrocode} +\cs_if_exist:NTF \@@_gset_count:Nw + { +% \end{macrocode} +% +% \subsubsection{Allocating arrays} +% +% \begin{variable}{\g_@@_table_int, \l_@@_bad_index_int} +% Used to differentiate intarrays in Lua and to record an invalid index. +% \begin{macrocode} + \int_new:N \g_@@_table_int + \int_new:N \l_@@_bad_index_int +%</tex> +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@:w} +% Used as marker for intarrays in Lua. Followed by an unbraced number +% identifying the array and a single space. This format is used to make it +% easy to scan from Lua. +% \begin{macrocode} +%<*lua> +luacmd('@@:w', function() + scan_int() + tex.error'LaTeX Error: Isolated intarray ignored' +end, 'protected', 'global') +%</lua> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\intarray_new:Nn, \intarray_new:cn} +% \begin{macro}{\@@_new:N} +% Declare |#1| as a tokenlist with the scanmark and a unique number. +% Pass the array's size to the Lua helper. +% Every \texttt{intarray} must be global; it's enough to run this +% check in \cs{intarray_new:Nn}. +% \begin{macrocode} +%<*tex> + \cs_new_protected:Npn \@@_new:N #1 + { + \__kernel_chk_if_free_cs:N #1 + \int_gincr:N \g_@@_table_int + \cs_gset_nopar:Npx #1 { \@@:w \int_use:N \g_@@_table_int \c_space_tl } + } + \cs_new_protected:Npn \intarray_new:Nn #1#2 + { + \@@_new:N #1 + \@@_gset_count:Nw #1 \int_eval:n {#2} \scan_stop: + \int_compare:nNnT { \intarray_count:N #1 } < 0 + { + \msg_error:nnx { kernel } { negative-array-size } + { \intarray_count:N #1 } + } + } + \cs_generate_variant:Nn \intarray_new:Nn { c } +%</tex> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% Before we get to the first command implmented in Lua, we first need some +% definitions. Since \texttt{token.create} only works correctly if \TeX{} +% has seen the tokens before, we first run a short \TeX{} sequence to ensure +% that all relevant control sequences are known. +% \begin{macrocode} +%<*lua> + +local scan_token = token.scan_token +local put_next = token.put_next +local intarray_marker = token_create_safe'@@:w' +local use_none = token_create_safe'use_none:n' +local use_i = token_create_safe'use:n' +local expand_after_scan_stop = {token_create_safe'exp_after:wN', + token_create_safe'scan_stop:'} +local comma = token_create(string.byte',') +% \end{macrocode} +% +% \begin{macro}{@@_table} +% Internal helper to scan an intarray token, extract the associated +% Lua table and return an error if the input is invalid. +% +% \begin{macrocode} +local @@_table do + local tables = get_luadata and get_luadata'@@' or {[0] = {}} + function @@_table() + local t = scan_token() + if t ~= intarray_marker then + put_next(t) + tex.error'LaTeX Error: intarray expected' + return tables[0] + end + local i = scan_int() + local current_table = tables[i] + if current_table then return current_table end + current_table = {} + tables[i] = current_table + return current_table + end +% \end{macrocode} +% Since in \LaTeX{} this is loaded in the format, we want to preserve any intarrays +% which are created while format building for the actual run. +% +% To do this, we use the \texttt{register_luadata} mechanism from \pkg{l3luatex}: +% Directly before the format get dumped, the following function gets invoked and serializes +% all existing tables into a string. This string gets compiled and dumped into the format and +% is made available at the beginning of regular runs as \texttt{get_luadata'@@'}. +% \begin{macrocode} + if register_luadata then + register_luadata('@@', function() + local t = "{[0]={}," + for i=1, #tables do + t = string.format("%s{%s},", t, table.concat(tables[i], ',')) + end + return t .. "}" + end) + end +end +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\intarray_count:N, \intarray_count:c} +% \begin{macro}[EXP]{\@@_gset_count:Nw} +% Set and get the size of an array. ``Setting the size'' means in this context that +% we add zeros until we reach the desired size. +% \begin{macrocode} + +local sprint = tex.sprint + +luacmd('@@_gset_count:Nw', function() + local t = @@_table() + local n = scan_int() + for i=#t+1, n do t[i] = 0 end +end, 'protected', 'global') + +luacmd('intarray_count:N', function() + sprint(-2, #@@_table()) +end, 'global') +%</lua> +% \end{macrocode} +% +% \begin{macrocode} +%<*tex> + \cs_generate_variant:Nn \intarray_count:N { c } +%</tex> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsubsection{Array items} +% +% \begin{macro}{\@@_gset:wF, \@@_gset:w} +% The setter provided by Lua. The argument order somewhat emulates the |\fontdimen|: +% First the array index, followed by the intarray and then the new value. +% This has been chosen over a more conventional order to provide a delimiter for the numbers. +% \begin{macrocode} +%<*lua> +luacmd('@@_gset:wF', function() + local i = scan_int() + local t = @@_table() + if t[i] then + t[i] = scan_int() + put_next(use_none) + else + tex.count.l_@@_bad_index_int = i + scan_int() + put_next(use_i) + end +end, 'protected', 'global') + +luacmd('@@_gset:w', function() + local i = scan_int() + local t = @@_table() + t[i] = scan_int() +end, 'protected', 'global') +%</lua> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\intarray_gset:Nnn, \intarray_gset:cnn, \__kernel_intarray_gset:Nnn} +% The \cs{__kernel_intarray_gset:Nnn} function does not use +% \cs{int_eval:n}, namely its arguments must be suitable for +% \cs{int_value:w}. The user version checks the position and value +% are within bounds. +% \begin{macrocode} +%<*tex> + \cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 + { \@@_gset:w #2 #1 #3 \scan_stop: } + \cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 + { + \@@_gset:wF \int_eval:n {#2} #1 \int_eval:n{#3} + { + \msg_error:nnxxx { kernel } { out-of-bounds } + { \token_to_str:N #1 } { \int_use:N \l_@@_bad_index_int } { \intarray_count:N #1 } + } + } + \cs_generate_variant:Nn \intarray_gset:Nnn { c } +%</tex> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\intarray_gzero:N, \intarray_gzero:c} +% Set the appropriate array entry to zero. No bound checking +% needed. +% \begin{macrocode} +%<*lua> +luacmd('intarray_gzero:N', function() + local t = @@_table() + for i=1, #t do + t[i] = 0 + end +end, 'global', 'protected') +%</lua> +%<*tex> + \cs_generate_variant:Nn \intarray_gzero:N { c } +%</tex> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\intarray_item:Nn, \intarray_item:cn, \__kernel_intarray_item:Nn} +% \begin{macro}{\@@_item:wF,\@@_item:w} +% Get the appropriate entry and perform bound checks. The +% \cs{__kernel_intarray_item:Nn} function omits bound checks and omits +% \cs{int_eval:n}, namely its argument must be a \TeX{} integer +% suitable for \cs{int_value:w}. +% \begin{macrocode} +%<*lua> +luacmd('@@_item:wF', function() + local i = scan_int() + local t = @@_table() + local item = t[i] + if item then + put_next(use_none) + else + tex.l_@@_bad_index_int = i + put_next(use_i) + end + put_next(expand_after_scan_stop) + scan_token() + if item then + sprint(-2, item) + end +end, 'global') + +luacmd('@@_item:w', function() + local i = scan_int() + local t = @@_table() + sprint(-2, t[i]) +end, 'global') +%</lua> +% \end{macrocode} +% +% \begin{macrocode} +%<*tex> + \cs_new:Npn \__kernel_intarray_item:Nn #1#2 + { \@@_item:w #2 #1 } + \cs_new:Npn \intarray_item:Nn #1#2 + { + \@@_item:wF \int_eval:n {#2} #1 + { + \msg_expandable_error:nnfff { kernel } { out-of-bounds } + { \token_to_str:N #1 } { \int_use:N \l_@@_bad_index_int } { \intarray_count:N #1 } + 0 + } + } + \cs_generate_variant:Nn \intarray_item:Nn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\intarray_rand_item:N, \intarray_rand_item:c} +% Importantly, \cs{intarray_item:Nn} only evaluates its argument once. +% \begin{macrocode} + \cs_new:Npn \intarray_rand_item:N #1 + { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } + \cs_generate_variant:Nn \intarray_rand_item:N { c } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Working with contents of integer arrays} +% +% \begin{macro}{\intarray_const_from_clist:Nn, \intarray_const_from_clist:cn} +% We use the \cs{__kernel_intarray_gset:Nnn} which does not do bounds checking +% and instead automatically resizes the array. +% This is not implemented in Lua to ensure that the clist parsing is consistent +% with the clist module. +% \begin{macrocode} + \cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 + { + \@@_new:N #1 + \int_zero:N \l_@@_loop_int + \clist_map_inline:nn {#2} + { + \int_incr:N \l_@@_loop_int + \__kernel_intarray_gset:Nnn #1 \l_@@_loop_int { \int_eval:n {##1} } } + } + \cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[rEXP]{\intarray_to_clist:N, \intarray_to_clist:c} +% \begin{macro}[rEXP]{\@@_to_clist:Nn, \@@_to_clist:w} +% The \cs{@@_to_clist:Nn} auxiliary allows to choose the delimiter and +% is also used in \cs{intarray_show:N}. Here we just pass the information +% to Lua and let \texttt{table.concat} do the actual work. +% We discard the category codes of the passed delimiter but this is not +% an issue since the delimiter is always just a comma or a comma and a space. +% In both cases \texttt{sprint(2, ...)} provides the right catcodes. +% \begin{macrocode} + \cs_new:Npn \intarray_to_clist:N #1 { \@@_to_clist:Nn #1 { , } } + \cs_generate_variant:Nn \intarray_to_clist:N { c } +%</tex> +%<*lua> +local concat = table.concat +luacmd('@@_to_clist:Nn', function() + local t = @@_table() + local sep = token.scan_string() + sprint(-2, concat(t, sep)) +end, 'global') +%</lua> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[rEXP]{\__kernel_intarray_range_to_clist:Nnn, \@@_range_to_clist:w} +% Loop through part of the array. +% \begin{macrocode} +%<*tex> + \cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 + { + \@@_range_to_clist:w #1 + \int_eval:n {#2} ~ \int_eval:n {#3} ~ + } +%</tex> +%<*lua> +luacmd('@@_range_to_clist:w', function() + local t = @@_table() + local from = scan_int() + local to = scan_int() + sprint(-2, concat(t, ',', from, to)) +end, 'global') +%</lua> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\__kernel_intarray_gset_range_from_clist:Nnn, \@@_gset_range:nNw} +% Loop through part of the array. We allow additional commas at the end. +% \begin{macrocode} +%<*tex> + \cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 + { + \@@_gset_range:w \int_eval:w #2 #1 #3 , , \scan_stop: + } +%</tex> +%<*lua> +luacmd('@@_gset_range:w', function() + local from = scan_int() + local t = @@_table() + while true do + local tok = scan_token() + if tok == comma then + repeat + tok = scan_token() + until tok ~= comma + break + else + put_next(tok) + end + t[from] = scan_int() + scan_token() + from = from + 1 + end + end, 'global', 'protected') +%</lua> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_gset_overflow_test:nw} +% In order to allow some code sharing later we provide the +% \cs{@@_gset_overflow_test:nw} name here. It doesn't actually test anything +% since the Lua implementation accepts all integers which could be tested with +% \cs{tex_ifabsnum:D}. +% \begin{macrocode} +%<*tex> + \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 + { + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Font dimension based implementation} +% +% Go to the false branch of the conditional above. +% \begin{macrocode} + } + { +% \end{macrocode} +% +% \subsubsection{Allocating arrays} +% +% \begin{macro}{\@@_entry:w, \@@_count:w} +% We use these primitives quite a lot in this module. +% \begin{macrocode} + \cs_new_eq:NN \@@_entry:w \tex_fontdimen:D + \cs_new_eq:NN \@@_count:w \tex_hyphenchar:D +% \end{macrocode} +% \end{macro} +% % \begin{variable}{\c_@@_sp_dim} % Used to convert integers to dimensions fast. % \begin{macrocode} -\dim_const:Nn \c_@@_sp_dim { 1 sp } + \dim_const:Nn \c_@@_sp_dim { 1 sp } % \end{macrocode} % \end{variable} % % \begin{variable}{\g_@@_font_int} % Used to assign one font per array. % \begin{macrocode} -\int_new:N \g_@@_font_int + \int_new:N \g_@@_font_int % \end{macrocode} % \end{variable} % -% \begin{macrocode} -\msg_new:nnn { kernel } { negative-array-size } - { Size~of~array~may~not~be~negative:~#1 } -% \end{macrocode} -% % \begin{macro}{\intarray_new:Nn, \intarray_new:cn} % \begin{macro}{\@@_new:N} % Declare |#1| to be a font (arbitrarily |cmr10| at a never-used @@ -221,28 +629,28 @@ % Every \texttt{intarray} must be global; it's enough to run this % check in \cs{intarray_new:Nn}. % \begin{macrocode} -\cs_new_protected:Npn \@@_new:N #1 - { - \__kernel_chk_if_free_cs:N #1 - \int_gincr:N \g_@@_font_int - \tex_global:D \tex_font:D #1 - = cmr10~at~ \g_@@_font_int \c_@@_sp_dim \scan_stop: - \int_step_inline:nn { 8 } - { \__kernel_intarray_gset:Nnn #1 {##1} \c_zero_int } - } -\cs_new_protected:Npn \intarray_new:Nn #1#2 - { - \@@_new:N #1 - \@@_count:w #1 = \int_eval:n {#2} \scan_stop: - \int_compare:nNnT { \intarray_count:N #1 } < 0 + \cs_new_protected:Npn \@@_new:N #1 { - \msg_error:nnx { kernel } { negative-array-size } - { \intarray_count:N #1 } + \__kernel_chk_if_free_cs:N #1 + \int_gincr:N \g_@@_font_int + \tex_global:D \tex_font:D #1 + = cmr10~at~ \g_@@_font_int \c_@@_sp_dim \scan_stop: + \int_step_inline:nn { 8 } + { \__kernel_intarray_gset:Nnn #1 {##1} \c_zero_int } } - \int_compare:nNnT { \intarray_count:N #1 } > 0 - { \__kernel_intarray_gset:Nnn #1 { \intarray_count:N #1 } { 0 } } - } -\cs_generate_variant:Nn \intarray_new:Nn { c } + \cs_new_protected:Npn \intarray_new:Nn #1#2 + { + \@@_new:N #1 + \@@_count:w #1 = \int_eval:n {#2} \scan_stop: + \int_compare:nNnT { \intarray_count:N #1 } < 0 + { + \msg_error:nnx { kernel } { negative-array-size } + { \intarray_count:N #1 } + } + \int_compare:nNnT { \intarray_count:N #1 } > 0 + { \__kernel_intarray_gset:Nnn #1 { \intarray_count:N #1 } { 0 } } + } + \cs_generate_variant:Nn \intarray_new:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} @@ -250,19 +658,19 @@ % \begin{macro}[EXP]{\intarray_count:N, \intarray_count:c} % Size of an array. % \begin{macrocode} -\cs_new:Npn \intarray_count:N #1 { \int_value:w \@@_count:w #1 } -\cs_generate_variant:Nn \intarray_count:N { c } + \cs_new:Npn \intarray_count:N #1 { \int_value:w \@@_count:w #1 } + \cs_generate_variant:Nn \intarray_count:N { c } % \end{macrocode} % \end{macro} % -% \subsection{Array items} +% \subsubsection{Array items} % % \begin{macro}[EXP]{\@@_signed_max_dim:n} % Used when an item to be stored is larger than \cs{c_max_dim} in % absolute value; it is replaced by $\pm\cs{c_max_dim}$. % \begin{macrocode} -\cs_new:Npn \@@_signed_max_dim:n #1 - { \int_value:w \int_compare:nNnT {#1} < 0 { - } \c_max_dim } + \cs_new:Npn \@@_signed_max_dim:n #1 + { \int_value:w \int_compare:nNnT {#1} < 0 { - } \c_max_dim } % \end{macrocode} % \end{macro} % @@ -271,24 +679,24 @@ % bounds checking. The |T| branch is used if |#3| is within bounds of % the array |#2|. % \begin{macrocode} -\cs_new:Npn \@@_bounds:NNnTF #1#2#3 - { - \if_int_compare:w 1 > #3 \exp_stop_f: - \@@_bounds_error:NNnw #1 #2 {#3} - \else: - \if_int_compare:w #3 > \intarray_count:N #2 \exp_stop_f: - \@@_bounds_error:NNnw #1 #2 {#3} - \fi: - \fi: - \use_i:nn - } -\cs_new:Npn \@@_bounds_error:NNnw #1#2#3#4 \use_i:nn #5#6 - { - #4 - #1 { kernel } { out-of-bounds } - { \token_to_str:N #2 } {#3} { \intarray_count:N #2 } - #6 - } + \cs_new:Npn \@@_bounds:NNnTF #1#2#3 + { + \if_int_compare:w 1 > #3 \exp_stop_f: + \@@_bounds_error:NNnw #1 #2 {#3} + \else: + \if_int_compare:w #3 > \intarray_count:N #2 \exp_stop_f: + \@@_bounds_error:NNnw #1 #2 {#3} + \fi: + \fi: + \use_i:nn + } + \cs_new:Npn \@@_bounds_error:NNnw #1#2#3#4 \use_i:nn #5#6 + { + #4 + #1 { kernel } { out-of-bounds } + { \token_to_str:N #2 } {#3} { \intarray_count:N #2 } + #6 + } % \end{macrocode} % \end{macro} % @@ -300,48 +708,48 @@ % \cs{int_value:w}. The user version checks the position and value % are within bounds. % \begin{macrocode} -\cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 - { \@@_entry:w #2 #1 #3 \c_@@_sp_dim } -\cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 - { - \exp_after:wN \@@_gset:Nww - \exp_after:wN #1 - \int_value:w \int_eval:n {#2} \exp_after:wN ; - \int_value:w \int_eval:n {#3} ; - } -\cs_generate_variant:Nn \intarray_gset:Nnn { c } -\cs_new_protected:Npn \@@_gset:Nww #1#2 ; #3 ; - { - \@@_bounds:NNnTF \msg_error:nnxxx #1 {#2} + \cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 + { \@@_entry:w #2 #1 #3 \c_@@_sp_dim } + \cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 { - \@@_gset_overflow_test:nw {#3} - \__kernel_intarray_gset:Nnn #1 {#2} {#3} + \exp_after:wN \@@_gset:Nww + \exp_after:wN #1 + \int_value:w \int_eval:n {#2} \exp_after:wN ; + \int_value:w \int_eval:n {#3} ; } - { } - } -\cs_if_exist:NTF \tex_ifabsnum:D - { - \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 + \cs_generate_variant:Nn \intarray_gset:Nnn { c } + \cs_new_protected:Npn \@@_gset:Nww #1#2 ; #3 ; { - \tex_ifabsnum:D #1 > \c_max_dim - \exp_after:wN \@@_gset_overflow:NNnn - \fi: + \@@_bounds:NNnTF \msg_error:nnxxx #1 {#2} + { + \@@_gset_overflow_test:nw {#3} + \__kernel_intarray_gset:Nnn #1 {#2} {#3} + } + { } } - } - { - \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 + \cs_if_exist:NTF \tex_ifabsnum:D { - \if_int_compare:w \int_abs:n {#1} > \c_max_dim - \exp_after:wN \@@_gset_overflow:NNnn - \fi: + \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 + { + \tex_ifabsnum:D #1 > \c_max_dim + \exp_after:wN \@@_gset_overflow:NNnn + \fi: + } + } + { + \cs_new_protected:Npn \@@_gset_overflow_test:nw #1 + { + \if_int_compare:w \int_abs:n {#1} > \c_max_dim + \exp_after:wN \@@_gset_overflow:NNnn + \fi: + } + } + \cs_new_protected:Npn \@@_gset_overflow:NNnn #1#2#3#4 + { + \msg_error:nnxxxx { kernel } { overflow } + { \token_to_str:N #2 } {#3} {#4} { \@@_signed_max_dim:n {#4} } + #1 #2 {#3} { \@@_signed_max_dim:n {#4} } } - } -\cs_new_protected:Npn \@@_gset_overflow:NNnn #1#2#3#4 - { - \msg_error:nnxxxx { kernel } { overflow } - { \token_to_str:N #2 } {#3} {#4} { \@@_signed_max_dim:n {#4} } - #1 #2 {#3} { \@@_signed_max_dim:n {#4} } - } % \end{macrocode} % \end{macro} % \end{macro} @@ -352,16 +760,16 @@ % memory, but this is somewhat comparable to the size of the array, % and it is much faster than an \cs{int_step_inline:nn} loop. % \begin{macrocode} -\cs_new_protected:Npn \intarray_gzero:N #1 - { - \int_zero:N \l_@@_loop_int - \prg_replicate:nn { \intarray_count:N #1 } + \cs_new_protected:Npn \intarray_gzero:N #1 { - \int_incr:N \l_@@_loop_int - \@@_entry:w \l_@@_loop_int #1 \c_zero_dim + \int_zero:N \l_@@_loop_int + \prg_replicate:nn { \intarray_count:N #1 } + { + \int_incr:N \l_@@_loop_int + \@@_entry:w \l_@@_loop_int #1 \c_zero_dim + } } - } -\cs_generate_variant:Nn \intarray_gzero:N { c } + \cs_generate_variant:Nn \intarray_gzero:N { c } % \end{macrocode} % \end{macro} % @@ -372,21 +780,21 @@ % \cs{int_eval:n}, namely its argument must be a \TeX{} integer % suitable for \cs{int_value:w}. % \begin{macrocode} -\cs_new:Npn \__kernel_intarray_item:Nn #1#2 - { \int_value:w \@@_entry:w #2 #1 } -\cs_new:Npn \intarray_item:Nn #1#2 - { - \exp_after:wN \@@_item:Nw - \exp_after:wN #1 - \int_value:w \int_eval:n {#2} ; - } -\cs_generate_variant:Nn \intarray_item:Nn { c } -\cs_new:Npn \@@_item:Nw #1#2 ; - { - \@@_bounds:NNnTF \msg_expandable_error:nnfff #1 {#2} - { \__kernel_intarray_item:Nn #1 {#2} } - { 0 } - } + \cs_new:Npn \__kernel_intarray_item:Nn #1#2 + { \int_value:w \@@_entry:w #2 #1 } + \cs_new:Npn \intarray_item:Nn #1#2 + { + \exp_after:wN \@@_item:Nw + \exp_after:wN #1 + \int_value:w \int_eval:n {#2} ; + } + \cs_generate_variant:Nn \intarray_item:Nn { c } + \cs_new:Npn \@@_item:Nw #1#2 ; + { + \@@_bounds:NNnTF \msg_expandable_error:nnfff #1 {#2} + { \__kernel_intarray_item:Nn #1 {#2} } + { 0 } + } % \end{macrocode} % \end{macro} % \end{macro} @@ -394,13 +802,13 @@ % \begin{macro}{\intarray_rand_item:N, \intarray_rand_item:c} % Importantly, \cs{intarray_item:Nn} only evaluates its argument once. % \begin{macrocode} -\cs_new:Npn \intarray_rand_item:N #1 - { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } -\cs_generate_variant:Nn \intarray_rand_item:N { c } + \cs_new:Npn \intarray_rand_item:N #1 + { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } + \cs_generate_variant:Nn \intarray_rand_item:N { c } % \end{macrocode} % \end{macro} % -% \subsection{Working with contents of integer arrays} +% \subsubsection{Working with contents of integer arrays} % % \begin{macro}{\intarray_const_from_clist:Nn, \intarray_const_from_clist:cn} % \begin{macro}{\@@_const_from_clist:nN} @@ -413,21 +821,21 @@ % big, namely \cs{@@_gset_overflow_test:nw}, but not the code that % checks bounds. At the end, set the size of the intarray. % \begin{macrocode} -\cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 - { - \@@_new:N #1 - \int_zero:N \l_@@_loop_int - \clist_map_inline:nn {#2} - { \exp_args:Nf \@@_const_from_clist:nN { \int_eval:n {##1} } #1 } - \@@_count:w #1 \l_@@_loop_int - } -\cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } -\cs_new_protected:Npn \@@_const_from_clist:nN #1#2 - { - \int_incr:N \l_@@_loop_int - \@@_gset_overflow_test:nw {#1} - \__kernel_intarray_gset:Nnn #2 \l_@@_loop_int {#1} - } + \cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 + { + \@@_new:N #1 + \int_zero:N \l_@@_loop_int + \clist_map_inline:nn {#2} + { \exp_args:Nf \@@_const_from_clist:nN { \int_eval:n {##1} } #1 } + \@@_count:w #1 \l_@@_loop_int + } + \cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } + \cs_new_protected:Npn \@@_const_from_clist:nN #1#2 + { + \int_incr:N \l_@@_loop_int + \@@_gset_overflow_test:nw {#1} + \__kernel_intarray_gset:Nnn #2 \l_@@_loop_int {#1} + } % \end{macrocode} % \end{macro} % \end{macro} @@ -438,25 +846,25 @@ % the leading comma with |f|-expansion. We also use the auxiliary in % \cs{intarray_show:N} with argument comma, space. % \begin{macrocode} -\cs_new:Npn \intarray_to_clist:N #1 { \@@_to_clist:Nn #1 { , } } -\cs_generate_variant:Nn \intarray_to_clist:N { c } -\cs_new:Npn \@@_to_clist:Nn #1#2 - { - \int_compare:nNnF { \intarray_count:N #1 } = \c_zero_int + \cs_new:Npn \intarray_to_clist:N #1 { \@@_to_clist:Nn #1 { , } } + \cs_generate_variant:Nn \intarray_to_clist:N { c } + \cs_new:Npn \@@_to_clist:Nn #1#2 { - \exp_last_unbraced:Nf \use_none:n - { \@@_to_clist:w 1 ; #1 {#2} \prg_break_point: } + \int_compare:nNnF { \intarray_count:N #1 } = \c_zero_int + { + \exp_last_unbraced:Nf \use_none:n + { \@@_to_clist:w 1 ; #1 {#2} \prg_break_point: } + } + } + \cs_new:Npn \@@_to_clist:w #1 ; #2#3 + { + \if_int_compare:w #1 > \@@_count:w #2 + \prg_break:n + \fi: + #3 \__kernel_intarray_item:Nn #2 {#1} + \exp_after:wN \@@_to_clist:w + \int_value:w \int_eval:w #1 + \c_one_int ; #2 {#3} } - } -\cs_new:Npn \@@_to_clist:w #1 ; #2#3 - { - \if_int_compare:w #1 > \@@_count:w #2 - \prg_break:n - \fi: - #3 \__kernel_intarray_item:Nn #2 {#1} - \exp_after:wN \@@_to_clist:w - \int_value:w \int_eval:w #1 + \c_one_int ; #2 {#3} - } % \end{macrocode} % \end{macro} % \end{macro} @@ -464,48 +872,54 @@ % \begin{macro}[rEXP]{\__kernel_intarray_range_to_clist:Nnn, \@@_range_to_clist:ww} % Loop through part of the array. % \begin{macrocode} -\cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 - { - \exp_last_unbraced:Nf \use_none:n + \cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 { + \exp_last_unbraced:Nf \use_none:n + { + \exp_after:wN \@@_range_to_clist:ww + \int_value:w \int_eval:w #2 \exp_after:wN ; + \int_value:w \int_eval:w #3 ; + #1 \prg_break_point: + } + } + \cs_new:Npn \@@_range_to_clist:ww #1 ; #2 ; #3 + { + \if_int_compare:w #1 > #2 \exp_stop_f: + \prg_break:n + \fi: + , \__kernel_intarray_item:Nn #3 {#1} \exp_after:wN \@@_range_to_clist:ww - \int_value:w \int_eval:w #2 \exp_after:wN ; - \int_value:w \int_eval:w #3 ; - #1 \prg_break_point: + \int_value:w \int_eval:w #1 + \c_one_int ; #2 ; #3 } - } -\cs_new:Npn \@@_range_to_clist:ww #1 ; #2 ; #3 - { - \if_int_compare:w #1 > #2 \exp_stop_f: - \prg_break:n - \fi: - , \__kernel_intarray_item:Nn #3 {#1} - \exp_after:wN \@@_range_to_clist:ww - \int_value:w \int_eval:w #1 + \c_one_int ; #2 ; #3 - } % \end{macrocode} % \end{macro} % % \begin{macro}{\__kernel_intarray_gset_range_from_clist:Nnn, \@@_gset_range:Nw} % Loop through part of the array. % \begin{macrocode} -\cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 - { - \int_set:Nn \l_@@_loop_int {#2} - \@@_gset_range:Nw #1 #3 , , \prg_break_point: - } -\cs_new_protected:Npn \@@_gset_range:Nw #1 #2 , - { - \if_catcode:w \scan_stop: \tl_to_str:n {#2} \scan_stop: - \prg_break:n - \fi: - \__kernel_intarray_gset:Nnn #1 \l_@@_loop_int {#2} - \int_incr:N \l_@@_loop_int - \@@_gset_range:Nw #1 - } + \cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 + { + \int_set:Nn \l_@@_loop_int {#2} + \@@_gset_range:Nw #1 #3 , , \prg_break_point: + } + \cs_new_protected:Npn \@@_gset_range:Nw #1 #2 , + { + \if_catcode:w \scan_stop: \tl_to_str:n {#2} \scan_stop: + \prg_break:n + \fi: + \__kernel_intarray_gset:Nnn #1 \l_@@_loop_int {#2} + \int_incr:N \l_@@_loop_int + \@@_gset_range:Nw #1 + } % \end{macrocode} % \end{macro} % +% \begin{macrocode} + } +% \end{macrocode} +% +% \subsection{Common parts} +% % \begin{macro}{\intarray_show:N, \intarray_show:c, \intarray_log:N, \intarray_log:c} % Convert the list to a comma list (with spaces after each comma) % \begin{macrocode} @@ -527,7 +941,7 @@ % \end{macrocode} % \end{macro} % -% \subsection{Random arrays} +% \subsubsection{Random arrays} % % \begin{macro}{\intarray_gset_rand:Nn, \intarray_gset_rand:cn} % \begin{macro}{\intarray_gset_rand:Nnn, \intarray_gset_rand:cnn} @@ -624,6 +1038,7 @@ % \end{macro} % % \begin{macrocode} +%</tex> %</package> % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx index e9da0d7e8cd..bfd7174febc 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index 355de420bd2..51bfbec7128 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -1780,41 +1780,30 @@ % % \subsection{Turning properties into actions} % -% \begin{macro}{\@@_bool_set:Nn, \@@_bool_set:cn} +% \begin{macro} +% { +% \@@_bool_set:Nn, \@@_bool_set:cn, +% \@@_bool_set_inverse:Nn, \@@_bool_set_inverse:cn +% } +% \begin{macro}{\@@_bool_set:Nnnn} % Boolean keys are really just choices, but all done by hand. The % second argument here is the scope: either empty or \texttt{ g } for % global. % \begin{macrocode} \cs_new_protected:Npn \@@_bool_set:Nn #1#2 - { - \bool_if_exist:NF #1 { \bool_new:N #1 } - \@@_choice_make: - \@@_cmd_set:nx { \l_keys_path_str / true } - { \exp_not:c { bool_ #2 set_true:N } \exp_not:N #1 } - \@@_cmd_set:nx { \l_keys_path_str / false } - { \exp_not:c { bool_ #2 set_false:N } \exp_not:N #1 } - \@@_cmd_set:nn { \l_keys_path_str / unknown } - { - \msg_error:nnx { keys } { boolean-values-only } - \l_keys_key_str - } - \@@_default_set:n { true } - } + { \@@_bool_set:Nnnn #1 {#2} { true } { false } } \cs_generate_variant:Nn \@@_bool_set:Nn { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_bool_set_inverse:Nn, \@@_bool_set_inverse:cn} -% Inverse boolean setting is much the same. -% \begin{macrocode} \cs_new_protected:Npn \@@_bool_set_inverse:Nn #1#2 + { \@@_bool_set:Nnnn #1 {#2} { false } { true } } +\cs_generate_variant:Nn \@@_bool_set_inverse:Nn { c } +\cs_new_protected:Npn \@@_bool_set:Nnnn #1#2#3#4 { \bool_if_exist:NF #1 { \bool_new:N #1 } \@@_choice_make: \@@_cmd_set:nx { \l_keys_path_str / true } - { \exp_not:c { bool_ #2 set_false:N } \exp_not:N #1 } + { \exp_not:c { bool_ #2 set_ #3 :N } \exp_not:N #1 } \@@_cmd_set:nx { \l_keys_path_str / false } - { \exp_not:c { bool_ #2 set_true:N } \exp_not:N #1 } + { \exp_not:c { bool_ #2 set_ #4 :N } \exp_not:N #1 } \@@_cmd_set:nn { \l_keys_path_str / unknown } { \msg_error:nnx { keys } { boolean-values-only } @@ -1822,9 +1811,10 @@ } \@@_default_set:n { true } } -\cs_generate_variant:Nn \@@_bool_set_inverse:Nn { c } +\cs_generate_variant:Nn \@@_bool_set:Nn { c } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}{\@@_choice_make:, \@@_multichoice_make:} % \begin{macro}{\@@_choice_make:N} @@ -1999,6 +1989,33 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_legacy_if_set:nn, \@@_legacy_if_inverse:nn} +% \begin{macro}{\@@_legacy_if_inverse:nnnn} +% Much the same as \pkg{expl3} booleans, except we assume that the switch +% exists. +% \begin{macrocode} +\cs_new_protected:Npn \@@_legacy_if_set:nn #1#2 + { \@@_legacy_if_set:nnnn {#1} {#2} { true } { false } } +\cs_new_protected:Npn \@@_legacy_if_set_inverse:nn #1#2 + { \@@_legacy_if_set:nnnn {#1} {#2} { false } { true } } +\cs_new_protected:Npn \@@_legacy_if_set:nnnn #1#2#3#4 + { + \@@_choice_make: + \@@_cmd_set:nx { \l_keys_path_str / true } + { \exp_not:c { legacy_if_#2 set_ #3 :n } { \exp_not:n {#1} } } + \@@_cmd_set:nx { \l_keys_path_str / false } + { \exp_not:c { legacy_if_#2 set_ #4 :n } { \exp_not:n {#1} } } + \@@_cmd_set:nn { \l_keys_path_str / unknown } + { + \msg_error:nnx { keys } { boolean-values-only } + \l_keys_key_str + } + \@@_default_set:n { true } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}{\@@_meta_make:n} % \begin{macro}{\@@_meta_make:nn} % To create a meta-key, simply set up to pass data through. @@ -2347,6 +2364,23 @@ % \end{macro} % \end{macro} % +% \begin{macro} +% { +% .legacy_if_set:n, .legacy_if_gset:n, +% .legacy_if_set_inverse:n, .legacy_if_gset_inverse:n +% } +% \begin{macrocode} +\cs_new_protected:cpn { \c_@@_props_root_str .legacy_if_set:n } #1 + { \@@_legacy_if_set:nn {#1} { } } +\cs_new_protected:cpn { \c_@@_props_root_str .legacy_if_gset:n } #1 + { \@@_legacy_if_set:nn {#1} { g } } +\cs_new_protected:cpn { \c_@@_props_root_str .legacy_if_set_inverse:n } #1 + { \@@_legacy_if_set_inverse:nn {#1} { } } +\cs_new_protected:cpn { \c_@@_props_root_str .legacy_if_gset_inverse:n } #1 + { \@@_legacy_if_set_inverse:nn {#1} { g } } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{.meta:n} % Making a meta is handled internally. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx b/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx index c04f318fad9..91492a68136 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index ac63d0f89a3..918f36c3acf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -370,9 +370,47 @@ local scan_int = token.scan_int or token.scan_integer local scan_string = token.scan_string local scan_keyword = token.scan_keyword local put_next = token.put_next +local token_create = token.create +% \end{macrocode} +% +% Since token.create only returns useful values after the tokens +% has been added to TeX's hash table, we define a variant which +% defines it first if necessary. +% \begin{macrocode} +local token_create_safe +do + local is_defined = token.is_defined + local set_char = token.set_char + local runtoks = tex.runtoks + local let_token = token_create'let' -local true_tok = token.create'prg_return_true:' -local false_tok = token.create'prg_return_false:' + function token_create_safe(s) + local orig_token = token_create(s) + if is_defined(s, true) then + return orig_token + end + set_char(s, 0) + local new_token = token_create(s) + runtoks(function() + put_next(let_token, new_token, orig_token) + end) + return new_token + end +end + +local true_tok = token_create_safe'prg_return_true:' +local false_tok = token_create_safe'prg_return_false:' +% \end{macrocode} +% In Con\TeX{}t lmtx \texttt{token.command_id} does not exist, +% but it can easily be emulated with Con\TeX{}t's \texttt{tokens.commands}. +% \begin{macrocode} +local command_id = token.command_id +if not command_id and tokens and tokens.commands then + local id_map = tokens.commands + function command_id(name) + return id_map[name] + end +end % \end{macrocode} % % \begin{macrocode} @@ -642,9 +680,8 @@ end) % a function instead of an index into the functions table. % \begin{macrocode} local luacmd do - local token_create = token.create local set_lua = token.set_lua - local undefined_cs = token.command_id'undefined_cs' + local undefined_cs = command_id'undefined_cs' if not context and not luatexbase then require'ltluatex' end if luatexbase then @@ -665,7 +702,7 @@ local luacmd do local register = context.functions.register local functions = context.functions.known function luacmd(name, func, ...) - local tok = token.create(name) + local tok = token_create(name) if tok.command == undefined_cs then token.set_lua(name, register(func), ...) else @@ -677,6 +714,85 @@ end % \end{macrocode} % \end{macro} % +% \subsection{Preserving iniTeX Lua data for runs} +% +% \begin{macrocode} +%<@@=lua> +% \end{macrocode} +% +% The Lua state is not dumped when a forat is written, therefore any Lua +% variables filled doing format building need to be restored in order to +% be accessible during normal runs. +% +% We provide some kernel-internal helpers for this. They will only be available if +% \texttt{luatexbase} is available. This is not a big restriction though, because +% Con\TeX{}t (which does not use \texttt{luatexbase}) does not load \pkg{expl3} +% in the format. +% +% \begin{macrocode} +local register_luadata, get_luadata + +if luatexbase then + local register = token_create'@expl@luadata@bytecode'.index + if status.ini_version then +% \end{macrocode} +% +% \begin{macro}{register_luadata} +% \texttt{register_luadata} is only available during format generation. +% It accept a string which uniquely identifies the data object and has to be +% provided to retrieve it later. Additionally it accepts a function which is +% called in the \texttt{pre_dump} callback and which has to return a string that +% evaluates to a valid Lua object to be preserved. +% \begin{macrocode} + local luadata, luadata_order = {}, {} + + function register_luadata(name, func) + if luadata[name] then + error(format("LaTeX error: data name %q already in use", name)) + end + luadata[name] = func + luadata_order[#luadata_order + 1] = func and name + end +% \end{macrocode} +% \end{macro} +% +% The actual work is done in \texttt{pre_dump}. The \texttt{luadata_order} is used +% to ensure that the order is consistent over multiple runs. +% \begin{macrocode} + luatexbase.add_to_callback("pre_dump", function() + if next(luadata) then + local str = "return {" + for i=1, #luadata_order do + local name = luadata_order[i] + str = format('%s[%q]=%s,', str, name, luadata[name]()) + end + lua.bytecode[register] = assert(load(str .. "}")) + end + end, "ltx.luadata") + else +% \end{macrocode} +% +% \begin{macro}{get_luadata} +% \texttt{get_luadata} is only available if data should be restored. +% It accept the identifier which was used when the data object was registered and +% returns the associated object. Every object can only be retrieved once. +% \begin{macrocode} + local luadata = lua.bytecode[register] + if luadata then + lua.bytecode[register] = nil + luadata = luadata() + end + function get_luadata(name) + if not luadata then return end + local data = luadata[name] + luadata[name] = nil + return data + end + end +end +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} %</lua> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx index 5804d528caa..d9c76ed8c46 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx index 2f3c8460cac..e046dd2c808 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx b/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx index 8a4b70eb160..5d7779ff4fd 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index 4a91ce9a8a4..f6eb57c9019 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx index ca6f9a3467c..55d962b292b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx index 907bd9453eb..cfa9a985da9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx index ac70e76eeab..dd95825c87f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -711,11 +711,12 @@ % \cs{regex_replace_once:nnN} \Arg{regular expression} \Arg{replacement} \meta{tl~var} % \cs{regex_replace_once:nnNTF} \Arg{regular expression} \Arg{replacement} \meta{tl~var} \Arg{true code} \Arg{false code} % \end{syntax} -% Searches for the \meta{regular expression} in the \meta{token list} -% and replaces the first match with the \meta{replacement}. The result -% is assigned locally to \meta{tl~var}. In the \meta{replacement}, +% Searches for the \meta{regular expression} in the contents of the +% \meta{tl~var} and replaces the first match with the +% \meta{replacement}. In the \meta{replacement}, % |\0| represents the full match, |\1| represent the contents of the % first capturing group, |\2| of the second, \emph{etc.} +% The result is assigned locally to \meta{tl~var}. % \end{function} % % \begin{function}[noTF, added = 2017-05-26] @@ -725,7 +726,8 @@ % \cs{regex_replace_all:nnNTF} \Arg{regular expression} \Arg{replacement} \meta{tl~var} \Arg{true code} \Arg{false code} % \end{syntax} % Replaces all occurrences of the \meta{regular expression} in the -% \meta{token list} by the \meta{replacement}, where |\0| represents +% contents of the \meta{tl~var} +% by the \meta{replacement}, where |\0| represents % the full match, |\1| represent the contents of the first capturing % group, |\2| of the second, \emph{etc.} Every match is treated % independently, and matches cannot overlap. The result is assigned diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index 5420a6df3ea..f6d5611de65 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx index ef814af3f9f..0f00ceb209f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx index 6315417c351..04d00e83d95 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx index edc2dd3cf50..50e5e82ccb6 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx index 40fd7437f07..89f7177e001 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx index 39b091d7df5..cbffa7e7eca 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -709,20 +709,26 @@ do % \begin{macro}{\@@_shell_shipout:e} % Execute commands through shell escape at shipout. % -% For \LuaTeX, we use the same helper as above but delayed to using a late_lua whatsit. +% For \LuaTeX, we use the same helper as above but delayed using a |late_lua| whatsit. +% Creating a |late_lua| whatsit works a bit different if we are running under Con\TeX{}t. % \begin{macrocode} %<*lua> - local whatsit_id = node.id'whatsit' - local latelua_sub = node.subtype'late_lua' - local node_new = node.direct.new - local setfield = node.direct.setwhatsitfield or node.direct.setfield + local new_latelua = nodes and nodes.nuts and nodes.nuts.pool and nodes.nuts.pool.latelua or (function() + local whatsit_id = node.id'whatsit' + local latelua_sub = node.subtype'late_lua' + local node_new = node.direct.new + local setfield = node.direct.setwhatsitfield or node.direct.setfield + return function(f) + local n = node_new(whatsit_id, latelua_sub) + setfield(n, 'data', f) + return n + end + end)() local node_write = node.direct.write luacmd("@@_shell_shipout:e", function() local cmd = scan_string() - local n = node_new(whatsit_id, latelua_sub) - setfield(n, 'data', function() shellescape(cmd) end) - node_write(n) + node_write(new_latelua(function() shellescape(cmd) end)) end, "global", "protected") end %</lua> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx index d27bae37d2b..914e725f0dd 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx index f1ad3be0fc5..a3349bea868 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text.dtx index 0fa054cceee..638d9f47b94 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3text.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3text.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx index 70522a9aac2..733ca763522 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index bda39b5cf09..1f2c4eed3b7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -584,14 +584,16 @@ % \begin{syntax} % \cs{tl_reverse:N} \meta{tl~var} % \end{syntax} -% Reverses the order of the \meta{items} stored in \meta{tl~var}, so +% Sets the \meta{tl~var} to contain the result of reversing +% the order of its \meta{items}, so % that \meta{item_1}\meta{item_2}\meta{item_3} \ldots \meta{item_n} % becomes \meta{item_n}\ldots \meta{item_3}\meta{item_2}\meta{item_1}. % This process preserves unprotected spaces within the % \meta{token list variable}. Braced token groups are copied without % reversing the order of tokens, but keep the outer set of braces. -% See also \cs{tl_reverse:n}, and, for improved performance, -% \cs{tl_reverse_items:n}. +% This is equivalent to a combination of an assignment and +% \cs{tl_reverse:V}. See also \cs{tl_reverse_items:n} for improved +% performance. % \end{function} % % \begin{function}[added = 2012-01-08, EXP]{\tl_reverse_items:n} @@ -649,10 +651,9 @@ % \begin{syntax} % \cs{tl_trim_spaces:N} \meta{tl~var} % \end{syntax} -% Removes any leading and trailing explicit space characters -% (explicit tokens with character code~$32$ and category code~$10$) -% from the content of the \meta{tl~var}. Note that this therefore -% \emph{resets} the content of the variable. +% Sets the \meta{tl~var} to contain the result of removing any leading +% and trailing explicit space characters (explicit tokens with +% character code~$32$ and category code~$10$) from its contents. % \end{function} % % \subsection{Viewing token lists} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx index 527ce36e080..e4381736518 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % @@ -2592,6 +2592,9 @@ % Again, \tn{nullfont} is a special case because it is the only primitive % with the normally non-primitive |set_font| command code. % +% In LuaMeta\TeX{} some of the command names are different, so we check for +% both versions. The first one is always the \LuaTeX{} version. +% % \begin{macrocode} \sys_if_engine_luatex:TF { @@ -2602,9 +2605,10 @@ do local get_command = token.get_command local get_index = token.get_index local get_mode = token.get_mode or token.get_index - local cmd = token.command_id + local cmd = command_id local set_font = cmd'get_font' - local biggest_char = token.biggest_char() + local biggest_char = token.biggest_char and token.biggest_char() + or status.getconstants().max_character_code local mode_below_biggest_char = {} local index_not_nil = {} @@ -2613,29 +2617,29 @@ do [cmd'left_brace'] = true, [cmd'right_brace'] = true, [cmd'math_shift'] = true, - [cmd'mac_param'] = mode_below_biggest_char, - [cmd'sup_mark'] = true, - [cmd'sub_mark'] = true, - [cmd'endv'] = true, + [cmd'mac_param' or cmd'parameter'] = mode_below_biggest_char, + [cmd'sup_mark' or cmd'superscript'] = true, + [cmd'sub_mark' or cmd'subscript'] = true, + [cmd'endv' or cmd'ignore'] = true, [cmd'spacer'] = true, [cmd'letter'] = true, [cmd'other_char'] = true, - [cmd'tab_mark'] = mode_below_biggest_char, + [cmd'tab_mark' or cmd'alignment_tab'] = mode_below_biggest_char, [cmd'char_given'] = true, - [cmd'math_given'] = true, - [cmd'xmath_given'] = true, + [cmd'math_given' or 'math_char_given'] = true, + [cmd'xmath_given' or 'math_char_xgiven'] = true, [cmd'set_font'] = mode_not_null, [cmd'undefined_cs'] = true, [cmd'call'] = true, - [cmd'long_call'] = true, - [cmd'outer_call'] = true, - [cmd'long_outer_call'] = true, - [cmd'assign_glue'] = index_not_nil, - [cmd'assign_mu_glue'] = index_not_nil, - [cmd'assign_toks'] = index_not_nil, - [cmd'assign_int'] = index_not_nil, - [cmd'assign_attr'] = true, - [cmd'assign_dimen'] = index_not_nil, + [cmd'long_call' or cmd'protected_call'] = true, + [cmd'outer_call' or cmd'tolerant_call'] = true, + [cmd'long_outer_call' or cmd'tolerant_protected_call'] = true, + [cmd'assign_glue' or cmd'register_glue'] = index_not_nil, + [cmd'assign_mu_glue' or cmd'register_mu_glue'] = index_not_nil, + [cmd'assign_toks' or cmd'register_toks'] = index_not_nil, + [cmd'assign_int' or cmd'register_int'] = index_not_nil, + [cmd'assign_attr' or cmd'register_attribute'] = true, + [cmd'assign_dimen' or cmd'register_dimen'] = index_not_nil, } luacmd("@@_if_primitive_lua:N", function() diff --git a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx index 5aa2987d19d..476eeb02bba 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2021-11-12} +% \date{Released 2021-11-22} % % \maketitle % diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex b/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex index acd7546557c..9bbbaa1dc45 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex @@ -24,7 +24,7 @@ %% l3file.dtx (with options: `package') %% l3skip.dtx (with options: `package') %% l3keys.dtx (with options: `package') -%% l3intarray.dtx (with options: `package') +%% l3intarray.dtx (with options: `package,tex') %% l3fp.dtx (with options: `package') %% l3fp-aux.dtx (with options: `package') %% l3fp-traps.dtx (with options: `package') @@ -70,7 +70,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx -\def\ExplFileDate{2021-11-12}% +\def\ExplFileDate{2021-11-22}% \begingroup \def\next{\endgroup}% \expandafter\ifx\csname PackageError\endcsname\relax @@ -158,10 +158,7 @@ \expandafter\ifx\csname newcatcodetable\endcsname\relax \input{ltluatex}% \fi - \begingroup\edef\ignored{% - \expandafter\noexpand\csname prg_return_true:\endcsname - \expandafter\noexpand\csname prg_return_false:\endcsname - }\endgroup + \ifdefined\newluabytecode\newluabytecode\@expl@luadata@bytecode\fi \directlua{require("expl3")}% \ifnum 0% \directlua{ @@ -13091,29 +13088,19 @@ \cs_new:Npn \__keys_define_code:w #1 \c_colon_str #2 \s__keys_stop { \tl_if_empty:nTF {#2} } \cs_new_protected:Npn \__keys_bool_set:Nn #1#2 - { - \bool_if_exist:NF #1 { \bool_new:N #1 } - \__keys_choice_make: - \__keys_cmd_set:nx { \l_keys_path_str / true } - { \exp_not:c { bool_ #2 set_true:N } \exp_not:N #1 } - \__keys_cmd_set:nx { \l_keys_path_str / false } - { \exp_not:c { bool_ #2 set_false:N } \exp_not:N #1 } - \__keys_cmd_set:nn { \l_keys_path_str / unknown } - { - \msg_error:nnx { keys } { boolean-values-only } - \l_keys_key_str - } - \__keys_default_set:n { true } - } + { \__keys_bool_set:Nnnn #1 {#2} { true } { false } } \cs_generate_variant:Nn \__keys_bool_set:Nn { c } \cs_new_protected:Npn \__keys_bool_set_inverse:Nn #1#2 + { \__keys_bool_set:Nnnn #1 {#2} { false } { true } } +\cs_generate_variant:Nn \__keys_bool_set_inverse:Nn { c } +\cs_new_protected:Npn \__keys_bool_set:Nnnn #1#2#3#4 { \bool_if_exist:NF #1 { \bool_new:N #1 } \__keys_choice_make: \__keys_cmd_set:nx { \l_keys_path_str / true } - { \exp_not:c { bool_ #2 set_false:N } \exp_not:N #1 } + { \exp_not:c { bool_ #2 set_ #3 :N } \exp_not:N #1 } \__keys_cmd_set:nx { \l_keys_path_str / false } - { \exp_not:c { bool_ #2 set_true:N } \exp_not:N #1 } + { \exp_not:c { bool_ #2 set_ #4 :N } \exp_not:N #1 } \__keys_cmd_set:nn { \l_keys_path_str / unknown } { \msg_error:nnx { keys } { boolean-values-only } @@ -13121,7 +13108,7 @@ } \__keys_default_set:n { true } } -\cs_generate_variant:Nn \__keys_bool_set_inverse:Nn { c } +\cs_generate_variant:Nn \__keys_bool_set:Nn { c } \cs_new_protected:Npn \__keys_choice_make: { \__keys_choice_make:N \__keys_choice_find:n } \cs_new_protected:Npn \__keys_multichoice_make: @@ -13228,6 +13215,24 @@ { \__keys_execute:nn \l_keys_path_str {#1} } } } +\cs_new_protected:Npn \__keys_legacy_if_set:nn #1#2 + { \__keys_legacy_if_set:nnnn {#1} {#2} { true } { false } } +\cs_new_protected:Npn \__keys_legacy_if_set_inverse:nn #1#2 + { \__keys_legacy_if_set:nnnn {#1} {#2} { false } { true } } +\cs_new_protected:Npn \__keys_legacy_if_set:nnnn #1#2#3#4 + { + \__keys_choice_make: + \__keys_cmd_set:nx { \l_keys_path_str / true } + { \exp_not:c { legacy_if_#2 set_ #3 :n } { \exp_not:n {#1} } } + \__keys_cmd_set:nx { \l_keys_path_str / false } + { \exp_not:c { legacy_if_#2 set_ #4 :n } { \exp_not:n {#1} } } + \__keys_cmd_set:nn { \l_keys_path_str / unknown } + { + \msg_error:nnx { keys } { boolean-values-only } + \l_keys_key_str + } + \__keys_default_set:n { true } + } \cs_new_protected:Npn \__keys_meta_make:n #1 { \__keys_cmd_set:Vo \l_keys_path_str @@ -13420,6 +13425,14 @@ { \__keys_variable_set_required:NnnN #1 { int } { g } n } \cs_new_protected:cpn { \c__keys_props_root_str .int_gset:c } #1 { \__keys_variable_set_required:cnnN {#1} { int } { g } n } +\cs_new_protected:cpn { \c__keys_props_root_str .legacy_if_set:n } #1 + { \__keys_legacy_if_set:nn {#1} { } } +\cs_new_protected:cpn { \c__keys_props_root_str .legacy_if_gset:n } #1 + { \__keys_legacy_if_set:nn {#1} { g } } +\cs_new_protected:cpn { \c__keys_props_root_str .legacy_if_set_inverse:n } #1 + { \__keys_legacy_if_set_inverse:nn {#1} { } } +\cs_new_protected:cpn { \c__keys_props_root_str .legacy_if_gset_inverse:n } #1 + { \__keys_legacy_if_set_inverse:nn {#1} { g } } \cs_new_protected:cpn { \c__keys_props_root_str .meta:n } #1 { \__keys_meta_make:n {#1} } \cs_new_protected:cpn { \c__keys_props_root_str .meta:nn } #1 @@ -14032,193 +14045,269 @@ \prop_gput:Nnn \g_msg_module_name_prop { keys } { LaTeX3 } \prop_gput:Nnn \g_msg_module_type_prop { keys } { } %% File: l3intarray.dtx -\cs_new_eq:NN \__intarray_entry:w \tex_fontdimen:D -\cs_new_eq:NN \__intarray_count:w \tex_hyphenchar:D -\int_new:N \l__intarray_loop_int -\dim_const:Nn \c__intarray_sp_dim { 1 sp } -\int_new:N \g__intarray_font_int \msg_new:nnn { kernel } { negative-array-size } { Size~of~array~may~not~be~negative:~#1 } -\cs_new_protected:Npn \__intarray_new:N #1 - { - \__kernel_chk_if_free_cs:N #1 - \int_gincr:N \g__intarray_font_int - \tex_global:D \tex_font:D #1 - = cmr10~at~ \g__intarray_font_int \c__intarray_sp_dim \scan_stop: - \int_step_inline:nn { 8 } - { \__kernel_intarray_gset:Nnn #1 {##1} \c_zero_int } - } -\cs_new_protected:Npn \intarray_new:Nn #1#2 +\int_new:N \l__intarray_loop_int +\cs_if_exist:NTF \__intarray_gset_count:Nw { - \__intarray_new:N #1 - \__intarray_count:w #1 = \int_eval:n {#2} \scan_stop: - \int_compare:nNnT { \intarray_count:N #1 } < 0 + \int_new:N \g__intarray_table_int + \int_new:N \l__intarray_bad_index_int + \cs_new_protected:Npn \__intarray_new:N #1 { - \msg_error:nnx { kernel } { negative-array-size } - { \intarray_count:N #1 } + \__kernel_chk_if_free_cs:N #1 + \int_gincr:N \g__intarray_table_int + \cs_gset_nopar:Npx #1 { \__intarray:w \int_use:N \g__intarray_table_int \c_space_tl } } - \int_compare:nNnT { \intarray_count:N #1 } > 0 - { \__kernel_intarray_gset:Nnn #1 { \intarray_count:N #1 } { 0 } } - } -\cs_generate_variant:Nn \intarray_new:Nn { c } -\cs_new:Npn \intarray_count:N #1 { \int_value:w \__intarray_count:w #1 } -\cs_generate_variant:Nn \intarray_count:N { c } -\cs_new:Npn \__intarray_signed_max_dim:n #1 - { \int_value:w \int_compare:nNnT {#1} < 0 { - } \c_max_dim } -\cs_new:Npn \__intarray_bounds:NNnTF #1#2#3 - { - \if_int_compare:w 1 > #3 \exp_stop_f: - \__intarray_bounds_error:NNnw #1 #2 {#3} - \else: - \if_int_compare:w #3 > \intarray_count:N #2 \exp_stop_f: - \__intarray_bounds_error:NNnw #1 #2 {#3} - \fi: - \fi: - \use_i:nn - } -\cs_new:Npn \__intarray_bounds_error:NNnw #1#2#3#4 \use_i:nn #5#6 - { - #4 - #1 { kernel } { out-of-bounds } - { \token_to_str:N #2 } {#3} { \intarray_count:N #2 } - #6 - } -\cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 - { \__intarray_entry:w #2 #1 #3 \c__intarray_sp_dim } -\cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 - { - \exp_after:wN \__intarray_gset:Nww - \exp_after:wN #1 - \int_value:w \int_eval:n {#2} \exp_after:wN ; - \int_value:w \int_eval:n {#3} ; - } -\cs_generate_variant:Nn \intarray_gset:Nnn { c } -\cs_new_protected:Npn \__intarray_gset:Nww #1#2 ; #3 ; - { - \__intarray_bounds:NNnTF \msg_error:nnxxx #1 {#2} + \cs_new_protected:Npn \intarray_new:Nn #1#2 { - \__intarray_gset_overflow_test:nw {#3} - \__kernel_intarray_gset:Nnn #1 {#2} {#3} + \__intarray_new:N #1 + \__intarray_gset_count:Nw #1 \int_eval:n {#2} \scan_stop: + \int_compare:nNnT { \intarray_count:N #1 } < 0 + { + \msg_error:nnx { kernel } { negative-array-size } + { \intarray_count:N #1 } + } } - { } - } -\cs_if_exist:NTF \tex_ifabsnum:D - { - \cs_new_protected:Npn \__intarray_gset_overflow_test:nw #1 + \cs_generate_variant:Nn \intarray_new:Nn { c } + \cs_generate_variant:Nn \intarray_count:N { c } + \cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 + { \__intarray_gset:w #2 #1 #3 \scan_stop: } + \cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 { - \tex_ifabsnum:D #1 > \c_max_dim - \exp_after:wN \__intarray_gset_overflow:NNnn - \fi: + \__intarray_gset:wF \int_eval:n {#2} #1 \int_eval:n{#3} + { + \msg_error:nnxxx { kernel } { out-of-bounds } + { \token_to_str:N #1 } { \int_use:N \l__intarray_bad_index_int } { \intarray_count:N #1 } + } + } + \cs_generate_variant:Nn \intarray_gset:Nnn { c } + \cs_generate_variant:Nn \intarray_gzero:N { c } + \cs_new:Npn \__kernel_intarray_item:Nn #1#2 + { \__intarray_item:w #2 #1 } + \cs_new:Npn \intarray_item:Nn #1#2 + { + \__intarray_item:wF \int_eval:n {#2} #1 + { + \msg_expandable_error:nnfff { kernel } { out-of-bounds } + { \token_to_str:N #1 } { \int_use:N \l__intarray_bad_index_int } { \intarray_count:N #1 } + 0 + } + } + \cs_generate_variant:Nn \intarray_item:Nn { c } + \cs_new:Npn \intarray_rand_item:N #1 + { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } + \cs_generate_variant:Nn \intarray_rand_item:N { c } + \cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 + { + \__intarray_new:N #1 + \int_zero:N \l__intarray_loop_int + \clist_map_inline:nn {#2} + { + \int_incr:N \l__intarray_loop_int + \__kernel_intarray_gset:Nnn #1 \l__intarray_loop_int { \int_eval:n {##1} } } } + \cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } + \cs_new:Npn \intarray_to_clist:N #1 { \__intarray_to_clist:Nn #1 { , } } + \cs_generate_variant:Nn \intarray_to_clist:N { c } + \cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 + { + \__intarray_range_to_clist:w #1 + \int_eval:n {#2} ~ \int_eval:n {#3} ~ + } + \cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 + { + \__intarray_gset_range:w \int_eval:w #2 #1 #3 , , \scan_stop: + } + \cs_new_protected:Npn \__intarray_gset_overflow_test:nw #1 + { + } } { - \cs_new_protected:Npn \__intarray_gset_overflow_test:nw #1 + \cs_new_eq:NN \__intarray_entry:w \tex_fontdimen:D + \cs_new_eq:NN \__intarray_count:w \tex_hyphenchar:D + \dim_const:Nn \c__intarray_sp_dim { 1 sp } + \int_new:N \g__intarray_font_int + \cs_new_protected:Npn \__intarray_new:N #1 { - \if_int_compare:w \int_abs:n {#1} > \c_max_dim - \exp_after:wN \__intarray_gset_overflow:NNnn + \__kernel_chk_if_free_cs:N #1 + \int_gincr:N \g__intarray_font_int + \tex_global:D \tex_font:D #1 + = cmr10~at~ \g__intarray_font_int \c__intarray_sp_dim \scan_stop: + \int_step_inline:nn { 8 } + { \__kernel_intarray_gset:Nnn #1 {##1} \c_zero_int } + } + \cs_new_protected:Npn \intarray_new:Nn #1#2 + { + \__intarray_new:N #1 + \__intarray_count:w #1 = \int_eval:n {#2} \scan_stop: + \int_compare:nNnT { \intarray_count:N #1 } < 0 + { + \msg_error:nnx { kernel } { negative-array-size } + { \intarray_count:N #1 } + } + \int_compare:nNnT { \intarray_count:N #1 } > 0 + { \__kernel_intarray_gset:Nnn #1 { \intarray_count:N #1 } { 0 } } + } + \cs_generate_variant:Nn \intarray_new:Nn { c } + \cs_new:Npn \intarray_count:N #1 { \int_value:w \__intarray_count:w #1 } + \cs_generate_variant:Nn \intarray_count:N { c } + \cs_new:Npn \__intarray_signed_max_dim:n #1 + { \int_value:w \int_compare:nNnT {#1} < 0 { - } \c_max_dim } + \cs_new:Npn \__intarray_bounds:NNnTF #1#2#3 + { + \if_int_compare:w 1 > #3 \exp_stop_f: + \__intarray_bounds_error:NNnw #1 #2 {#3} + \else: + \if_int_compare:w #3 > \intarray_count:N #2 \exp_stop_f: + \__intarray_bounds_error:NNnw #1 #2 {#3} + \fi: \fi: + \use_i:nn } - } -\cs_new_protected:Npn \__intarray_gset_overflow:NNnn #1#2#3#4 - { - \msg_error:nnxxxx { kernel } { overflow } - { \token_to_str:N #2 } {#3} {#4} { \__intarray_signed_max_dim:n {#4} } - #1 #2 {#3} { \__intarray_signed_max_dim:n {#4} } - } -\cs_new_protected:Npn \intarray_gzero:N #1 - { - \int_zero:N \l__intarray_loop_int - \prg_replicate:nn { \intarray_count:N #1 } + \cs_new:Npn \__intarray_bounds_error:NNnw #1#2#3#4 \use_i:nn #5#6 + { + #4 + #1 { kernel } { out-of-bounds } + { \token_to_str:N #2 } {#3} { \intarray_count:N #2 } + #6 + } + \cs_new_protected:Npn \__kernel_intarray_gset:Nnn #1#2#3 + { \__intarray_entry:w #2 #1 #3 \c__intarray_sp_dim } + \cs_new_protected:Npn \intarray_gset:Nnn #1#2#3 + { + \exp_after:wN \__intarray_gset:Nww + \exp_after:wN #1 + \int_value:w \int_eval:n {#2} \exp_after:wN ; + \int_value:w \int_eval:n {#3} ; + } + \cs_generate_variant:Nn \intarray_gset:Nnn { c } + \cs_new_protected:Npn \__intarray_gset:Nww #1#2 ; #3 ; + { + \__intarray_bounds:NNnTF \msg_error:nnxxx #1 {#2} + { + \__intarray_gset_overflow_test:nw {#3} + \__kernel_intarray_gset:Nnn #1 {#2} {#3} + } + { } + } + \cs_if_exist:NTF \tex_ifabsnum:D + { + \cs_new_protected:Npn \__intarray_gset_overflow_test:nw #1 + { + \tex_ifabsnum:D #1 > \c_max_dim + \exp_after:wN \__intarray_gset_overflow:NNnn + \fi: + } + } + { + \cs_new_protected:Npn \__intarray_gset_overflow_test:nw #1 + { + \if_int_compare:w \int_abs:n {#1} > \c_max_dim + \exp_after:wN \__intarray_gset_overflow:NNnn + \fi: + } + } + \cs_new_protected:Npn \__intarray_gset_overflow:NNnn #1#2#3#4 + { + \msg_error:nnxxxx { kernel } { overflow } + { \token_to_str:N #2 } {#3} {#4} { \__intarray_signed_max_dim:n {#4} } + #1 #2 {#3} { \__intarray_signed_max_dim:n {#4} } + } + \cs_new_protected:Npn \intarray_gzero:N #1 + { + \int_zero:N \l__intarray_loop_int + \prg_replicate:nn { \intarray_count:N #1 } + { + \int_incr:N \l__intarray_loop_int + \__intarray_entry:w \l__intarray_loop_int #1 \c_zero_dim + } + } + \cs_generate_variant:Nn \intarray_gzero:N { c } + \cs_new:Npn \__kernel_intarray_item:Nn #1#2 + { \int_value:w \__intarray_entry:w #2 #1 } + \cs_new:Npn \intarray_item:Nn #1#2 + { + \exp_after:wN \__intarray_item:Nw + \exp_after:wN #1 + \int_value:w \int_eval:n {#2} ; + } + \cs_generate_variant:Nn \intarray_item:Nn { c } + \cs_new:Npn \__intarray_item:Nw #1#2 ; + { + \__intarray_bounds:NNnTF \msg_expandable_error:nnfff #1 {#2} + { \__kernel_intarray_item:Nn #1 {#2} } + { 0 } + } + \cs_new:Npn \intarray_rand_item:N #1 + { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } + \cs_generate_variant:Nn \intarray_rand_item:N { c } + \cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 + { + \__intarray_new:N #1 + \int_zero:N \l__intarray_loop_int + \clist_map_inline:nn {#2} + { \exp_args:Nf \__intarray_const_from_clist:nN { \int_eval:n {##1} } #1 } + \__intarray_count:w #1 \l__intarray_loop_int + } + \cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } + \cs_new_protected:Npn \__intarray_const_from_clist:nN #1#2 { \int_incr:N \l__intarray_loop_int - \__intarray_entry:w \l__intarray_loop_int #1 \c_zero_dim + \__intarray_gset_overflow_test:nw {#1} + \__kernel_intarray_gset:Nnn #2 \l__intarray_loop_int {#1} } - } -\cs_generate_variant:Nn \intarray_gzero:N { c } -\cs_new:Npn \__kernel_intarray_item:Nn #1#2 - { \int_value:w \__intarray_entry:w #2 #1 } -\cs_new:Npn \intarray_item:Nn #1#2 - { - \exp_after:wN \__intarray_item:Nw - \exp_after:wN #1 - \int_value:w \int_eval:n {#2} ; - } -\cs_generate_variant:Nn \intarray_item:Nn { c } -\cs_new:Npn \__intarray_item:Nw #1#2 ; - { - \__intarray_bounds:NNnTF \msg_expandable_error:nnfff #1 {#2} - { \__kernel_intarray_item:Nn #1 {#2} } - { 0 } - } -\cs_new:Npn \intarray_rand_item:N #1 - { \intarray_item:Nn #1 { \int_rand:n { \intarray_count:N #1 } } } -\cs_generate_variant:Nn \intarray_rand_item:N { c } -\cs_new_protected:Npn \intarray_const_from_clist:Nn #1#2 - { - \__intarray_new:N #1 - \int_zero:N \l__intarray_loop_int - \clist_map_inline:nn {#2} - { \exp_args:Nf \__intarray_const_from_clist:nN { \int_eval:n {##1} } #1 } - \__intarray_count:w #1 \l__intarray_loop_int - } -\cs_generate_variant:Nn \intarray_const_from_clist:Nn { c } -\cs_new_protected:Npn \__intarray_const_from_clist:nN #1#2 - { - \int_incr:N \l__intarray_loop_int - \__intarray_gset_overflow_test:nw {#1} - \__kernel_intarray_gset:Nnn #2 \l__intarray_loop_int {#1} - } -\cs_new:Npn \intarray_to_clist:N #1 { \__intarray_to_clist:Nn #1 { , } } -\cs_generate_variant:Nn \intarray_to_clist:N { c } -\cs_new:Npn \__intarray_to_clist:Nn #1#2 - { - \int_compare:nNnF { \intarray_count:N #1 } = \c_zero_int + \cs_new:Npn \intarray_to_clist:N #1 { \__intarray_to_clist:Nn #1 { , } } + \cs_generate_variant:Nn \intarray_to_clist:N { c } + \cs_new:Npn \__intarray_to_clist:Nn #1#2 + { + \int_compare:nNnF { \intarray_count:N #1 } = \c_zero_int + { + \exp_last_unbraced:Nf \use_none:n + { \__intarray_to_clist:w 1 ; #1 {#2} \prg_break_point: } + } + } + \cs_new:Npn \__intarray_to_clist:w #1 ; #2#3 + { + \if_int_compare:w #1 > \__intarray_count:w #2 + \prg_break:n + \fi: + #3 \__kernel_intarray_item:Nn #2 {#1} + \exp_after:wN \__intarray_to_clist:w + \int_value:w \int_eval:w #1 + \c_one_int ; #2 {#3} + } + \cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 { \exp_last_unbraced:Nf \use_none:n - { \__intarray_to_clist:w 1 ; #1 {#2} \prg_break_point: } + { + \exp_after:wN \__intarray_range_to_clist:ww + \int_value:w \int_eval:w #2 \exp_after:wN ; + \int_value:w \int_eval:w #3 ; + #1 \prg_break_point: + } } - } -\cs_new:Npn \__intarray_to_clist:w #1 ; #2#3 - { - \if_int_compare:w #1 > \__intarray_count:w #2 - \prg_break:n - \fi: - #3 \__kernel_intarray_item:Nn #2 {#1} - \exp_after:wN \__intarray_to_clist:w - \int_value:w \int_eval:w #1 + \c_one_int ; #2 {#3} - } -\cs_new:Npn \__kernel_intarray_range_to_clist:Nnn #1#2#3 - { - \exp_last_unbraced:Nf \use_none:n + \cs_new:Npn \__intarray_range_to_clist:ww #1 ; #2 ; #3 { + \if_int_compare:w #1 > #2 \exp_stop_f: + \prg_break:n + \fi: + , \__kernel_intarray_item:Nn #3 {#1} \exp_after:wN \__intarray_range_to_clist:ww - \int_value:w \int_eval:w #2 \exp_after:wN ; - \int_value:w \int_eval:w #3 ; - #1 \prg_break_point: + \int_value:w \int_eval:w #1 + \c_one_int ; #2 ; #3 + } + \cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 + { + \int_set:Nn \l__intarray_loop_int {#2} + \__intarray_gset_range:Nw #1 #3 , , \prg_break_point: + } + \cs_new_protected:Npn \__intarray_gset_range:Nw #1 #2 , + { + \if_catcode:w \scan_stop: \tl_to_str:n {#2} \scan_stop: + \prg_break:n + \fi: + \__kernel_intarray_gset:Nnn #1 \l__intarray_loop_int {#2} + \int_incr:N \l__intarray_loop_int + \__intarray_gset_range:Nw #1 } - } -\cs_new:Npn \__intarray_range_to_clist:ww #1 ; #2 ; #3 - { - \if_int_compare:w #1 > #2 \exp_stop_f: - \prg_break:n - \fi: - , \__kernel_intarray_item:Nn #3 {#1} - \exp_after:wN \__intarray_range_to_clist:ww - \int_value:w \int_eval:w #1 + \c_one_int ; #2 ; #3 - } -\cs_new_protected:Npn \__kernel_intarray_gset_range_from_clist:Nnn #1#2#3 - { - \int_set:Nn \l__intarray_loop_int {#2} - \__intarray_gset_range:Nw #1 #3 , , \prg_break_point: - } -\cs_new_protected:Npn \__intarray_gset_range:Nw #1 #2 , - { - \if_catcode:w \scan_stop: \tl_to_str:n {#2} \scan_stop: - \prg_break:n - \fi: - \__kernel_intarray_gset:Nnn #1 \l__intarray_loop_int {#2} - \int_incr:N \l__intarray_loop_int - \__intarray_gset_range:Nw #1 } \cs_new_protected:Npn \intarray_show:N { \__intarray_show:NN \msg_show:nnxxxx } \cs_generate_variant:Nn \intarray_show:N { c } diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex b/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex index 3e0a8141cb7..12f6e53070f 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex @@ -19,7 +19,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx -\def\ExplFileDate{2021-11-12}% +\def\ExplFileDate{2021-11-22}% \let\ExplLoaderFileDate\ExplFileDate \begingroup \catcode`\_=11 diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx b/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx index b581aa5d546..9c5d9531678 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx @@ -19,7 +19,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx -\def\ExplFileDate{2021-11-12}% +\def\ExplFileDate{2021-11-22}% \let\ExplLoaderFileDate\ExplFileDate \begingroup \catcode`\_=11 diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3.lua b/Master/texmf-dist/tex/latex/l3kernel/expl3.lua index 9eed3547cf9..befb32e536c 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3.lua +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3.lua @@ -8,6 +8,7 @@ -- l3names.dtx (with options: `package,lua') -- l3sys.dtx (with options: `package,lua') -- l3token.dtx (with options: `package,lua') +-- l3intarray.dtx (with options: `package,lua') -- -- Copyright (C) 1990-2021 The LaTeX Project -- @@ -56,9 +57,37 @@ local scan_int = token.scan_int or token.scan_integer local scan_string = token.scan_string local scan_keyword = token.scan_keyword local put_next = token.put_next +local token_create = token.create +local token_create_safe +do + local is_defined = token.is_defined + local set_char = token.set_char + local runtoks = tex.runtoks + local let_token = token_create'let' + + function token_create_safe(s) + local orig_token = token_create(s) + if is_defined(s, true) then + return orig_token + end + set_char(s, 0) + local new_token = token_create(s) + runtoks(function() + put_next(let_token, new_token, orig_token) + end) + return new_token + end +end -local true_tok = token.create'prg_return_true:' -local false_tok = token.create'prg_return_false:' +local true_tok = token_create_safe'prg_return_true:' +local false_tok = token_create_safe'prg_return_false:' +local command_id = token.command_id +if not command_id and tokens and tokens.commands then + local id_map = tokens.commands + function command_id(name) + return id_map[name] + end +end local function deprecated(table, name, func) table[name] = function(...) write_nl(format("Calling deprecated Lua function %s", name)) @@ -226,9 +255,8 @@ deprecated(l3kernel, "shellescape", function(cmd) end end) local luacmd do - local token_create = token.create local set_lua = token.set_lua - local undefined_cs = token.command_id'undefined_cs' + local undefined_cs = command_id'undefined_cs' if not context and not luatexbase then require'ltluatex' end if luatexbase then @@ -249,7 +277,7 @@ local luacmd do local register = context.functions.register local functions = context.functions.known function luacmd(name, func, ...) - local tok = token.create(name) + local tok = token_create(name) if tok.command == undefined_cs then token.set_lua(name, register(func), ...) else @@ -258,6 +286,44 @@ local luacmd do end end end +local register_luadata, get_luadata + +if luatexbase then + local register = token_create'@expl@luadata@bytecode'.index + if status.ini_version then + local luadata, luadata_order = {}, {} + + function register_luadata(name, func) + if luadata[name] then + error(format("LaTeX error: data name %q already in use", name)) + end + luadata[name] = func + luadata_order[#luadata_order + 1] = func and name + end + luatexbase.add_to_callback("pre_dump", function() + if next(luadata) then + local str = "return {" + for i=1, #luadata_order do + local name = luadata_order[i] + str = format('%s[%q]=%s,', str, name, luadata[name]()) + end + lua.bytecode[register] = assert(load(str .. "}")) + end + end, "ltx.luadata") + else + local luadata = lua.bytecode[register] + if luadata then + lua.bytecode[register] = nil + luadata = luadata() + end + function get_luadata(name) + if not luadata then return end + local data = luadata[name] + luadata[name] = nil + return data + end + end +end -- File: l3names.dtx local minus_tok = token.new(string.byte'-', 12) local zero_tok = token.new(string.byte'0', 12) @@ -318,17 +384,22 @@ do luacmd("__sys_shell_now:e", function() shellescape(scan_string()) end, "global", "protected") - local whatsit_id = node.id'whatsit' - local latelua_sub = node.subtype'late_lua' - local node_new = node.direct.new - local setfield = node.direct.setwhatsitfield or node.direct.setfield + local new_latelua = nodes and nodes.nuts and nodes.nuts.pool and nodes.nuts.pool.latelua or (function() + local whatsit_id = node.id'whatsit' + local latelua_sub = node.subtype'late_lua' + local node_new = node.direct.new + local setfield = node.direct.setwhatsitfield or node.direct.setfield + return function(f) + local n = node_new(whatsit_id, latelua_sub) + setfield(n, 'data', f) + return n + end + end)() local node_write = node.direct.write luacmd("__sys_shell_shipout:e", function() local cmd = scan_string() - local n = node_new(whatsit_id, latelua_sub) - setfield(n, 'data', function() shellescape(cmd) end) - node_write(n) + node_write(new_latelua(function() shellescape(cmd) end)) end, "global", "protected") end local gettimeofday = os.gettimeofday @@ -344,9 +415,10 @@ do local get_command = token.get_command local get_index = token.get_index local get_mode = token.get_mode or token.get_index - local cmd = token.command_id + local cmd = command_id local set_font = cmd'get_font' - local biggest_char = token.biggest_char() + local biggest_char = token.biggest_char and token.biggest_char() + or status.getconstants().max_character_code local mode_below_biggest_char = {} local index_not_nil = {} @@ -355,29 +427,29 @@ do [cmd'left_brace'] = true, [cmd'right_brace'] = true, [cmd'math_shift'] = true, - [cmd'mac_param'] = mode_below_biggest_char, - [cmd'sup_mark'] = true, - [cmd'sub_mark'] = true, - [cmd'endv'] = true, + [cmd'mac_param' or cmd'parameter'] = mode_below_biggest_char, + [cmd'sup_mark' or cmd'superscript'] = true, + [cmd'sub_mark' or cmd'subscript'] = true, + [cmd'endv' or cmd'ignore'] = true, [cmd'spacer'] = true, [cmd'letter'] = true, [cmd'other_char'] = true, - [cmd'tab_mark'] = mode_below_biggest_char, + [cmd'tab_mark' or cmd'alignment_tab'] = mode_below_biggest_char, [cmd'char_given'] = true, - [cmd'math_given'] = true, - [cmd'xmath_given'] = true, + [cmd'math_given' or 'math_char_given'] = true, + [cmd'xmath_given' or 'math_char_xgiven'] = true, [cmd'set_font'] = mode_not_null, [cmd'undefined_cs'] = true, [cmd'call'] = true, - [cmd'long_call'] = true, - [cmd'outer_call'] = true, - [cmd'long_outer_call'] = true, - [cmd'assign_glue'] = index_not_nil, - [cmd'assign_mu_glue'] = index_not_nil, - [cmd'assign_toks'] = index_not_nil, - [cmd'assign_int'] = index_not_nil, - [cmd'assign_attr'] = true, - [cmd'assign_dimen'] = index_not_nil, + [cmd'long_call' or cmd'protected_call'] = true, + [cmd'outer_call' or cmd'tolerant_call'] = true, + [cmd'long_outer_call' or cmd'tolerant_protected_call'] = true, + [cmd'assign_glue' or cmd'register_glue'] = index_not_nil, + [cmd'assign_mu_glue' or cmd'register_mu_glue'] = index_not_nil, + [cmd'assign_toks' or cmd'register_toks'] = index_not_nil, + [cmd'assign_int' or cmd'register_int'] = index_not_nil, + [cmd'assign_attr' or cmd'register_attribute'] = true, + [cmd'assign_dimen' or cmd'register_dimen'] = index_not_nil, } luacmd("__token_if_primitive_lua:N", function() @@ -396,3 +468,131 @@ do and (get_mode(tok) > biggest_char and true_tok or false_tok)) end, "global") end +-- File: l3intarray.dtx +luacmd('__intarray:w', function() + scan_int() + tex.error'LaTeX Error: Isolated intarray ignored' +end, 'protected', 'global') + +local scan_token = token.scan_token +local put_next = token.put_next +local intarray_marker = token_create_safe'__intarray:w' +local use_none = token_create_safe'use_none:n' +local use_i = token_create_safe'use:n' +local expand_after_scan_stop = {token_create_safe'exp_after:wN', + token_create_safe'scan_stop:'} +local comma = token_create(string.byte',') +local __intarray_table do + local tables = get_luadata and get_luadata'__intarray' or {[0] = {}} + function __intarray_table() + local t = scan_token() + if t ~= intarray_marker then + put_next(t) + tex.error'LaTeX Error: intarray expected' + return tables[0] + end + local i = scan_int() + local current_table = tables[i] + if current_table then return current_table end + current_table = {} + tables[i] = current_table + return current_table + end + if register_luadata then + register_luadata('__intarray', function() + local t = "{[0]={}," + for i=1, #tables do + t = string.format("%s{%s},", t, table.concat(tables[i], ',')) + end + return t .. "}" + end) + end +end + +local sprint = tex.sprint + +luacmd('__intarray_gset_count:Nw', function() + local t = __intarray_table() + local n = scan_int() + for i=#t+1, n do t[i] = 0 end +end, 'protected', 'global') + +luacmd('intarray_count:N', function() + sprint(-2, #__intarray_table()) +end, 'global') +luacmd('__intarray_gset:wF', function() + local i = scan_int() + local t = __intarray_table() + if t[i] then + t[i] = scan_int() + put_next(use_none) + else + tex.count.l__intarray_bad_index_int = i + scan_int() + put_next(use_i) + end +end, 'protected', 'global') + +luacmd('__intarray_gset:w', function() + local i = scan_int() + local t = __intarray_table() + t[i] = scan_int() +end, 'protected', 'global') +luacmd('intarray_gzero:N', function() + local t = __intarray_table() + for i=1, #t do + t[i] = 0 + end +end, 'global', 'protected') +luacmd('__intarray_item:wF', function() + local i = scan_int() + local t = __intarray_table() + local item = t[i] + if item then + put_next(use_none) + else + tex.l__intarray_bad_index_int = i + put_next(use_i) + end + put_next(expand_after_scan_stop) + scan_token() + if item then + sprint(-2, item) + end +end, 'global') + +luacmd('__intarray_item:w', function() + local i = scan_int() + local t = __intarray_table() + sprint(-2, t[i]) +end, 'global') +local concat = table.concat +luacmd('__intarray_to_clist:Nn', function() + local t = __intarray_table() + local sep = token.scan_string() + sprint(-2, concat(t, sep)) +end, 'global') +luacmd('__intarray_range_to_clist:w', function() + local t = __intarray_table() + local from = scan_int() + local to = scan_int() + sprint(-2, concat(t, ',', from, to)) +end, 'global') +luacmd('__intarray_gset_range:w', function() + local from = scan_int() + local t = __intarray_table() + while true do + local tok = scan_token() + if tok == comma then + repeat + tok = scan_token() + until tok ~= comma + break + else + put_next(tok) + end + t[from] = scan_int() + scan_token() + from = from + 1 + end + end, 'global', 'protected') diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3.sty b/Master/texmf-dist/tex/latex/l3kernel/expl3.sty index 068438f51d7..eb2ccfa77a1 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3.sty @@ -19,7 +19,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx -\def\ExplFileDate{2021-11-12}% +\def\ExplFileDate{2021-11-22}% \let\ExplLoaderFileDate\ExplFileDate \ProvidesPackage{expl3} [% |