Skip to content

comp.ts sheds 468 tokens, so the next changes fit under its cap - #1509

Merged
nicolas-abril merged 5 commits into
bendlang:mainfrom
viridale:comp-token-trim
Oct 12, 2026
Merged

nicolas-abril merged 5 commits into
bendlang:mainfrom
viridale:comp-token-trim

Conversation

@viridale

@viridale viridale commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

comp.ts is at 63,929 of its 64,000 ttok cap with ttok 0.3, which CI pins. With ttok 1.0 it is over the cap, at 64,098. This PR frees 468 tokens without changing what any program prints, so the next fix has room. comp.ts ends at 63,461 with ttok 0.3 and 63,637 with ttok 1.0.

It takes over #1479's token commit, so that all the trimming lives in one PR. Once this merges, #1479 can be the fix alone.

Commits

  • 3b4a864e is fix(cpu): deal a slow grow's forks to idle threads (#1475) #1479's a7e927ed, cherry-picked onto today's main without conflicts. It saves 250 tokens:
    • File and Scope become ReturnType<typeof file_new> and ReturnType<typeof scope_new>.
    • pool_rows' drain loop drops !err_seen(e.mem). The loop runs only on the host, where that test is always false.
    • task_deal computes its cursor start in one expression.
    • The f32 show and read operations use tpl_ops.
    • src_add uses memo.
  • 707eba89 is new. It saves 181 tokens:
    • File spreads its book (...book) instead of holding it, so FL.book.tlds becomes FL.tlds across 50 lines (−52). The spread is safe: tmps is a record mutated in place, only the checker bumps hols, and io_base already spreads a book.
    • Seg is ReturnType<typeof seg_new> (−40). spin and fork now start false instead of absent, so emit_jump's bang defaults to false.
    • ctr_take copies a node's fields in one loop from term_peek, which is term_loc for an unshared node (−38).
    • The TODO(#1105) comment in js_marshal is deleted (−37). The error string right below it says the same and names the issue.
    • term_peek and blk_read each return a ternary (−14).
  • 6a663300 fixes or cuts five comments. It saves 37 tokens:
    • The C and JS show comments both said show_chr escapes "as char_show". bend.ts no longer has a char_show (it is now chr_show, inside term_show), and both comments already say the output matches term_show, so the clause goes.
    • The show descriptor comment now lists Char's boxed flag, which show_main writes and the C show_val reads.
    • "EPIPE ends the program by SIGPIPE" above io_lost restated its three lines.
    • The note on let FL: File repeated the File comment.

ReturnType for record types is new to comp.ts; #1479 introduced it. If you'd rather keep hand-written types, File, Scope and Seg would cost back about 235 of the 468 tokens.

What I ran

  • JS: for all 899 runnable tests, the generated .js and .mjs match main's byte for byte, except for the one runtime comment line 6a663300 shortens. The build messages are identical.
  • C: every generated file differs from main's by the same five hunks: term_peek, ctr_take, blk_read, task_deal and pool_rows, plus 6a663300's comment lines.
  • 6a663300 changes only comments, so I didn't rerun the suite for it. I built one test (show/char_unicode) to C and JS before and after it: only comment lines differ.
  • Codegen: with Apple clang at -O3 (queens, raytrace, tree-radix):
    • term_peek and blk_read compile to identical assembly.
    • The ctr_take merge keeps the same loads and stores, with one more conditional branch per program.
    • Alternating SEQ-CPU runs, 5 each, show no difference. Median user time, before → after: queens 8.45 → 8.44 s, raytrace 7.49 → 7.49 s.
  • Tests:
    • --checkup (check and interpret) over all 1,602 test modules prints the same as main.
    • Every C-lane test was built and run on this Mac, with Metal for the bang tests: 746 pass.
    • 123 tests are refused at build, exactly as on main, because main's type can't be printed.
    • gfx_window and gfx_clicks fail as on main: they expect "no display", but a window opens on this desktop.
  • Types: tsc reports no new errors.
  • Repo gate: gates/repo.ts passes 54/54 with ttok 0.3. With ttok 1.0 it flags only bendtt.lean (64,192), which this PR doesn't touch.
  • Not run: the cluster gates, Linux and CUDA. The perf gate is the real check on ctr_take.

…ew and scope_new, and four small cuts

- `File` and `Scope` were each a record type that repeated, field by field,
  the object `file_new` and `scope_new` build. They are now
  `ReturnType<typeof file_new>` and `ReturnType<typeof scope_new>`, and each
  initializer carries its field's type (`new Map<Name, Fun>()`, `[] as Seg[]`).
- `pool_rows`' drain loop drops `!err_seen(e.mem)`: the loop runs only on
  the host, where `err_seen` is `DEVICE && ...`, always false.
- `task_deal` computes its cursor start in one expression.
- The f32 `show` and `read` operations use `tpl_ops`, as the table's other
  families do.
- `src_add` uses `memo`.

Every test's JS is byte-identical; the C differs only in `task_deal` and
`pool_rows`. comp.ts: 63,929 -> 63,679 ttok (ttok 0.3, as CI counts).
…ype from seg_new, and three smaller cuts

- `File` spreads its book instead of holding it, so `FL.book.tlds` is now
  `FL.tlds` (50 lines). The book's mutable parts survive the spread: `tmps`
  is a record mutated in place, and only the checker bumps `hols`. `io_base`
  already spreads a book.
- `Seg` is `ReturnType<typeof seg_new>`, as `File` and `Scope` are. `spin`
  and `fork` now start false instead of absent, so `emit_jump`'s `bang`
  defaults to false.
- `ctr_take` copies a node's fields in one loop from `term_peek`, which is
  `term_loc` for an unshared node, instead of one loop per case.
- `term_peek` and `blk_read` each return a ternary.
- The TODO(bendlang#1105) comment in `js_marshal` goes: the error string below it
  says the same and names the issue.

Every test's JS is byte-identical; the C differs only in `term_peek`,
`ctr_take` and `blk_read`. comp.ts: 63,679 -> 63,498 ttok (ttok 0.3).
@viridale

Copy link
Copy Markdown
Contributor Author

One issue with the instruction to keep these files under a certain token count is that we're right on the edge for comp.ts but some fixes may take it over. Then agents start looking to do accessory code golfing and muddle PR intent to bring it back under 64k tokens. This is going to be a continual issue, so at the very least making some independent attempts to reduce tokens feels like a worthwhile task

…d io_lost and a duplicate FL note; the show descriptor names Char's boxed flag
@viridale viridale changed the title comp.ts sheds 431 tokens, so the next changes fit under its cap comp.ts sheds 468 tokens, so the next changes fit under its cap Oct 12, 2026
…m ReturnType

File is Bend.Book & {...}, since it spreads its book; Seg's spin and fork
are booleans, since seg_new sets them. file_new, scope_new and seg_new
declare their return types. Transpiled comp.ts is byte-identical.
@nicolas-abril

Copy link
Copy Markdown
Collaborator

Unsupervised AI review (via Unii, on behalf of @nicolas): may be wrong.

Pushed a3367cc on top: File, Scope and Seg are hand-written types again; comp.ts does not use ReturnType or functions without a declared return type.

  • File is Bend.Book & { ... }, since it now spreads its book (main's fields minus book).
  • Seg has spin: boolean; fork: boolean, matching this PR's seg_new.
  • file_new, scope_new and seg_new declare : File, : Scope, : Seg; the explicit generics and as casts go.

comp.ts: 63,461 → 63,704 ttok (main 63,929, so still −225). Bun's transpile of comp.ts is byte-identical to the PR head, so emitted C/JS and perf are unchanged. tsc --strict reports the same 12 pre-existing errors. Gates on macOS: repo 54/54, test 1602/1602.

@nicolas-abril

Copy link
Copy Markdown
Collaborator

Pushed a commit on top:

  • File holds its book in a book field again instead of being Bend.Book & {...}; every FL.tlds/FL.ctrs/FL.order and Bend.*(FL, ...) call goes back to FL.book.
  • term_peek, blk_read and task_deal keep their if statements; the ternaries are undone.

comp.ts is now 63,787 ttok (main 63,929). Gates: repo 54/54, test 1602/1602. tsc shows the same 12 errors that were already there.

Unsupervised AI review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants