feat(stdlib/S1.1): DeclId for every declaration — additive DeclTable [additive]

Build a DeclTable in parallel with the import facts: every RawDeclRef
(source / imported / namespaced / C-imported) gets a stable DeclId carrying
source path, display name, AST node identity, span, and DeclKind. Namespace
targets record their members' DeclIds (NamespaceTarget.member_ids). A generic
struct's template is keyed by DeclId in a parallel struct_template_by_decl
store, written alongside the live name-keyed struct_template_map.

A Debug-only round-trip cross-check (RawDeclRef -> DeclId -> AST node ptr)
asserts the table identifies the same node across the corpus, run from
buildDeclTable and pinned by a unit test.

Additive (S0.1 class: mirror): the old maps stay active and lowering still
consumes them; nothing reads the DeclTable / struct_template_by_decl for
selection yet (the S4 cutover does). Generated IR + output bytes are unchanged
by construction.

Gate over the baseline-green corpus: zig build, zig build test (424/424),
bash tests/run_examples.sh (540 passed) — all exit 0; single-author output
byte-identical (37 .ir snapshots unchanged).
This commit is contained in:
agra
2026-06-09 11:25:04 +03:00
parent 864a14e42b
commit 8058be2538
5 changed files with 348 additions and 1 deletions

View File

@@ -38,6 +38,10 @@ pub const Compilation = struct {
/// Namespace import edges (`importer → alias → NamespaceTarget`), built by
/// `imports.buildImportFacts`. Borrowed by `ProgramIndex.namespace_edges`.
namespace_edges: imports.NamespaceEdges,
/// Stable `DeclId` for every declaration (Fork C S1), built by
/// `imports.buildDeclTable` in parallel with the import facts. Borrowed by
/// `ProgramIndex.decl_table`.
decl_table: imports.DeclTable,
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
@@ -68,6 +72,7 @@ pub const Compilation = struct {
.module_fns = imports.ModuleFns.init(allocator),
.module_decls = imports.ModuleDecls.init(allocator),
.namespace_edges = imports.NamespaceEdges.init(allocator),
.decl_table = imports.DeclTable.init(allocator),
.target_config = target_config,
.stdlib_paths = stdlib_paths,
};
@@ -143,6 +148,12 @@ pub const Compilation = struct {
self.module_decls = facts.decls;
self.namespace_edges = facts.ns_edges;
// DeclTable (Fork C S1): a stable DeclId for every declaration, built in
// parallel from the SAME modules. Additive — nothing consumes it for
// selection yet, so generated IR + bytes are unchanged. Updates
// `namespace_edges` in place to record each target's member ids.
self.decl_table = try imports.buildDeclTable(self.allocator, self.file_path, mod, &cache, &self.module_decls, &self.namespace_edges);
// Store main file source in import_sources so error reporting can find it
self.import_sources.put(self.file_path, self.source) catch {};
@@ -312,6 +323,7 @@ pub const Compilation = struct {
lowering.program_index.module_fns = &self.module_fns;
lowering.program_index.module_decls = &self.module_decls;
lowering.program_index.namespace_edges = &self.namespace_edges;
lowering.program_index.decl_table = &self.decl_table;
lowering.lowerRoot(root);
if (self.diagnostics.hasErrors()) return error.CompileError;