Interactive grammar §4 (last big section before composites). Suite 28/28 (13 run + 15 reject), LL(1)-clean throughout.
compiler/src/M2.atg)Expr = SimExpr [Rel SimExpr]: = # < <= > >= (no <>, no IN
yet), RelCheck → 213, result BOOLEAN via new QbeGen.Cmp
(ceqw/cnew/csltw/cslew/csgtw/csgew, eager 0/1).OR/AND (BoolCheck → 212) eager via or/and; NOT via xor-1.BOOLEAN/CHAR variables load like integers now (still w);
named CHAR consts load too; other named-const use stays 230.
VAR x: BOOLEAN/CHAR accepted (enums/subranges still 230).a..b ranges, ELSE), RETURN with 232 checks
(outside proc / value-vs-proper mismatch / missing value).QbeGen: labels, jumps, dead positions)New: deterministic @LN labels, EmitLabel/Jmp/Jnz, Cmp, NotQ,
LOOP-exit stack. Plus the section's hard lesson, handled once in
the backend instead of every action:
jmp lAfter, so no-match fallthrough skips the
body (cmp; jnz(lBody,lF); lF: ...; jmp lAfter; lBody: S; ...
lAfter:). The first attempt (fallthrough into the body) ran the
wrong branch and is recorded here so it isn't reinvented.Proc-stack: EnterProc/ReenterProc push, new CloseProc pops both scope and stack (all three heading sites converted); InProc/CurRes drive the RETURN 232s. Frame gains 232 "bad RETURN".
Run: t_if/while/repeat/loop/for (incl. BY -2 and empty-range
skip)/case (labels+ranges+ELSE)/bool (vars, chars, #, NOT) +
showcase3 tour → 183. Reject: 214 non-boolean WHILE, stray EXIT,
module-level RETURN 1, BY 0. Total 28 (13 run + 15 reject).
Open (step 2/3/4): REAL lowering, WITH, IN, CHAR arithmetic
policy (currently 211), unmatched-FORWARD 231, call emission.