AstGen: implement error set decls
This commit is contained in:
84
BRANCH_TODO
84
BRANCH_TODO
@@ -604,73 +604,6 @@ fn astgenAndSemaVarDecl(
|
||||
}
|
||||
|
||||
|
||||
fn errorSetDecl(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
node: ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const tree = &astgen.file.tree;
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
// Count how many fields there are.
|
||||
const error_token = main_tokens[node];
|
||||
const count: usize = count: {
|
||||
var tok_i = error_token + 2;
|
||||
var count: usize = 0;
|
||||
while (true) : (tok_i += 1) {
|
||||
switch (token_tags[tok_i]) {
|
||||
.doc_comment, .comma => {},
|
||||
.identifier => count += 1,
|
||||
.r_brace => break :count count,
|
||||
else => unreachable,
|
||||
}
|
||||
} else unreachable; // TODO should not need else unreachable here
|
||||
};
|
||||
|
||||
const gpa = astgen.gpa;
|
||||
var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
|
||||
errdefer new_decl_arena.deinit();
|
||||
const arena = &new_decl_arena.allocator;
|
||||
|
||||
const fields = try arena.alloc([]const u8, count);
|
||||
{
|
||||
var tok_i = error_token + 2;
|
||||
var field_i: usize = 0;
|
||||
while (true) : (tok_i += 1) {
|
||||
switch (token_tags[tok_i]) {
|
||||
.doc_comment, .comma => {},
|
||||
.identifier => {
|
||||
fields[field_i] = try astgen.identifierTokenStringTreeArena(tok_i, tree, arena);
|
||||
field_i += 1;
|
||||
},
|
||||
.r_brace => break,
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
const error_set = try arena.create(Module.ErrorSet);
|
||||
error_set.* = .{
|
||||
.owner_decl = astgen.decl,
|
||||
.node_offset = astgen.decl.nodeIndexToRelative(node),
|
||||
.names_ptr = fields.ptr,
|
||||
.names_len = @intCast(u32, fields.len),
|
||||
};
|
||||
const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
|
||||
const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
|
||||
const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = error_set_val,
|
||||
});
|
||||
const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
|
||||
const result = try gz.addDecl(.decl_val, decl_index, node);
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (mod.lookupIdentifier(scope, ident_name)) |decl| {
|
||||
const msg = msg: {
|
||||
const msg = try mod.errMsg(
|
||||
@@ -761,3 +694,20 @@ fn errorSetDecl(
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const error_set = try arena.create(Module.ErrorSet);
|
||||
error_set.* = .{
|
||||
.owner_decl = astgen.decl,
|
||||
.node_offset = astgen.decl.nodeIndexToRelative(node),
|
||||
.names_ptr = fields.ptr,
|
||||
.names_len = @intCast(u32, fields.len),
|
||||
};
|
||||
const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
|
||||
const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
|
||||
const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = error_set_val,
|
||||
});
|
||||
const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
|
||||
const result = try gz.addDecl(.decl_val, decl_index, node);
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
|
||||
@@ -1463,6 +1463,7 @@ fn blockExprStmts(
|
||||
.enum_decl,
|
||||
.enum_decl_nonexhaustive,
|
||||
.opaque_decl,
|
||||
.error_set_decl,
|
||||
.int_to_enum,
|
||||
.enum_to_int,
|
||||
.type_info,
|
||||
@@ -2930,11 +2931,37 @@ fn errorSetDecl(
|
||||
node: ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
const tree = &astgen.file.tree;
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
return astgen.failNode(node, "TODO AstGen errorSetDecl", .{});
|
||||
var field_names: std.ArrayListUnmanaged(u32) = .{};
|
||||
defer field_names.deinit(gpa);
|
||||
|
||||
{
|
||||
const error_token = main_tokens[node];
|
||||
var tok_i = error_token + 2;
|
||||
var field_i: usize = 0;
|
||||
while (true) : (tok_i += 1) {
|
||||
switch (token_tags[tok_i]) {
|
||||
.doc_comment, .comma => {},
|
||||
.identifier => {
|
||||
const str_index = try gz.identAsString(tok_i);
|
||||
try field_names.append(gpa, str_index);
|
||||
field_i += 1;
|
||||
},
|
||||
.r_brace => break,
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{
|
||||
.fields_len = @intCast(u32, field_names.items.len),
|
||||
});
|
||||
try astgen.extra.appendSlice(gpa, field_names.items);
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
}
|
||||
|
||||
fn orelseCatchExpr(
|
||||
|
||||
12
src/Sema.zig
12
src/Sema.zig
@@ -343,6 +343,7 @@ pub fn analyzeBody(
|
||||
.enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),
|
||||
.union_decl => try sema.zirUnionDecl(block, inst),
|
||||
.opaque_decl => try sema.zirOpaqueDecl(block, inst),
|
||||
.error_set_decl => try sema.zirErrorSetDecl(block, inst),
|
||||
|
||||
.add => try sema.zirArithmetic(block, inst),
|
||||
.addwrap => try sema.zirArithmetic(block, inst),
|
||||
@@ -978,6 +979,17 @@ fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
|
||||
return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});
|
||||
}
|
||||
|
||||
fn zirErrorSetDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
|
||||
|
||||
return sema.mod.fail(&block.base, sema.src, "TODO implement zirErrorSetDecl", .{});
|
||||
}
|
||||
|
||||
fn zirRetPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
36
src/Zir.zig
36
src/Zir.zig
@@ -307,6 +307,9 @@ pub const Inst = struct {
|
||||
/// An opaque type definition. Provides an AST node only.
|
||||
/// Uses the `node` union field.
|
||||
opaque_decl,
|
||||
/// An error set type definition. Contains a list of field names.
|
||||
/// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
|
||||
error_set_decl,
|
||||
/// Declares the beginning of a statement. Used for debug info.
|
||||
/// Uses the `node` union field.
|
||||
dbg_stmt_node,
|
||||
@@ -986,6 +989,7 @@ pub const Inst = struct {
|
||||
.enum_decl,
|
||||
.enum_decl_nonexhaustive,
|
||||
.opaque_decl,
|
||||
.error_set_decl,
|
||||
.dbg_stmt_node,
|
||||
.decl_ref,
|
||||
.decl_val,
|
||||
@@ -2011,6 +2015,11 @@ pub const Inst = struct {
|
||||
fields_len: u32,
|
||||
};
|
||||
|
||||
/// Trailing: field_name: u32 // for every field: null terminated string index
|
||||
pub const ErrorSetDecl = struct {
|
||||
fields_len: u32,
|
||||
};
|
||||
|
||||
/// A f128 value, broken up into 4 u32 parts.
|
||||
pub const Float128 = struct {
|
||||
piece0: u32,
|
||||
@@ -2328,6 +2337,8 @@ const Writer = struct {
|
||||
.builtin_async_call,
|
||||
=> try self.writePlNode(stream, inst),
|
||||
|
||||
.error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst),
|
||||
|
||||
.add_with_overflow,
|
||||
.sub_with_overflow,
|
||||
.mul_with_overflow,
|
||||
@@ -2596,11 +2607,7 @@ const Writer = struct {
|
||||
try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
|
||||
}
|
||||
|
||||
fn writePlNode(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
inst: Inst.Index,
|
||||
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
|
||||
fn writePlNode(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
try stream.writeAll("TODO) ");
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
@@ -2616,6 +2623,25 @@ const Writer = struct {
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writePlNodeErrorSetDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = self.code.extraData(Inst.ErrorSetDecl, inst_data.payload_index);
|
||||
const fields = self.code.extra[extra.end..][0..extra.data.fields_len];
|
||||
|
||||
try stream.writeAll("{\n");
|
||||
self.indent += 2;
|
||||
for (fields) |str_index| {
|
||||
const name = self.code.nullTerminatedString(str_index);
|
||||
try stream.writeByteNTimes(' ', self.indent);
|
||||
try stream.print("{},\n", .{std.zig.fmtId(name)});
|
||||
}
|
||||
self.indent -= 2;
|
||||
try stream.writeByteNTimes(' ', self.indent);
|
||||
try stream.writeAll("}) ");
|
||||
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writePlNodeOverflowArithmetic(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = self.code.extraData(Inst.OverflowArithmetic, inst_data.payload_index).data;
|
||||
|
||||
Reference in New Issue
Block a user