diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-04-16 22:21:26 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-04-16 22:21:26 -0700 |
| commit | 8cf0ef27790a96e784c368d00338229f205c95d9 (patch) | |
| tree | d706896341cf35842e23a699adcb106eb8f13ffe | |
| parent | 0409d433ba7f84885c782decbe06ec285c02c78c (diff) | |
| download | zig-8cf0ef27790a96e784c368d00338229f205c95d9.tar.gz zig-8cf0ef27790a96e784c368d00338229f205c95d9.zip | |
AstGen: implement simple enums and decls for enums
| -rw-r--r-- | src/AstGen.zig | 125 | ||||
| -rw-r--r-- | src/Zir.zig | 94 |
2 files changed, 162 insertions, 57 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index a66655c723..6b4dfc187b 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2438,12 +2438,11 @@ fn structDeclInner( const decl_inst = try gz.addBlock(tag, node); try gz.instructions.append(gpa, decl_inst); - if (field_index != 0) { + if (block_scope.instructions.items.len != 0) { _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); } - try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + - @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len + block_scope.instructions.items.len + wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) + @@ -2483,6 +2482,7 @@ fn containerDecl( const tree = &astgen.file.tree; const token_tags = tree.tokens.items(.tag); const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); // We must not create any types until Sema. Here the goal is only to generate // ZIR for all the field types, alignments, and default value expressions. @@ -2594,22 +2594,12 @@ fn containerDecl( }, ); } - if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) { - return astgen.failNode(node, "TODO AstGen simple enums", .{}); - } // In this case we must generate ZIR code for the tag values, similar to // how structs are handled above. const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0) .enum_decl else .enum_decl_nonexhaustive; - if (counts.total_fields == 0) { - return gz.addPlNode(tag, node, Zir.Inst.EnumDecl{ - .tag_type = arg_inst, - .fields_len = 0, - .body_len = 0, - }); - } // The enum_decl instruction introduces a scope in which the decls of the enum // are in scope, so that tag values can refer to decls within the enum itself. @@ -2621,6 +2611,9 @@ fn containerDecl( }; defer block_scope.instructions.deinit(gpa); + var wip_decls: WipDecls = .{}; + defer wip_decls.deinit(gpa); + var fields_data = ArrayListUnmanaged(u32){}; defer fields_data.deinit(gpa); @@ -2639,7 +2632,81 @@ fn containerDecl( .container_field_init => tree.containerFieldInit(member_node), .container_field_align => tree.containerFieldAlign(member_node), .container_field => tree.containerField(member_node), - else => continue, + + .fn_decl => { + const fn_proto = node_datas[member_node].lhs; + const body = node_datas[member_node].rhs; + switch (node_tags[fn_proto]) { + .fn_proto_simple => { + var params: [1]ast.Node.Index = undefined; + try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoSimple(¶ms, fn_proto)); + continue; + }, + .fn_proto_multi => { + try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoMulti(fn_proto)); + continue; + }, + .fn_proto_one => { + var params: [1]ast.Node.Index = undefined; + try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoOne(¶ms, fn_proto)); + continue; + }, + .fn_proto => { + try astgen.fnDecl(gz, &wip_decls, body, tree.fnProto(fn_proto)); + continue; + }, + else => unreachable, + } + }, + .fn_proto_simple => { + var params: [1]ast.Node.Index = undefined; + try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoSimple(¶ms, member_node)); + continue; + }, + .fn_proto_multi => { + try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoMulti(member_node)); + continue; + }, + .fn_proto_one => { + var params: [1]ast.Node.Index = undefined; + try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoOne(¶ms, member_node)); + continue; + }, + .fn_proto => { + try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProto(member_node)); + continue; + }, + + .global_var_decl => { + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node)); + continue; + }, + .local_var_decl => { + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node)); + continue; + }, + .simple_var_decl => { + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node)); + continue; + }, + .aligned_var_decl => { + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node)); + continue; + }, + + .@"comptime" => { + try astgen.comptimeDecl(gz, scope, member_node); + continue; + }, + .@"usingnamespace" => { + try astgen.usingnamespaceDecl(gz, scope, member_node); + continue; + }, + .test_decl => { + try astgen.testDecl(gz, scope, member_node); + continue; + }, + else => unreachable, }; if (field_index % 32 == 0 and field_index != 0) { try bit_bag.append(gpa, cur_bit_bag); @@ -2663,27 +2730,45 @@ fn containerDecl( field_index += 1; } - const empty_slot_count = 32 - (field_index % 32); - cur_bit_bag >>= @intCast(u5, empty_slot_count); + { + const empty_slot_count = 32 - (field_index % 32); + cur_bit_bag >>= @intCast(u5, empty_slot_count); + } + + if (wip_decls.decl_index != 0) { + const empty_slot_count = 16 - (wip_decls.decl_index % 16); + wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2); + } const decl_inst = try gz.addBlock(tag, node); try gz.instructions.append(gpa, decl_inst); - _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); + if (block_scope.instructions.items.len != 0) { + _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); + } - try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + - @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + bit_bag.items.len + 1 + fields_data.items.len + - block_scope.instructions.items.len); + block_scope.instructions.items.len + + wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) + + wip_decls.name_and_value.items.len); const zir_datas = astgen.instructions.items(.data); zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ .tag_type = arg_inst, .body_len = @intCast(u32, block_scope.instructions.items.len), .fields_len = @intCast(u32, field_index), + .decls_len = @intCast(u32, wip_decls.decl_index), }); astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. astgen.extra.appendAssumeCapacity(cur_bit_bag); astgen.extra.appendSliceAssumeCapacity(fields_data.items); + + astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. + if (wip_decls.decl_index != 0) { + astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); + } + astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items); + return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node); }, .keyword_opaque => { diff --git a/src/Zir.zig b/src/Zir.zig index 423add0ab9..066be22be0 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -1591,11 +1591,20 @@ pub const Inst = struct { /// field_name: u32, /// value: Ref, // if corresponding bit is set /// } + /// 3. decl_bits: u32 // for every 16 decls + /// - sets of 2 bits: + /// 0b0X: whether corresponding decl is pub + /// 0bX0: whether corresponding decl is exported + /// 4. decl: { // for every decls_len + /// name: u32, // null terminated string index + /// value: Index, + /// } pub const EnumDecl = struct { /// Can be `Ref.none`. tag_type: Ref, body_len: u32, fields_len: u32, + decls_len: u32, }; /// Trailing: @@ -2231,6 +2240,7 @@ const Writer = struct { const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index); const body = self.code.extra[extra.end..][0..extra.data.body_len]; const fields_len = extra.data.fields_len; + const decls_len = extra.data.decls_len; const tag_ty_ref = extra.data.tag_type; if (tag_ty_ref != .none) { @@ -2238,53 +2248,63 @@ const Writer = struct { try stream.writeAll(", "); } + var extra_index: usize = undefined; + if (fields_len == 0) { assert(body.len == 0); - try stream.writeAll("{}, {}) "); - try self.writeSrc(stream, inst_data.src()); - return; - } - - try stream.writeAll("{\n"); - self.indent += 2; - try self.writeBody(stream, body); + try stream.writeAll("{}, {}, {"); + extra_index = extra.end; + } else { + try stream.writeAll("{\n"); + self.indent += 2; + try self.writeBody(stream, body); - try stream.writeByteNTimes(' ', self.indent - 2); - try stream.writeAll("}, {\n"); + try stream.writeByteNTimes(' ', self.indent - 2); + try stream.writeAll("}, {\n"); - const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; - const body_end = extra.end + body.len; - var extra_index: usize = body_end + bit_bags_count; - var bit_bag_index: usize = body_end; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % 32 == 0) { - cur_bit_bag = self.code.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_tag_value = @truncate(u1, cur_bit_bag) != 0; - cur_bit_bag >>= 1; + const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; + const body_end = extra.end + body.len; + extra_index = body_end + bit_bags_count; + var bit_bag_index: usize = body_end; + var cur_bit_bag: u32 = undefined; + var field_i: u32 = 0; + while (field_i < fields_len) : (field_i += 1) { + if (field_i % 32 == 0) { + cur_bit_bag = self.code.extra[bit_bag_index]; + bit_bag_index += 1; + } + const has_tag_value = @truncate(u1, cur_bit_bag) != 0; + cur_bit_bag >>= 1; - const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]); - extra_index += 1; + const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]); + extra_index += 1; - try stream.writeByteNTimes(' ', self.indent); - try stream.print("{}", .{std.zig.fmtId(field_name)}); + try stream.writeByteNTimes(' ', self.indent); + try stream.print("{}", .{std.zig.fmtId(field_name)}); - if (has_tag_value) { - const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]); - extra_index += 1; + if (has_tag_value) { + const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]); + extra_index += 1; - try stream.writeAll(" = "); - try self.writeInstRef(stream, tag_value_ref); + try stream.writeAll(" = "); + try self.writeInstRef(stream, tag_value_ref); + } + try stream.writeAll(",\n"); } - try stream.writeAll(",\n"); + self.indent -= 2; + try stream.writeByteNTimes(' ', self.indent); + try stream.writeAll("}, {"); + } + if (decls_len == 0) { + try stream.writeAll("}) "); + } else { + try stream.writeAll("\n"); + self.indent += 2; + try self.writeDecls(stream, decls_len, extra_index); + self.indent -= 2; + try stream.writeByteNTimes(' ', self.indent); + try stream.writeAll("}) "); } - - self.indent -= 2; - try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("}) "); try self.writeSrc(stream, inst_data.src()); } |
