commit 2c4ddf29989d0268c443776e94a40a5a5a8a67fe
parent 3e176380b0cb20e7e0a4ddefdde87a75b68d4039
Author: Robert Russell <robertrussell.72001@gmail.com>
Date: Sat, 15 Apr 2023 23:46:52 -0700
Update allocator
The allocator now maintains a free list for each register type, so
we can free registers!
Implementing this nicely required splitting "util" into "basic"
and "util".
Diffstat:
| M | alloc.tex | | | 114 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
| A | basic.tex | | | 95 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | font.tex | | | 4 | ++-- |
| M | r3tex.tex | | | 1 | + |
| M | util.tex | | | 98 | ++++--------------------------------------------------------------------------- |
5 files changed, 180 insertions(+), 132 deletions(-)
diff --git a/alloc.tex b/alloc.tex
@@ -20,7 +20,9 @@
% 0--255: temporary
% 256--65535: allocated
% box:
-% 0--100: temporary
+% 0--9: temporary
+% 10--29: internal to allocator
+% 30--100: temporary
% 101--254: allocated inserts
% 255: \outputbox
% 256--65535: allocated
@@ -38,7 +40,29 @@
% 256--32767: allocated
% TODO: marks? How do eTeX marks classes work?
-\countdef\allocnum=10 \allocnum=-1
+\protected\def\newif#1{%
+ \gcsdef{\ea\@remif\csstring#1true}{\let#1=\iftrue}%
+ \gcsdef{\ea\@remif\csstring#1false}{\let#1=\iffalse}%
+ \glet#1=\iffalse
+}
+{\uccode`1=`i \uccode`2=`f \uppercase{\gdef\@remif12{}}}
+
+\newif\if@galloc
+\countdef\@allocnum=10 \@allocnum=-1
+
+\chardef\@countlist=11 \setbox\@countlist=\hbox{}
+\chardef\@dimenlist=12 \setbox\@dimenlist=\hbox{}
+\chardef\@skiplist=13 \setbox\@skiplist=\hbox{}
+\chardef\@muskiplist=14 \setbox\@muskiplist=\hbox{}
+\chardef\@boxlist=15 \setbox\@boxlist=\hbox{}
+\chardef\@tokslist=16 \setbox\@tokslist=\hbox{}
+\chardef\@readlist=17 \setbox\@readlist=\hbox{}
+\chardef\@writelist=18 \setbox\@writelist=\hbox{}
+\chardef\@famlist=19 \setbox\@famlist=\hbox{}
+\chardef\@attrlist=20 \setbox\@attrlist=\hbox{}
+\chardef\@cctablist=21 \setbox\@cctablist=\hbox{}
+\chardef\@insertlist=22 \setbox\@insertlist=\hbox{}
+
\countdef\@countnext=11 \@countnext=256 \chardef\@countmax=65535
\countdef\@dimennext=12 \@dimennext=256 \chardef\@dimenmax=65535
\countdef\@skipnext=13 \@skipnext=256 \chardef\@skipmax=65535
@@ -52,39 +76,64 @@
\countdef\@cctabnext=21 \@cctabnext=256 \chardef\@cctabmax=32767
\countdef\@insertnext=22 \@insertnext=254 \chardef\@insertmin=101
-\def\allocate#1#2#3#4#5{%
- \ifnum#3>#4%
- \errmessage{No room for a new \string#1}%
- \else
- \global\allocnum=#3%
- \global#2#5=\allocnum
- \wlog{\string#5=\string#1\the\allocnum}%
- \global\advance#31
+\def\@allocate#1#2#3#4#5#6#7#8{%
+ \gsetbox#3=\hbox{\unhbox#3\global\@allocnum=\lastpenalty \unpenalty}%
+ \ifnum\@allocnum=0
+ \ifnum#5#6#7%
+ \errmessage{No room for a new \string#1}%
+ \else
+ \global\@allocnum=#5%
+ \global#4#5%
+ \fi
\fi
+ \if@galloc\global\fi#2#8=\@allocnum
+ \@gallocfalse
+ \wlog{\string#8=\string#1\the\@allocnum}%
}
-\protected\def\newcount{\allocate\count\countdef\@countnext\@countmax}
-\protected\def\newdimen{\allocate\dimen\dimendef\@dimennext\@dimenmax}
-\protected\def\newskip{\allocate\skip\skipdef\@skipnext\@skipmax}
-\protected\def\newmuskip{\allocate\muskip\muskipdef\@muskipnext\@muskipmax}
-\protected\def\newbox{\allocate\box\chardef\@boxnext\@boxmax}
-\protected\def\newtoks{\allocate\toks\toksdef\@toksnext\@toksmax}
-\protected\def\newread{\allocate\read\chardef\@readnext\@readmax}
-\protected\def\newwrite{\allocate\write\chardef\@writenext\@writemax}
-\protected\def\newfam{\allocate\fam\chardef\@famnext\@fammax}
-\protected\def\newattr{\allocate\attr\attrdef\@attrnext\@attrmax}
-\protected\def\newcctab{\allocate\cctab\chardef\@cctabnext\@cctabmax}
+\protected\def\newcount{\@allocate\count\countdef\@countlist\incr\@countnext>\@countmax}
+\protected\def\newdimen{\@allocate\dimen\dimendef\@dimenlist\incr\@dimennext>\@dimenmax}
+\protected\def\newskip{\@allocate\skip\skipdef\@skiplist\incr\@skipnext>\@skipmax}
+\protected\def\newmuskip{\@allocate\muskip\muskipdef\@muskiplist\incr\@muskipnext>\@muskipmax}
+\protected\def\newbox{\@allocate\box\chardef\@boxlist\incr\@boxnext>\@boxmax}
+\protected\def\newtoks{\@allocate\toks\toksdef\@tokslist\incr\@toksnext>\@toksmax}
+\protected\def\newread{\@allocate\read\chardef\@readlist\incr\@readnext>\@readmax}
+\protected\def\newwrite{\@allocate\write\chardef\@writelist\incr\@writenext>\@writemax}
+\protected\def\newfam{\@allocate\fam\chardef\@famlist\incr\@famnext>\@fammax}
+\protected\def\newattr{\@allocate\attr\attrdef\@attrlist\incr\@attrnext>\@attrmax}
+\protected\def\newcctab{\@allocate\cctab\chardef\@cctablist\incr\@cctabnext>\@cctabmax}
+\protected\def\newinsert{\@allocate\insert\chardef\@insertlist\decr\@insertnext<\@insertmin}
-\protected\def\newinsert#1{%
- \ifnum\@insertnext<\@insertmin
- \errmessage{No room for a new \string\insert}%
- \else
- \global\chardef#1=\@insertnext
- \wlog{\string#1=\string\insert\the\@insertnext}%
- \global\advance\@insertnext-1
- \fi
+\protected\def\gnewcount{\@galloctrue \newcount}
+\protected\def\gnewdimen{\@galloctrue \newdimen}
+\protected\def\gnewskip{\@galloctrue \newskip}
+\protected\def\gnewmuskip{\@galloctrue \newmuskip}
+\protected\def\gnewbox{\@galloctrue \newbox}
+\protected\def\gnewtoks{\@galloctrue \newtoks}
+\protected\def\gnewread{\@galloctrue \newread}
+\protected\def\gnewwrite{\@galloctrue \newwrite}
+\protected\def\gnewfam{\@galloctrue \newfam}
+\protected\def\gnewattr{\@galloctrue \newattr}
+\protected\def\gnewcctab{\@galloctrue \newcctab}
+\protected\def\gnewinsert{\@galloctrue \newinsert}
+
+\def\@free#1#2#3{%
+ \gsetbox#1=\hbox{\unhbox#1\penalty#2#3}%
}
+\protected\def\freecount{\@free\@countlist\regnum}
+\protected\def\freedimen{\@free\@dimenlist\regnum}
+\protected\def\freeskip{\@free\@skiplist\regnum}
+\protected\def\freemuskip{\@free\@muskiplist\regnum}
+\protected\def\freebox{\@free\@boxlist{}}
+\protected\def\freetoks{\@free\@tokslist\regnum}
+\protected\def\freeread{\@free\@readlist{}}
+\protected\def\freewrite{\@free\@writelist{}}
+\protected\def\freefam{\@free\@famlist{}}
+\protected\def\freeattr{\@free\@attrlist\regnum}
+\protected\def\freecctab{\@free\@cctablist{}}
+\protected\def\freeinsert{\@free\@insertlist{}}
+
% Temporaries of various types:
% TODO: distinguish between local and global temporaries?
\countdef\countA=30 \countdef\countB=31 \countdef\countC=32
@@ -95,11 +144,4 @@
\toksdef\toksA=30 \toksdef\toksB=31 \toksdef\toksC=32
% temporary control sequences: csA csB csC ...
-\protected\def\newif#1{%
- \gcsdef{\ea\@remif\csstring#1true}{\let#1=\iftrue}%
- \gcsdef{\ea\@remif\csstring#1false}{\let#1=\iffalse}%
- \global\let#1=\iffalse
-}
-{\uccode`1=`i \uccode`2=`f \uppercase{\gdef\@remif12{}}}
-
\endinput
diff --git a/basic.tex b/basic.tex
@@ -0,0 +1,95 @@
+% Primitive abbreviations
+\let\ea=\expandafter
+\let\nx=\noexpand
+\let\attr=\attribute
+\let\attrdef=\attributedef
+\let\cctab=\catcodetable
+\let\initcctab=\initcatcodetable
+\let\savecctab=\savecatcodetable
+\let\begcs=\csname
+\let\endcs=\endcsname
+\let\ifcs=\ifcsname
+\let\beggroup=\begingroup
+\let\easn=\immediateassignment
+
+% Primitive aliases
+\let\rescan=\scantextokens
+\let\endgraf=\par
+\let\endline=\cr
+\def\null{\hbox{}}
+
+% Special character aliases
+\chardef\%=`\%
+\chardef\&=`\&
+\chardef\#=`\#
+\chardef\$=`\$
+\chardef\~=`\~
+
+% Misc, mostly from plain
+\let\bgroup={
+\let\egroup=}
+\def\empty{}
+\def\space{ }
+\def\tab{^^I}
+\def\nosurround{\mathsurround=0pt } % XXX: \mathsurroundskip and \mathsurroundmode
+\def\m@th{\errmessage{m@th is deprecated}} % TODO: remove
+
+% Expansion control
+\def\eonce#1{\unexpanded\ea{#1}}
+% XXX: are these useful?
+\def\deferfi#1#2\fi{#2\fi#1}
+\def\afterfi#1\fi{\fi#1}
+\def\jumpfi#1#2\fi{\fi#1}
+
+% Expandable macro to get the number of a defined register. E.g.,
+% \countdef\mycount=255
+% \regnum\mycount -> 255
+\def\@regnum#1#2\@END{%
+ \ifx\relax#1\else
+ \ifnum1<1#1 #1\fi % Check if #1 is a digit.
+ \@regnum#2\@END
+ \fi
+}
+\def\regnum#1{\ea\@regnum\meaning#1\relax\@END\relax}
+
+{\catcode`\p=12 \catcode`\t=12 \gdef\csA#1pt{#1}}
+\let\rempt=\csA
+\def\decimal{\ea\rempt\the}
+
+% Caution: \incr\count0 does not do what you'd hope. We use the "by" keyword
+% to catch this error.
+\protected\def\incr#1{\advance#1by1 }
+\protected\def\gincr{\global\incr}
+\protected\def\decr#1{\advance#1by-1 }
+\protected\def\gdecr{\global\decr}
+
+\def\gsetbox{\global\setbox}
+
+\def\cs#1{\begcs#1\endcs}
+
+\protected\def\csdef#1{\ea\def\begcs#1\endcs}
+\protected\def\ecsdef#1{\ea\edef\begcs#1\endcs}
+\protected\def\gcsdef#1{\ea\gdef\begcs#1\endcs}
+\protected\def\xcsdef#1{\ea\xdef\begcs#1\endcs}
+\protected\def\undef#1{\let#1\@undefined}
+\protected\def\gundef#1{\glet#1\@undefined}
+
+\protected\def\cslet#1{\ea\let\begcs#1\endcs}
+\protected\def\gcslet#1{\ea\glet\begcs#1\endcs}
+\protected\def\letcs#1#2{\ea\let\ea#1\begcs#2\endcs}
+\protected\def\gletcs#1#2{\ea\glet\ea#1\begcs#2\endcs}
+\protected\def\csletcs#1#2{\ea\let\begcs#1\ea\endcs\begcs#2\endcs}
+\protected\def\gcsletcs#1#2{\ea\glet\begcs#1\ea\endcs\begcs#2\endcs}
+
+\def\swap#1#2{#2#1}
+\def\selectx#1{} % \gobble
+\def\selecto#1{#1}
+\def\selectxx#1#2{} % \gobbletwo
+\def\selectox#1#2{#1} % \firstoftwo
+\def\selectxo#1#2{#2} % \secondoftwo
+\def\selectxxx#1#2#3{}
+\def\selectoxx#1#2#3{#1}
+\def\selectxox#1#2#3{#2}
+\def\selectxxo#1#2#3{#3}
+
+\endinput
diff --git a/font.tex b/font.tex
@@ -113,7 +113,7 @@
}
\def\Fupdatedelim#1#2{%
- \setbox\boxA=\vbox{\hbox{$\m@th#2$}\kern0pt}%
+ \setbox\boxA=\vbox{\hbox{$\nosurround#2$}\kern0pt}%
#1=\dimexpr\ht\boxA/2 + \fontdimen22 \textfont2\relax
}
@@ -364,7 +364,7 @@
\Fdef\csA\FSmpalsy\dimexpr\Ftsize+1.5pt\relax \textfont2=\csA
\Fdef\csA\FSmpalsy\dimexpr\Fssize+1.5pt\relax \scriptfont2=\csA
\Fdef\csA\FSmpalsy\dimexpr\Fzsize+1pt\relax \scriptscriptfont2=\csA
- $\m@th\sty#1\mathchar"029B$%
+ $\nosurround\sty#1\mathchar"029B$%
}}
\mathchardef\neq="3E3C
\Umathchardef\notin="3"12"3C
diff --git a/r3tex.tex b/r3tex.tex
@@ -1,5 +1,6 @@
\input catcode % plain-like catcode initialization
\input primitive % LuaTeX primitives, pdfTeX compatibility
+\input basic
\input alloc
\input debug % utilities for debugging
\input util
diff --git a/util.tex b/util.tex
@@ -1,38 +1,3 @@
-% Primitive abbreviations
-\let\ea=\expandafter
-\let\nx=\noexpand
-\let\attr=\attribute
-\let\attrdef=\attributedef
-\let\cctab=\catcodetable
-\let\initcctab=\initcatcodetable
-\let\savecctab=\savecatcodetable
-\let\begcs=\csname
-\let\endcs=\endcsname
-\let\ifcs=\ifcsname
-\let\beggroup=\begingroup
-\let\easn=\immediateassignment
-
-% Primitive aliases
-\let\rescan=\scantextokens
-\let\endgraf=\par
-\let\endline=\cr
-\def\null{\hbox{}}
-
-% Special character aliases
-\chardef\%=`\%
-\chardef\&=`\&
-\chardef\#=`\#
-\chardef\$=`\$
-\chardef\~=`\~
-
-% Misc, mostly from plain
-\let\bgroup={
-\let\egroup=}
-\def\empty{}
-\def\space{ }
-\def\tab{^^I}
-\def\m@th{\mathsurround=0pt } % XXX: \mathsurroundskip and \mathsurroundmode
-
% Special constants
\chardef\maxchar=1114111
\newcount\maxcount \maxcount="7FFFFFFF
@@ -40,49 +5,6 @@
\newskip\centering \centering=0pt plus1000pt minus1000pt
\newbox\voidbox
-% Expansion control
-\def\eonce#1{\unexpanded\ea{#1}}
-% XXX: are these useful?
-\def\deferfi#1#2\fi{#2\fi#1}
-\def\afterfi#1\fi{\fi#1}
-\def\jumpfi#1#2\fi{\fi#1}
-
-% Expandable macro to get the number of a defined register. E.g.,
-% \countdef\mycount=255
-% \regnum\mycount -> 255
-\def\@regnum#1#2\@END{%
- \ifx\relax#1\else
- \ifnum1<1#1 #1\fi % Check if #1 is a digit.
- \@regnum#2\@END
- \fi
-}
-\def\regnum#1{\ea\@regnum\meaning#1\relax\@END\relax}
-
-% Caution: \incr\count0 does not do what you'd hope. We use the "by" keyword
-% to catch this error.
-\protected\def\incr#1{\advance#1by1 }
-\protected\def\gincr{\global\incr}
-\protected\def\decr#1{\advance#1by-1 }
-\protected\def\gdecr{\global\decr}
-
-\def\gsetbox{\global\setbox}
-
-\def\cs#1{\begcs#1\endcs}
-
-\protected\def\csdef#1{\ea\def\begcs#1\endcs}
-\protected\def\ecsdef#1{\ea\edef\begcs#1\endcs}
-\protected\def\gcsdef#1{\ea\gdef\begcs#1\endcs}
-\protected\def\xcsdef#1{\ea\xdef\begcs#1\endcs}
-\protected\def\undef#1{\let#1\@undefined}
-\protected\def\gundef#1{\glet#1\@undefined}
-
-\protected\def\cslet#1{\ea\let\begcs#1\endcs}
-\protected\def\gcslet#1{\ea\glet\begcs#1\endcs}
-\protected\def\letcs#1#2{\ea\let\ea#1\begcs#2\endcs}
-\protected\def\gletcs#1#2{\ea\glet\ea#1\begcs#2\endcs}
-\protected\def\csletcs#1#2{\ea\let\begcs#1\ea\endcs\begcs#2\endcs}
-\protected\def\gcsletcs#1#2{\ea\glet\begcs#1\ea\endcs\begcs#2\endcs}
-
% \defevent defines an "event". Hooks can be attached to events with \addhook,
% and all hooks are run in order when the event is triggered with \event.
% Events can have parameters like macros, and hooks have access to these
@@ -107,17 +29,6 @@
}
\protected\def\addhook[#1]#2{\cs{hooks:#1}\ea{\the\cs{hooks:#1}#2}}
-\def\swap#1#2{#2#1}
-\def\selectx#1{} % \gobble
-\def\selecto#1{#1}
-\def\selectxx#1#2{} % \gobbletwo
-\def\selectox#1#2{#1} % \firstoftwo
-\def\selectxo#1#2{#2} % \secondoftwo
-\def\selectxxx#1#2#3{}
-\def\selectoxx#1#2#3{#1}
-\def\selectxox#1#2#3{#2}
-\def\selectxxo#1#2#3{#3}
-
% White space control
\def\^^M{\ } % control <return> = control <space>
\def\^^I{\ } % control <tab> = control <space>
@@ -162,6 +73,7 @@
% Generalized mathpalette---gives number to be used with \ifcase
\def\mathpalette#1#2{\mathchoice{#10{#2}}{#11{#2}}{#12{#2}}{#13{#2}}}
+
\protected\def\sty#1{%
\ifcase\numexpr#1\relax
\displaystyle
@@ -170,6 +82,7 @@
\or\scriptscriptstyle
\fi
}
+
\protected\def\styfont#1{%
\ifcase\numexpr#1\relax
\textfont
@@ -178,12 +91,9 @@
\or\scriptscriptfont
\fi
}
-% \styfontdimen<sty><fam><number>
-\def\styfontdimen#1#2#3{\fontdimen\numexpr#3\relax\styfont{#1}\numexpr#2\relax}
-{\catcode`\p=12 \catcode`\t=12 \gdef\csA#1pt{#1}}
-\let\rempt=\csA
-\def\decimal{\ea\rempt\the}
+% Usage: \styfontdimen<sty><fam><number>
+\def\styfontdimen#1#2#3{\fontdimen\numexpr#3\relax\styfont{#1}\numexpr#2\relax}
% \defer defers execution of the given tokens until after the current group
% (like \aftergroup, but with multiple tokens).