m2comp-step5)Single-image separate compilation, v1 step-11 style: M2comp lib.def
impl.mod prog.mod compiles definitions, then implementations, then
exactly one program into one <Prog>.MC4 (depCount 0). One .LST
per input, fail-fast. Suite 54/54 (41 inherited + 6 run + 7 reject);
all single-file images byte-identical to step 4 (no drift).
M2comp = Unit ".", Unit = "DEFINITION" DefUnit |
"IMPLEMENTATION" ImplUnit | Module. New keywords DEFINITION /
IMPLEMENTATION (token numbers shifted; Msg regenerated from
.err automatically, no test depends on numbers).DEFINITION MODULE L — CONST (integer-family only, else 230) /
TYPE / VAR + procedure HEADINGS (no bodies). All top-level names
auto-exported at END (parameters excluded).IMPLEMENTATION MODULE L — needs L defined (201) and not yet
implemented (200); private CONST/TYPE/VAR + bodies + optional
BEGIN init body. Every heading needs its body at END (231).MODULE — IMPORT L / FROM L IMPORT x need L defined
AND implemented (201). Unknown-module imports stay unchecked
stubs (legacy behavior, unchanged).Incorrect source (no .LST mark). A session
without a program emits nothing (Incorrect source).src/SymTab: session state (no per-file Init; driver inits
once) — SetUnit/UnitKind, BeginDef/EndDef (auto-export +
def registry), DefExists/ImplDone, OpenImpl/EndImpl (fresh
scope + interface materialization), EnterHeading,
BeginBody/EndBodyHeader (body headers re-parse into the heading
entry: signature snapshot compare, 231 on mismatch/double-body),
EnterAlias/SetProcNum (FROM-import materialization),
ExpConstVal + const-value export snapshot (integer family).
231 message already existed in the driver (compiler.frm).DefDecl/ProcHeading, ImplUnit/ImplDecl/ImplProcBody,
rewritten Import (second ax attribute carries alias decl
nodes) + ImpName (201 unknown / 200 duplicate / 230
unsupported), InProc guard (session FROM-import inside a
PROCEDURE is 230), InDef guard (REAL/STRING CONST in a
definition is 230). ConstFold accepts qualified Lib.C (bounds
across files).compiler.frm): SymTab.Init once, per-file
ResetErrors (the firstErr list never reset — stale errors
leaked into later files' listings), unit-root collection, impl→def
merge by module name, ONE MGen.EmitModule over the session
root (program decls chained after the library units; zero units
reuses the program root verbatim).src/MGen (3 small changes): EmitDecls shares the library
global slot for tag-stamped alias nkVars (no double slots);
ConstFindMod + tag-aware PushConstName/ConstTextOf with an
export-table fallback (plain IMPORT + Lib.C needs no
materialization); EmitExpr routes qualified const designators
(aux = KindConst) to the const path.run_tests.sh: expect_run_files / expect_fail_files /
expect_fail_multi (MC4-aware, timeout-guarded like the rest).New tests/d_* (hand-computed ExitCodes): DBasic 60 (FROM +
qualified, var/proc), DFrom 35 (two libs, const/var/proc,
cross-def import), DMulti 68 (qualified VAR actual), DInit 7
(impl BEGIN runs: preset 2 vs zeroed 0), DFunc 81 (nested
function calls), DType 40 (FROM array type + qualified
Lib.Point record). Rejections: unknown definition (201),
signature mismatch (231), missing body (231), unimplemented
import (201), duplicate definition (200), private access (201),
second program file (driver-level).
Unit double-consumed MODULE (every file rejected) — Module
keeps its own keyword.ProcHeading ate the ; its caller also expected (def files
rejected with cascade ';' expected).CONST dbl = step + step doesn't fold (ConstFold
is literal/negation/name-only, pre-existing single-file limit) —
test lib uses a literal + a bound-via-imported-const instead.WITH/CASE,
LONGINT/LONGREAL quads, multi-.MC4 depCount emission.