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...@@ -36,7 +36,8 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
36 size: usize,36 size: usize,
37 max_distance_from_start_index: usize,37 max_distance_from_start_index: usize,
38 allocator: *Allocator,38 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.
40 modification_count: debug_u32,41 modification_count: debug_u32,
4142
42 const Self = @This();43 const Self = @This();
lib/std/meta.zig+10
...@@ -542,3 +542,13 @@ pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {...@@ -542,3 +542,13 @@ pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {
542 }542 }
543 return error.InvalidEnumTag;543 return error.InvalidEnumTag;
544}544}
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 @@...@@ -104,6 +104,16 @@
104 background-color: #FFBB4D;104 background-color: #FFBB4D;
105 color: #000;105 color: #000;
106 }106 }
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 }
107 #logo {117 #logo {
108 width: 8em;118 width: 8em;
109 padding: 0.5em 1em;119 padding: 0.5em 1em;
...@@ -289,7 +299,6 @@...@@ -289,7 +299,6 @@
289 <pre id="fnProtoCode"></pre>299 <pre id="fnProtoCode"></pre>
290 </div>300 </div>
291 <h1 id="hdrName" class="hidden"></h1>301 <h1 id="hdrName" class="hidden"></h1>
292 <div id="fnExamples" class="hidden"></div>
293 <div id="fnNoExamples" class="hidden">302 <div id="fnNoExamples" class="hidden">
294 <p>This function is not tested or referenced.</p>303 <p>This function is not tested or referenced.</p>
295 </div>304 </div>
...@@ -357,6 +366,10 @@...@@ -357,6 +366,10 @@
357 <ul id="listErrSets">366 <ul id="listErrSets">
358 </ul>367 </ul>
359 </div>368 </div>
369 <div id="fnExamples" class="hidden">
370 <h2>Examples</h2>
371 <ul id="listFnExamples"></ul>
372 </div>
360 </section>373 </section>
361 <div id="helpDialog" class="hidden">374 <div id="helpDialog" class="hidden">
362 <h1>Keyboard Shortcuts</h1>375 <h1>Keyboard Shortcuts</h1>
lib/std/special/docs/main.js+230-19
...@@ -26,6 +26,7 @@...@@ -26,6 +26,7 @@
26 var domTableFnErrors = document.getElementById("tableFnErrors");26 var domTableFnErrors = document.getElementById("tableFnErrors");
27 var domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");27 var domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
28 var domFnExamples = document.getElementById("fnExamples");28 var domFnExamples = document.getElementById("fnExamples");
29 var domListFnExamples = document.getElementById("listFnExamples");
29 var domFnNoExamples = document.getElementById("fnNoExamples");30 var domFnNoExamples = document.getElementById("fnNoExamples");
30 var domDeclNoRef = document.getElementById("declNoRef");31 var domDeclNoRef = document.getElementById("declNoRef");
31 var domSearch = document.getElementById("search");32 var domSearch = document.getElementById("search");
...@@ -64,6 +65,9 @@...@@ -64,6 +65,9 @@
64 declNames: [],65 declNames: [],
65 // these will be all types, except the last one may be a type or a decl66 // these will be all types, except the last one may be a type or a decl
66 declObjs: [],67 declObjs: [],
68
69 // (a, b, c, d) comptime call; result is the value the docs refer to
70 callName: null,
67 };71 };
68 var curNavSearch = "";72 var curNavSearch = "";
69 var curSearchIndex = -1;73 var curSearchIndex = -1;
...@@ -237,20 +241,29 @@...@@ -237,20 +241,29 @@
237 renderErrorSet(errSetType);241 renderErrorSet(errSetType);
238 }242 }
239243
240 var protoSrcIndex;244 var fnObj = zigAnalysis.fns[fnDecl.value];
245 var protoSrcIndex = fnObj.src;
241 if (typeIsGenericFn(fnDecl.type)) {246 if (typeIsGenericFn(fnDecl.type)) {
242 protoSrcIndex = fnDecl.value;
243
244 var instantiations = nodesToFnsMap[protoSrcIndex];247 var instantiations = nodesToFnsMap[protoSrcIndex];
245 var calls = nodesToCallsMap[protoSrcIndex];248 var calls = nodesToCallsMap[protoSrcIndex];
246 if (instantiations == null && calls == null) {249 if (instantiations == null && calls == null) {
247 domFnNoExamples.classList.remove("hidden");250 domFnNoExamples.classList.remove("hidden");
248 } else {251 } else if (calls != null) {
249 // TODO show examples252 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
250 domFnExamples.classList.remove("hidden");262 domFnExamples.classList.remove("hidden");
263 } else if (instantiations != null) {
264 // TODO
251 }265 }
252 } else {266 } else {
253 protoSrcIndex = zigAnalysis.fns[fnDecl.value].src;
254267
255 domFnExamples.classList.add("hidden");268 domFnExamples.classList.add("hidden");
256 domFnNoExamples.classList.add("hidden");269 domFnNoExamples.classList.add("hidden");
...@@ -349,13 +362,15 @@...@@ -349,13 +362,15 @@
349 }362 }
350 }363 }
351364
352 function navLink(pkgNames, declNames) {365 function navLink(pkgNames, declNames, callName) {
353 if (pkgNames.length === 0 && declNames.length === 0) {366 if (pkgNames.length === 0 && declNames.length === 0) {
354 return '#';367 return '#';
355 } else if (declNames.length === 0) {368 } else if (declNames.length === 0 && callName == null) {
356 return '#' + pkgNames.join('.');369 return '#' + pkgNames.join('.');
357 } else {370 } else if (callName == null) {
358 return '#' + pkgNames.join('.') + ';' + declNames.join('.');371 return '#' + pkgNames.join('.') + ';' + declNames.join('.');
372 } else {
373 return '#' + pkgNames.join('.') + ';' + declNames.join('.') + ';' + callName;
359 }374 }
360 }375 }
361376
...@@ -367,6 +382,22 @@...@@ -367,6 +382,22 @@
367 return navLink(curNav.pkgNames, curNav.declNames.concat([childName]));382 return navLink(curNav.pkgNames, curNav.declNames.concat([childName]));
368 }383 }
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
370 function resizeDomListDl(dlDom, desiredLen) {401 function resizeDomListDl(dlDom, desiredLen) {
371 // add the missing dom entries402 // add the missing dom entries
372 var i, ev;403 var i, ev;
...@@ -426,6 +457,40 @@...@@ -426,6 +457,40 @@
426 return (typeObj.len == null) ? pointerSizeEnum.One : typeObj.len;457 return (typeObj.len == null) ? pointerSizeEnum.One : typeObj.len;
427 }458 }
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
429 function typeName(typeObj, wantHtml, wantSubLink, fnDecl, linkFnNameDecl) {494 function typeName(typeObj, wantHtml, wantSubLink, fnDecl, linkFnNameDecl) {
430 switch (typeObj.kind) {495 switch (typeObj.kind) {
431 case typeKinds.Array:496 case typeKinds.Array:
...@@ -544,6 +609,12 @@...@@ -544,6 +609,12 @@
544 } else {609 } else {
545 return "void";610 return "void";
546 }611 }
612 case typeKinds.EnumLiteral:
613 if (wantHtml) {
614 return '<span class="tok-type">(enum literal)</span>';
615 } else {
616 return "(enum literal)";
617 }
547 case typeKinds.NoReturn:618 case typeKinds.NoReturn:
548 if (wantHtml) {619 if (wantHtml) {
549 return '<span class="tok-type">noreturn</span>';620 return '<span class="tok-type">noreturn</span>';
...@@ -592,6 +663,15 @@...@@ -592,6 +663,15 @@
592 }663 }
593 payloadHtml += '(';664 payloadHtml += '(';
594 if (typeObj.args != null) {665 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
595 for (var i = 0; i < typeObj.args.length; i += 1) {675 for (var i = 0; i < typeObj.args.length; i += 1) {
596 if (i != 0) {676 if (i != 0) {
597 payloadHtml += ', ';677 payloadHtml += ', ';
...@@ -599,10 +679,31 @@...@@ -599,10 +679,31 @@
599679
600 var argTypeIndex = typeObj.args[i];680 var argTypeIndex = typeObj.args[i];
601681
602 if (fnDecl != null && zigAnalysis.astNodes[fnDecl.src].fields != null) {682 if (fields != null) {
603 var paramDeclIndex = zigAnalysis.astNodes[fnDecl.src].fields[i];683 var paramNode = zigAnalysis.astNodes[fields[i]];
604 var paramName = zigAnalysis.astNodes[paramDeclIndex].name;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;
606 if (paramName != null) {707 if (paramName != null) {
607 // skip if it matches the type name708 // skip if it matches the type name
608 if (argTypeIndex == null || !shouldSkipParamName(argTypeIndex, paramName)) {709 if (argTypeIndex == null || !shouldSkipParamName(argTypeIndex, paramName)) {
...@@ -611,7 +712,9 @@...@@ -611,7 +712,9 @@
611 }712 }
612 }713 }
613714
614 if (argTypeIndex != null) {715 if (isVarArgs && i === typeObj.args.length - 1) {
716 payloadHtml += '...';
717 } else if (argTypeIndex != null) {
615 payloadHtml += typeIndexName(argTypeIndex, wantHtml, wantSubLink);718 payloadHtml += typeIndexName(argTypeIndex, wantHtml, wantSubLink);
616 } else if (wantHtml) {719 } else if (wantHtml) {
617 payloadHtml += '<span class="tok-kw">var</span>';720 payloadHtml += '<span class="tok-kw">var</span>';
...@@ -690,7 +793,7 @@...@@ -690,7 +793,7 @@
690 }793 }
691794
692 function allCompTimeFnCallsHaveTypeResult(typeIndex, value) {795 function allCompTimeFnCallsHaveTypeResult(typeIndex, value) {
693 var srcIndex = typeIsGenericFn(typeIndex) ? value : zigAnalysis.fns[value].src;796 var srcIndex = zigAnalysis.fns[value].src;
694 var calls = nodesToCallsMap[srcIndex];797 var calls = nodesToCallsMap[srcIndex];
695 if (calls == null) return false;798 if (calls == null) return false;
696 for (var i = 0; i < calls.length; i += 1) {799 for (var i = 0; i < calls.length; i += 1) {
...@@ -700,6 +803,90 @@...@@ -700,6 +803,90 @@
700 return true;803 return true;
701 }804 }
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
703 function renderValue(decl) {890 function renderValue(decl) {
704 domFnProtoCode.innerHTML = '<span class="tok-kw">const</span> ' +891 domFnProtoCode.innerHTML = '<span class="tok-kw">const</span> ' +
705 escapeHtml(decl.name) + ': ' + typeIndexName(decl.type, true, true);892 escapeHtml(decl.name) + ': ' + typeIndexName(decl.type, true, true);
...@@ -733,13 +920,15 @@...@@ -733,13 +920,15 @@
733 var fnsList = [];920 var fnsList = [];
734 var varsList = [];921 var varsList = [];
735 var valsList = [];922 var valsList = [];
923
736 for (var i = 0; i < container.pubDecls.length; i += 1) {924 for (var i = 0; i < container.pubDecls.length; i += 1) {
737 var decl = zigAnalysis.decls[container.pubDecls[i]];925 var decl = zigAnalysis.decls[container.pubDecls[i]];
926
738 if (decl.kind === 'var') {927 if (decl.kind === 'var') {
739 varsList.push(decl);928 varsList.push(decl);
740 continue;929 continue;
741 } else if (decl.kind === 'const' && decl.type != null) {930 } else if (decl.kind === 'const' && decl.type != null) {
742 if (decl.type == typeTypeId) {931 if (decl.type === typeTypeId) {
743 if (typeIsErrSet(decl.value)) {932 if (typeIsErrSet(decl.value)) {
744 errSetsList.push(decl);933 errSetsList.push(decl);
745 } else if (typeIsStructWithNoFields(decl.value)) {934 } else if (typeIsStructWithNoFields(decl.value)) {
...@@ -838,7 +1027,12 @@...@@ -838,7 +1027,12 @@
838 if (container.kind === typeKinds.Enum) {1027 if (container.kind === typeKinds.Enum) {
839 html += ' = <span class="tok-number">' + field + '</span>';1028 html += ' = <span class="tok-number">' + field + '</span>';
840 } else {1029 } 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 }
842 }1036 }
8431037
844 html += ',</pre>';1038 html += ',</pre>';
...@@ -1042,13 +1236,16 @@...@@ -1042,13 +1236,16 @@
1042 return list;1236 return list;
1043 }1237 }
10441238
1045 function declCanRepresentTypeKind(typeKind) {1239 function typeKindIsContainer(typeKind) {
1046 return typeKind === typeKinds.ErrorSet ||1240 return typeKind === typeKinds.Struct ||
1047 typeKind === typeKinds.Struct ||
1048 typeKind === typeKinds.Union ||1241 typeKind === typeKinds.Union ||
1049 typeKind === typeKinds.Enum;1242 typeKind === typeKinds.Enum;
1050 }1243 }
10511244
1245 function declCanRepresentTypeKind(typeKind) {
1246 return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
1247 }
1248
1052 function computeCanonDeclPaths() {1249 function computeCanonDeclPaths() {
1053 var list = new Array(zigAnalysis.decls.length);1250 var list = new Array(zigAnalysis.decls.length);
1054 canonTypeDecls = new Array(zigAnalysis.types.length);1251 canonTypeDecls = new Array(zigAnalysis.types.length);
...@@ -1406,4 +1603,18 @@...@@ -1406,4 +1603,18 @@
1406 function byNameProperty(a, b) {1603 function byNameProperty(a, b) {
1407 return operatorCompare(a.name, b.name);1604 return operatorCompare(a.name, b.name);
1408 }1605 }
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 }
1409})();1620})();
src/dump_analysis.cpp+98-64
...@@ -456,6 +456,10 @@ static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {...@@ -456,6 +456,10 @@ static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) {
456 auto existing_entry = ctx->fn_map.put_unique(fn, fn_id);456 auto existing_entry = ctx->fn_map.put_unique(fn, fn_id);
457 if (existing_entry == nullptr) {457 if (existing_entry == nullptr) {
458 ctx->fn_list.append(fn);458 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);
459 } else {463 } else {
460 fn_id = existing_entry->value;464 fn_id = existing_entry->value;
461 }465 }
...@@ -700,11 +704,7 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,...@@ -700,11 +704,7 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,
700 case ZigTypeIdFn: {704 case ZigTypeIdFn: {
701 if (value->data.x_ptr.special == ConstPtrSpecialFunction) {705 if (value->data.x_ptr.special == ConstPtrSpecialFunction) {
702 ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry;706 ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry;
703 if (val_fn->type_entry->data.fn.is_generic) {707 anal_dump_fn_ref(ctx, val_fn);
704 anal_dump_node_ref(ctx, val_fn->proto_node);
705 } else {
706 anal_dump_fn_ref(ctx, val_fn);
707 }
708 } else {708 } else {
709 jw_null(&ctx->jw);709 jw_null(&ctx->jw);
710 }710 }
...@@ -758,6 +758,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {...@@ -758,6 +758,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
758 switch (ty->id) {758 switch (ty->id) {
759 case ZigTypeIdMetaType:759 case ZigTypeIdMetaType:
760 case ZigTypeIdBool:760 case ZigTypeIdBool:
761 case ZigTypeIdEnumLiteral:
761 break;762 break;
762 case ZigTypeIdStruct: {763 case ZigTypeIdStruct: {
763 if (ty->data.structure.is_slice) {764 if (ty->data.structure.is_slice) {
...@@ -1072,13 +1073,25 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {...@@ -1072,13 +1073,25 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
1072 jw_object_field(jw, "col");1073 jw_object_field(jw, "col");
1073 jw_int(jw, node->column);1074 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
1076 switch (node->type) {1083 switch (node->type) {
1077 case NodeTypeParamDecl:1084 case NodeTypeParamDecl:
1078 doc_comments_buf = &node->data.param_decl.doc_comments;1085 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;
1079 break;1090 break;
1080 case NodeTypeFnProto:1091 case NodeTypeFnProto:
1081 doc_comments_buf = &node->data.fn_proto.doc_comments;1092 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;
1082 break;1095 break;
1083 case NodeTypeVariableDeclaration:1096 case NodeTypeVariableDeclaration:
1084 doc_comments_buf = &node->data.variable_declaration.doc_comments;1097 doc_comments_buf = &node->data.variable_declaration.doc_comments;
...@@ -1088,55 +1101,50 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {...@@ -1088,55 +1101,50 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
1088 break;1101 break;
1089 case NodeTypeStructField:1102 case NodeTypeStructField:
1090 doc_comments_buf = &node->data.struct_field.doc_comments;1103 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;
1091 break;1108 break;
1092 default:1109 default:
1093 doc_comments_buf = nullptr;
1094 break;1110 break;
1095 }1111 }
1112
1096 if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) {1113 if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) {
1097 jw_object_field(jw, "docs");1114 jw_object_field(jw, "docs");
1098 jw_string(jw, buf_ptr(doc_comments_buf));1115 jw_string(jw, buf_ptr(doc_comments_buf));
1099 }1116 }
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 }
1113 if (name_buf != nullptr) {1118 if (name_buf != nullptr) {
1114 jw_object_field(jw, "name");1119 jw_object_field(jw, "name");
1115 jw_string(jw, buf_ptr(name_buf));1120 jw_string(jw, buf_ptr(name_buf));
1116 }1121 }
11171122
1118 const ZigList<AstNode *> *fieldNodes;1123 if (field_nodes != nullptr) {
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) {
1131 jw_object_field(jw, "fields");1124 jw_object_field(jw, "fields");
1132 jw_begin_array(jw);1125 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) {
1134 jw_array_elem(jw);1127 jw_array_elem(jw);
1135 anal_dump_node_ref(ctx, fieldNodes->at(i));1128 anal_dump_node_ref(ctx, field_nodes->at(i));
1136 }1129 }
1137 jw_end_array(jw);1130 jw_end_array(jw);
1138 }1131 }
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
1140 jw_end_object(jw);1148 jw_end_object(jw);
1141}1149}
11421150
...@@ -1235,59 +1243,76 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const...@@ -1235,59 +1243,76 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
1235 jw_object_field(jw, "calls");1243 jw_object_field(jw, "calls");
1236 jw_begin_array(jw);1244 jw_begin_array(jw);
1237 {1245 {
1246 ZigList<ZigVar *> var_stack = {};
1247
1238 auto it = g->memoized_fn_eval_table.entry_iterator();1248 auto it = g->memoized_fn_eval_table.entry_iterator();
1239 for (;;) {1249 for (;;) {
1240 auto *entry = it.next();1250 auto *entry = it.next();
1241 if (!entry)1251 if (!entry)
1242 break;1252 break;
12431253
1244 jw_array_elem(jw);1254 var_stack.resize(0);
1245 jw_begin_object(jw);1255 ZigFn *fn = nullptr;
1246
1247 jw_object_field(jw, "args");
1248 jw_begin_object(jw);
12491256
1250 Scope *scope = entry->key;1257 Scope *scope = entry->key;
1251 while (scope != nullptr) {1258 while (scope != nullptr) {
1252 if (scope->id == ScopeIdVarDecl) {1259 if (scope->id == ScopeIdVarDecl) {
1253 ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;1260 ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
1254 jw_object_field(jw, var->name);1261 var_stack.append(var);
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 } else if (scope->id == ScopeIdFnDef) {1262 } 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");1295 while (var_stack.length != 0) {
1265 ZigFn *fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry;1296 ZigVar *var = var_stack.pop();
1266 anal_dump_fn_ref(&ctx, fn);
12671297
1268 ConstExprValue *result = entry->value;1298 jw_array_elem(jw);
1269 jw_object_field(jw, "result");
1270 jw_begin_object(jw);1299 jw_begin_object(jw);
1300
1271 jw_object_field(jw, "type");1301 jw_object_field(jw, "type");
1272 anal_dump_type_ref(&ctx, result->type);1302 anal_dump_type_ref(&ctx, var->var_type);
1303
1273 jw_object_field(jw, "value");1304 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
1275 jw_end_object(jw);1307 jw_end_object(jw);
1276 break;
1277 }1308 }
1278 scope = scope->parent;1309 jw_end_array(jw);
1279 }1310 }
1311
1280 jw_end_object(jw);1312 jw_end_object(jw);
1281 }1313 }
1282 }
1283 jw_end_array(jw);
12841314
1285 jw_object_field(jw, "fns");1315 var_stack.deinit();
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);
1291 }1316 }
1292 jw_end_array(jw);1317 jw_end_array(jw);
12931318
...@@ -1315,6 +1340,15 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const...@@ -1315,6 +1340,15 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
1315 }1340 }
1316 jw_end_array(jw);1341 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
1318 jw_object_field(jw, "errors");1352 jw_object_field(jw, "errors");
1319 jw_begin_array(jw);1353 jw_begin_array(jw);
1320 for (uint32_t i = 0; i < ctx.err_list.length; i += 1) {1354 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");...@@ -2,6 +2,8 @@ const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const json = std.json;3const json = std.json;
4const mem = std.mem;4const mem = std.mem;
5const fieldIndex = std.meta.fieldIndex;
6const TypeId = builtin.TypeId;
57
6pub fn main() anyerror!void {8pub fn main() anyerror!void {
7 var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);9 var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
...@@ -61,6 +63,81 @@ const Error = struct {...@@ -61,6 +63,81 @@ const Error = struct {
61 }63 }
62};64};
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
64const Dump = struct {141const Dump = struct {
65 zig_id: ?[]const u8 = null,142 zig_id: ?[]const u8 = null,
66 zig_version: ?[]const u8 = null,143 zig_version: ?[]const u8 = null,
...@@ -79,6 +156,10 @@ const Dump = struct {...@@ -79,6 +156,10 @@ const Dump = struct {
79 error_list: std.ArrayList(Error),156 error_list: std.ArrayList(Error),
80 error_map: ErrorMap,157 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
82 fn init(allocator: *mem.Allocator) Dump {163 fn init(allocator: *mem.Allocator) Dump {
83 return Dump{164 return Dump{
84 .targets = std.ArrayList([]const u8).init(allocator),165 .targets = std.ArrayList([]const u8).init(allocator),
...@@ -88,6 +169,8 @@ const Dump = struct {...@@ -88,6 +169,8 @@ const Dump = struct {
88 .node_map = NodeMap.init(allocator),169 .node_map = NodeMap.init(allocator),
89 .error_list = std.ArrayList(Error).init(allocator),170 .error_list = std.ArrayList(Error).init(allocator),
90 .error_map = ErrorMap.init(allocator),171 .error_map = ErrorMap.init(allocator),
172 .type_list = std.ArrayList(Type).init(allocator),
173 .type_map = TypeMap.init(allocator),
91 };174 };
92 }175 }
93176
...@@ -165,6 +248,66 @@ const Dump = struct {...@@ -165,6 +248,66 @@ const Dump = struct {
165 }248 }
166 try other_error_to_mine.putNoClobber(i, gop.kv.value);249 try other_error_to_mine.putNoClobber(i, gop.kv.value);
167 }250 }
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);
168 }311 }
169312
170 fn render(self: *Dump, stream: var) !void {313 fn render(self: *Dump, stream: var) !void {
...@@ -204,6 +347,36 @@ const Dump = struct {...@@ -204,6 +347,36 @@ const Dump = struct {
204347
205 try jw.endObject();348 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
207 try jw.objectField("errors");380 try jw.objectField("errors");
208 try jw.beginArray();381 try jw.beginArray();
209 for (self.error_list.toSliceConst()) |zig_error| {382 for (self.error_list.toSliceConst()) |zig_error| {