Tag v3-corpus-run. V3 suite 169/169, fixpoint OK.
The TopSpeed corpus validated the sidecar grammar, not V3 the
compiler (the sidecar is a separate TSM2 binary built from
TopSpeed-V3-M2.atg; it reuses V3's SymTab/QbeGen/FileIO sources
but never runs compiler/M2). So this work runs V3 itself over two
real Modula-2 corpora and fixes what it finds.
Harness: tools/v3-corpus/corpus.sh — compiles each file with
compiler/M2 in a scratch tree, together with its sibling DEFINITION
and the DEFINITION of every module it imports ($V3_LIBS search path),
and splits failures into CRASH / LIB (unresolved import) / LANG (real
gap).
1. gm2 testsuite (gm2/pim/pass + gm2/iso/run/pass, 612 files):
| no libs | with $V3_LIBS |
|
|---|---|---|
| compile-OK | 242 | 392 |
| CRASH | 0 | 0 |
| LIB | 185 | 9 |
| LANG | 185 | 212 |
2. gm2 standard libraries (m2pim/m2iso/m2log/m2cor/m2min,
336 files):
| no libs | with $V3_LIBS |
|
|---|---|---|
| compile-OK | 78 | 127 |
| LIB | 176 | 0 |
| LANG | 82 | 209 |
(With the import path set, LIB noise is gone and the true LANG counts are visible.)
v3-fix-longline-crash) — GetLine
wrote past a 256-byte listing buffer; a long line (an 860-char enum)
overflowed the stack. Fixed (GetLine truncates, buffer 4096,
bounded caret loop); CRASH → 0.EXPORT QUALIFIED in DEFINITION modules (v3-export-qualified).SYSTEM facilities — predefine BYTE/SBYTE/WORD/SWORD/
LONGWORD/SHORTADDR/LONGADDR/PROC/LOC (mapped onto V3's
integer family / ADDRESS) so FROM SYSTEM IMPORT BYTE; and
ARRAY OF BYTE resolve.T[lo..hi] (INTEGER [-1 .. 24]).PROCEDURE (VAR ARRAY OF
REAL)) plus open arrays in procedure types and structural
proc-type formal compatibility (ParamTypesOk), so assigning a
procedure with an open-array parameter to a procedure variable works.corpus.sh now finds and passes the
.def of each imported module ($V3_LIBS), removing the LIB noise.T{…} (GNU Modula-2). A CONST whose value
is a constructor (my = arr {'h','e','l','l','o'}, arr {1,2,3,4 BY
3}, nested names { "Thu", "Fri" }) now lowers to a pooled static
descriptor (data $ctoN = { l len, … }) with the same layout as a
declared array, and the constant resolves to its address; whole-array
copy, indexing and LEN then work unchanged. Elements: scalars
(b/w/d/l by class), nested constructors, string literals for
nested ARRAY OF CHAR, and the expr BY n repeat form. New
QbeGen.Ctor{Begin,Elem,End}; the old TypedSetLit became
the unified TypedBraceLit (BITSET{…} still a set).RecName{…}
fills a record's fields in declaration order (static when every
element is constant, so it works in CONST; a nested constructor is
inlined, and a string becomes a matching CHAR-array field). When
any element is a runtime value the descriptor is built on the stack
(alloc8) and filled with stores/copies (ElemStore, CopyArray,
CopyRecord, CopySet); this also covers non-CONST array
constructors (a := arr{i, i+1, i+2}). strcons.mod now compiles.R{7, S{1,3,5}} (both
runtime and via a typed set constructor); the nested braceCls
dispatch flag is saved/restored around a nested set constructor.arraytype {Hello + " " + World}: CONST string values are
supported, + on constant strings folds to one literal
(QbeGen.StrFold), and a string element expands into consecutive
CHAR elements. constarray2.mod compiles.ARRAY <ordinalType> OF T (e.g.
ARRAY Colour OF T, ARRAY Sq OF T) — the index type's ordinal
bounds give [lo..hi] (array2/array3 now compile). Enum
values are accepted as array indices.MIN/MAX builtins over any ordinal type, array, or set
(MIN(Colour), MAX(large), ARRAY [MIN(c)..MAX(c)] OF T);
SymTab.TypeBounds + enum literal counts.FROM libc intrinsic — printf/exit/… import as permissive
external C procedures (varargs, no result) and bind to the C
symbols; string/CHAR-array actuals pass as descriptor+8.SET OF <enum>,
SET OF ['A'..'z'], enum/BOOLEAN subranges; span limit
256 → 65536.MIN/MAX for REAL/LONGINT and gm2 sized names
(LONGCARD, SHORTREAL, INTEGER8/16/32/64,
CARDINAL8/16/32/64).INCL/EXCL (statements) and SHIFT/ROTATE
(expressions, bit-by-bit over a runtime amount).String and opaque/forward types — an unresolved (opaque or
forward) alias is pointer-like (assign NIL, copy, compare, pass),
which is what gm2's opaque String needs. String is not
built-in: it is imported from a definition module
(DynamicStrings/opaque), as in gm2. An undeclared type name at
module level is reported (201, undeclared identifier) once the
module's TYPE declarations are known (FwdPending/FwdInfo).MODULE — exported names, nested-nested modules
and bodies are lowered as startup init functions (was already
largely working; verified and documented).ADDRESS ↔ pointer assignment (p := ADR(x)), checked before
the pointer-subclass test.undeclared identifier — SYSTEM facilities beyond the set
above, and small library holes.PROCEDURE __BUILTIN__ name(…), C-name
pragmas, ISO module attributes (not V3's dialect; skip).not supported yet — deliberate 230s.cd tools/v3-corpus
./corpus.sh # testsuite, no libs
G=$HOME/bin/Modula2/Gm2/lib/gcc/x86_64-pc-linux-gnu/16.0.1/m2
V3_LIBS="$G/m2pim:$G/m2iso:$G/m2log:$G/m2cor:$G/m2min" ./corpus.sh
V3_LIBS="$G/m2pim:$G/m2iso:$G/m2log:$G/m2cor:$G/m2min" \
./corpus.sh "$G/m2pim" "$G/m2iso" "$G/m2log" "$G/m2cor" "$G/m2min"
SYSTEM facilities / library holes.LargeInt-style operations; gm2-only pragmas (skip).tools/v3-corpus/{corpus.sh,README.md}, compiler/src/compiler.frm
(long-line), compiler/src/M2.atg (EXPORT QUALIFIED, anchored
subranges, unnamed proc-type params, TypedBraceLit array/record
constructors, index-type arrays, MIN/MAX, enum indices),
compiler/src/SymTab.def/.mod (SYSTEM predefs, ParamTypesOk,
TypeBounds, enum counts), compiler/src/QbeGen.def/.mod
(CtorBegin/CtorElem/CtorEnd, StrFold, FlushCtors, static +
runtime descriptor building), compiler/tests/t_ctor{1..7}.mod,
compiler/tests/t_minmax.mod, compiler/tests/t_longline.mod,
compiler/run_tests.sh, this doc.