authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-16 01:29:16-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-16 01:49:02-04:00
log1014cfdf3b60faf9af5b062d198f4f44976cb1bc
treecfa5bff2c520b70c510e3a6ca44b35588417be38
parent47dfaf3d175ebea63b169a373b4dec4af6af7001
signaturelock-open Commit is signed but in an unrecognized format.

generated docs: progress towards generic types being useful

See #3406

6 files changed, 527 insertions(+), 85 deletions(-)

lib/std/hash_map.zig+2-1
......@@ -36,7 +36,8 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
3636 size: usize,
3737 max_distance_from_start_index: usize,
3838 allocator: *Allocator,
39 // this is used to detect bugs where a hashtable is edited while an iterator is running.
39
40 /// This is used to detect bugs where a hashtable is edited while an iterator is running.
4041 modification_count: debug_u32,
4142
4243 const Self = @This();
lib/std/meta.zig+10
......@@ -542,3 +542,13 @@ pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {
542542 }
543543 return error.InvalidEnumTag;
544544}
545
546/// Given a type and a name, return the field index according to source order.
547/// Returns `null` if the field is not found.
548pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int {
549 inline for (fields(T)) |field, i| {
550 if (mem.eql(u8, field.name, name))
551 return comptime_int(i);
552 }
553 return null;
554}
lib/std/special/docs/index.html+14-1
......@@ -104,6 +104,16 @@
104104 background-color: #FFBB4D;
105105 color: #000;
106106 }
107 #listFnExamples {
108 list-style-type: none;
109 margin: 0;
110 padding: 0;
111 }
112 #listFnExamples li {
113 padding: 0.5em 0;
114 white-space: nowrap;
115 overflow-x: auto;
116 }
107117 #logo {
108118 width: 8em;
109119 padding: 0.5em 1em;
......@@ -289,7 +299,6 @@
289299 <pre id="fnProtoCode"></pre>
290300 </div>
291301 <h1 id="hdrName" class="hidden"></h1>
292 <div id="fnExamples" class="hidden"></div>
293302 <div id="fnNoExamples" class="hidden">
294303 <p>This function is not tested or referenced.</p>
295304 </div>
......@@ -357,6 +366,10 @@
357366 <ul id="listErrSets">
358367 </ul>
359368 </div>
369 <div id="fnExamples" class="hidden">
370 <h2>Examples</h2>
371 <ul id="listFnExamples"></ul>
372 </div>
360373 </section>
361374 <div id="helpDialog" class="hidden">
362375 <h1>Keyboard Shortcuts</h1>
lib/std/special/docs/main.js+230-19
......@@ -26,6 +26,7 @@
2626 var domTableFnErrors = document.getElementById("tableFnErrors");
2727 var domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
2828 var domFnExamples = document.getElementById("fnExamples");
29 var domListFnExamples = document.getElementById("listFnExamples");
2930 var domFnNoExamples = document.getElementById("fnNoExamples");
3031 var domDeclNoRef = document.getElementById("declNoRef");
3132 var domSearch = document.getElementById("search");
......@@ -64,6 +65,9 @@
6465 declNames: [],
6566 // these will be all types, except the last one may be a type or a decl
6667 declObjs: [],
68
69 // (a, b, c, d) comptime call; result is the value the docs refer to
70 callName: null,
6771 };
6872 var curNavSearch = "";
6973 var curSearchIndex = -1;
......@@ -237,20 +241,29 @@
237241 renderErrorSet(errSetType);
238242 }
239243
240 var protoSrcIndex;
244 var fnObj = zigAnalysis.fns[fnDecl.value];
245 var protoSrcIndex = fnObj.src;
241246 if (typeIsGenericFn(fnDecl.type)) {
242 protoSrcIndex = fnDecl.value;
243
244247 var instantiations = nodesToFnsMap[protoSrcIndex];
245248 var calls = nodesToCallsMap[protoSrcIndex];
246249 if (instantiations == null && calls == null) {
247250 domFnNoExamples.classList.remove("hidden");
248 } else {
249 // TODO show examples
251 } else if (calls != null) {
252 if (fnObj.combined === undefined) fnObj.combined = allCompTimeFnCallsResult(calls);
253 if (fnObj.combined != null) renderContainer(fnObj.combined);
254
255 resizeDomList(domListFnExamples, calls.length, '<li></li>');
256
257 for (var callI = 0; callI < calls.length; callI += 1) {
258 var liDom = domListFnExamples.children[callI];
259 liDom.innerHTML = getCallHtml(fnDecl, calls[callI]);
260 }
261
250262 domFnExamples.classList.remove("hidden");
263 } else if (instantiations != null) {
264 // TODO
251265 }
252266 } else {
253 protoSrcIndex = zigAnalysis.fns[fnDecl.value].src;
254267
255268 domFnExamples.classList.add("hidden");
256269 domFnNoExamples.classList.add("hidden");
......@@ -349,13 +362,15 @@
349362 }
350363 }
351364
352 function navLink(pkgNames, declNames) {
365 function navLink(pkgNames, declNames, callName) {
353366 if (pkgNames.length === 0 && declNames.length === 0) {
354367 return '#';
355 } else if (declNames.length === 0) {
368 } else if (declNames.length === 0 && callName == null) {
356369 return '#' + pkgNames.join('.');
357 } else {
370 } else if (callName == null) {
358371 return '#' + pkgNames.join('.') + ';' + declNames.join('.');
372 } else {
373 return '#' + pkgNames.join('.') + ';' + declNames.join('.') + ';' + callName;
359374 }
360375 }
361376
......@@ -367,6 +382,22 @@
367382 return navLink(curNav.pkgNames, curNav.declNames.concat([childName]));
368383 }
369384
385 function navLinkCall(callObj) {
386 var declNamesCopy = curNav.declNames.concat([]);
387 var callName = declNamesCopy.pop();
388
389 callName += '(';
390 for (var arg_i = 0; arg_i < callObj.args.length; arg_i += 1) {
391 if (arg_i !== 0) callName += ',';
392 var argObj = callObj.args[arg_i];
393 callName += getValueText(argObj.type, argObj.value, false, false);
394 }
395 callName += ')';
396
397 declNamesCopy.push(callName);
398 return navLink(curNav.pkgNames, declNamesCopy);
399 }
400
370401 function resizeDomListDl(dlDom, desiredLen) {
371402 // add the missing dom entries
372403 var i, ev;
......@@ -426,6 +457,40 @@
426457 return (typeObj.len == null) ? pointerSizeEnum.One : typeObj.len;
427458 }
428459
460 function getCallHtml(fnDecl, callIndex) {
461 var callObj = zigAnalysis.calls[callIndex];
462
463 // TODO make these links work
464 //var html = '<a href="' + navLinkCall(callObj) + '">' + escapeHtml(fnDecl.name) + '</a>(';
465 var html = escapeHtml(fnDecl.name) + '(';
466 for (var arg_i = 0; arg_i < callObj.args.length; arg_i += 1) {
467 if (arg_i !== 0) html += ', ';
468 var argObj = callObj.args[arg_i];
469 html += getValueText(argObj.type, argObj.value, true, true);
470 }
471 html += ')';
472 return html;
473 }
474
475 function getValueText(typeIndex, value, wantHtml, wantLink) {
476 var typeObj = zigAnalysis.types[typeIndex];
477 switch (typeObj.kind) {
478 case typeKinds.Type:
479 return typeIndexName(value, wantHtml, wantLink);
480 case typeKinds.Fn:
481 var fnObj = zigAnalysis.fns[value];
482 return typeIndexName(fnObj.type, wantHtml, wantLink);
483 case typeKinds.Int:
484 if (wantHtml) {
485 return '<span class="tok-number">' + value + '</span>';
486 } else {
487 return value + "";
488 }
489 default:
490 throw new Error("TODO implement getValueText for this type");
491 }
492 }
493
429494 function typeName(typeObj, wantHtml, wantSubLink, fnDecl, linkFnNameDecl) {
430495 switch (typeObj.kind) {
431496 case typeKinds.Array:
......@@ -544,6 +609,12 @@
544609 } else {
545610 return "void";
546611 }
612 case typeKinds.EnumLiteral:
613 if (wantHtml) {
614 return '<span class="tok-type">(enum literal)</span>';
615 } else {
616 return "(enum literal)";
617 }
547618 case typeKinds.NoReturn:
548619 if (wantHtml) {
549620 return '<span class="tok-type">noreturn</span>';
......@@ -592,6 +663,15 @@
592663 }
593664 payloadHtml += '(';
594665 if (typeObj.args != null) {
666 var fields = null;
667 var isVarArgs = false;
668 if (fnDecl != null) {
669 var fnObj = zigAnalysis.fns[fnDecl.value];
670 var fnNode = zigAnalysis.astNodes[fnObj.src];
671 fields = fnNode.fields;
672 isVarArgs = fnNode.varArgs;
673 }
674
595675 for (var i = 0; i < typeObj.args.length; i += 1) {
596676 if (i != 0) {
597677 payloadHtml += ', ';
......@@ -599,10 +679,31 @@
599679
600680 var argTypeIndex = typeObj.args[i];
601681
602 if (fnDecl != null && zigAnalysis.astNodes[fnDecl.src].fields != null) {
603 var paramDeclIndex = zigAnalysis.astNodes[fnDecl.src].fields[i];
604 var paramName = zigAnalysis.astNodes[paramDeclIndex].name;
682 if (fields != null) {
683 var paramNode = zigAnalysis.astNodes[fields[i]];
684
685 if (paramNode.varArgs) {
686 payloadHtml += '...';
687 continue;
688 }
689
690 if (paramNode.noalias) {
691 if (wantHtml) {
692 payloadHtml += '<span class="tok-kw">noalias</span> ';
693 } else {
694 payloadHtml += 'noalias ';
695 }
696 }
697
698 if (paramNode.comptime) {
699 if (wantHtml) {
700 payloadHtml += '<span class="tok-kw">comptime</span> ';
701 } else {
702 payloadHtml += 'comptime ';
703 }
704 }
605705
706 var paramName = paramNode.name;
606707 if (paramName != null) {
607708 // skip if it matches the type name
608709 if (argTypeIndex == null || !shouldSkipParamName(argTypeIndex, paramName)) {
......@@ -611,7 +712,9 @@
611712 }
612713 }
613714
614 if (argTypeIndex != null) {
715 if (isVarArgs && i === typeObj.args.length - 1) {
716 payloadHtml += '...';
717 } else if (argTypeIndex != null) {
615718 payloadHtml += typeIndexName(argTypeIndex, wantHtml, wantSubLink);
616719 } else if (wantHtml) {
617720 payloadHtml += '<span class="tok-kw">var</span>';
......@@ -690,7 +793,7 @@
690793 }
691794
692795 function allCompTimeFnCallsHaveTypeResult(typeIndex, value) {
693 var srcIndex = typeIsGenericFn(typeIndex) ? value : zigAnalysis.fns[value].src;
796 var srcIndex = zigAnalysis.fns[value].src;
694797 var calls = nodesToCallsMap[srcIndex];
695798 if (calls == null) return false;
696799 for (var i = 0; i < calls.length; i += 1) {
......@@ -700,6 +803,90 @@
700803 return true;
701804 }
702805
806 function allCompTimeFnCallsResult(calls) {
807 var firstTypeObj = null;
808 var containerObj = {
809 privDecls: [],
810 };
811 for (var callI = 0; callI < calls.length; callI += 1) {
812 var call = zigAnalysis.calls[calls[callI]];
813 if (call.result.type !== typeTypeId) return null;
814 var typeObj = zigAnalysis.types[call.result.value];
815 if (!typeKindIsContainer(typeObj.kind)) return null;
816 if (firstTypeObj == null) {
817 firstTypeObj = typeObj;
818 containerObj.src = typeObj.src;
819 } else if (firstTypeObj.src !== typeObj.src) {
820 return null;
821 }
822
823 if (containerObj.fields == null) {
824 containerObj.fields = (typeObj.fields || []).concat([]);
825 } else for (var fieldI = 0; fieldI < typeObj.fields.length; fieldI += 1) {
826 var prev = containerObj.fields[fieldI];
827 var next = typeObj.fields[fieldI];
828 if (prev === next) continue;
829 if (typeof(prev) === 'object') {
830 if (prev[next] == null) prev[next] = typeObj;
831 } else {
832 containerObj.fields[fieldI] = {};
833 containerObj.fields[fieldI][prev] = firstTypeObj;
834 containerObj.fields[fieldI][next] = typeObj;
835 }
836 }
837
838 if (containerObj.pubDecls == null) {
839 containerObj.pubDecls = (typeObj.pubDecls || []).concat([]);
840 } else for (var declI = 0; declI < typeObj.pubDecls.length; declI += 1) {
841 var prev = containerObj.pubDecls[declI];
842 var next = typeObj.pubDecls[declI];
843 if (prev === next) continue;
844 // TODO instead of showing "examples" as the public declarations,
845 // do logic like this:
846 //if (typeof(prev) !== 'object') {
847 // var newDeclId = zigAnalysis.decls.length;
848 // prev = clone(zigAnalysis.decls[prev]);
849 // prev.id = newDeclId;
850 // zigAnalysis.decls.push(prev);
851 // containerObj.pubDecls[declI] = prev;
852 //}
853 //mergeDecls(prev, next, firstTypeObj, typeObj);
854 }
855 }
856 for (var declI = 0; declI < containerObj.pubDecls.length; declI += 1) {
857 var decl = containerObj.pubDecls[declI];
858 if (typeof(decl) === 'object') {
859 containerObj.pubDecls[declI] = containerObj.pubDecls[declI].id;
860 }
861 }
862 return containerObj;
863 }
864
865 function mergeDecls(declObj, nextDeclIndex, firstTypeObj, typeObj) {
866 var nextDeclObj = zigAnalysis.decls[nextDeclIndex];
867 if (declObj.type != null && nextDeclObj.type != null && declObj.type !== nextDeclObj.type) {
868 if (typeof(declObj.type) !== 'object') {
869 var prevType = declObj.type;
870 declObj.type = {};
871 declObj.type[prevType] = firstTypeObj;
872 declObj.value = null;
873 }
874 declObj.type[nextDeclObj.type] = typeObj;
875 } else if (declObj.type == null && nextDeclObj != null) {
876 declObj.type = nextDeclObj.type;
877 }
878 if (declObj.value != null && nextDeclObj.value != null && declObj.value !== nextDeclObj.value) {
879 if (typeof(declObj.value) !== 'object') {
880 var prevValue = declObj.value;
881 declObj.value = {};
882 declObj.value[prevValue] = firstTypeObj;
883 }
884 declObj.value[nextDeclObj.value] = typeObj;
885 } else if (declObj.value == null && nextDeclObj.value != null) {
886 declObj.value = nextDeclObj.value;
887 }
888 }
889
703890 function renderValue(decl) {
704891 domFnProtoCode.innerHTML = '<span class="tok-kw">const</span> ' +
705892 escapeHtml(decl.name) + ': ' + typeIndexName(decl.type, true, true);
......@@ -733,13 +920,15 @@
733920 var fnsList = [];
734921 var varsList = [];
735922 var valsList = [];
923
736924 for (var i = 0; i < container.pubDecls.length; i += 1) {
737925 var decl = zigAnalysis.decls[container.pubDecls[i]];
926
738927 if (decl.kind === 'var') {
739928 varsList.push(decl);
740929 continue;
741930 } else if (decl.kind === 'const' && decl.type != null) {
742 if (decl.type == typeTypeId) {
931 if (decl.type === typeTypeId) {
743932 if (typeIsErrSet(decl.value)) {
744933 errSetsList.push(decl);
745934 } else if (typeIsStructWithNoFields(decl.value)) {
......@@ -838,7 +1027,12 @@
8381027 if (container.kind === typeKinds.Enum) {
8391028 html += ' = <span class="tok-number">' + field + '</span>';
8401029 } else {
841 html += ": " + typeIndexName(field, true, true);
1030 html += ": ";
1031 if (typeof(field) === 'object') {
1032 html += '<span class="tok-kw">var</span>';
1033 } else {
1034 html += typeIndexName(field, true, true);
1035 }
8421036 }
8431037
8441038 html += ',</pre>';
......@@ -1042,13 +1236,16 @@
10421236 return list;
10431237 }
10441238
1045 function declCanRepresentTypeKind(typeKind) {
1046 return typeKind === typeKinds.ErrorSet ||
1047 typeKind === typeKinds.Struct ||
1239 function typeKindIsContainer(typeKind) {
1240 return typeKind === typeKinds.Struct ||
10481241 typeKind === typeKinds.Union ||
10491242 typeKind === typeKinds.Enum;
10501243 }
10511244
1245 function declCanRepresentTypeKind(typeKind) {
1246 return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
1247 }
1248
10521249 function computeCanonDeclPaths() {
10531250 var list = new Array(zigAnalysis.decls.length);
10541251 canonTypeDecls = new Array(zigAnalysis.types.length);
......@@ -1406,4 +1603,18 @@
14061603 function byNameProperty(a, b) {
14071604 return operatorCompare(a.name, b.name);
14081605 }
1606
1607 function clone(obj) {
1608 var res = {};
1609 for (var key in obj) {
1610 res[key] = obj[key];
1611 }
1612 return res;
1613 }
1614
1615 function firstObjectKey(obj) {
1616 for (var key in obj) {
1617 return key;
1618 }
1619 }
14091620})();
src/dump_analysis.cpp+98-64
......@@ -456,6 +456,10 @@ static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {
456456 auto existing_entry = ctx->fn_map.put_unique(fn, fn_id);
457457 if (existing_entry == nullptr) {
458458 ctx->fn_list.append(fn);
459
460 // poke the fn
461 (void)anal_dump_get_type_id(ctx, fn->type_entry);
462 (void)anal_dump_get_node_id(ctx, fn->proto_node);
459463 } else {
460464 fn_id = existing_entry->value;
461465 }
......@@ -700,11 +704,7 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,
700704 case ZigTypeIdFn: {
701705 if (value->data.x_ptr.special == ConstPtrSpecialFunction) {
702706 ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry;
703 if (val_fn->type_entry->data.fn.is_generic) {
704 anal_dump_node_ref(ctx, val_fn->proto_node);
705 } else {
706 anal_dump_fn_ref(ctx, val_fn);
707 }
707 anal_dump_fn_ref(ctx, val_fn);
708708 } else {
709709 jw_null(&ctx->jw);
710710 }
......@@ -758,6 +758,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
758758 switch (ty->id) {
759759 case ZigTypeIdMetaType:
760760 case ZigTypeIdBool:
761 case ZigTypeIdEnumLiteral:
761762 break;
762763 case ZigTypeIdStruct: {
763764 if (ty->data.structure.is_slice) {
......@@ -1072,13 +1073,25 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
10721073 jw_object_field(jw, "col");
10731074 jw_int(jw, node->column);
10741075
1075 const Buf *doc_comments_buf;
1076 const Buf *doc_comments_buf = nullptr;
1077 const Buf *name_buf = nullptr;
1078 const ZigList<AstNode *> *field_nodes = nullptr;
1079 bool is_var_args = false;
1080 bool is_noalias = false;
1081 bool is_comptime = false;
1082
10761083 switch (node->type) {
10771084 case NodeTypeParamDecl:
10781085 doc_comments_buf = &node->data.param_decl.doc_comments;
1086 name_buf = node->data.param_decl.name;
1087 is_var_args = node->data.param_decl.is_var_args;
1088 is_noalias = node->data.param_decl.is_noalias;
1089 is_comptime = node->data.param_decl.is_comptime;
10791090 break;
10801091 case NodeTypeFnProto:
10811092 doc_comments_buf = &node->data.fn_proto.doc_comments;
1093 field_nodes = &node->data.fn_proto.params;
1094 is_var_args = node->data.fn_proto.is_var_args;
10821095 break;
10831096 case NodeTypeVariableDeclaration:
10841097 doc_comments_buf = &node->data.variable_declaration.doc_comments;
......@@ -1088,55 +1101,50 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
10881101 break;
10891102 case NodeTypeStructField:
10901103 doc_comments_buf = &node->data.struct_field.doc_comments;
1104 name_buf = node->data.struct_field.name;
1105 break;
1106 case NodeTypeContainerDecl:
1107 field_nodes = &node->data.container_decl.fields;
10911108 break;
10921109 default:
1093 doc_comments_buf = nullptr;
10941110 break;
10951111 }
1112
10961113 if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) {
10971114 jw_object_field(jw, "docs");
10981115 jw_string(jw, buf_ptr(doc_comments_buf));
10991116 }
11001117
1101 const Buf *name_buf;
1102 switch (node->type) {
1103 case NodeTypeStructField:
1104 name_buf = node->data.struct_field.name;
1105 break;
1106 case NodeTypeParamDecl:
1107 name_buf = node->data.param_decl.name;
1108 break;
1109 default:
1110 name_buf = nullptr;
1111 break;
1112 }
11131118 if (name_buf != nullptr) {
11141119 jw_object_field(jw, "name");
11151120 jw_string(jw, buf_ptr(name_buf));
11161121 }
11171122
1118 const ZigList<AstNode *> *fieldNodes;
1119 switch (node->type) {
1120 case NodeTypeContainerDecl:
1121 fieldNodes = &node->data.container_decl.fields;
1122 break;
1123 case NodeTypeFnProto:
1124 fieldNodes = &node->data.fn_proto.params;
1125 break;
1126 default:
1127 fieldNodes = nullptr;
1128 break;
1129 }
1130 if (fieldNodes != nullptr) {
1123 if (field_nodes != nullptr) {
11311124 jw_object_field(jw, "fields");
11321125 jw_begin_array(jw);
1133 for (size_t i = 0; i < fieldNodes->length; i += 1) {
1126 for (size_t i = 0; i < field_nodes->length; i += 1) {
11341127 jw_array_elem(jw);
1135 anal_dump_node_ref(ctx, fieldNodes->at(i));
1128 anal_dump_node_ref(ctx, field_nodes->at(i));
11361129 }
11371130 jw_end_array(jw);
11381131 }
11391132
1133 if (is_var_args) {
1134 jw_object_field(jw, "varArgs");
1135 jw_bool(jw, true);
1136 }
1137
1138 if (is_comptime) {
1139 jw_object_field(jw, "comptime");
1140 jw_bool(jw, true);
1141 }
1142
1143 if (is_noalias) {
1144 jw_object_field(jw, "noalias");
1145 jw_bool(jw, true);
1146 }
1147
11401148 jw_end_object(jw);
11411149}
11421150
......@@ -1235,59 +1243,76 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
12351243 jw_object_field(jw, "calls");
12361244 jw_begin_array(jw);
12371245 {
1246 ZigList<ZigVar *> var_stack = {};
1247
12381248 auto it = g->memoized_fn_eval_table.entry_iterator();
12391249 for (;;) {
12401250 auto *entry = it.next();
12411251 if (!entry)
12421252 break;
12431253
1244 jw_array_elem(jw);
1245 jw_begin_object(jw);
1246
1247 jw_object_field(jw, "args");
1248 jw_begin_object(jw);
1254 var_stack.resize(0);
1255 ZigFn *fn = nullptr;
12491256
12501257 Scope *scope = entry->key;
12511258 while (scope != nullptr) {
12521259 if (scope->id == ScopeIdVarDecl) {
12531260 ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
1254 jw_object_field(jw, var->name);
1255 jw_begin_object(jw);
1256 jw_object_field(jw, "type");
1257 anal_dump_type_ref(&ctx, var->var_type);
1258 jw_object_field(jw, "value");
1259 anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value);
1260 jw_end_object(jw);
1261 var_stack.append(var);
12611262 } else if (scope->id == ScopeIdFnDef) {
1262 jw_end_object(jw);
1263 fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry;
1264 break;
1265 }
1266 scope = scope->parent;
1267 }
1268 ConstExprValue *result = entry->value;
1269
1270 assert(fn != nullptr);
1271
1272 jw_array_elem(jw);
1273 jw_begin_object(jw);
1274
1275 jw_object_field(jw, "fn");
1276 anal_dump_fn_ref(&ctx, fn);
1277
1278 jw_object_field(jw, "result");
1279 {
1280 jw_begin_object(jw);
1281
1282 jw_object_field(jw, "type");
1283 anal_dump_type_ref(&ctx, result->type);
1284
1285 jw_object_field(jw, "value");
1286 anal_dump_value(&ctx, scope->source_node, result->type, result);
1287
1288 jw_end_object(jw);
1289 }
1290
1291 if (var_stack.length != 0) {
1292 jw_object_field(jw, "args");
1293 jw_begin_array(jw);
12631294
1264 jw_object_field(jw, "fn");
1265 ZigFn *fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry;
1266 anal_dump_fn_ref(&ctx, fn);
1295 while (var_stack.length != 0) {
1296 ZigVar *var = var_stack.pop();
12671297
1268 ConstExprValue *result = entry->value;
1269 jw_object_field(jw, "result");
1298 jw_array_elem(jw);
12701299 jw_begin_object(jw);
1300
12711301 jw_object_field(jw, "type");
1272 anal_dump_type_ref(&ctx, result->type);
1302 anal_dump_type_ref(&ctx, var->var_type);
1303
12731304 jw_object_field(jw, "value");
1274 anal_dump_value(&ctx, scope->source_node, result->type, result);
1305 anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value);
1306
12751307 jw_end_object(jw);
1276 break;
12771308 }
1278 scope = scope->parent;
1309 jw_end_array(jw);
12791310 }
1311
12801312 jw_end_object(jw);
12811313 }
1282 }
1283 jw_end_array(jw);
12841314
1285 jw_object_field(jw, "fns");
1286 jw_begin_array(jw);
1287 for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) {
1288 ZigFn *fn = ctx.fn_list.at(i);
1289 jw_array_elem(jw);
1290 anal_dump_fn(&ctx, fn);
1315 var_stack.deinit();
12911316 }
12921317 jw_end_array(jw);
12931318
......@@ -1315,6 +1340,15 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
13151340 }
13161341 jw_end_array(jw);
13171342
1343 jw_object_field(jw, "fns");
1344 jw_begin_array(jw);
1345 for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) {
1346 ZigFn *fn = ctx.fn_list.at(i);
1347 jw_array_elem(jw);
1348 anal_dump_fn(&ctx, fn);
1349 }
1350 jw_end_array(jw);
1351
13181352 jw_object_field(jw, "errors");
13191353 jw_begin_array(jw);
13201354 for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {
tools/merge_anal_dumps.zig+173
......@@ -2,6 +2,8 @@ const builtin = @import("builtin");
22const std = @import("std");
33const json = std.json;
44const mem = std.mem;
5const fieldIndex = std.meta.fieldIndex;
6const TypeId = builtin.TypeId;
57
68pub fn main() anyerror!void {
79 var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
......@@ -61,6 +63,81 @@ const Error = struct {
6163 }
6264};
6365
66const simple_types = [_][]const u8{
67 "Type",
68 "Void",
69 "Bool",
70 "NoReturn",
71 "ComptimeFloat",
72 "ComptimeInt",
73 "Undefined",
74 "Null",
75 "AnyFrame",
76 "EnumLiteral",
77};
78
79const Type = union(builtin.TypeId) {
80 Type,
81 Void,
82 Bool,
83 NoReturn,
84 ComptimeFloat,
85 ComptimeInt,
86 Undefined,
87 Null,
88 AnyFrame,
89 EnumLiteral,
90
91 Int: Int,
92 Float: usize, // bits
93
94 Vector: Array,
95 Optional: usize, // payload type index
96 Pointer: Pointer,
97 Array: Array,
98
99 Struct, // TODO
100 ErrorUnion, // TODO
101 ErrorSet, // TODO
102 Enum, // TODO
103 Union, // TODO
104 Fn, // TODO
105 BoundFn, // TODO
106 ArgTuple, // TODO
107 Opaque, // TODO
108 Frame, // TODO
109
110 const Int = struct {
111 bits: usize,
112 signed: bool,
113 };
114
115 const Pointer = struct {
116 elem: usize,
117 alignment: usize,
118 is_const: bool,
119 is_volatile: bool,
120 allow_zero: bool,
121 host_int_bytes: usize,
122 bit_offset_in_host: usize,
123 };
124
125 const Array = struct {
126 elem: usize,
127 len: usize,
128 };
129
130 fn hash(t: Type) u32 {
131 var hasher = std.hash.Wyhash.init(0);
132 std.hash.autoHash(&hasher, builtin.TypeId(t));
133 return @truncate(u32, hasher.final());
134 }
135
136 fn eql(a: Type, b: Type) bool {
137 return std.meta.eql(a, b);
138 }
139};
140
64141const Dump = struct {
65142 zig_id: ?[]const u8 = null,
66143 zig_version: ?[]const u8 = null,
......@@ -79,6 +156,10 @@ const Dump = struct {
79156 error_list: std.ArrayList(Error),
80157 error_map: ErrorMap,
81158
159 const TypeMap = std.HashMap(Type, usize, Type.hash, Type.eql);
160 type_list: std.ArrayList(Type),
161 type_map: TypeMap,
162
82163 fn init(allocator: *mem.Allocator) Dump {
83164 return Dump{
84165 .targets = std.ArrayList([]const u8).init(allocator),
......@@ -88,6 +169,8 @@ const Dump = struct {
88169 .node_map = NodeMap.init(allocator),
89170 .error_list = std.ArrayList(Error).init(allocator),
90171 .error_map = ErrorMap.init(allocator),
172 .type_list = std.ArrayList(Type).init(allocator),
173 .type_map = TypeMap.init(allocator),
91174 };
92175 }
93176
......@@ -165,6 +248,66 @@ const Dump = struct {
165248 }
166249 try other_error_to_mine.putNoClobber(i, gop.kv.value);
167250 }
251
252 // Merge types. Now it starts to get advanced.
253 // First we identify all the simple types and merge those.
254 // Example: void, type, noreturn
255 // We can also do integers and floats.
256 const other_types = root.Object.get("types").?.value.Array.toSliceConst();
257 var other_types_to_mine = std.AutoHashMap(usize, usize).init(self.a());
258 for (other_types) |other_type_json, i| {
259 const type_kind = jsonObjInt(other_type_json, "kind");
260 switch (type_kind) {
261 fieldIndex(TypeId, "Int").? => {
262 var signed: bool = undefined;
263 var bits: usize = undefined;
264 if (other_type_json.Object.get("i")) |kv| {
265 signed = true;
266 bits = @intCast(usize, kv.value.Integer);
267 } else if (other_type_json.Object.get("u")) |kv| {
268 signed = false;
269 bits = @intCast(usize, kv.value.Integer);
270 } else {
271 unreachable;
272 }
273 const other_type = Type{
274 .Int = Type.Int{
275 .bits = bits,
276 .signed = signed,
277 },
278 };
279 try self.mergeOtherType(other_type, i, &other_types_to_mine);
280 },
281 fieldIndex(TypeId, "Float").? => {
282 const other_type = Type{
283 .Float = jsonObjInt(other_type_json, "bits"),
284 };
285 try self.mergeOtherType(other_type, i, &other_types_to_mine);
286 },
287 else => {},
288 }
289
290 inline for (simple_types) |simple_type_name| {
291 if (type_kind == std.meta.fieldIndex(builtin.TypeId, simple_type_name).?) {
292 const other_type = @unionInit(Type, simple_type_name, {});
293 try self.mergeOtherType(other_type, i, &other_types_to_mine);
294 }
295 }
296 }
297 }
298
299 fn mergeOtherType(
300 self: *Dump,
301 other_type: Type,
302 other_type_index: usize,
303 other_types_to_mine: *std.AutoHashMap(usize, usize),
304 ) !void {
305 const gop = try self.type_map.getOrPut(other_type);
306 if (!gop.found_existing) {
307 gop.kv.value = self.type_list.len;
308 try self.type_list.append(other_type);
309 }
310 try other_types_to_mine.putNoClobber(other_type_index, gop.kv.value);
168311 }
169312
170313 fn render(self: *Dump, stream: var) !void {
......@@ -204,6 +347,36 @@ const Dump = struct {
204347
205348 try jw.endObject();
206349
350 try jw.objectField("types");
351 try jw.beginArray();
352 for (self.type_list.toSliceConst()) |t| {
353 try jw.arrayElem();
354 try jw.beginObject();
355
356 try jw.objectField("kind");
357 try jw.emitNumber(@enumToInt(builtin.TypeId(t)));
358
359 switch (t) {
360 .Int => |int| {
361 if (int.signed) {
362 try jw.objectField("i");
363 } else {
364 try jw.objectField("u");
365 }
366 try jw.emitNumber(int.bits);
367 },
368 .Float => |bits| {
369 try jw.objectField("bits");
370 try jw.emitNumber(bits);
371 },
372
373 else => {},
374 }
375
376 try jw.endObject();
377 }
378 try jw.endArray();
379
207380 try jw.objectField("errors");
208381 try jw.beginArray();
209382 for (self.error_list.toSliceConst()) |zig_error| {