authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-19 16:03:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-19 16:03:46-07:00
log7f931a75229b4d6b9d07a7485bfc1726a92fc591
tree43204015dc5eee275711d33238d3d40f41815bc1
parent2083208f19a4eb7caa1953980f9a2f2496115695

AstGen: implement error set decls


4 files changed, 88 insertions(+), 73 deletions(-)

BRANCH_TODO+17-67
......@@ -604,73 +604,6 @@ fn astgenAndSemaVarDecl(
604604 }
605605
606606
607fn errorSetDecl(
608 gz: *GenZir,
609 scope: *Scope,
610 rl: ResultLoc,
611 node: ast.Node.Index,
612) InnerError!Zir.Inst.Ref {
613 const astgen = gz.astgen;
614 const tree = &astgen.file.tree;
615 const main_tokens = tree.nodes.items(.main_token);
616 const token_tags = tree.tokens.items(.tag);
617
618 // Count how many fields there are.
619 const error_token = main_tokens[node];
620 const count: usize = count: {
621 var tok_i = error_token + 2;
622 var count: usize = 0;
623 while (true) : (tok_i += 1) {
624 switch (token_tags[tok_i]) {
625 .doc_comment, .comma => {},
626 .identifier => count += 1,
627 .r_brace => break :count count,
628 else => unreachable,
629 }
630 } else unreachable; // TODO should not need else unreachable here
631 };
632
633 const gpa = astgen.gpa;
634 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
635 errdefer new_decl_arena.deinit();
636 const arena = &new_decl_arena.allocator;
637
638 const fields = try arena.alloc([]const u8, count);
639 {
640 var tok_i = error_token + 2;
641 var field_i: usize = 0;
642 while (true) : (tok_i += 1) {
643 switch (token_tags[tok_i]) {
644 .doc_comment, .comma => {},
645 .identifier => {
646 fields[field_i] = try astgen.identifierTokenStringTreeArena(tok_i, tree, arena);
647 field_i += 1;
648 },
649 .r_brace => break,
650 else => unreachable,
651 }
652 }
653 }
654 const error_set = try arena.create(Module.ErrorSet);
655 error_set.* = .{
656 .owner_decl = astgen.decl,
657 .node_offset = astgen.decl.nodeIndexToRelative(node),
658 .names_ptr = fields.ptr,
659 .names_len = @intCast(u32, fields.len),
660 };
661 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
662 const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
663 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
664 .ty = Type.initTag(.type),
665 .val = error_set_val,
666 });
667 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
668 const result = try gz.addDecl(.decl_val, decl_index, node);
669 return rvalue(gz, scope, rl, result, node);
670}
671
672
673
674607 if (mod.lookupIdentifier(scope, ident_name)) |decl| {
675608 const msg = msg: {
676609 const msg = try mod.errMsg(
......@@ -761,3 +694,20 @@ fn errorSetDecl(
761694 );
762695 }
763696
697
698 const error_set = try arena.create(Module.ErrorSet);
699 error_set.* = .{
700 .owner_decl = astgen.decl,
701 .node_offset = astgen.decl.nodeIndexToRelative(node),
702 .names_ptr = fields.ptr,
703 .names_len = @intCast(u32, fields.len),
704 };
705 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
706 const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
707 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
708 .ty = Type.initTag(.type),
709 .val = error_set_val,
710 });
711 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
712 const result = try gz.addDecl(.decl_val, decl_index, node);
713 return rvalue(gz, scope, rl, result, node);
src/AstGen.zig+28-1
......@@ -1463,6 +1463,7 @@ fn blockExprStmts(
14631463 .enum_decl,
14641464 .enum_decl_nonexhaustive,
14651465 .opaque_decl,
1466 .error_set_decl,
14661467 .int_to_enum,
14671468 .enum_to_int,
14681469 .type_info,
......@@ -2930,11 +2931,37 @@ fn errorSetDecl(
29302931 node: ast.Node.Index,
29312932) InnerError!Zir.Inst.Ref {
29322933 const astgen = gz.astgen;
2934 const gpa = astgen.gpa;
29332935 const tree = &astgen.file.tree;
29342936 const main_tokens = tree.nodes.items(.main_token);
29352937 const token_tags = tree.tokens.items(.tag);
29362938
2937 return astgen.failNode(node, "TODO AstGen errorSetDecl", .{});
2939 var field_names: std.ArrayListUnmanaged(u32) = .{};
2940 defer field_names.deinit(gpa);
2941
2942 {
2943 const error_token = main_tokens[node];
2944 var tok_i = error_token + 2;
2945 var field_i: usize = 0;
2946 while (true) : (tok_i += 1) {
2947 switch (token_tags[tok_i]) {
2948 .doc_comment, .comma => {},
2949 .identifier => {
2950 const str_index = try gz.identAsString(tok_i);
2951 try field_names.append(gpa, str_index);
2952 field_i += 1;
2953 },
2954 .r_brace => break,
2955 else => unreachable,
2956 }
2957 }
2958 }
2959
2960 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{
2961 .fields_len = @intCast(u32, field_names.items.len),
2962 });
2963 try astgen.extra.appendSlice(gpa, field_names.items);
2964 return rvalue(gz, scope, rl, result, node);
29382965}
29392966
29402967fn orelseCatchExpr(
src/Sema.zig+12
......@@ -343,6 +343,7 @@ pub fn analyzeBody(
343343 .enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),
344344 .union_decl => try sema.zirUnionDecl(block, inst),
345345 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
346 .error_set_decl => try sema.zirErrorSetDecl(block, inst),
346347
347348 .add => try sema.zirArithmetic(block, inst),
348349 .addwrap => try sema.zirArithmetic(block, inst),
......@@ -978,6 +979,17 @@ fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
978979 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});
979980}
980981
982fn zirErrorSetDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
983 const tracy = trace(@src());
984 defer tracy.end();
985
986 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
987 const src = inst_data.src();
988 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
989
990 return sema.mod.fail(&block.base, sema.src, "TODO implement zirErrorSetDecl", .{});
991}
992
981993fn zirRetPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
982994 const tracy = trace(@src());
983995 defer tracy.end();
src/Zir.zig+31-5
......@@ -307,6 +307,9 @@ pub const Inst = struct {
307307 /// An opaque type definition. Provides an AST node only.
308308 /// Uses the `node` union field.
309309 opaque_decl,
310 /// An error set type definition. Contains a list of field names.
311 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
312 error_set_decl,
310313 /// Declares the beginning of a statement. Used for debug info.
311314 /// Uses the `node` union field.
312315 dbg_stmt_node,
......@@ -986,6 +989,7 @@ pub const Inst = struct {
986989 .enum_decl,
987990 .enum_decl_nonexhaustive,
988991 .opaque_decl,
992 .error_set_decl,
989993 .dbg_stmt_node,
990994 .decl_ref,
991995 .decl_val,
......@@ -2011,6 +2015,11 @@ pub const Inst = struct {
20112015 fields_len: u32,
20122016 };
20132017
2018 /// Trailing: field_name: u32 // for every field: null terminated string index
2019 pub const ErrorSetDecl = struct {
2020 fields_len: u32,
2021 };
2022
20142023 /// A f128 value, broken up into 4 u32 parts.
20152024 pub const Float128 = struct {
20162025 piece0: u32,
......@@ -2328,6 +2337,8 @@ const Writer = struct {
23282337 .builtin_async_call,
23292338 => try self.writePlNode(stream, inst),
23302339
2340 .error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst),
2341
23312342 .add_with_overflow,
23322343 .sub_with_overflow,
23332344 .mul_with_overflow,
......@@ -2596,11 +2607,7 @@ const Writer = struct {
25962607 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
25972608 }
25982609
2599 fn writePlNode(
2600 self: *Writer,
2601 stream: anytype,
2602 inst: Inst.Index,
2603 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2610 fn writePlNode(self: *Writer, stream: anytype, inst: Inst.Index) !void {
26042611 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
26052612 try stream.writeAll("TODO) ");
26062613 try self.writeSrc(stream, inst_data.src());
......@@ -2616,6 +2623,25 @@ const Writer = struct {
26162623 try self.writeSrc(stream, inst_data.src());
26172624 }
26182625
2626 fn writePlNodeErrorSetDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2627 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2628 const extra = self.code.extraData(Inst.ErrorSetDecl, inst_data.payload_index);
2629 const fields = self.code.extra[extra.end..][0..extra.data.fields_len];
2630
2631 try stream.writeAll("{\n");
2632 self.indent += 2;
2633 for (fields) |str_index| {
2634 const name = self.code.nullTerminatedString(str_index);
2635 try stream.writeByteNTimes(' ', self.indent);
2636 try stream.print("{},\n", .{std.zig.fmtId(name)});
2637 }
2638 self.indent -= 2;
2639 try stream.writeByteNTimes(' ', self.indent);
2640 try stream.writeAll("}) ");
2641
2642 try self.writeSrc(stream, inst_data.src());
2643 }
2644
26192645 fn writePlNodeOverflowArithmetic(self: *Writer, stream: anytype, inst: Inst.Index) !void {
26202646 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
26212647 const extra = self.code.extraData(Inst.OverflowArithmetic, inst_data.payload_index).data;