Skip to content

gen-ts: lower the bodies of pure functions, so a host imports a spec's rule instead of copying it #7871

Open

Description

@gHashTag

Owner, 2026-10-08: "MVP 100% from .t27, working in prod". gen-ts emitted declarations only, so every host re-wrote each spec fn by hand and pinned the copy with the spec's vectors: two homes for one rule.

This lowers the pure subset (bool/integer/str parameters and results; return, locals, assignment, if/else, while, for-range, break, continue; literals, params, locals, the module's constants and functions, indexing into a constant, !, unary -, and/or, comparisons, + - * %, integer / as Math.trunc). Anything else refuses the whole function with a sentence, and a function calling one that does not lower does not lower either.

Measured over the corpus: 2437 functions in 534 specs, every generated module passes tsc --strict.


Generated by Claude Code

User Scenarios

  • Given a .t27 spec with a pure function using only the allowed subset (bool/int/str params and results, return, locals, assignment, if/else, while, for-range, break, continue, literals, params, locals, module constants/functions, indexing into constants, !, unary -, and/or, comparisons, + - * %, integer / as Math.trunc), When gen-ts runs on that spec, Then the generated TypeScript module contains the full function body (not just a declaration) so a host can import and call it directly.
  • Given a .t27 spec with a function that uses any construct outside the pure subset (e.g., float division, method calls, object allocation, external calls), When gen-ts runs on that spec, Then gen-ts emits only a declaration for that function and refuses to lower its body with a diagnostic sentence explaining why.
  • Given a .t27 spec where function A calls function B, and B does not lower (uses an impure construct), When gen-ts runs on that spec, Then function A also refuses to lower and emits only a declaration with a diagnostic referencing B.

Requirements

FR-001: gen-ts MUST lower the body of every function whose signature and body use only the pure subset (bool/integer/str params and results; return, locals, assignment, if/else, while, for-range, break, continue; literals, params, locals, module constants and functions, indexing into a constant; !, unary -, and/or, comparisons, + - * %, integer / as Math.trunc).
FR-002: gen-ts MUST refuse to lower any function that uses a construct outside the pure subset, and MUST emit a diagnostic sentence naming the offending construct.
FR-003: gen-ts MUST transitively refuse to lower any function that (directly or indirectly) calls a function that does not lower.
FR-004: Every generated TypeScript module MUST pass tsc --strict without errors.
FR-005: The lowering logic MUST be implemented in the existing lowering pipeline (cli/t27b/src/lower.rs) and driven by the compiler CLI (compiler/cli/spec.t27).

Success Criteria

  • cargo test -p t27b -- lowering exits 0 and runs at least 5 tests covering pure lowering, refusal on impure constructs, and transitive refusal.
  • gen-ts on the 534 specs in the corpus produces 2437 lowered functions (matching the measured count) and 0 functions incorrectly lowered or incorrectly refused.
  • tsc --strict on every generated module in the corpus exits 0.
  • The files cli/t27b/src/lower.rs and compiler/cli/spec.t27 are modified to implement the lowering and refusal logic.
  • Test fixtures bootstrap/tests/fixtures/trinity_matrix/functions.t27 and bootstrap/tests/fixtures/trinity_matrix/imports.t27 are updated or referenced by new tests that exercise the pure subset and refusal cases.

Boundary

  • cli/t27b/src/lower.rs
  • compiler/cli/spec.t27
  • bootstrap/tests/fixtures/trinity_matrix/functions.t27
  • bootstrap/tests/fixtures/trinity_matrix/imports.t27

Activity

  1. gHashTag commented on Oct 17, 2026

    @gHashTag
    OwnerAuthor

    Superseded by #9994. PR #7872 adds 441 hand-written Rust lines to bootstrap/src/codegen_ts_fn.rs, and the own-language gate refuses that: more than 40 in one file and more than 80 in total, and no label lifts it. #9994 builds the same capability as t27b ts, written in .t27 the way t27b verilog is (verilog_emit.t27 through t27c gen-rust).

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions