authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-05-18 18:55:13+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 19:10:11-07:00
logcf685c1132113b867f1476f4cd9d7a47d96a4782
tree2c82093069b8ff86c8835ceb94c6b0d705bc2589
parent0339e1c7d4fc3cc2144f4f5aae335b16fa808531

autodoc: collect type information for some expressions


2 files changed, 691 insertions(+), 625 deletions(-)

lib/docs/main.js+347-300
......@@ -494,6 +494,8 @@ var zigAnalysis;
494494 * @return {WalkResult}
495495 */
496496 function typeOfDecl(decl){
497 return decl.value.typeRef;
498
497499 let i = 0;
498500 while(i < 1000) {
499501 i += 1;
......@@ -502,6 +504,13 @@ var zigAnalysis;
502504 return /** @type {WalkResult} */({ type: typeTypeId });
503505 }
504506
507// if ("string" in decl.value) {
508// return /** @type {WalkResult} */({ type: {
509// kind: typeKinds.Pointer,
510// size: pointerSizeEnum.One,
511// child: });
512// }
513
505514 if ("refPath" in decl.value) {
506515 decl = /** @type {Decl} */({
507516 value: decl.value.refPath[decl.value.refPath.length -1]
......@@ -1009,6 +1018,327 @@ var zigAnalysis;
10091018 }
10101019 }
10111020
1021 /**
1022 * @typedef {{
1023 wantHtml: boolean,
1024 }} RenderWrOptions
1025 * @param {WalkResult} wr,
1026 * @param {RenderWrOptions} opts,
1027 * @return {string}
1028 */
1029
1030 function exprName(expr, opts) {
1031 const activeField = Object.keys(expr)[0];
1032 switch (activeField) {
1033 case "int": {
1034 return "" + expr.int;
1035 }
1036 case "string": {
1037 return "\"" + escapeHtml(expr.string) + "\"";
1038 }
1039
1040 case "anytype": {
1041 return "anytype";
1042 }
1043
1044 case "this":{
1045 return "this";
1046 }
1047
1048 case "type": {
1049 let name = "";
1050 const typeObj = zigAnalysis.types[expr.type];
1051 switch (typeObj.kind) {
1052 case typeKinds.Array:
1053 {
1054 let arrayObj = /** @type {ArrayType} */(typeObj);
1055 let name = "[";
1056 let lenName = exprName(arrayObj.len, opts);
1057 if (opts.wantHtml) {
1058 name += '<span class="tok-number">' + lenName + '</span>';
1059 } else {
1060 name += lenName;
1061 }
1062 name += "]";
1063 name += exprName(arrayObj.child, opts);
1064 return name;
1065 }
1066 case typeKinds.Optional:
1067
1068 return "?" + typeValueName(/**@type {OptionalType} */(typeObj).child, wantHtml, wantSubLink, fnDecl, linkFnNameDecl);
1069 case typeKinds.Pointer:
1070 {
1071 let ptrObj = /** @type {PointerType} */(typeObj);
1072 let name = "";
1073 switch (ptrObj.size) {
1074 default:
1075 console.log("TODO: implement unhandled pointer size case");
1076 case pointerSizeEnum.One:
1077 name += "*";
1078 break;
1079 case pointerSizeEnum.Many:
1080 name += "[*]";
1081 break;
1082 case pointerSizeEnum.Slice:
1083 name += "[]";
1084 break;
1085 case pointerSizeEnum.C:
1086 name += "[*c]";
1087 break;
1088 }
1089 if (ptrObj['const']) {
1090 if (opts.wantHtml) {
1091 name += '<span class="tok-kw">const</span> ';
1092 } else {
1093 name += "const ";
1094 }
1095 }
1096 if (ptrObj['volatile']) {
1097 if (opts.wantHtml) {
1098 name += '<span class="tok-kw">volatile</span> ';
1099 } else {
1100 name += "volatile ";
1101 }
1102 }
1103 if (ptrObj.align != null) {
1104 if (opts.wantHtml) {
1105 name += '<span class="tok-kw">align</span>(';
1106 } else {
1107 name += "align(";
1108 }
1109 if (opts.wantHtml) {
1110 name += '<span class="tok-number">' + ptrObj.align + '</span>';
1111 } else {
1112 name += ptrObj.align;
1113 }
1114 if (ptrObj.hostIntBytes != null) {
1115 name += ":";
1116 if (opts.wantHtml) {
1117 name += '<span class="tok-number">' + ptrObj.bitOffsetInHost + '</span>';
1118 } else {
1119 name += ptrObj.bitOffsetInHost;
1120 }
1121 name += ":";
1122 if (opts.wantHtml) {
1123 name += '<span class="tok-number">' + ptrObj.hostIntBytes + '</span>';
1124 } else {
1125 name += ptrObj.hostIntBytes;
1126 }
1127 }
1128 name += ") ";
1129 }
1130 //name += typeValueName(ptrObj.child, wantHtml, wantSubLink, null);
1131 name += exprName(ptrObj.child, opts);
1132 return name;
1133 }
1134 case typeKinds.Float:
1135 {
1136 let floatObj = /** @type {NumberType} */ (typeObj);
1137
1138 if (wantHtml) {
1139 return '<span class="tok-type">' + floatObj.name + '</span>';
1140 } else {
1141 return floatObj.name;
1142 }
1143 }
1144 case typeKinds.Int:
1145 {
1146 let intObj = /** @type {NumberType} */(typeObj);
1147 let name = intObj.name;
1148 if (opts.wantHtml) {
1149 return '<span class="tok-type">' + name + '</span>';
1150 } else {
1151 return name;
1152 }
1153 }
1154 case typeKinds.ComptimeInt:
1155 if (wantHtml) {
1156 return '<span class="tok-type">comptime_int</span>';
1157 } else {
1158 return "comptime_int";
1159 }
1160 case typeKinds.ComptimeFloat:
1161 if (wantHtml) {
1162 return '<span class="tok-type">comptime_float</span>';
1163 } else {
1164 return "comptime_float";
1165 }
1166 case typeKinds.Type:
1167 if (wantHtml) {
1168 return '<span class="tok-type">type</span>';
1169 } else {
1170 return "type";
1171 }
1172 case typeKinds.Bool:
1173 if (wantHtml) {
1174 return '<span class="tok-type">bool</span>';
1175 } else {
1176 return "bool";
1177 }
1178 case typeKinds.Void:
1179 if (wantHtml) {
1180 return '<span class="tok-type">void</span>';
1181 } else {
1182 return "void";
1183 }
1184 case typeKinds.EnumLiteral:
1185 if (wantHtml) {
1186 return '<span class="tok-type">(enum literal)</span>';
1187 } else {
1188 return "(enum literal)";
1189 }
1190 case typeKinds.NoReturn:
1191 if (wantHtml) {
1192 return '<span class="tok-type">noreturn</span>';
1193 } else {
1194 return "noreturn";
1195 }
1196 case typeKinds.ErrorSet:
1197 {
1198 let errSetObj = /** @type {ErrSetType} */(typeObj);
1199 if (errSetObj.fields == null) {
1200 if (wantHtml) {
1201 return '<span class="tok-type">anyerror</span>';
1202 } else {
1203 return "anyerror";
1204 }
1205 } else {
1206 throw "TODO";
1207 // if (wantHtml) {
1208 // return escapeHtml(typeObj.name);
1209 // } else {
1210 // return typeObj.name;
1211 // }
1212 }
1213 }
1214 case typeKinds.ErrorUnion:
1215 {
1216 throw "TODO";
1217 // TODO: implement error union printing assuming that both
1218 // payload and error union are walk results!
1219 // let errUnionObj = /** @type {ErrUnionType} */(typeObj);
1220 // let errSetTypeObj = /** @type {ErrSetType} */ (zigAnalysis.types[errUnionObj.err]);
1221 // let payloadHtml = typeValueName(errUnionObj.payload, wantHtml, wantSubLink, null);
1222 // if (fnDecl != null && errSetTypeObj.fn === fnDecl.value.type) {
1223 // // function index parameter supplied and this is the inferred error set of it
1224 // return "!" + payloadHtml;
1225 // } else {
1226 // return typeValueName(errUnionObj.err, wantHtml, wantSubLink, null) + "!" + payloadHtml;
1227 // }
1228 }
1229 case typeKinds.Fn:
1230 {
1231 let fnObj = /** @type {Fn} */(typeObj);
1232 let payloadHtml = "";
1233 if (wantHtml) {
1234 payloadHtml += '<span class="tok-kw">fn</span>';
1235 if (fnDecl != null) {
1236 payloadHtml += ' <span class="tok-fn">';
1237 if (linkFnNameDecl != null) {
1238 payloadHtml += '<a href="' + linkFnNameDecl + '">' +
1239 escapeHtml(fnDecl.name) + '</a>';
1240 } else {
1241 payloadHtml += escapeHtml(fnDecl.name);
1242 }
1243 payloadHtml += '</span>';
1244 }
1245 } else {
1246 payloadHtml += 'fn'
1247 }
1248 payloadHtml += '(';
1249 if (fnObj.params) {
1250 let fields = null;
1251 let isVarArgs = false;
1252 let fnNode = zigAnalysis.astNodes[fnObj.src];
1253 fields = fnNode.fields;
1254 isVarArgs = fnNode.varArgs;
1255
1256 for (let i = 0; i < fnObj.params.length; i += 1) {
1257 if (i != 0) {
1258 payloadHtml += ', ';
1259 }
1260
1261 let value = fnObj.params[i];
1262 let paramValue = resolveValue(value);
1263
1264 if (fields != null) {
1265 let paramNode = zigAnalysis.astNodes[fields[i]];
1266
1267 if (paramNode.varArgs) {
1268 payloadHtml += '...';
1269 continue;
1270 }
1271
1272 if (paramNode.noalias) {
1273 if (wantHtml) {
1274 payloadHtml += '<span class="tok-kw">noalias</span> ';
1275 } else {
1276 payloadHtml += 'noalias ';
1277 }
1278 }
1279
1280 if (paramNode.comptime) {
1281 if (wantHtml) {
1282 payloadHtml += '<span class="tok-kw">comptime</span> ';
1283 } else {
1284 payloadHtml += 'comptime ';
1285 }
1286 }
1287
1288 let paramName = paramNode.name;
1289 if (paramName != null) {
1290 // skip if it matches the type name
1291 if (!shouldSkipParamName(paramValue, paramName)) {
1292 payloadHtml += paramName + ': ';
1293 }
1294 }
1295 }
1296
1297 if (isVarArgs && i === fnObj.params.length - 1) {
1298 payloadHtml += '...';
1299 } else if ("refPath" in value) {
1300 payloadHtml += '<a href="">';
1301 payloadHtml += '<span class="tok-kw" style="color:lightblue;">[Ref Path]</span>';
1302 payloadHtml += '</a>';
1303
1304 } else if ("type" in value) {
1305 let name = typeValueName(value, false, false, fnDecl, linkFnNameDecl);
1306 payloadHtml += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
1307 } else if ("comptimeExpr" in value) {
1308 payloadHtml += '<span class="tok-kw">[ComptimeExpr]</span>';
1309 } else if (wantHtml) {
1310 payloadHtml += '<span class="tok-kw">var</span>';
1311 } else {
1312 payloadHtml += 'var';
1313 }
1314 }
1315 }
1316
1317 payloadHtml += ') ';
1318 if (fnObj.ret != null) {
1319 payloadHtml += typeValueName(fnObj.ret, wantHtml, wantSubLink, fnDecl);
1320 } else if (wantHtml) {
1321 payloadHtml += '<span class="tok-kw">anytype</span>';
1322 } else {
1323 payloadHtml += 'anytype';
1324 }
1325 return payloadHtml;
1326 }
1327 default:
1328 throw "TODO";
1329 // if (wantHtml) {
1330 // return escapeHtml(typeObj.name);
1331 // } else {
1332 // return typeObj.name;
1333 // }
1334 }
1335 }
1336
1337 default: throw "oh no";
1338 }
1339 }
1340
1341
10121342 /**
10131343 * @param {WalkResult} typeValue,
10141344 * @param {boolean} wantHtml,
......@@ -1174,289 +1504,6 @@ var zigAnalysis;
11741504 * @return {string}
11751505 */
11761506 function typeName(typeObj, wantHtml, wantSubLink, fnDecl, linkFnNameDecl) {
1177 switch (typeObj.kind) {
1178 case typeKinds.Array:
1179 {
1180 let arrayObj = /** @type {ArrayType} */(typeObj);
1181 let name = "[";
1182 let lenName = typeValueName(arrayObj.len, wantHtml, wantSubLink);
1183 if (wantHtml) {
1184 name += '<span class="tok-number">' + lenName + '</span>';
1185 } else {
1186 name += lenName;
1187 }
1188 name += "]";
1189 name += typeValueName(arrayObj.child, wantHtml, wantSubLink, null);
1190 return name;
1191 }
1192 case typeKinds.Optional:
1193
1194 return "?" + typeValueName(/**@type {OptionalType} */(typeObj).child, wantHtml, wantSubLink, fnDecl, linkFnNameDecl);
1195 case typeKinds.Pointer:
1196 {
1197 let ptrObj = /** @type {PointerType} */(typeObj);
1198 let name = "";
1199 switch (ptrObj.size) {
1200 default:
1201 console.log("TODO: implement unhandled pointer size case");
1202 case pointerSizeEnum.One:
1203 name += "*";
1204 break;
1205 case pointerSizeEnum.Many:
1206 name += "[*]";
1207 break;
1208 case pointerSizeEnum.Slice:
1209 name += "[]";
1210 break;
1211 case pointerSizeEnum.C:
1212 name += "[*c]";
1213 break;
1214 }
1215 if (ptrObj['const']) {
1216 if (wantHtml) {
1217 name += '<span class="tok-kw">const</span> ';
1218 } else {
1219 name += "const ";
1220 }
1221 }
1222 if (ptrObj['volatile']) {
1223 if (wantHtml) {
1224 name += '<span class="tok-kw">volatile</span> ';
1225 } else {
1226 name += "volatile ";
1227 }
1228 }
1229 if (ptrObj.align != null) {
1230 if (wantHtml) {
1231 name += '<span class="tok-kw">align</span>(';
1232 } else {
1233 name += "align(";
1234 }
1235 if (wantHtml) {
1236 name += '<span class="tok-number">' + ptrObj.align + '</span>';
1237 } else {
1238 name += ptrObj.align;
1239 }
1240 if (ptrObj.hostIntBytes != null) {
1241 name += ":";
1242 if (wantHtml) {
1243 name += '<span class="tok-number">' + ptrObj.bitOffsetInHost + '</span>';
1244 } else {
1245 name += ptrObj.bitOffsetInHost;
1246 }
1247 name += ":";
1248 if (wantHtml) {
1249 name += '<span class="tok-number">' + ptrObj.hostIntBytes + '</span>';
1250 } else {
1251 name += ptrObj.hostIntBytes;
1252 }
1253 }
1254 name += ") ";
1255 }
1256 name += typeValueName(ptrObj.child, wantHtml, wantSubLink, null);
1257 return name;
1258 }
1259 case typeKinds.Float:
1260 {
1261 let floatObj = /** @type {NumberType} */ (typeObj);
1262
1263 if (wantHtml) {
1264 return '<span class="tok-type">' + floatObj.name + '</span>';
1265 } else {
1266 return floatObj.name;
1267 }
1268 }
1269 case typeKinds.Int:
1270 {
1271 let intObj = /** @type {NumberType} */(typeObj);
1272 let name = intObj.name;
1273 if (wantHtml) {
1274 return '<span class="tok-type">' + name + '</span>';
1275 } else {
1276 return name;
1277 }
1278 }
1279 case typeKinds.ComptimeInt:
1280 if (wantHtml) {
1281 return '<span class="tok-type">comptime_int</span>';
1282 } else {
1283 return "comptime_int";
1284 }
1285 case typeKinds.ComptimeFloat:
1286 if (wantHtml) {
1287 return '<span class="tok-type">comptime_float</span>';
1288 } else {
1289 return "comptime_float";
1290 }
1291 case typeKinds.Type:
1292 if (wantHtml) {
1293 return '<span class="tok-type">type</span>';
1294 } else {
1295 return "type";
1296 }
1297 case typeKinds.Bool:
1298 if (wantHtml) {
1299 return '<span class="tok-type">bool</span>';
1300 } else {
1301 return "bool";
1302 }
1303 case typeKinds.Void:
1304 if (wantHtml) {
1305 return '<span class="tok-type">void</span>';
1306 } else {
1307 return "void";
1308 }
1309 case typeKinds.EnumLiteral:
1310 if (wantHtml) {
1311 return '<span class="tok-type">(enum literal)</span>';
1312 } else {
1313 return "(enum literal)";
1314 }
1315 case typeKinds.NoReturn:
1316 if (wantHtml) {
1317 return '<span class="tok-type">noreturn</span>';
1318 } else {
1319 return "noreturn";
1320 }
1321 case typeKinds.ErrorSet:
1322 {
1323 let errSetObj = /** @type {ErrSetType} */(typeObj);
1324 if (errSetObj.fields == null) {
1325 if (wantHtml) {
1326 return '<span class="tok-type">anyerror</span>';
1327 } else {
1328 return "anyerror";
1329 }
1330 } else {
1331 throw "TODO";
1332 // if (wantHtml) {
1333 // return escapeHtml(typeObj.name);
1334 // } else {
1335 // return typeObj.name;
1336 // }
1337 }
1338 }
1339 case typeKinds.ErrorUnion:
1340 {
1341 throw "TODO";
1342 // TODO: implement error union printing assuming that both
1343 // payload and error union are walk results!
1344 // let errUnionObj = /** @type {ErrUnionType} */(typeObj);
1345 // let errSetTypeObj = /** @type {ErrSetType} */ (zigAnalysis.types[errUnionObj.err]);
1346 // let payloadHtml = typeValueName(errUnionObj.payload, wantHtml, wantSubLink, null);
1347 // if (fnDecl != null && errSetTypeObj.fn === fnDecl.value.type) {
1348 // // function index parameter supplied and this is the inferred error set of it
1349 // return "!" + payloadHtml;
1350 // } else {
1351 // return typeValueName(errUnionObj.err, wantHtml, wantSubLink, null) + "!" + payloadHtml;
1352 // }
1353 }
1354 case typeKinds.Fn:
1355 {
1356 let fnObj = /** @type {Fn} */(typeObj);
1357 let payloadHtml = "";
1358 if (wantHtml) {
1359 payloadHtml += '<span class="tok-kw">fn</span>';
1360 if (fnDecl != null) {
1361 payloadHtml += ' <span class="tok-fn">';
1362 if (linkFnNameDecl != null) {
1363 payloadHtml += '<a href="' + linkFnNameDecl + '">' +
1364 escapeHtml(fnDecl.name) + '</a>';
1365 } else {
1366 payloadHtml += escapeHtml(fnDecl.name);
1367 }
1368 payloadHtml += '</span>';
1369 }
1370 } else {
1371 payloadHtml += 'fn'
1372 }
1373 payloadHtml += '(';
1374 if (fnObj.params) {
1375 let fields = null;
1376 let isVarArgs = false;
1377 let fnNode = zigAnalysis.astNodes[fnObj.src];
1378 fields = fnNode.fields;
1379 isVarArgs = fnNode.varArgs;
1380
1381 for (let i = 0; i < fnObj.params.length; i += 1) {
1382 if (i != 0) {
1383 payloadHtml += ', ';
1384 }
1385
1386 let value = fnObj.params[i];
1387 let paramValue = resolveValue(value);
1388
1389 if (fields != null) {
1390 let paramNode = zigAnalysis.astNodes[fields[i]];
1391
1392 if (paramNode.varArgs) {
1393 payloadHtml += '...';
1394 continue;
1395 }
1396
1397 if (paramNode.noalias) {
1398 if (wantHtml) {
1399 payloadHtml += '<span class="tok-kw">noalias</span> ';
1400 } else {
1401 payloadHtml += 'noalias ';
1402 }
1403 }
1404
1405 if (paramNode.comptime) {
1406 if (wantHtml) {
1407 payloadHtml += '<span class="tok-kw">comptime</span> ';
1408 } else {
1409 payloadHtml += 'comptime ';
1410 }
1411 }
1412
1413 let paramName = paramNode.name;
1414 if (paramName != null) {
1415 // skip if it matches the type name
1416 if (!shouldSkipParamName(paramValue, paramName)) {
1417 payloadHtml += paramName + ': ';
1418 }
1419 }
1420 }
1421
1422 if (isVarArgs && i === fnObj.params.length - 1) {
1423 payloadHtml += '...';
1424 } else if ("refPath" in value) {
1425 payloadHtml += '<a href="">';
1426 payloadHtml += '<span class="tok-kw" style="color:lightblue;">[Ref Path]</span>';
1427 payloadHtml += '</a>';
1428
1429 } else if ("type" in value) {
1430 let name = typeValueName(value, false, false, fnDecl, linkFnNameDecl);
1431 payloadHtml += '<span class="tok-kw">' + escapeHtml(name) + '</span>';
1432 } else if ("comptimeExpr" in value) {
1433 payloadHtml += '<span class="tok-kw">[ComptimeExpr]</span>';
1434 } else if (wantHtml) {
1435 payloadHtml += '<span class="tok-kw">var</span>';
1436 } else {
1437 payloadHtml += 'var';
1438 }
1439 }
1440 }
1441
1442 payloadHtml += ') ';
1443 if (fnObj.ret != null) {
1444 payloadHtml += typeValueName(fnObj.ret, wantHtml, wantSubLink, fnDecl);
1445 } else if (wantHtml) {
1446 payloadHtml += '<span class="tok-kw">anytype</span>';
1447 } else {
1448 payloadHtml += 'anytype';
1449 }
1450 return payloadHtml;
1451 }
1452 default:
1453 throw "TODO";
1454 // if (wantHtml) {
1455 // return escapeHtml(typeObj.name);
1456 // } else {
1457 // return typeObj.name;
1458 // }
1459 }
14601507 }
14611508
14621509 /** @param {Type} typeObj */
......@@ -1607,25 +1654,25 @@ var zigAnalysis;
16071654 /** @param {Decl} decl */
16081655 function renderValue(decl) {
16091656
1610 let declTypeRef = typeOfDecl(decl);
1611 let declValueText = "";
1612 switch(Object.keys(decl.value)[0]) {
1613 case "int":
1614 declValueText += /** @type {{int: {value: number}}} */(decl.value).int.value;
1615 break;
1616 case "float":
1617 declValueText += /** @type {{float: {value: number}}} */(decl.value).float.value;
1618 break;
1619 case "comptimeExpr":
1620 declValueText += "[ComptimeExpr]";
1621 break;
1622 default:
1623 console.log("TODO: renderValue for ", Object.keys(decl.value)[0]);
1624 declValueText += "#TODO#";
1625 }
1657 let declTypeRef = decl.value.typeRef;
1658 let declValueText = exprName(decl.value.expr);
1659// switch(Object.keys(decl.value)[0]) {
1660// case "int":
1661// declValueText += /** @type {{int: {value: number}}} */(decl.value).int.value;
1662// break;
1663// case "float":
1664// declValueText += /** @type {{float: {value: number}}} */(decl.value).float.value;
1665// break;
1666// case "comptimeExpr":
1667// declValueText += "[ComptimeExpr]";
1668// break;
1669// default:
1670// console.log("TODO: renderValue for ", Object.keys(decl.value)[0]);
1671// declValueText += "#TODO#";
1672// }
16261673
16271674 domFnProtoCode.innerHTML = '<span class="tok-kw">const</span> ' +
1628 escapeHtml(decl.name) + ': ' + typeValueName(declTypeRef, true, true) +
1675 escapeHtml(decl.name) + ': ' + exprName(declTypeRef, {wantHtml: true}) +
16291676 " = " + declValueText;
16301677
16311678 let docs = zigAnalysis.astNodes[decl.src].docs;
src/Autodoc.zig+344-325
......@@ -17,13 +17,14 @@ files: std.AutoHashMapUnmanaged(*File, usize) = .{},
1717calls: std.ArrayListUnmanaged(DocData.Call) = .{},
1818types: std.ArrayListUnmanaged(DocData.Type) = .{},
1919decls: std.ArrayListUnmanaged(DocData.Decl) = .{},
20exprs: std.ArrayListUnmanaged(DocData.Expr) = .{},
2021ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{},
2122comptime_exprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{},
2223
2324// These fields hold temporary state of the analysis process
2425// and are mainly used by the decl path resolving algorithm.
2526pending_ref_paths: std.AutoHashMapUnmanaged(
26 *DocData.WalkResult, // pointer to declpath tail end (ie `&decl_path[decl_path.len - 1]`)
27 *DocData.Expr, // pointer to declpath tail end (ie `&decl_path[decl_path.len - 1]`)
2728 std.ArrayListUnmanaged(RefPathResumeInfo),
2829) = .{},
2930ref_paths_pending_on_decls: std.AutoHashMapUnmanaged(
......@@ -37,7 +38,7 @@ ref_paths_pending_on_types: std.AutoHashMapUnmanaged(
3738
3839const RefPathResumeInfo = struct {
3940 file: *File,
40 ref_path: []DocData.WalkResult,
41 ref_path: []DocData.Expr,
4142};
4243
4344var arena_allocator: std.heap.ArenaAllocator = undefined;
......@@ -80,7 +81,6 @@ pub fn generateZirData(self: *Autodoc) !void {
8081 .ComptimeExpr = .{ .name = "ComptimeExpr" },
8182 });
8283
83 var tr = DocData.WalkResult{ .type = @enumToInt(Ref.usize_type) };
8484 // this skipts Ref.none but it's ok becuse we replaced it with ComptimeExpr
8585 var i: u32 = 1;
8686 while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) {
......@@ -96,7 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void {
9696 .Array = .{
9797 .len = .{
9898 .int = .{
99 .typeRef = &tr,
10099 .value = 1,
101100 .negated = false,
102101 },
......@@ -163,7 +162,7 @@ pub fn generateZirData(self: *Autodoc) !void {
163162 var root_scope = Scope{ .parent = null, .enclosing_type = main_type_index };
164163 try self.ast_nodes.append(self.arena, .{ .name = "(root)" });
165164 try self.files.put(self.arena, file, main_type_index);
166 _ = try self.walkInstruction(file, &root_scope, Zir.main_struct_inst);
165 _ = try self.walkInstruction(file, &root_scope, Zir.main_struct_inst, false);
167166
168167 if (self.ref_paths_pending_on_decls.count() > 0) {
169168 @panic("some decl paths were never fully analized (pending on decls)");
......@@ -182,6 +181,7 @@ pub fn generateZirData(self: *Autodoc) !void {
182181 .calls = self.calls.items,
183182 .types = self.types.items,
184183 .decls = self.decls.items,
184 .exprs = self.exprs.items,
185185 .astNodes = self.ast_nodes.items,
186186 .comptimeExprs = self.comptime_exprs.items,
187187 };
......@@ -305,11 +305,12 @@ const DocData = struct {
305305 },
306306 types: []Type,
307307 decls: []Decl,
308 exprs: []Expr,
308309 comptimeExprs: []ComptimeExpr,
309310 const Call = struct {
310 func: WalkResult,
311 args: []WalkResult,
312 ret: WalkResult,
311 func: Expr,
312 args: []Expr,
313 ret: Expr,
313314 };
314315
315316 /// All the type "families" as described by `std.builtin.TypeId`
......@@ -340,7 +341,6 @@ const DocData = struct {
340341
341342 const ComptimeExpr = struct {
342343 code: []const u8,
343 typeRef: WalkResult,
344344 };
345345 const Package = struct {
346346 name: []const u8 = "root",
......@@ -356,7 +356,6 @@ const DocData = struct {
356356 kind: []const u8,
357357 isTest: bool,
358358 src: usize, // index into astNodes
359 // typeRef: TypeRef,
360359 value: WalkResult,
361360 // The index in astNodes of the `test declname { }` node
362361 decltest: ?usize = null,
......@@ -383,18 +382,18 @@ const DocData = struct {
383382 Float: struct { name: []const u8 },
384383 Pointer: struct {
385384 size: std.builtin.TypeInfo.Pointer.Size,
386 child: WalkResult,
385 child: Expr,
387386 },
388387 Array: struct {
389 len: WalkResult,
390 child: WalkResult,
388 len: Expr,
389 child: Expr,
391390 },
392391 Struct: struct {
393392 name: []const u8,
394393 src: usize, // index into astNodes
395394 privDecls: []usize = &.{}, // index into decls
396395 pubDecls: []usize = &.{}, // index into decls
397 fields: ?[]WalkResult = null, // (use src->fields to find names)
396 fields: ?[]Expr = null, // (use src->fields to find names)
398397 },
399398 ComptimeExpr: struct { name: []const u8 },
400399 ComptimeFloat: struct { name: []const u8 },
......@@ -403,7 +402,7 @@ const DocData = struct {
403402 Null: struct { name: []const u8 },
404403 Optional: struct {
405404 name: []const u8,
406 child: WalkResult,
405 child: Expr,
407406 },
408407 ErrorUnion: struct { name: []const u8 },
409408 ErrorSet: struct {
......@@ -423,13 +422,13 @@ const DocData = struct {
423422 src: usize, // index into astNodes
424423 privDecls: []usize = &.{}, // index into decls
425424 pubDecls: []usize = &.{}, // index into decls
426 fields: []WalkResult = &.{}, // (use src->fields to find names)
425 fields: []Expr = &.{}, // (use src->fields to find names)
427426 },
428427 Fn: struct {
429428 name: []const u8,
430429 src: ?usize = null, // index into astNodes
431 ret: WalkResult,
432 params: ?[]WalkResult = null, // (use src->fields to find names)
430 ret: Expr,
431 params: ?[]Expr = null, // (use src->fields to find names)
433432 },
434433 BoundFn: struct { name: []const u8 },
435434 Opaque: struct { name: []const u8 },
......@@ -517,75 +516,61 @@ const DocData = struct {
517516 }
518517 };
519518
520 /// A WalkResult represents the result of the analysis process done to a
521 /// declaration. This includes: decls, fields, etc.
522 ///
523 /// The data in WalkResult is mostly normalized, which means that a
524 /// WalkResult that results in a type definition will hold an index into
525 /// `self.types`.
526 const WalkResult = union(enum) {
519 /// An Expr represents the (untyped) result of analizing instructions.
520 /// The data is normalized, which means that an Expr that results in a
521 /// type definition will hold an index into `self.types`.
522 pub const Expr = union(enum) {
527523 comptimeExpr: usize, // index in `comptimeExprs`
528524 void,
529525 @"unreachable",
530 @"null": *WalkResult,
531 @"undefined": *WalkResult,
532 @"struct": Struct,
526 @"null",
527 @"undefined",
528 @"struct": []FieldVal,
533529 bool: bool,
534530 @"anytype",
535531 type: usize, // index in `types`
536532 this: usize, // index in `types`
537533 declRef: usize, // index in `decls`
538534 fieldRef: FieldRef,
539 refPath: []WalkResult,
535 refPath: []Expr,
540536 int: struct {
541 typeRef: *WalkResult,
542537 value: usize, // direct value
543538 negated: bool = false,
544539 },
545 float: struct {
546 typeRef: *WalkResult,
547 value: f64, // direct value
548 negated: bool = false,
549 },
550 array: Array,
540 float: f64, // direct value
541 array: []usize, // index in `exprs`
551542 call: usize, // index in `calls`
552 enumLiteral: []const u8,
553 typeOf: *WalkResult,
554 sizeOf: *WalkResult,
543 enumLiteral: []const u8, // direct value
544 typeOf: usize, // index in `exprs`
545 as: struct {
546 typeRefArg: ?usize, // index in `exprs`
547 exprArg: usize, // index in `exprs`
548 },
549 sizeOf: usize, // index in `exprs`
555550 compileError: []const u8,
556 string: []const u8,
557
551 string: []const u8, // direct value
558552 const FieldRef = struct {
559553 type: usize, // index in `types`
560554 index: usize, // index in type.fields
561555 };
562556
563 const Struct = struct {
564 typeRef: *WalkResult,
565 fieldVals: []FieldVal,
566
567 const FieldVal = struct {
568 name: []const u8,
569 val: WalkResult,
570 };
571 };
572 const Array = struct {
573 typeRef: *WalkResult,
574 data: []WalkResult,
557 const FieldVal = struct {
558 name: []const u8,
559 val: WalkResult,
575560 };
576561
577562 pub fn jsonStringify(
578 self: WalkResult,
563 self: Expr,
579564 options: std.json.StringifyOptions,
580565 w: anytype,
581566 ) std.os.WriteError!void {
582567 switch (self) {
583 .void, .@"unreachable", .@"anytype" => {
568 .void, .@"unreachable", .@"anytype", .@"null", .@"undefined" => {
584569 try w.print(
585570 \\{{ "{s}":{{}} }}
586571 , .{@tagName(self)});
587572 },
588 .type, .comptimeExpr, .call, .this, .declRef => |v| {
573 .type, .comptimeExpr, .call, .this, .declRef, .typeOf => |v| {
589574 try w.print(
590575 \\{{ "{s}":{} }}
591576 , .{ @tagName(self), v });
......@@ -593,43 +578,28 @@ const DocData = struct {
593578 .int => |v| {
594579 const neg = if (v.negated) "-" else "";
595580 try w.print(
596 \\{{ "int": {{ "typeRef":
597 , .{});
598 try v.typeRef.jsonStringify(options, w);
599 try w.print(
600 \\, "value": {s}{} }} }}
581 \\{{ "int": {s}{} }}
601582 , .{ neg, v.value });
602583 },
603584 .float => |v| {
604 const neg = if (v.negated) "-" else "";
605 try w.print(
606 \\{{ "float": {{ "typeRef":
607 , .{});
608 try v.typeRef.jsonStringify(options, w);
609585 try w.print(
610 \\, "value": {s}1 }} }}
611 , .{neg});
612 // TODO: uncomment once float panic is fixed in stdlib
613 // See: https://github.com/ziglang/zig/issues/11283
614 // try w.print(
615 // \\, "value": {s}{e} }} }}
616 // , .{ neg, v.value });
586 \\{{ "float": {} }}
587 , .{v});
617588 },
618589 .bool => |v| {
619590 try w.print(
620591 \\{{ "bool":{} }}
621592 , .{v});
622593 },
623 .@"undefined" => |v| try std.json.stringify(v, options, w),
624 .@"null" => |v| try std.json.stringify(v, options, w),
625 .typeOf, .sizeOf => |v| try std.json.stringify(v, options, w),
594 .sizeOf => |v| try std.json.stringify(v, options, w),
595 .as => |v| try std.json.stringify(v, options, w),
626596 .fieldRef => |v| try std.json.stringify(
627597 struct { fieldRef: FieldRef }{ .fieldRef = v },
628598 options,
629599 w,
630600 ),
631601 .@"struct" => |v| try std.json.stringify(
632 struct { @"struct": Struct }{ .@"struct" = v },
602 struct { @"struct": []FieldVal }{ .@"struct" = v },
633603 options,
634604 w,
635605 ),
......@@ -642,7 +612,7 @@ const DocData = struct {
642612 }
643613 },
644614 .array => |v| try std.json.stringify(
645 struct { @"array": Array }{ .@"array" = v },
615 struct { @"array": []usize }{ .@"array" = v },
646616 options,
647617 w,
648618 ),
......@@ -677,6 +647,17 @@ const DocData = struct {
677647 }
678648 }
679649 };
650
651 /// A WalkResult represents the result of the analysis process done to a
652 /// a Zir instruction. Walk results carry type information either inferred
653 /// from the context (eg string literals are pointers to null-terminated
654 /// arrays), or because of @as() instructions.
655 /// Since the type information is only needed in certain contexts, the
656 /// underlying normalized data (Expr) is untyped.
657 const WalkResult = struct {
658 typeRef: ?Expr = null, // index in `exprs`
659 expr: Expr, // index in `exprs`
660 };
680661};
681662
682663/// Called when we need to analyze a Zir instruction.
......@@ -692,6 +673,7 @@ fn walkInstruction(
692673 file: *File,
693674 parent_scope: *Scope,
694675 inst_index: usize,
676 need_type: bool, // true if the caller needs us to provide also a typeRef
695677) error{OutOfMemory}!DocData.WalkResult {
696678 const tags = file.zir.instructions.items(.tag);
697679 const data = file.zir.instructions.items(.data);
......@@ -711,11 +693,11 @@ fn walkInstruction(
711693 },
712694 .closure_get => {
713695 const inst_node = data[inst_index].inst_node;
714 return try self.walkInstruction(file, parent_scope, inst_node.inst);
696 return try self.walkInstruction(file, parent_scope, inst_node.inst, need_type);
715697 },
716698 .closure_capture => {
717699 const un_tok = data[inst_index].un_tok;
718 return try self.walkRef(file, parent_scope, un_tok.operand);
700 return try self.walkRef(file, parent_scope, un_tok.operand, need_type);
719701 },
720702 .import => {
721703 const str_tok = data[inst_index].str_tok;
......@@ -726,17 +708,20 @@ fn walkInstruction(
726708 const cte_slot_index = self.comptime_exprs.items.len;
727709 try self.comptime_exprs.append(self.arena, .{
728710 .code = path,
729 .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.Type) },
730711 });
731712 return DocData.WalkResult{
732 .comptimeExpr = cte_slot_index,
713 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
714 .expr = .{ .comptimeExpr = cte_slot_index },
733715 };
734716 }
735717
736718 const new_file = self.module.importFile(file, path) catch unreachable;
737719 const result = try self.files.getOrPut(self.arena, new_file.file);
738720 if (result.found_existing) {
739 return DocData.WalkResult{ .type = result.value_ptr.* };
721 return DocData.WalkResult{
722 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
723 .expr = .{ .type = result.value_ptr.* },
724 };
740725 }
741726
742727 result.value_ptr.* = self.types.items.len;
......@@ -745,18 +730,38 @@ fn walkInstruction(
745730 .parent = null,
746731 .enclosing_type = self.types.items.len,
747732 };
748 const new_file_walk_result = self.walkInstruction(
733
734 return self.walkInstruction(
749735 new_file.file,
750736 &new_scope,
751737 Zir.main_struct_inst,
738 need_type,
752739 );
753
754 return new_file_walk_result;
755740 },
756741 .str => {
757 const str = data[inst_index].str;
742 const str = data[inst_index].str.get(file.zir);
743
744 const tRef: ?DocData.Expr = if (!need_type) null else blk: {
745 const arrTypeId = self.types.items.len;
746 try self.types.append(self.arena, .{
747 .Array = .{
748 .len = .{ .int = .{ .value = str.len } },
749 .child = .{ .type = @enumToInt(Ref.u8_type) },
750 },
751 });
752 const ptrTypeId = self.types.items.len;
753 try self.types.append(self.arena, .{
754 .Pointer = .{
755 .size = .One,
756 .child = .{ .type = arrTypeId },
757 // TODO: add sentinel!
758 },
759 });
760 break :blk .{ .type = ptrTypeId };
761 };
758762 return DocData.WalkResult{
759 .string = str.get(file.zir),
763 .typeRef = tRef,
764 .expr = .{ .string = str },
760765 };
761766 },
762767 .compile_error => {
......@@ -765,24 +770,23 @@ fn walkInstruction(
765770 file,
766771 parent_scope,
767772 un_node.operand,
773 false,
768774 );
769775
770 return DocData.WalkResult{ .compileError = operand.string };
776 return DocData.WalkResult{
777 .expr = .{ .compileError = operand.expr.string },
778 };
771779 },
772780 .enum_literal => {
773781 const str_tok = data[inst_index].str_tok;
774782 const literal = file.zir.nullTerminatedString(str_tok.start);
775 return DocData.WalkResult{ .enumLiteral = literal };
783 return DocData.WalkResult{ .expr = .{ .enumLiteral = literal } };
776784 },
777785 .int => {
778786 const int = data[inst_index].int;
779 const t = try self.arena.create(DocData.WalkResult);
780 t.* = .{ .type = @enumToInt(Ref.comptime_int_type) };
781787 return DocData.WalkResult{
782 .int = .{
783 .typeRef = t,
784 .value = int,
785 },
788 .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) },
789 .expr = .{ .int = .{ .value = int } },
786790 };
787791 },
788792 .error_union_type => {
......@@ -790,20 +794,23 @@ fn walkInstruction(
790794 const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index);
791795
792796 // TODO: return the actual error union instread of cheating
793 return self.walkRef(file, parent_scope, extra.data.rhs);
797 return self.walkRef(file, parent_scope, extra.data.rhs, need_type);
794798 },
795799 .ptr_type_simple => {
796800 const ptr = data[inst_index].ptr_type_simple;
797801 const type_slot_index = self.types.items.len;
798 const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type);
802 const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type, false);
799803 try self.types.append(self.arena, .{
800804 .Pointer = .{
801805 .size = ptr.size,
802 .child = elem_type_ref,
806 .child = elem_type_ref.expr,
803807 },
804808 });
805809
806 return DocData.WalkResult{ .type = type_slot_index };
810 return DocData.WalkResult{
811 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
812 .expr = .{ .type = type_slot_index },
813 };
807814 },
808815 .ptr_type => {
809816 const ptr = data[inst_index].ptr_type;
......@@ -814,74 +821,84 @@ fn walkInstruction(
814821 file,
815822 parent_scope,
816823 extra.data.elem_type,
824 false,
817825 );
818826 try self.types.append(self.arena, .{
819827 .Pointer = .{
820828 .size = ptr.size,
821 .child = elem_type_ref,
829 .child = elem_type_ref.expr,
822830 },
823831 });
824
825 return DocData.WalkResult{ .type = type_slot_index };
832 return DocData.WalkResult{
833 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
834 .expr = .{ .type = type_slot_index },
835 };
826836 },
827837 .array_type => {
828838 const bin = data[inst_index].bin;
829 const len = try self.walkRef(file, parent_scope, bin.lhs);
830 const child = try self.walkRef(file, parent_scope, bin.rhs);
839 const len = try self.walkRef(file, parent_scope, bin.lhs, false);
840 const child = try self.walkRef(file, parent_scope, bin.rhs, false);
831841
832842 const type_slot_index = self.types.items.len;
833843 try self.types.append(self.arena, .{
834844 .Array = .{
835 .len = len,
836 .child = child,
845 .len = len.expr,
846 .child = child.expr,
837847 },
838848 });
839 return DocData.WalkResult{ .type = type_slot_index };
849 return DocData.WalkResult{
850 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
851 .expr = .{ .type = type_slot_index },
852 };
840853 },
841854 .array_init => {
842855 const pl_node = data[inst_index].pl_node;
843856 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
844857 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
845 const array_data = try self.arena.alloc(DocData.WalkResult, operands.len);
858 const array_data = try self.arena.alloc(usize, operands.len);
859
860 // TODO: make sure that you want the array to be fully normalized for real
861 // then update this code to conform to your choice.
862
863 var array_type: ?DocData.Expr = null;
846864 for (operands) |op, idx| {
847 array_data[idx] = try self.walkRef(file, parent_scope, op);
848 }
865 // we only ask to figure out type info for the first element
866 // as it will be used later on to find out the array type!
867 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
868
869 if (idx == 0) {
870 array_type = wr.typeRef;
871 }
849872
850 const at = try self.arena.create(DocData.WalkResult);
851 at.* = .{ .type = @enumToInt(Ref.usize_type) };
873 // We know that Zir wraps every operand in an @as expression
874 // so we want to peel it away and only save the target type
875 // once, since we need it later to define the array type.
876 array_data[idx] = wr.expr.as.exprArg;
877 }
852878
853879 const type_slot_index = self.types.items.len;
854880 try self.types.append(self.arena, .{
855881 .Array = .{
856882 .len = .{
857883 .int = .{
858 .typeRef = at,
859884 .value = operands.len,
860885 .negated = false,
861886 },
862887 },
863 .child = try self.typeOfWalkResult(array_data[0]),
888 .child = array_type.?,
864889 },
865890 });
866891
867 const t = try self.arena.create(DocData.WalkResult);
868 t.* = .{ .type = type_slot_index };
869 return DocData.WalkResult{ .array = .{
870 .typeRef = t,
871 .data = array_data,
872 } };
892 return DocData.WalkResult{
893 .typeRef = .{ .type = type_slot_index },
894 .expr = .{ .array = array_data },
895 };
873896 },
874897 .float => {
875898 const float = data[inst_index].float;
876
877 const t = try self.arena.create(DocData.WalkResult);
878 t.* = .{ .type = @enumToInt(Ref.comptime_float_type) };
879
880899 return DocData.WalkResult{
881 .float = .{
882 .typeRef = t,
883 .value = float,
884 },
900 .typeRef = .{ .type = @enumToInt(Ref.comptime_float_type) },
901 .expr = .{ .float = float },
885902 };
886903 },
887904 .negate => {
......@@ -890,8 +907,9 @@ fn walkInstruction(
890907 file,
891908 parent_scope,
892909 un_node.operand,
910 need_type,
893911 );
894 switch (operand) {
912 switch (operand.expr) {
895913 .int => |*int| int.negated = true,
896914 else => {
897915 printWithContext(
......@@ -906,75 +924,93 @@ fn walkInstruction(
906924 },
907925 .size_of => {
908926 const un_node = data[inst_index].un_node;
909 var operand = try self.arena.create(DocData.WalkResult);
910 operand.* = try self.walkRef(
927 const operand = try self.walkRef(
911928 file,
912929 parent_scope,
913930 un_node.operand,
931 false,
914932 );
915 return DocData.WalkResult{ .sizeOf = operand };
933 const operand_index = self.exprs.items.len;
934 try self.exprs.append(self.arena, operand.expr);
935 return DocData.WalkResult{
936 .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) },
937 .expr = .{ .sizeOf = operand_index },
938 };
916939 },
917940
918941 .typeof => {
919942 const un_node = data[inst_index].un_node;
920 var operand = try self.arena.create(DocData.WalkResult);
921 operand.* = try self.walkRef(
943 const operand = try self.walkRef(
922944 file,
923945 parent_scope,
924946 un_node.operand,
947 need_type,
925948 );
926 return DocData.WalkResult{ .typeOf = operand };
949 const operand_index = self.exprs.items.len;
950 try self.exprs.append(self.arena, operand.expr);
951
952 return DocData.WalkResult{
953 .typeRef = operand.typeRef,
954 .expr = .{ .typeOf = operand_index },
955 };
927956 },
928957 .as_node => {
929958 const pl_node = data[inst_index].pl_node;
930959 const extra = file.zir.extraData(Zir.Inst.As, pl_node.payload_index);
931 const dest_type_walk = try self.walkRef(file, parent_scope, extra.data.dest_type);
932 const dest_type_ref = dest_type_walk;
960 const dest_type_walk = try self.walkRef(
961 file,
962 parent_scope,
963 extra.data.dest_type,
964 false,
965 );
933966
934 var operand = try self.walkRef(file, parent_scope, extra.data.operand);
967 const operand = try self.walkRef(
968 file,
969 parent_scope,
970 extra.data.operand,
971 false,
972 );
973 const operand_idx = self.exprs.items.len;
974 try self.exprs.append(self.arena, operand.expr);
935975
936 switch (operand) {
937 else => printWithContext(
938 file,
939 inst_index,
940 "TODO: handle {s} in `walkInstruction.as_node`",
941 .{@tagName(operand)},
942 ),
943 .declRef, .refPath, .type, .string, .call, .enumLiteral => {},
944 // we don't do anything because up until now,
945 // I've only seen this used as such:
946 // @as(@as(type, Baz), .{})
947 // and we don't want to toss away the
948 // decl_val information (eg by replacing it with
949 // a WalkResult.type).
950 .comptimeExpr => {
951 self.comptime_exprs.items[operand.comptimeExpr].typeRef = dest_type_ref;
952 },
953 .int => operand.int.typeRef.* = dest_type_ref,
954 .@"struct" => operand.@"struct".typeRef.* = dest_type_ref,
955 .@"undefined" => operand.@"undefined".* = dest_type_ref,
956 }
976 const dest_type_idx = self.exprs.items.len;
977 try self.exprs.append(self.arena, dest_type_walk.expr);
957978
958 return operand;
979 // TODO: there's something wrong with how both `as` and `WalkrResult`
980 // try to store type information.
981 return DocData.WalkResult{
982 .typeRef = dest_type_walk.expr,
983 .expr = .{
984 .as = .{
985 .typeRefArg = dest_type_idx,
986 .exprArg = operand_idx,
987 },
988 },
989 };
959990 },
960991 .optional_type => {
961992 const un_node = data[inst_index].un_node;
962 var operand: DocData.WalkResult = try self.walkRef(
993 const operand: DocData.WalkResult = try self.walkRef(
963994 file,
964995 parent_scope,
965996 un_node.operand,
997 false,
966998 );
967 const type_ref = operand;
968 const res = DocData.WalkResult{ .type = self.types.items.len };
999
1000 const operand_idx = self.types.items.len;
9691001 try self.types.append(self.arena, .{
970 .Optional = .{ .name = "?TODO", .child = type_ref },
1002 .Optional = .{ .name = "?TODO", .child = operand.expr },
9711003 });
972 return res;
1004
1005 return DocData.WalkResult{
1006 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1007 .expr = .{ .type = operand_idx },
1008 };
9731009 },
9741010 .decl_val, .decl_ref => {
9751011 const str_tok = data[inst_index].str_tok;
9761012 const decls_slot_index = parent_scope.resolveDeclName(str_tok.start);
977 return DocData.WalkResult{ .declRef = decls_slot_index };
1013 return DocData.WalkResult{ .expr = .{ .declRef = decls_slot_index } };
9781014 },
9791015 .field_val, .field_call_bind, .field_ptr, .field_type => {
9801016 // TODO: field type uses Zir.Inst.FieldType, it just happens to have the
......@@ -982,7 +1018,7 @@ fn walkInstruction(
9821018 const pl_node = data[inst_index].pl_node;
9831019 const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index);
9841020
985 var path: std.ArrayListUnmanaged(DocData.WalkResult) = .{};
1021 var path: std.ArrayListUnmanaged(DocData.Expr) = .{};
9861022 var lhs = @enumToInt(extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs
9871023
9881024 try path.append(self.arena, .{
......@@ -1006,12 +1042,13 @@ fn walkInstruction(
10061042 lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs
10071043 }
10081044
1009 const wr = try self.walkInstruction(file, parent_scope, lhs);
1010 try path.append(self.arena, wr);
1045 // TODO: double check that we really don't need type info here
1046 const wr = try self.walkInstruction(file, parent_scope, lhs, false);
1047 try path.append(self.arena, wr.expr);
10111048
10121049 // This way the data in `path` has the same ordering that the ref
10131050 // path has in the text: most general component first.
1014 std.mem.reverse(DocData.WalkResult, path.items);
1051 std.mem.reverse(DocData.Expr, path.items);
10151052
10161053 // Righ now, every element of `path` is a string except its first
10171054 // element (at index 0). We're now going to attempt to resolve each
......@@ -1026,7 +1063,7 @@ fn walkInstruction(
10261063 // any value that depends on that will have to become a
10271064 // comptimeExpr.
10281065 try self.tryResolveRefPath(file, lhs, path.items);
1029 return DocData.WalkResult{ .refPath = path.items };
1066 return DocData.WalkResult{ .expr = .{ .refPath = path.items } };
10301067 },
10311068 .int_type => {
10321069 const int_type = data[inst_index].int_type;
......@@ -1037,28 +1074,37 @@ fn walkInstruction(
10371074 try self.types.append(self.arena, .{
10381075 .Int = .{ .name = name },
10391076 });
1040 return DocData.WalkResult{ .type = self.types.items.len - 1 };
1077 return DocData.WalkResult{
1078 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1079 .expr = .{ .type = self.types.items.len - 1 },
1080 };
10411081 },
10421082 .block => {
1043 const res = DocData.WalkResult{ .comptimeExpr = self.comptime_exprs.items.len };
1083 const res = DocData.WalkResult{ .expr = .{
1084 .comptimeExpr = self.comptime_exprs.items.len,
1085 } };
10441086 try self.comptime_exprs.append(self.arena, .{
10451087 .code = "if(banana) 1 else 0",
1046 .typeRef = .{ .type = 0 },
10471088 });
10481089 return res;
10491090 },
10501091 .block_inline => {
1051 return self.walkRef(file, parent_scope, getBlockInlineBreak(file.zir, inst_index));
1092 return self.walkRef(
1093 file,
1094 parent_scope,
1095 getBlockInlineBreak(file.zir, inst_index),
1096 need_type,
1097 );
10521098 },
10531099 .struct_init => {
10541100 const pl_node = data[inst_index].pl_node;
10551101 const extra = file.zir.extraData(Zir.Inst.StructInit, pl_node.payload_index);
10561102 const field_vals = try self.arena.alloc(
1057 DocData.WalkResult.Struct.FieldVal,
1103 DocData.Expr.FieldVal,
10581104 extra.data.fields_len,
10591105 );
10601106
1061 const type_ref = try self.arena.create(DocData.WalkResult);
1107 var type_ref: DocData.Expr = undefined;
10621108 var idx = extra.end;
10631109 for (field_vals) |*fv| {
10641110 const init_extra = file.zir.extraData(Zir.Inst.StructInit.Item, idx);
......@@ -1079,19 +1125,25 @@ fn walkInstruction(
10791125 file,
10801126 parent_scope,
10811127 field_extra.data.container_type,
1128 false,
10821129 );
1083 type_ref.* = wr;
1130 type_ref = wr.expr;
10841131 }
10851132 break :blk file.zir.nullTerminatedString(field_extra.data.name_start);
10861133 };
1087 const value = try self.walkRef(file, parent_scope, init_extra.data.init);
1134 const value = try self.walkRef(
1135 file,
1136 parent_scope,
1137 init_extra.data.init,
1138 need_type,
1139 );
10881140 fv.* = .{ .name = field_name, .val = value };
10891141 }
10901142
1091 return DocData.WalkResult{ .@"struct" = .{
1143 return DocData.WalkResult{
10921144 .typeRef = type_ref,
1093 .fieldVals = field_vals,
1094 } };
1145 .expr = .{ .@"struct" = field_vals },
1146 };
10951147 },
10961148 .error_set_decl => {
10971149 const pl_node = data[inst_index].pl_node;
......@@ -1122,7 +1174,10 @@ fn walkInstruction(
11221174 },
11231175 });
11241176
1125 return DocData.WalkResult{ .type = type_slot_index };
1177 return DocData.WalkResult{
1178 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1179 .expr = .{ .type = type_slot_index },
1180 };
11261181 },
11271182 .param_anytype => {
11281183 // Analysis of anytype function params happens in `.func`.
......@@ -1134,9 +1189,8 @@ fn walkInstruction(
11341189 const cte_slot_index = self.comptime_exprs.items.len;
11351190 try self.comptime_exprs.append(self.arena, .{
11361191 .code = name,
1137 .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr) },
11381192 });
1139 return DocData.WalkResult{ .comptimeExpr = cte_slot_index };
1193 return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } };
11401194 },
11411195 .param, .param_comptime => {
11421196 // See .param_anytype for more information.
......@@ -1146,41 +1200,46 @@ fn walkInstruction(
11461200 const cte_slot_index = self.comptime_exprs.items.len;
11471201 try self.comptime_exprs.append(self.arena, .{
11481202 .code = name,
1149 .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr) },
11501203 });
1151 return DocData.WalkResult{ .comptimeExpr = cte_slot_index };
1204 return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } };
11521205 },
11531206 .call => {
11541207 const pl_node = data[inst_index].pl_node;
11551208 const extra = file.zir.extraData(Zir.Inst.Call, pl_node.payload_index);
11561209
1157 const callee = try self.walkRef(file, parent_scope, extra.data.callee);
1210 const callee = try self.walkRef(file, parent_scope, extra.data.callee, need_type);
11581211
11591212 const args_len = extra.data.flags.args_len;
1160 var args = try self.arena.alloc(DocData.WalkResult, args_len);
1213 var args = try self.arena.alloc(DocData.Expr, args_len);
11611214 const arg_refs = file.zir.refSlice(extra.end, args_len);
11621215 for (arg_refs) |ref, idx| {
1163 args[idx] = try self.walkRef(file, parent_scope, ref);
1216 // TODO: consider toggling need_type to true if we ever want
1217 // to show discrepancies between the types of provided
1218 // arguments and the types declared in the function
1219 // signature for its parameters.
1220 const wr = try self.walkRef(file, parent_scope, ref, false);
1221 args[idx] = wr.expr;
11641222 }
11651223
1166 // TODO: see if we can ever do something better than just always
1167 // resolve function calls to a comptimeExpr.
11681224 const cte_slot_index = self.comptime_exprs.items.len;
11691225 try self.comptime_exprs.append(self.arena, .{
11701226 .code = "func call",
1171 .typeRef = .{
1172 .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr),
1173 }, // TODO: extract return type from callee when available
11741227 });
11751228
11761229 const call_slot_index = self.calls.items.len;
11771230 try self.calls.append(self.arena, .{
1178 .func = callee,
1231 .func = callee.expr,
11791232 .args = args,
11801233 .ret = .{ .comptimeExpr = cte_slot_index },
11811234 });
11821235
1183 return DocData.WalkResult{ .call = call_slot_index };
1236 return DocData.WalkResult{
1237 .typeRef = if (callee.typeRef) |tr| switch (tr) {
1238 .type => |func_type_idx| self.types.items[func_type_idx].Fn.ret,
1239 else => null,
1240 } else null,
1241 .expr = .{ .call = call_slot_index },
1242 };
11841243 },
11851244 .func, .func_inferred => {
11861245 const type_slot_index = self.types.items.len;
......@@ -1208,42 +1267,13 @@ fn walkInstruction(
12081267 },
12091268
12101269 .opaque_decl => return self.cteTodo("opaque {...}"),
1211 // .func => {
1212 // const type_slot_index = self.types.items.len;
1213 // try self.types.append(self.arena, .{ .Unanalyzed = {} });
1214 //
1215 // const result = try self.analyzeFunction(
1216 // file,
1217 // parent_scope,
1218 // inst_index,
1219 // self_ast_node_index,
1220 // type_slot_index,
1221 // );
1222 // if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| {
1223 // for (paths.items) |resume_info| {
1224 // try self.tryResolveRefPath(
1225 // resume_info.file,
1226 // inst_index,
1227 // resume_info.ref_path,
1228 // );
1229 // }
1230 //
1231 // _ = self.ref_paths_pending_on_types.remove(type_slot_index);
1232 // // TODO: we should deallocate the arraylist that holds all the
1233 // // decl paths. not doing it now since it's arena-allocated
1234 // // anyway, but maybe we should put it elsewhere.
1235 // }
1236 // return result;
1237 // },
12381270 .variable => {
12391271 const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small);
12401272 var extra_index: usize = extended.operand;
12411273 if (small.has_lib_name) extra_index += 1;
12421274 if (small.has_align) extra_index += 1;
12431275
1244 const value: DocData.WalkResult =
1245 if (small.has_init)
1246 .{ .void = {} } else .{ .void = {} };
1276 const value: DocData.WalkResult = if (small.has_init) .{ .expr = .{ .void = {} } } else .{ .expr = .{ .void = {} } };
12471277
12481278 return value;
12491279 },
......@@ -1322,10 +1352,9 @@ fn walkInstruction(
13221352 extra_index,
13231353 );
13241354
1325 // const body = file.zir.extra[extra_index..][0..body_len];
13261355 extra_index += body_len;
13271356
1328 var field_type_refs = try std.ArrayListUnmanaged(DocData.WalkResult).initCapacity(
1357 var field_type_refs = try std.ArrayListUnmanaged(DocData.Expr).initCapacity(
13291358 self.arena,
13301359 fields_len,
13311360 );
......@@ -1369,7 +1398,10 @@ fn walkInstruction(
13691398 // anyway, but maybe we should put it elsewhere.
13701399 }
13711400
1372 return DocData.WalkResult{ .type = type_slot_index };
1401 return DocData.WalkResult{
1402 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1403 .expr = .{ .type = type_slot_index },
1404 };
13731405 },
13741406 .enum_decl => {
13751407 const type_slot_index = self.types.items.len;
......@@ -1516,8 +1548,10 @@ fn walkInstruction(
15161548 // decl paths. not doing it now since it's arena-allocated
15171549 // anyway, but maybe we should put it elsewhere.
15181550 }
1519
1520 return DocData.WalkResult{ .type = type_slot_index };
1551 return DocData.WalkResult{
1552 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1553 .expr = .{ .type = type_slot_index },
1554 };
15211555 },
15221556 .struct_decl => {
15231557 const type_slot_index = self.types.items.len;
......@@ -1590,7 +1624,7 @@ fn walkInstruction(
15901624 // const body = file.zir.extra[extra_index..][0..body_len];
15911625 extra_index += body_len;
15921626
1593 var field_type_refs: std.ArrayListUnmanaged(DocData.WalkResult) = .{};
1627 var field_type_refs: std.ArrayListUnmanaged(DocData.Expr) = .{};
15941628 var field_name_indexes: std.ArrayListUnmanaged(usize) = .{};
15951629 try self.collectStructFieldInfo(
15961630 file,
......@@ -1626,11 +1660,16 @@ fn walkInstruction(
16261660 // decl paths. not doing it now since it's arena-allocated
16271661 // anyway, but maybe we should put it elsewhere.
16281662 }
1629
1630 return DocData.WalkResult{ .type = type_slot_index };
1663 return DocData.WalkResult{
1664 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1665 .expr = .{ .type = type_slot_index },
1666 };
16311667 },
16321668 .this => {
1633 return DocData.WalkResult{ .this = parent_scope.enclosing_type };
1669 return DocData.WalkResult{
1670 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
1671 .expr = .{ .this = parent_scope.enclosing_type },
1672 };
16341673 },
16351674 }
16361675 },
......@@ -1793,7 +1832,7 @@ fn walkDecls(
17931832 .name = "test",
17941833 .isTest = true,
17951834 .src = ast_node_index,
1796 .value = .{ .type = 0 },
1835 .value = .{ .expr = .{ .type = 0 } },
17971836 .kind = "const",
17981837 };
17991838 continue;
......@@ -1827,9 +1866,9 @@ fn walkDecls(
18271866 };
18281867
18291868 const walk_result = if (is_test) // TODO: decide if tests should show up at all
1830 DocData.WalkResult{ .void = {} }
1869 DocData.WalkResult{ .expr = .{ .void = {} } }
18311870 else
1832 try self.walkInstruction(file, scope, value_index);
1871 try self.walkInstruction(file, scope, value_index, true);
18331872
18341873 if (is_pub) {
18351874 try decl_indexes.append(self.arena, decls_slot_index);
......@@ -1857,7 +1896,7 @@ fn walkDecls(
18571896 .name = name,
18581897 .isTest = is_test,
18591898 .src = ast_node_index,
1860 // .typeRef = decl_type_ref,
1899 //.typeRef = decl_type_ref,
18611900 .value = walk_result,
18621901 .kind = "const", // find where this information can be found
18631902 };
......@@ -1906,7 +1945,7 @@ fn tryResolveRefPath(
19061945 /// File from which the decl path originates.
19071946 file: *File,
19081947 inst_index: usize, // used only for panicWithContext
1909 path: []DocData.WalkResult,
1948 path: []DocData.Expr,
19101949) error{OutOfMemory}!void {
19111950 var i: usize = 0;
19121951 outer: while (i < path.len - 1) : (i += 1) {
......@@ -1922,7 +1961,7 @@ fn tryResolveRefPath(
19221961 .declRef => |decl_index| {
19231962 const decl = self.decls.items[decl_index];
19241963 if (decl._analyzed) {
1925 resolved_parent = decl.value;
1964 resolved_parent = decl.value.expr;
19261965 continue;
19271966 }
19281967
......@@ -2004,7 +2043,7 @@ fn tryResolveRefPath(
20042043 "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}",
20052044 .{ @tagName(resolved_parent), resolved_parent },
20062045 );
2007 path[i + 1] = try self.cteTodo("match failure");
2046 path[i + 1] = (try self.cteTodo("match failure")).expr;
20082047 continue :outer;
20092048 },
20102049 .comptimeExpr, .call => {
......@@ -2088,7 +2127,7 @@ fn tryResolveRefPath(
20882127 .{child_string},
20892128 );
20902129
2091 path[i + 1] = try self.cteTodo("match failure");
2130 path[i + 1] = (try self.cteTodo("match failure")).expr;
20922131 continue :outer;
20932132 },
20942133 .Union => |t_union| {
......@@ -2134,7 +2173,7 @@ fn tryResolveRefPath(
21342173 "failed to match `{s}` in union",
21352174 .{child_string},
21362175 );
2137 path[i + 1] = try self.cteTodo("match failure");
2176 path[i + 1] = (try self.cteTodo("match failure")).expr;
21382177 continue :outer;
21392178 },
21402179
......@@ -2181,7 +2220,7 @@ fn tryResolveRefPath(
21812220 "failed to match `{s}` in struct",
21822221 .{child_string},
21832222 );
2184 path[i + 1] = try self.cteTodo("match failure");
2223 path[i + 1] = (try self.cteTodo("match failure")).expr;
21852224 continue :outer;
21862225 },
21872226 },
......@@ -2214,7 +2253,7 @@ fn analyzeFunction(
22142253 const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index));
22152254
22162255 try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len);
2217 var param_type_refs = try std.ArrayListUnmanaged(DocData.WalkResult).initCapacity(
2256 var param_type_refs = try std.ArrayListUnmanaged(DocData.Expr).initCapacity(
22182257 self.arena,
22192258 fn_info.total_params_len,
22202259 );
......@@ -2246,7 +2285,7 @@ fn analyzeFunction(
22462285 });
22472286
22482287 param_type_refs.appendAssumeCapacity(
2249 DocData.WalkResult{ .@"anytype" = {} },
2288 DocData.Expr{ .@"anytype" = {} },
22502289 );
22512290 },
22522291 .param, .param_comptime => {
......@@ -2267,9 +2306,9 @@ fn analyzeFunction(
22672306
22682307 const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1];
22692308 const break_operand = data[break_index].@"break".operand;
2270 const param_type_ref = try self.walkRef(file, scope, break_operand);
2309 const param_type_ref = try self.walkRef(file, scope, break_operand, false);
22712310
2272 param_type_refs.appendAssumeCapacity(param_type_ref);
2311 param_type_refs.appendAssumeCapacity(param_type_ref.expr);
22732312 },
22742313 }
22752314 }
......@@ -2278,7 +2317,7 @@ fn analyzeFunction(
22782317 const ret_type_ref = blk: {
22792318 const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1];
22802319 const break_operand = data[last_instr_index].@"break".operand;
2281 const wr = try self.walkRef(file, scope, break_operand);
2320 const wr = try self.walkRef(file, scope, break_operand, false);
22822321 break :blk wr;
22832322 };
22842323
......@@ -2288,10 +2327,13 @@ fn analyzeFunction(
22882327 .name = "todo_name func",
22892328 .src = self_ast_node_index,
22902329 .params = param_type_refs.items,
2291 .ret = ret_type_ref,
2330 .ret = ret_type_ref.expr,
22922331 },
22932332 };
2294 return DocData.WalkResult{ .type = type_slot_index };
2333 return DocData.WalkResult{
2334 .typeRef = .{ .type = @enumToInt(Ref.type_type) },
2335 .expr = .{ .type = type_slot_index },
2336 };
22952337}
22962338
22972339fn collectUnionFieldInfo(
......@@ -2299,7 +2341,7 @@ fn collectUnionFieldInfo(
22992341 file: *File,
23002342 scope: *Scope,
23012343 fields_len: usize,
2302 field_type_refs: *std.ArrayListUnmanaged(DocData.WalkResult),
2344 field_type_refs: *std.ArrayListUnmanaged(DocData.Expr),
23032345 field_name_indexes: *std.ArrayListUnmanaged(usize),
23042346 ei: usize,
23052347) !void {
......@@ -2344,8 +2386,8 @@ fn collectUnionFieldInfo(
23442386
23452387 // type
23462388 {
2347 const walk_result = try self.walkRef(file, scope, field_type);
2348 try field_type_refs.append(self.arena, walk_result);
2389 const walk_result = try self.walkRef(file, scope, field_type, false);
2390 try field_type_refs.append(self.arena, walk_result.expr);
23492391 }
23502392
23512393 // ast node
......@@ -2368,7 +2410,7 @@ fn collectStructFieldInfo(
23682410 file: *File,
23692411 scope: *Scope,
23702412 fields_len: usize,
2371 field_type_refs: *std.ArrayListUnmanaged(DocData.WalkResult),
2413 field_type_refs: *std.ArrayListUnmanaged(DocData.Expr),
23722414 field_name_indexes: *std.ArrayListUnmanaged(usize),
23732415 ei: usize,
23742416) !void {
......@@ -2410,8 +2452,8 @@ fn collectStructFieldInfo(
24102452
24112453 // type
24122454 {
2413 const walk_result = try self.walkRef(file, scope, field_type);
2414 try field_type_refs.append(self.arena, walk_result);
2455 const walk_result = try self.walkRef(file, scope, field_type, false);
2456 try field_type_refs.append(self.arena, walk_result.expr);
24152457 }
24162458
24172459 // ast node
......@@ -2436,13 +2478,17 @@ fn walkRef(
24362478 file: *File,
24372479 parent_scope: *Scope,
24382480 ref: Ref,
2481 need_type: bool, // true when the caller needs also a typeRef for the return value
24392482) !DocData.WalkResult {
24402483 const enum_value = @enumToInt(ref);
24412484 if (enum_value <= @enumToInt(Ref.anyerror_void_error_union_type)) {
24422485 // We can just return a type that indexes into `types` with the
24432486 // enum value because in the beginning we pre-filled `types` with
24442487 // the types that are listed in `Ref`.
2445 return DocData.WalkResult{ .type = enum_value };
2488 return DocData.WalkResult{
2489 .typeRef = .{ .type = @enumToInt(std.builtin.TypeId.Type) },
2490 .expr = .{ .type = enum_value },
2491 };
24462492 } else if (enum_value < Ref.typed_value_map.len) {
24472493 switch (ref) {
24482494 else => {
......@@ -2451,69 +2497,62 @@ fn walkRef(
24512497 });
24522498 },
24532499 .undef => {
2454 var t = try self.arena.create(DocData.WalkResult);
2455 t.* = .void;
2456
2457 return DocData.WalkResult{ .@"undefined" = t };
2500 return DocData.WalkResult{ .expr = .@"undefined" };
24582501 },
24592502 .zero => {
2460 var t = try self.arena.create(DocData.WalkResult);
2461 t.* = .{ .type = @enumToInt(Ref.comptime_int_type) };
2462 return DocData.WalkResult{ .int = .{
2463 .typeRef = t,
2464 .value = 0,
2465 } };
2503 return DocData.WalkResult{
2504 .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) },
2505 .expr = .{ .int = .{ .value = 0 } },
2506 };
24662507 },
24672508 .one => {
2468 var t = try self.arena.create(DocData.WalkResult);
2469 t.* = .{ .type = @enumToInt(Ref.comptime_int_type) };
2470 return DocData.WalkResult{ .int = .{
2471 .typeRef = t,
2472 .value = 1,
2473 } };
2509 return DocData.WalkResult{
2510 .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) },
2511 .expr = .{ .int = .{ .value = 1 } },
2512 };
24742513 },
24752514
24762515 .void_value => {
2477 return DocData.WalkResult{ .void = {} };
2516 return DocData.WalkResult{
2517 .typeRef = .{ .type = @enumToInt(Ref.void_type) },
2518 .expr = .{ .void = {} },
2519 };
24782520 },
24792521 .unreachable_value => {
2480 return DocData.WalkResult{ .@"unreachable" = {} };
2522 return DocData.WalkResult{
2523 .typeRef = .{ .type = @enumToInt(Ref.noreturn_type) },
2524 .expr = .{ .@"unreachable" = {} },
2525 };
24812526 },
24822527 .null_value => {
2483 var t = try self.arena.create(DocData.WalkResult);
2484 t.* = .void;
2485 return DocData.WalkResult{ .@"null" = t };
2528 return DocData.WalkResult{ .expr = .@"null" };
24862529 },
24872530 .bool_true => {
2488 return DocData.WalkResult{ .bool = true };
2531 return DocData.WalkResult{
2532 .typeRef = .{ .type = @enumToInt(Ref.bool_type) },
2533 .expr = .{ .bool = true },
2534 };
24892535 },
24902536 .bool_false => {
2491 return DocData.WalkResult{ .bool = false };
2537 return DocData.WalkResult{
2538 .typeRef = .{ .type = @enumToInt(Ref.bool_type) },
2539 .expr = .{ .bool = false },
2540 };
24922541 },
24932542 .empty_struct => {
2494 var t = try self.arena.create(DocData.WalkResult);
2495 t.* = .void;
2496
2497 return DocData.WalkResult{ .@"struct" = .{
2498 .typeRef = t,
2499 .fieldVals = &.{},
2500 } };
2543 return DocData.WalkResult{ .expr = .{ .@"struct" = &.{} } };
25012544 },
25022545 .zero_usize => {
2503 var t = try self.arena.create(DocData.WalkResult);
2504 t.* = .{ .type = @enumToInt(Ref.usize_type) };
2505 return DocData.WalkResult{ .int = .{
2506 .typeRef = t,
2507 .value = 0,
2508 } };
2546 return DocData.WalkResult{
2547 .typeRef = .{ .type = @enumToInt(Ref.usize_type) },
2548 .expr = .{ .int = .{ .value = 0 } },
2549 };
25092550 },
25102551 .one_usize => {
2511 var t = try self.arena.create(DocData.WalkResult);
2512 t.* = .{ .type = @enumToInt(Ref.usize_type) };
2513 return DocData.WalkResult{ .int = .{
2514 .typeRef = t,
2515 .value = 1,
2516 } };
2552 return DocData.WalkResult{
2553 .typeRef = .{ .type = @enumToInt(Ref.usize_type) },
2554 .expr = .{ .int = .{ .value = 1 } },
2555 };
25172556 },
25182557 // TODO: dunno what to do with those
25192558 // .calling_convention_c => {
......@@ -2537,29 +2576,10 @@ fn walkRef(
25372576 }
25382577 } else {
25392578 const zir_index = enum_value - Ref.typed_value_map.len;
2540 return self.walkInstruction(file, parent_scope, zir_index);
2579 return self.walkInstruction(file, parent_scope, zir_index, need_type);
25412580 }
25422581}
25432582
2544/// Given a WalkResult, tries to find its type.
2545/// Used to analyze instructions like `array_init`, which require us to
2546/// inspect its first element to find out the array type.
2547fn typeOfWalkResult(self: *Autodoc, wr: DocData.WalkResult) !DocData.WalkResult {
2548 return switch (wr) {
2549 else => {
2550 std.debug.print(
2551 "TODO: handle `{s}` in typeOfWalkResult\n",
2552 .{@tagName(wr)},
2553 );
2554 return self.cteTodo(@tagName(wr));
2555 },
2556 .type => .{ .type = @enumToInt(DocData.DocTypeKinds.Type) },
2557 .int => |v| v.typeRef.*,
2558 .float => |v| v.typeRef.*,
2559 .array => |v| v.typeRef.*,
2560 };
2561}
2562
25632583fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref {
25642584 const tags = zir.instructions.items(.tag);
25652585 const data = zir.instructions.items(.data);
......@@ -2585,7 +2605,6 @@ fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResul
25852605 const cte_slot_index = self.comptime_exprs.items.len;
25862606 try self.comptime_exprs.append(self.arena, .{
25872607 .code = msg,
2588 .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr) },
25892608 });
2590 return DocData.WalkResult{ .comptimeExpr = cte_slot_index };
2609 return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } };
25912610}