Repository navigation
t27core: for over one range and switch as a value, byte-identical to gen-c #7429
Description
Part of #5980.
The self-hosted core (specs/compiler/core/t27core.t27) should accept for over one range and switch as a value, and write the same C bytes as t27c gen-c, once gen-c lowers them (#7331, closing #7307 and #7308).
A for (a..b) |i| { } becomes for (size_t i = a; i < b; i++) {, and a |_| capture names the counter __t27_i. C reads the end on every pass while Zig reads it once, so the core takes a for only when the end calls nothing and the body can neither assign a name the end reads nor, when the end reads a module var, make any call. Two ranges, a for-each over an array (#7420) and ..= are refused.
A switch becomes a chain of ternaries, (x == 1) ? (10) : 0. gen-c loses several shapes (#7419), so the core takes a switch only as the whole value of a return, a local initializer or an assignment, or as an arm value. The subject must call nothing, each label must be a number without _ separators (an optional - is allowed), and else must come exactly once and last. Everything else is refused.
The fixpoint and the DDC pin move with the core. New accept fixtures cover both shapes and run under C, and the refusals name the gen-c defect each shape avoids.
Boundary
specs/compiler/core/t27core.t27
User Scenarios
- Given a t27 source with
for (0..10) |i| { sum += i; }where the end expression calls nothing and the body doesn't assign names read by the end, When compiled by t27core, Then the emitted C is byte-identical tot27c gen-coutput for the same construct. - Given a t27 source with
return switch (x) { 1 => 10, else => 0 };where the subject calls nothing, labels are plain numbers, and else is last, When compiled by t27core, Then the emitted C is a ternary chain(x == 1) ? 10 : 0byte-identical tot27c gen-coutput. - Given a t27 source with a refused shape (two ranges, for-each over array,
..=, switch subject that calls, non-numeric label, missing or misplaced else), When compiled by t27core, Then compilation fails with a message naming the gen-c defect that shape avoids.
Requirements
- FR-001: t27core MUST accept
for (a..b) |i| { body }only when the end expressionbcalls no function, the body assigns no name thatbreads, and ifbreads a module variable the body makes no calls. - FR-002: t27core MUST lower accepted
for (a..b) |i| { body }to Cfor (size_t i = a; i < b; i++) { body }with|_|capture naming the counter__t27_i, byte-identical tot27c gen-coutput. - FR-003: t27core MUST refuse two-range
for, for-each over array, and..=inclusive range with a diagnostic naming the gen-c defect each avoids. - FR-004: t27core MUST accept
switchas a value only when it is the whole value of areturn, a local initializer, an assignment, or an arm value; the subject calls nothing; each label is a plain integer literal (optional-allowed, no_separators); andelseappears exactly once and last. - FR-005: t27core MUST lower accepted
switchto a ternary chain(subject == label1) ? value1 : (subject == label2) ? value2 : ... elseValuebyte-identical tot27c gen-coutput. - FR-006: t27core MUST refuse all other switch shapes with a diagnostic naming the gen-c defect each avoids.
- FR-007: New accept fixtures for both shapes MUST be added and MUST pass under C execution.
- FR-008: The fixpoint and DDC pin MUST be updated to match the new core.
Success Criteria
t27c check specs/compiler/core/t27core.t27exits 0t27c build specs/compiler/core/t27core.t27exits 0 and produces a binary that compiles the accept fixturesspecs/compiler/core/fixtures/accept/for-range-one.t27compiles and runs under C with exit 0specs/compiler/core/fixtures/accept/switch-value.t27compiles and runs under C with exit 0specs/compiler/core/fixtures/refuse/for-range-refusals.t27fails to compile with diagnostics naming gen-c defects (5 tests)specs/compiler/core/fixtures/refuse/switch-value-refusals.t27fails to compile with diagnostics naming gen-c defects (7 tests)- Fixpoint rebuild
t27c fixpointexits 0 - DDC pin update
t27c ddc-pinexits 0
Activity
gHashTag commentedon Oct 7, 2026
Reopened 2026-10-07: the bulk close of issues without a
## Boundarysection was reverted by the owner. Nothing to do here; this comment replaces the earlier close notice.Merge self-host-p1-for-switch into master ce605a6 (from master's side)
t27core: for over one range and switch as a value, byte-identical to …