Jelajahi Sumber

docs: record open-array M5 record fields and constructors

Eric Streit 22 jam lalu
induk
melakukan
680ace0bd4

+ 5 - 4
README.md

@@ -47,19 +47,20 @@ docs/              STATUS.md, plan.md, plan-*.md, analysis_*.md, summary_*.md
 
 ## Status (2026-10-23)
 
-- Suite **295/295**; self-hosting **fixpoint OK** (byte-identical
-  stage2/stage3, 3,480,366 bytes); corpus **518/612 compile-OK,
+- Suite **299/299**; self-hosting **fixpoint OK** (byte-identical
+  stage2/stage3, 3,534,072 bytes); corpus **518/612 compile-OK,
   0 crashes** (`tools/v3-corpus`; the corpus is gm2's testsuite, so it
   mixes conforming Modula-2 with gm2 leniencies — see `docs/gaps/`).
   The remaining `except*`/`onebyte*`-style corpus files still hit V3's
   declaration-order policy.
-- Active branch **`master`**, feature state **`v3-open-arrays-m4`**.
+- Active branch **`master`**, feature state **`v3-open-arrays-m5`**.
   Recent milestones: `PACKEDSET`, ISO exceptions (`EXCEPT`/`RETRY`,
   `EXCEPTIONS`, `M2EXCEPTION`, catchable language traps including
   `functionException`, module `FINALLY`), self-referential pointer
   records/chained fields, and multi-dimensional fixed/open arrays
   (M1–M4): flat payloads + per-level views, open-array calls, and
-  payload `SIZE`/view `ADR`.
+  payload `SIZE`/view `ADR`, and flat multi-dimensional record fields
+  and constructors.
 
 Lowers today: program modules; `CONST`/`VAR`/`TYPE` (scalars,
 subranges, enums, arrays, records incl. variants and self-referential

+ 7 - 5
docs/INDEX.md

@@ -20,7 +20,7 @@ bisecting *why* a decision was made, not for reading end-to-end).
 - **`features.md`** — the feature list.
 - **`comparison-PIM4-gm2-V3.md`** — PIM4 / GNU Modula-2 / **M2R10** /
   **TopSpeed V3** / V3 feature comparison (2026-10-23; V3 at
-  `v3-open-arrays-m4`; filename kept for link stability).
+  `v3-open-arrays-m5`; filename kept for link stability).
 - **`analysis_gaps.md`** — language gaps + corpus notes.
 - **`gaps/README.md`** — minimal reproducers, one per unsupported gap,
   and the gm2-extension policy.
@@ -45,9 +45,8 @@ bisecting *why* a decision was made, not for reading end-to-end).
 - **`design-open-arrays.md`** — multi-dimensional open-array ABI:
   per-level view descriptors over a flat backing block, payload
   `SIZE`/`ADR`, fixed/open 2-D and 3-D arrays, row/byte flattening,
-  records/constructors and corpus mapping.  M1–M4 are implemented;
-  M5 (record fields/constructors) and the optional pointer-based 1-D
-  view remain.
+  records/constructors and corpus mapping.  M1–M5 are implemented;
+  only the optional pointer-based 1-D view and final M6 polish remain.
 - `blaise-phases-map.md`, `language-report.md`, `grammar.md` — the
   grammar/phases reference.
 - `summary_l3_selfhost_fix.md` — the self-host root cause; also where
@@ -55,10 +54,13 @@ bisecting *why* a decision was made, not for reading end-to-end).
 
 ## Recent session summaries (newest first)
 
+- **`summary_session-2026-10-24-open-arrays-m5.md`** — M5 record
+  fields and constructors: inline flat payloads, synthesized field
+  views, static/runtime constructors; tag `v3-open-arrays-m5`.
 - **`summary_session-2026-10-23-open-arrays.md`** — fixed/open
   multi-dimensional arrays M1–M4: flat payload + views, open calls,
   row/subarray conversion, payload `SIZE`/`ADR`; tags
-  `v3-open-arrays-m4` and `v3-open-arrays-m4-summary`; next M5.
+  `v3-open-arrays-m4` and `v3-open-arrays-m4-summary`.
 - **`summary_session-2026-10-23-exceptions.md`** — ISO exceptions
   M1–M5: parser/AST, runtime/codegen, `EXCEPTIONS`/`M2EXCEPTION`,
   index/range/CASE traps; tag `v3-exceptions`; corpus caveats.

+ 5 - 6
docs/STATUS.md

@@ -4,9 +4,9 @@ This answers "where are we now?".
 
 ## Numbers
 
-- Suite **295/295** (`compiler/run_tests.sh`).
+- Suite **299/299** (`compiler/run_tests.sh`).
 - Self-hosting **FIXPOINT OK** — stage2 and stage3 images are
-  byte-identical (3,480,366 bytes).
+  byte-identical (3,534,072 bytes).
 - Corpus **518 / 612** sources compile with 0 errors, **0 crashes**
   (`tools/v3-corpus/corpus.sh` over the gm2 testsuite; the harness now
   resolves V3's own shipped libraries); the rest are genuine language
@@ -14,7 +14,7 @@ This answers "where are we now?".
   imports of gm2-only modules.  Open-array corpus cases `unbounded`,
   `unbounded2`, `unbounded3`, `unbounded4` and `array9` now compile;
   `unbounded`/`unbounded2`/`unbounded3`/`unbounded4` also run.
-- Branch **`master`**, feature state **`v3-open-arrays-m4`**; tree
+- Branch **`master`**, feature state **`v3-open-arrays-m5`**; tree
   clean.
 
 ## Architecture (current)
@@ -179,9 +179,8 @@ declarations still work (`t_fwdproc`, `t_fwdok`).
    at the stop point.  The remaining `LANG` entries are mostly:
    **declaration order** cases V3 rejects by policy (`docs/gaps/`); ISO
    exceptions (coroutine/protection follow-ups — see
-   `docs/design-exceptions.md`); gm2-only extensions; and the M5
-   array tail (record fields/constructors plus the optional
-   pointer-based 1-D view migration).  See
+   `docs/design-exceptions.md`); gm2-only extensions; and the optional
+   pointer-based 1-D view migration.  See
    `docs/handoff-2026-10-23-next.md` and `docs/analysis_gaps.md`.
 2. ~~**The size-sensitive V3 miscompile**~~ — **root-caused and fixed**
    (2026-10-19; see `docs/summary_l3_selfhost_fix.md`).  It was never

+ 4 - 4
docs/comparison-PIM4-gm2-V3.md

@@ -1,7 +1,7 @@
 # PIM4 vs GNU Modula-2 vs M2R10 vs TopSpeed V3 vs V3 — feature comparison
 
-**Date:** 2026-10-23 · **V3 state:** `v3-open-arrays-m4` (suite
-295/295, self-hosting fixpoint OK 3,480,366 bytes, corpus 518/612,
+**Date:** 2026-10-24 · **V3 state:** `v3-open-arrays-m5` (suite
+299/299, self-hosting fixpoint OK 3,534,072 bytes, corpus 518/612,
 0 crashes).
 
 **Scope and sources.**
@@ -76,7 +76,7 @@ change individual cells.
 | Fixed / multi-dimensional arrays | ✅ `[a], [b] OF` | ✅ | ✅ `ARRAY count, count OF` (zero-based) | ✅ | ✅ both `[a], [b]` and `[a, b]` |
 | Open arrays (1-D) | ✅ | ✅ | ✅ (`BARE ARRAY OF`) | ✅ | ✅ |
 | Multi-dimensional open arrays | ❌ (ISO addition) | ✅ | 🔄 one-dimensional `BARE` arrays | ❌ | ✅ (flat payload + per-level views; legacy 1-D ABI adapter) |
-| Records | ✅ | ✅ | ✅ extensible | ✅ | ✅ (incl. self-referential pointer fields) |
+| Records | ✅ | ✅ | ✅ extensible | ✅ | ✅ (incl. self-referential pointer fields and flat multi-dimensional array fields) |
 | Variant records | ✅ | ✅ | ❌ removed (extensible records replace them) | ✅ | ✅ (plus empty arms/`ELSE`) |
 | Pointers, `NIL`, opaque types | ✅ | ✅ | ✅ (`OPAQUE` keyword) | ✅ | ✅ (incl. chained `p^.next^.value`) |
 | Procedure types | ✅ (`PROCEDURE`) | ✅ (`PROCEDURE`, `PROC`) | ✅ (comma-separated formals) | ✅ | ✅ (`PROCEDURE`, `PROC`; comma/unnamed forms) |
@@ -201,7 +201,7 @@ change individual cells.
 - V3: `docs/STATUS.md`, `docs/features.md`, `docs/gaps/README.md`,
   `docs/analysis_gaps.md`,
   `docs/summary_session-2026-10-23-open-arrays.md`; the gates in this
-  document were run at `v3-open-arrays-m4`.
+  document were run at `v3-open-arrays-m5`.
 - gm2: the GCC Modula-2 testsuite and `gm2-libs`/`gm2-libs-iso`
   definition modules in the sibling `gcc-git` tree.
 - M2R10: the published R10 grammar (m2r10-grammar.gll) and

+ 26 - 10
docs/design-open-arrays.md

@@ -1,11 +1,12 @@
 # Design — multi-dimensional open arrays
 
-**Status: design + M1 helpers + M2 fixed storage + M3 open views + M4
-builtins (2026-10-23).**  Rank-2/3 fixed and open arrays use the view ABI;
-array `SIZE`/`TSIZE` and view `ADR` are implemented.  The 1-D open
-descriptor still uses its legacy `{count,data}` layout at ABI boundaries.
-Current gates: suite **295/295**, fixpoint OK **3,480,366 bytes**, corpus
-**518/612 compile-OK**, 0 crashes.
+**Status: design + M1–M5 (2026-10-24).**  Rank-2/3 fixed and open
+arrays use the view ABI; array `SIZE`/`TSIZE` and view `ADR` are
+implemented; multi-dimensional record fields and constructors use the
+flat layout.  The 1-D open descriptor still uses its legacy
+`{count,data}` layout at ABI boundaries.  Current gates: suite
+**299/299**, fixpoint OK **3,534,072 bytes**, corpus **518/612
+compile-OK**, 0 crashes.
 
 Interactive decisions already taken:
 
@@ -423,10 +424,25 @@ Gates after each step: suite, fixpoint, corpus.
      pointer-based view (row `ADR` identity through a 1-D internal call).
      The current adapter preserves writes but is copy-based.  This does
      not block the corpus cases that reach the compiler today.
-5. **M5 — records/constructors/corpus**
-   (multi array fields, records arrays, constructors; run the 8 corpus
-   cases).
-6. **M6 — docs/gates/tag `v3-open-arrays`.**
+5. **M5 — records/constructors** — **done (2026-10-24)**
+   - Record/class layout stores rank-2/3 array fields as inline flat
+     payloads; `TypeSizeD`/`FieldSize` use payload size for those
+     fields.  Nested records and array-of-record layout follow.
+   - `Lower` synthesizes a fresh view chain when a multi field is
+     selected (`MakeFieldView`), so indexing, passing to open formals,
+     `SIZE`, `ADR`, and whole-row assignment work.
+   - Static record data (`RecItems`/`ArrBodyItems`) writes zero flat
+     payloads; large record arrays use the existing template/init loop;
+     local/heap records zero multi fields through `InitMultiField`.
+   - Runtime and static constructors handle multi fields:
+     `CtorRecStatic` flattens nested array constructors into the field
+     payload; runtime record construction builds a field view and copies
+     through it.  Array-of-record constructors inline record elements
+     statically and copy records at runtime.
+   - Tests: `t_record_multidim`, `t_record_multidim_ctor`,
+     `t_record_multidim_const`, `t_record_multidim_arrctor`, plus
+     `t_nestarr`; suite 299/299.
+6. **M6 — final docs/gates/tag `v3-open-arrays`.**
 
 `unbounded5` remains a declaration-order case, not this feature.
 

+ 9 - 4
docs/features.md

@@ -1,4 +1,4 @@
-# m2compiler-V3 — feature status (2026-10-23; suite 295/295 green)
+# m2compiler-V3 — feature status (2026-10-24; suite 299/299 green)
 
 Pipeline: Coco/R `M2.atg` (1748 lines, 73 productions) → `gm2`-built
 `M2` → QBE `.ssa` → `qbe` → `cc` → run. `SymTab.mod` 1623 lines,
@@ -29,7 +29,9 @@ Legend: ✅ done · 🔄 partial · ⏸ not started / deferred.
   repeated-group form `ARRAY [lo..hi], [lo..hi] OF T`; fixed and open
   multi-dimensional formals (`ARRAY OF ARRAY OF …`) use flat payloads
   + per-level views, with row/subarray conversion and open-to-open
-  forwarding.
+  forwarding.  Record/class fields of rank 2/3 are inline flat payloads
+  with synthesized views; record and array-of-record constructors
+  support them.
 - ✅ ISO empty string literal: `""`/`''` is compatible with `CHAR`
   (value 0) in assignment, comparison, `CASE` labels, `FOR` bounds,
   actuals and `RETURN`; in an `ARRAY OF CHAR` context it stays the
@@ -43,8 +45,11 @@ Legend: ✅ done · 🔄 partial · ⏸ not started / deferred.
   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.
+  elements still bakes a static descriptor.  Multi-dimensional array
+  fields are flattened into the record payload, including static and
+  runtime record/array-of-record constructors.  Set fields, and
+  constant string concatenation folded into a `CHAR`-array element,
+  included.
 - ✅ Index-type arrays `ARRAY <ordinalType> OF T`; enum values usable
   as array indices.
 - ✅ `MIN`/`MAX` over any ordinal type, array or set (a set's bounds

+ 13 - 3
docs/handoff-2026-10-23-next.md

@@ -1,7 +1,7 @@
 # Next session — plan (from 2026-10-23)
 
 **Branch:** `master`.  **Feature state:** `v3-exceptions` + `v3-ptrchain` + `v3-function-exception` + `v3-finally` + open-array M1/M2/M3/M4.
-**Gates:** suite **295/295**, fixpoint **OK (3,480,366 bytes)**,
+**Gates:** suite **299/299**, fixpoint **OK (3,534,072 bytes)**,
 corpus **518/612, 0 crashes**.
 
 Read first: `docs/STATUS.md`, `docs/features.md`,
@@ -115,8 +115,18 @@ views/rows and the payload base for 1-D open descriptors, while fixed
 descriptors now include the CHAR/UCHAR terminator.  Tests:
 `t_open2d_size`, `t_open2d_adr`, `t_open1d_size_adr`; `unbounded3`
 runs with 60/12/2/2.  Suite **295/295**, fixpoint **3,480,366 bytes**,
-corpus **518/612**.  Remaining: pointer-based 1-D view migration (row
-`ADR` identity through an internal 1-D call) and M5 records/constructors.
+corpus **518/612**.
+
+**M5 — record fields and constructors — done (2026-10-24).**  Rank-2/3
+record/class fields now store an inline flat payload and synthesize a
+view on selection; `FieldSize`/record layout use payload size.  Static
+record data, local/heap initialization, record constructors and
+array-of-record constructors handle the flat fields.  Tests:
+`t_record_multidim`, `t_record_multidim_ctor`,
+`t_record_multidim_const`, `t_record_multidim_arrctor`, `t_nestarr`.
+Suite **299/299**, fixpoint **3,534,072 bytes**, corpus **518/612**.
+Remaining: optional pointer-based 1-D view migration and M6 final
+docs/tag.
 
 ## 4. Runtime range checks — done, follow-ups
 

+ 6 - 2
docs/summary_session-2026-10-23-open-arrays.md

@@ -1,5 +1,8 @@
 # Session 2026-10-23 — multi-dimensional open arrays (M1–M4)
 
+> Continued on 2026-10-24 with record fields and constructors:
+> see `summary_session-2026-10-24-open-arrays-m5.md`.
+
 Same-day continuation of the range-check/PACKEDSET and ISO-exception
 sessions.  This session implemented the open-array ABI in four steps:
 fixed storage, open views/calls, and payload `SIZE`/`ADR`.
@@ -98,8 +101,9 @@ procedures).  The corpus is compile-only; it is not a run gate.
 
 ## Remaining
 
-- M5: multi-dimensional **record fields**, arrays of records with
-  multi fields, and constructors using the flat/view layout.
+- M5 (done 2026-10-24): multi-dimensional record fields, arrays of
+  records with multi fields, and constructors using the flat/view
+  layout; see `summary_session-2026-10-24-open-arrays-m5.md`.
 - Optional follow-up: migrate the legacy 1-D descriptor itself to a
   pointer-based view.  Row → 1-D still uses a copy-in/copy-back bridge,
   so row `ADR` identity through an internal 1-D call is not preserved.

+ 101 - 0
docs/summary_session-2026-10-24-open-arrays-m5.md

@@ -0,0 +1,101 @@
+# Session 2026-10-24 — open-array M5 (record fields and constructors)
+
+Continuation of the 2026-10-23 M1–M4 open-array session.  M5 moves
+rank-2/3 array fields inside records/classes to the flat+view layout
+and makes constructors produce/consume that layout.
+
+**Branch:** `master`.  **Feature state:** `v3-open-arrays-m5`.
+**Gates at the end:** suite **299/299**, fixpoint **OK
+(3,534,072 bytes)**, corpus **518/612 compile-OK, 0 crashes**.
+
+---
+
+## Numbers
+
+| gate | start (M4) | end (M5) |
+| --- | --- | --- |
+| suite (`compiler/run_tests.sh`) | 295/295 | **299/299** |
+| fixpoint (`bootstrap/fixpoint.sh`) | 3,480,366 B | **3,534,072 B** |
+| corpus (`tools/v3-corpus/corpus.sh`) | 518/612 | **518/612, 0 crashes** |
+
+The corpus is compile-only and has no new cases for record-field
+layout; the new coverage is in the suite.
+
+---
+
+## What landed
+
+### Record layout
+
+- `SymTab.ArrayFieldFootprint` selects the inline field size:
+  - rank-2/3 arrays: `ArrayPayloadSize` (flat payload only);
+  - 1-D arrays: legacy `ArrObjSize` descriptor.
+- `TypeSizeD`, variant-record sizing and `FieldSize` use that helper, so
+  record offsets/sizes match the new data layout.
+- Record static data (`RecItems`, `RecStatics`, `ArrBodyItems`,
+  `ArrData`) writes flat zero payloads for multi fields and no longer
+  emits per-row sub-descriptors.
+- `InitHeap` zeroes local/heap record multi fields with `InitMultiField`;
+  array-of-record templates/`InitRecArray` inherit the same layout.
+
+### Field access
+
+- `Lower.LowerDesign` synthesizes a view chain with
+  `QbeGen.MakeFieldView` when a multi-dimensional field is selected
+  (including `WITH` fields and fields reached through arrays/pointers).
+- The synthesized outer view points at the inline field payload; lower
+  levels are stack templates, so `ViewIndex`, row subviews, open-array
+  calls, `SIZE`, `ADR`, and row assignment work unchanged.
+- `t_nestarr` (record array with nested CHAR field) now uses the flat
+  field layout and remains green.
+
+### Constructors
+
+- Static record constructors (`CtorRecStatic`) receive a flattened
+  payload for multi fields.  Nested array-constructor text is parsed
+  and flattened by `FlattenCtorText`/`FlattenArrayText`; missing fields
+  become `z payload`.
+- Runtime record constructors build a field view with `MakeFieldView`
+  and copy the source constructor through `CopyArray`; absent multi
+  fields are zeroed with `ClearMultiField`.
+- Static array-of-record constructors inline record elements instead of
+  storing pointers; runtime array-of-record constructors copy child
+  records and zero absent records.
+- `CtorArrStatic`/`CtorEnd` continue to support ordinary 1-D/scalar
+  constructors; existing `t_ctor3`, `t_ctor7` and `showcase20` behavior
+  is unchanged.
+
+### Tests added
+
+- `t_record_multidim` — global/local records, record arrays, field
+  indexing, open-array pass, `SIZE` and `ADR`.
+- `t_record_multidim_ctor` — runtime record constructor with a 2-D
+  field.
+- `t_record_multidim_const` — static `CONST` record constructor.
+- `t_record_multidim_arrctor` — static and runtime array-of-record
+  constructors with 2-D fields.
+- Existing `t_nestarr` now exercises the migrated field layout.
+
+---
+
+## Remaining
+
+- Optional pointer-based 1-D view migration: row → 1-D internal calls
+  still use the copy-in/copy-back legacy descriptor, so row `ADR`
+  identity is not preserved.  Writes are preserved.
+- M6: final docs/gates/tag and any small polish.
+- `unbounded6`/`unbounded8`/`adrunbounded3` remain declaration-order
+  cases under V3 policy.
+
+---
+
+## Commits and tags
+
+| commit | tag | work |
+| --- | --- | --- |
+| `df72d03` | `v3-open-arrays-m4` | payload `SIZE`/`TSIZE`, view `ADR` |
+| `04ab8b5` | `v3-open-arrays-m5` | flat multi-dimensional record fields and constructors |
+| this docs commit | `v3-open-arrays-m5-summary` | M5 summary/docs |
+| final docs commit | `v3-session-2026-10-24-open-arrays-end` | session tag |
+
+No push was performed.