m2comp-step4)The compiler is end-to-end: Modula-2 source → Coco/R frontend →
SymTab checks → AST → MGen MC64 .MC4 images runnable under
mcint, with execution tests. Follows the Blaise front/back split
(frontend builds the tree; backend walks it) rather than m2c's
single-pass emit, reusing m2c's proven lowering recipes and the
mc64-spec.md contract.
src/MGen.def/.mod (~1300 lines, single module): EmitModule
walks the checked AST and writes <Module>.MC4. Globals from
slot 4 (0..3 are the print-helper temps), ENTER frames with
ED/EC/EE calls, E0/E1 jumps with fixups, ExitCode print
convention (copied EmitPrint), full image assembly
(magic/descriptor/proc table/checksum).
DIV/MOD (truncating synthesis), int→real
widening, REAL (binary64) arithmetic/comparisons.VAR params (addresses in slots), functions,
recursion, nested procedures with display access, module
procedures, init bodies called once at startup (m2c parity).copy_block,
char arrays (literals materialized slot-wise), sets
(masks/IN/=), pointers (^, NIL), open-array formals
(unchecked, lo=0).src/SymTab layout enrichment: NewSubB/NewArrayB/WrapArrayB
with folded bounds, IndexBounds (CHAR 0..255, BOOLEAN 0..1,
subranges; INTEGER unbounded → 230), ArrayLo/Hi/Len,
TypeSlots/FieldOffset (cycle-guarded), const-value table
with chained ConstFold (IMPORT AST, acyclic).aux (symbol kind) + tag (module qualifier) stamps on
name/field nodes (scopes pop after parsing, so the backend
resolves through its own scope stack), num stamp on nkProc,
grammar-time 230s for value composite params and composite
function returns (m2c parity).src/compiler.frm driver hook: after a successful parse,
MGen.EmitModule(AST.GetRoot()) runs before the listing, so
backend 230s (via M2compP.SemError) still reach the .LST.run_tests.sh: expect_run (ExitCode compare) and
expect_run_none (silent, terminating), both with timeout
guards and VM-rc checks so diverging programs fail fast
instead of hanging the suite.4 accept + 15 reject + 6 AST dumps (steps 1–3 intact), 2 silent runs, 14 execution runs: arith 8, flow 69, bool 11, real 1111, proc 162 (fact), varpar 48, nested-display 213, array 39, record 15, set 12, string 111, ptr 111, module-init 83, const-chains 1102.
PROCEDURE ... FORWARD; is rejected with a
cryptic "too many errors in pass 3" (CR's -m flag comments
forwards out for this reason; m2c has zero forwards). Deleted.OpAdd =
OpTimes made 2*3 emit ADD; then OpEq = OpAdd made =
emit ADD (1=1 passed by accident). Mul codes → 10–14,
relation codes → 20–27 (all uses symbolic).51H/70H store orders differ (addr-on-top vs value-on-top);
m2c never emits 51H. Ours uses 70H everywhere.Jmp(endL)/DefLabel, m2c parity) — else fall-through
executes them with the wrong frame.CHAR consts never folded (Q → 230); multi-index chains
emitted only the first index (wrong code, now looped).| head masked VM hangs (rc was head's); silent
divergences now fail via timeout + rc checks.showcase.mod and the old ok_proc.mod DIVERGE by construction
(Work restarts its own FOR 1..10; P(i,i) mutates its loop
control 1→2→-1→…). Any correct implementation hangs; both stay
check-only. ok_proc's body was fixed to v := v + 1 so it
terminates and runs silent (constructs unchanged).D5 real comparisons misbehave identically
under byte-identical m2c output — VM-domain quirk, avoided in
tests, not a backend bug.
[Correction (step 5.2): misattributed — it WAS a backend
(codegen) bug in the recipe shared by both compilers: real
< > <= >= emitted stack juggling with no D5, so a leftover
operand's bits became the boolean. D5 itself was always
correct. Fixed; see summary_m2comp_step5.2.md.]Slot-per-element composites (no byte packing, no 0D/1D ops);
BY may be a runtime expression; open-array bounds unchecked;
module inits run once at startup even when nested (m2c parity);
NEW/DISPOSE unreachable (no grammar productions).
Step 5 candidates: DEFINITION/IMPLEMENTATION separate
compilation (multi-.MC4 + depCount loader path), opaque
types, procedure types, WITH/CASE, LONGINT/LONGREAL
quads, debugger listings. SymTab/AST/MGen APIs are ready
(ByNum queries, export tables, pnum/typ on nodes).