Eric Streit f53cdad58b language: __BUILTIN__/__ATTRIBUTE__ pragmas (gap14); docs consolidation (P5) 1 gün önce
..
README.md f53cdad58b language: __BUILTIN__/__ATTRIBUTE__ pragmas (gap14); docs consolidation (P5) 1 gün önce
gap01_fwd_type_const_conv.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap02_fwd_type_var.mod 5fb4950e65 language: strict declaration order (no forward type references) 2 gün önce
gap03_fwd_type_heading.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap04_fwd_const_bound.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap05_fwd_type_size.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap06_fwd_setconst.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap09_scalar_to_bytearray.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap10_var_param_type.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap11_bare_proc_stmt.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap12_variant_empty_arms.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap14_builtin_pragma.def b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap16_wide_set.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap17_set_of_cardinal.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap18_set_case_labels.mod b5c959c4f4 docs+revert: follow Modula-2, not gm2 leniency (docs/gaps) 2 gün önce
gap19_fwd_array_index.mod d91871a0d5 docs(gaps): add gap19 (forward array index) after the revert 2 gün önce
gap20_fwd_set_of_type.mod 5fb4950e65 language: strict declaration order (no forward type references) 2 gün önce
gap21_fwd_record_field.mod 5fb4950e65 language: strict declaration order (no forward type references) 2 gün önce
gap22_file_line.mod 481b2c306d language: set<->word VAL/CAST (BITSET as a machine word) 2 gün önce

README.md

Unsupported / non-standard cases

One minimal source per known V3 gap (2026-10-18). Each file's header comment carries its tag, its Modula-2 status, 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 case has a runnable example.

Verify one with:

cd compiler && ./build.sh
./M2 ../docs/gaps/gap07_convert.mod     # prints the diagnostic on stdout

Policy: follow Modula-2, not degraded gm2

The corpus is gcc's gm2 testsuite, so "compiles on the corpus" mixes conforming Modula-2 with gm2 leniencies and extensions. This project follows the language:

Standard Modula-2 (PIM and ISO) requires declaration before use; the declaration part is ordered CONST, TYPE, VAR. The only forward reference the language allows is a POINTER's base type (for recursive/self-referential types).

V3 therefore intentionally rejects use-before-declaration; that is conforming behaviour, not a gap. gm2 accepts such programs because it resolves the whole declaration part before checking — a leniency.

Since 2026-10-19 the rule is also enforced inside deferred procedure bodies for module-level data (variables, constants, types): a body may not use one declared after its procedure. Forward procedure calls from a body remain allowed (the generated parser relies on it).

The class column says what a change would mean:

  • decl-order — not legal Modula-2; gm2 leniency. V3 rejects it correctly. Not a target.
  • gm2-ext — not standard; a gm2/PIM extension or leniency. Not a target unless we choose gm2 compatibility.
  • iso/system — a standard ISO Modula-2 / SYSTEM facility V3 lacks. A genuine gap.
  • v3-deviation — V3 is stricter than the standard (a V3 bug to fix).
  • impl-limit — the language allows it; V3 has a fixed implementation limit.

Index

tag file class diagnostic corpus exemplars
gap01-fwd-type-const-conv gap01_fwd_type_const_conv.mod decl-order undeclared identifier subrange4, subrange7
gap02-fwd-type-var gap02_fwd_type_var.mod decl-order undeclared identifier subrange11, arrayptr, arrayptr6, constructor1, constructor3, param3
gap03-fwd-type-heading gap03_fwd_type_heading.mod decl-order undeclared identifier shift3, shift4
gap04-fwd-const-bound gap04_fwd_const_bound.mod decl-order undeclared identifier setconst3
gap05-fwd-type-size gap05_fwd_type_size.mod decl-order undeclared identifier constsize2
gap06-fwd-setconst gap06_fwd_setconst.mod decl-order undeclared identifier setoverflow
gap09-scalar-to-bytearray gap09_scalar_to_bytearray.mod gm2-ext (accepted) — aochar, arrayofbyte, bytearray
gap10-var-param-type gap10_var_param_type.mod gm2-ext (accepted) — testparam2
gap11-bare-proc-stmt gap11_bare_proc_stmt.mod gm2-ext (accepted) — tinyproc2, tinyproc4
gap12-variant-empty-arms gap12_variant_empty_arms.mod gm2-ext (accepted) — varient2, varient3, varient8, tsize, tsize2
gap14-builtin-pragma gap14_builtin_pragma.def gm2-ext (accepted) — builtin.def, builtin.mod
gap16-wide-set gap16_wide_set.mod impl-limit not supported yet settest1
gap17-set-of-cardinal gap17_set_of_cardinal.mod impl-limit not supported yet settest3
gap18-set-case-labels gap18_set_case_labels.mod gm2-ext (accepted) — bitset5
gap19-fwd-array-index gap19_fwd_array_index.mod decl-order not supported yet record7, complextypes
gap20-fwd-set-of-type gap20_fwd_set_of_type.mod decl-order undeclared identifier tinyset6, tinyset7
gap21-fwd-record-field gap21_fwd_record_field.mod decl-order undeclared identifier record14.def, record15.def, record16.def
gap22-file-line gap22_file_line.mod gm2-ext (accepted) — packed

First diagnostic (message) per file at commit time (line:col varies as comments change):

gap01_fwd_type_const_conv.mod   undeclared identifier   (ind0)
gap02_fwd_type_var.mod          undeclared identifier   (arr)
gap03_fwd_type_heading.mod      undeclared identifier   (large)
gap04_fwd_const_bound.mod       undeclared identifier   (n)
gap05_fwd_type_size.mod         undeclared identifier   (t)
gap06_fwd_setconst.mod          undeclared identifier   (CharSet / tab)
gap09_scalar_to_bytearray.mod   invalid call            (scalar -> ARRAY OF BYTE)
gap10_var_param_type.mod        invalid call            (VAR actual type)
gap11_bare_proc_stmt.mod        invalid call            (bare proc value)
gap12_variant_empty_arms.mod    invalid VarLabel
gap14_builtin_pragma.def        ident expected          (__BUILTIN__)
gap16_wide_set.mod              not supported yet       (span > 65536)
gap17_set_of_cardinal.mod       not supported yet       (unbounded base)
gap18_set_case_labels.mod       not supported yet       (set as CASE selector)
gap19_fwd_array_index.mod       not supported yet       (array index declared later)
gap20_fwd_set_of_type.mod       undeclared identifier   (SET OF base declared later)
gap21_fwd_record_field.mod      undeclared identifier   (record field type declared later)
gap22_file_line.mod             invalid Fact            (__LINE__)

Genuine gaps (worth fixing, standard Modula-2)

  • gap07 CONVERT — fixed (2026-10-18): CONVERT(T, x) is accepted as a VAL sibling (procconv2 passes).
  • gap08 set↔word CAST/VAL — fixed (2026-10-18): VAL/CAST between a set and its machine word (constset, constset2, constset3 pass). packed still needs gap22 (__FILE__/__LINE__).
  • gap13 builtins as identifiers — corpus case fixed; remainder deferred (2026-10-18 / confirmed 2026-10-19): ORDL (a gm2/FileIO helper, not a Modula-2 built-in) is no longer reserved, so PROCEDURE ORDL is accepted (fileio.def/mod, baseimport pass; the scanner frame imports FileIO.ORDL). The standard built-ins (ORD, CHR, VAL, SIZE, ABS, … ~24 words) are still reserved keywords. De-reserving them is a contextual-keyword rewrite of Fact/ArgList/the statement builtins (Coco/R is LL(1), so it cannot branch on an identifier's text; the dedicated builtin alternatives would have to merge into the general Design+ArgList path). There is no corpus exemplar in the scanned dirs (no file declares a builtin as a name), so the payoff is conformance-only; a declaration- site-only half-measure would bind calls to the builtin (silently wrong), so it is deliberately not shipped. Tracked as a known v3-deviation.
  • gap15 enumeration literals with an imported type — fixed (2026-10-18): literals now travel with the type through re-export, FROM-import and qualified access; also fixed the qualified-const value (LoadDesignator returned 0 for enum consts). imp* pass.
  • Foreign modules FOR "C" / EXPORT UNQUALIFIED — already fixed (§ STATUS).

gap16/gap17 are implementation limits (raising the set span cap).

gm2 extensions now accepted (deliberate compatibility)

These are not standard Modula-2; V3 accepts them for gm2 compatibility (they do not relax any conforming rule).

  • gap22 __FILE__ / __LINE__ — supported (2026-10-19). The scanner now allows a leading _ in identifiers, the two names are reserved literals, and the parser folds them to the current file-name string and line-number integer (scanner.frm records the file with SetFileName). Corpus: packed (+2 more __LINE__ users) now pass.
  • gap09 scalar actual → ARRAY OF BYTE — accepted (2026-10-19). SYSTEM.BYTE is V3's 32-bit CARDINAL, so ARRAY OF BYTE cannot be byte-granular; the ARRAY OF BYTE open formal is marked at parse time and a scalar/pointer/string actual is accepted. For a scalar the caller builds a stack descriptor [count = SIZE(actual)][copy of the value], so HIGH matches gm2's SIZE-1, but writes reach the copy, not the actual, and a string actual is passed as-is (its HIGH is the NUL index, so one less than gm2's). A genuine 8-bit BYTE (and byte-exact buffers) remains out of scope. Corpus: aochar, arrayofbyte, bytearray (×2) now compile.
  • gap10 scalar VAR actual, same size — accepted (2026-10-19). VarParamOk accepts a scalar VAR actual of a different type when ObjectSize matches (e.g. INTEGER for VAR WORD). testparam3 (SHORTREAL for VAR WORD) still fails: V3 models every real as 8 bytes, so there is no 4-byte SHORTREAL.
  • gap11 bare procedure value as a statement — accepted (2026-10-19). The PIM PROC type keyword is now recognised, and a proc-typed designator with no parameter list is an implicit zero-argument call (named or indirect).
  • gap12 variant records — extended (2026-10-19). Empty arms, ELSE arms, comma-separated labels, tolerated extra | separators, untagged inner CASE : T OF, and nested variant CASEs inside an arm. (An untagged variant falls back to sequential layout, since there is no tag slot to overlay from.)
  • gap18 set-typed CASE labels — accepted (2026-10-19). A set selector takes set labels; the compare-chain uses word-wise set equality (QbeGen.CmpSet).
  • gap14 __BUILTIN__ / __ATTRIBUTE__ pragmas — accepted (2026-10-19). An optional declaration pragma after PROCEDURE (__BUILTIN__, or __ATTRIBUTE__ __BUILTIN__ (( name ))) is parsed and ignored; the procedure is compiled normally. Corpus: builtin.def, builtin.mod.

The gap13 remainder (standard builtins as identifiers) and gap14 (__BUILTIN__) remain; gap19/gap21 are decl-order.

Not represented by a source

  • Record array field passed as an open array — a record's inline array field loses its length word when the record sits in static array-of-record data, so passing the field as an ARRAY OF … actual reads length 0 and traps. Worked around by flattening Lower's tables; the general fix and docs/wip/nested-array-field-bug.mod remain open (see docs/summary_l3_selfhost_fix.md).

  • Size-sensitive V3 miscompile — root-caused 2026-10-19: not size-sensitive, and not a codegen bug at all. The ASTDUMP debug dump printed the literal "Parsed correctly", which satisfied the fixpoint's grep -q Parsed gate while the compiler session was reporting Incorrect source; removing the dump simply unmasked the real errors (Lower's forward procedure calls). Fixed in a3ef897.