comparison-PIM4-gm2-V3.md 8.3 KB

PIM4 vs GNU Modula-2 vs V3 โ€” feature comparison

Date: 2026-10-22 ยท V3 state: v3-proc-types (suite 255/255, self-hosting fixpoint OK 3,935,235 bytes, corpus 503/612, 0 crashes).

Scope. PIM4 is Wirth's Programming in Modula-2, 4th edition (the language specification, not a compiler). GNU Modula-2 (gm2) is the GCC front end: its PIM and ISO modes plus the extensions common in its testsuite. V3 is this compiler: a PIM/ISO subset plus the gm2 compatibility it deliberately chose.

Legend: โœ… supported / standard ยท ๐Ÿ”„ partial or caveated ยท โŒ absent ยท โš ๏ธ non-standard extension ยท n/a not applicable.

The tables describe the common/default behaviour; the exact flags and modes of gm2 can change individual cells. V3's deliberate deviations are listed at the end.

Standards & dialect

Feature PIM4 GNU Modula-2 V3
PIM base language โœ… (definition) โœ… (PIM 2/3/4 modes) โœ… (PIM/ISO subset)
ISO 10514-1 base โŒ (predates ISO) โœ… ๐Ÿ”„ mostly; see missing ISO rows below
ISO 10514-2 generics โŒ โœ… โœ… (refinement form)
ISO 10514-3 OO โŒ โŒ โŒ (CLASS is Clarion-form, not ISO OO)
Declaration before use โœ… strict ๐Ÿ”„ multi-pass, accepts forward refs โœ… strict for data; ๐Ÿ”„ forward procedure calls allowed
FORWARD declarations โœ… โœ… โœ…
EXPORT QUALIFIED / UNQUALIFIED โŒ (PIM export list only) โœ… โœ…
Foreign modules (DEFINITION MODULE FOR "C") โŒ โœ… โœ…

Lexical

Feature PIM4 GNU Modula-2 V3
Identifiers with _ โŒ (classic names) โœ… โœ…
Numeric bases โœ… octal B, hex H โœ… B/H (and more) โŒ (0x/0X only; 012H/666B rejected)
Nested (* *) comments โœ… โœ… โœ…
'โ€ฆ' and "โ€ฆ" strings โœ… โœ… โœ…
Unicode UCHAR/UString โŒ โŒ โœ… (extension: U'a', U"โ€ฆ", UCHR, UORD)

Types

Feature PIM4 GNU Modula-2 V3
INTEGER/CARDINAL/SHORTINT/LONGINT, REAL/LONGREAL, BOOLEAN, CHAR โœ… โœ… โœ…
Subranges โœ… โœ… โœ… (typed CHAR/enum subranges since 2026-10-22)
Enumerations โœ… โœ… โœ…
Sets (SET OF) โœ… any finite ordinal (impl. limit) โœ… ๐Ÿ”„ bool/char/enum/small-int subrange; span โ‰ค 65536; no SET OF CARDINAL
PACKEDSET โŒ (ISO) โœ… โŒ
Fixed arrays, multi-dimensional โœ… ARRAY [a], [b] OF โœ… โœ… both [a], [b] and [a, b]
Open arrays (1-D) โœ… โœ… โœ…
Multi-dimensional open arrays โŒ (ISO addition) โœ… โŒ (V3 descriptor-per-level representation; unbounded* gaps)
Records, variant records โœ… โœ… โœ… (plus empty arms/ELSE extensions)
Pointers, NIL, opaque types โœ… โœ… โœ…
Procedure types โœ… (PROCEDURE) โœ… (PROCEDURE, PROC) โœ… (PROCEDURE, PROC; comma/unnamed forms)
Complex types (COMPLEX, LONGCOMPLEX) โŒ โœ… (ISO) โŒ (COMPLEX64 is a REAL placeholder, no arithmetic)
SYSTEM sized types (WORD32, CARDINAL8, BITSET32, โ€ฆ) โŒ โœ… โœ… names, but mapped to V3's 32-bit/64-bit model
BYTE granularity โœ… 8-bit โœ… 8-bit ๐Ÿ”„ BYTE = 32-bit CARDINAL; ARRAY OF BYTE is not byte-granular
SHORTREAL (32-bit) โŒ โœ… โŒ (all reals are 8 bytes)
ADDRESS arithmetic (ADDADR/SUBADR/DIFADR) โŒ โœ… โŒ
Absolute variables VAR [addr]: T โŒ โœ… (extension) โŒ
Set ordering (<, <=, >, >=) โŒ (=/#/IN only) โœ… (extension) โŒ

Statements & procedures

Feature PIM4 GNU Modula-2 V3
IF/CASE/WHILE/REPEAT/LOOP/EXIT/WITH, RETURN, HALT โœ… โœ… โœ…
FOR over any ordinal (CHAR/enum) โœ… โœ… โœ… (since 2026-10-22)
GOTO / labels โœ… โœ… โœ…
INC/DEC on enumerations โŒ (integer) โœ… โŒ (integer only)
Empty string ""/'' as CHAR โŒ/unclear (ISO rule) โœ… โœ… (ISO rule, since 2026-10-22)
LENGTH โŒ (ISO adds it) โœ… โœ…
HIGH โœ… โœ… โœ… / ๐Ÿ”„ (HIGH of a string CONST still missing)
TSIZE/SIZE/ADR โœ… โœ… โœ…
SHIFT/ROTATE โš ๏ธ implementation SYSTEM extension โœ… โœ…
TBITSIZE โŒ โœ… โŒ
ISO exceptions (EXCEPT, RETRY, EXCEPTIONS) โŒ โœ… โŒ
Module finalization (FINALLY) โŒ โœ… โŒ
__FILE__ / __LINE__ / __FUNCTION__ โŒ โœ… โœ… / โœ… / โŒ
__BUILTIN__ / __ATTRIBUTE__ pragmas โŒ โœ… โœ… (parsed, ignored)
Inline ASM โŒ โœ… โŒ

Modules, compilation, libraries

Feature PIM4 GNU Modula-2 V3
Definition / implementation / program modules โœ… โœ… โœ…
Local modules โœ… โœ… โœ…
Separate compilation โœ… โœ… (object files/archives) ๐Ÿ”„ one invocation compiles all units into one image; no incremental objects
Generics โŒ โœ… โœ…
Object orientation โŒ โŒ ๐Ÿ”„ Clarion-form CLASS (single inheritance, virtual dispatch), not ISO 10514-3
PIM coroutines (PROCESS, NEWPROCESS, TRANSFER, IOTRANSFER) โœ… โœ… โœ… (IOTRANSFER degrades to a transfer)
ISO COROUTINES module โŒ โœ… โŒ (PIM interface only)
Standard library โŒ (none defined) โœ… PIM + ISO libraries ๐Ÿ”„ subset: ISO/PIM I/O, strings, storage, SysClock; no ISO exceptions/termination libs
Self-hosting n/a โœ… (part of GCC) โœ… (byte-identical 3-stage fixpoint)
Backend / target n/a GCC (many targets) QBE โ†’ C (amd64 SysV today)

The practical differences

  • PIM4 is the clean specification: strict declaration order, no ISO exceptions/complex numbers/PACKEDSET/generics, no standard library, no sized SYSTEM types or address arithmetic.
  • gm2 is the superset in practice: PIM and ISO modes, generics, exceptions, complex numbers, PACKEDSET, multi-dimensional open arrays, sized SYSTEM types, address arithmetic, absolute variables, ASM, pragmas, and many extensions โ€” but deliberately permissive (multi-pass resolution accepts forward references).
  • V3 is a PIM/ISO compiler with the opposite bias: it rejects gm2 leniencies (declaration order), implements the common ISO/PIM constructs (generics, coroutines, foreign modules, ISO strings/SYSTEM/ procedure types, empty string as CHAR), and documents its chosen gm2 compatibility (__FILE__/__LINE__, scalarโ†’ARRAY OF BYTE, same-size VAR, bare proc values, variant extensions, set CASE labels, libc prototypes). Its hard gaps are the large ISO features (exceptions, complex arithmetic, PACKEDSET, finalization/protection, multi-dimensional open arrays, ISO OO) and its 32-bit word model (BYTE granularity, SHORTREAL, REAL width), plus a 65536-bit set span limit.

V3-specific deviations and limits

  • Strict data declaration order (PIM-conforming); forward procedure calls are allowed where strict PIM would require FORWARD.
  • 32-bit word model: INTEGER/CARDINAL/WORD/BYTE are 32-bit; LONGINT/LONGCARD are 64-bit; every REAL/SHORTREAL is 8 bytes; COMPLEX* is a placeholder. ARRAY OF BYTE is a compatibility descriptor, not an 8-bit buffer.
  • Sets: bases limited to bool/char/enum/small subranges; total span โ‰ค 65536; no SET OF CARDINAL.
  • No runtime range checks on subrange assignment (V3 is already lenient for the integer family).
  • Multi-dimensional open arrays are not supported: V3 represents an array level as its own descriptor, whereas gm2 passes a flat block โ€” accepting the corpus files would compile but miscompile.
  • Single-invocation compilation: definition, implementation and program units are compiled together into one image; there is no incremental object/archive format.
  • OO is the Clarion-form CLASS dialect (single inheritance, virtual dispatch), not ISO 10514-3.

Sources

  • V3: docs/STATUS.md, docs/features.md, docs/gaps/README.md, docs/analysis_gaps.md, docs/summary_session-2026-10-22.md; the gates in this document were run at v3-proc-types.
  • gm2: the GCC Modula-2 testsuite and gm2-libs/gm2-libs-iso definition modules in the sibling gcc-git tree.
  • PIM4: N. Wirth, Programming in Modula-2, 4th edition.