← board

Language gaps surfaced by the demo apps (sudoku / sieve / chess)

Why

The demos are written platonically (idiomatic code, no workarounds). Library holes go in the RTL ticket. A few gaps are in the language/compiler itself — either confirmed or strongly suspected while writing — collected here.

Gap 1 — set of built from runtime values (DONE 2026-06-19)

Resolved. Runtime set construction + mutation landed:

Lowered entirely in the shared IR (IRLowerSetBitMutate / IRLowerSetRangeMutate in compiler/ir.inc) from IR_BINOP / IR_LOAD_MEM / IR_STORE_MEM primitives — no new IR ops, no per-backend asm, no builtinheap dependency. The value is masked to 0..255 so the byte index always lands inside the 32-byte set (out-of-range elements ignored, matching the constant path). Parser: a constant element still folds to AN_INT_LIT (ParseSetElementAST), a non-constant one is parsed as a full expression; AN_SET_INCL / AN_SET_EXCL carry Include/Exclude.

Validated on all 4 targets: test/test_set_runtime.pas in test-core + i386/aarch64/arm32 cross suites (output identical to x86-64); self-host + cross-bootstrap byte-identical. The sudoku/maze/chess candidate-set lanes can now use real set of 1..9 + Include/Exclude instead of integer bitmasks.

Original report below.

(original) set of built from runtime values (CONFIRMED)

From feature-demo-sudoku: s := s + [v] with a variable v errors ("set item must be constant"), and Include / Exclude are unimplemented. So the candidate-set lane (set of 1..9 per row/col/box) cannot be built at runtime; the sudoku solver, the sudoku game, and chess all fall back to integer bitmasks where the value is dynamic. Chess uses sets only with constant elements ([mfCapture, mfPromo], pos.castling - [crWK]), which works.

To close:

This is the poster-child set feature; closing it lets the sudoku demos use the real set lane instead of a bitmask, and is likely the pragmatic substrate for the bit-set type in the RTL ticket.

Gap 2 — yield from a nested routine inside a generator (SUSPECTED)

Chess movegen wanted a nested helper EmitPawnTo(...) that does the four promotion yields, called from the generator body. The stackful-coroutine model appears to only allow yield lexically in the generator's own body, so the helper was inlined (promotion expansion duplicated for push and capture). Verify whether yield inside a nested proc of a generator routine is supported; if not, either support it or document the restriction.

Gap 3 — generator yielding a record / aggregate (TO VERIFY)

test/test_generator.pas only yields Integer. Chess declares function GenMoves(const pos): TMove; generator; and for m in GenMoves(pos) over a record element. If aggregate yield / aggregate for-in-over-generator is not yet wired, the chess demo will not compile — confirm against the for-in aggregate path (test/test_forin_aggr_elems.pas proves array-of-record for-in; the generator element path is the unverified one).

Acceptance

Gap 3 — generator yielding a record (DONE 2026-06-19)

Confirmed real (segfaulted) and fixed. A ; generator; routine can now yield a record element consumed by for x in. A record does not fit the one-word "current" slot, so yield m stores the record's ADDRESS (the stackful generator's frame keeps it alive until the next resume) and the for-in desugar derefs that address into the loop variable:

Validated x86-64 (test/test_generator_record.pas, in test-core) for 16- and 24-byte records + accumulation; self-host + cross-bootstrap byte-identical. Scope: the stackful (coroutine) path — stackful generators are x86-64-only (CoSwitch). Stackless ; generator; stackless; record-yield would need the same deref in the SlCurrent path (separate, lower priority). Unblocks chess movegen (yielding a TMove).

Gap 2 — yield from a nested routine (documented limitation 2026-06-19)

Confirmed: yield inside a nested routine of a generator does not parse (yield is only valid lexically in the generator's own body). Threading the generator self-pointer into nested routines (stackful-only) is invasive and deferred; the error now states the limitation clearly ("yield must appear directly in a generator body, not in a nested routine — inline the helper for now"). Chess already matches this (promotion expansion is inlined), so the acceptance criterion ("the limitation is documented and the chess source matches it") is met.

Log