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

Eric Streit 4383fb486d v3 step 4.2 — nested procedures: static-link display (82/82 tests green) hace 2 semanas
compiler 4383fb486d v3 step 4.2 — nested procedures: static-link display (82/82 tests green) hace 2 semanas
docs 4383fb486d v3 step 4.2 — nested procedures: static-link display (82/82 tests green) hace 2 semanas
vendor 8d68fea6f6 v3 step 1 — minimal integer pipeline to QBE (5/5 tests green) hace 3 semanas
README.md 0973e131ed v3 step 1.10 — Clarion classes + corrected OOP sketch (33/33 tests green) hace 3 semanas

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.

Layout (Blaise-adapted)

compiler/src/      M2.atg, frames, FileIO, SymTab, QbeGen (+ 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, …)
stdlib/            opt-in libraries (Strings, TextIO, …; classic form)
tools/             syntax helpers (redux-check direction)
bootstrap/         stage1/2/3 + fixpoint.sh (self-hosting proof)
vendor/            qbe toolchain pin
docs/              plan.md, summary_stepN.md (one file per step)

Language status (at v3-step2, 30/30 green)

Lowers today: program modules; CONST/VAR/TYPE (named, integer subranges, enums declared); all scalar arithmetic, relations, boolean connectives (eager); IF/WHILE/REPEAT/LOOP/ FOR/CASE, EXIT, RETURN (checked); REAL incl. conversions. Parse-now/lower-later (single 230): DEFINITION/IMPLEMENTATION, nested modules, procedure bodies, FORWARD, enum use, Clarion-form CLASS (declaration + single inheritance + CLASS IMPLEMENTATION blocks + VIRTUAL methods; classic identifiers only, so the docs/OOP.txt Table example's _names stay out of reach). Still syntax errors: composites (ARRAY/RECORD/SET/POINTER), WITH, IN, calls — that's step 3/4 territory.

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-step record in docs/summary_stepN.md; showcase<N>.mod tours each stage.
  • Tags v3-step1[.sub] / v3-step2 mark green states; no pushes without asking (see git.txt for the remote recipe).