motiejus/zig

fork of https://codeberg.org/ziglang/zig
git clone https://git.jakstys.lt/motiejus/zig.git
Log | Tree | Refs | README | LICENSE

commit 784a493dc7114b6e6807c2a37d03dbadecee81e6 (tree)
parent 03a6b33a73612500038635633d4c8326c2b5cf5f
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Tue,  8 Oct 2019 13:41:13 -0400

generated docs: functions with inferred error sets display nicely

infrastructure in place for displaying error sets

Diffstat:
Mlib/std/special/docs/index.html | 1+
Mlib/std/special/docs/main.js | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/all_types.hpp | 6+++++-
Msrc/analyze.cpp | 25+++++++++++++++++++------
Msrc/dump_analysis.cpp | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/ir.cpp | 6+++---
6 files changed, 156 insertions(+), 20 deletions(-)

diff --git a/lib/std/special/docs/index.html b/lib/std/special/docs/index.html @@ -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> diff --git a/lib/std/special/docs/main.js b/lib/std/special/docs/main.js @@ -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() { diff --git a/src/all_types.hpp b/src/all_types.hpp @@ -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; diff --git a/src/analyze.cpp b/src/analyze.cpp @@ -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; } diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp @@ -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) { diff --git a/src/ir.cpp b/src/ir.cpp @@ -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); } }