autodoc: add support for non-generic function calls

This commit is contained in:
Loris Cro 2022-03-03 19:15:04 +01:00 committed by Andrew Kelley
parent 028c8a3c91
commit 195231b212
2 changed files with 58 additions and 21 deletions

View file

@ -82,7 +82,7 @@
// map of decl index to list of non-generic fn indexes // map of decl index to list of non-generic fn indexes
// var nodesToFnsMap = indexNodesToFns(); // var nodesToFnsMap = indexNodesToFns();
// map of decl index to list of comptime fn calls // map of decl index to list of comptime fn calls
var nodesToCallsMap = indexNodesToCalls(); // var nodesToCallsMap = indexNodesToCalls();
domSearch.addEventListener('keydown', onSearchKeyDown, false); domSearch.addEventListener('keydown', onSearchKeyDown, false);
window.addEventListener('hashchange', onHashChange, false); window.addEventListener('hashchange', onHashChange, false);
@ -193,6 +193,17 @@
return resolveTypeRefToTypeId(cte.typeRef); return resolveTypeRefToTypeId(cte.typeRef);
} }
if ("call" in decl.value) {
const fn_call = zigAnalysis.calls[decl.value.call];
console.assert("declPath" in fn_call.func);
const fn_decl = zigAnalysis.decls[fn_call.func.declPath[0]];
const fn_decl_value = resolveValue(fn_decl.value);
console.assert("type" in fn_decl_value); //TODO handle comptimeExpr
const fn_type = zigAnalysis.types[fn_decl_value.type];
console.assert(fn_type.kind === typeKinds.Fn);
return resolveTypeRefToTypeId(fn_type.ret);
}
console.log("TODO: handle in `typeOfDecl` more cases: ", decl); console.log("TODO: handle in `typeOfDecl` more cases: ", decl);
console.assert(false); console.assert(false);
throw {}; throw {};

View file

@ -10,6 +10,7 @@ module: *Module,
doc_location: Compilation.EmitLoc, doc_location: Compilation.EmitLoc,
arena: std.mem.Allocator, arena: std.mem.Allocator,
files: std.AutoHashMapUnmanaged(*File, usize) = .{}, files: std.AutoHashMapUnmanaged(*File, usize) = .{},
calls: std.ArrayListUnmanaged(DocData.Call) = .{},
types: std.ArrayListUnmanaged(DocData.Type) = .{}, types: std.ArrayListUnmanaged(DocData.Type) = .{},
decls: std.ArrayListUnmanaged(DocData.Decl) = .{}, decls: std.ArrayListUnmanaged(DocData.Decl) = .{},
ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{}, ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{},
@ -155,6 +156,7 @@ pub fn generateZirData(self: *Autodoc) !void {
var data = DocData{ var data = DocData{
.files = .{ .data = self.files }, .files = .{ .data = self.files },
.calls = self.calls.items,
.types = self.types.items, .types = self.types.items,
.decls = self.decls.items, .decls = self.decls.items,
.astNodes = self.ast_nodes.items, .astNodes = self.ast_nodes.items,
@ -240,10 +242,10 @@ const DocData = struct {
} = .{}, } = .{},
packages: [1]Package = .{.{}}, packages: [1]Package = .{.{}},
errors: []struct {} = &.{}, errors: []struct {} = &.{},
calls: []struct {} = &.{},
// non-hardcoded stuff // non-hardcoded stuff
astNodes: []AstNode, astNodes: []AstNode,
calls: []Call,
files: struct { files: struct {
// this struct is a temporary hack to support json serialization // this struct is a temporary hack to support json serialization
data: std.AutoHashMapUnmanaged(*File, usize), data: std.AutoHashMapUnmanaged(*File, usize),
@ -274,7 +276,11 @@ const DocData = struct {
types: []Type, types: []Type,
decls: []Decl, decls: []Decl,
comptimeExprs: []ComptimeExpr, comptimeExprs: []ComptimeExpr,
const Call = struct {
func: TypeRef,
args: []WalkResult,
ret: WalkResult,
};
const DocTypeKinds = blk: { const DocTypeKinds = blk: {
var info = @typeInfo(std.builtin.TypeId); var info = @typeInfo(std.builtin.TypeId);
const original_len = info.Enum.fields.len; const original_len = info.Enum.fields.len;
@ -344,8 +350,8 @@ const DocData = struct {
Struct: struct { Struct: struct {
name: []const u8, name: []const u8,
src: ?usize = null, // index into astNodes src: ?usize = null, // index into astNodes
privDecls: ?[]usize = null, // index into decls privDecls: []usize = &.{}, // index into decls
pubDecls: []usize, // index into decls pubDecls: []usize = &.{}, // index into decls
fields: ?[]TypeRef = null, // (use src->fields to find names) fields: ?[]TypeRef = null, // (use src->fields to find names)
}, },
ComptimeExpr: struct { name: []const u8 }, ComptimeExpr: struct { name: []const u8 },
@ -507,6 +513,7 @@ const DocData = struct {
value: f64, // direct value value: f64, // direct value
negated: bool = false, negated: bool = false,
}, },
call: usize, // index in `calls`
const Struct = struct { const Struct = struct {
typeRef: TypeRef, typeRef: TypeRef,
@ -526,7 +533,7 @@ const DocData = struct {
\\{{ "{s}":{{}} }} \\{{ "{s}":{{}} }}
, .{@tagName(self)}); , .{@tagName(self)});
}, },
.type, .comptimeExpr => |v| { .type, .comptimeExpr, .call => |v| {
try w.print( try w.print(
\\{{ "{s}":{} }} \\{{ "{s}":{} }}
, .{ @tagName(self), v }); , .{ @tagName(self), v });
@ -616,14 +623,7 @@ fn walkInstruction(
return new_file_walk_result; return new_file_walk_result;
}, },
.block => {
const res = DocData.WalkResult{ .comptimeExpr = self.comptime_exprs.items.len };
try self.comptime_exprs.append(self.arena, .{
.code = "if(banana) 1 else 0",
.typeRef = .{ .type = 0 },
});
return res;
},
.int => { .int => {
const int = data[inst_index].int; const int = data[inst_index].int;
return DocData.WalkResult{ return DocData.WalkResult{
@ -755,16 +755,42 @@ fn walkInstruction(
}); });
return DocData.WalkResult{ .type = self.types.items.len - 1 }; return DocData.WalkResult{ .type = self.types.items.len - 1 };
}, },
//.block => { .block => {
//const pl_node = data[inst_index].pl_node; const res = DocData.WalkResult{ .comptimeExpr = self.comptime_exprs.items.len };
//const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index); try self.comptime_exprs.append(self.arena, .{
//const last_instr_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; .code = "if(banana) 1 else 0",
//const break_operand = data[break_index].@"break".operand; .typeRef = .{ .type = 0 },
//return self.walkRef(file, parent_scope, break_operand); });
//}, return res;
},
.block_inline => { .block_inline => {
return self.walkRef(file, parent_scope, getBlockInlineBreak(file.zir, inst_index)); return self.walkRef(file, parent_scope, getBlockInlineBreak(file.zir, inst_index));
}, },
.call => {
const pl_node = data[inst_index].pl_node;
const extra = file.zir.extraData(Zir.Inst.Call, pl_node.payload_index);
// TODO: handle the way scoping works with fn args
const callee = DocData.TypeRef.fromWalkResult(
try self.walkRef(file, parent_scope, extra.data.callee),
);
const args_len = extra.data.flags.args_len;
var args = try self.arena.alloc(DocData.WalkResult, args_len);
const arg_refs = file.zir.refSlice(extra.end, args_len);
for (arg_refs) |ref, idx| {
args[idx] = try self.walkRef(file, parent_scope, ref);
}
const call_slot_index = self.calls.items.len;
try self.calls.append(self.arena, .{
.func = callee,
.args = args,
.ret = .{ .void = {} }, // TODO: handle returns!
});
return DocData.WalkResult{ .call = call_slot_index };
},
.func => { .func => {
const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index));