summary_step3.3.md 2.6 KB

V3 step 3.3 — sets: multi-word masks, full expressions, all ops (done 2026-09-20)

Suite 50/50 (21 run — incl. 3 trap-aborts — + 29 reject). LL(1)-clean (only the known-benign TypeBlock warning).

Model (locked: multi-word, full expressions, all ops + IN)

Sets are memory addresses (globals or alloc8 temps), never scalars — uniform with arrays. No header (size is static); W words of bitmask, bit v-lo. Unrolled straight-line word code everywhere (counts static, deterministic).

Grammar (M2.atg)

  • SetType: SET OF bool/char/bounded-subrange (span ≤ 256); enums wait for ordinals, INTEGER is unbounded → 230.
  • SetLit/SetElem in Fact: literals are SET OF [0..255] (8 words); elements int/char/bool, folded values checked 0..255 statically (222), computed values trap via SetBit; ranges always lower via SetRange (literals validated, inverted runtime ranges are naturally empty, like FOR 5 TO 1).
  • + - * / branch to union/difference/intersection/symdiff when both sides are sets (result spans max, typed exactly so downstream word counts match allocations); IN added to Rel (mismatch → 222); set =/# via word-wise CmpSet; CASE labels reject sets (arrays/strings already 213 themselves).
  • Assign copies sets (CopySet with dst/span word counts).

Backend (QbeGen, all probed first)

DeclSet, NewSetTemp (alloc8, 8-rounded), SetZero, SetBit/SetRange (span traps), SetBinOp (overlap via op, larger-side extras copied or zeroed), CmpSet (min words + zero-check extras), CopySet (min-word memcpy, zero-fill, trap when src extras beyond dst are nonzero — narrowing {100} into SET OF [0..7] aborts instead of silently dropping bits), InSet (bit test + span trap). Probe facts reused: alloc8, shr/shl, strict width checking (a mixed-width mul in the probe failed loudly — hence WidenIndex everywhere).

SymTab (lenient-by-design, documented)

SubBounds/SetBase/SetWords/SetBaseLo/SetCount; SetBasesOk accepts any two suitable bases (masks compare over min words); InCheck accepts small int/char/bool against suitable sets. Static 222s stay for what is known bad (out-of-span literals, non-sets in IN); the runtime trap catches the rest.

Tests

t_set → 131 (all four ops, IN, =/#, empty, var index), t_setchar → 77 (word-3 bits), t_setrange → 55 (ranges, var element, empty compare); t_bad_setelem/t_bad_in → 222, t_bad_setbase → 230; t_trap_setspan → abort (rc=134).

Deferred: enum bases (ordinals), string =/+, multi-word performance (unrolled is fine for now), CHAR-bound subtleties.