Commit a55db08a7b
Changed files (7)
lib
std
lib/std/special/docs/index.html
@@ -210,6 +210,10 @@
</div>
<h1 id="hdrName" class="hidden"></h1>
<div id="fnDocs" class="hidden"></div>
+ <div id="fnExamples" class="hidden"></div>
+ <div id="fnNoExamples" class="hidden">
+ <p>This function is not tested or referenced.</p>
+ </div>
<div id="sectSearchResults" class="hidden">
<h2>Search Results</h2>
<ul id="listSearchResults"></ul>
lib/std/special/docs/main.js
@@ -11,6 +11,8 @@
var domFnProto = document.getElementById("fnProto");
var domFnProtoCode = document.getElementById("fnProtoCode");
var domFnDocs = document.getElementById("fnDocs");
+ var domFnExamples = document.getElementById("fnExamples");
+ var domFnNoExamples = document.getElementById("fnNoExamples");
var domSearch = document.getElementById("search");
var domSectSearchResults = document.getElementById("sectSearchResults");
var domListSearchResults = document.getElementById("listSearchResults");
@@ -50,6 +52,12 @@
var rootIsStd = detectRootIsStd();
var typeTypeId = findTypeTypeId();
+
+ // map of decl index to list of non-generic fn indexes
+ var nodesToFnsMap = indexNodesToFns();
+ // map of decl index to list of comptime fn calls
+ var nodesToCallsMap = indexNodesToCalls();
+
domSearch.addEventListener('keydown', onSearchKeyDown, false);
window.addEventListener('hashchange', onHashChange, false);
window.addEventListener('keydown', onWindowKeyDown, false);
@@ -81,6 +89,8 @@
domSectInfo.classList.add("hidden");
domHdrName.classList.add("hidden");
domSectNav.classList.add("hidden");
+ domFnExamples.classList.add("hidden");
+ domFnNoExamples.classList.add("hidden");
renderTitle();
renderInfo();
@@ -138,16 +148,51 @@
}
}
+ function typeIsGenericFn(typeIndex) {
+ var typeObj = zigAnalysis.types[typeIndex];
+ if (typeObj.kind !== typeKindFnId) {
+ return false;
+ }
+ return typeObj.generic;
+ }
+
function renderFn(fnDecl) {
var typeObj = zigAnalysis.types[fnDecl.type];
domFnProtoCode.textContent = "fn " + fnDecl.name + typeObj.name.substring(2);
+ var docsSource = null;
var srcNode = zigAnalysis.astNodes[fnDecl.src];
if (srcNode.docs != null) {
- domFnDocs.innerHTML = markdown(srcNode.docs);
- domFnDocs.classList.remove("hidden");
+ docsSource = srcNode.docs;
+ }
+
+ var protoSrcIndex;
+ if (typeIsGenericFn(fnDecl.type)) {
+ protoSrcIndex = fnDecl.value;
+
+ var instantiations = nodesToFnsMap[protoSrcIndex];
+ var calls = nodesToCallsMap[protoSrcIndex];
+ if (instantiations == null && calls == null) {
+ domFnNoExamples.classList.remove("hidden");
+ } else {
+ // TODO show examples
+ domFnExamples.classList.remove("hidden");
+ }
+ } else {
+ protoSrcIndex = zigAnalysis.fns[fnDecl.value].src;
+
+ domFnExamples.classList.add("hidden");
+ domFnNoExamples.classList.add("hidden");
}
+ var protoSrcNode = zigAnalysis.astNodes[protoSrcIndex];
+ if (docsSource == null && protoSrcNode.docs != null) {
+ docsSource = protoSrcNode.docs;
+ }
+ if (docsSource != null) {
+ domFnDocs.innerHTML = markdown(docsSource);
+ domFnDocs.classList.remove("hidden");
+ }
domFnProto.classList.remove("hidden");
}
@@ -268,6 +313,17 @@
}
}
+ function allCompTimeFnCallsHaveTypeResult(typeIndex, value) {
+ var srcIndex = typeIsGenericFn(typeIndex) ? value : zigAnalysis.fns[value].src;
+ var calls = nodesToCallsMap[srcIndex];
+ if (calls == null) return false;
+ for (var i = 0; i < calls.length; i += 1) {
+ var call = zigAnalysis.calls[calls[i]];
+ if (call.result.type !== typeTypeId) return false;
+ }
+ return true;
+ }
+
function renderContainer(container) {
var typesList = [];
var fnsList = [];
@@ -279,7 +335,11 @@
} else {
var typeKind = zigAnalysis.types[decl.type].kind;
if (typeKind === typeKindFnId) {
- fnsList.push(decl);
+ if (allCompTimeFnCallsHaveTypeResult(decl.type, decl.value)) {
+ typesList.push(decl);
+ } else {
+ fnsList.push(decl);
+ }
}
}
}
@@ -688,4 +748,32 @@
}
}
}
+
+ function indexNodesToFns() {
+ var map = {};
+ for (var i = 0; i < zigAnalysis.fns.length; i += 1) {
+ var fn = zigAnalysis.fns[i];
+ if (typeIsGenericFn(fn.type)) continue;
+ if (map[fn.src] == null) {
+ map[fn.src] = [i];
+ } else {
+ map[fn.src].push(i);
+ }
+ }
+ return map;
+ }
+
+ function indexNodesToCalls() {
+ var map = {};
+ for (var i = 0; i < zigAnalysis.calls.length; i += 1) {
+ var call = zigAnalysis.calls[i];
+ var fn = zigAnalysis.fns[call.fn];
+ if (map[fn.src] == null) {
+ map[fn.src] = [i];
+ } else {
+ map[fn.src].push(i);
+ }
+ }
+ return map;
+ }
})();
lib/std/debug.zig
@@ -2439,3 +2439,8 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
);
std.debug.warn("{} sp = 0x{x}\n", prefix, sp);
}
+
+// Reference everything so it gets tested.
+test "" {
+ _ = leb;
+}
lib/std/std.zig
@@ -62,61 +62,69 @@ pub const unicode = @import("unicode.zig");
pub const valgrind = @import("valgrind.zig");
pub const zig = @import("zig.zig");
-test "std" {
- // run tests from these
- _ = @import("array_list.zig");
- _ = @import("atomic.zig");
- _ = @import("bloom_filter.zig");
- _ = @import("buf_map.zig");
- _ = @import("buf_set.zig");
- _ = @import("buffer.zig");
- _ = @import("hash_map.zig");
- _ = @import("linked_list.zig");
- _ = @import("mutex.zig");
- _ = @import("statically_initialized_mutex.zig");
- _ = @import("segmented_list.zig");
- _ = @import("spinlock.zig");
- _ = @import("child_process.zig");
+// Reference everything so it gets tested.
+test "" {
+ _ = AlignedArrayList;
+ _ = ArrayList;
+ _ = AutoHashMap;
+ _ = BloomFilter;
+ _ = BufMap;
+ _ = BufSet;
+ _ = Buffer;
+ _ = BufferOutStream;
+ _ = DynLib;
+ _ = HashMap;
+ _ = Mutex;
+ _ = PackedIntArrayEndian;
+ _ = PackedIntArray;
+ _ = PackedIntSliceEndian;
+ _ = PackedIntSlice;
+ _ = PriorityQueue;
+ _ = SinglyLinkedList;
+ _ = StaticallyInitializedMutex;
+ _ = SegmentedList;
+ _ = SpinLock;
+ _ = StringHashMap;
+ _ = ChildProcess;
+ _ = TailQueue;
+ _ = Thread;
- _ = @import("ascii.zig");
- _ = @import("base64.zig");
- _ = @import("build.zig");
- _ = @import("c.zig");
- _ = @import("coff.zig");
- _ = @import("crypto.zig");
- _ = @import("cstr.zig");
- _ = @import("debug.zig");
- _ = @import("dwarf.zig");
- _ = @import("dynamic_library.zig");
- _ = @import("elf.zig");
- _ = @import("event.zig");
- _ = @import("fmt.zig");
- _ = @import("fs.zig");
- _ = @import("hash.zig");
- _ = @import("heap.zig");
- _ = @import("http.zig");
- _ = @import("io.zig");
- _ = @import("json.zig");
- _ = @import("lazy_init.zig");
- _ = @import("macho.zig");
- _ = @import("math.zig");
- _ = @import("mem.zig");
- _ = @import("meta.zig");
- _ = @import("net.zig");
- _ = @import("os.zig");
- _ = @import("pdb.zig");
- _ = @import("process.zig");
- _ = @import("packed_int_array.zig");
- _ = @import("priority_queue.zig");
- _ = @import("rand.zig");
- _ = @import("rb.zig");
- _ = @import("sort.zig");
- _ = @import("testing.zig");
- _ = @import("thread.zig");
- _ = @import("time.zig");
- _ = @import("unicode.zig");
- _ = @import("valgrind.zig");
- _ = @import("zig.zig");
-
- _ = @import("debug/leb128.zig");
+ _ = atomic;
+ _ = base64;
+ _ = build;
+ _ = c;
+ _ = coff;
+ _ = crypto;
+ _ = cstr;
+ _ = debug;
+ _ = dwarf;
+ _ = elf;
+ _ = event;
+ _ = fmt;
+ _ = fs;
+ _ = hash;
+ _ = hash_map;
+ _ = heap;
+ _ = http;
+ _ = io;
+ _ = json;
+ _ = lazyInit;
+ _ = macho;
+ _ = math;
+ _ = mem;
+ _ = meta;
+ _ = net;
+ _ = os;
+ _ = packed_int_array;
+ _ = pdb;
+ _ = process;
+ _ = rand;
+ _ = rb;
+ _ = sort;
+ _ = ascii;
+ _ = testing;
+ _ = time;
+ _ = unicode;
+ _ = valgrind;
+ _ = zig;
}
src/all_types.hpp
@@ -1325,6 +1325,9 @@ bool tld_ptr_eql(const Tld *a, const Tld *b);
uint32_t node_ptr_hash(const AstNode *ptr);
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);
+
struct ZigTypeUnion {
AstNode *decl_node;
TypeUnionField *fields;
src/analyze.cpp
@@ -7328,6 +7328,14 @@ bool node_ptr_eql(const AstNode *a, const AstNode *b) {
return a == b;
}
+uint32_t fn_ptr_hash(const ZigFn *ptr) {
+ return hash_ptr((void*)ptr);
+}
+
+bool fn_ptr_eql(const ZigFn *a, const ZigFn *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);
src/dump_analysis.cpp
@@ -352,6 +352,9 @@ struct AnalDumpCtx {
ZigList<Tld *> decl_list;
HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map;
+ ZigList<ZigFn *> fn_list;
+ HashMap<const ZigFn *, uint32_t, fn_ptr_hash, fn_ptr_eql> fn_map;
+
ZigList<AstNode *> node_list;
HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map;
};
@@ -430,6 +433,17 @@ static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) {
return node_id;
}
+static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {
+ uint32_t fn_id = ctx->fn_list.length;
+ auto existing_entry = ctx->fn_map.put_unique(fn, fn_id);
+ if (existing_entry == nullptr) {
+ ctx->fn_list.append(fn);
+ } else {
+ fn_id = existing_entry->value;
+ }
+ return fn_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);
@@ -494,6 +508,11 @@ static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) {
jw_int(&ctx->jw, node_id);
}
+static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) {
+ uint32_t fn_id = anal_dump_get_fn_id(ctx, fn);
+ jw_int(&ctx->jw, fn_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);
@@ -600,8 +619,10 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) {
jw_object_field(jw, "type");
anal_dump_type_ref(ctx, fn->type_entry);
- }
+ jw_object_field(jw, "value");
+ anal_dump_fn_ref(ctx, fn);
+ }
break;
}
default:
@@ -642,6 +663,19 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,
anal_dump_type_ref(ctx, val_ty);
return;
}
+ case ZigTypeIdFn: {
+ if (value->data.x_ptr.special == ConstPtrSpecialFunction) {
+ ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry;
+ if (val_fn->type_entry->data.fn.is_generic) {
+ anal_dump_node_ref(ctx, val_fn->proto_node);
+ } else {
+ anal_dump_fn_ref(ctx, val_fn);
+ }
+ } else {
+ jw_null(&ctx->jw);
+ }
+ return;
+ }
default:
jw_null(&ctx->jw);
return;
@@ -721,6 +755,11 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
jw_int(jw, ty->data.floating.bit_count);
break;
}
+ case ZigTypeIdFn: {
+ jw_object_field(jw, "generic");
+ jw_bool(jw, ty->data.fn.is_generic);
+ break;
+ }
default:
// TODO
break;
@@ -763,7 +802,7 @@ void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
doc_comments_buf = nullptr;
break;
}
- if (doc_comments_buf->list.length != 0) {
+ if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) {
jw_object_field(jw, "docs");
jw_string(jw, buf_ptr(doc_comments_buf));
}
@@ -771,6 +810,19 @@ void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
jw_end_object(jw);
}
+void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) {
+ JsonWriter *jw = &ctx->jw;
+
+ jw_begin_object(jw);
+
+ jw_object_field(jw, "src");
+ anal_dump_node_ref(ctx, fn->proto_node);
+
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(ctx, fn->type_entry);
+
+ jw_end_object(jw);
+}
void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) {
Error err;
@@ -783,6 +835,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
ctx.file_map.init(16);
ctx.decl_map.init(16);
ctx.node_map.init(16);
+ ctx.fn_map.init(16);
jw_begin_object(jw);
@@ -822,6 +875,71 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
jw_object_field(jw, "rootPkg");
anal_dump_pkg_ref(&ctx, g->root_package);
+ // Poke the functions
+ for (size_t i = 0; i < g->fn_defs.length; i += 1) {
+ ZigFn *fn = g->fn_defs.at(i);
+ (void)anal_dump_get_fn_id(&ctx, fn);
+ }
+
+ jw_object_field(jw, "calls");
+ jw_begin_array(jw);
+ {
+ auto it = g->memoized_fn_eval_table.entry_iterator();
+ for (;;) {
+ auto *entry = it.next();
+ if (!entry)
+ break;
+
+ jw_array_elem(jw);
+ jw_begin_object(jw);
+
+ jw_object_field(jw, "args");
+ jw_begin_object(jw);
+
+ Scope *scope = entry->key;
+ while (scope != nullptr) {
+ if (scope->id == ScopeIdVarDecl) {
+ ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
+ jw_object_field(jw, var->name);
+ jw_begin_object(jw);
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(&ctx, var->var_type);
+ jw_object_field(jw, "value");
+ anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value);
+ jw_end_object(jw);
+ } else if (scope->id == ScopeIdFnDef) {
+ jw_end_object(jw);
+
+ jw_object_field(jw, "fn");
+ ZigFn *fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry;
+ anal_dump_fn_ref(&ctx, fn);
+
+ ConstExprValue *result = entry->value;
+ jw_object_field(jw, "result");
+ jw_begin_object(jw);
+ jw_object_field(jw, "type");
+ anal_dump_type_ref(&ctx, result->type);
+ jw_object_field(jw, "value");
+ anal_dump_value(&ctx, scope->source_node, result->type, result);
+ jw_end_object(jw);
+ break;
+ }
+ scope = scope->parent;
+ }
+ jw_end_object(jw);
+ }
+ }
+ jw_end_array(jw);
+
+ jw_object_field(jw, "fns");
+ jw_begin_array(jw);
+ for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) {
+ ZigFn *fn = ctx.fn_list.at(i);
+ jw_array_elem(jw);
+ anal_dump_fn(&ctx, fn);
+ }
+ jw_end_array(jw);
+
jw_object_field(jw, "packages");
jw_begin_array(jw);
for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) {