# V3 step 1.2 — dynamic symbol storage (done 2026-09-19) Follow-up to step 1.1 (scope tree + per-scope BST): the fixed-size pools are gone, replaced by `Storage`-allocated linked structures. `SymTab.def` unchanged apart from dropping the now-meaningless `MaxSyms`; `M2.atg` untouched; suite stays 6/6. ## What changed (`compiler/src/SymTab.mod` only) - Symbols: heap nodes (`SymPtr`, `ALLOCATE` + `TSIZE`) linked as a BST per scope instead of `nodes[0..255]`. No capacity limit; `Enter` fails only on duplicates. - Scopes: heap nodes (`ScopePtr`) forming the scope tree, plus a creation-order `link` chain so `PrintTable` still dumps every scope (in-order per scope, alphabetical). - Record fields: heap list (`FieldPtr`, filtered by `owner`) instead of `fields[0..511]`. - Kept bounded on purpose: `pend[]/pendF[]` (transient, per single declaration, max 64) and type descriptors (`tform[]/tref[]` — `TypeIndex` is an INTEGER woven through the grammar, so descriptors stay indexed for now). - Nothing is ever freed: one compilation per process, the whole table is discarded at the next `Init`. `DEALLOCATE` intentionally unused (single-pass compiler, no steady-state growth). ## Verification Rebuilt clean (LL(1)-clean, no gm2 warnings introduced), 6/6 green: insert/find/dup-detection all exercised (`t_bad_dup` → 200, `t_bad_undecl` → 201, 3 run tests byte-identical `.ssa` — the backend is untouched). ## Note for step 7 (syslib port) `FROM Storage IMPORT ALLOCATE` is now the only gm2-hosted import in `SymTab` (plus `SYSTEM.TSIZE`, directly lowered later). The port swaps it for the self-hosted `Storage` without touching the tree logic — one reason the pool removal happened before the port.