summary_step5.1.md 2.3 KB

V3 step 5.1 — foreign functions + SysIO (done 2026-09-22)

First stdlib landing: the compiler can now call the host. Suite 88/88 (45 run — incl. 4 trap-aborts, 4 sessions, 1 session-output — + 43 reject). LL(1)-clean, zero gm2 warnings.

EXTERNAL procedures (FFI)

  • Grammar: PROCEDURE P(...); EXTERNAL; — a body-less procedure in an implementation. MarkExternal flags the current heading; its header/scope are discarded (AbortFunc), so no function is emitted.
  • SymTab: ext + link on the procedure node; MarkExternal, IsExternal, ProcLink. The flag rides the node, and the implementation resumes the definition's node (ResumeProc), so clients that IMPORT/FROM-import the routine also see it as external.
  • QbeGen: Mangled binds an external procedure to its link name (default: its own name — a valid C symbol; m2write etc.).
  • No static link for C callees: CallBegin/CallEnd gained an isExt flag; the hidden static-link argument is omitted for external calls (the shim signature has no link).

Runtime shim (runtime/syslib/shim.c)

Small C layer that knows the compiler's memory layout. A string (ARRAY OF CHAR) value is a descriptor { LONGCARD count, bytes }; the compiler passes its address as an l. Shim exports: m2write(desc), m2writeln(), m2writeint(v), m2exit(code). Linked into every session image by the harness.

SysIO library (tests/sysio.def + .mod)

Classic DEFINITION/IMPLEMENTATION (separate compilation): Write(VAR s : ARRAY OF CHAR), WriteLn, WriteInt(n), each a thin Modula-2 wrapper over an EXTERNAL shim routine. This also exercises passing a string literal as a VAR ARRAY OF CHAR actual: literals now register their static descriptor address in the actual-address note table.

Tests

Hello → stdout Hello, Modula-2! then 42, exit 0 — the first V3 program with real output, checked by the new expect_run_files_out harness (exit code + first output line). Harness refactor: build_session (compile→qbe→cc with the shim) shared by expect_run_files / expect_run_files_out.

Deferred to 5.2+

SYSTEM/Storage (malloc/free wrappers), Strings, TextIO, WholeIO, Math, Files; explicit external link names (EXTERNAL "c_name"); string escapes (so literals are raw bytes — newlines come from WriteLn); reading input.