commit 2bbbf9a2dc5e86a04ae7b7d098468ed1d9a83c2b
parent 62c9827179c9a468db0706658e1637274d23c454
Author: robert <robertrussell.72001@gmail.com>
Date: Fri, 17 Dec 2021 15:36:04 -0800
Generalize stacks to queues
Diffstat:
| M | loop.tex | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++------ |
| A | queue.tex | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | stack.tex | | | 55 | ------------------------------------------------------- |
| M | util.tex | | | 1 | + |
4 files changed, 108 insertions(+), 61 deletions(-)
diff --git a/loop.tex b/loop.tex
@@ -1,3 +1,4 @@
+% 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).
@@ -7,7 +8,7 @@
\def\@iterate{\@body\ea\@iterate\fi}
% Loops that can be nested use this stack.
-\newstack\@loopstack
+\newq\@loopstack
\newcount\@forcnt
\newcount\@forlim
@@ -34,10 +35,10 @@
\pushcount\@loopstack\@forstep
}
\def\@forrestore{%
- \popcount\@loopstack \@forstep=\pcount
- \popcount\@loopstack \@forlim=\pcount
- \popcount\@loopstack \@forcnt=\pcount
- \poptok\@loopstack \let\@body=\ptok
+ \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}}
@@ -45,9 +46,48 @@
\pushtok\@loopstack\@body
\long\gdef\@body#2{#3\futurelet\@next\@foreachB}%
\@body#1\@foreachend
- \poptok\@loopstack \let\@body=\ptok
+ \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
@@ -0,0 +1,61 @@
+\newcount\@qn
+\newcount\@qt
+\newcount\qcount
+\newdimen\qdimen
+\newskip\qskip
+\newmuskip\qmuskip
+\newbox\qbox
+\newtoks\qtoks
+
+% TODO make expandable with immediateassignment?
+% TODO option to avoid all \deferasn's to improve performance?
+% \def\@pushcount{\penalty\pcount} % \afterassignment this, instead of deferasn
+
+\newif\if@qapp \@qappfalse
+\newif\if@qpeek \@qpeekfalse
+\protected\def\newq#1{\newbox#1\g\setbox#1=\hbox{\penalty0}}
+\def\@qop#1{%
+ \g\setbox\@qn=\hbox{\unhbox\@qn \g\@qt=\lastpenalty \unpenalty}%
+ \g\setbox\@qn=\hbox{%
+ \if@qapp \unhbox\@qn \fi
+ #1%
+ \unhbox\@qn % no op iff @qapp is true
+ \penalty\@qt
+ }%
+}
+\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=}
+\protected\def\pretoks {\deferasn{\@qq{\xcsdef\@qcs{\the\qtoks}\gincr\@qt}\g\qtoks=}\@qn=}
+\protected\def\pretok {\deferasn{\@qq{\gcslet\@qcs\qtok\gincr\@qt}\glet\qtok=}\@qn=}
+
+\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 \pretoks}
+\protected\def\pushtok {\@qapptrue \pretok}
+
+\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\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}
+
+\endinput
diff --git a/stack.tex b/stack.tex
@@ -1,55 +0,0 @@
-\newcount\@stackn
-\newcount\pcount
-\newdimen\pdimen
-\newskip\pskip
-\newmuskip\pmuskip
-\newbox\pbox
-\newtoks\ptoks
-\let\@stacktokn=\countA
-
-% TODO make expandable with immediateassignment?
-
-\protected\def\newstack#1{\newbox#1\global\setbox#1=\hbox{\penalty0}}
-\def\@stackop#1{%
- \global\setbox\@stackn=\hbox{%
- \unhbox\@stackn
- \@stacktokn=\lastpenalty \unpenalty
- #1%
- \penalty\@stacktokn
- }%
-}
-\def\@stackcs{stack:\the\@stackn:\the\@stacktokn}
-\def\@push#1#2{\deferasn{\deferasn{\@stackop{#2}}\global#1}\@stackn=}
-\def\@pop#1{\deferasn{\@stackop{#1}}\@stackn=}
-\def\isstackempty{%
- \deferasn{%
- \@stackop{\global\pcount=\lastnodetype}%
- \ifnum\pcount=-1 \else \ea\unless \fi
- }\@stackn=%
-}
-
-\protected\def\pushcount{\@push\pcount{\penalty\pcount}}
-\protected\def\pushdimen{\@push\pdimen{\kern\pdimen}}
-\protected\def\pushskip{\@push\pskip{\hskip\pskip}}
-\protected\def\pushmuskip{\@push{\pskip\mutoglue}{\hskip\pskip}}
-\protected\def\pushbox{\@push{\setbox\pbox}{\box\pbox}}
-\protected\def\pushtoks{\@push\ptoks{\xcsdef\@stackcs{\the\ptoks}\incr\@stacktokn}}
-\protected\def\pushtok{\@push{\let\ptok}{\gcslet\@stackcs\ptok\incr\@stacktokn}}
-
-\protected\def\popcount{\@pop{\global\pcount\lastpenalty \unpenalty}}
-\protected\def\popdimen{\@pop{\global\pdimen\lastkern \unkern}}
-\protected\def\popskip{\@pop{\global\pskip\lastskip \unskip}}
-\protected\def\popmuskip{\@pop{\global\pmuskip\gluetomu\lastskip \unskip}}
-\protected\def\popbox{\@pop{\global\setbox\pbox\lastbox}}
-\protected\def\poptoks{\@pop{\decr\@stacktokn \gletcs\ptok\@stackcs \global\ptoks\ea{\ptok}}}
-\protected\def\poptok{\@pop{\decr\@stacktokn \gletcs\ptok\@stackcs}}
-
-\protected\def\peekcount{\@pop{\global\pcount\lastpenalty}}
-\protected\def\peekdimen{\@pop{\global\pdimen\lastkern}}
-\protected\def\peekskip{\@pop{\global\pskip\lastskip}}
-\protected\def\peekmuskip{\@pop{\global\pmuskip\gluetomu\lastskip}}
-\protected\def\peekbox{\@pop{\global\setbox\pbox\lastbox \copy\pbox}}
-\protected\def\peektoks{\@pop{{\decr\@stacktokn \gletcs\ptok\@stackcs}\global\ptoks\ea{\ptok}}}
-\protected\def\peektok{\@pop{{\decr\@stacktokn \gletcs\ptok\@stackcs}}}
-
-\endinput
diff --git a/util.tex b/util.tex
@@ -1,6 +1,7 @@
\let\bgroup={ \let\egroup=}
% Primitive abbreviations.
+\let\g=\global
\let\ea=\expandafter
\let\attr=\attribute
\let\attrdef=\attributedef