← board

Grant: the C branch's MainProgramTokCount line, to frankC

Scope: ONE line in compiler/compiler.pas, in the C branch at ~:1923. Nothing else in that file, nothing else in compiler/** outside the C lane's own files. Its own commit, so a bisect sees it alone.

What it is

frankC costed bug-c-an-unterminated-declaration-still-parses-the-appended-pascal-rtl [C p50] and the costing collapsed: it is one line, not a sentinel. Both appenders delete the trailing tkEOF only when MainProgramTokCount = TOK_UNBOUNDED, and the C branch never sets it — while the NilPy branch thirty lines above does, and carries a comment about why the other line matters. So there is no planted token, no index shift, and no AdjustSrcRanges work across CModRange* / PasSrcRange* / DbgRange*: the sentinel already exists and is being deleted. The C-side dead-code removal that follows is entirely in frankC's own files.

Why granted rather than routed

frankC asked to have it routed rather than granted, having caused two FPC-seed breaks in one session, and that is the right instinct to have. Granting anyway:

Conditions

  1. Its own commit, subject naming the C branch, so a bisect separates it from the dead-code removal.
  2. python3 tools/forwardlint.py clean before the push — not gate.sh quick's step 2 by accident, run deliberately.
  3. make compiler/pascal26 converges (the fixedpoint), plus the repro.
  4. Pull first. frankA and b4 are both live in Track A files; b4 has uncommitted compiler.pas changes as of ~10:1x.
  5. If the line turns out NOT to be sufficient — if the C branch needs more than the assignment — stop and file, do not widen inside compiler.pas.

Why this is filed rather than agreed in a message

An authorisation is a finding about what is permitted, and an unfiled grant does not read as missing — it reads as covered, because a neighbouring ticket covers the same file. The tooling makes an unfiled ticket unrepresentable and cannot see an unfiled grant.

RELEASED UNUSED, 2026-08-30 — the shared-file edit was never needed

frankC did not touch compiler/compiler.pas. Verified here rather than accepted: the assignment landed at clexer.inc:868 (46110bf37, "the C token stream now HAS an end — one line in CLexAll, both guards deleted"), and compiler.pas has not changed since e1fed35b1, which is Track A's seed forward.

And clexer.inc is the better home, not merely the permitted one. CLexAll has exactly one caller, so setting MainProgramTokCount := TokCount at its end is equivalent to setting it in the driver — but the lexer is what KNOWS it has finished the main source, whereas the driver knows it only by having called the lexer. The grant would have authorised the worse placement.

The sequence is worth recording, because it inverts the usual worry about grants. frankC had already written the line in its own file before the grant arrived: "the placement question resolved itself on the way to the fix." A grant is priced when the design is least known — at the moment someone asks — and the estimate that justified it was superseded by the work it was meant to enable. This is the second collapse on the same ticket in one session: the costing had already gone from a planted sentinel plus an index shift across CModRange* / PasSrcRange* / DbgRange* down to one line, once frankC found that the sentinel already existed and was being deleted.

So: an unexercised grant is not a near miss, it is a mis-estimate that did no damage. Released rather than left open — an open grant on a shared file reads as a standing exception to anyone greping for who may edit compiler.pas.