I continue to work on my Modula-2 compiler. This one is more elaborate. Wip.

Eric Streit 0adc637908 feat: add separate compilation with per-unit objects há 12 horas atrás
bootstrap f9043074ef build: split standard library into dialect folders há 13 horas atrás
compiler 0adc637908 feat: add separate compilation with per-unit objects há 12 horas atrás
docs 0adc637908 feat: add separate compilation with per-unit objects há 12 horas atrás
lib f9043074ef build: split standard library into dialect folders há 13 horas atrás
runtime 11c8db2c3a language: pointer-based 1-D open views (M6) há 15 horas atrás
tools 0adc637908 feat: add separate compilation with per-unit objects há 12 horas atrás
vendor 8d68fea6f6 v3 step 1 — minimal integer pipeline to QBE (5/5 tests green) há 1 mês atrás
.gitignore 0adc637908 feat: add separate compilation with per-unit objects há 12 horas atrás
README.md 0adc637908 feat: add separate compilation with per-unit objects há 12 horas atrás
m2make.md 2f243ed497 m2make: build-order front-end for M2/gm2 (topo-sort imports, incremental build); FileIO argv starts at 1 há 1 mês atrás

README.md

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

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)

compiler/src/      M2.atg, frames, FileIO, SymTab, QbeGen, Lower (+ generated)
compiler/tests/    t_*.mod (check/reject/run) + showcase<N>.mod tours
compiler/gen_ssa/  build outputs (gitignored)
runtime/syslib/    always-linked runtime (SYSTEM, Storage, SysIO, …)
lib/{pim,iso,common,gm2}/ opt-in dialect libraries
runtime/syslib/    shared runtime (SysShim, FileIO, …)
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-23)

  • Suite 303/303; self-hosting fixpoint OK (byte-identical stage2/stage3, 3,717,887 bytes); corpus 519/612 compile-OK, 0 crashes (tools/v3-corpus; the corpus is gm2's testsuite, so it mixes conforming Modula-2 with gm2 leniencies — see docs/gaps/). The remaining except*/onebyte*-style corpus files still hit V3's declaration-order policy.
  • Active branch master, feature state v3-separate-compilation. Recent milestones: PACKEDSET, ISO exceptions (EXCEPT/RETRY, EXCEPTIONS, M2EXCEPTION, catchable language traps including functionException, module FINALLY), self-referential pointer records/chained fields, and multi-dimensional fixed/open arrays (M1–M4): flat payloads + per-level views, open-array calls, and payload SIZE/view ADR, flat multi-dimensional record fields and constructors, pointer-based 1-D open views, an LFLOAT builtin, and dialect library folders (lib/pim, lib/iso, lib/common, lib/gm2), and separate compilation (M2 -c objects, M2make --separate).

Lowers today: program modules; CONST/VAR/TYPE (scalars, subranges, enums, arrays, records incl. variants and self-referential pointer records, sets incl. PACKEDSET, pointers); ARRAY/RECORD/SET/POINTER, WITH, IN; fixed and open multi-dimensional arrays (view descriptors, row/subarray conversion, payload SIZE/ADR); 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; ISO exceptions (EXCEPT/RETRY, SYSTEM.THROW, EXCEPTIONS, M2EXCEPTION, catchable index/range/CASE/function traps, module FINALLY); 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 (M2 -c per-unit objects, M2make --separate) and the one-shot multi-file mode (lib.def lib.mod prog.mod → 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<N>.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).