autodocs: output data support for more types
This commit is contained in:
325
src/Autodoc.zig
325
src/Autodoc.zig
@@ -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 {
|
||||
|
||||
//}
|
||||
|
||||
Reference in New Issue
Block a user