# V3 step 5.6 — module-qualified symbols + real qualified access (done 2026-09-22) Removes both separate-compilation limitations from step 5.4/5.5. Suite 97/97 (54 run — incl. 4 trap-aborts, 7 sessions, 3 session-output, 2 session-input, 1 unit — + 43 reject). LL(1)-clean, zero gm2 warnings. ## 1. Module-qualified globals Module-level `VAR`/`CONST` data now emits as `$_` (previously `$`), so two modules with a global of the same name no longer collide at link time. `QbeGen.SetModule` (called by each unit's `Begin*`) supplies the module; `DeclVar`/`DeclConst` prefix it. Real-const startup flushes and the `ExitCode` load use the same qualified name. ## 2. Real per-module qualified access `L.x` / `L.P` no longer flatten-clone under the plain name (which let one library's export shadow another's). New `SymTab.MaterializeAlias(mod, name, alias)` clones under a per-module key `$` (`$` can't appear in identifiers), and the symbol node keeps: - `sym` — the base symbol name (for QBE mangling/global names), and - `mod` — the defining module. `SymBase` and `GlobalRef` read those back; `QbeGen.Mangled` now mangles via `SymBase` (drops any alias prefix) and `SymRef` builds `$_` for data access. All other lookups (type/kind/uid/params/result/external/depth) work unchanged because they only need `Find(alias)`. ## Tests - `ClashProg` → 60: two modules `ClashA`/`ClashB` each with a global `count` **and** a procedure `Get`; the program uses both qualified. Image shows `$ClashA_count`/`$ClashB_count` and `Get_0`/`Get_1`. - `MixProg` → prints `7`: `TextIO.WriteInt` (console) and `Files.WriteInt` (file) in one program — the exact case that failed before this pass. - Full prior suite unchanged (95 → 97). ## Remaining known edge `FROM A IMPORT x` followed by `FROM B IMPORT x` is still first-wins (`Materialize` returns the existing node) — genuinely ambiguous by name; callers should use qualified access or distinct names. Qualified access is fully per-module. ## Unblocks `Storage`/`SYSTEM` (`ADDRESS`, generic pointers) and the step-7 syslib port: `SYSTEM`/`Storage`/`Trap` can now be ordinary modules whose internals bind externals without symbol collisions.