Selaa lähdekoodia

docs: one minimal reproducer per unsupported gap (docs/gaps/)

Add docs/gaps/ with a self-contained source for every remaining known
V3 gap listed in analysis_gaps.md §9, each tagged in its header comment
and indexed in docs/gaps/README.md with the observed diagnostic and the
corpus exemplars:

  gap01 fwd-type-const-conv     gap10 var-param-type
  gap02 fwd-type-var            gap11 bare-proc-stmt
  gap03 fwd-type-heading        gap12 variant-empty-arms
  gap04 fwd-const-bound         gap13 builtin-proc-name
  gap05 fwd-type-size           gap14 builtin-pragma
  gap06 fwd-setconst            gap15a/b qualified/from import
  gap07 convert-builtin         gap16 wide-set
  gap08 set-word-cast           gap17 set-of-cardinal
  gap09 scalar-to-bytearray

The size-sensitive self-host miscompile has no standalone repro (noted
in the README).  All diagnostics verified against HEAD.
Eric Streit 14 tuntia sitten
vanhempi
commit
d718a1ee34

+ 3 - 0
.gitignore

@@ -5,3 +5,6 @@ tools/topspeed-grammar/build/
 
 # local scratch (agent work area; never commit)
 .scratch/
+
+# gap reproducers: listings
+docs/gaps/*.LST

+ 1 - 0
docs/INDEX.md

@@ -10,6 +10,7 @@ bisecting *why* a decision was made, not for reading end-to-end).
 - **`plan.md`** — the phased plan (Blaise-adapted).
 - **`features.md`** — the feature list.
 - **`analysis_gaps.md`** — language gaps + corpus notes.
+- **`gaps/README.md`** — minimal reproducers, one per unsupported gap.
 
 ## Designs / running records
 

+ 3 - 0
docs/analysis_gaps.md

@@ -236,3 +236,6 @@ Next (recorded): forward *type* references in a `CONST` conversion
 `bytearray` (scalar actual into `ARRAY OF BYTE`); variant empty arms /
 `ELSE`; builtin names as procedure names; the `imp*` qualified-import
 family (partly a corpus-harness transitive-`.def` gap).
+
+Every gap above has a self-contained reproducer in `docs/gaps/`
+(`docs/gaps/README.md` indexes them by tag).

+ 69 - 0
docs/gaps/README.md

@@ -0,0 +1,69 @@
+# Unsupported-gap reproducers
+
+One minimal source per known V3 gap (2026-10-18).  Each file's header
+comment carries its **tag** and the gm2 corpus file(s) it stands for.
+These are *not* part of the test suite (they are expected to fail); they
+exist so each gap has a runnable, self-contained example.
+
+Verify one with:
+
+```sh
+cd compiler && ./build.sh
+./M2 ../docs/gaps/gap07_convert.mod     # prints the diagnostic on stdout
+```
+
+## Index
+
+| tag | file | diagnostic | corpus exemplars |
+| --- | --- | --- | --- |
+| `gap01-fwd-type-const-conv` | `gap01_fwd_type_const_conv.mod` | `undeclared identifier` | `subrange4`, `subrange7` |
+| `gap02-fwd-type-var` | `gap02_fwd_type_var.mod` | `undeclared identifier` | `subrange11` (procedure-local part) |
+| `gap03-fwd-type-heading` | `gap03_fwd_type_heading.mod` | `undeclared identifier` | `shift3`, `shift4` |
+| `gap04-fwd-const-bound` | `gap04_fwd_const_bound.mod` | `undeclared identifier` | `setconst3` |
+| `gap05-fwd-type-size` | `gap05_fwd_type_size.mod` | `undeclared identifier` | `constsize2` |
+| `gap06-fwd-setconst` | `gap06_fwd_setconst.mod` | `undeclared identifier` | `setoverflow` |
+| `gap07-convert-builtin` | `gap07_convert.mod` | `undeclared identifier` | `procconv2` |
+| `gap08-set-word-cast` | `gap08_val_cast_set_word.mod` | `not supported yet` | `constset`, `constset2`, `constset3`, `packed`, `bitset5`, `packed` |
+| `gap09-scalar-to-bytearray` | `gap09_scalar_to_bytearray.mod` | `invalid call` | `aochar`, `arrayofbyte`, `bytearray` |
+| `gap10-var-param-type` | `gap10_var_param_type.mod` | `invalid call` | `testparam2`, `testparam3` |
+| `gap11-bare-proc-stmt` | `gap11_bare_proc_stmt.mod` | `invalid call` | `tinyproc2`, `tinyproc4` |
+| `gap12-variant-empty-arms` | `gap12_variant_empty_arms.mod` | `invalid VarLabel` | `varient2`, `varient3`, `varient8`, `tsize`, `tsize2` |
+| `gap13-builtin-proc-name` | `gap13_builtin_proc_name.mod` | `ident expected` | `fileio.def`, `fileio.mod` |
+| `gap14-builtin-pragma` | `gap14_builtin_pragma.def` | `ident expected` | `builtin.def`, `builtin.mod` |
+| `gap15a-qualified-import` | `gap15a_qualified_import.mod` (+ `gap15_base.def`, `gap15_lib.def`) | `undeclared identifier` | `impf`, `impk`, `impl`, `impq` |
+| `gap15b-from-import` | `gap15b_from_import.mod` (+ `gap15_base.def`, `gap15_lib.def`) | `undeclared identifier` | `impi` |
+| `gap16-wide-set` | `gap16_wide_set.mod` | `not supported yet` | `settest1` |
+| `gap17-set-of-cardinal` | `gap17_set_of_cardinal.mod` | `not supported yet` | `settest3` |
+
+Observed first diagnostics (line:col) at commit time:
+
+```
+gap01_fwd_type_const_conv.mod:5:13   undeclared identifier
+gap02_fwd_type_var.mod:7:9           undeclared identifier
+gap03_fwd_type_heading.mod:5:17      undeclared identifier
+gap04_fwd_const_bound.mod:5:19       undeclared identifier
+gap05_fwd_type_size.mod:5:17         undeclared identifier
+gap06_fwd_setconst.mod:5:12          undeclared identifier
+gap07_convert.mod:8:12               undeclared identifier
+gap08_val_cast_set_word.mod:7:35     not supported yet
+gap09_scalar_to_bytearray.mod:9:13   invalid call
+gap10_var_param_type.mod:9:11        invalid call
+gap11_bare_proc_stmt.mod:6:7         invalid call
+gap12_variant_empty_arms.mod:8:12    invalid VarLabel
+gap13_builtin_proc_name.mod:5:11     ident expected
+gap14_builtin_pragma.def:5:11        ident expected
+gap15a_qualified_import.mod:8:21     undeclared identifier
+gap15b_from_import.mod:6:16          undeclared identifier
+gap16_wide_set.mod:5:29              not supported yet
+gap17_set_of_cardinal.mod:5:19       not supported yet
+```
+
+## Not represented by a source
+
+- **Size-sensitive V3 miscompile** — a *latent* codegen bug that only
+  manifests at the compiler's own scale (the historical "removing
+  `ASTDUMP` breaks the fixpoint"); see `docs/summary_l3_selfhost_fix.md`.
+  No small standalone source triggers it.
+
+Companion files (`gap15_base.def`, `gap15_lib.def`) are not gaps
+themselves; they model the `impc` → `impb` re-export chain.

+ 8 - 0
docs/gaps/gap01_fwd_type_const_conv.mod

@@ -0,0 +1,8 @@
+MODULE Gap01FwdTypeConstConv;
+(* GAP gap01-fwd-type-const-conv: a CONST whose conversion names a TYPE
+   declared later.  Corpus: subrange4, subrange7.
+   EXPECT: undeclared identifier (the forward TYPE). *)
+CONST low = ind0(-100);
+TYPE ind0 = [-100..100];
+VAR x : ind0;
+BEGIN x := low END Gap01FwdTypeConstConv.

+ 10 - 0
docs/gaps/gap02_fwd_type_var.mod

@@ -0,0 +1,10 @@
+MODULE Gap02FwdTypeVar;
+(* GAP gap02-fwd-type-var: a procedure-local VAR whose type is declared
+   later in the same procedure's TYPE block (forward types are refused
+   inside a procedure).  Corpus: subrange11 (partly).
+   EXPECT: undeclared identifier (the forward TYPE). *)
+PROCEDURE outer;
+VAR a : arr;
+TYPE arr = ARRAY [0..3] OF INTEGER;
+BEGIN a[0] := 0 END outer;
+BEGIN outer END Gap02FwdTypeVar.

+ 8 - 0
docs/gaps/gap03_fwd_type_heading.mod

@@ -0,0 +1,8 @@
+MODULE Gap03FwdTypeHeading;
+(* GAP gap03-fwd-type-heading: a procedure heading whose formal names a
+   TYPE declared later at module level.  Corpus: shift3, shift4.
+   EXPECT: undeclared identifier (the forward TYPE). *)
+PROCEDURE p(a : large);
+BEGIN END p;
+TYPE large = SET OF [0..31];
+BEGIN END Gap03FwdTypeHeading.

+ 7 - 0
docs/gaps/gap04_fwd_const_bound.mod

@@ -0,0 +1,7 @@
+MODULE Gap04FwdConstBound;
+(* GAP gap04-fwd-const-bound: a VAR array bound names a CONST declared
+   later.  Corpus: setconst3.
+   EXPECT: undeclared identifier (the forward CONST). *)
+VAR a : ARRAY [0..n] OF INTEGER;
+CONST n = 3;
+BEGIN a[0] := 0 END Gap04FwdConstBound.

+ 7 - 0
docs/gaps/gap05_fwd_type_size.mod

@@ -0,0 +1,7 @@
+MODULE Gap05FwdTypeSize;
+(* GAP gap05-fwd-type-size: a CONST uses SIZE(T) where T is declared
+   later.  Corpus: constsize2.
+   EXPECT: undeclared identifier (the forward TYPE). *)
+CONST sz = SIZE(t);
+TYPE t = ARRAY [0..4] OF CARDINAL;
+BEGIN END Gap05FwdTypeSize.

+ 9 - 0
docs/gaps/gap06_fwd_setconst.mod

@@ -0,0 +1,9 @@
+MODULE Gap06FwdSetConst;
+(* GAP gap06-fwd-setconst: a set CONST whose elements name a CONST and a
+   TYPE declared later.  Corpus: setoverflow.
+   EXPECT: undeclared identifier (tab and CharSet). *)
+CONST ws = CharSet{tab, ' '};
+      tab = 9;
+TYPE CharSet = SET OF CHAR;
+VAR s : CharSet;
+BEGIN s := ws END Gap06FwdSetConst.

+ 8 - 0
docs/gaps/gap07_convert.mod

@@ -0,0 +1,8 @@
+MODULE Gap07Convert;
+(* GAP gap07-convert-builtin: CONVERT(T, x) is not implemented.
+   Corpus: procconv2.
+   EXPECT: undeclared identifier (CONVERT). *)
+FROM SYSTEM IMPORT ADDRESS;
+PROCEDURE foo; BEGIN END foo;
+VAR a : ADDRESS;
+BEGIN a := CONVERT(ADDRESS, foo) END Gap07Convert.

+ 7 - 0
docs/gaps/gap08_val_cast_set_word.mod

@@ -0,0 +1,7 @@
+MODULE Gap08ValCastSetWord;
+(* GAP gap08-set-word-cast: a set is an address, not a machine word, so
+   VAL/CAST between a set and CARDINAL is rejected.  Corpus: constset,
+   constset2, constset3, packed, bitset5.
+   EXPECT: not supported yet (230). *)
+VAR c : CARDINAL;
+BEGIN c := VAL(CARDINAL, BITSET{0}) END Gap08ValCastSetWord.

+ 9 - 0
docs/gaps/gap09_scalar_to_bytearray.mod

@@ -0,0 +1,9 @@
+MODULE Gap09ScalarToByteArray;
+(* GAP gap09-scalar-to-bytearray: a scalar actual for an ARRAY OF BYTE
+   formal (gm2's untyped byte buffer).  Corpus: aochar, arrayofbyte,
+   bytearray.
+   EXPECT: invalid call (233). *)
+FROM SYSTEM IMPORT BYTE;
+PROCEDURE bytes(b : ARRAY OF BYTE); BEGIN END bytes;
+VAR i : INTEGER;
+BEGIN bytes(i) END Gap09ScalarToByteArray.

+ 9 - 0
docs/gaps/gap10_var_param_type.mod

@@ -0,0 +1,9 @@
+MODULE Gap10VarParamType;
+(* GAP gap10-var-param-type: a VAR actual whose type differs from the
+   formal (gm2 accepts same-size families).  Corpus: testparam2,
+   testparam3.
+   EXPECT: invalid call (233). *)
+FROM SYSTEM IMPORT WORD;
+PROCEDURE foo(VAR p : WORD); BEGIN p := 1 END foo;
+VAR f : INTEGER;
+BEGIN foo(f) END Gap10VarParamType.

+ 6 - 0
docs/gaps/gap11_bare_proc_stmt.mod

@@ -0,0 +1,6 @@
+MODULE Gap11BareProcStmt;
+(* GAP gap11-bare-proc-stmt: a bare procedure value as a statement (an
+   implicit zero-arg call).  Corpus: tinyproc2, tinyproc4.
+   EXPECT: invalid call (233). *)
+VAR p : PROC;
+BEGIN p END Gap11BareProcStmt.

+ 15 - 0
docs/gaps/gap12_variant_empty_arms.mod

@@ -0,0 +1,15 @@
+MODULE Gap12VariantEmptyArms;
+(* GAP gap12-variant-empty-arms: a variant part with empty arms and an
+   untagged inner CASE.  Corpus: varient2, varient3, tsize, tsize2.
+   EXPECT: invalid VarLabel. *)
+TYPE form = (sets, bigsets);
+     r = RECORD
+           CASE f : form OF
+           | sets, bigsets : base : CARDINAL;
+                             CASE : form OF
+                             | bigsets : off : CARDINAL;
+                             | sets :
+                             END;
+           END
+         END;
+BEGIN END Gap12VariantEmptyArms.

+ 7 - 0
docs/gaps/gap13_builtin_proc_name.mod

@@ -0,0 +1,7 @@
+MODULE Gap13BuiltinProcName;
+(* GAP gap13-builtin-proc-name: a procedure named after a builtin
+   keyword (ORDL).  Corpus: fileio.def, fileio.mod.
+   EXPECT: ident expected. *)
+PROCEDURE ORDL(i : INTEGER) : CARDINAL;
+BEGIN RETURN 0 END ORDL;
+BEGIN END Gap13BuiltinProcName.

+ 6 - 0
docs/gaps/gap14_builtin_pragma.def

@@ -0,0 +1,6 @@
+DEFINITION MODULE Gap14BuiltinPragma;
+(* GAP gap14-builtin-pragma: the __BUILTIN__ pragma before a procedure
+   name.  Corpus: builtin.def, builtin.mod.
+   EXPECT: ident expected. *)
+PROCEDURE __BUILTIN__ f(x : CARDINAL) : CARDINAL;
+END Gap14BuiltinPragma.

+ 4 - 0
docs/gaps/gap15_base.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE Gap15Base;
+(* Companion for the gap15 qualified-import repros. *)
+TYPE Colour = (red, green);
+END Gap15Base.

+ 5 - 0
docs/gaps/gap15_lib.def

@@ -0,0 +1,5 @@
+DEFINITION MODULE Gap15Lib;
+(* Companion: re-exports Gap15Base's type (impb = impc.C). *)
+IMPORT Gap15Base;
+TYPE Colour = Gap15Base.Colour;
+END Gap15Lib.

+ 8 - 0
docs/gaps/gap15a_qualified_import.mod

@@ -0,0 +1,8 @@
+MODULE Gap15QualifiedImport;
+(* GAP gap15a-qualified-import: a qualified access to an enum literal
+   reached through a *re-exported* type.  Corpus: impf, impk, impl,
+   impq.
+   EXPECT: undeclared identifier at Gap15Lib.red. *)
+IMPORT Gap15Lib;
+VAR a : Gap15Lib.Colour;
+BEGIN a := Gap15Lib.red END Gap15QualifiedImport.

+ 7 - 0
docs/gaps/gap15b_from_import.mod

@@ -0,0 +1,7 @@
+MODULE Gap15FromImport;
+(* GAP gap15b-from-import: FROM-importing a type should bring its enum
+   literals into scope (unqualified).  Corpus: impi.
+   EXPECT: undeclared identifier at red/green. *)
+FROM Gap15Lib IMPORT Colour;
+VAR a : ARRAY [red..green] OF CARDINAL;
+BEGIN END Gap15FromImport.

+ 7 - 0
docs/gaps/gap16_wide_set.mod

@@ -0,0 +1,7 @@
+MODULE Gap16WideSet;
+(* GAP gap16-wide-set: SET OF [0..100000] exceeds the 65536-value span.
+   Corpus: settest1.
+   EXPECT: not supported yet (230). *)
+TYPE big = SET OF [0..100000];
+VAR s : big;
+BEGIN END Gap16WideSet.

+ 7 - 0
docs/gaps/gap17_set_of_cardinal.mod

@@ -0,0 +1,7 @@
+MODULE Gap17SetOfCardinal;
+(* GAP gap17-set-of-cardinal: SET OF CARDINAL has an unbounded base.
+   Corpus: settest3.
+   EXPECT: not supported yet (230). *)
+TYPE big = SET OF CARDINAL;
+VAR s : big;
+BEGIN END Gap17SetOfCardinal.