فهرست منبع

generics inc3: actual-kind constraints (type vs value formal)

At instantiation the actual's kind must match the formal's category: a
type formal needs a type actual, a value formal a value actual,
otherwise 233. Regression test g_badbuf (Buf(INTEGER) rejected) plus
BufProg. Suite 210/210; fixpoint OK; corpus unchanged. Docs record
procedure parameters as the remaining inc3 item with the two mechanisms
they need (imports in the refinement form; a cross-parse proc alias).
Eric Streit 1 روز پیش
والد
کامیت
e15787757a
5فایلهای تغییر یافته به همراه815 افزوده شده و 791 حذف شده
  1. 1 0
      compiler/run_tests.sh
  2. 11 1
      compiler/src/M2.atg
  3. 783 783
      compiler/src/M2.lst
  4. 2 0
      compiler/tests/g_badbuf.def
  5. 18 7
      docs/analysis_generics.md

+ 1 - 0
compiler/run_tests.sh

@@ -468,6 +468,7 @@ expect_fail_files() {
 
 expect_fail_files d_badimp_prog "undeclared identifier" d_basic.def d_basic.mod d_badimp_prog.mod
 expect_fail_files sig "implementation does not match definition" sig.def sig.mod sig_prog.mod
+expect_fail_files g_badbuf "invalid call" g_buf.def g_buf.mod g_badbuf.def
 
 # --- two-phase parse gate.  Deferral is now the DEFAULT (procedure
 #     bodies are parsed after the unit's declarations); -notwophase

+ 11 - 1
compiler/src/M2.atg

@@ -562,11 +562,21 @@ PRODUCTIONS
                                            WHILE k < nn DO
                                              IF isTypeFormal THEN
                                                IF instActive THEN
-                                                 IF NOT SymTab.EnterTypeParamBound(names[k], InstActualGet(instFk)) THEN
+                                                 (* constraint: a type
+                                                    formal needs a type
+                                                    actual *)
+                                                 IF InstActualKind(instFk) # 0 THEN
+                                                   SemError(233)
+                                                 ELSIF NOT SymTab.EnterTypeParamBound(names[k], InstActualGet(instFk)) THEN
                                                    SemError(200) END
                                                ELSIF NOT SymTab.EnterTypeParam(names[k]) THEN
                                                  SemError(200) END
                                              ELSE
+                                               (* constraint: a value
+                                                  formal needs a value
+                                                  actual *)
+                                               IF instActive AND (InstActualKind(instFk) # 1) THEN
+                                                 SemError(233) END;
                                                IF NOT SymTab.Enter(names[k], SymTab.KindConst) THEN
                                                  SemError(200) END;
                                                SymTab.SetSymType(names[k], vt);

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 783 - 783
compiler/src/M2.lst


+ 2 - 0
compiler/tests/g_badbuf.def

@@ -0,0 +1,2 @@
+DEFINITION MODULE BufBad = Buf(INTEGER);
+END BufBad.

+ 18 - 7
docs/analysis_generics.md

@@ -25,9 +25,9 @@
 > pre-register `X`), a `SymTab.EnterTypeParamBound`, a grammar
 > instantiation context + accessors, and driver re-parse logic.
 >
-> **Done (Increment 3, partial — 2026-10-16): value (constant)
-> parameters.**  A generic formal may now be a value rather than a
-> type: `GENERIC DEFINITION MODULE Buf (size : CARDINAL); TYPE T = ARRAY
+> **Done (Increment 3 — 2026-10-16): value (constant) parameters and
+> actual-kind constraints.**  A generic formal may now be a value rather
+> than a type: `GENERIC DEFINITION MODULE Buf (size : CARDINAL); TYPE T = ARRAY
 > [0..size] OF CHAR; …` instantiated by `MODULE X = Buf(10);`.  Grammar:
 > `GenericFormal` collects its names then accepts `: TYPE` (type formal)
 > or `: TypeIdent` (value formal); `Actual` accepts an integer, `charConst`
@@ -38,10 +38,21 @@
 > On instantiation a value formal becomes a `CONST` bound to the actual
 > value; in the **abstract template** it is a `CONST` with a placeholder
 > value (`"0"`), so template parsing succeeds — templates are never
-> lowered, so only instances matter.  Suite tests `BufProg` (and a
-> second instance, `Buf(3)`), verified end-to-end (`HIGH(T)` reflects the
-> bound size).  Suite 209/209, fixpoint OK, corpus unchanged.
-> Procedure parameters / constraints remain for a later increment.
+> lowered, so only instances matter.  **Constraints:** the actual's kind
+> must match the formal (a type formal needs a type actual, a value
+> formal a value one) — otherwise `233`; tested by `g_badbuf`.
+> Suite **210/210**, fixpoint OK, corpus unchanged.
+>
+> **Still open for inc3+:** *procedure parameters*
+> (`Compare : CompareProc`, actual = a procedure).  These need two
+> mechanisms not yet present: (1) the refinement form
+> (`MODULE X = G(...);`) must accept `{ Import }` so the actual
+> procedure is visible; (2) a cross-parse **procedure alias** — clone
+> the actual proc's `SymNode` under the formal's name in the
+> instantiation scope (the `Materialize`/`MaterializeAlias` pattern,
+> which keeps `uid`/`mod` so mangling resolves).  Also open: a
+> **constraint model** beyond kind-matching (e.g. "`T` must be
+> ordinal"), and `GENERIC CLASS`.
 
 Study reviewed: `../Generics/` (the three `m2-generics-coco-r-*.md`
 analyses, the `m2generic/` prototype: `M2Generic.atg`,

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است