r3tex

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

commit 9facb33ceb7735b3597975ffd99b3462f17f958b
parent ce596b979f1dc4b8a446c9e5449aa22fae3d6f89
Author: robert <robertrussell.72001@gmail.com>
Date:   Thu,  7 Apr 2022 15:48:14 -0700

Rework queue interface

Now there is some symmetry between pushing and popping. Also, queue
operations should be somewhat more efficient.

Diffstat:
Acontrol.tex | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dloop.tex | 93-------------------------------------------------------------------------------
Mqueue.tex | 80++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
3 files changed, 139 insertions(+), 126 deletions(-)

diff --git a/control.tex b/control.tex @@ -0,0 +1,92 @@ +% TODO: make loops expandable with immediateassign{ment,ed}? + +% The classical Plain TeX \loop macro (approximately). +% Needs grouping to be nested. +\def\loop#1\repeat{\def\@body{#1}\@iterate} +\let\repeat=\fi +\def\@iterate{\@body\ea\@iterate\fi} + +% Loops that can be nested use this stack. +\newq\@loopstack + +\newcount\@forcnt +\newcount\@forlim +\newcount\@forstep +\def\fornum#1=#2..#3\do{\fornumstep#1=#2..#3:1\do} +\def\fornumstep#1=#2..#3:#4\do#5{% + \@forsave + \def\@body{\edef#1{\the\@forcnt}#5}% + \@forcnt=\numexpr#2\relax + \@forlim=\numexpr#3\relax + \@forstep=\numexpr#4\relax + \@forloop + \@forrestore +} +\def\@forloop{% + \ifnum\@forcnt \ifnum\@forstep<0>\else<\fi \@forlim + \@body \advance\@forcnt\@forstep \ea\@forloop + \fi +} +\def\@forsave{% + \let\qtok=\@body \pushtok\@loopstack + \qcount=\@forcnt \pushcount\@loopstack + \qcount=\@forlim \pushcount\@loopstack + \qcount=\@forstep \pushcount\@loopstack +} +\def\@forrestore{% + \popcount\@loopstack \@forstep=\qcount + \popcount\@loopstack \@forlim=\qcount + \popcount\@loopstack \@forcnt=\qcount + \poptok\@loopstack \let\@body=\qtok +} + +\def\foreach#1\do#2#{\@foreachA{#1}{#2}} +\def\@foreachA#1#2#3{% + \let\qtok\@body \pushtok\@loopstack + \gdef\@body#2{#3\futurelet\@next\@foreachB}% + \@body#1\@foreachend + \poptok\@loopstack \let\@body=\qtok +} +\def\@foreachB{\ifx\@next\@foreachend \ea\selectx \else \ea\@body \fi} +\def\@foreachend{\errmessage{this can not happen}} + +\newcount\swnum +\def\switchnum#1#{% + \qcount=\sqnum \pushcount\@loopstack \swnum=\numexpr#1\relax + \let\qtok=\case \pushtok\@loopstack \let\case=\@casenum + \@fallthroughfalse \@switchnum +} +\def\@switchnum#1{#1\@endswitch \popcount\@loopstack \swnum=\qcount} +\def\@casenum#1#{% + \if@fallthrough + \ea\@case + \else\ifnum\swnum=\numexpr#1\relax + \ea\ea\ea\@case + \else + \ea\ea\ea\selectx + \fi\fi +} + +\newdimen\swdim +\def\switchdim#1#{% + \qdimen=\swdim \pushdimen\@loopstack \swdim=\dimexpr#1\relax + \let\qtok=\case \pushtok\@loopstack \let\case=\@casedim + \@fallthroughfalse \@switchdim +} +\def\@switchdim#1{#1\@endswitch \popdimen\@loopstack \swdim=\qdimen} +\def\@casedim#1#{% + \if@fallthrough + \ea\@case + \else\ifdim\swdim=\dimexpr#1\relax + \ea\ea\ea\@case + \else + \ea\ea\ea\selectx + \fi\fi +} + +\newif\if@fallthrough +\def\@endswitch{\poptok\@loopstack \let\case=\qtok} +\def\fallthrough{\@fallthroughtrue} +\def\@case#1#2\@endswitch{\@fallthroughfalse#1\if@fallthrough#2\fi\@endswitch} + +\endinput diff --git a/loop.tex b/loop.tex @@ -1,93 +0,0 @@ -% TODO: rename loop.tex -> control.tex and add defer macros -% TODO: make loops expandable with immediateassign{ment,ed}? - -% The classical Plain TeX \loop macro (approximately). -% Needs grouping to be nested. -\def\loop#1\repeat{\def\@body{#1}\@iterate} -\let\repeat=\fi -\def\@iterate{\@body\ea\@iterate\fi} - -% Loops that can be nested use this stack. -\newq\@loopstack - -\newcount\@forcnt -\newcount\@forlim -\newcount\@forstep -\def\fornum#1=#2..#3\do{\fornumstep#1=#2..#3:1\do} -\def\fornumstep#1=#2..#3:#4\do#5{% - \@forsave - \def\@body{\edef#1{\the\@forcnt}#5}% - \@forcnt=\numexpr#2\relax - \@forlim=\numexpr#3\relax - \@forstep=\numexpr#4\relax - \@forloop - \@forrestore -} -\def\@forloop{% - \ifnum\@forcnt \ifnum\@forstep<0>\else<\fi \@forlim - \@body \advance\@forcnt\@forstep \ea\@forloop - \fi -} -\def\@forsave{% - \pushtok\@loopstack\@body - \pushcount\@loopstack\@forcnt - \pushcount\@loopstack\@forlim - \pushcount\@loopstack\@forstep -} -\def\@forrestore{% - \popcount\@loopstack \@forstep=\qcount - \popcount\@loopstack \@forlim=\qcount - \popcount\@loopstack \@forcnt=\qcount - \poptok\@loopstack \let\@body=\qtok -} - -\def\foreach#1\do#2#{\@foreachA{#1}{#2}} -\def\@foreachA#1#2#3{% - \pushtok\@loopstack\@body - \gdef\@body#2{#3\futurelet\@next\@foreachB}% - \@body#1\@foreachend - \poptok\@loopstack \let\@body=\qtok -} -\def\@foreachB{\ifx\@next\@foreachend \ea\selectx \else \ea\@body \fi} -\def\@foreachend{\errmessage{this can not happen}} - -\newcount\swnum -\def\switchnum#1#{% - \pushcount\@loopstack\swnum \swnum=\numexpr#1\relax - \pushtok\@loopstack\case \let\case=\@casenum - \@fallthroughfalse \@switchnum -} -\def\@switchnum#1{#1\@endswitch \popcount\@loopstack \swnum=\qcount} -\def\@casenum#1#{% - \if@fallthrough - \ea\@case - \else\ifnum\swnum=\numexpr#1\relax - \ea\ea\ea\@case - \else - \ea\ea\ea\selectx - \fi\fi -} - -\newdimen\swdim -\def\switchdim#1#{% - \pushdimen\@loopstack\swdim \swdim=\dimexpr#1\relax - \pushtok\@loopstack\case \let\case=\@casedim - \@fallthroughfalse \@switchdim -} -\def\@switchdim#1{#1\@endswitch \popdimen\@loopstack \swdim=\qdimen} -\def\@casedim#1#{% - \if@fallthrough - \ea\@case - \else\ifdim\swdim=\dimexpr#1\relax - \ea\ea\ea\@case - \else - \ea\ea\ea\selectx - \fi\fi -} - -\newif\if@fallthrough -\def\@endswitch{\poptok\@loopstack \let\case=\qtok} -\def\fallthrough{\@fallthroughtrue} -\def\@case#1#2\@endswitch{\@fallthroughfalse#1\if@fallthrough#2\fi\@endswitch} - -\endinput diff --git a/queue.tex b/queue.tex @@ -6,27 +6,35 @@ \newmuskip\qmuskip \newbox\qbox \newtoks\qtoks +\newif\if@qapp +\newif\if@qpeek -\newif\if@qapp \@qappfalse -\newif\if@qpeek \@qpeekfalse \protected\def\newq#1{\newbox#1\g\setbox#1=\hbox{\penalty0}} -\def\@qop#1{% +\def\@qexec{% \g\setbox\@qn=\hbox{\unhbox\@qn \g\@qt=\lastpenalty \unpenalty}% \g\setbox\@qn=\hbox{% \if@qapp \unhbox\@qn \fi - #1% + \@qop \unhbox\@qn % no op iff @qapp is true \penalty\@qt }% } +\def\@qmodify#1{\def\@qop{#1}\afterassignment\@qexec\@qn=} \def\@qcs{q:\the\@qn:\the\@qt} -\def\@qq#1{\deferasn{\@qop{#1}\@qappfalse\@qpeekfalse}} -\protected\def\precount {\deferasn{\@qq{\penalty\qcount}\g\qcount=}\@qn=} -\protected\def\predimen {\deferasn{\@qq{\kern\qdimen}\g\qdimen=}\@qn=} -\protected\def\preskip {\deferasn{\@qq{\hskip\qskip}\g\qskip=}\@qn=} -\protected\def\premuskip{\deferasn{\@qq{\hskip\mutoglue\qmuskip}\g\qmuskip=}\@qn=} -\protected\def\prebox {\deferasn{\@qq{\box\qbox}\g\setbox\qbox=}\@qn=} +\def\@qwcount {\@qmodify{\penalty\qcount}} +\def\@qwdimen {\@qmodify{\kern\qdimen}} +\def\@qwskip {\@qmodify{\hskip\qskip}} +\def\@qwmuskip{\@qmodify{\hskip\mutoglue\qmuskip}} +\def\@qwbox {\@qmodify{\box\qbox}} +\def\@qwtoks {\@qmodify{\xcsdef\@qcs{\the\qtoks}\gincr\@qt}} +\def\@qwtok {\@qmodify{\gcslet\@qcs\qtok\gincr\@qt}} + +\protected\def\precount {\@qappfalse \@qwcount} +\protected\def\predimen {\@qappfalse \@qwdimen} +\protected\def\preskip {\@qappfalse \@qwskip} +\protected\def\premuskip{\@qappfalse \@qwmuskip} +\protected\def\prebox {\@qappfalse \@qwbox} % TODO: Implement prepending of tok and toks, which have their own stacking % mechanism using \@qt. My current idea for how to implement this is to track % two integers, \@qh (head) and \@qt (tail), for the allocation of unique @@ -41,31 +49,37 @@ % \@qh - \@qt. With this compaction scheme, appends and prepends remain % constant time operations, whereas popping becomes amortized constant % (assuming that compaction happens only after pops). -% \protected\def\pretoks{?} -% \protected\def\pretok{?} -\protected\def\pushcount {\@qapptrue \precount} -\protected\def\pushdimen {\@qapptrue \predimen} -\protected\def\pushskip {\@qapptrue \preskip} -\protected\def\pushmuskip{\@qapptrue \premuskip} -\protected\def\pushbox {\@qapptrue \prebox} -\protected\def\pushtoks {\@qapptrue \deferasn{\@qq{\xcsdef\@qcs{\the\qtoks}\gincr\@qt}\g\qtoks=}\@qn=} -\protected\def\pushtok {\@qapptrue \deferasn{\@qq{\gcslet\@qcs\qtok\gincr\@qt}\glet\qtok=}\@qn=} +\protected\def\pushcount {\@qapptrue \@qwcount} +\protected\def\pushdimen {\@qapptrue \@qwdimen} +\protected\def\pushskip {\@qapptrue \@qwskip} +\protected\def\pushmuskip{\@qapptrue \@qwmuskip} +\protected\def\pushbox {\@qapptrue \@qwbox} +\protected\def\pushtoks {\@qapptrue \@qwtoks} +\protected\def\pushtok {\@qapptrue \@qwtok} + +\def\@qrcount {\@qmodify{\g\qcount\lastpenalty \if@qpeek\else\unpenalty\fi}} +\def\@qrdimen {\@qmodify{\g\qdimen\lastkern \if@qpeek\else\unkern\fi}} +\def\@qrskip {\@qmodify{\g\qskip\lastskip \if@qpeek\else\unskip\fi}} +\def\@qrmuskip{\@qmodify{\g\qmuskip\gluetomu\lastskip \if@qpeek\else\unskip\fi}} +\def\@qrbox {\@qmodify{\g\setbox\qbox\lastbox \if@qpeek\copy\qbox\fi}} +\def\@qrtoks {\@qmodify{{\if@qpeek\else\g\fi\decr\@qt \gletcs\qtok\@qcs \g\qtoks\ea{\qtok}}}} +\def\@qrtok {\@qmodify{{\if@qpeek\else\g\fi\decr\@qt \gletcs\qtok\@qcs}}} -\protected\def\popcount {\@qq{\g\qcount\lastpenalty \if@qpeek\else\unpenalty\fi}\@qn=} -\protected\def\popdimen {\@qq{\g\qdimen\lastkern \if@qpeek\else\unkern\fi}\@qn=} -\protected\def\popskip {\@qq{\g\qskip\lastskip \if@qpeek\else\unskip\fi}\@qn=} -\protected\def\popmuskip{\@qq{\g\qmuskip\gluetomu\lastskip \if@qpeek\else\unskip\fi}\@qn=} -\protected\def\popbox {\@qq{\g\setbox\qbox\lastbox \if@qpeek\copy\qbox\fi}\@qn=} -\protected\def\poptoks {\@qq{{\if@qpeek\else\g\fi\decr\@qt \gletcs\qtok\@qcs \g\qtoks\ea{\qtok}}}\@qn=} -\protected\def\poptok {\@qq{{\if@qpeek\else\g\fi\decr\@qt \gletcs\qtok\@qcs}}\@qn=} +\protected\def\popcount {\@qpeekfalse \@qrcount} +\protected\def\popdimen {\@qpeekfalse \@qrdimen} +\protected\def\popskip {\@qpeekfalse \@qrskip} +\protected\def\popmuskip{\@qpeekfalse \@qrmuskip} +\protected\def\popbox {\@qpeekfalse \@qrbox} +\protected\def\poptoks {\@qpeekfalse \@qrtoks} +\protected\def\poptok {\@qpeekfalse \@qrtok} -\protected\def\peekcount {\@qpeektrue \popcount} -\protected\def\peekdimen {\@qpeektrue \popdimen} -\protected\def\peekskip {\@qpeektrue \popskip} -\protected\def\peekmuskip{\@qpeektrue \popmuskip} -\protected\def\peekbox {\@qpeektrue \popbox} -\protected\def\peektoks {\@qpeektrue \poptoks} -\protected\def\peektok {\@qpeektrue \poptok} +\protected\def\peekcount {\@qpeektrue \@qrcount} +\protected\def\peekdimen {\@qpeektrue \@qrdimen} +\protected\def\peekskip {\@qpeektrue \@qrskip} +\protected\def\peekmuskip{\@qpeektrue \@qrmuskip} +\protected\def\peekbox {\@qpeektrue \@qrbox} +\protected\def\peektoks {\@qpeektrue \@qrtoks} +\protected\def\peektok {\@qpeektrue \@qrtok} \endinput