# m2compiler-V3 — status (2026-10-18) This answers "where are we now?". ## Numbers - Suite **237/237** (`compiler/run_tests.sh`). - Self-hosting **FIXPOINT OK** — stage2 and stage3 images are byte-identical (3,823,257 bytes). - Corpus **402 / 612** sources compile with 0 errors, **0 crashes** (`tools/v3-corpus/corpus.sh` over the gm2 testsuite); the rest are genuine language gaps, **gm2 leniencies V3 deliberately rejects**, or unresolved imports. - Branch **`resolve-check`**; tree clean. ## Architecture (current) ``` per unit: Parse -> AST + declarations; each procedure body is skipped and re-parsed at unit end, so forward references bind normally Lower -> walk the AST, emit QBE (the only emitter) Emit -> buffered image, EndModule ``` - **Two-phase parse.** Procedure bodies are deferred (module level) and re-parsed after the unit's declarations, which removed the entire forward-reference mechanism (`FwdVar*`, `Design`'s forward branch). A module body may now call a procedure declared later; a nested-local forward is a plain `201`. `-notwophase` restores the legacy inline parse for debugging. - **No resolve/check pass.** The `Check` module was deleted once it was proven vestigial (gutting it left the emitted `.ssa` byte-identical): binding is late by construction. - **`Lower` is the only emitter**; the AST is the interface. ## Language coverage Program modules; `CONST`/`VAR`/`TYPE` (scalars, subranges, enums, arrays, records incl. variants, sets, pointers); `WITH`/`IN`; whole array/record copy; `NEW`/`DISPOSE`; full expressions and control flow; `GOTO`/labels; procedures (value/`VAR` params, functions, recursion, `FORWARD`, nested procedures, procedure values); Clarion-form `CLASS` (methods, single inheritance, virtual dispatch); PIM coroutines; Unicode (`UCHAR`/`UString`, UTF-8 edges); ISO type conversions `T(x)`; separate compilation (`FROM`/`IMPORT`, qualified `L.x`, opaque types); **generics** (ISO 10514-2 refinement): type/value/procedure parameters, constraints, nested generics, generic classes. ## Landed recently (this thread) - AST + `Lower` (L0–L7) — `Lower` emits the whole session from the AST. - Two-phase parse; forward machinery deleted; `Check` deleted. - Generics increment 3: value/procedure parameters, constraint model, nested generics, generic classes via generic modules. - ISO type conversions `T(x)` (incl. CONST folding), the builtins `ODD`/`TRUNC`/`FLOAT`, and BOOLEAN/ENUM array bounds + indices: corpus 365 → 381. - **SET CONST** (static masks): a set constant (`CharSet{"0".."9"}`, a union of set constants) is folded to a mask at parse and re-emitted as a pooled `data $setN` descriptor. **Builtin `CONST` folding** (`CAP`/`ABS`/`ODD` over immediates), `BOOLEAN` `CONST`s, representation-changing `CONST` conversions (`VAL(REAL, int)`, `VAL(LONGINT, int)`, …), **procedure values** (`ADR(proc)`, `VAL`↔`PROC` conversions, `p := foo` into a `PROC`), SYSTEM sized reals (`REAL32`/`REAL64`), `FROM SYSTEM IMPORT SHIFT`/`ROTATE`/`CAST`/… (a builtin import is accepted), and ISO foreign modules (`DEFINITION/IMPLEMENTATION MODULE FOR "C"`, `EXPORT UNQUALIFIED`), and ISO `CONVERT(T, x)` (a `VAL` sibling), set↔word `VAL`/`CAST` (BITSET), and **enumeration literals with their type** (export/import/ qualified; `imp*`): corpus 382 → 402. Fixed a `SHIFT`-by-a-negative fault and the qualified-const value (`LoadDesignator`). - The **corpus harness** now resolves **transitive** imports (it used to under-provide `.def`s); this more accurate harness is the method from 2026-10-18. - Clean `M2` exit codes (0 ok / 1 errors / 2 usage-IO). - Bug fixes: `PopPos` wiping repass diagnostics; global record data size (`w 0` → `l 0` for pointer/`LONGINT`/proc fields); template arithmetic over a type formal; proc-typed formals in DEF/IMPL; imported procedures used as values. - Showcase `showcase23` (generic doubly linked list). ## Conformance policy V3 follows **Modula-2** (PIM/ISO), not gm2's degradations. In particular the language requires **declaration before use** (the only forward reference is a `POINTER`'s base type), so the use-before- declaration programs that gm2 accepts are **rejected by design**. The corpus is gcc's gm2 testsuite, so its number mixes conforming programs with gm2 leniencies; each known case is catalogued (with a reproducer) in `docs/gaps/`. *Known non-conforming behaviour still retained* (pre-existing, not yet removed): forward references to module-level **variables** and forward **procedure** calls from a body (both are the two-phase parse deferring procedure bodies — separate from the declaration part). The declaration part itself is now strict: module-level forward type/`VAR` references, forward types inside a `TYPE` block, and forward `SET OF ` are all rejected (Track A, first cut, 2026-10-18). Corpus 398 → 388 (the drop is the 10 gm2-leniency files now correctly rejected). ## What remains 1. **Corpus** — genuine gaps remain (`not supported yet`, `undeclared identifier`, `invalid call`); separate them from gm2 leniencies (`docs/gaps/`) and missing stdlib imports (`LIB`). See `docs/analysis_gaps.md`. 2. **The size-sensitive V3 miscompile** — the long-standing "removing `ASTDUMP` from `M2.atg` breaks the fixpoint" has never been root-caused. A real correctness landmine. 3. **Robustness** — fixed table limits resolve silently when exceeded; weak error recovery; error-message polish. 4. **Library holes** — channel/device framework (`docs/wip/`). 5. **Housekeeping** — consolidate `docs/summary_*.md` (see `docs/INDEX.md`); decide on merging/pushing `resolve-check`. ## How to check for yourself ```sh cd compiler ./build.sh # M2.atg -> scanner/parser/driver -> ./M2 ./run_tests.sh # 237/237 cd .. ./bootstrap/fixpoint.sh # FIXPOINT OK (byte-identical stage2/stage3) ```