authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-16 22:21:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-16 22:21:26-07:00
log8cf0ef27790a96e784c368d00338229f205c95d9
treed706896341cf35842e23a699adcb106eb8f13ffe
parent0409d433ba7f84885c782decbe06ec285c02c78c

AstGen: implement simple enums and decls for enums


2 files changed, 162 insertions(+), 57 deletions(-)

src/AstGen.zig+105-20
......@@ -2438,12 +2438,11 @@ fn structDeclInner(
24382438
24392439 const decl_inst = try gz.addBlock(tag, node);
24402440 try gz.instructions.append(gpa, decl_inst);
2441 if (field_index != 0) {
2441 if (block_scope.instructions.items.len != 0) {
24422442 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
24432443 }
24442444
2445 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
2446 @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
2445 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
24472446 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +
24482447 block_scope.instructions.items.len +
24492448 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
......@@ -2483,6 +2482,7 @@ fn containerDecl(
24832482 const tree = &astgen.file.tree;
24842483 const token_tags = tree.tokens.items(.tag);
24852484 const node_tags = tree.nodes.items(.tag);
2485 const node_datas = tree.nodes.items(.data);
24862486
24872487 // We must not create any types until Sema. Here the goal is only to generate
24882488 // ZIR for all the field types, alignments, and default value expressions.
......@@ -2594,22 +2594,12 @@ fn containerDecl(
25942594 },
25952595 );
25962596 }
2597 if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) {
2598 return astgen.failNode(node, "TODO AstGen simple enums", .{});
2599 }
26002597 // In this case we must generate ZIR code for the tag values, similar to
26012598 // how structs are handled above.
26022599 const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0)
26032600 .enum_decl
26042601 else
26052602 .enum_decl_nonexhaustive;
2606 if (counts.total_fields == 0) {
2607 return gz.addPlNode(tag, node, Zir.Inst.EnumDecl{
2608 .tag_type = arg_inst,
2609 .fields_len = 0,
2610 .body_len = 0,
2611 });
2612 }
26132603
26142604 // The enum_decl instruction introduces a scope in which the decls of the enum
26152605 // are in scope, so that tag values can refer to decls within the enum itself.
......@@ -2621,6 +2611,9 @@ fn containerDecl(
26212611 };
26222612 defer block_scope.instructions.deinit(gpa);
26232613
2614 var wip_decls: WipDecls = .{};
2615 defer wip_decls.deinit(gpa);
2616
26242617 var fields_data = ArrayListUnmanaged(u32){};
26252618 defer fields_data.deinit(gpa);
26262619
......@@ -2639,7 +2632,81 @@ fn containerDecl(
26392632 .container_field_init => tree.containerFieldInit(member_node),
26402633 .container_field_align => tree.containerFieldAlign(member_node),
26412634 .container_field => tree.containerField(member_node),
2642 else => continue,
2635
2636 .fn_decl => {
2637 const fn_proto = node_datas[member_node].lhs;
2638 const body = node_datas[member_node].rhs;
2639 switch (node_tags[fn_proto]) {
2640 .fn_proto_simple => {
2641 var params: [1]ast.Node.Index = undefined;
2642 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoSimple(&params, fn_proto));
2643 continue;
2644 },
2645 .fn_proto_multi => {
2646 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoMulti(fn_proto));
2647 continue;
2648 },
2649 .fn_proto_one => {
2650 var params: [1]ast.Node.Index = undefined;
2651 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoOne(&params, fn_proto));
2652 continue;
2653 },
2654 .fn_proto => {
2655 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProto(fn_proto));
2656 continue;
2657 },
2658 else => unreachable,
2659 }
2660 },
2661 .fn_proto_simple => {
2662 var params: [1]ast.Node.Index = undefined;
2663 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoSimple(&params, member_node));
2664 continue;
2665 },
2666 .fn_proto_multi => {
2667 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoMulti(member_node));
2668 continue;
2669 },
2670 .fn_proto_one => {
2671 var params: [1]ast.Node.Index = undefined;
2672 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoOne(&params, member_node));
2673 continue;
2674 },
2675 .fn_proto => {
2676 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProto(member_node));
2677 continue;
2678 },
2679
2680 .global_var_decl => {
2681 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
2682 continue;
2683 },
2684 .local_var_decl => {
2685 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
2686 continue;
2687 },
2688 .simple_var_decl => {
2689 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
2690 continue;
2691 },
2692 .aligned_var_decl => {
2693 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
2694 continue;
2695 },
2696
2697 .@"comptime" => {
2698 try astgen.comptimeDecl(gz, scope, member_node);
2699 continue;
2700 },
2701 .@"usingnamespace" => {
2702 try astgen.usingnamespaceDecl(gz, scope, member_node);
2703 continue;
2704 },
2705 .test_decl => {
2706 try astgen.testDecl(gz, scope, member_node);
2707 continue;
2708 },
2709 else => unreachable,
26432710 };
26442711 if (field_index % 32 == 0 and field_index != 0) {
26452712 try bit_bag.append(gpa, cur_bit_bag);
......@@ -2663,27 +2730,45 @@ fn containerDecl(
26632730
26642731 field_index += 1;
26652732 }
2666 const empty_slot_count = 32 - (field_index % 32);
2667 cur_bit_bag >>= @intCast(u5, empty_slot_count);
2733 {
2734 const empty_slot_count = 32 - (field_index % 32);
2735 cur_bit_bag >>= @intCast(u5, empty_slot_count);
2736 }
2737
2738 if (wip_decls.decl_index != 0) {
2739 const empty_slot_count = 16 - (wip_decls.decl_index % 16);
2740 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
2741 }
26682742
26692743 const decl_inst = try gz.addBlock(tag, node);
26702744 try gz.instructions.append(gpa, decl_inst);
2671 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
2745 if (block_scope.instructions.items.len != 0) {
2746 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
2747 }
26722748
2673 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
2674 @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
2749 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
26752750 bit_bag.items.len + 1 + fields_data.items.len +
2676 block_scope.instructions.items.len);
2751 block_scope.instructions.items.len +
2752 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
2753 wip_decls.name_and_value.items.len);
26772754 const zir_datas = astgen.instructions.items(.data);
26782755 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
26792756 .tag_type = arg_inst,
26802757 .body_len = @intCast(u32, block_scope.instructions.items.len),
26812758 .fields_len = @intCast(u32, field_index),
2759 .decls_len = @intCast(u32, wip_decls.decl_index),
26822760 });
26832761 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
26842762 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
26852763 astgen.extra.appendAssumeCapacity(cur_bit_bag);
26862764 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
2765
2766 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
2767 if (wip_decls.decl_index != 0) {
2768 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
2769 }
2770 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);
2771
26872772 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
26882773 },
26892774 .keyword_opaque => {
src/Zir.zig+57-37
......@@ -1591,11 +1591,20 @@ pub const Inst = struct {
15911591 /// field_name: u32,
15921592 /// value: Ref, // if corresponding bit is set
15931593 /// }
1594 /// 3. decl_bits: u32 // for every 16 decls
1595 /// - sets of 2 bits:
1596 /// 0b0X: whether corresponding decl is pub
1597 /// 0bX0: whether corresponding decl is exported
1598 /// 4. decl: { // for every decls_len
1599 /// name: u32, // null terminated string index
1600 /// value: Index,
1601 /// }
15941602 pub const EnumDecl = struct {
15951603 /// Can be `Ref.none`.
15961604 tag_type: Ref,
15971605 body_len: u32,
15981606 fields_len: u32,
1607 decls_len: u32,
15991608 };
16001609
16011610 /// Trailing:
......@@ -2231,6 +2240,7 @@ const Writer = struct {
22312240 const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index);
22322241 const body = self.code.extra[extra.end..][0..extra.data.body_len];
22332242 const fields_len = extra.data.fields_len;
2243 const decls_len = extra.data.decls_len;
22342244 const tag_ty_ref = extra.data.tag_type;
22352245
22362246 if (tag_ty_ref != .none) {
......@@ -2238,53 +2248,63 @@ const Writer = struct {
22382248 try stream.writeAll(", ");
22392249 }
22402250
2251 var extra_index: usize = undefined;
2252
22412253 if (fields_len == 0) {
22422254 assert(body.len == 0);
2243 try stream.writeAll("{}, {}) ");
2244 try self.writeSrc(stream, inst_data.src());
2245 return;
2246 }
2247
2248 try stream.writeAll("{\n");
2249 self.indent += 2;
2250 try self.writeBody(stream, body);
2255 try stream.writeAll("{}, {}, {");
2256 extra_index = extra.end;
2257 } else {
2258 try stream.writeAll("{\n");
2259 self.indent += 2;
2260 try self.writeBody(stream, body);
22512261
2252 try stream.writeByteNTimes(' ', self.indent - 2);
2253 try stream.writeAll("}, {\n");
2262 try stream.writeByteNTimes(' ', self.indent - 2);
2263 try stream.writeAll("}, {\n");
22542264
2255 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
2256 const body_end = extra.end + body.len;
2257 var extra_index: usize = body_end + bit_bags_count;
2258 var bit_bag_index: usize = body_end;
2259 var cur_bit_bag: u32 = undefined;
2260 var field_i: u32 = 0;
2261 while (field_i < fields_len) : (field_i += 1) {
2262 if (field_i % 32 == 0) {
2263 cur_bit_bag = self.code.extra[bit_bag_index];
2264 bit_bag_index += 1;
2265 }
2266 const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
2267 cur_bit_bag >>= 1;
2265 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
2266 const body_end = extra.end + body.len;
2267 extra_index = body_end + bit_bags_count;
2268 var bit_bag_index: usize = body_end;
2269 var cur_bit_bag: u32 = undefined;
2270 var field_i: u32 = 0;
2271 while (field_i < fields_len) : (field_i += 1) {
2272 if (field_i % 32 == 0) {
2273 cur_bit_bag = self.code.extra[bit_bag_index];
2274 bit_bag_index += 1;
2275 }
2276 const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
2277 cur_bit_bag >>= 1;
22682278
2269 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
2270 extra_index += 1;
2279 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
2280 extra_index += 1;
22712281
2272 try stream.writeByteNTimes(' ', self.indent);
2273 try stream.print("{}", .{std.zig.fmtId(field_name)});
2282 try stream.writeByteNTimes(' ', self.indent);
2283 try stream.print("{}", .{std.zig.fmtId(field_name)});
22742284
2275 if (has_tag_value) {
2276 const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2277 extra_index += 1;
2285 if (has_tag_value) {
2286 const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2287 extra_index += 1;
22782288
2279 try stream.writeAll(" = ");
2280 try self.writeInstRef(stream, tag_value_ref);
2289 try stream.writeAll(" = ");
2290 try self.writeInstRef(stream, tag_value_ref);
2291 }
2292 try stream.writeAll(",\n");
22812293 }
2282 try stream.writeAll(",\n");
2294 self.indent -= 2;
2295 try stream.writeByteNTimes(' ', self.indent);
2296 try stream.writeAll("}, {");
2297 }
2298 if (decls_len == 0) {
2299 try stream.writeAll("}) ");
2300 } else {
2301 try stream.writeAll("\n");
2302 self.indent += 2;
2303 try self.writeDecls(stream, decls_len, extra_index);
2304 self.indent -= 2;
2305 try stream.writeByteNTimes(' ', self.indent);
2306 try stream.writeAll("}) ");
22832307 }
2284
2285 self.indent -= 2;
2286 try stream.writeByteNTimes(' ', self.indent);
2287 try stream.writeAll("}) ");
22882308 try self.writeSrc(stream, inst_data.src());
22892309 }
22902310