← board

pasmith: multi-unit programs

Why

Every other rung on the widening list is in ([[feature-pasmith-widen-grammar]]): records

Shape

Emit N units plus a program: each unit declares types (records, enums, exception classes), some of them referring to types from earlier units; each exports procedures and functions; the program uses them in a random order. The checksum discipline is unchanged (one number out), so the oracle machinery needs nothing new.

The real work is in the driver, not the generator: tools/pasmith_run.py currently compiles one file. It has to write a unit set to a directory, put that directory on both compilers' unit paths (fpc -Fu, pxx -Fu) and compile the program against it — and the seed must still reproduce the whole set byte-for-byte.

Acceptance

pasmith --seed N --units 3 emits a program plus 3 units that FPC accepts (the generator's contract), the driver compiles and runs the set under every oracle, and a divergence still names its statement via the trace diff. One bounded run logged here, clean or not.

Done — 2026-08-13

tools/pasmith.py --seed N --units K --outdir DIR emits a support unit, K units and a program; tools/pasmith_run.py --units K drives them through every oracle. The single-file path is untouched — --units is a MODE, not a rung.

Shape, and why it is this shape

The three bug classes this ticket names are all about ORDER, and the third one (initialization sections) is the one that could easily have been tested unsoundly. Pascal initialises a unit's DEPENDENCIES first, and only then follows the uses clause. So the units are emitted as a chain — unit k uses unit k-1 — which pins the true order to u0, u1, ... uK-1, and the program's uses clause is then shuffled from the seed. A compiler that initialises in uses-clause order rather than dependency order produces a different order log and diverges; a compiler that gets it right cannot be made to differ by the shuffle. That keeps the rung inside the generator's contract: well-defined programs only, no implementation-defined ordering to produce divergences that are nobody's bug.

Per unit k: an exception class EUk descending from EUk-1 in an earlier unit (the b339 shape with a unit boundary through the middle), a record whose field type comes from unit k-1 (a layout that cannot be computed without resolving across the boundary), an enum, exported functions folded into the checksum, and an initialization section that reads unit k-1's initialised global and calls Note(k) on a shared support unit every unit depends on — so the order log is complete by construction.

The program raises EUk and catches it on EUj, j<=k chosen by seed: a descendant caught on a base declared in a different, earlier unit.

Checksum discipline unchanged — one number out — so the oracle machinery needed nothing new.

Driver

As predicted, the work was in the driver, and it came to less than expected because the shapes converge: both a single file and a unit set end up as "a .pas to compile with its directory on the unit path".

Acceptance

The bounded run, as asked: CLEAN

pasmith_run: 120 programs, 0 divergences
             (0 = FPC-rejected/generator bugs, 0 = known signatures, 0 = NEW)
             oracles=[fpc-O0, fpc-O2, pxx-O0, pxx-O2, pxx-O3]

600 compile-and-run pairs, no divergence. pxx agrees with FPC on cross-unit exception matching, cross-unit record layout, and initialization order for every seed tried.

Read that with the right amount of confidence. A clean run means either pxx handles these shapes, or the generated diversity is too narrow to have found anything — and the set IS narrow by design: the per-unit shape is fixed, and only the constants, the enum values and the catch level vary by seed. What is now in place is the structure (units, the dependency chain, the driver, the trace contract); widening what lives inside each unit is the cheap part and the obvious next step for anyone who wants this rung to earn more.

Single-file regression check: --seeds 1-6 --wide produces byte-identical output before and after this change (3 divergences, same signatures), confirmed against the committed version.

Log