summary_forward-calls.md 3.2 KB

Within-module forward procedure calls — M2S and M2P compile clean (110/110)

Tag v3-forward-calls.

The finding

CR's parser output relies on gm2 hoisting: by default it wraps its forward declarations in a comment ((* ----- FORWARD not needed in multipass compilers … *)). The -m flag toggles that (M Suppresses FORWARD declarations in parser (for multipass compilers)), and our build.sh passed -m.

V3 is single-pass, so with -m the generated M2P.mod had ~102 undeclared identifier errors for its own procedures.

The fix (two halves)

  1. Emit real FORWARD declarations for V3-facing generation — run CR without -m. V3 already supports FORWARD (including mutual recursion); verified with a direct test.
  2. Keep -m for the gm2 stage-1 build. gm2 compiles FORWARD fine (gm2 -c OK) but its link-time whole-program/“pass 3” recompilation rejects FORWARD in an implementation module (too many errors in pass 3); reproduced minimally, and -fscaffold-*, -fno-whole-program etc. do not help.

So the bootstrap is stage-specific: stage 1 (gm2) generates with -m; stage 2+ (V3) generates without -m. The .ssa fixpoint is between V3 stages, both using the FORWARD form.

Other fixes in this step

  • Empty ELSIF … THEN body — the earlier [ StatSeq ] change had missed the ELSIF site (different indentation); CR-generated code hits it (comment-only THEN).
  • BITSET — added as a predefined type (SET OF [0..15]).
  • Typed set constructor TypeName{ … } (BITSET{0}, BITSET{}) — new TypedSetLit rule; Fact uses it when a type name designator is followed by {.
  • File-handle leak — compiler.frm never closed the source file, so each session source consumed a handle and the host FileIO cap (MaxFiles = BitSetSize = 16) tripped once a session had >16 sources (exactly the compiler's own build). The driver now closes src after each file.

Result

Under V3 (sources generated without -m):

Source Errors
SymTab 0
QbeGen 0
M2S 0
M2P 0 (was 107 before FORWARDs, then 5, then 0)

Main suite 110/110.

Remaining: the driver M2.mod (12 errors)

  • Nested modules — the driver's ListHandler is a Wirth-style local MODULE … EXPORT StoreError, PrintListing, …, which V3 parses but marks 230; its exports (StoreError, PrintListing, PrintConsoleErrors, ResetErrors) are therefore undeclared at the enclosing scope.
  • String building — the driver uses Strings.Delete/Append to construct file names. V3's descriptor header is both the open-array count and the logical string length (m2setlen sets it), so once Assign shrinks it, Append writing past the logical length traps. Delete alone is fine; incremental Append needs a model decision (or a driver rewrite).

Build note

Generating for V3 (no -m) and for gm2 (-m) are different commands; this wants a small stage-aware build script (or a build_v3.sh), which also feeds bootstrap/fixpoint.sh.

Files

compiler/src/M2.atg, compiler/src/SymTab.mod, compiler/src/compiler.frm, compiler/src/M2.lst.