summary_step5.2.md 2.1 KB

V3 step 5.2 — HIGH/LEN + Strings/TextIO stdlib (done 2026-09-22)

Second stdlib landing. Suite 90/90 (47 run — incl. 4 trap-aborts, 4 sessions, 2 session-output, 1 unit — + 43 reject). LL(1)-clean, zero gm2 warnings.

HIGH / LEN builtins

Pulled forward from step 6 because string libraries need the descriptor length at runtime:

  • Fixed array: HIGH/LEN fold to immediates from the static bounds (ArrayHi/ArrayLen).
  • Open array (formal): read the header — LEN = loadl count, HIGH = loadl count - 1 (new QbeGen.LoadCount).
  • Non-array → 217. Works on nested designators (HIGH(m[i])), since Design yields the inner descriptor address.
  • t_highlen → 18 (HIGH(a)+LEN(a)+F(a) with a 5-element array).

Standard library (stdlib/, classic form)

  • sysio.def/.mod — Write, WriteLn, WriteInt, WriteChar over the shim externals (moved out of tests/ into stdlib/).
  • strings.def/.mod — Length, Assign, Concat, Compare, Copy. The descriptor header holds the logical length: Assign/Concat call the new shim m2setlen so Length reports content, not capacity (otherwise a fixed ARRAY [0..15] would always report 16). Writes are capacity-bounded (truncate, never overrun).
  • textio.def/.mod — ISO-style WriteString/WriteLn/WriteInt/ WriteCard/WriteChar, binding the shim directly (avoids the flatten-on-import name shadowing that would make a wrapper named the same as its SysIO target recurse).

Shim additions (runtime/syslib/shim.c)

m2setlen(desc, n) (set logical length), m2writechar(c).

Harness

build_session now accepts paths (anything containing / is used as-is), so sessions mix ../stdlib/*.def|mod with tests/*. New expect_run_files_out checks the first output line as well as the exit code (Hello → Hello, Modula-2!, StringsProg → Hello World).

Tests

Hello (output), StringsProg (assign/concat/length/compare → Hello World, 11, 1), t_highlen → 18; suite 90/90.

Deferred to 5.3+

WholeIO, Math, Files, Storage/SYSTEM; explicit external link names; string escapes; input (Read). Traps still $abort.