autodocs: output data support for more types

This commit is contained in:
Loris Cro
2022-02-08 07:44:16 +01:00
committed by Andrew Kelley
parent ef5a2e8d6f
commit 5a31126d89

View File

@@ -47,8 +47,6 @@ pub fn generateZirData(self: *Autodoc) !void {
defer self.arena.free(abs_root_path);
const zir = self.module.import_table.get(abs_root_path).?.zir;
// var decl_map = std.AutoHashMap(Zir.Inst.Index, usize); // values are positions in the `decls` array
// append all the types in Zir.Inst.Ref
{
@@ -57,14 +55,16 @@ pub fn generateZirData(self: *Autodoc) !void {
while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) {
var tmpbuf = std.ArrayList(u8).init(self.arena);
try Ref.typed_value_map[i].val.format("", .{}, tmpbuf.writer());
try self.types.append(self.arena, .{
.name = tmpbuf.toOwnedSlice(),
.kind = switch (@intToEnum(Ref, i)) {
try self.types.append(
self.arena,
switch (@intToEnum(Ref, i)) {
else => blk: {
//std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{
// @tagName(t),
//});
break :blk 7;
break :blk .{
.Array = .{ .name = tmpbuf.toOwnedSlice() },
};
},
.u1_type,
.u8_type,
@@ -88,19 +88,35 @@ pub fn generateZirData(self: *Autodoc) !void {
.c_longlong_type,
.c_ulonglong_type,
.c_longdouble_type,
=> @enumToInt(std.builtin.TypeId.Int),
=> .{
.Int = .{ .name = tmpbuf.toOwnedSlice() },
},
.f16_type,
.f32_type,
.f64_type,
.f128_type,
=> @enumToInt(std.builtin.TypeId.Float),
.comptime_int_type => @enumToInt(std.builtin.TypeId.ComptimeInt),
.comptime_float_type => @enumToInt(std.builtin.TypeId.ComptimeFloat),
.bool_type => @enumToInt(std.builtin.TypeId.Bool),
.void_type => @enumToInt(std.builtin.TypeId.Void),
.type_type => @enumToInt(std.builtin.TypeId.Type),
=> .{
.Float = .{ .name = tmpbuf.toOwnedSlice() },
},
.comptime_int_type => .{
.ComptimeInt = .{ .name = tmpbuf.toOwnedSlice() },
},
.comptime_float_type => .{
.ComptimeFloat = .{ .name = tmpbuf.toOwnedSlice() },
},
.bool_type => .{
.Bool = .{ .name = tmpbuf.toOwnedSlice() },
},
.void_type => .{
.Void = .{ .name = tmpbuf.toOwnedSlice() },
},
.type_type => .{
.Type = .{ .name = tmpbuf.toOwnedSlice() },
},
},
});
);
}
}
@@ -117,16 +133,21 @@ pub fn generateZirData(self: *Autodoc) !void {
data.packages[0].main = main_type_index.type;
if (self.doc_location.directory) |d|
(d.handle.makeDir(self.doc_location.basename) catch |e| switch (e) {
if (self.doc_location.directory) |d| {
d.handle.makeDir(
self.doc_location.basename,
) catch |e| switch (e) {
error.PathAlreadyExists => {},
else => unreachable,
})
else
(self.module.zig_cache_artifact_directory.handle.makeDir(self.doc_location.basename) catch |e| switch (e) {
};
} else {
self.module.zig_cache_artifact_directory.handle.makeDir(
self.doc_location.basename,
) catch |e| switch (e) {
error.PathAlreadyExists => {},
else => unreachable,
});
};
}
const output_dir = if (self.doc_location.directory) |d|
(d.handle.openDir(self.doc_location.basename, .{}) catch unreachable)
else
@@ -224,18 +245,126 @@ const DocData = struct {
fields: ?[]usize = null, // index into astNodes
};
const Type = struct {
kind: u32, // index into typeKinds
name: []const u8,
src: ?usize = null, // index into astNodes
privDecls: ?[]usize = null, // index into decls
pubDecls: ?[]usize = null, // index into decls
fields: ?[]WalkResult = null, // (use src->fields to find names)
const Type = union(std.builtin.TypeId) {
Type: struct { name: []const u8 },
Void: struct { name: []const u8 },
Bool: struct { name: []const u8 },
NoReturn: struct { name: []const u8 },
Int: struct { name: []const u8 },
Float: struct { name: []const u8 },
Pointer: struct { name: []const u8 },
Array: struct { name: []const u8 },
Struct: struct {
name: []const u8,
src: ?usize = null, // index into astNodes
privDecls: ?[]usize = null, // index into decls
pubDecls: ?[]usize = null, // index into decls
fields: ?[]TypeRef = null, // (use src->fields to find names)
},
ComptimeFloat: struct { name: []const u8 },
ComptimeInt: struct { name: []const u8 },
Undefined: struct { name: []const u8 },
Null: struct { name: []const u8 },
Optional: struct { name: []const u8 },
ErrorUnion: struct { name: []const u8 },
ErrorSet: struct { name: []const u8 },
Enum: struct {
name: []const u8,
src: ?usize = null, // index into astNodes
privDecls: ?[]usize = null, // index into decls
pubDecls: ?[]usize = null, // index into decls
// (use src->fields to find field names)
},
Union: struct {
name: []const u8,
src: ?usize = null, // index into astNodes
privDecls: ?[]usize = null, // index into decls
pubDecls: ?[]usize = null, // index into decls
fields: ?[]TypeRef = null, // (use src->fields to find names)
},
Fn: struct {
name: []const u8,
src: ?usize = null, // index into astNodes
ret: TypeRef,
params: ?[]TypeRef = null, // (use src->fields to find names)
},
BoundFn: struct { name: []const u8 },
Opaque: struct { name: []const u8 },
Frame: struct { name: []const u8 },
AnyFrame: struct { name: []const u8 },
Vector: struct { name: []const u8 },
EnumLiteral: struct { name: []const u8 },
pub fn jsonStringify(
self: Type,
opt: std.json.StringifyOptions,
w: anytype,
) !void {
try w.print(
\\{{ "kind": {},
\\
, .{@enumToInt(std.meta.activeTag(self))});
var options = opt;
if (options.whitespace) |*ws| ws.indent_level += 1;
switch (self) {
.Array => |v| try printTypeBody(v, options, w),
.Bool => |v| try printTypeBody(v, options, w),
.Void => |v| try printTypeBody(v, options, w),
.ComptimeInt => |v| try printTypeBody(v, options, w),
.ComptimeFloat => |v| try printTypeBody(v, options, w),
.Null => |v| try printTypeBody(v, options, w),
.Struct => |v| try printTypeBody(v, options, w),
.Fn => |v| try printTypeBody(v, options, w),
.Union => |v| try printTypeBody(v, options, w),
.Enum => |v| try printTypeBody(v, options, w),
.Int => |v| try printTypeBody(v, options, w),
.Float => |v| try printTypeBody(v, options, w),
.Type => |v| try printTypeBody(v, options, w),
else => {
std.debug.print(
"TODO: add {s} to `DocData.Type.jsonStringify`\n",
.{@tagName(self)},
);
},
}
try w.print("}}", .{});
}
fn printTypeBody(
body: anytype,
options: std.json.StringifyOptions,
w: anytype,
) !void {
const fields = std.meta.fields(@TypeOf(body));
inline for (fields) |f, idx| {
if (options.whitespace) |ws| try ws.outputIndent(w);
try w.print("\"{s}\": ", .{f.name});
try std.json.stringify(@field(body, f.name), options, w);
if (idx != fields.len - 1) try w.writeByte(',');
try w.writeByte('\n');
}
if (options.whitespace) |ws| {
var up = ws;
up.indent_level -= 1;
try up.outputIndent(w);
}
}
};
const TypeRef = union(enum) {
unspecified,
declRef: usize, // index in `decls`
type: usize, // index in `types`
pub fn fromWalkResult(wr: WalkResult) TypeRef {
return switch (wr) {
.declRef => |v| .{ .declRef = v },
.type => |v| .{ .type = v },
else => @panic("Found non-type WalkResult"),
};
}
pub fn jsonStringify(
self: TypeRef,
_: std.json.StringifyOptions,
@@ -247,6 +376,7 @@ const DocData = struct {
\\{{ "unspecified":{{}} }}
, .{});
},
.declRef, .type => |v| {
try w.print(
\\{{ "{s}":{} }}
@@ -287,9 +417,7 @@ const DocData = struct {
w: anytype,
) !void {
switch (self) {
.void,
.@"unreachable",
=> {
.void, .@"unreachable" => {
try w.print(
\\{{ "{s}":{{}} }}
, .{@tagName(self)});
@@ -360,7 +488,9 @@ fn walkInstruction(
const int = data[inst_index].int;
return DocData.WalkResult{
.int = .{
.typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) },
.typeRef = .{
.type = @enumToInt(Ref.comptime_int_type),
},
.value = int,
},
};
@@ -369,14 +499,20 @@ fn walkInstruction(
const float = data[inst_index].float;
return DocData.WalkResult{
.float = .{
.typeRef = .{ .type = @enumToInt(Ref.comptime_float_type) },
.typeRef = .{
.type = @enumToInt(Ref.comptime_float_type),
},
.value = float,
},
};
},
.negate => {
const un_node = data[inst_index].un_node;
var operand = try self.walkRef(zir, parent_scope, un_node.operand);
var operand: DocData.WalkResult = try self.walkRef(
zir,
parent_scope,
un_node.operand,
);
operand.int.negated = true; // only support ints for now
return operand;
},
@@ -420,8 +556,7 @@ fn walkInstruction(
const name = try std.fmt.allocPrint(self.arena, "{s}{}", .{ sign, bits });
try self.types.append(self.arena, .{
.kind = @enumToInt(std.builtin.TypeId.Int),
.name = name,
.Int = .{ .name = name },
});
return DocData.WalkResult{ .type = self.types.items.len - 1 };
},
@@ -432,12 +567,57 @@ fn walkInstruction(
const break_operand = data[break_index].@"break".operand;
return self.walkRef(zir, parent_scope, break_operand);
},
.func => {
const fn_info = zir.getFnInfo(@intCast(u32, inst_index));
// TODO: change this to a resize and change the appends accordingly
try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len);
try self.types.ensureUnusedCapacity(self.arena, fn_info.total_params_len);
var param_type_refs = try std.ArrayListUnmanaged(DocData.TypeRef).initCapacity(
self.arena,
fn_info.total_params_len,
);
var param_ast_indexes = try std.ArrayListUnmanaged(usize).initCapacity(
self.arena,
fn_info.total_params_len,
);
for (fn_info.param_body[0..fn_info.total_params_len]) |param_index| {
if (tags[param_index] != .param) unreachable; // TODO: handle more param types
const pl_tok = data[param_index].pl_tok;
const extra = zir.extraData(Zir.Inst.Param, pl_tok.payload_index);
param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
try self.ast_nodes.append(self.arena, .{
.name = zir.nullTerminatedString(zir.extra[extra.data.name]),
.docs = "",
});
const break_index = zir.extra[extra.end..][extra.data.body_len - 1];
const break_operand = data[break_index].@"break".operand;
const walk_res = try self.walkRef(zir, parent_scope, break_operand);
param_type_refs.appendAssumeCapacity(
DocData.TypeRef.fromWalkResult(walk_res),
);
}
self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items;
try self.types.append(self.arena, .{
.Fn = .{
.name = "todo_name func",
.src = self_ast_node_index,
.params = param_type_refs.items,
.ret = .{ .type = @enumToInt(Ref.void_type) },
},
});
return DocData.WalkResult{ .type = self.types.items.len - 1 };
},
.extended => {
const extended = data[inst_index].extended;
switch (extended.opcode) {
else => {
std.debug.panic(
"TODO: implement `walkInstruction.extended` for {s}\n\n",
"TODO: implement `walkinstruction.extended` for {s}\n\n",
.{@tagName(extended.opcode)},
);
},
@@ -510,13 +690,19 @@ fn walkInstruction(
// const body = zir.extra[extra_index..][0..body_len];
extra_index += body_len;
var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{};
var field_name_indexes: std.ArrayListUnmanaged(usize) = .{};
var field_type_refs = try std.ArrayListUnmanaged(DocData.TypeRef).initCapacity(
self.arena,
fields_len,
);
var field_name_indexes = try std.ArrayListUnmanaged(usize).initCapacity(
self.arena,
fields_len,
);
try self.collectUnionFieldInfo(
zir,
&scope,
fields_len,
&field_type_indexes,
&field_type_refs,
&field_name_indexes,
extra_index,
);
@@ -524,12 +710,13 @@ fn walkInstruction(
self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items;
try self.types.append(self.arena, .{
.kind = @enumToInt(std.builtin.TypeId.Union),
.name = "todo_name",
.src = self_ast_node_index,
.privDecls = priv_decl_indexes.items,
.pubDecls = decl_indexes.items,
.fields = field_type_indexes.items,
.Union = .{
.name = "todo_name",
.src = self_ast_node_index,
.privDecls = priv_decl_indexes.items,
.pubDecls = decl_indexes.items,
.fields = field_type_refs.items,
},
});
return DocData.WalkResult{ .type = self.types.items.len - 1 };
@@ -649,11 +836,12 @@ fn walkInstruction(
self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items;
try self.types.append(self.arena, .{
.kind = @enumToInt(std.builtin.TypeId.Enum),
.name = "todo_name",
.src = self_ast_node_index,
.privDecls = priv_decl_indexes.items,
.pubDecls = decl_indexes.items,
.Enum = .{
.name = "todo_name",
.src = self_ast_node_index,
.privDecls = priv_decl_indexes.items,
.pubDecls = decl_indexes.items,
},
});
return DocData.WalkResult{ .type = self.types.items.len - 1 };
@@ -720,13 +908,13 @@ fn walkInstruction(
// const body = zir.extra[extra_index..][0..body_len];
extra_index += body_len;
var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{};
var field_type_refs: std.ArrayListUnmanaged(DocData.TypeRef) = .{};
var field_name_indexes: std.ArrayListUnmanaged(usize) = .{};
try self.collectStructFieldInfo(
zir,
&scope,
fields_len,
&field_type_indexes,
&field_type_refs,
&field_name_indexes,
extra_index,
);
@@ -734,12 +922,13 @@ fn walkInstruction(
self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items;
try self.types.append(self.arena, .{
.kind = @enumToInt(std.builtin.TypeId.Struct),
.name = "todo_name",
.src = self_ast_node_index,
.privDecls = priv_decl_indexes.items,
.pubDecls = decl_indexes.items,
.fields = field_type_indexes.items,
.Struct = .{
.name = "todo_name",
.src = self_ast_node_index,
.privDecls = priv_decl_indexes.items,
.pubDecls = decl_indexes.items,
.fields = field_type_refs.items,
},
});
return DocData.WalkResult{ .type = self.types.items.len - 1 };
@@ -893,7 +1082,7 @@ fn collectUnionFieldInfo(
zir: Zir,
scope: *Scope,
fields_len: usize,
field_type_indexes: *std.ArrayListUnmanaged(DocData.WalkResult),
field_type_refs: *std.ArrayListUnmanaged(DocData.TypeRef),
field_name_indexes: *std.ArrayListUnmanaged(usize),
ei: usize,
) !void {
@@ -939,7 +1128,10 @@ fn collectUnionFieldInfo(
// type
{
const walk_result = try self.walkRef(zir, scope, field_type);
try field_type_indexes.append(self.arena, walk_result);
try field_type_refs.append(
self.arena,
walkResultToTypeRef(walk_result),
);
}
// ast node
@@ -962,7 +1154,7 @@ fn collectStructFieldInfo(
zir: Zir,
scope: *Scope,
fields_len: usize,
field_type_indexes: *std.ArrayListUnmanaged(DocData.WalkResult),
field_type_refs: *std.ArrayListUnmanaged(DocData.TypeRef),
field_name_indexes: *std.ArrayListUnmanaged(usize),
ei: usize,
) !void {
@@ -1005,7 +1197,10 @@ fn collectStructFieldInfo(
// type
{
const walk_result = try self.walkRef(zir, scope, field_type);
try field_type_indexes.append(self.arena, walk_result);
try field_type_refs.append(
self.arena,
walkResultToTypeRef(walk_result),
);
}
// ast node
@@ -1120,7 +1315,7 @@ fn walkRef(
fn walkResultToTypeRef(wr: DocData.WalkResult) DocData.TypeRef {
return switch (wr) {
else => std.debug.panic(
"TODO: handle `{s}` in `walkInstruction.as_node.dest_type`\n",
"TODO: handle `{s}` in `walkResultToTypeRef.as_node.dest_type`\n",
.{@tagName(wr)},
),
@@ -1128,3 +1323,7 @@ fn walkResultToTypeRef(wr: DocData.WalkResult) DocData.TypeRef {
.type => |v| .{ .type = v },
};
}
//fn collectParamInfo(self: *Autodoc, zir: Zir, scope: *Scope, inst_idx: Zir.Index) void {
//}