texlive[61121] Master/texmf-dist: l3kernel (22nov21)

commits+karl at tug.org commits+karl at tug.org
Mon Nov 22 22:19:01 CET 2021


Revision: 61121
          http://tug.org/svn/texlive?view=revision&revision=61121
Author:   karl
Date:     2021-11-22 22:19:01 +0100 (Mon, 22 Nov 2021)
Log Message:
-----------
l3kernel (22nov21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
    trunk/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex
    trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins
    trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md	2021-11-22 21:19:01 UTC (rev 61121)
@@ -7,6 +7,15 @@
 
 ## [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 @@
 - 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

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/README.md	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/README.md	2021-11-22 21:19:01 UTC (rev 61121)
@@ -1,7 +1,7 @@
 LaTeX3 Programming Conventions
 ==============================
 
-Release 2021-11-12
+Release 2021-11-22
 
 Overview
 --------

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -54,7 +54,7 @@
          {latex-team at latex-project.org}%
    }%
 }
-\date{Released 2021-11-12}
+\date{Released 2021-11-22}
 
 \pagenumbering{roman}
 \maketitle

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2021-11-12}
+\date{Released 2021-11-22}
 
 \begin{document}
 

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2021-11-12}
+\date{Released 2021-11-22}
 
 \newcommand{\TF}{\textit{(TF)}}
 

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2021-11-12}
+\date{Released 2021-11-22}
 
 \newcommand{\TF}{\textit{(TF)}}
 

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -53,7 +53,7 @@
          {latex-team at latex-project.org}%
    }%
 }
-\date{Released 2021-11-12}
+\date{Released 2021-11-22}
 
 \pagenumbering{roman}
 \maketitle

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins	2021-11-22 21:19:01 UTC (rev 61121)
@@ -78,7 +78,7 @@
         \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 @@
   \from{l3names.dtx}{package,lua}
   \from{l3sys.dtx}{package,lua}
   \from{l3token.dtx}{package,lua}
+  \from{l3intarray.dtx}{package,lua}
 }}
 
 \endbatchfile

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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 at luadata@bytecode\fi
     \directlua{require("expl3")}%
 %    \end{macrocode}
 %   As the user might be making a custom format, no assumption is made about

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -79,7 +79,7 @@
 %
 % \title{The \cls{l3doc} class}
 % \author{\Team}
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 % \maketitle
 % \tableofcontents
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -63,7 +63,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 % \maketitle
 %
 % \begin{documentation}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 % \maketitle
 %
 % \begin{documentation}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -49,7 +49,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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,10 +190,423 @@
 %    \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}
 %
@@ -200,15 +613,10 @@
 % \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: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_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} }
+      }
 %    \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,25 +872,25 @@
 % \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}
 %
@@ -489,23 +897,29 @@
 % \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}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %
@@ -370,10 +370,48 @@
 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}
 local function deprecated(table, name, func)
@@ -642,9 +680,8 @@
 % 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 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,7 +714,86 @@
 %    \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 at 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}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %
@@ -709,20 +709,26 @@
 % \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>

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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 @@
   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 @@
     [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()

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2021-11-12}
+% \date{Released 2021-11-22}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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 at 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,194 +14045,270 @@
 \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
+\int_new:N \l__intarray_loop_int
+\cs_if_exist:NTF \__intarray_gset_count:Nw
   {
-    \__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
+    \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 }
 \cs_new_protected:Npn \intarray_log:N { \__intarray_show:NN \msg_log:nnxxxx }

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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_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'
 
-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:'
+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 @@
   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 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 @@
     end
   end
 end
+local register_luadata, get_luadata
+
+if luatexbase then
+  local register = token_create'@expl at 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 @@
   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 @@
   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 @@
     [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 @@
              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')

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty	2021-11-22 21:18:21 UTC (rev 61120)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty	2021-11-22 21:19:01 UTC (rev 61121)
@@ -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}
   [%



More information about the tex-live-commits mailing list.