ERR/E1.1 (slice 1): error-set type + global tag registry + decl registration
First sema/types step. Implemented in the IR layer (ir/types.zig +
type_bridge.zig + lower.zig), NOT src/sema.zig — lowering doesn't consume
sema; the frontend Type is LSP-only. Mirrors how enums are handled.
- ir/types.zig: new `.error_set` TypeInfo kind (ErrorSetInfo {name, tags:
[]u32}; identity = name, like enum) with a u32 runtime layout (size/align
4, LLVM i32) per the locked error-slot ABI. New TagRegistry on TypeTable
(global tag pool: name -> u32, monotonic, id 0 reserved for "no error").
internTag/getTagName/errorSetType helpers; `.error_set` arms in all 7
exhaustive switches + findByName.
- emit_llvm: toLLVMTypeInfo -> i32. print: writeType -> set name.
- type_bridge: resolveInlineErrorSet (mirrors resolveInlineUnion) +
.error_set_decl arm.
- lower.zig: registerErrorSetDecl (rejects empty `error { }` with a
diagnostic) wired into both top-level decl switches + the block-local one.
- tests: ir/types.test (TagRegistry 0-reserved + identity; errorSetType u32
layout + named display + dedup; sorted storage) and ir/type_bridge.test
(decl -> type + tag interning + re-resolve dedup).
End-to-end: `Foo :: error { A, B }` + main compiles + runs (exit 0) — first
ERR syntax to survive the full pipeline; empty set rejects with a diagnostic.
Inferred bare `!`, error.X value, and == typing deferred to slice 2 / E1.2.
zig build, zig build test, and 254/254 examples green.
This commit is contained in:
@@ -477,6 +477,9 @@ pub const Lowering = struct {
|
||||
.union_decl => {
|
||||
_ = type_bridge.resolveAstType(decl, &self.module.types);
|
||||
},
|
||||
.error_set_decl => {
|
||||
self.registerErrorSetDecl(decl);
|
||||
},
|
||||
.protocol_decl => {
|
||||
self.registerProtocolDecl(&decl.data.protocol_decl);
|
||||
},
|
||||
@@ -710,6 +713,9 @@ pub const Lowering = struct {
|
||||
// Register plain union types in the type table
|
||||
_ = type_bridge.resolveAstType(decl, &self.module.types);
|
||||
},
|
||||
.error_set_decl => {
|
||||
self.registerErrorSetDecl(decl);
|
||||
},
|
||||
.protocol_decl => {
|
||||
self.registerProtocolDecl(&decl.data.protocol_decl);
|
||||
},
|
||||
@@ -1486,6 +1492,7 @@ pub const Lowering = struct {
|
||||
.enum_decl, .union_decl => {
|
||||
_ = type_bridge.resolveAstType(node, &self.module.types);
|
||||
},
|
||||
.error_set_decl => self.registerErrorSetDecl(node),
|
||||
.ufcs_alias => |ua| {
|
||||
self.ufcs_alias_map.put(ua.name, ua.target) catch {};
|
||||
},
|
||||
@@ -12063,6 +12070,20 @@ pub const Lowering = struct {
|
||||
// ── Type registration ───────────────────────────────────────────
|
||||
|
||||
/// Register a struct declaration's fields and methods in the IR type table.
|
||||
/// Register a `Foo :: error { A, B }` declaration as an error-set type.
|
||||
/// Rejects an empty set here (sema gate) since type_bridge has no
|
||||
/// diagnostics; non-empty sets are interned via type_bridge.
|
||||
fn registerErrorSetDecl(self: *Lowering, node: *const Node) void {
|
||||
const esd = node.data.error_set_decl;
|
||||
if (esd.tag_names.len == 0) {
|
||||
if (self.diagnostics) |diags| {
|
||||
diags.addFmt(.err, node.span, "error set '{s}' must declare at least one tag", .{esd.name});
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ = type_bridge.resolveAstType(node, &self.module.types);
|
||||
}
|
||||
|
||||
fn registerStructDecl(self: *Lowering, sd: *const ast.StructDecl) void {
|
||||
const table = &self.module.types;
|
||||
const name_id = table.internString(sd.name);
|
||||
|
||||
Reference in New Issue
Block a user