|
|
@@ -0,0 +1,87 @@
|
|
|
+# Session summary — 2026-10-16 (c): generics increment 3
|
|
|
+
|
|
|
+Branch **`resolve-check`**, tree clean. Suite **211/211**; fixpoint
|
|
|
+**OK (3,702,885 bytes)**; corpus **372 OK / 0 crash**.
|
|
|
+
|
|
|
+Tags: `v3-generics-value-params`, `v3-generics-inc3`,
|
|
|
+`v3-generics-proc-params`.
|
|
|
+
|
|
|
+## What inc3 added
|
|
|
+
|
|
|
+ISO 10514-2 refinement generics now accept **value** and **procedure**
|
|
|
+parameters, plus **actual-kind constraints**.
|
|
|
+
|
|
|
+### 1. Value (constant) parameters
|
|
|
+
|
|
|
+```modula2
|
|
|
+GENERIC DEFINITION MODULE Buf (size : CARDINAL);
|
|
|
+TYPE T = ARRAY [0..size] OF CHAR;
|
|
|
+END Buf.
|
|
|
+DEFINITION MODULE Buf10 = Buf(10); END Buf10.
|
|
|
+```
|
|
|
+
|
|
|
+`GenericFormal` collects its names, then takes `: TYPE` (type formal)
|
|
|
+or `: TypeIdent` (value formal). `Actual` accepts an integer,
|
|
|
+`charConst`, or an identifier. Refinement actuals carry a **kind**
|
|
|
+(0 type / 1 value / 2 proc) and a **value text**
|
|
|
+(`refKind`/`refVal`, `instKind`/`instVal` + accessors). A value formal
|
|
|
+binds to a `CONST` with the actual value at instantiation; in the
|
|
|
+**abstract template** it is a `CONST` placeholder (`"0"`) — templates
|
|
|
+are never lowered, so only instances matter. Verified with two
|
|
|
+instances of different sizes.
|
|
|
+
|
|
|
+### 2. Actual-kind constraints
|
|
|
+
|
|
|
+At instantiation the actual's kind must match the formal: a type formal
|
|
|
+needs a type actual, a value formal a value actual, else `233`
|
|
|
+(`g_badbuf`).
|
|
|
+
|
|
|
+### 3. Procedure parameters
|
|
|
+
|
|
|
+```modula2
|
|
|
+GENERIC DEFINITION MODULE Sort
|
|
|
+ (Element : TYPE; Compare : PROCEDURE(a, b : Element) : INTEGER);
|
|
|
+PROCEDURE Smaller(x, y : Element) : Element;
|
|
|
+END Sort.
|
|
|
+DEFINITION/IMPLEMENTATION MODULE IntSort = Sort(INTEGER, Cmp.IntCompare);
|
|
|
+```
|
|
|
+
|
|
|
+The formal's type is an inline `ProcType`; the actual is a **qualified**
|
|
|
+procedure name (the refinement parses actuals before any import, so
|
|
|
+qualification is the only way to reach a proc without one). In the
|
|
|
+template the formal is a proc-typed callable (the body checks, via an
|
|
|
+indirect call there); at instantiation it is aliased to the actual:
|
|
|
+
|
|
|
+- `SymTab.AliasProc(formal, mod, actual)` — clones the actual's
|
|
|
+ `SymNode` under the formal's name (keeps `uid`/`mod`/`sym`).
|
|
|
+- `Lower.AliasProc(...)` — a **scope-neutral proc-table entry**, because
|
|
|
+ `Lower` resolves call targets from its own table, not `SymTab`
|
|
|
+ (the first attempt emitted `call $Compare`, an unresolved symbol).
|
|
|
+- `SymTab.ProcBaseByUid` + a uid→base map, so `QbeGen.Mangled` recovers
|
|
|
+ the base name after the instance scope has been popped.
|
|
|
+
|
|
|
+Refinement forms also accept `{ Import }` now. Verified end-to-end
|
|
|
+(`Smaller(7,3)` through `IntSort`, `IntCompare` in a separate module,
|
|
|
+returns 3).
|
|
|
+
|
|
|
+## Verification
|
|
|
+
|
|
|
+- Suite **211/211** (`BufProg`, `g_badbuf`, `SortProg`); forward tests,
|
|
|
+ two-phase gates, and exit-code gates all green.
|
|
|
+- Fixpoint **OK** (3,702,885 bytes).
|
|
|
+- Corpus unchanged: **372 OK, 0 crash** (generics are not in the corpus).
|
|
|
+
|
|
|
+## Remaining in the generics thread
|
|
|
+
|
|
|
+- A **richer constraint model** (e.g. "`T` must be ordinal") — next.
|
|
|
+- `GENERIC CLASS`; instance dedup; nested generics as actuals.
|
|
|
+
|
|
|
+## Resume
|
|
|
+
|
|
|
+```sh
|
|
|
+cd .../m2compiler-V3/compiler
|
|
|
+./M2 tests/g_cmp.def tests/g_cmp.mod tests/g_sort.def tests/g_sort.mod \
|
|
|
+ tests/g_isort.def tests/g_isort.mod tests/g_sortprog.mod # SortProg -> 3
|
|
|
+./M2 tests/g_buf.def tests/g_buf.mod tests/g_buf10.def \
|
|
|
+ tests/g_buf10.mod tests/g_bufprog.mod # BufProg -> 42
|
|
|
+```
|