generated docs: functions with inferred error sets display nicely

infrastructure in place for displaying error sets
This commit is contained in:
Andrew Kelley 2019-10-08 13:41:13 -04:00
parent 03a6b33a73
commit 784a493dc7
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
6 changed files with 156 additions and 20 deletions

View File

@ -262,6 +262,7 @@
</div>
<h1 id="hdrName" class="hidden"></h1>
<div id="fnDocs" class="hidden"></div>
<div id="fnErrors" class="hidden"></div>
<div id="fnExamples" class="hidden"></div>
<div id="fnNoExamples" class="hidden">
<p>This function is not tested or referenced.</p>

View File

@ -11,6 +11,7 @@
var domFnProto = document.getElementById("fnProto");
var domFnProtoCode = document.getElementById("fnProtoCode");
var domFnDocs = document.getElementById("fnDocs");
var domFnErrors = document.getElementById("fnErrors");
var domFnExamples = document.getElementById("fnExamples");
var domFnNoExamples = document.getElementById("fnNoExamples");
var domSearch = document.getElementById("search");
@ -33,6 +34,8 @@
var typeKindFloatId;
var typeKindIntId;
var typeKindBoolId;
var typeKindErrSetId;
var typeKindErrUnionId;
findTypeKinds();
// for each package, is an array with packages to get to this one
@ -96,6 +99,7 @@
domSectInfo.classList.add("hidden");
domHdrName.classList.add("hidden");
domSectNav.classList.add("hidden");
domFnErrors.classList.add("hidden");
domFnExamples.classList.add("hidden");
domFnNoExamples.classList.add("hidden");
@ -183,7 +187,7 @@
protoHtml += ') ';
if (typeObj.ret != null) {
protoHtml += typeIndexName(typeObj.ret, true, true);
protoHtml += typeIndexName(typeObj.ret, true, true, fnDecl.value);
} else {
protoHtml += '<span class="tok-kw">var</span>';
}
@ -335,24 +339,24 @@
}
}
function typeIndexName(typeIndex, wantHtml, wantLink) {
function typeIndexName(typeIndex, wantHtml, wantLink, fnIndex) {
var typeObj = zigAnalysis.types[typeIndex];
if (wantLink) {
var declIndex = getCanonTypeDecl(typeIndex);
var declPath = getCanonDeclPath(declIndex);
var haveLink = declPath != null;
var typeNameHtml = typeName(typeObj, true, !haveLink);
var typeNameHtml = typeName(typeObj, true, !haveLink, fnIndex);
if (haveLink) {
return '<a href="' + navLink(declPath.pkgNames, declPath.declNames) + '">' + typeNameHtml + '</a>';
} else {
return typeNameHtml;
}
} else {
return typeName(typeObj, wantHtml);
return typeName(typeObj, wantHtml, false, fnIndex);
}
}
function typeName(typeObj, wantHtml, wantSubLink) {
function typeName(typeObj, wantHtml, wantSubLink, fnIndex) {
switch (typeObj.kind) {
case typeKindPtrId:
var name = "";
@ -397,11 +401,22 @@
name += typeObj.align;
}
if (typeObj.hostIntBytes != null) {
name += ":" + typeObj.bitOffsetInHost + ":" + typeObj.hostIntBytes;
name += ":";
if (wantHtml) {
name += '<span class="tok-number">' + typeObj.bitOffsetInHost + '</span>';
} else {
name += typeObj.bitOffsetInHost;
}
name += ":";
if (wantHtml) {
name += '<span class="tok-number">' + typeObj.hostIntBytes + '</span>';
} else {
name += typeObj.hostIntBytes;
}
}
name += ") ";
}
name += typeIndexName(typeObj.elem, wantHtml, wantSubLink);
name += typeIndexName(typeObj.elem, wantHtml, wantSubLink, null);
return name;
case typeKindFloatId:
if (wantHtml) {
@ -429,6 +444,29 @@
} else {
return "bool";
}
case typeKindErrSetId:
if (typeObj.errors == null) {
if (wantHtml) {
return '<span class="tok-type">anyerror</span>';
} else {
return "anyerror";
}
} else {
if (wantHtml) {
return escapeHtml(typeObj.name);
} else {
return typeObj.name;
}
}
case typeKindErrUnionId:
var errSetTypeObj = zigAnalysis.types[typeObj.err];
var payloadHtml = typeIndexName(typeObj.payload, wantHtml, wantSubLink, null);
if (errSetTypeObj.fn != null && errSetTypeObj.fn == fnIndex) {
// function index parameter supplied and this is the inferred error set of it
return "!" + payloadHtml;
} else {
return typeIndexName(typeObj.err, wantHtml, wantSubLink, null) + "!" + payloadHtml;
}
default:
if (wantHtml) {
return escapeHtml(typeObj.name);
@ -439,7 +477,7 @@
}
function renderType(typeObj) {
var name = typeName(typeObj);
var name = typeName(typeObj, false, false);
if (name != null && name != "") {
domHdrName.innerText = zigAnalysis.typeKinds[typeObj.kind] + " " + name;
domHdrName.classList.remove("hidden");
@ -543,6 +581,10 @@
typeKindIntId = i;
} else if (zigAnalysis.typeKinds[i] === "Bool") {
typeKindBoolId = i;
} else if (zigAnalysis.typeKinds[i] === "ErrorSet") {
typeKindErrSetId = i;
} else if (zigAnalysis.typeKinds[i] === "ErrorUnion") {
typeKindErrUnionId = i;
}
}
if (typeKindTypeId == null) {
@ -563,6 +605,12 @@
if (typeKindBoolId == null) {
throw new Error("No type kind 'Bool' found");
}
if (typeKindErrSetId == null) {
throw new Error("No type kind 'ErrorSet' found");
}
if (typeKindErrUnionId == null) {
throw new Error("No type kind 'ErrorUnion' found");
}
}
function findTypeTypeId() {

View File

@ -1290,9 +1290,10 @@ struct ZigTypeErrorUnion {
};
struct ZigTypeErrorSet {
uint32_t err_count;
ErrorTableEntry **errors;
ZigFn *infer_fn;
uint32_t err_count;
bool incomplete;
};
struct ZigTypeEnum {
@ -1328,6 +1329,9 @@ bool node_ptr_eql(const AstNode *a, const AstNode *b);
uint32_t fn_ptr_hash(const ZigFn *ptr);
bool fn_ptr_eql(const ZigFn *a, const ZigFn *b);
uint32_t err_ptr_hash(const ErrorTableEntry *ptr);
bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b);
struct ZigTypeUnion {
AstNode *decl_node;
TypeUnionField *fields;

View File

@ -1633,6 +1633,7 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
err_set_type->data.error_set.err_count = 0;
err_set_type->data.error_set.errors = nullptr;
err_set_type->data.error_set.infer_fn = fn_entry;
err_set_type->data.error_set.incomplete = true;
err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits;
err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align;
err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size;
@ -4277,12 +4278,12 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) {
assert(err_set_type->id == ZigTypeIdErrorSet);
ZigFn *infer_fn = err_set_type->data.error_set.infer_fn;
if (infer_fn != nullptr) {
if (infer_fn != nullptr && err_set_type->data.error_set.incomplete) {
if (infer_fn->anal_state == FnAnalStateInvalid) {
return false;
} else if (infer_fn->anal_state == FnAnalStateReady) {
analyze_fn_body(g, infer_fn);
if (err_set_type->data.error_set.infer_fn != nullptr) {
if (err_set_type->data.error_set.incomplete) {
assert(g->errors.length != 0);
return false;
}
@ -4509,7 +4510,9 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
if (fn_type_id->return_type->id == ZigTypeIdErrorUnion) {
ZigType *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type;
if (return_err_set_type->data.error_set.infer_fn != nullptr) {
if (return_err_set_type->data.error_set.infer_fn != nullptr &&
return_err_set_type->data.error_set.incomplete)
{
ZigType *inferred_err_set_type;
if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) {
inferred_err_set_type = fn->src_implicit_return_type;
@ -4522,14 +4525,16 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
return;
}
if (inferred_err_set_type->data.error_set.infer_fn != nullptr) {
if (inferred_err_set_type->data.error_set.infer_fn != nullptr &&
inferred_err_set_type->data.error_set.incomplete)
{
if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) {
fn->anal_state = FnAnalStateInvalid;
return;
}
}
return_err_set_type->data.error_set.infer_fn = nullptr;
return_err_set_type->data.error_set.incomplete = false;
if (type_is_global_error_set(inferred_err_set_type)) {
return_err_set_type->data.error_set.err_count = UINT32_MAX;
} else {
@ -7336,6 +7341,14 @@ bool fn_ptr_eql(const ZigFn *a, const ZigFn *b) {
return a == b;
}
uint32_t err_ptr_hash(const ErrorTableEntry *ptr) {
return hash_ptr((void*)ptr);
}
bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b) {
return a == b;
}
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
resolve_top_level_decl(codegen, tld, nullptr, false);
@ -7348,7 +7361,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
bool type_is_global_error_set(ZigType *err_set_type) {
assert(err_set_type->id == ZigTypeIdErrorSet);
assert(err_set_type->data.error_set.infer_fn == nullptr);
assert(!err_set_type->data.error_set.incomplete);
return err_set_type->data.error_set.err_count == UINT32_MAX;
}

View File

@ -357,6 +357,9 @@ struct AnalDumpCtx {
ZigList<AstNode *> node_list;
HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map;
ZigList<ErrorTableEntry *> err_list;
HashMap<const ErrorTableEntry *, uint32_t, err_ptr_hash, err_ptr_eql> err_map;
};
static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty);
@ -444,6 +447,17 @@ static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {
return fn_id;
}
static uint32_t anal_dump_get_err_id(AnalDumpCtx *ctx, ErrorTableEntry *err) {
uint32_t err_id = ctx->err_list.length;
auto existing_entry = ctx->err_map.put_unique(err, err_id);
if (existing_entry == nullptr) {
ctx->err_list.append(err);
} else {
err_id = existing_entry->value;
}
return err_id;
}
static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) {
uint32_t decl_id = ctx->decl_list.length;
auto existing_entry = ctx->decl_map.put_unique(tld, decl_id);
@ -513,6 +527,11 @@ static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) {
jw_int(&ctx->jw, fn_id);
}
static void anal_dump_err_ref(AnalDumpCtx *ctx, ErrorTableEntry *err) {
uint32_t err_id = anal_dump_get_err_id(ctx, err);
jw_int(&ctx->jw, err_id);
}
static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) {
uint32_t decl_id = anal_dump_get_decl_id(ctx, tld);
jw_int(&ctx->jw, decl_id);
@ -841,6 +860,33 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
anal_dump_pointer_attrs(ctx, ty);
break;
}
case ZigTypeIdErrorSet: {
if (type_is_global_error_set(ty)) {
break;
}
if (ty->data.error_set.infer_fn != nullptr) {
jw_object_field(jw, "fn");
anal_dump_fn_ref(ctx, ty->data.error_set.infer_fn);
}
jw_object_field(jw, "errors");
jw_begin_array(jw);
for (uint32_t i = 0; i < ty->data.error_set.err_count; i += 1) {
jw_array_elem(jw);
ErrorTableEntry *err = ty->data.error_set.errors[i];
anal_dump_err_ref(ctx, err);
}
jw_end_array(jw);
break;
}
case ZigTypeIdErrorUnion: {
jw_object_field(jw, "err");
anal_dump_type_ref(ctx, ty->data.error_union.err_set_type);
jw_object_field(jw, "payload");
anal_dump_type_ref(ctx, ty->data.error_union.payload_type);
break;
}
default:
jw_object_field(jw, "name");
jw_string(jw, buf_ptr(&ty->name));
@ -849,7 +895,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
jw_end_object(jw);
}
void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
JsonWriter *jw = &ctx->jw;
jw_begin_object(jw);
@ -892,7 +938,21 @@ void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
jw_end_object(jw);
}
void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) {
static void anal_dump_err(AnalDumpCtx *ctx, const ErrorTableEntry *err) {
JsonWriter *jw = &ctx->jw;
jw_begin_object(jw);
jw_object_field(jw, "src");
anal_dump_node_ref(ctx, err->decl_node);
jw_object_field(jw, "name");
jw_string(jw, buf_ptr(&err->name));
jw_end_object(jw);
}
static void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) {
JsonWriter *jw = &ctx->jw;
jw_begin_object(jw);
@ -918,6 +978,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
ctx.decl_map.init(16);
ctx.node_map.init(16);
ctx.fn_map.init(16);
ctx.err_map.init(16);
jw_begin_object(jw);
@ -1055,6 +1116,15 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
}
jw_end_array(jw);
jw_object_field(jw, "errors");
jw_begin_array(jw);
for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {
const ErrorTableEntry *err = ctx.err_list.at(i);
jw_array_elem(jw);
anal_dump_err(&ctx, err);
}
jw_end_array(jw);
jw_object_field(jw, "astNodes");
jw_begin_array(jw);
for (uint32_t i = 0; i < ctx.node_list.length; i += 1) {

View File

@ -9692,7 +9692,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
ZigType *container_set = wanted_type;
// if the container set is inferred, then this will always work.
if (container_set->data.error_set.infer_fn != nullptr) {
if (container_set->data.error_set.infer_fn != nullptr && container_set->data.error_set.incomplete) {
return result;
}
// if the container set is the global one, it will always work.
@ -16157,7 +16157,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
UndefOk);
if (inferred_err_set_type != nullptr) {
inferred_err_set_type->data.error_set.infer_fn = nullptr;
inferred_err_set_type->data.error_set.incomplete = false;
if (result->type->id == ZigTypeIdErrorUnion) {
ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
if (err != nullptr) {
@ -23617,7 +23617,7 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
if (!type_is_global_error_set(err_set_type) &&
err_set_type->data.error_set.err_count == 0)
{
assert(err_set_type->data.error_set.infer_fn == nullptr);
assert(!err_set_type->data.error_set.incomplete);
return ir_const_bool(ira, &instruction->base, false);
}
}