# m2compiler-V3 — feature status (at `v3-string-variant-nested`, 169/169 green) Pipeline: Coco/R `M2.atg` (1748 lines, 73 productions) → `gm2`-built `M2` → QBE `.ssa` → `qbe` → `cc` → run. `SymTab.mod` 1623 lines, `QbeGen.mod` 2193 lines. Regenerate with `cd compiler && ./build.sh && ./run_tests.sh`. Legend: ✅ done · 🔄 partial · ⏸ not started / deferred. ## Lexical / syntax - ✅ Classic idents (no `_`), `0x`/`0X` hex (no `H`), reals with `E` exponents, `#` `<` `<=` `>` `>=` `=`, `//` + nested `(* *)`, strings `'…'`/`"…"`, `0x` array bounds. - ✅ `NOT`/`AND`/`OR` (no `~`/`&`), unary minus at expr start, no octal `B`/`C` suffixes. ## Types - ✅ `INTEGER`/`CARDINAL`/`SHORTINT`/`LONGINT` (one family, QBE `w`), `REAL`/`LONGREAL` (`d`, widened), `BOOLEAN`, `CHAR`. - ✅ Named types, aliases, integer/char subranges (folded bounds), enumerations (literals carry ordinals; usable in expressions, `CASE` labels, `CONST` and as parameter/value types). - ✅ `ARRAY [lo..hi,…]` (multi-dim) and open `ARRAY OF` formals. - ✅ Array constructors `T{…}` (GNU Modula-2): a `CONST` of an array type fills a pooled static descriptor (copied/indexed like a declared array); scalar elements, nested `Sub{…}`, string elements for nested `ARRAY OF CHAR`, and the `expr BY n` repeat form. - ✅ Record constructors `Rec{…}` (fields in declaration order) and runtime construction: any non-constant element builds the array/ record descriptor on the stack and fills it in place, so constructors also work outside `CONST` (`a := arr{i, i+1}`, `p := Person{"Blaise Pascal", d}`); a `CONST` with all-constant elements still bakes a static descriptor. Set fields, and constant string concatenation folded into a `CHAR`-array element, included. - ✅ Index-type arrays `ARRAY OF T`; enum values usable as array indices. - ✅ `MIN`/`MAX` over any ordinal type, array or set; REAL/LONGREAL and LONGINT bounds too. - ✅ gm2 sized/scalar names: `LONGCARD`, `SHORTREAL`, `INTEGER8/16/32/64`, `CARDINAL8/16/32/64`. - ✅ `FROM libc IMPORT printf, exit, …`: intrinsic permissive external C procedures (varargs, no result); string/CHAR-array actuals pass as `descriptor+8`. - ✅ Set builtins `INCL`/`EXCL` and `SHIFT`/`ROTATE`; `SET OF ` and `SET OF `; set spans up to 65536. - ✅ Module-level forward type references (a global may name a type declared further down; emission deferred). - ✅ `RECORD` (flat blobs, nested inline, array fields as pointers), including variant records (`RECORD … ; CASE tag : T OF … END`): plain fields pack before the tag, each branch's fields overlay after it. - ✅ `SET OF` bool/char/subrange (multi-word masks). - ✅ `POINTER TO`, `NIL` as a real type, `ADDRESS` ↔ any pointer assignment (`p := ADR(x)`). - ✅ `UCHAR` (32-bit codepoint) + `U'a'`/`U"…"` literals (strict RFC3629 decode → 234 on bad bytes), `UCHR`/`CHR8`/`UORD`, `U"…"` whole-string assignment to a 1-D `ARRAY OF UCHAR`, `+` concatenation of `U"…"` (and single-codepoint operands), and `LEN`/`LENGTH`/`HIGH` of a UString. - ✅ Opaque `TYPE T;` + completion in the implementation. - ✅ Variant records (`RECORD CASE … OF … END`); whole-record assignment is a flat byte blit (correct for overlapping fields) and whole-record `=` is 213. - ✅ Opaque/forward types used as values: an unresolved (opaque or forward) alias is pointer-like (assign `NIL`, copy, compare, pass). gm2's `String` is **not** built in — it is an opaque type imported from a definition module (`DynamicStrings`, or a local `opaque`); an undeclared type name is an error as in gm2. ## Declarations - ✅ `CONST` (integer/char/real literals, folded), `VAR`, `TYPE`, `PROCEDURE` headings + bodies, `FORWARD`. - ✅ `DEFINITION`/`IMPLEMENTATION` modules, `IMPORT`/`FROM … IMPORT`, `EXPORT` (parsed), nested local `MODULE` (including `EXPORT` lists, nested-nested modules, and bodies lowered as startup init functions). - ✅ Opaque completion; opaque/forward types used as pointer-like values; module `BEGIN` init bodies. - ✅ Strict impl-vs-def signature checks (error **235**): result type, formal count, formal types and `VAR`-ness are compared against the `DEFINITION` (was arity-only). ## Statements - ✅ Assignment, `IF/ELSIF/ELSE`, `CASE` (labels, ranges, `ELSE`), `WHILE`, `REPEAT/UNTIL`, `LOOP/EXIT`, `FOR/TO/BY` (static sign), `WITH` (single/multi/nested), `RETURN` (232-checked), `NEW`/`DISPOSE` (builtins), bare and parenthesized calls. - ✅ `HIGH`/`LEN`; ⏸ `GOTO`/labels. ## Expressions - ✅ Full precedence, `+ - * / DIV MOD`, comparisons, eager `AND`/`OR`/`NOT`, `IN`, set ops (`+ - * /` = union/diff/inter/symdiff), pointer `=`/`#`, int→real conversion, `^` deref, indexing, field access, qualified `L.x`/`L.P`. - ✅ String `=`/`#` (content), string `+` (concatenation for literals, `CHAR` arrays and `CHAR` operands), string assignment (content copy, truncated to the array capacity, NUL-terminated), `LEN`/`LENGTH` of arrays and string literals. UString `+`/`LEN` likewise. - ✅ `NIL` comparisons/assignment. - ✅ `VAL`/`ADR`/`TSIZE`/`SIZE`/`HIGH`/`LEN` work. ✅ Result suffixes (`F()^`, `F()[i]`, `F().field`): components after a call result, loaded like Design components. ## Procedures & modules - ✅ Value + `VAR` params, function results, recursion, mutual recursion (`FORWARD`), nested procedures with static-link display (any depth), array/record/set/pointer params, open-array `VAR` formals. - ✅ Separate compilation: `lib.def lib.mod prog.mod` → one image; module init functions; opaque completion; strict 235 signature checks between a definition and its implementation. - ⏸ Procedure-type variables / indirect calls, per-file object emission, import cycles. ## Backend (QBE) - ✅ Length-prefixed arrays (count + elements), deep record copy, count-checked whole-array assign, runtime bounds/span traps (`$abort`, rc 134), multi-word sets, `alloc8` heap (`malloc`/`free`), static-link frames, deterministic `%tN`/`@LN`, whole-image buffering. - ✅ `REAL` runtime const flush, string literals as descriptors. - ⏸ `runtime/syslib/Trap` (traps are `$abort` for now), recursive `DISPOSE`. ## Error codes - ✅ 200/201/202, 210–222, 223 (declared), 230, 231, 232, **233 `invalid call`**, **234 `invalid UTF-8 in U-literal`**, **235 `implementation does not match definition`**, plus `file:line:col` console format. ## Library - ✅ `runtime/syslib`: `SysShim`, `FileIO`, `Utf8` (UTF-8 codec). - ✅ `stdlib`: `SysIO`, `TextIO` (+ UTF-8 `U*`), `WholeIO`, `Math` (incl. `log10`/`atan2`/`sinh`/`cosh`/`tanh`/`hypot`/ `floor`/`ceil`/`trunc`/`round`/`fmod`; `ln`/`arctan` wrap `log`/`atan`), `Strings` (incl. `Slice` (Python-style), `Insert`, `Replace`, `Capitalize`), `CharClass`, `Files` (layered on `IOChan`), `Conversions` (ISO `ConvResults` statuses + BOOLEAN shortcuts), `RealIO`, `ProgramArgs`, `SysClock`, `IOChan` (streams + files; `Position`/`Seek`/`Rewind`), `Storage`. - ✅ gm2/ISO text + conversion library added: `ConvTypes`, `IOConsts`, `SIOResult`, `TERMINATION`, `StrIO`, `InOut`, `StdIO`, `WholeStr`, `RealStr`, `LongStr`, `LongMath`, `LongIO`, `STextIO`, `SWholeIO`, `SRealIO`, `DynamicStrings` (core subset), `SysStorage`. ## Coroutines - ✅ PIM/SYSTEM coroutines: `PROCESS`, `NEWPROCESS`, `TRANSFER`, `IOTRANSFER` (the last degrades to a transfer without an interrupt subsystem). Bind to `ucontext` helpers in the shim; coroutine bodies are called with a 0 static link (module-level procedures). ## Not started - ✅ Clarion `CLASS`: fields, methods (value/VAR formals, results), single inheritance, `WITH`, a hidden `THIS` receiver, **`VIRTUAL` dynamic dispatch via vtables** (with subtype pointer assignment), bare sibling-method calls (a call on `THIS`), and a class `BEGIN … END` init body (runs at startup). ⏸ Multiple parents (deliberately single inheritance only; a Tier-1/Tier-2 cost breakdown for future MI is recorded in `docs/OOP.txt`). See `docs/summary_class-lowering.md`, `docs/summary_virtual-dispatch.md`, `docs/summary_class-finish.md`. - ✅ `VAL` conversions across `INTEGER`/`CHAR`/`BOOLEAN`/enum, `INTEGER`↔`LONGINT` (widen/narrow), `INTEGER`/`LONGINT`↔`REAL` (truncate/widen) and pointer↔pointer. The TopSpeed legacy grammar (`TopSpeed-V3-M2.atg`) is a separate sidecar, not merged. (Self-hosting is reached: `bootstrap/fixpoint.sh` builds a byte-identical compiler image; `stdlib/` + `runtime/syslib` are in use. See `docs/summary_selfhosting.md`.) Next: variant records, `UString` assignment, `Files` on `IOChan`. Roadmap: `docs/plan.md`, `docs/blaise-phases-map.md`.