engine: \@ifnextchar halves ## in the branch it picks, and package names expand - #99
Merged
Conversation
…mes expand Two defects that turn out to be one story: no beamer theme had ever been loaded, and every keyval value was silently lost. 1. \@ifnextchar does not INSERT the branch it picks — it stores it first. ltdefns.dtx: \long\def\@ifnextchar#1#2#3{\let\reserved@d=#1 \def\reserved@a{#2}\def\reserved@b{#3}\futurelet\@let@token\@ifnch} and \def\reserved@b{#3} SCANS the branch as a macro body, which halves ## a second time (tex.web §479: a # followed by a # stores one #). This engine's \@ifnextchar is a primitive that inserted the branch verbatim, skipping it. keyval is built on exactly that: \def\define@key#1#2{\@ifnextchar[{\KV@def{#1}{#2}}{\long\@namedef{KV@#1@#2}####1}} The #### is halved once into \define@key's own body and a second time by \@ifnextchar, leaving the one # that \def reads as the parameter text #1. Without it the generated macro's parameter text was ##1 and bound nothing: \setkeys{fam}{k=VAL} gave <<>>. Real LaTeX gives \long macro:#1-><<#1>> where this engine gave macro:##1-><<#1>>. \@ifstar and \@ifnextbracket pick their branch the same way and are halved for the same reason. 2. \usepackage, \documentclass and \LoadClass now EXPAND their {name}. Checked in one line: \def\nm{marker}\usepackage{zz\nm} loads zzmarker.sty in real LaTeX and loaded nothing here. beamer builds every theme file name that way — \beamer@calltheme does \usepackage[{#1}]{beamertheme\beamer@themename} — so \usetheme{default} asked for a package literally named "beamertheme\beamer@themename". Together: the frametitle template (beamerouterthemedefault.sty) finally exists, so a FRAME TITLE renders; and because key values no longer leak, the theme files stop contributing four pages of debris. On the minimal document that is exactly the reference — n frames make n pages, title and body both present, page 364.2x273.15. Measured over 200 real beamer talks: 0 content lost, pages 1061 -> 1095, vector paths 155106 -> 174863. Eight documents stop producing a sized page and each was checked by hand: four are corpus FRAGMENTS with no \begin{document} (0 pages is what real LaTeX gives them), one is a talk with no frame at all, one is a fragile frame whose verbatim body this engine cannot render either way, one is unchanged when re-run cold, and one (039a234b02c5…) trips the runaway guard on main TOO — the guard now fires sooner, so 40KB of debris becomes none. Over 200 arXiv papers: the single apparent loss renders 2.46MB in both binaries when re-run cold; it had exceeded the sweep's time cap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects that turn out to be one story: no beamer theme had ever been loaded,
and every keyval value was silently lost.
1.
\@ifnextcharmust halve##in the branch it picksIt does not insert the branch — it stores it first.
ltdefns.dtx:and
\def\reserved@b{#3}scans the branch as a macro body, which halves##asecond time (
tex.web§479: a#followed by a#stores one#). This engine's\@ifnextcharis a primitive that inserted the branch verbatim, skipping it.keyval is built on exactly that:
The
####is halved once into\define@key's own body and a second time by\@ifnextchar, leaving the one#that\defreads as the parameter text#1.Without it the generated macro's parameter text was
##1and bound nothing —\setkeys{fam}{k=VAL}gave<<>>.\meaning\KV@fam@k\long macro:#1-><<#1>>macro:##1-><<#1>>macro:#1-><<#1>>\@ifstarand\@ifnextbracketpick their branch the same way and are halved forthe same reason (
\def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}).2. Package names expand
\usepackage,\documentclassand\LoadClassnow expand their{name}.Checked in one line:
\def\nm{marker}\usepackage{zz\nm}loadszzmarker.styinreal LaTeX and loaded nothing here. beamer builds every theme file name that way —
\beamer@callthemedoes\usepackage[{#1}]{beamertheme\beamer@themename}— so\usetheme{default}asked for a package literally namedbeamertheme\beamer@themename.Together
The
frametitletemplate lives inbeamerouterthemedefault.sty, so it finallyexists and a frame title renders; and because key values no longer leak, the
theme files stop contributing four pages of debris. On the minimal document that is
exactly the reference:
Measured, including every apparent loss
200 beamer talks: 0 content lost, pages 1061 → 1095, vector paths
155 106 → 174 863. Eight documents stop producing a sized page; each was checked by
hand:
\begin{document}— 0 pages is what realLaTeX gives them;
[fragile]frame whose verbatim body this engine cannot rendereither way — debris before, less debris after;
039a234b02c5…) trips the runaway guard onmaintoo — the guard nowfires sooner, so 40 KB of debris becomes none.
200 arXiv papers: the single apparent loss renders 2.46 MB in both binaries
when re-run cold — it had simply exceeded the sweep's 90 s cap.