astgen: implement error set declarations
Port errorSetDecl from upstream AstGen.zig:5905-5955. Replaces the SET_ERROR placeholder at the ERROR_SET_DECL case. Loops tokens between lbrace and rbrace, collecting identifier strings into the ErrorSetDecl payload. Also add error_set_decl to the test comparison functions. Tests added: empty error set, error set with members. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
29
astgen.c
29
astgen.c
@@ -3476,11 +3476,32 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
return rvalue(gz, rl,
|
||||
addStrTok(gz, ZIR_INST_ERROR_VALUE, str, error_token), node);
|
||||
}
|
||||
// error_set_decl (AstGen.zig:1131-1140).
|
||||
// error_set_decl (AstGen.zig:5905-5955).
|
||||
case AST_NODE_ERROR_SET_DECL: {
|
||||
// TODO: proper error set, for now just emit a placeholder.
|
||||
SET_ERROR(ag);
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
AstData esd = ag->tree->nodes.datas[node];
|
||||
uint32_t lbrace = esd.lhs;
|
||||
uint32_t rbrace = esd.rhs;
|
||||
// Reserve 1 extra word for ErrorSetDecl.fields_len.
|
||||
ensureExtraCapacity(ag, 1 + (rbrace - lbrace));
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra_len++; // placeholder for fields_len
|
||||
uint32_t fields_len = 0;
|
||||
for (uint32_t tok = lbrace + 1; tok < rbrace; tok++) {
|
||||
TokenizerTag ttag = ag->tree->tokens.tags[tok];
|
||||
if (ttag == TOKEN_DOC_COMMENT || ttag == TOKEN_COMMA)
|
||||
continue;
|
||||
if (ttag == TOKEN_IDENTIFIER) {
|
||||
uint32_t str_index = identAsString(ag, tok);
|
||||
ensureExtraCapacity(ag, 1);
|
||||
ag->extra[ag->extra_len++] = str_index;
|
||||
fields_len++;
|
||||
}
|
||||
}
|
||||
ag->extra[payload_index] = fields_len;
|
||||
return rvalue(gz, rl,
|
||||
addPlNodePayloadIndex(
|
||||
gz, ZIR_INST_ERROR_SET_DECL, node, payload_index),
|
||||
node);
|
||||
}
|
||||
// assign in expr context (AstGen.zig:1011-1014).
|
||||
case AST_NODE_ASSIGN:
|
||||
|
||||
@@ -472,6 +472,7 @@ fn expectEqualData(
|
||||
.array_cat,
|
||||
.array_init,
|
||||
.array_init_ref,
|
||||
.error_set_decl,
|
||||
=> {
|
||||
const r = ref.pl_node;
|
||||
const g = got.pl_node;
|
||||
@@ -780,6 +781,7 @@ fn dataMatches(tag: Zir.Inst.Tag, ref: Zir.Inst.Data, got: c.ZirInstData) bool {
|
||||
.array_cat,
|
||||
.array_init,
|
||||
.array_init_ref,
|
||||
.error_set_decl,
|
||||
=> {
|
||||
return @intFromEnum(ref.pl_node.src_node) == got.pl_node.src_node and
|
||||
ref.pl_node.payload_index == got.pl_node.payload_index;
|
||||
@@ -908,6 +910,30 @@ test "astgen: struct comptime field" {
|
||||
try expectEqualZir(gpa, ref_zir, c_zir);
|
||||
}
|
||||
|
||||
test "astgen: empty error set" {
|
||||
const gpa = std.testing.allocator;
|
||||
const source: [:0]const u8 = "const E = error{};";
|
||||
var ref_zir = try refZir(gpa, source);
|
||||
defer ref_zir.deinit(gpa);
|
||||
var c_ast = c.astParse(source.ptr, @intCast(source.len));
|
||||
defer c.astDeinit(&c_ast);
|
||||
var c_zir = c.astGen(&c_ast);
|
||||
defer c.zirDeinit(&c_zir);
|
||||
try expectEqualZir(gpa, ref_zir, c_zir);
|
||||
}
|
||||
|
||||
test "astgen: error set with members" {
|
||||
const gpa = std.testing.allocator;
|
||||
const source: [:0]const u8 = "const E = error{ OutOfMemory, OutOfTime };";
|
||||
var ref_zir = try refZir(gpa, source);
|
||||
defer ref_zir.deinit(gpa);
|
||||
var c_ast = c.astParse(source.ptr, @intCast(source.len));
|
||||
defer c.astDeinit(&c_ast);
|
||||
var c_zir = c.astGen(&c_ast);
|
||||
defer c.zirDeinit(&c_zir);
|
||||
try expectEqualZir(gpa, ref_zir, c_zir);
|
||||
}
|
||||
|
||||
test "astgen: corpus test_all.zig" {
|
||||
const gpa = std.testing.allocator;
|
||||
try corpusCheck(gpa, "test_all.zig", @embedFile("test_all.zig"));
|
||||
|
||||
Reference in New Issue
Block a user