Skip to content

feat(t27b): module-level var as a writable global - #6296

Merged
gHashTag merged 1 commit into
masterfrom
claude/t27b-assign
Oct 4, 2026
Merged

gHashTag merged 1 commit into
masterfrom
claude/t27b-assign

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Closes #6294
Refs #6063, #6295

What

This PR takes the StmtAssign(undeclared) blocker family.

  • Before: t27b treated a top-level var as a constant, so every assignment to it was refused.
  • Now:
    • A typed module var with a compile-time initializer (scalar, bool, enum, struct or array) lowers to ExprKind::Global, backed by Program::globals.
    • JIT: the initial bytes are copied into a heap region before every host call.
    • Checked interpreter: resets the globals when depth == 0.
    • Both match t27c test-report, which runs each test in a fresh process.
    • Object file (Mach-O, which has no writable section yet): refused as VarDecl(module, object file).

Refused by name: the reference Zig cannot compile these

The reference bugs are filed as #6295.

Shape Blocker Reason
A test assigns a module var StmtAssign(module var in test) The test-binding pass turns the first assignment into const x = .., which shadows the container var (Zig error).
A test or fn local shadows a module var StmtLocal(shadows module var) Zig forbids the shadowing. A mutated param is rebound as var x = x_arg, which shadows too.
A test that follows a fn whose param was renamed (x -> x_arg) and mentions x ExprIdentifier(renamed module var) param_renames leaks into later tests.
A module var in an invariant ExprIdentifier(var at comptime) Invariants are comptime.
A non-compile-time or untyped initializer VarDecl(module)

t27b corpus specs

before after
pass 246 (1655 tests, 279 inv) 258 (1728 tests, 292 inv)
pass_vacuous 279 279
test fails 4 6
rejected 687 670
front-end error 40 40
mismatch 0 0
timeout 0 3
crash 0 0

No file that passed before regressed.

12 newly passing files

Each one matches t27c test-report from the same master, test for test.

  • specs/fpga/testbench/:
    • assembler_tb (7)
    • cts_tb (10)
    • partition_tb (8)
    • placement_tb (9)
    • power_tb (8)
    • router_tb (9)
    • simulator_tb (6)
  • specs/port/fpga/verilog/dsp_probe.t27 (2)
  • trinity_qmtech (5)
  • led_d5_test (4)
  • specs/ternary/clocked_counter.t27 (1)
  • specs/ternary/stream_ternary_mac.t27 (4)

New test fails and timeouts

  • timing_tb: 9 pass, 1 fail (test_fmax_computation). The reference fails the same test.
  • hir_tb: 7 pass, 1 fail (test_tick).
  • Timeouts:
    • axi4_tb: the reference is BLOCKED.
    • clock_domain_tb and gf16_accel_tb: the reference also times out (900 s).
    • All three spin forever on a module flag that nothing sets, for example while !sync_ready { tick_fast(); }.

Gaps left open

  • The rest of StmtAssign(undeclared) is a different shape, not lowered here:
    • the discard _ = expr; (31 files);
    • an undeclared loop i (3 files).
  • An invariant that calls a fn which reads or writes a global is not detected yet.
  • Pre-existing: the overflow trap line for an assignment is reported one line late (plain locals too). The new test checks only the trap kind.

Top 5 blockers after

  1. ExprCall(assert with message): +19
  2. ExprIdentifier statement: +18
  3. FnDecl: +15
  4. ExprBinary statement: +12
  5. ExprCall(@compileAssert): +9

🤖 Generated with Claude Code

A typed module `var` with a compile-time initializer (scalar, enum,
struct, array) lowers to ExprKind::Global backed by Program::globals.
The JIT and the checked interpreter reset globals on every host entry,
matching t27c test-report's one-process-per-test isolation. Object
files refuse it as VarDecl(module, object file).

Shapes the reference Zig cannot compile are refused by name:
StmtAssign(module var in test), StmtLocal(shadows module var),
ExprIdentifier(renamed module var), ExprIdentifier(var at comptime).
Reference bugs filed as #6295.

t27b corpus specs: pass 246 -> 258, rejected 687 -> 670, mismatch 0.

Closes #6294
Refs #6063

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-04 23:18:29 UTC

Summary

Status Count
Total Open PRs 44
PRs with Failing Checks 32
PRs with All Checks Green 12
READY 11
FAILING 32
PENDING 0
NO CHECKS YET 0

These columns do not partition: 11 + 32 + 0 + 0 = 43, and there are 44 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=8597b6ded596 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 7e69777 into master Oct 4, 2026
29 of 31 checks passed
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.

t27b: module-level var (StmtAssign(undeclared) family)

1 participant