# V3 step 1.7 — declarations: scalar TYPEs, headings, bodies, FORWARD (done 2026-09-19) Interactive grammar §3, landed syntax-now/backend-later like §2. Suite 15/15 (5 run + 10 reject), LL(1)-clean. ## Grammar (`compiler/src/M2.atg`) - `TypeBlock` replaces `OpaqueBlock` in both DefUnit (TRUE) and DeclSeq (FALSE). `TypeItem = ident ("=" Type | /*opaque*/)` — the branch happens *after* the ident so `=` vs `;` keeps it LL(1). Opaque outside DEFINITION → new 231 (frame text added). - Scalar-phase `Type = TypeIdent | Subrange | Enum`. Composites (ARRAY/RECORD/SET/POINTER) are still syntax errors → step 3. - `TypeIdent` factored (named/predef/import-tolerant) and reused by VarDecl (which now also accepts imported type names as Invalid). - `Subrange = "[" Expr ".." Expr "]"`: integer-family bounds folded via new `SymTab.ConstInt` (literals incl. `0x`, folded unary minus); non-literal/non-int/inverted bounds → 230. Stored via new `NewSubR(lo,hi)`; baseless `FSub` resolves to `ClInt` (ClassOf fix). - `Enum = "(" idents ")"`: literals entered as KindConst of the new type. *Use* of non-INTEGER consts (enum/char/bool/real) is now 230 (Design KindConst branch tightened; NIL stays silent). - `ProcHeading` (OUT name): `EnterProc`/`ReenterProc` + optional formals + optional `: TypeIdent` result. DefUnit uses it + `PopScope`. - `FormalParams`: `"(" [groups] ")"`, `VAR` per group, `EnterParam` + `FixPending` (params behave as typed variables in bodies). - `ProcDecl = heading ";" ("FORWARD" | Block)`; Block parses decls + optional body with END-name check, one 230 (lowering = step 4). Wirth trailing-`;` convention (V1 parity): DeclSeq uses `ProcDecl ";"`. ## SymTab growth (additive, no interface breakage) KindProc/KindParam; node fields rslt/plink/isVar/fwd; EnterProc (pushes scope), ReenterProc (fwd→body, fresh signature), EnterParam (pend-records + positional chain), SetProcRes/ProcRes/MarkFwd, NewSubR + tlo/thi, ConstInt. PrintTable shows PROC/PARAM. ## Bugs found by the new tests (all fixed, suite proved each) 1. `ProcDecl ";"` missing → FORWARD's trailing `;` misparsed as 'END' expected (V1 had the same separator rule). 2. `[0..9]` lexed wrong without Test2's `CONTEXT("..")` guard on the integer token (spaced `[0 .. 9]` worked, unspaced didn't). 3. `ReenterProc` didn't reset `plink` → second param list chained onto a NIL tail: SIGABRT heap crash, bisected to fwd+params on both headings. 4. `EnterParam` didn't pend-record → params stayed InvalidType and every use falsely 230'd (5 errors in t_proc instead of 1). ## Tests `t_types` run → 8 (subrange/alias/hex use); `t_enumdecl`, `t_proc` (value + VAR formals, result), `t_forward` (fwd/body pair) → single 230s; `t_bad_opaque` → 231. Deferred on record: unmatched FORWARD (no body) is silently accepted — step 4 makes it 231; fwd/body signature compare also step 4.