step4 to create)74/74 tests green (49 regressions + 15 run + 10 rejection), mc64 24/24 + boot + readtest green.
Composite types (Phase 3): fixed ARRAYs (bounds, 1D/multi-D, unchecked scaled indexing, byte-packed CHAR/BOOLEAN), RECORDs (offsets, .field, WITH incl. nested), SETs (+ union, - difference, * intersection, inclusive .. ranges), POINTERs (NEW/DISPOSE via VM ALLOCATE, ^, NIL), strings (ARRAY OF CHAR literal assign). Open arrays deferred; whole array/record copy deferred except string literals.
SymTab: TypeSlots (slots, 0=unsized), TypeLo/Hi/Len, ArrayLo/Hi/Len, FieldOffset, NewSubB/NewArrayB/EnumAdd, record tNext offsets, sized FixPending (locals re-based, base=lowest), pointer structural compatibility in Assignable (same-base Ptrs assignable).MGen: multi-slot globals (DeclVarSized, vBase/vSize, DVarCount=nVars), IdxScale (unchecked base+(i-lo)*bytes), FieldAdd, CopyBlock, AllocOp/DeallocOp (40H 05H/06H), BitXor, EmitString (8CH inline), StrLenOf/StrComp, Swap/LoadByte/StoreByte (0DH/1DH for CHAR), WithEnter/Exit/WithAddr (temp globals, top-down field search).M2c.atg: VarDecl sized, subrange literal bounds (NewSubB, else 230), EnumAdd, nested NewArrayB, value-composite params 230, DesignHead (Ptr→PushVar, Array/Record→PushAddr, Field→WithAddr), DesignTail ([] IdxScale + byte-sized CHAR, . FieldAdd, ^ with first-tail keep else Deref), Fact deref (LoadIndir/LoadByte), AssignOrCall (sfx→StoreIndir0/StoreByte, whole composite 210/230, string Str→Array copy with length check 210), New/DispStat (PushAddr/WithAddr + PushBytes + Alloc/Dealloc), set +-* (Or/And+Xor), string literals via EmitString (no 230), composite =/# rejected 213, WithStat (PushAddr/WithAddr + WithEnter, no 230).mc64/Extended,Loader2: heap bump-up fix (was top-down colliding with stack at 16777208, giving heapAddr instead of 42). SetHeapBase(next) after loads, AllocateHeap grows up with SP check, FREEMEM=SP-hp. mkdtest 24/24 still 252 (exclusive VM kept; M2c ranges made inclusive via hi+1).15 run: t_arr 39 (1D), a_mat 134 (2x2 multiply), a_sieve 129 (BOOLEAN sieve), a_varpar 150 (VAR array params), a_enum 21 (enum index), t_rec 30, r_nest 135 (nested records + nested WITH), t_with 37, r_varpar 303 (VAR record), t_ptr 42 (NEW/^/DISPOSE), t_ptr0 5 (NIL/=), p_list 21 (linked list + recursion), t_setop 22 (+*-), s_range 21 (ranges), t_str 11 (strings). 10 rejections, each exactly one error: 218, 217, 210 (array:=int), 216, 215, 219 (NEW non-ptr), 222, 230 (value array param), 210 (string too long), 210 (record:=int).
51H store order wrong (addr on top) for addr,value order — use 70H (StoreIndir0).next with SP check.FieldMask exclusive hi ((1<<hi)-(1<<lo), missing hi) — M2c pushes hi+1 for inclusive ranges (VM/mkdtest unchanged at 252).IdxScale ebytes=1, LoadByte/StoreByte (0DH/1DH); slots over-allocated 8x, acceptable.a:=x gave 230 hiding 210 — check Assignable before 230.Design unreachable after WITH lift (Coco error) — removed dead Design.dk = KindField & ~sfx precedence (= tighter than & in generated Modula-2? Actually & tighter — need parens) — parenthesized.M2c.atg header)Unchecked indexing (no DA/DB), NIL deref reads 0 (no trap yet), CHAR/BOOLEAN byte-packed (slots 8x), open arrays deferred (parse error), whole array/record copy deferred except string literals (230), VAR actuals must be simple (a[i]/p^/fields as VAR →233), value composite params/returns 230, composite =/# 213 (no string_comp yet), 8-deep WITH, 1024 slots/type.