session-2026-09-22-step5.md 3.2 KB

Session save — 2026-09-22 (m2compiler-V3, step 5 complete)

Where we are

HEAD: d260e48 — milestone tag v3-step5 (alongside v3-step5.1 … v3-step5.4). Suite 94/94 (51 run — incl. 4 trap-aborts, 5 sessions, 2 session-output, 2 session-input, 1 unit — + 43 reject). Build warning-free. Tree clean; git.txt untracked (now in .gitignore). No remote.

Step 5 in four landings (all green at each tag)

  • v3-step5.1 (88/88) — foreign functions: PROCEDURE P(...); EXTERNAL;, C link-name mangling, no static link for C callees; runtime/syslib/shim.c (knows the descriptor layout); SysIO (Write/WriteLn/WriteInt/WriteChar); first real output.
  • v3-step5.2 (90/90) — HIGH/LEN (static for fixed arrays, header-read for open formals); stdlib/strings (Length/Assign/Concat/Compare/Copy, logical-length via m2setlen); stdlib/textio.
  • v3-step5.3 (93/93) — Math (libm sqrt/exp/ln/sin/ cos/arctan/abs, Pi/E); input (m2readchar/ m2readint, SysIO.ReadChar/ReadInt, harness stdin variant); stdlib/wholeio.
  • v3-step5.4 (94/94) — Files (stdio OpenRead/OpenWrite/ Close/Read*/Write*; opaque pointer handle).

stdlib/: sysio, textio, strings, wholeio, math, files.

Locked decisions from this session

  • Runtime is a C shim (runtime/syslib/shim.c) that encodes the compiler's memory model (a string = [LONGCARD count, bytes]); stdlib binds it with EXTERNAL. Traps are still $abort.
  • A string's descriptor header holds its logical length, updated by m2setlen on Assign/Concat (fixed arrays would otherwise always report their capacity).
  • Host pointers must be pointer-class types. File = INTEGER (w) truncated a C FILE*; File = POINTER TO FileRec (l) is required. Applies to any future handle type.

Known limitations found (next work)

  1. Module-level globals are not module-qualified — DeclVar emits data $<name>, so two modules with the same global name collide at link time. Functions are safe (<proc>_<uid>, uid unique per session).
  2. Qualified access is flatten-on-import — L.x clones x into the client scope; if the client already imported a same-named export from another module, the call resolves to the wrong signature (233). The tests avoid mixing same-named imports.

Both are fixed by a symbol-naming pass: prefix module-level globals with their defining module and resolve L.x/L.P per-module instead of flattening. That also unblocks Storage/ SYSTEM (ADDRESS, generic pointers) and is a prerequisite for the step-7 syslib port and self-hosting.

Deferred (carry forward)

Storage/SYSTEM (ALLOCATE/DEALLOCATE, ADDRESS, generic pointers), ReadString, string escapes, explicit external link names (EXTERNAL "c_name"), and the step-6 Unicode work (UCHAR/UString, UTF-8 lexer). Traps still $abort; runtime/syslib SYSTEM/Storage/Trap land with step 7.

Resume commands

cd /home/eric/Projets/Projets-Modula2/MyWork/m2compiler-V3/compiler
./build.sh && ./run_tests.sh   # expect 94/94, zero gm2 warnings

Recommended next: the symbol-naming / qualified-resolution pass.