|
|
1 dzień temu | |
|---|---|---|
| .. | ||
| README.md | 1 dzień temu | |
| gap01_fwd_type_const_conv.mod | 5 dni temu | |
| gap02_fwd_type_var.mod | 5 dni temu | |
| gap03_fwd_type_heading.mod | 5 dni temu | |
| gap04_fwd_const_bound.mod | 5 dni temu | |
| gap05_fwd_type_size.mod | 5 dni temu | |
| gap06_fwd_setconst.mod | 5 dni temu | |
| gap09_scalar_to_bytearray.mod | 5 dni temu | |
| gap10_var_param_type.mod | 5 dni temu | |
| gap11_bare_proc_stmt.mod | 5 dni temu | |
| gap12_variant_empty_arms.mod | 5 dni temu | |
| gap14_builtin_pragma.def | 5 dni temu | |
| gap16_wide_set.mod | 5 dni temu | |
| gap17_set_of_cardinal.mod | 5 dni temu | |
| gap18_set_case_labels.mod | 5 dni temu | |
| gap19_fwd_array_index.mod | 5 dni temu | |
| gap20_fwd_set_of_type.mod | 5 dni temu | |
| gap21_fwd_record_field.mod | 5 dni temu | |
| gap22_file_line.mod | 5 dni temu | |
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
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 aPOINTER'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.| 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__)
libc prototypes — fixed (2026-10-22): the known C functions
now have real signatures (exit, write/read/open/close/
lseek, malloc, memcpy/memset/strncpy, system/getenv,
atof/strtod). printf/snprintf are varargs functions: the
format is checked as ARRAY OF CHAR, extra arguments are untyped,
and the result may be used or discarded in statement position.
That last point is the single accepted "function call as statement",
limited to foreign C varargs; an ordinary Modula-2 function used as a
statement is still 233 (t_bad_funstmt). Corpus +6:
procedure2, tinyparam, tinyparam2, sizes, variant9,
varient (except5 gets past printf and stops on ISO exceptions).
Regression t_libc2.ISO SYSTEM sized types + qualified SYSTEM — fixed (2026-10-22):
WORD8/16/32/64, BITSET8/16/32, REAL32/64/128,
COMPLEX32/64/128, CSIZE_T/CSSIZE_T/COFF_T and the
BITSPERLOC/LOCSPERWORD/LOCSPERBYTE constants are predefined.
The hard-coded SYSTEM module is now registered with its own scope,
so SYSTEM.CARDINAL8/SYSTEM.BITSET32 resolve (the qualified type
path used QualType, which needs a module). FROM SYSTEM IMPORT
stays permissive (its names are global predefs/keywords). Corpus
+8: compsize, int8field, returnrecord, printsize,
testgeneric, testgeneric2/3/4. Regression t_system. V3's
word model is 32-bit, so the narrow names share INTEGER/CARDINAL
and COMPLEX* is a REAL placeholder.
Multi-index arrays — fixed (2026-10-22): the PIM/ISO form is
ARRAY [lo..hi], [lo..hi] OF T (one bracket group per dimension).
V3 only accepted a non-standard single-bracket comma list; it now
takes both, nesting the groups inside-out. Corpus +6:
arraybool, assignment2, foo, recordarray2, tinyarray4,
tinyarray5.
Subranges keep their ordinal base — fixed (2026-10-22):
['A'..'Z'] was classified as an integer subrange, so assigning a
CHAR (or an enumeration literal to [red..blue]) was
incompatible assignment/comparison. Subranges now carry their
base type (SymTab.NewSubB), and CHAR/BOOLEAN/enum values
assign to and compare with a subrange of the same base. Corpus
+3: subrange16, subrange17, enum3. Not covered yet: a
runtime range check on assignment (V3 remains lenient, as for the
integer family).
FOR over any ordinal — fixed (2026-10-22): the control
variable and bounds may be CHAR, BOOLEAN, an enumeration or a
subrange (bounds must be assignment-compatible with the variable),
not only the integer family. MIN/MAX of a SET now has the
set's base type, so FOR i := MIN(S) TO MAX(S) works. Corpus
+3: forloop2, smallset4, minmax.
ISO empty string literal — fixed (2026-10-22): "" / '' is a
string literal of length 0 and is compatible with CHAR, where its
value is the terminator (ISO 10514-1, "Strings" and "Assignment
compatibility"). V3 typed it as a plain string, so ch := "",
ch = "", CASE ch OF "", FOR ch := "" TO …, an actual for a
CHAR formal, and RETURN "" were rejected or wrong. It stays a
string in ARRAY OF CHAR contexts (whole-array assignment and
content comparison), so both sides keep working. Corpus +6:
arraychar, arraychar2, arraychar3, nulcharcase,
nulcharvar, forloopnulchar. Regression t_emptychar.
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).
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.
Record array field passed as an open array — fixed (hybrid
QbeGen.ArrBodyItems): small record arrays are expanded per element so
each inline array field's length word is in the static data; large ones
get a generated runtime init loop. Covered by t_arrrecfld,
t_arrrecbig, t_nestarr; 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.