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:
| A | control.tex | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | loop.tex | | | 93 | ------------------------------------------------------------------------------- |
| M | queue.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