r3tex

custom LuaTeX format
git clone git://git.rr3.xyz/r3tex
Log | Files | Refs | README | LICENSE

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:
Malloc.tex | 114++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Abasic.tex | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfont.tex | 4++--
Mr3tex.tex | 1+
Mutil.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).