Composites complete. Suite 64/64 (30 run — incl. 3 trap-aborts —
NIL was InvalidType piggy-backing on error suppression, which
made p := NIL silently emit nothing and p = NIL fold false.
Now FNil/ClNil/dNil: NIL assigns to pointers (210
elsewhere — i := NIL finally errors instead of vanishing),
compares with pointers via ceql/cnel (213 against the rest),
and is rejected everywhere else through existing predicates
(211/212/214/222/230 all automatic). Named CONST X = NIL
flows identically. No new error codes needed.
M2.atg)PointerType (POINTER TO, never open inside); ^ suffix with
sfx discipline (address flows, load at use; chains compose:
pa^[i], pr^.f, pp^^); < > <= >= on pointers are 213.NEW/DISPOSE as builtin statements (no call syntax until
step 4): plain vars via name, suffixed designators via address;
210 on non-vars, 219 on non-pointers.Design root loads pointers (LoadPtr); Assign stores them
(StorePtr); VarDecl accepts them ({ l 0 } data).DISPOSE nils afterwards — deviates from Wirth-undefined
(testable postcondition, safer); DISPOSE is shallow (nested
objects leak — documented); nil-deref is raw (no check).QbeGen, all probed first)LoadPtr/StorePtr, CmpL, DataLineL, NewHeap (extern
malloc, size from descriptors) + recursive InitHeap (static
counts stored, nested objects allocated unrolled, members
otherwise garbage). Single-arg extern calls and store-immediates
(storel 0, $p) verified by probe before use.
FNil/ClNil/dNil, Assignable nil→ptr rule, EqCheck nil rules.
NewPtr/PtrBase (Test2 heritage) finally wired.
t_pointer → 42 (NEW/deref/alias/both NIL directions/DISPOSE/
nil-after), t_ptrarray → 15 (heap sizing, ^-index chains),
t_ptrrec → 15 (record heap objects, pr^.f chains),
t_ptrnest → 10 (recursive heap allocation), t_opaqueptr
(pointer-to-opaque descriptors — the step-4 ADT hook),
t_bad_deref/t_bad_new → 219. Total 64.
Deferred: recursive DISPOSE, nil-deref trap, HIGH/LEN
(step 4 calls), class lowering, procedure-type calls.