Branch resolve-check, tree clean. Suite 213/213; fixpoint
OK (3,706,134 bytes); corpus 372 OK / 0 crash.
Tags: v3-generics-value-params, v3-generics-inc3,
v3-generics-proc-params, v3-generics-constraints.
ISO 10514-2 refinement generics now accept value and procedure parameters, an explicit constraint model, and actual-kind constraints.
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.
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).
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).
A type formal may carry an explicit constraint:
GENERIC DEFINITION MODULE OrdBox (T : TYPE (ORDINAL));
TYPE Box = ARRAY [0..3] OF T;
END OrdBox.
DEFINITION MODULE IntBox = OrdBox(INTEGER); (* ok *)
DEFINITION MODULE RealBox = OrdBox(REAL); (* rejected: 233 *)
GenericFormal's TYPE branch takes an optional ( name );
ConsCode maps ORDINAL/INTEGER/REAL → 0/1/2/3 and ConsOk
tests the actual (ORDINAL → SymTab.IsOrdinal; INTEGER → ClInt;
REAL → ClReal). The constraint is read from the formal's source on
both passes (template and re-parse), so no extra state is needed.
Verified: OrdBox(INTEGER) compiles and runs (b[0]+b[3] → 42);
OrdBox(REAL) is rejected.
BufProg, g_badbuf, SortProg, OrdProg,
g_realbox); forward tests, two-phase gates, and exit-code gates all
green.GENERIC CLASS; instance dedup; nested generics as actuals; further
constraint names (POINTER, SCALAR).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
./M2 tests/g_ordbox.def tests/g_ordbox.mod tests/g_intbox.def \
tests/g_intbox.mod tests/g_ordprog.mod # OrdProg -> 42