summary_step11.md 3.5 KB

Step 11 — Separate compilation units (DEFINITION/IMPLEMENTATION/IMPORT)

157/157 tests green (144 + 7 run + 6 rejection), mc64 boot + example green, Showcases unchanged (157, 83, 168), new Showcase4 prints 225 as hand-computed.

Goal

DEFINITION/IMPLEMENTATION compilation units with IMPORT/FROM, compiled from several files into a single .MC4 image (the remaining big item from the step-10 limits).

What was built

  • Driver (compiler.frm, the true source of generated M2c.mod): multi-file session M2c lib.def libimpl.mod ... prog.mod, one .LST per input, fail-fast on the first bad file (no HALT abort: a clean EXIT with Incorrect source). SymTab.Init and MGen.OpenModule("") run once; the program unit sets the image name (MGen.SetModName).
  • Grammar (M2c.atg): M2c = Unit, Unit = DefUnit | ImplUnit | ProgUnit. New DEFINITION/IMPLEMENTATION keywords were added in end-of-file productions so existing token numbers only shifted by position — CR regenerates M2c.mod's Msg table from M2c.err (verified identical mapping); new-productions note added.
  • SymTab: definition interfaces publish to the existing export tables plus an in-memory side table (8 defs, 32 names each); OpenImplementation re-enters the interface into a fresh scope (slots allocated once at definition, found via the module context); procedure headings match through the forward machinery (ReuseProc/VerifyProc, 231 on mismatch); CloseImplementation requires every body (231). FROM L IMPORT x materializes real alias symbols (EnterImpProc shares the proc number, so call checking is unchanged; VAR/CONST aliases resolve through the new GlobAlias hook in MGen.QualGlob, the single funnel for all global use-paths). Ghosts are 201, bad kinds 221, duplicates 200.
  • run_tests.sh: expect_run_files / expect_fail_files for multi-file sessions.

Tests — 157/157 (144 + 7 + 6)

7 run: d_basic 25 (FROM var/func, qualified const/var/call, VAR param, lib init), d_from 12 (exported array type, private impl helper, VAR composite formal), d_multi 82 (two libs, implementation-level IMPORT), d_init 510 (init order across files, init reading another lib via FROM), d_func 55 (recursive lib function), d_type 1122 (exported record, VAR record formal), d_case 25 (qualified enum CASE labels). 6 rejections, each exactly one error: d_bad_nodef 201, d_bad_sig 231, d_bad_nobody 231, d_bad_imp 201, d_bad_exp 201, d_bad_dup 200.

Bugs found and fixed

  1. DefProcHead double-semicolon: heading already consumes its own ; (';' expected on the first definition).
  2. HALT on compile failure aborts (SIGABRT, Abandon noise in every rejection run) — replaced with a clean loop EXIT.
  3. Value composite formals in a test (Sum(x : Vec)) correctly hit the pre-existing 230 rule — test switched to VAR formal.
  4. M2c.mod is REGENERATED by CR from compiler.frm on every build: driver edits first went to M2c.mod and were silently lost. Driver work belongs in compiler.frm (same for the Msg table, auto-mirrored from M2c.err).

Known limits (deferred)

M.x as a VAR actual is still 233 (pre-existing local-module limitation, confirmed identical on step-10 build — Showcase4 works around it via a temp); second program unit rejected (230 + follow-on 200); multi-.MC4 images with depCount loading (still single image, depCount 0); circular imports; opaque types; WITH-field VAR actuals; CHAR/BOOLEAN tails as VAR actuals.