Suite 81/81 (39 run — incl. 4 trap-aborts — + 42 reject). LL(1)-clean (only the known-benign TypeBlock advisory). Nested/recursive/module-level all lower; methods stay 230.
B and
D mutate A's s), three-level nesting (A > B > C), and
nested recursion (Down calls itself through the display).l. Its entry allocates an 8-byte-per-slot link record
(alloc8 520, 64 slots + parent link) and stores the incoming
link at [0].LocAdd (locals + params) stores each slot address into the
record: [1..]. AddrOf of a same-scope var returns the slot;
of an up-level var walks the chain.LocFindUp returns levels + flat index):
walk loadl levels times from the current link, then load
the link cell. For composites the cell holds the address;
for scalars the cell holds the slot address (so indexing/
deref compose unchanged).CallBegin time (the
caller context can't change mid-call): module callers pass 0;
others walk funcDepth - calleeDepth links. Depth comes from
SymTab.ProcDepthOf (lexical, recorded at heading time).QBE rejects a function definition nested inside a function body,
but the parser reaches Inner's BEGIN while still inside
Outer's body. First fix: buffer nested-function text and emit
it after main. That failed for 3 levels: a single shared
buffer preserved parse order, so C (parsed inside B)
landed textually inside B's emitted body → "label expected".
Cure: one buffer per nesting depth (nestBufs[0..15]), so
each function's own text stays contiguous regardless of how the
parse interleaves; EndModule flushes them in depth order.
outSel = funcDepth is derived, not counted (AbortFunc and
EndFunc both restore it), which removed the stale-flag class of
bug entirely.
ProcDecl no longer sets NoEmit for nesting (methods still
do); the EndFuncHeader flush is at the Block boundary so
FORWARD/DefUnit paths discard cleanly via AbortFunc.P; calls (parameterless proper procedures) are now
legal (AssOrCall third alternative); they were a syntax error
before. Inner; in Modula-2 style finally parses. F();
(function-as-statement) and P(args); with wrong arity stay 233.LocFull guard → 233 past 64 locals per scope.fdep per procedure (lexical depth at heading), ProcDepthOf.
Nothing else changed — the scope tree from step 1.1 already
modelled nesting, so name lookup needed no work.
t_nestedproc → 20 (inner reads+writes parent locals, called
twice), t_nestdeep → 211 (three levels + siblings sharing the
parent, proven by the output), t_nestrec → 15 (nested
recursion); t_nestedproc promoted from 230-reject to a real
run test. Total 81.
Deferred: methods still 230 (class lowering), procedure-type
variables, separate compilation + opaque completion + HIGH/
LEN (4.3), >64 locals, F()^ result suffixes.