Skip to content

comp.ts: nothing reads emitted text, pure mains print through Bend - #1817

Open
nicolas-abril wants to merge 1 commit into
bendlang:mainfrom
nicolas-abril:comp-deslop-a
Open

nicolas-abril wants to merge 1 commit into
bendlang:mainfrom
nicolas-abril:comp-deslop-a

Conversation

@nicolas-abril

Copy link
Copy Markdown
Collaborator

The simplification half of #1601, split out so it can be reviewed apart from the compile-speed change (#1601, which goes on top of this). compile_book keeps main's loop: it emits every def again until a pass adds no fact.

comp.ts is 66,209 ttok against main's 66,000, over the 66,000 cap, so the repo gate fails (53/54) until the cap moves or 209 more come out. Test gate: 1715/1715 on the cluster.

Facts are one set

  • own, stat, ctr, type, fam, arg and open are strings in one set read through fact(), replacing Hot, FL.stat, FL.own, the brws memo and the hand-written reset of ten fields per pass. A fact that only leads to other facts is an implication (fact_when), not a dependency.
  • Each def and spin keeps its own output (segments, lends, closures), so a pass replaces a def's output instead of clearing the file's.

Nothing reads the text it emitted

  • A value carries the borrowed root of each box (Val.rs), replacing a lookup of the word's string in a scope map. A read-only walk owns its list when a sum type puts an unboxed field where another constructor has a boxed one #1805's rule (only a box roots) sits in val_new.
  • A Nat's Succs are counted on the term (nat_peel), not by regexes over emitted nat_chk(... + n).
  • A table's rows are words on both lanes, folded on values: an F32 constant keeps its bits, and an op over rows runs its JS on their values only if it calls nothing past Math.fround and Math.imul. The C lane no longer runs JS text that the JS lane printed.
  • A local is a name name_local made, not a name's shape. An op's argument is held in a local unless it is a variable or a constant (op_bare), replacing the bracket counting.
  • A JS call that waits on its callee calls the callee's entry ($$k), declared after the last def, instead of a marker rewritten by a regex over the finished program. A JS closure captures the variables free in its term. A line is indented as it is pushed.

Match arms that rebuild their scrutinee read it

  • A U32, F32, Nat or Char default arm often rebuilds its scrutinee from the bits and fields it knows. arm_self reads each such rebuild as the scrutinee itself; an arm that no longer reads its fields binds none.
  • The JS lane then needs no views (FL.views, js_view, word_u32 go).

A pure main prints through Bend code

  • It printed three ways: a descriptor of main's type built by the compiler, a C printer and a JS printer. Now a pure main of type T builds as a Bend printer of main's value: main_pure writes it as Bend source, parses it into a copy of the book and checks it. The printer writes as it goes, so a 3M-element List<U32> peaks at 49.6 MB on C as on main (49.4 MB); an Array of Data is read in place by index (Array.write on C, Array.show on JS). A pure main prints imported types too.
  • Base gains Char.quote, String.quote, F32.show.dot, U32.hex, Array.write and Array.show.
  • JS holds stdout off a terminal and writes it before a wait, an error, an exit, a File.write or at 64 KiB.

Smaller things

  • The term caches live as long as the file; the fold cache is cleared per def, as a hit costs no fuel.
  • A spin is one per def. lay_eq walks the layout DAG instead of comparing JSON. Reserved names are refused before anything else, on both lanes.

Compile time (C and JS emit, median of 5, M4 Max): boss_3d 1,127 ms on main, 587 ms here; the 35 demos and benches that build, 3.04 s → 1.89 s in total.

Verification

🤖 Generated with Claude Code

The simplification half of bendlang#1601, on main's pass loop: compile_book still
emits every def again until a pass adds no fact.

- Facts are one set of strings (own, stat, ctr, type, fam, arg, open)
  read through fact(), replacing Hot, FL.stat, FL.own, the brws memo and
  the reset of ten fields per pass; a fact that only leads to others is
  an implication (fact_when). Each def and spin keeps its own output.
- A value carries the borrowed root of each box (Val.rs); a Nat's Succs
  are counted on the term (nat_peel); a table's rows are words on both
  lanes, folded on values, and an op's JS runs on them only if it calls
  nothing past Math.fround and Math.imul; a local is a name name_local
  made; an op's argument is held unless it is a variable or a constant
  (op_bare); a JS call that waits on its callee calls its entry ($$k); a
  JS closure captures what is free in it.
- A match arm that rebuilds its scrutinee reads it (arm_self), so JS
  needs no views.
- A pure main prints through a Bend printer of main's value (main_pure),
  instead of a descriptor and a C and a JS printer; Base gains
  Char.quote, String.quote, F32.show.dot, U32.hex, Array.write and
  Array.show. JS holds stdout off a terminal and writes it before a wait,
  an error, an exit, a File.write or at 64 KiB.
- The term caches live as long as the file; the fold cache is cleared per
  def. Reserved names are refused before anything else, on both lanes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

1 participant