summary_unicode-stdlib.md 4.1 KB

Session summary — Unicode (UCHAR/UString) + stdlib Conversions/RealIO

Date 2026-09-28 (second save). Suite 122/122; self-hosting fixpoint OK (bootstrap/fixpoint.sh, image 2,062,392 bytes). master, tree clean except the user's uncommitted compiler/toto.mod.

Tags this session: v3-unicode-1, v3-unicode-2, v3-stdlib-conversions, v3-unicode-stdlib-summary (this doc).

1. Unicode step — complete

Implemented in two increments (docs/summary_unicode.md).

Increment 1 — types, literals, conversions (af09dc6, v3-unicode-1)

  • UCHAR: 32-bit codepoint 0..1114111 (QBE w), a distinct type (ClUChar/FUChar), usable in declarations and ARRAY OF UCHAR.
  • U'..' / U".." literals (ustring token). One codepoint → UCHAR immediate; otherwise a UString descriptor data $ustrN = { l count, w cp0, … } — which is a V3 length-prefixed array, so a literal is a valid actual for an open ARRAY OF UCHAR formal.
  • Strict RFC 3629 decoding (QbeGen.DeclUStr): overlong, surrogate (D800..DFFF), >10FFFF, truncation → semantic error 234 invalid UTF-8 in U-literal.
  • UCHR, CHR8 (l-domain 0..255 check → trap), UORD.

Increment 2 — codec + output (f1bfd76, v3-unicode-2)

  • runtime/syslib/Utf8 — Decode/Encode (MaxUTF8Length = 4, MaxCodePoint = 1114111).
  • TextIO.UWriteChar / UWriteString(VAR u: ARRAY OF UCHAR) / UWriteLn — real UTF-8 on stdout (verified byte-for-byte).

Flagged deviations from the locked design

  • UORD returns INTEGER, not LONGCARD: V3 has no LONGCARD type name and no 64→32-bit conversion, so a LONGCARD result would be unusable in codegen; a codepoint fits in 32 bits.
  • UCHR also accepts an integer-family operand (the UCHAR constructor), so a computed codepoint can be built without a literal.
  • The front end decodes in QbeGen.DeclUStr: Stage 1 is gm2-built and does not know UCHAR, so the compiler cannot import Utf8.
  • .ssa is still written when error 234 fires (image gate pending).

2. stdlib — Conversions + RealIO

(2f80422, v3-stdlib-conversions; docs/summary_stdlib-conversions.md.)

  • Conversions: IntToStr/CardToStr (M2), RealToStr (shim %.6E), StrToInt/StrToCard (whole-string parse), StrToReal (shim strtod) — BOOLEAN results.
  • RealIO: WriteReal, WriteRealF(x, width), ReadReal.
  • runtime/syslib/shim.c: m2realstr, m2strreal, m2writereal(f), m2readreal.

Conversions uses BOOLEAN rather than the ISO ConvResults enumeration (V3 enumeration values in expressions are still 230).

Tests added this session

  • t_unicode.mod (exit 31) — U'é', U'😀', U'€', UCHR, CHR8, UORD.
  • t_trap_chr8.mod — CHR8(U'😀') aborts (rc 134).
  • t_bad_overlong.mod, t_bad_surrogate.mod, t_bad_utf8big.mod, t_bad_truncutf.mod — expect error 234 (raw invalid bytes; .LST output git-ignored).
  • utf8_prog.mod (exit 127) — Utf8 round-trips.
  • utext_prog.mod — TextIO.UWriteString(U"héllo") → stdout héllo.
  • conv_prog.mod (exit 127) — Conversions round-trips.
  • realio_prog.mod (exit 42) — WriteReal→3.500000E+00, reads 1.25.

Tags of interest

  • v3-unicode-1 — af09dc6 (types/literals/conversions).
  • v3-unicode-2 — f1bfd76 (codec + UTF-8 output).
  • v3-stdlib-conversions — 2f80422 (Conversions/RealIO).
  • Earlier milestones: v3-fixpoint, v3-bootstrap, v3-stdlib-broaden, v3-selfhosting.

Resume

cd .../m2compiler-V3
./bootstrap/fixpoint.sh                       # FIXPOINT OK
cd compiler && ./build.sh && ./run_tests.sh   # 122/122

Remaining polish

  • Unicode: UString whole-string assignment to a fixed array (the count check traps, as it does for CHAR arrays today); UString =/+/concat.
  • stdlib: ProgramArgs (shim m2argc/m2arg already exist), IOChan; ConvResults once enumerations are usable in expressions.
  • Language: enum literals in expressions / CASE labels; strict 231 def/impl signature checks; suppressing .ssa on error 234.