refactor(imports): retain dup same-name fn authors + build identity indexes [0102a]

First of four fix-0102 sub-steps. Purely additive: retains data that the
flat/directory merge currently first-wins-drops and builds two identity
indexes for later bare-name disambiguation (fix-0102c). No resolution
change — the existing first-wins bare path still wins; suite unchanged.

- mergeFlat + directory merge: stop dropping a same-name FUNCTION authored
  by a different module/file. Non-function decls keep first-wins dedup; node
  identity dedup is untouched.
- flat_import_graph: a flat-only subset of import_graph, recording an edge
  only for a bare `#import` (imp.name == null), never a namespaced
  `ns :: #import`. Threaded through resolveImports/resolveDirectoryImport
  and into ProgramIndex.
- module_fns (path -> name -> *const FnDecl): per-module authored-function
  index mirroring module_scopes, built in core.zig from the main module +
  cache. Same-name cross-module authors stay distinct under their own paths.
- imports.test.zig: asserts both a.sx/b.sx greet authors are retained in
  module_fns and in the global flat list, and that flat_import_graph
  excludes the namespaced edge while import_graph includes it.

Gate (this worktree): zig build, zig build test (398/398),
bash tests/run_examples.sh (457 passed) all green.
This commit is contained in:
agra
2026-06-06 11:27:11 +03:00
parent 792ed55068
commit ff9cb50079
5 changed files with 245 additions and 11 deletions

View File

@@ -26,6 +26,12 @@ pub const Compilation = struct {
import_sources: std.StringHashMap([:0]const u8),
module_scopes: std.StringHashMap(std.StringHashMap(void)),
import_graph: std.StringHashMap(std.StringHashMap(void)),
/// Flat-only subset of `import_graph` (bare `#import` edges, no namespaced
/// `ns :: #import`). Borrowed by `ProgramIndex.flat_import_graph`.
flat_import_graph: std.StringHashMap(std.StringHashMap(void)),
/// Per-module authored-function index (`path → name → *const FnDecl`).
/// Borrowed by `ProgramIndex.module_fns`.
module_fns: imports.ModuleFns,
ir_emitter: ?ir.LLVMEmitter = null,
/// Lowered IR module, kept alive past `generateCode` so post-link
/// callbacks can re-enter the interpreter to invoke sx functions
@@ -52,6 +58,8 @@ pub const Compilation = struct {
.import_sources = std.StringHashMap([:0]const u8).init(allocator),
.module_scopes = std.StringHashMap(std.StringHashMap(void)).init(allocator),
.import_graph = std.StringHashMap(std.StringHashMap(void)).init(allocator),
.flat_import_graph = std.StringHashMap(std.StringHashMap(void)).init(allocator),
.module_fns = imports.ModuleFns.init(allocator),
.target_config = target_config,
.stdlib_paths = stdlib_paths,
};
@@ -101,6 +109,7 @@ pub const Compilation = struct {
&self.diagnostics,
self.stdlib_paths,
&self.import_graph,
&self.flat_import_graph,
self.comptimeContext(),
) catch return error.CompileError;
@@ -111,6 +120,11 @@ pub const Compilation = struct {
self.module_scopes.put(entry.key_ptr.*, entry.value_ptr.scope) catch {};
}
// Per-module authored-function index, built from the SAME modules as
// `module_scopes` (main + every cache entry). Keyed by path; same-name
// cross-module authors stay distinct under their own paths.
imports.buildModuleFns(self.allocator, self.file_path, mod, &cache, &self.module_fns) catch {};
// Store main file source in import_sources so error reporting can find it
self.import_sources.put(self.file_path, self.source) catch {};
@@ -276,6 +290,8 @@ pub const Compilation = struct {
lowering.diagnostics = &self.diagnostics;
lowering.program_index.module_scopes = &self.module_scopes;
lowering.program_index.import_graph = &self.import_graph;
lowering.program_index.flat_import_graph = &self.flat_import_graph;
lowering.program_index.module_fns = &self.module_fns;
lowering.lowerRoot(root);
if (self.diagnostics.hasErrors()) return error.CompileError;