CORPUS-TEST.md 4.1 KB

Pascal corpus census

Sources/Dezip/ is an external collection, not part of the build. The working tree now retains only pascsrc/: 71 .pas files, all of which compile. The original dump contained 4,919 .pas files (77 MB, about 354k lines); its census below is kept as history, not as the current result.

Method

Every file is compiled separately with shell/compiletest, in a fresh process and with a 5-second timeout. Separate processes matter: one crashing source must not hide the rest. The repeatable check is tests/corpus_check.py, wired into tests/run_all.sh when Sources/Dezip/pascsrc exists.

Historical census (pre-cleanup)

result count
compiles 49
errors 4,870
crashes/timeouts 0

By error code:

code meaning count
41 unknown construct/identifier 4,335
90 include file not found 418
102 not implemented 48
1 syntax / semicolon 39
30 simple type expected 20
56 type mismatch 9
99 compiler overflow 1

The useful subset is pascsrc/, which is the classic TP3 example material: 44 of 84 compile. The SWAG tree is 4,473 files, almost all FreePascal or Delphi units; only 5 compile.

Bugs found by the corpus

  • Typed constants containing an array of strings crashed the compiler. A one-character element such as 'I' is scanned as a CHAR scalar, not a string, so DefConst took the integer path and shifted a 16-bit value through divi until it became zero: SIGFPE in DefConst. The array element type is now consulted; a scalar element of a STRING array is stored as a one-character string. t118_strconstarray compiles and prints '', I, II.
  • This bug was also hit by Roman2.pas in the SWAG tree. It now gets a normal diagnostic (Word is not yet a type) instead of killing the compiler.

Main blockers visible in the census

  1. uses/unit imports. Most SWAG files cannot even reach a declaration after their uses line.
  2. The wider integer family: Word, LongInt, ShortInt, Single, Double.
  3. Turbo extras such as absolute, Printer, Dos, Mem/Msdos, and Addr beyond the currently supported pointer paths.
  4. Includes whose names or search paths differ from the file's own directory (ERROR 90, 418 files).

The surviving 71 files are wired into run_all.sh through tests/corpus_check.py; an absent Sources/ tree is a skip, because that material is user-owned and untracked. The current result is 71 / 71 OK.

Conservative cleanup

The obvious non-TP3 material was removed:

  • the whole Dezip/swag-pascal-master tree and its swag-pascal-master.zip;
  • 416 .pas files outside that tree that declare unit, use uses, or carry FreePascal/Delphi markers;
  • 42 zip archives whose Pascal entries were all marked in that way.

Mixed archives — including pascsrc.zip, which also contains the compiling TP3 examples — were deliberately kept during that first pass.

Before cleanup: 6,810 files, 4,919 .pas, 907 zips. After the conservative pass: 1,731 files, 71 .pas, 858 zips.

The final working-tree cleanup removed Sources/simtel and every Sources/Dezip entry except pascsrc/. The tree is now 78 files / 71 .pas / 0 zips, and all 71 Pascal files compile.

The remaining 71 Pascal files compile as 71 OK / 0 errors with the current compiler. The upgrades cover long identifiers, named labels, Addr, field widths, nested arrays, negative bounds, forward pointer types, NIL, forward procedure parameters, nested record fields, whole-record/array assignment, integer / as REAL division, Ord, Succ/Pred on enums, and enum subranges, a leading set constructor in a set expression, Round/Trunc, integer-to-REAL assignment, SHL/SHR, address-based pointers, char arrays, Msdos/Intr, and variant records. The TP3-feature gaps are now closed; the corpus is clean:

The final batch closed dynamic set constructors ([Storage[Index]]), text-file width formatting (Write(File, integer:width) and string widths), Getdir/Seg/Ofs/Mem, and text-file numeric Read/Readln.