summary_set-constants-2026-10-18.md 3.2 KB

Session summary — SET CONST (static masks) 2026-10-18

Branch resolve-check. Suite 225/225; fixpoint OK (3,823,438 bytes); corpus 387/612 compile-OK, 0 crashes.

Tag: v3-set-constants.

What this session did

Landed set constants — the first of the two features recorded in docs/analysis_gaps.md §9 — from the previous corpus sweep.

CONST Digits = CharSet{"0".."9"};          (* char range *)
      Signs  = CharSet{'+', '-'};
      NumCh  = Signs + Digits;             (* union of two set constants *)
      Warm   = CS{Red, Blue};              (* enum base *)

Corpus 382 → 387 (+5 files: setconst, setconst2, and 3 more), 0 crashes. New suite tests t_setconst (run, exit 42) and t_bad_setconst (reject, 230).

Why it was reverted before, and the fix

A set literal is emitted as a runtime temp (NewSetTemp/SetZero/ SetBit), so a set CONST had no static value; accepting the declaration produced a 230 rather than a miscompile (see the previous sweep's finding). Sets are also addresses of memory words, so the constant must be a real data symbol.

The fix computes the bit mask at parse time — where the element values are known and validated — and has Lower re-emit it as a pooled static descriptor:

  • Lower.SetConstMaskOf (exported) folds a set expression to (mask, words, lo): set literals (NkSetLit/NkBraceLit), char / integer / named-CONST elements, a..b ranges, and +/-/*// over two foldable set operands (union / difference / intersection / symdiff), plus + - * DIV MOD on element ordinals.
  • ConstDecl (grammar) calls it for ClSet; on success it records the mask (Lower.NoteSetMask) and lets the constant be an aggregate; on failure it stays a clear 230.
  • Lower.LowerDecls looks the mask up by name and calls the new QbeGen.PoolSet, which registers data $setN = { w mask0, ... } and returns its address. FlushSets emits the pool in EndModule.
  • The grammar's Design and Lower's LowerDesign now treat a ClSet KindConst as an aggregate: its value is the descriptor address (so c1 := Digits, c IN Digits work).

Bound: masks are folded up to 16 words (512 bits); a wider SET CONST stays a 230 (MaxCFoldW). The corpus set constants are ≤ 8 words.

Not fixed (recorded)

  • setconst3.mod still fails: its VAR mem: ARRAY [0..CARDINAL( addressLines)] names a CONST declared after the VAR (a forward CONST reference), which is a separate gap. Its SET CONST itself now parses.
  • Builtin calls in CONST (CAP(VAL(CHAR,65)), MIN/MAX of sets) — still the second recorded feature; fold builtins over immediates.

Files

compiler/src/Lower.{def,mod} (evaluator + PoolSet call), compiler/src/QbeGen.{def,mod} (PoolSet/FlushSets/pool state), compiler/src/M2.atg (ConstDecl, Design), compiler/tests/t_setconst.mod, compiler/tests/t_bad_setconst.mod, compiler/run_tests.sh.

Resume

cd .../m2compiler-V3
git checkout resolve-check
cd compiler && ./build.sh && ./run_tests.sh   # 225/225
cd .. && TMP="$PWD/.scratch/fixpoint" ./bootstrap/fixpoint.sh
M2FLAGS="" ./.scratch/corpusx.sh              # 387 OK, 0 crash