# m2compiler-V3 — modern Modula-2, Coco/R frontend, QBE backend A from-scratch Modula-2 compiler in the Blaise spirit (phased, test-guarded, self-hosting as the end goal): a Coco/R-generated frontend in GNU Modula-2, a fresh QBE SSA backend, and a length-prefixed runtime data model. Modern syntax follows the Benjamin R10 specs where they don't break classic code (Kowarsch/Redux cleanups: `#` not `<>`, `NOT/AND/OR` only, no `B/C` octals, `0x` hex, `//` comments). ## Prerequisites - GNU Modula-2 (`gm2 -fiso`; developed with GCC 16.0.1 experimental) - Coco/R `CR` V1.53 (`CRBIN` env var, defaults to the sibling `CocoGm2/CR` used here) - `qbe` (default target `amd64_sysv`; pin: `vendor/qbe-pin.txt`) - `cc`, `timeout`, standard shell tools ## Build and test ```sh cd compiler ./build.sh # M2.atg -> scanner/parser/driver -> ./M2 ./run_tests.sh # M2 -> gen_ssa/*.ssa -> qbe -> cc -> exit codes ``` Pipeline per test: `./M2 tests/foo.mod` writes `gen_ssa/FOO.ssa`; a global `VAR ExitCode : INTEGER` selects the process exit code (else 0). Reject tests assert on `.LST` messages; every error also prints as `file:line:col: message` on stdout. `M2` itself exits **0** on success, **1** on compile errors and **2** on usage/IO problems (no input, unopenable file) — no aborts. ## Layout (Blaise-adapted) ```text compiler/src/ M2.atg, frames, FileIO, SymTab, QbeGen, Lower (+ generated) compiler/tests/ t_*.mod (check/reject/run) + showcase.mod tours compiler/gen_ssa/ build outputs (gitignored) runtime/syslib/ always-linked runtime (SYSTEM, Storage, SysIO, …) stdlib/ opt-in libraries (Strings, TextIO, …; classic form) tools/ syntax helpers + v3-corpus (coverage harness) bootstrap/ stage1/2/3 + fixpoint.sh (self-hosting proof) vendor/ qbe toolchain pin docs/ STATUS.md, plan.md, plan-*.md, analysis_*.md, summary_*.md ``` ## Status (2026-10-16) - Suite **219/219**; self-hosting **fixpoint OK** (byte-identical stage2/stage3, 3,714,376 bytes); corpus **372/612 compile-OK, 0 crashes** (`tools/v3-corpus`). - Active branch **`resolve-check`** (holds the AST/`Lower`/parse refactors and generics). Lowers today: program modules; `CONST`/`VAR`/`TYPE` (scalars, subranges, enums, arrays, records incl. variants, sets, pointers); `ARRAY`/`RECORD`/`SET`/`POINTER`, `WITH`, `IN`; whole array/record copy; `NEW`/`DISPOSE`; all scalar arithmetic, relations, boolean connectives; `IF/CASE/WHILE/REPEAT/LOOP/FOR`, `GOTO`/labels; procedures with value/`VAR` params, functions, recursion, `FORWARD`, nested procedures (static-link display), procedure values; Clarion-form `CLASS` with methods, inheritance and virtual dispatch; PIM coroutines (`PROCESS`/`NEWPROCESS`/`TRANSFER`/`IOTRANSFER`); Unicode (`UCHAR` codepoints, `UString`, UTF-8 at the edges); ISO type conversions `T(x)` (incl. CONST folding); **separate compilation** (`lib.def lib.mod prog.mod` in one run → one image, `FROM`/`IMPORT`, qualified `L.x`, opaque-type completion); **generics** — ISO 10514-2 refinement form (`GENERIC … MODULE M(T:TYPE)` + `MODULE X = M(actuals)`) with type/value/procedure parameters, constraints (`T : TYPE (ORDINAL|INTEGER|REAL|POINTER|SCALAR)`), nested generics, and generic classes. Architecture: a **two-phase parse** — each unit's procedure bodies are deferred and re-parsed at unit end, so forward references bind normally and the old forward-reference machinery is gone. There is no separate resolve/check pass; `Lower` is the only emitter and walks the AST. `-notwophase` restores the legacy inline parse (debug escape). Long-term rules already locked: every `ARRAY` is `LONGCARD` count + elements (all arrays, inline, element counts, no NUL); `UCHAR` = 32-bit codepoint, `UString` = count + codepoints, UTF-8 at the edges with hard lex errors; self-hosting bar is byte-identical `.ssa` over three stages. ## Working conventions - Grammar grows section by section in `compiler/src/M2.atg` (kept LL(1)-clean — Coco/R must report no errors). - Every step keeps the full suite green; per-session record in `docs/summary_*.md`; `showcase.mod` tours each stage. See `docs/INDEX.md` for the load-bearing docs. - Tags `v3-*` mark green states; no pushes without asking (see `git.txt` for the remote recipe).