mirror of
https://github.com/ziglang/zig.git
synced 2024-11-30 09:02:32 +00:00
6354851909
"Dialog" is the incorrect term here because a dialog is a separate window that still lets you use the app but a modal is a window where you can't continue using the app until you close it.
3395 lines
101 KiB
JavaScript
3395 lines
101 KiB
JavaScript
"use strict";
|
|
|
|
var zigAnalysis;
|
|
|
|
(function () {
|
|
let domStatus = document.getElementById("status");
|
|
let domSectNav = document.getElementById("sectNav");
|
|
let domListNav = document.getElementById("listNav");
|
|
let domSectMainPkg = document.getElementById("sectMainPkg");
|
|
let domSectPkgs = document.getElementById("sectPkgs");
|
|
let domListPkgs = document.getElementById("listPkgs");
|
|
let domSectTypes = document.getElementById("sectTypes");
|
|
let domListTypes = document.getElementById("listTypes");
|
|
let domSectTests = document.getElementById("sectTests");
|
|
let domListTests = document.getElementById("listTests");
|
|
let domSectNamespaces = document.getElementById("sectNamespaces");
|
|
let domListNamespaces = document.getElementById("listNamespaces");
|
|
let domSectErrSets = document.getElementById("sectErrSets");
|
|
let domListErrSets = document.getElementById("listErrSets");
|
|
let domSectFns = document.getElementById("sectFns");
|
|
let domListFns = document.getElementById("listFns");
|
|
let domSectFields = document.getElementById("sectFields");
|
|
let domListFields = document.getElementById("listFields");
|
|
let domSectGlobalVars = document.getElementById("sectGlobalVars");
|
|
let domListGlobalVars = document.getElementById("listGlobalVars");
|
|
let domSectValues = document.getElementById("sectValues");
|
|
let domListValues = document.getElementById("listValues");
|
|
let domFnProto = document.getElementById("fnProto");
|
|
let domFnProtoCode = document.getElementById("fnProtoCode");
|
|
let domSectParams = document.getElementById("sectParams");
|
|
let domListParams = document.getElementById("listParams");
|
|
let domTldDocs = document.getElementById("tldDocs");
|
|
let domSectFnErrors = document.getElementById("sectFnErrors");
|
|
let domListFnErrors = document.getElementById("listFnErrors");
|
|
let domTableFnErrors = document.getElementById("tableFnErrors");
|
|
let domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
|
|
let domFnExamples = document.getElementById("fnExamples");
|
|
// let domListFnExamples = (document.getElementById("listFnExamples"));
|
|
let domFnNoExamples = document.getElementById("fnNoExamples");
|
|
let domDeclNoRef = document.getElementById("declNoRef");
|
|
let domSearch = document.getElementById("search");
|
|
let domSectSearchResults = document.getElementById("sectSearchResults");
|
|
|
|
let domListSearchResults = document.getElementById("listSearchResults");
|
|
let domSectSearchNoResults = document.getElementById("sectSearchNoResults");
|
|
let domSectInfo = document.getElementById("sectInfo");
|
|
// let domTdTarget = (document.getElementById("tdTarget"));
|
|
let domPrivDeclsBox = document.getElementById("privDeclsBox");
|
|
let domTdZigVer = document.getElementById("tdZigVer");
|
|
let domHdrName = document.getElementById("hdrName");
|
|
let domHelpModal = document.getElementById("helpModal");
|
|
|
|
let searchTimer = null;
|
|
|
|
let escapeHtmlReplacements = {
|
|
"&": "&",
|
|
'"': """,
|
|
"<": "<",
|
|
">": ">",
|
|
};
|
|
|
|
let typeKinds = indexTypeKinds();
|
|
let typeTypeId = findTypeTypeId();
|
|
let pointerSizeEnum = { One: 0, Many: 1, Slice: 2, C: 3 };
|
|
|
|
// for each package, is an array with packages to get to this one
|
|
let canonPkgPaths = computeCanonicalPackagePaths();
|
|
|
|
// for each decl, is an array with {declNames, pkgNames} to get to this one
|
|
|
|
let canonDeclPaths = null; // lazy; use getCanonDeclPath
|
|
|
|
// for each type, is an array with {declNames, pkgNames} to get to this one
|
|
|
|
let canonTypeDecls = null; // lazy; use getCanonTypeDecl
|
|
|
|
let curNav = {
|
|
showPrivDecls: false,
|
|
// each element is a package name, e.g. @import("a") then within there @import("b")
|
|
// starting implicitly from root package
|
|
pkgNames: [],
|
|
// same as above except actual packages, not names
|
|
pkgObjs: [],
|
|
// Each element is a decl name, `a.b.c`, a is 0, b is 1, c is 2, etc.
|
|
// empty array means refers to the package itself
|
|
declNames: [],
|
|
// these will be all types, except the last one may be a type or a decl
|
|
declObjs: [],
|
|
|
|
// (a, b, c, d) comptime call; result is the value the docs refer to
|
|
callName: null,
|
|
};
|
|
|
|
let curNavSearch = "";
|
|
let curSearchIndex = -1;
|
|
let imFeelingLucky = false;
|
|
|
|
let rootIsStd = detectRootIsStd();
|
|
|
|
// map of decl index to list of non-generic fn indexes
|
|
// let nodesToFnsMap = indexNodesToFns();
|
|
// map of decl index to list of comptime fn calls
|
|
// let nodesToCallsMap = indexNodesToCalls();
|
|
|
|
domSearch.addEventListener("keydown", onSearchKeyDown, false);
|
|
domPrivDeclsBox.addEventListener(
|
|
"change",
|
|
function () {
|
|
if (this.checked != curNav.showPrivDecls) {
|
|
if (
|
|
this.checked &&
|
|
location.hash.length > 1 &&
|
|
location.hash[1] != "*"
|
|
) {
|
|
location.hash = "#*" + location.hash.substring(1);
|
|
return;
|
|
}
|
|
if (
|
|
!this.checked &&
|
|
location.hash.length > 1 &&
|
|
location.hash[1] == "*"
|
|
) {
|
|
location.hash = "#" + location.hash.substring(2);
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
false
|
|
);
|
|
|
|
if (location.hash == "") {
|
|
location.hash = "#root";
|
|
}
|
|
|
|
// make the modal disappear if you click outside it
|
|
domHelpModal.addEventListener("click", ev => {
|
|
if (ev.target.className == "help-modal")
|
|
domHelpModal.classList.add("hidden");
|
|
})
|
|
|
|
window.addEventListener("hashchange", onHashChange, false);
|
|
window.addEventListener("keydown", onWindowKeyDown, false);
|
|
onHashChange();
|
|
|
|
function renderTitle() {
|
|
let list = curNav.pkgNames.concat(curNav.declNames);
|
|
let suffix = " - Zig";
|
|
if (list.length === 0) {
|
|
if (rootIsStd) {
|
|
document.title = "std" + suffix;
|
|
} else {
|
|
document.title = zigAnalysis.params.rootName + suffix;
|
|
}
|
|
} else {
|
|
document.title = list.join(".") + suffix;
|
|
}
|
|
}
|
|
|
|
function isDecl(x) {
|
|
return "value" in x;
|
|
}
|
|
|
|
function isType(x) {
|
|
return "kind" in x && !("value" in x);
|
|
}
|
|
|
|
function isContainerType(x) {
|
|
return isType(x) && typeKindIsContainer(x.kind);
|
|
}
|
|
|
|
function typeShorthandName(expr) {
|
|
let resolvedExpr = resolveValue({ expr: expr });
|
|
if (!("type" in resolvedExpr)) {
|
|
return null;
|
|
}
|
|
let type = zigAnalysis.types[resolvedExpr.type];
|
|
|
|
outer: for (let i = 0; i < 10000; i += 1) {
|
|
switch (type.kind) {
|
|
case typeKinds.Optional:
|
|
case typeKinds.Pointer:
|
|
let child = type.child;
|
|
let resolvedChild = resolveValue(child);
|
|
if ("type" in resolvedChild) {
|
|
type = zigAnalysis.types[resolvedChild.type];
|
|
continue;
|
|
} else {
|
|
return null;
|
|
}
|
|
default:
|
|
break outer;
|
|
}
|
|
|
|
if (i == 9999) throw "Exhausted typeShorthandName quota";
|
|
}
|
|
|
|
let name = undefined;
|
|
if (type.kind === typeKinds.Struct) {
|
|
name = "struct";
|
|
} else if (type.kind === typeKinds.Enum) {
|
|
name = "enum";
|
|
} else if (type.kind === typeKinds.Union) {
|
|
name = "union";
|
|
} else {
|
|
console.log("TODO: unhalndled case in typeShortName");
|
|
return null;
|
|
}
|
|
|
|
return escapeHtml(name);
|
|
}
|
|
|
|
function typeKindIsContainer(typeKind) {
|
|
return (
|
|
typeKind === typeKinds.Struct ||
|
|
typeKind === typeKinds.Union ||
|
|
typeKind === typeKinds.Enum
|
|
);
|
|
}
|
|
|
|
function declCanRepresentTypeKind(typeKind) {
|
|
return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
|
|
}
|
|
|
|
//
|
|
// function findCteInRefPath(path) {
|
|
// for (let i = path.length - 1; i >= 0; i -= 1) {
|
|
// const ref = path[i];
|
|
// if ("string" in ref) continue;
|
|
// if ("comptimeExpr" in ref) return ref;
|
|
// if ("refPath" in ref) return findCteInRefPath(ref.refPath);
|
|
// return null;
|
|
// }
|
|
|
|
// return null;
|
|
// }
|
|
|
|
function resolveValue(value) {
|
|
let i = 0;
|
|
while (i < 1000) {
|
|
i += 1;
|
|
|
|
if ("refPath" in value.expr) {
|
|
value = { expr: value.expr.refPath[value.expr.refPath.length - 1] };
|
|
continue;
|
|
}
|
|
|
|
if ("declRef" in value.expr) {
|
|
value = zigAnalysis.decls[value.expr.declRef].value;
|
|
continue;
|
|
}
|
|
|
|
if ("as" in value.expr) {
|
|
value = {
|
|
typeRef: zigAnalysis.exprs[value.expr.as.typeRefArg],
|
|
expr: zigAnalysis.exprs[value.expr.as.exprArg],
|
|
};
|
|
continue;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
console.assert(false);
|
|
return {};
|
|
}
|
|
|
|
// function typeOfDecl(decl){
|
|
// return decl.value.typeRef;
|
|
//
|
|
// let i = 0;
|
|
// while(i < 1000) {
|
|
// i += 1;
|
|
// console.assert(isDecl(decl));
|
|
// if ("type" in decl.value) {
|
|
// return ({ type: typeTypeId });
|
|
// }
|
|
//
|
|
//// if ("string" in decl.value) {
|
|
//// return ({ type: {
|
|
//// kind: typeKinds.Pointer,
|
|
//// size: pointerSizeEnum.One,
|
|
//// child: });
|
|
//// }
|
|
//
|
|
// if ("refPath" in decl.value) {
|
|
// decl = ({
|
|
// value: decl.value.refPath[decl.value.refPath.length -1]
|
|
// });
|
|
// continue;
|
|
// }
|
|
//
|
|
// if ("declRef" in decl.value) {
|
|
// decl = zigAnalysis.decls[decl.value.declRef];
|
|
// continue;
|
|
// }
|
|
//
|
|
// if ("int" in decl.value) {
|
|
// return decl.value.int.typeRef;
|
|
// }
|
|
//
|
|
// if ("float" in decl.value) {
|
|
// return decl.value.float.typeRef;
|
|
// }
|
|
//
|
|
// if ("array" in decl.value) {
|
|
// return decl.value.array.typeRef;
|
|
// }
|
|
//
|
|
// if ("struct" in decl.value) {
|
|
// return decl.value.struct.typeRef;
|
|
// }
|
|
//
|
|
// if ("comptimeExpr" in decl.value) {
|
|
// const cte = zigAnalysis.comptimeExprs[decl.value.comptimeExpr];
|
|
// return cte.typeRef;
|
|
// }
|
|
//
|
|
// if ("call" in decl.value) {
|
|
// const fn_call = zigAnalysis.calls[decl.value.call];
|
|
// let fn_decl = undefined;
|
|
// if ("declRef" in fn_call.func) {
|
|
// fn_decl = zigAnalysis.decls[fn_call.func.declRef];
|
|
// } else if ("refPath" in fn_call.func) {
|
|
// console.assert("declRef" in fn_call.func.refPath[fn_call.func.refPath.length -1]);
|
|
// fn_decl = zigAnalysis.decls[fn_call.func.refPath[fn_call.func.refPath.length -1].declRef];
|
|
// } else throw {};
|
|
//
|
|
// const fn_decl_value = resolveValue(fn_decl.value);
|
|
// console.assert("type" in fn_decl_value); //TODO handle comptimeExpr
|
|
// const fn_type = (zigAnalysis.types[fn_decl_value.type]);
|
|
// console.assert(fn_type.kind === typeKinds.Fn);
|
|
// return fn_type.ret;
|
|
// }
|
|
//
|
|
// if ("void" in decl.value) {
|
|
// return ({ type: typeTypeId });
|
|
// }
|
|
//
|
|
// if ("bool" in decl.value) {
|
|
// return ({ type: typeKinds.Bool });
|
|
// }
|
|
//
|
|
// console.log("TODO: handle in `typeOfDecl` more cases: ", decl);
|
|
// console.assert(false);
|
|
// throw {};
|
|
// }
|
|
// console.assert(false);
|
|
// return ({});
|
|
// }
|
|
|
|
function render() {
|
|
domStatus.classList.add("hidden");
|
|
domFnProto.classList.add("hidden");
|
|
domSectParams.classList.add("hidden");
|
|
domTldDocs.classList.add("hidden");
|
|
domSectMainPkg.classList.add("hidden");
|
|
domSectPkgs.classList.add("hidden");
|
|
domSectTypes.classList.add("hidden");
|
|
domSectTests.classList.add("hidden");
|
|
domSectNamespaces.classList.add("hidden");
|
|
domSectErrSets.classList.add("hidden");
|
|
domSectFns.classList.add("hidden");
|
|
domSectFields.classList.add("hidden");
|
|
domSectSearchResults.classList.add("hidden");
|
|
domSectSearchNoResults.classList.add("hidden");
|
|
domSectInfo.classList.add("hidden");
|
|
domHdrName.classList.add("hidden");
|
|
domSectNav.classList.add("hidden");
|
|
domSectFnErrors.classList.add("hidden");
|
|
domFnExamples.classList.add("hidden");
|
|
domFnNoExamples.classList.add("hidden");
|
|
domDeclNoRef.classList.add("hidden");
|
|
domFnErrorsAnyError.classList.add("hidden");
|
|
domTableFnErrors.classList.add("hidden");
|
|
domSectGlobalVars.classList.add("hidden");
|
|
domSectValues.classList.add("hidden");
|
|
|
|
renderTitle();
|
|
renderInfo();
|
|
renderPkgList();
|
|
|
|
domPrivDeclsBox.checked = curNav.showPrivDecls;
|
|
|
|
if (curNavSearch !== "") {
|
|
return renderSearch();
|
|
}
|
|
|
|
let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
|
|
let pkg = rootPkg;
|
|
curNav.pkgObjs = [pkg];
|
|
for (let i = 0; i < curNav.pkgNames.length; i += 1) {
|
|
let childPkg = zigAnalysis.packages[pkg.table[curNav.pkgNames[i]]];
|
|
if (childPkg == null) {
|
|
return render404();
|
|
}
|
|
pkg = childPkg;
|
|
curNav.pkgObjs.push(pkg);
|
|
}
|
|
|
|
let currentType = zigAnalysis.types[pkg.main];
|
|
curNav.declObjs = [currentType];
|
|
for (let i = 0; i < curNav.declNames.length; i += 1) {
|
|
let childDecl = findSubDecl(currentType, curNav.declNames[i]);
|
|
if (childDecl == null) {
|
|
return render404();
|
|
}
|
|
|
|
let childDeclValue = resolveValue(childDecl.value).expr;
|
|
if ("type" in childDeclValue) {
|
|
const t = zigAnalysis.types[childDeclValue.type];
|
|
if (t.kind != typeKinds.Fn) {
|
|
childDecl = t;
|
|
}
|
|
}
|
|
|
|
currentType = childDecl;
|
|
curNav.declObjs.push(currentType);
|
|
}
|
|
|
|
renderNav();
|
|
|
|
let last = curNav.declObjs[curNav.declObjs.length - 1];
|
|
let lastIsDecl = isDecl(last);
|
|
let lastIsType = isType(last);
|
|
let lastIsContainerType = isContainerType(last);
|
|
|
|
if (lastIsContainerType) {
|
|
return renderContainer(last);
|
|
}
|
|
|
|
if (!lastIsDecl && !lastIsType) {
|
|
return renderUnknownDecl(last);
|
|
}
|
|
|
|
if (lastIsType) {
|
|
return renderType(last);
|
|
}
|
|
|
|
if (lastIsDecl && last.kind === "var") {
|
|
return renderVar(last);
|
|
}
|
|
|
|
if (lastIsDecl && last.kind === "const") {
|
|
let typeObj = zigAnalysis.types[resolveValue(last.value).expr.type];
|
|
if (typeObj && typeObj.kind === typeKinds.Fn) {
|
|
return renderFn(last);
|
|
}
|
|
|
|
return renderValue(last);
|
|
}
|
|
}
|
|
|
|
function renderUnknownDecl(decl) {
|
|
domDeclNoRef.classList.remove("hidden");
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
domTldDocs.innerHTML = markdown(docs);
|
|
} else {
|
|
domTldDocs.innerHTML =
|
|
"<p>There are no doc comments for this declaration.</p>";
|
|
}
|
|
domTldDocs.classList.remove("hidden");
|
|
}
|
|
|
|
function typeIsErrSet(typeIndex) {
|
|
let typeObj = zigAnalysis.types[typeIndex];
|
|
return typeObj.kind === typeKinds.ErrorSet;
|
|
}
|
|
|
|
function typeIsStructWithNoFields(typeIndex) {
|
|
let typeObj = zigAnalysis.types[typeIndex];
|
|
if (typeObj.kind !== typeKinds.Struct) return false;
|
|
return typeObj.fields.length == 0;
|
|
}
|
|
|
|
function typeIsGenericFn(typeIndex) {
|
|
let typeObj = zigAnalysis.types[typeIndex];
|
|
if (typeObj.kind !== typeKinds.Fn) {
|
|
return false;
|
|
}
|
|
return typeObj.generic_ret != null;
|
|
}
|
|
|
|
function renderFn(fnDecl) {
|
|
if ("refPath" in fnDecl.value.expr) {
|
|
let last = fnDecl.value.expr.refPath.length - 1;
|
|
let lastExpr = fnDecl.value.expr.refPath[last];
|
|
console.assert("declRef" in lastExpr);
|
|
fnDecl = zigAnalysis.decls[lastExpr.declRef];
|
|
}
|
|
|
|
let value = resolveValue(fnDecl.value);
|
|
console.assert("type" in value.expr);
|
|
let typeObj = zigAnalysis.types[value.expr.type];
|
|
|
|
domFnProtoCode.innerHTML = exprName(value.expr, {
|
|
wantHtml: true,
|
|
wantLink: true,
|
|
fnDecl,
|
|
});
|
|
|
|
let docsSource = null;
|
|
let srcNode = zigAnalysis.astNodes[fnDecl.src];
|
|
if (srcNode.docs != null) {
|
|
docsSource = srcNode.docs;
|
|
}
|
|
|
|
renderFnParamDocs(fnDecl, typeObj);
|
|
|
|
let retExpr = resolveValue({ expr: typeObj.ret }).expr;
|
|
if ("type" in retExpr) {
|
|
let retIndex = retExpr.type;
|
|
let errSetTypeIndex = null;
|
|
let retType = zigAnalysis.types[retIndex];
|
|
if (retType.kind === typeKinds.ErrorSet) {
|
|
errSetTypeIndex = retIndex;
|
|
} else if (retType.kind === typeKinds.ErrorUnion) {
|
|
errSetTypeIndex = retType.err.type;
|
|
}
|
|
if (errSetTypeIndex != null) {
|
|
let errSetType = zigAnalysis.types[errSetTypeIndex];
|
|
renderErrorSet(errSetType);
|
|
}
|
|
}
|
|
|
|
let protoSrcIndex = fnDecl.src;
|
|
if (typeIsGenericFn(value.expr.type)) {
|
|
// does the generic_ret contain a container?
|
|
var resolvedGenericRet = resolveValue({ expr: typeObj.generic_ret });
|
|
|
|
if ("call" in resolvedGenericRet.expr) {
|
|
let call = zigAnalysis.calls[resolvedGenericRet.expr.call];
|
|
let resolvedFunc = resolveValue({ expr: call.func });
|
|
if (!("type" in resolvedFunc.expr)) return;
|
|
let callee = zigAnalysis.types[resolvedFunc.expr.type];
|
|
if (!callee.generic_ret) return;
|
|
resolvedGenericRet = resolveValue({ expr: callee.generic_ret });
|
|
}
|
|
|
|
// TODO: see if unwrapping the `as` here is a good idea or not.
|
|
if ("as" in resolvedGenericRet.expr) {
|
|
resolvedGenericRet = {
|
|
expr: zigAnalysis.exprs[resolvedGenericRet.expr.as.exprArg],
|
|
};
|
|
}
|
|
|
|
if (!("type" in resolvedGenericRet.expr)) return;
|
|
const genericType = zigAnalysis.types[resolvedGenericRet.expr.type];
|
|
if (isContainerType(genericType)) {
|
|
renderContainer(genericType);
|
|
}
|
|
|
|
// old code
|
|
// let instantiations = nodesToFnsMap[protoSrcIndex];
|
|
// let calls = nodesToCallsMap[protoSrcIndex];
|
|
// if (instantiations == null && calls == null) {
|
|
// domFnNoExamples.classList.remove("hidden");
|
|
// } else if (calls != null) {
|
|
// // if (fnObj.combined === undefined) fnObj.combined = allCompTimeFnCallsResult(calls);
|
|
// if (fnObj.combined != null) renderContainer(fnObj.combined);
|
|
|
|
// resizeDomList(domListFnExamples, calls.length, '<li></li>');
|
|
|
|
// for (let callI = 0; callI < calls.length; callI += 1) {
|
|
// let liDom = domListFnExamples.children[callI];
|
|
// liDom.innerHTML = getCallHtml(fnDecl, calls[callI]);
|
|
// }
|
|
|
|
// domFnExamples.classList.remove("hidden");
|
|
// } else if (instantiations != null) {
|
|
// // TODO
|
|
// }
|
|
} else {
|
|
domFnExamples.classList.add("hidden");
|
|
domFnNoExamples.classList.add("hidden");
|
|
}
|
|
|
|
let protoSrcNode = zigAnalysis.astNodes[protoSrcIndex];
|
|
if (
|
|
docsSource == null &&
|
|
protoSrcNode != null &&
|
|
protoSrcNode.docs != null
|
|
) {
|
|
docsSource = protoSrcNode.docs;
|
|
}
|
|
if (docsSource != null) {
|
|
domTldDocs.innerHTML = markdown(docsSource);
|
|
domTldDocs.classList.remove("hidden");
|
|
}
|
|
domFnProto.classList.remove("hidden");
|
|
}
|
|
|
|
function renderFnParamDocs(fnDecl, typeObj) {
|
|
let docCount = 0;
|
|
|
|
let fnNode = zigAnalysis.astNodes[fnDecl.src];
|
|
let fields = fnNode.fields;
|
|
let isVarArgs = fnNode.varArgs;
|
|
|
|
for (let i = 0; i < fields.length; i += 1) {
|
|
let field = fields[i];
|
|
let fieldNode = zigAnalysis.astNodes[field];
|
|
if (fieldNode.docs != null) {
|
|
docCount += 1;
|
|
}
|
|
}
|
|
if (docCount == 0) {
|
|
return;
|
|
}
|
|
|
|
resizeDomList(domListParams, docCount, "<div></div>");
|
|
let domIndex = 0;
|
|
|
|
for (let i = 0; i < fields.length; i += 1) {
|
|
let field = fields[i];
|
|
let fieldNode = zigAnalysis.astNodes[field];
|
|
let docs = fieldNode.docs;
|
|
if (fieldNode.docs == null) {
|
|
continue;
|
|
}
|
|
let docsNonEmpty = docs !== "";
|
|
let divDom = domListParams.children[domIndex];
|
|
domIndex += 1;
|
|
|
|
let value = typeObj.params[i];
|
|
let preClass = docsNonEmpty ? ' class="fieldHasDocs"' : "";
|
|
let html = "<pre" + preClass + ">" + escapeHtml(fieldNode.name) + ": ";
|
|
if (isVarArgs && i === typeObj.params.length - 1) {
|
|
html += "...";
|
|
} else {
|
|
let name = exprName(value, { wantHtml: false, wantLink: false });
|
|
html += '<span class="tok-kw">' + name + "</span>";
|
|
}
|
|
|
|
html += ",</pre>";
|
|
|
|
if (docsNonEmpty) {
|
|
html += '<div class="fieldDocs">' + markdown(docs) + "</div>";
|
|
}
|
|
divDom.innerHTML = html;
|
|
}
|
|
domSectParams.classList.remove("hidden");
|
|
}
|
|
|
|
function renderNav() {
|
|
let len = curNav.pkgNames.length + curNav.declNames.length;
|
|
resizeDomList(domListNav, len, '<li><a href="#"></a></li>');
|
|
let list = [];
|
|
let hrefPkgNames = [];
|
|
let hrefDeclNames = [];
|
|
for (let i = 0; i < curNav.pkgNames.length; i += 1) {
|
|
hrefPkgNames.push(curNav.pkgNames[i]);
|
|
let name = curNav.pkgNames[i];
|
|
if (name == "root") name = zigAnalysis.rootPkgName;
|
|
list.push({
|
|
name: name,
|
|
link: navLink(hrefPkgNames, hrefDeclNames),
|
|
});
|
|
}
|
|
for (let i = 0; i < curNav.declNames.length; i += 1) {
|
|
hrefDeclNames.push(curNav.declNames[i]);
|
|
list.push({
|
|
name: curNav.declNames[i],
|
|
link: navLink(hrefPkgNames, hrefDeclNames),
|
|
});
|
|
}
|
|
|
|
for (let i = 0; i < list.length; i += 1) {
|
|
let liDom = domListNav.children[i];
|
|
let aDom = liDom.children[0];
|
|
aDom.textContent = list[i].name;
|
|
aDom.setAttribute("href", list[i].link);
|
|
if (i + 1 == list.length) {
|
|
aDom.classList.add("active");
|
|
} else {
|
|
aDom.classList.remove("active");
|
|
}
|
|
}
|
|
|
|
domSectNav.classList.remove("hidden");
|
|
}
|
|
|
|
function renderInfo() {
|
|
domTdZigVer.textContent = zigAnalysis.params.zigVersion;
|
|
//domTdTarget.textContent = zigAnalysis.params.builds[0].target;
|
|
|
|
domSectInfo.classList.remove("hidden");
|
|
}
|
|
|
|
function render404() {
|
|
domStatus.textContent = "404 Not Found";
|
|
domStatus.classList.remove("hidden");
|
|
}
|
|
|
|
function renderPkgList() {
|
|
let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
|
|
let list = [];
|
|
for (let key in rootPkg.table) {
|
|
let pkgIndex = rootPkg.table[key];
|
|
if (zigAnalysis.packages[pkgIndex] == null) continue;
|
|
if (key == zigAnalysis.params.rootName) continue;
|
|
list.push({
|
|
name: key,
|
|
pkg: pkgIndex,
|
|
});
|
|
}
|
|
|
|
{
|
|
let aDom = domSectMainPkg.children[1].children[0].children[0];
|
|
aDom.textContent = zigAnalysis.rootPkgName;
|
|
aDom.setAttribute("href", navLinkPkg(zigAnalysis.rootPkg));
|
|
if (zigAnalysis.params.rootName === curNav.pkgNames[0]) {
|
|
aDom.classList.add("active");
|
|
} else {
|
|
aDom.classList.remove("active");
|
|
}
|
|
domSectMainPkg.classList.remove("hidden");
|
|
}
|
|
|
|
list.sort(function (a, b) {
|
|
return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
|
|
});
|
|
|
|
if (list.length !== 0) {
|
|
resizeDomList(domListPkgs, list.length, '<li><a href="#"></a></li>');
|
|
for (let i = 0; i < list.length; i += 1) {
|
|
let liDom = domListPkgs.children[i];
|
|
let aDom = liDom.children[0];
|
|
aDom.textContent = list[i].name;
|
|
aDom.setAttribute("href", navLinkPkg(list[i].pkg));
|
|
if (list[i].name === curNav.pkgNames[0]) {
|
|
aDom.classList.add("active");
|
|
} else {
|
|
aDom.classList.remove("active");
|
|
}
|
|
}
|
|
|
|
domSectPkgs.classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
function navLink(pkgNames, declNames, callName) {
|
|
let base = "#";
|
|
if (curNav.showPrivDecls) {
|
|
base += "*";
|
|
}
|
|
|
|
if (pkgNames.length === 0 && declNames.length === 0) {
|
|
return base;
|
|
} else if (declNames.length === 0 && callName == null) {
|
|
return base + pkgNames.join(".");
|
|
} else if (callName == null) {
|
|
return base + pkgNames.join(".") + ";" + declNames.join(".");
|
|
} else {
|
|
return (
|
|
base + pkgNames.join(".") + ";" + declNames.join(".") + ";" + callName
|
|
);
|
|
}
|
|
}
|
|
|
|
function navLinkPkg(pkgIndex) {
|
|
return navLink(canonPkgPaths[pkgIndex], []);
|
|
}
|
|
|
|
function navLinkDecl(childName) {
|
|
return navLink(curNav.pkgNames, curNav.declNames.concat([childName]));
|
|
}
|
|
|
|
//
|
|
// function navLinkCall(callObj) {
|
|
// let declNamesCopy = curNav.declNames.concat([]);
|
|
// let callName = (declNamesCopy.pop());
|
|
|
|
// callName += '(';
|
|
// for (let arg_i = 0; arg_i < callObj.args.length; arg_i += 1) {
|
|
// if (arg_i !== 0) callName += ',';
|
|
// let argObj = callObj.args[arg_i];
|
|
// callName += getValueText(argObj, argObj, false, false);
|
|
// }
|
|
// callName += ')';
|
|
|
|
// declNamesCopy.push(callName);
|
|
// return navLink(curNav.pkgNames, declNamesCopy);
|
|
// }
|
|
|
|
function resizeDomListDl(dlDom, desiredLen) {
|
|
// add the missing dom entries
|
|
for (let i = dlDom.childElementCount / 2; i < desiredLen; i += 1) {
|
|
dlDom.insertAdjacentHTML("beforeend", "<dt></dt><dd></dd>");
|
|
}
|
|
// remove extra dom entries
|
|
while (desiredLen < dlDom.childElementCount / 2) {
|
|
dlDom.removeChild(dlDom.lastChild);
|
|
dlDom.removeChild(dlDom.lastChild);
|
|
}
|
|
}
|
|
|
|
function resizeDomList(listDom, desiredLen, templateHtml) {
|
|
// add the missing dom entries
|
|
for (let i = listDom.childElementCount; i < desiredLen; i += 1) {
|
|
listDom.insertAdjacentHTML("beforeend", templateHtml);
|
|
}
|
|
// remove extra dom entries
|
|
while (desiredLen < listDom.childElementCount) {
|
|
listDom.removeChild(listDom.lastChild);
|
|
}
|
|
}
|
|
|
|
function walkResultTypeRef(wr) {
|
|
if (wr.typeRef) return wr.typeRef;
|
|
let resolved = resolveValue(wr);
|
|
if (wr === resolved) {
|
|
return { type: 0 };
|
|
}
|
|
return walkResultTypeRef(resolved);
|
|
}
|
|
|
|
function exprName(expr, opts) {
|
|
switch (Object.keys(expr)[0]) {
|
|
default:
|
|
throw "this expression is not implemented yet";
|
|
case "bool": {
|
|
if (expr.bool) {
|
|
return "true";
|
|
}
|
|
return "false";
|
|
}
|
|
case "&": {
|
|
return "&" + exprName(zigAnalysis.exprs[expr["&"]]);
|
|
}
|
|
case "compileError": {
|
|
let compileError = expr.compileError;
|
|
return compileError;
|
|
}
|
|
case "enumLiteral": {
|
|
let literal = expr.enumLiteral;
|
|
return "." + literal;
|
|
}
|
|
case "void": {
|
|
return "void";
|
|
}
|
|
case "slice": {
|
|
let payloadHtml = "";
|
|
const lhsExpr = zigAnalysis.exprs[expr.slice.lhs];
|
|
const startExpr = zigAnalysis.exprs[expr.slice.start];
|
|
let decl = exprName(lhsExpr);
|
|
let start = exprName(startExpr);
|
|
let end = "";
|
|
let sentinel = "";
|
|
if (expr.slice["end"]) {
|
|
const endExpr = zigAnalysis.exprs[expr.slice.end];
|
|
let end_ = exprName(endExpr);
|
|
end += end_;
|
|
}
|
|
if (expr.slice["sentinel"]) {
|
|
const sentinelExpr = zigAnalysis.exprs[expr.slice.sentinel];
|
|
let sentinel_ = exprName(sentinelExpr);
|
|
sentinel += " :" + sentinel_;
|
|
}
|
|
payloadHtml += decl + "[" + start + ".." + end + sentinel + "]";
|
|
return payloadHtml;
|
|
}
|
|
case "sliceIndex": {
|
|
const sliceIndex = zigAnalysis.exprs[expr.sliceIndex];
|
|
return exprName(sliceIndex, opts);
|
|
}
|
|
case "cmpxchg": {
|
|
const typeIndex = zigAnalysis.exprs[expr.cmpxchg.type];
|
|
const ptrIndex = zigAnalysis.exprs[expr.cmpxchg.ptr];
|
|
const expectedValueIndex =
|
|
zigAnalysis.exprs[expr.cmpxchg.expected_value];
|
|
const newValueIndex = zigAnalysis.exprs[expr.cmpxchg.new_value];
|
|
const successOrderIndex = zigAnalysis.exprs[expr.cmpxchg.success_order];
|
|
const failureOrderIndex = zigAnalysis.exprs[expr.cmpxchg.failure_order];
|
|
|
|
const type = exprName(typeIndex, opts);
|
|
const ptr = exprName(ptrIndex, opts);
|
|
const expectedValue = exprName(expectedValueIndex, opts);
|
|
const newValue = exprName(newValueIndex, opts);
|
|
const successOrder = exprName(successOrderIndex, opts);
|
|
const failureOrder = exprName(failureOrderIndex, opts);
|
|
|
|
let fnName = "@";
|
|
|
|
switch (expr.cmpxchg.name) {
|
|
case "cmpxchg_strong": {
|
|
fnName += "cmpxchgStrong";
|
|
break;
|
|
}
|
|
case "cmpxchg_weak": {
|
|
fnName += "cmpxchgWeak";
|
|
break;
|
|
}
|
|
default: {
|
|
console.log("There's only cmpxchg_strong and cmpxchg_weak");
|
|
}
|
|
}
|
|
|
|
return (
|
|
fnName +
|
|
"(" +
|
|
type +
|
|
", " +
|
|
ptr +
|
|
", " +
|
|
expectedValue +
|
|
", " +
|
|
newValue +
|
|
", " +
|
|
"." +
|
|
successOrder +
|
|
", " +
|
|
"." +
|
|
failureOrder +
|
|
")"
|
|
);
|
|
}
|
|
case "cmpxchgIndex": {
|
|
const cmpxchgIndex = zigAnalysis.exprs[expr.cmpxchgIndex];
|
|
return exprName(cmpxchgIndex, opts);
|
|
}
|
|
case "switchOp": {
|
|
let condExpr = zigAnalysis.exprs[expr.switchOp.cond_index];
|
|
let ast = zigAnalysis.astNodes[expr.switchOp.ast];
|
|
let file_name = expr.switchOp.file_name;
|
|
let outer_decl_index = expr.switchOp.outer_decl;
|
|
let outer_decl = zigAnalysis.types[outer_decl_index];
|
|
let line = 0;
|
|
// console.log(expr.switchOp)
|
|
// console.log(outer_decl)
|
|
while (outer_decl_index !== 0 && outer_decl.line_number > 0) {
|
|
line += outer_decl.line_number;
|
|
outer_decl_index = outer_decl.outer_decl;
|
|
outer_decl = zigAnalysis.types[outer_decl_index];
|
|
// console.log(outer_decl)
|
|
}
|
|
line += ast.line + 1;
|
|
let payloadHtml = "";
|
|
let cond = exprName(condExpr, opts);
|
|
|
|
payloadHtml +=
|
|
"</br>" +
|
|
"node_name: " +
|
|
ast.name +
|
|
"</br>" +
|
|
"file: " +
|
|
file_name +
|
|
"</br>" +
|
|
"line: " +
|
|
line +
|
|
"</br>";
|
|
payloadHtml +=
|
|
"switch(" +
|
|
cond +
|
|
") {" +
|
|
'<a href="https://github.com/ziglang/zig/tree/master/lib/std/' +
|
|
file_name +
|
|
"#L" +
|
|
line +
|
|
'">' +
|
|
"..." +
|
|
"</a>}";
|
|
return payloadHtml;
|
|
}
|
|
case "switchIndex": {
|
|
const switchIndex = zigAnalysis.exprs[expr.switchIndex];
|
|
return exprName(switchIndex, opts);
|
|
}
|
|
case "refPath": {
|
|
let name = exprName(expr.refPath[0]);
|
|
for (let i = 1; i < expr.refPath.length; i++) {
|
|
let component = undefined;
|
|
if ("string" in expr.refPath[i]) {
|
|
component = expr.refPath[i].string;
|
|
} else {
|
|
component = exprName(expr.refPath[i]);
|
|
}
|
|
name += "." + component;
|
|
}
|
|
return name;
|
|
}
|
|
case "fieldRef": {
|
|
const enumObj = exprName({ type: expr.fieldRef.type }, opts);
|
|
const field =
|
|
zigAnalysis.astNodes[enumObj.ast].fields[expr.fieldRef.index];
|
|
const name = zigAnalysis.astNodes[field].name;
|
|
return name;
|
|
}
|
|
case "enumToInt": {
|
|
const enumToInt = zigAnalysis.exprs[expr.enumToInt];
|
|
return "@enumToInt(" + exprName(enumToInt, opts) + ")";
|
|
}
|
|
case "bitSizeOf": {
|
|
const bitSizeOf = zigAnalysis.exprs[expr.bitSizeOf];
|
|
return "@bitSizeOf(" + exprName(bitSizeOf, opts) + ")";
|
|
}
|
|
case "sizeOf": {
|
|
const sizeOf = zigAnalysis.exprs[expr.sizeOf];
|
|
return "@sizeOf(" + exprName(sizeOf, opts) + ")";
|
|
}
|
|
case "builtinIndex": {
|
|
const builtinIndex = zigAnalysis.exprs[expr.builtinIndex];
|
|
return exprName(builtinIndex, opts);
|
|
}
|
|
case "builtin": {
|
|
const param_expr = zigAnalysis.exprs[expr.builtin.param];
|
|
let param = exprName(param_expr, opts);
|
|
|
|
let payloadHtml = "@";
|
|
switch (expr.builtin.name) {
|
|
case "align_of": {
|
|
payloadHtml += "alignOf";
|
|
break;
|
|
}
|
|
case "bool_to_int": {
|
|
payloadHtml += "boolToInt";
|
|
break;
|
|
}
|
|
case "embed_file": {
|
|
payloadHtml += "embedFile";
|
|
break;
|
|
}
|
|
case "error_name": {
|
|
payloadHtml += "errorName";
|
|
break;
|
|
}
|
|
case "panic": {
|
|
payloadHtml += "panic";
|
|
break;
|
|
}
|
|
case "set_cold": {
|
|
payloadHtml += "setCold";
|
|
break;
|
|
}
|
|
case "set_runtime_safety": {
|
|
payloadHtml += "setRuntimeSafety";
|
|
break;
|
|
}
|
|
case "sqrt": {
|
|
payloadHtml += "sqrt";
|
|
break;
|
|
}
|
|
case "sin": {
|
|
payloadHtml += "sin";
|
|
break;
|
|
}
|
|
case "cos": {
|
|
payloadHtml += "cos";
|
|
break;
|
|
}
|
|
case "tan": {
|
|
payloadHtml += "tan";
|
|
break;
|
|
}
|
|
case "exp": {
|
|
payloadHtml += "exp";
|
|
break;
|
|
}
|
|
case "exp2": {
|
|
payloadHtml += "exp2";
|
|
break;
|
|
}
|
|
case "log": {
|
|
payloadHtml += "log";
|
|
break;
|
|
}
|
|
case "log2": {
|
|
payloadHtml += "log2";
|
|
break;
|
|
}
|
|
case "log10": {
|
|
payloadHtml += "log10";
|
|
break;
|
|
}
|
|
case "fabs": {
|
|
payloadHtml += "fabs";
|
|
break;
|
|
}
|
|
case "floor": {
|
|
payloadHtml += "floor";
|
|
break;
|
|
}
|
|
case "ceil": {
|
|
payloadHtml += "ceil";
|
|
break;
|
|
}
|
|
case "trunc": {
|
|
payloadHtml += "trunc";
|
|
break;
|
|
}
|
|
case "round": {
|
|
payloadHtml += "round";
|
|
break;
|
|
}
|
|
case "tag_name": {
|
|
payloadHtml += "tagName";
|
|
break;
|
|
}
|
|
case "reify": {
|
|
payloadHtml += "Type";
|
|
break;
|
|
}
|
|
case "type_name": {
|
|
payloadHtml += "typeName";
|
|
break;
|
|
}
|
|
case "frame_type": {
|
|
payloadHtml += "Frame";
|
|
break;
|
|
}
|
|
case "frame_size": {
|
|
payloadHtml += "frameSize";
|
|
break;
|
|
}
|
|
case "ptr_to_int": {
|
|
payloadHtml += "ptrToInt";
|
|
break;
|
|
}
|
|
case "error_to_int": {
|
|
payloadHtml += "errorToInt";
|
|
break;
|
|
}
|
|
case "int_to_error": {
|
|
payloadHtml += "intToError";
|
|
break;
|
|
}
|
|
case "maximum": {
|
|
payloadHtml += "maximum";
|
|
break;
|
|
}
|
|
case "minimum": {
|
|
payloadHtml += "minimum";
|
|
break;
|
|
}
|
|
case "bit_not": {
|
|
return "~" + param;
|
|
}
|
|
case "clz": {
|
|
return "@clz(T" + ", " + param + ")";
|
|
}
|
|
case "ctz": {
|
|
return "@ctz(T" + ", " + param + ")";
|
|
}
|
|
case "pop_count": {
|
|
return "@popCount(T" + ", " + param + ")";
|
|
}
|
|
case "byte_swap": {
|
|
return "@byteSwap(T" + ", " + param + ")";
|
|
}
|
|
case "bit_reverse": {
|
|
return "@bitReverse(T" + ", " + param + ")";
|
|
}
|
|
default:
|
|
console.log("builtin function not handled yet or doesn't exist!");
|
|
}
|
|
return payloadHtml + "(" + param + ")";
|
|
}
|
|
case "builtinBinIndex": {
|
|
const builtinBinIndex = zigAnalysis.exprs[expr.builtinBinIndex];
|
|
return exprName(builtinBinIndex, opts);
|
|
}
|
|
case "builtinBin": {
|
|
const lhsOp = zigAnalysis.exprs[expr.builtinBin.lhs];
|
|
const rhsOp = zigAnalysis.exprs[expr.builtinBin.rhs];
|
|
let lhs = exprName(lhsOp, opts);
|
|
let rhs = exprName(rhsOp, opts);
|
|
|
|
let payloadHtml = "@";
|
|
switch (expr.builtinBin.name) {
|
|
case "float_to_int": {
|
|
payloadHtml += "floatToInt";
|
|
break;
|
|
}
|
|
case "int_to_float": {
|
|
payloadHtml += "intToFloat";
|
|
break;
|
|
}
|
|
case "int_to_ptr": {
|
|
payloadHtml += "intToPtr";
|
|
break;
|
|
}
|
|
case "int_to_enum": {
|
|
payloadHtml += "intToEnum";
|
|
break;
|
|
}
|
|
case "float_cast": {
|
|
payloadHtml += "floatCast";
|
|
break;
|
|
}
|
|
case "int_cast": {
|
|
payloadHtml += "intCast";
|
|
break;
|
|
}
|
|
case "ptr_cast": {
|
|
payloadHtml += "ptrCast";
|
|
break;
|
|
}
|
|
case "truncate": {
|
|
payloadHtml += "truncate";
|
|
break;
|
|
}
|
|
case "align_cast": {
|
|
payloadHtml += "alignCast";
|
|
break;
|
|
}
|
|
case "has_decl": {
|
|
payloadHtml += "hasDecl";
|
|
break;
|
|
}
|
|
case "has_field": {
|
|
payloadHtml += "hasField";
|
|
break;
|
|
}
|
|
case "bit_reverse": {
|
|
payloadHtml += "bitReverse";
|
|
break;
|
|
}
|
|
case "div_exact": {
|
|
payloadHtml += "divExact";
|
|
break;
|
|
}
|
|
case "div_floor": {
|
|
payloadHtml += "divFloor";
|
|
break;
|
|
}
|
|
case "div_trunc": {
|
|
payloadHtml += "divTrunc";
|
|
break;
|
|
}
|
|
case "mod": {
|
|
payloadHtml += "mod";
|
|
break;
|
|
}
|
|
case "rem": {
|
|
payloadHtml += "rem";
|
|
break;
|
|
}
|
|
case "mod_rem": {
|
|
payloadHtml += "rem";
|
|
break;
|
|
}
|
|
case "shl_exact": {
|
|
payloadHtml += "shlExact";
|
|
break;
|
|
}
|
|
case "shr_exact": {
|
|
payloadHtml += "shrExact";
|
|
break;
|
|
}
|
|
case "bitcast": {
|
|
payloadHtml += "bitCast";
|
|
break;
|
|
}
|
|
case "align_cast": {
|
|
payloadHtml += "alignCast";
|
|
break;
|
|
}
|
|
case "vector_type": {
|
|
payloadHtml += "Vector";
|
|
break;
|
|
}
|
|
case "reduce": {
|
|
payloadHtml += "reduce";
|
|
break;
|
|
}
|
|
case "splat": {
|
|
payloadHtml += "splat";
|
|
break;
|
|
}
|
|
case "offset_of": {
|
|
payloadHtml += "offsetOf";
|
|
break;
|
|
}
|
|
case "bit_offset_of": {
|
|
payloadHtml += "bitOffsetOf";
|
|
break;
|
|
}
|
|
default:
|
|
console.log("builtin function not handled yet or doesn't exist!");
|
|
}
|
|
return payloadHtml + "(" + lhs + ", " + rhs + ")";
|
|
}
|
|
case "binOpIndex": {
|
|
const binOpIndex = zigAnalysis.exprs[expr.binOpIndex];
|
|
return exprName(binOpIndex, opts);
|
|
}
|
|
case "binOp": {
|
|
const lhsOp = zigAnalysis.exprs[expr.binOp.lhs];
|
|
const rhsOp = zigAnalysis.exprs[expr.binOp.rhs];
|
|
let lhs = exprName(lhsOp, opts);
|
|
let rhs = exprName(rhsOp, opts);
|
|
|
|
let print_lhs = "";
|
|
let print_rhs = "";
|
|
|
|
if (lhsOp["binOpIndex"]) {
|
|
print_lhs = "(" + lhs + ")";
|
|
} else {
|
|
print_lhs = lhs;
|
|
}
|
|
if (rhsOp["binOpIndex"]) {
|
|
print_rhs = "(" + rhs + ")";
|
|
} else {
|
|
print_rhs = rhs;
|
|
}
|
|
|
|
let operator = "";
|
|
|
|
switch (expr.binOp.name) {
|
|
case "add": {
|
|
operator += "+";
|
|
break;
|
|
}
|
|
case "addwrap": {
|
|
operator += "+%";
|
|
break;
|
|
}
|
|
case "add_sat": {
|
|
operator += "+|";
|
|
break;
|
|
}
|
|
case "sub": {
|
|
operator += "-";
|
|
break;
|
|
}
|
|
case "subwrap": {
|
|
operator += "-%";
|
|
break;
|
|
}
|
|
case "sub_sat": {
|
|
operator += "-|";
|
|
break;
|
|
}
|
|
case "mul": {
|
|
operator += "*";
|
|
break;
|
|
}
|
|
case "mulwrap": {
|
|
operator += "*%";
|
|
break;
|
|
}
|
|
case "mul_sat": {
|
|
operator += "*|";
|
|
break;
|
|
}
|
|
case "div": {
|
|
operator += "/";
|
|
break;
|
|
}
|
|
case "shl": {
|
|
operator += "<<";
|
|
break;
|
|
}
|
|
case "shl_sat": {
|
|
operator += "<<|";
|
|
break;
|
|
}
|
|
case "shr": {
|
|
operator += ">>";
|
|
break;
|
|
}
|
|
case "bit_or": {
|
|
operator += "|";
|
|
break;
|
|
}
|
|
case "bit_and": {
|
|
operator += "&";
|
|
break;
|
|
}
|
|
case "array_cat": {
|
|
operator += "++";
|
|
break;
|
|
}
|
|
case "array_mul": {
|
|
operator += "**";
|
|
break;
|
|
}
|
|
default:
|
|
console.log("operator not handled yet or doesn't exist!");
|
|
}
|
|
|
|
return print_lhs + " " + operator + " " + print_rhs;
|
|
}
|
|
case "errorSets": {
|
|
const errUnionObj = zigAnalysis.types[expr.errorSets];
|
|
let lhs = exprName(errUnionObj.lhs, opts);
|
|
let rhs = exprName(errUnionObj.rhs, opts);
|
|
return lhs + " || " + rhs;
|
|
}
|
|
case "errorUnion": {
|
|
const errUnionObj = zigAnalysis.types[expr.errorUnion];
|
|
let lhs = exprName(errUnionObj.lhs, opts);
|
|
let rhs = exprName(errUnionObj.rhs, opts);
|
|
return lhs + "!" + rhs;
|
|
}
|
|
case "struct": {
|
|
const struct_name =
|
|
zigAnalysis.decls[expr.struct[0].val.typeRef.refPath[0].declRef].name;
|
|
let struct_body = "";
|
|
struct_body += struct_name + "{ ";
|
|
for (let i = 0; i < expr.struct.length; i++) {
|
|
const val = expr.struct[i].name;
|
|
const exprArg = zigAnalysis.exprs[expr.struct[i].val.expr.as.exprArg];
|
|
let value_field = exprArg[Object.keys(exprArg)[0]];
|
|
if (value_field instanceof Object) {
|
|
value_field =
|
|
zigAnalysis.decls[value_field[0].val.typeRef.refPath[0].declRef]
|
|
.name;
|
|
}
|
|
struct_body += "." + val + " = " + value_field;
|
|
if (i !== expr.struct.length - 1) {
|
|
struct_body += ", ";
|
|
} else {
|
|
struct_body += " ";
|
|
}
|
|
}
|
|
struct_body += "}";
|
|
return struct_body;
|
|
}
|
|
case "typeOf_peer": {
|
|
let payloadHtml = "@TypeOf(";
|
|
for (let i = 0; i < expr.typeOf_peer.length; i++) {
|
|
let elem = zigAnalysis.exprs[expr.typeOf_peer[i]];
|
|
payloadHtml += exprName(elem, { wantHtml: true, wantLink: true });
|
|
if (i !== expr.typeOf_peer.length - 1) {
|
|
payloadHtml += ", ";
|
|
}
|
|
}
|
|
payloadHtml += ")";
|
|
return payloadHtml;
|
|
}
|
|
case "alignOf": {
|
|
const alignRefArg = zigAnalysis.exprs[expr.alignOf];
|
|
let payloadHtml =
|
|
"@alignOf(" +
|
|
exprName(alignRefArg, { wantHtml: true, wantLink: true }) +
|
|
")";
|
|
return payloadHtml;
|
|
}
|
|
case "typeOf": {
|
|
const typeRefArg = zigAnalysis.exprs[expr.typeOf];
|
|
let payloadHtml =
|
|
"@TypeOf(" +
|
|
exprName(typeRefArg, { wantHtml: true, wantLink: true }) +
|
|
")";
|
|
return payloadHtml;
|
|
}
|
|
case "typeInfo": {
|
|
const typeRefArg = zigAnalysis.exprs[expr.typeInfo];
|
|
let payloadHtml =
|
|
"@typeInfo(" +
|
|
exprName(typeRefArg, { wantHtml: true, wantLink: true }) +
|
|
")";
|
|
return payloadHtml;
|
|
}
|
|
case "null": {
|
|
return "null";
|
|
}
|
|
case "array": {
|
|
let payloadHtml = ".{";
|
|
for (let i = 0; i < expr.array.length; i++) {
|
|
if (i != 0) payloadHtml += ", ";
|
|
let elem = zigAnalysis.exprs[expr.array[i]];
|
|
payloadHtml += exprName(elem, opts);
|
|
}
|
|
return payloadHtml + "}";
|
|
}
|
|
case "comptimeExpr": {
|
|
return zigAnalysis.comptimeExprs[expr.comptimeExpr].code;
|
|
}
|
|
case "call": {
|
|
let call = zigAnalysis.calls[expr.call];
|
|
let payloadHtml = "";
|
|
|
|
switch (Object.keys(call.func)[0]) {
|
|
default:
|
|
throw "TODO";
|
|
case "declRef":
|
|
case "refPath": {
|
|
payloadHtml += exprName(call.func, opts);
|
|
break;
|
|
}
|
|
}
|
|
payloadHtml += "(";
|
|
|
|
for (let i = 0; i < call.args.length; i++) {
|
|
if (i != 0) payloadHtml += ", ";
|
|
payloadHtml += exprName(call.args[i], opts);
|
|
}
|
|
|
|
payloadHtml += ")";
|
|
return payloadHtml;
|
|
}
|
|
case "as": {
|
|
// @Check : this should be done in backend because there are legit @as() calls
|
|
// const typeRefArg = zigAnalysis.exprs[expr.as.typeRefArg];
|
|
const exprArg = zigAnalysis.exprs[expr.as.exprArg];
|
|
// return "@as(" + exprName(typeRefArg, opts) +
|
|
// ", " + exprName(exprArg, opts) + ")";
|
|
return exprName(exprArg, opts);
|
|
}
|
|
case "declRef": {
|
|
return zigAnalysis.decls[expr.declRef].name;
|
|
}
|
|
case "refPath": {
|
|
return expr.refPath.map((x) => exprName(x, opts)).join(".");
|
|
}
|
|
case "int": {
|
|
return "" + expr.int;
|
|
}
|
|
case "float": {
|
|
return "" + expr.float.toFixed(2);
|
|
}
|
|
case "float128": {
|
|
return "" + expr.float128.toFixed(2);
|
|
}
|
|
case "undefined": {
|
|
return "undefined";
|
|
}
|
|
case "string": {
|
|
return '"' + escapeHtml(expr.string) + '"';
|
|
}
|
|
|
|
case "anytype": {
|
|
return "anytype";
|
|
}
|
|
|
|
case "this": {
|
|
return "@This()";
|
|
}
|
|
|
|
case "type": {
|
|
let name = "";
|
|
|
|
let typeObj = expr.type;
|
|
if (typeof typeObj === "number") typeObj = zigAnalysis.types[typeObj];
|
|
switch (typeObj.kind) {
|
|
default:
|
|
throw "TODO";
|
|
case typeKinds.Struct: {
|
|
let structObj = typeObj;
|
|
return structObj;
|
|
}
|
|
case typeKinds.Enum: {
|
|
let enumObj = typeObj;
|
|
return enumObj;
|
|
}
|
|
case typeKinds.Opaque: {
|
|
let opaqueObj = typeObj;
|
|
|
|
return opaqueObj.name;
|
|
}
|
|
case typeKinds.ComptimeExpr: {
|
|
return "anyopaque";
|
|
}
|
|
case typeKinds.Array: {
|
|
let arrayObj = typeObj;
|
|
let name = "[";
|
|
let lenName = exprName(arrayObj.len, opts);
|
|
let sentinel = arrayObj.sentinel
|
|
? ":" + exprName(arrayObj.sentinel, opts)
|
|
: "";
|
|
// let is_mutable = arrayObj.is_multable ? "const " : "";
|
|
|
|
if (opts.wantHtml) {
|
|
name +=
|
|
'<span class="tok-number">' + lenName + sentinel + "</span>";
|
|
} else {
|
|
name += lenName + sentinel;
|
|
}
|
|
name += "]";
|
|
// name += is_mutable;
|
|
name += exprName(arrayObj.child, opts);
|
|
return name;
|
|
}
|
|
case typeKinds.Optional:
|
|
return "?" + exprName(typeObj.child, opts);
|
|
case typeKinds.Pointer: {
|
|
let ptrObj = typeObj;
|
|
let sentinel = ptrObj.sentinel
|
|
? ":" + exprName(ptrObj.sentinel, opts)
|
|
: "";
|
|
let is_mutable = !ptrObj.is_mutable ? "const " : "";
|
|
let name = "";
|
|
switch (ptrObj.size) {
|
|
default:
|
|
console.log("TODO: implement unhandled pointer size case");
|
|
case pointerSizeEnum.One:
|
|
name += "*";
|
|
name += is_mutable;
|
|
break;
|
|
case pointerSizeEnum.Many:
|
|
name += "[*";
|
|
name += sentinel;
|
|
name += "]";
|
|
name += is_mutable;
|
|
break;
|
|
case pointerSizeEnum.Slice:
|
|
if (ptrObj.is_ref) {
|
|
name += "*";
|
|
}
|
|
name += "[";
|
|
name += sentinel;
|
|
name += "]";
|
|
name += is_mutable;
|
|
break;
|
|
case pointerSizeEnum.C:
|
|
name += "[*c";
|
|
name += sentinel;
|
|
name += "]";
|
|
name += is_mutable;
|
|
break;
|
|
}
|
|
// @check: after the major changes in arrays the consts are came from switch above
|
|
// if (!ptrObj.is_mutable) {
|
|
// if (opts.wantHtml) {
|
|
// name += '<span class="tok-kw">const</span> ';
|
|
// } else {
|
|
// name += "const ";
|
|
// }
|
|
// }
|
|
if (ptrObj.is_allowzero) {
|
|
name += "allowzero ";
|
|
}
|
|
if (ptrObj.is_volatile) {
|
|
name += "volatile ";
|
|
}
|
|
if (ptrObj.has_addrspace) {
|
|
name += "addrspace(";
|
|
name += "." + "";
|
|
name += ") ";
|
|
}
|
|
if (ptrObj.has_align) {
|
|
let align = exprName(ptrObj.align, opts);
|
|
if (opts.wantHtml) {
|
|
name += '<span class="tok-kw">align</span>(';
|
|
} else {
|
|
name += "align(";
|
|
}
|
|
if (opts.wantHtml) {
|
|
name += '<span class="tok-number">' + align + "</span>";
|
|
} else {
|
|
name += align;
|
|
}
|
|
if (ptrObj.hostIntBytes != null) {
|
|
name += ":";
|
|
if (opts.wantHtml) {
|
|
name +=
|
|
'<span class="tok-number">' +
|
|
ptrObj.bitOffsetInHost +
|
|
"</span>";
|
|
} else {
|
|
name += ptrObj.bitOffsetInHost;
|
|
}
|
|
name += ":";
|
|
if (opts.wantHtml) {
|
|
name +=
|
|
'<span class="tok-number">' +
|
|
ptrObj.hostIntBytes +
|
|
"</span>";
|
|
} else {
|
|
name += ptrObj.hostIntBytes;
|
|
}
|
|
}
|
|
name += ") ";
|
|
}
|
|
//name += typeValueName(ptrObj.child, wantHtml, wantSubLink, null);
|
|
name += exprName(ptrObj.child, opts);
|
|
return name;
|
|
}
|
|
case typeKinds.Float: {
|
|
let floatObj = typeObj;
|
|
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">' + floatObj.name + "</span>";
|
|
} else {
|
|
return floatObj.name;
|
|
}
|
|
}
|
|
case typeKinds.Int: {
|
|
let intObj = typeObj;
|
|
let name = intObj.name;
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">' + name + "</span>";
|
|
} else {
|
|
return name;
|
|
}
|
|
}
|
|
case typeKinds.ComptimeInt:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">comptime_int</span>';
|
|
} else {
|
|
return "comptime_int";
|
|
}
|
|
case typeKinds.ComptimeFloat:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">comptime_float</span>';
|
|
} else {
|
|
return "comptime_float";
|
|
}
|
|
case typeKinds.Type:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">type</span>';
|
|
} else {
|
|
return "type";
|
|
}
|
|
case typeKinds.Bool:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">bool</span>';
|
|
} else {
|
|
return "bool";
|
|
}
|
|
case typeKinds.Void:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">void</span>';
|
|
} else {
|
|
return "void";
|
|
}
|
|
case typeKinds.EnumLiteral:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">(enum literal)</span>';
|
|
} else {
|
|
return "(enum literal)";
|
|
}
|
|
case typeKinds.NoReturn:
|
|
if (opts.wantHtml) {
|
|
return '<span class="tok-type">noreturn</span>';
|
|
} else {
|
|
return "noreturn";
|
|
}
|
|
case typeKinds.ErrorSet: {
|
|
let errSetObj = typeObj;
|
|
if (errSetObj.fields == null) {
|
|
return '<span class="tok-type">anyerror</span>';
|
|
} else {
|
|
// throw "TODO";
|
|
let html = "error{" + errSetObj.fields[0].name + "}";
|
|
return html;
|
|
}
|
|
}
|
|
|
|
case typeKinds.ErrorUnion: {
|
|
let errUnionObj = typeObj;
|
|
let lhs = exprName(errUnionObj.lhs, opts);
|
|
let rhs = exprName(errUnionObj.rhs, opts);
|
|
return lhs + "!" + rhs;
|
|
}
|
|
case typeKinds.InferredErrorUnion: {
|
|
let errUnionObj = typeObj;
|
|
let payload = exprName(errUnionObj.payload, opts);
|
|
return "!" + payload;
|
|
}
|
|
case typeKinds.Fn: {
|
|
let fnObj = typeObj;
|
|
let payloadHtml = "";
|
|
if (opts.wantHtml) {
|
|
if (fnObj.is_extern) {
|
|
payloadHtml += "pub extern ";
|
|
}
|
|
if (fnObj.has_lib_name) {
|
|
payloadHtml += '"' + fnObj.lib_name + '" ';
|
|
}
|
|
payloadHtml += '<span class="tok-kw">fn</span>';
|
|
if (opts.fnDecl) {
|
|
payloadHtml += ' <span class="tok-fn">';
|
|
if (opts.linkFnNameDecl) {
|
|
payloadHtml +=
|
|
'<a href="' +
|
|
opts.linkFnNameDecl +
|
|
'">' +
|
|
escapeHtml(opts.fnDecl.name) +
|
|
"</a>";
|
|
} else {
|
|
payloadHtml += escapeHtml(opts.fnDecl.name);
|
|
}
|
|
payloadHtml += "</span>";
|
|
}
|
|
} else {
|
|
payloadHtml += "fn ";
|
|
}
|
|
payloadHtml += "(";
|
|
if (fnObj.params) {
|
|
let fields = null;
|
|
let isVarArgs = false;
|
|
let fnNode = zigAnalysis.astNodes[fnObj.src];
|
|
fields = fnNode.fields;
|
|
isVarArgs = fnNode.varArgs;
|
|
|
|
for (let i = 0; i < fnObj.params.length; i += 1) {
|
|
if (i != 0) {
|
|
payloadHtml += ", ";
|
|
}
|
|
|
|
payloadHtml +=
|
|
"<span class='argBreaker'><br> </span>";
|
|
let value = fnObj.params[i];
|
|
let paramValue = resolveValue({ expr: value });
|
|
|
|
if (fields != null) {
|
|
let paramNode = zigAnalysis.astNodes[fields[i]];
|
|
|
|
if (paramNode.varArgs) {
|
|
payloadHtml += "...";
|
|
continue;
|
|
}
|
|
|
|
if (paramNode.noalias) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<span class="tok-kw">noalias</span> ';
|
|
} else {
|
|
payloadHtml += "noalias ";
|
|
}
|
|
}
|
|
|
|
if (paramNode.comptime) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<span class="tok-kw">comptime</span> ';
|
|
} else {
|
|
payloadHtml += "comptime ";
|
|
}
|
|
}
|
|
|
|
let paramName = paramNode.name;
|
|
if (paramName != null) {
|
|
// skip if it matches the type name
|
|
if (!shouldSkipParamName(paramValue, paramName)) {
|
|
payloadHtml += paramName + ": ";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isVarArgs && i === fnObj.params.length - 1) {
|
|
payloadHtml += "...";
|
|
} else if ("alignOf" in value) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<a href="">';
|
|
payloadHtml +=
|
|
'<span class="tok-kw" style="color:lightblue;">' +
|
|
exprName(value, opts) +
|
|
"</span>";
|
|
payloadHtml += "</a>";
|
|
} else {
|
|
payloadHtml += exprName(value, opts);
|
|
}
|
|
} else if ("typeOf" in value) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<a href="">';
|
|
payloadHtml +=
|
|
'<span class="tok-kw" style="color:lightblue;">' +
|
|
exprName(value, opts) +
|
|
"</span>";
|
|
payloadHtml += "</a>";
|
|
} else {
|
|
payloadHtml += exprName(value, opts);
|
|
}
|
|
} else if ("typeOf_peer" in value) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<a href="">';
|
|
payloadHtml +=
|
|
'<span class="tok-kw" style="color:lightblue;">' +
|
|
exprName(value, opts) +
|
|
"</span>";
|
|
payloadHtml += "</a>";
|
|
} else {
|
|
payloadHtml += exprName(value, opts);
|
|
}
|
|
} else if ("declRef" in value) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<a href="">';
|
|
payloadHtml +=
|
|
'<span class="tok-kw" style="color:lightblue;">' +
|
|
exprName(value, opts) +
|
|
"</span>";
|
|
payloadHtml += "</a>";
|
|
} else {
|
|
payloadHtml += exprName(value, opts);
|
|
}
|
|
} else if ("call" in value) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<a href="">';
|
|
payloadHtml +=
|
|
'<span class="tok-kw" style="color:lightblue;">' +
|
|
exprName(value, opts) +
|
|
"</span>";
|
|
payloadHtml += "</a>";
|
|
} else {
|
|
payloadHtml += exprName(value, opts);
|
|
}
|
|
} else if ("refPath" in value) {
|
|
if (opts.wantHtml) {
|
|
payloadHtml += '<a href="">';
|
|
payloadHtml +=
|
|
'<span class="tok-kw" style="color:lightblue;">' +
|
|
exprName(value, opts) +
|
|
"</span>";
|
|
payloadHtml += "</a>";
|
|
} else {
|
|
payloadHtml += exprName(value, opts);
|
|
}
|
|
} else if ("type" in value) {
|
|
let name = exprName(value, {
|
|
wantHtml: false,
|
|
wantLink: false,
|
|
fnDecl: opts.fnDecl,
|
|
linkFnNameDecl: opts.linkFnNameDecl,
|
|
});
|
|
payloadHtml += '<span class="tok-kw">' + name + "</span>";
|
|
} else if ("binOpIndex" in value) {
|
|
payloadHtml += exprName(value, opts);
|
|
} else if ("comptimeExpr" in value) {
|
|
let comptimeExpr =
|
|
zigAnalysis.comptimeExprs[value.comptimeExpr].code;
|
|
if (opts.wantHtml) {
|
|
payloadHtml +=
|
|
'<span class="tok-kw">' + comptimeExpr + "</span>";
|
|
} else {
|
|
payloadHtml += comptimeExpr;
|
|
}
|
|
} else if (opts.wantHtml) {
|
|
payloadHtml += '<span class="tok-kw">anytype</span>';
|
|
} else {
|
|
payloadHtml += "anytype";
|
|
}
|
|
}
|
|
}
|
|
|
|
payloadHtml += "<span class='argBreaker'>,<br></span>";
|
|
payloadHtml += ") ";
|
|
|
|
if (fnObj.has_align) {
|
|
let align = zigAnalysis.exprs[fnObj.align];
|
|
payloadHtml += "align(" + exprName(align, opts) + ") ";
|
|
}
|
|
if (fnObj.has_cc) {
|
|
let cc = zigAnalysis.exprs[fnObj.cc];
|
|
if (cc) {
|
|
payloadHtml += "callconv(." + cc.enumLiteral + ") ";
|
|
}
|
|
}
|
|
|
|
if (fnObj.is_inferred_error) {
|
|
payloadHtml += "!";
|
|
}
|
|
if (fnObj.ret != null) {
|
|
payloadHtml += exprName(fnObj.ret, opts);
|
|
} else if (opts.wantHtml) {
|
|
payloadHtml += '<span class="tok-kw">anytype</span>';
|
|
} else {
|
|
payloadHtml += "anytype";
|
|
}
|
|
return payloadHtml;
|
|
}
|
|
// if (wantHtml) {
|
|
// return escapeHtml(typeObj.name);
|
|
// } else {
|
|
// return typeObj.name;
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function shouldSkipParamName(typeRef, paramName) {
|
|
let resolvedTypeRef = resolveValue({ expr: typeRef });
|
|
if ("type" in resolvedTypeRef) {
|
|
let typeObj = zigAnalysis.types[resolvedTypeRef.type];
|
|
if (typeObj.kind === typeKinds.Pointer) {
|
|
let ptrObj = typeObj;
|
|
if (getPtrSize(ptrObj) === pointerSizeEnum.One) {
|
|
const value = resolveValue(ptrObj.child);
|
|
return typeValueName(value, false, true).toLowerCase() === paramName;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function getPtrSize(typeObj) {
|
|
return typeObj.size == null ? pointerSizeEnum.One : typeObj.size;
|
|
}
|
|
|
|
function renderType(typeObj) {
|
|
let name;
|
|
if (
|
|
rootIsStd &&
|
|
typeObj ===
|
|
zigAnalysis.types[zigAnalysis.packages[zigAnalysis.rootPkg].main]
|
|
) {
|
|
name = "std";
|
|
} else {
|
|
name = exprName({ type: typeObj }, false, false);
|
|
}
|
|
if (name != null && name != "") {
|
|
domHdrName.innerText =
|
|
name + " (" + zigAnalysis.typeKinds[typeObj.kind] + ")";
|
|
domHdrName.classList.remove("hidden");
|
|
}
|
|
if (typeObj.kind == typeKinds.ErrorSet) {
|
|
renderErrorSet(typeObj);
|
|
}
|
|
}
|
|
|
|
function renderErrorSet(errSetType) {
|
|
if (errSetType.fields == null) {
|
|
domFnErrorsAnyError.classList.remove("hidden");
|
|
} else {
|
|
let errorList = [];
|
|
for (let i = 0; i < errSetType.fields.length; i += 1) {
|
|
let errObj = errSetType.fields[i];
|
|
//let srcObj = zigAnalysis.astNodes[errObj.src];
|
|
errorList.push(errObj);
|
|
}
|
|
errorList.sort(function (a, b) {
|
|
return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase());
|
|
});
|
|
|
|
resizeDomListDl(domListFnErrors, errorList.length);
|
|
for (let i = 0; i < errorList.length; i += 1) {
|
|
let nameTdDom = domListFnErrors.children[i * 2 + 0];
|
|
let descTdDom = domListFnErrors.children[i * 2 + 1];
|
|
nameTdDom.textContent = errorList[i].name;
|
|
let docs = errorList[i].docs;
|
|
if (docs != null) {
|
|
descTdDom.innerHTML = markdown(docs);
|
|
} else {
|
|
descTdDom.textContent = "";
|
|
}
|
|
}
|
|
domTableFnErrors.classList.remove("hidden");
|
|
}
|
|
domSectFnErrors.classList.remove("hidden");
|
|
}
|
|
|
|
// function allCompTimeFnCallsHaveTypeResult(typeIndex, value) {
|
|
// let srcIndex = zigAnalysis.fns[value].src;
|
|
// let calls = nodesToCallsMap[srcIndex];
|
|
// if (calls == null) return false;
|
|
// for (let i = 0; i < calls.length; i += 1) {
|
|
// let call = zigAnalysis.calls[calls[i]];
|
|
// if (call.result.type !== typeTypeId) return false;
|
|
// }
|
|
// return true;
|
|
// }
|
|
//
|
|
// function allCompTimeFnCallsResult(calls) {
|
|
// let firstTypeObj = null;
|
|
// let containerObj = {
|
|
// privDecls: [],
|
|
// };
|
|
// for (let callI = 0; callI < calls.length; callI += 1) {
|
|
// let call = zigAnalysis.calls[calls[callI]];
|
|
// if (call.result.type !== typeTypeId) return null;
|
|
// let typeObj = zigAnalysis.types[call.result.value];
|
|
// if (!typeKindIsContainer(typeObj.kind)) return null;
|
|
// if (firstTypeObj == null) {
|
|
// firstTypeObj = typeObj;
|
|
// containerObj.src = typeObj.src;
|
|
// } else if (firstTypeObj.src !== typeObj.src) {
|
|
// return null;
|
|
// }
|
|
//
|
|
// if (containerObj.fields == null) {
|
|
// containerObj.fields = (typeObj.fields || []).concat([]);
|
|
// } else for (let fieldI = 0; fieldI < typeObj.fields.length; fieldI += 1) {
|
|
// let prev = containerObj.fields[fieldI];
|
|
// let next = typeObj.fields[fieldI];
|
|
// if (prev === next) continue;
|
|
// if (typeof(prev) === 'object') {
|
|
// if (prev[next] == null) prev[next] = typeObj;
|
|
// } else {
|
|
// containerObj.fields[fieldI] = {};
|
|
// containerObj.fields[fieldI][prev] = firstTypeObj;
|
|
// containerObj.fields[fieldI][next] = typeObj;
|
|
// }
|
|
// }
|
|
//
|
|
// if (containerObj.pubDecls == null) {
|
|
// containerObj.pubDecls = (typeObj.pubDecls || []).concat([]);
|
|
// } else for (let declI = 0; declI < typeObj.pubDecls.length; declI += 1) {
|
|
// let prev = containerObj.pubDecls[declI];
|
|
// let next = typeObj.pubDecls[declI];
|
|
// if (prev === next) continue;
|
|
// // TODO instead of showing "examples" as the public declarations,
|
|
// // do logic like this:
|
|
// //if (typeof(prev) !== 'object') {
|
|
// // let newDeclId = zigAnalysis.decls.length;
|
|
// // prev = clone(zigAnalysis.decls[prev]);
|
|
// // prev.id = newDeclId;
|
|
// // zigAnalysis.decls.push(prev);
|
|
// // containerObj.pubDecls[declI] = prev;
|
|
// //}
|
|
// //mergeDecls(prev, next, firstTypeObj, typeObj);
|
|
// }
|
|
// }
|
|
// for (let declI = 0; declI < containerObj.pubDecls.length; declI += 1) {
|
|
// let decl = containerObj.pubDecls[declI];
|
|
// if (typeof(decl) === 'object') {
|
|
// containerObj.pubDecls[declI] = containerObj.pubDecls[declI].id;
|
|
// }
|
|
// }
|
|
// return containerObj;
|
|
// }
|
|
|
|
function renderValue(decl) {
|
|
let resolvedValue = resolveValue(decl.value);
|
|
|
|
if (resolvedValue.expr.fieldRef) {
|
|
const declRef = decl.value.expr.refPath[0].declRef;
|
|
const type = zigAnalysis.decls[declRef];
|
|
domFnProtoCode.innerHTML =
|
|
'<span class="tok-kw">const</span> ' +
|
|
escapeHtml(decl.name) +
|
|
": " +
|
|
type.name +
|
|
" = " +
|
|
exprName(decl.value.expr, { wantHtml: true, wantLink: true }) +
|
|
";";
|
|
} else if (
|
|
resolvedValue.expr.string !== undefined ||
|
|
resolvedValue.expr.call !== undefined ||
|
|
resolvedValue.expr.comptimeExpr
|
|
) {
|
|
domFnProtoCode.innerHTML =
|
|
'<span class="tok-kw">const</span> ' +
|
|
escapeHtml(decl.name) +
|
|
": " +
|
|
exprName(resolvedValue.expr, { wantHtml: true, wantLink: true }) +
|
|
" = " +
|
|
exprName(decl.value.expr, { wantHtml: true, wantLink: true }) +
|
|
";";
|
|
} else if (resolvedValue.expr.compileError) {
|
|
domFnProtoCode.innerHTML =
|
|
'<span class="tok-kw">const</span> ' +
|
|
escapeHtml(decl.name) +
|
|
" = " +
|
|
exprName(decl.value.expr, { wantHtml: true, wantLink: true }) +
|
|
";";
|
|
} else {
|
|
domFnProtoCode.innerHTML =
|
|
'<span class="tok-kw">const</span> ' +
|
|
escapeHtml(decl.name) +
|
|
": " +
|
|
exprName(resolvedValue.typeRef, { wantHtml: true, wantLink: true }) +
|
|
" = " +
|
|
exprName(decl.value.expr, { wantHtml: true, wantLink: true }) +
|
|
";";
|
|
}
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
domTldDocs.innerHTML = markdown(docs);
|
|
domTldDocs.classList.remove("hidden");
|
|
}
|
|
|
|
domFnProto.classList.remove("hidden");
|
|
}
|
|
|
|
function renderVar(decl) {
|
|
let declTypeRef = typeOfDecl(decl);
|
|
domFnProtoCode.innerHTML =
|
|
'<span class="tok-kw">var</span> ' +
|
|
escapeHtml(decl.name) +
|
|
": " +
|
|
typeValueName(declTypeRef, true, true);
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
domTldDocs.innerHTML = markdown(docs);
|
|
domTldDocs.classList.remove("hidden");
|
|
}
|
|
|
|
domFnProto.classList.remove("hidden");
|
|
}
|
|
|
|
function categorizeDecls(
|
|
decls,
|
|
typesList,
|
|
namespacesList,
|
|
errSetsList,
|
|
fnsList,
|
|
varsList,
|
|
valsList,
|
|
testsList
|
|
) {
|
|
for (let i = 0; i < decls.length; i += 1) {
|
|
let decl = zigAnalysis.decls[decls[i]];
|
|
let declValue = resolveValue(decl.value);
|
|
|
|
if (decl.isTest) {
|
|
testsList.push(decl);
|
|
continue;
|
|
}
|
|
|
|
if (decl.kind === "var") {
|
|
varsList.push(decl);
|
|
continue;
|
|
}
|
|
|
|
if (decl.kind === "const") {
|
|
if ("type" in declValue.expr) {
|
|
// We have the actual type expression at hand.
|
|
const typeExpr = zigAnalysis.types[declValue.expr.type];
|
|
if (typeExpr.kind == typeKinds.Fn) {
|
|
const funcRetExpr = resolveValue({
|
|
expr: typeExpr.ret,
|
|
});
|
|
if (
|
|
"type" in funcRetExpr.expr &&
|
|
funcRetExpr.expr.type == typeTypeId
|
|
) {
|
|
if (typeIsErrSet(declValue.expr.type)) {
|
|
errSetsList.push(decl);
|
|
} else if (typeIsStructWithNoFields(declValue.expr.type)) {
|
|
namespacesList.push(decl);
|
|
} else {
|
|
typesList.push(decl);
|
|
}
|
|
} else {
|
|
fnsList.push(decl);
|
|
}
|
|
} else {
|
|
if (typeIsErrSet(declValue.expr.type)) {
|
|
errSetsList.push(decl);
|
|
} else if (typeIsStructWithNoFields(declValue.expr.type)) {
|
|
namespacesList.push(decl);
|
|
} else {
|
|
typesList.push(decl);
|
|
}
|
|
}
|
|
} else if ("typeRef" in declValue) {
|
|
if ("type" in declValue.typeRef && declValue.typeRef == typeTypeId) {
|
|
// We don't know what the type expression is, but we know it's a type.
|
|
typesList.push(decl);
|
|
} else {
|
|
valsList.push(decl);
|
|
}
|
|
} else {
|
|
valsList.push(decl);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function renderContainer(container) {
|
|
let typesList = [];
|
|
|
|
let namespacesList = [];
|
|
|
|
let errSetsList = [];
|
|
|
|
let fnsList = [];
|
|
|
|
let varsList = [];
|
|
|
|
let valsList = [];
|
|
|
|
let testsList = [];
|
|
|
|
categorizeDecls(
|
|
container.pubDecls,
|
|
typesList,
|
|
namespacesList,
|
|
errSetsList,
|
|
fnsList,
|
|
varsList,
|
|
valsList,
|
|
testsList
|
|
);
|
|
if (curNav.showPrivDecls)
|
|
categorizeDecls(
|
|
container.privDecls,
|
|
typesList,
|
|
namespacesList,
|
|
errSetsList,
|
|
fnsList,
|
|
varsList,
|
|
valsList,
|
|
testsList
|
|
);
|
|
|
|
typesList.sort(byNameProperty);
|
|
namespacesList.sort(byNameProperty);
|
|
errSetsList.sort(byNameProperty);
|
|
fnsList.sort(byNameProperty);
|
|
varsList.sort(byNameProperty);
|
|
valsList.sort(byNameProperty);
|
|
testsList.sort(byNameProperty);
|
|
|
|
if (container.src != null) {
|
|
let docs = zigAnalysis.astNodes[container.src].docs;
|
|
if (docs != null) {
|
|
domTldDocs.innerHTML = markdown(docs);
|
|
domTldDocs.classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
if (typesList.length !== 0) {
|
|
window.x = typesList;
|
|
resizeDomList(
|
|
domListTypes,
|
|
typesList.length,
|
|
'<li><a href="#"></a></li>'
|
|
);
|
|
for (let i = 0; i < typesList.length; i += 1) {
|
|
let liDom = domListTypes.children[i];
|
|
let aDom = liDom.children[0];
|
|
let decl = typesList[i];
|
|
aDom.textContent = decl.name;
|
|
aDom.setAttribute("href", navLinkDecl(decl.name));
|
|
}
|
|
domSectTypes.classList.remove("hidden");
|
|
}
|
|
if (namespacesList.length !== 0) {
|
|
resizeDomList(
|
|
domListNamespaces,
|
|
namespacesList.length,
|
|
'<li><a href="#"></a></li>'
|
|
);
|
|
for (let i = 0; i < namespacesList.length; i += 1) {
|
|
let liDom = domListNamespaces.children[i];
|
|
let aDom = liDom.children[0];
|
|
let decl = namespacesList[i];
|
|
aDom.textContent = decl.name;
|
|
aDom.setAttribute("href", navLinkDecl(decl.name));
|
|
}
|
|
domSectNamespaces.classList.remove("hidden");
|
|
}
|
|
|
|
if (errSetsList.length !== 0) {
|
|
resizeDomList(
|
|
domListErrSets,
|
|
errSetsList.length,
|
|
'<li><a href="#"></a></li>'
|
|
);
|
|
for (let i = 0; i < errSetsList.length; i += 1) {
|
|
let liDom = domListErrSets.children[i];
|
|
let aDom = liDom.children[0];
|
|
let decl = errSetsList[i];
|
|
aDom.textContent = decl.name;
|
|
aDom.setAttribute("href", navLinkDecl(decl.name));
|
|
}
|
|
domSectErrSets.classList.remove("hidden");
|
|
}
|
|
|
|
if (fnsList.length !== 0) {
|
|
resizeDomList(
|
|
domListFns,
|
|
fnsList.length,
|
|
"<div><dt></dt><dd></dd></div>"
|
|
);
|
|
|
|
for (let i = 0; i < fnsList.length; i += 1) {
|
|
let decl = fnsList[i];
|
|
let trDom = domListFns.children[i];
|
|
|
|
let tdFnCode = trDom.children[0];
|
|
let tdDesc = trDom.children[1];
|
|
|
|
let declType = resolveValue(decl.value);
|
|
console.assert("type" in declType.expr);
|
|
|
|
tdFnCode.innerHTML = exprName(declType.expr, {
|
|
wantHtml: true,
|
|
wantLink: true,
|
|
fnDecl: decl,
|
|
linkFnNameDecl: navLinkDecl(decl.name),
|
|
});
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
tdDesc.innerHTML = shortDescMarkdown(docs);
|
|
} else {
|
|
tdDesc.textContent = "";
|
|
}
|
|
}
|
|
domSectFns.classList.remove("hidden");
|
|
}
|
|
|
|
let containerNode = zigAnalysis.astNodes[container.src];
|
|
if (containerNode.fields && containerNode.fields.length > 0) {
|
|
resizeDomList(domListFields, containerNode.fields.length, "<div></div>");
|
|
|
|
for (let i = 0; i < containerNode.fields.length; i += 1) {
|
|
let fieldNode = zigAnalysis.astNodes[containerNode.fields[i]];
|
|
let divDom = domListFields.children[i];
|
|
let fieldName = fieldNode.name;
|
|
let docs = fieldNode.docs;
|
|
let docsNonEmpty = docs != null && docs !== "";
|
|
let extraPreClass = docsNonEmpty ? " fieldHasDocs" : "";
|
|
|
|
let html =
|
|
'<div class="mobile-scroll-container"><pre class="scroll-item' +
|
|
extraPreClass +
|
|
'">' +
|
|
escapeHtml(fieldName);
|
|
|
|
if (container.kind === typeKinds.Enum) {
|
|
html += ' = <span class="tok-number">' + fieldName + "</span>";
|
|
} else {
|
|
let fieldTypeExpr = container.fields[i];
|
|
html += ": ";
|
|
let name = exprName(fieldTypeExpr, false, false);
|
|
html += '<span class="tok-kw">' + name + "</span>";
|
|
let tsn = typeShorthandName(fieldTypeExpr);
|
|
if (tsn) {
|
|
html += "<span> (" + tsn + ")</span>";
|
|
}
|
|
}
|
|
|
|
html += ",</pre></div>";
|
|
|
|
if (docsNonEmpty) {
|
|
html += '<div class="fieldDocs">' + markdown(docs) + "</div>";
|
|
}
|
|
divDom.innerHTML = html;
|
|
}
|
|
domSectFields.classList.remove("hidden");
|
|
}
|
|
|
|
if (varsList.length !== 0) {
|
|
resizeDomList(
|
|
domListGlobalVars,
|
|
varsList.length,
|
|
'<tr><td><a href="#"></a></td><td></td><td></td></tr>'
|
|
);
|
|
for (let i = 0; i < varsList.length; i += 1) {
|
|
let decl = varsList[i];
|
|
let trDom = domListGlobalVars.children[i];
|
|
|
|
let tdName = trDom.children[0];
|
|
let tdNameA = tdName.children[0];
|
|
let tdType = trDom.children[1];
|
|
let tdDesc = trDom.children[2];
|
|
|
|
tdNameA.setAttribute("href", navLinkDecl(decl.name));
|
|
tdNameA.textContent = decl.name;
|
|
|
|
tdType.innerHTML = typeValueName(typeOfDecl(decl), true, true);
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
tdDesc.innerHTML = shortDescMarkdown(docs);
|
|
} else {
|
|
tdDesc.textContent = "";
|
|
}
|
|
}
|
|
domSectGlobalVars.classList.remove("hidden");
|
|
}
|
|
|
|
if (valsList.length !== 0) {
|
|
resizeDomList(
|
|
domListValues,
|
|
valsList.length,
|
|
'<tr><td><a href="#"></a></td><td></td><td></td></tr>'
|
|
);
|
|
for (let i = 0; i < valsList.length; i += 1) {
|
|
let decl = valsList[i];
|
|
let trDom = domListValues.children[i];
|
|
|
|
let tdName = trDom.children[0];
|
|
let tdNameA = tdName.children[0];
|
|
let tdType = trDom.children[1];
|
|
let tdDesc = trDom.children[2];
|
|
|
|
tdNameA.setAttribute("href", navLinkDecl(decl.name));
|
|
tdNameA.textContent = decl.name;
|
|
|
|
tdType.innerHTML = exprName(walkResultTypeRef(decl.value), {
|
|
wantHtml: true,
|
|
wantLink: true,
|
|
});
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
tdDesc.innerHTML = shortDescMarkdown(docs);
|
|
} else {
|
|
tdDesc.textContent = "";
|
|
}
|
|
}
|
|
domSectValues.classList.remove("hidden");
|
|
}
|
|
|
|
if (testsList.length !== 0) {
|
|
resizeDomList(
|
|
domListTests,
|
|
testsList.length,
|
|
'<tr><td><a href="#"></a></td><td></td><td></td></tr>'
|
|
);
|
|
for (let i = 0; i < testsList.length; i += 1) {
|
|
let decl = testsList[i];
|
|
let trDom = domListTests.children[i];
|
|
|
|
let tdName = trDom.children[0];
|
|
let tdNameA = tdName.children[0];
|
|
let tdType = trDom.children[1];
|
|
let tdDesc = trDom.children[2];
|
|
|
|
tdNameA.setAttribute("href", navLinkDecl(decl.name));
|
|
tdNameA.textContent = decl.name;
|
|
|
|
tdType.innerHTML = exprName(walkResultTypeRef(decl.value), {
|
|
wantHtml: true,
|
|
wantLink: true,
|
|
});
|
|
|
|
let docs = zigAnalysis.astNodes[decl.src].docs;
|
|
if (docs != null) {
|
|
tdDesc.innerHTML = shortDescMarkdown(docs);
|
|
} else {
|
|
tdDesc.textContent = "";
|
|
}
|
|
}
|
|
domSectTests.classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
function operatorCompare(a, b) {
|
|
if (a === b) {
|
|
return 0;
|
|
} else if (a < b) {
|
|
return -1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
function detectRootIsStd() {
|
|
let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
|
|
if (rootPkg.table["std"] == null) {
|
|
// no std mapped into the root package
|
|
return false;
|
|
}
|
|
let stdPkg = zigAnalysis.packages[rootPkg.table["std"]];
|
|
if (stdPkg == null) return false;
|
|
return rootPkg.file === stdPkg.file;
|
|
}
|
|
|
|
function indexTypeKinds() {
|
|
let map = {};
|
|
for (let i = 0; i < zigAnalysis.typeKinds.length; i += 1) {
|
|
map[zigAnalysis.typeKinds[i]] = i;
|
|
}
|
|
// This is just for debugging purposes, not needed to function
|
|
let assertList = [
|
|
"Type",
|
|
"Void",
|
|
"Bool",
|
|
"NoReturn",
|
|
"Int",
|
|
"Float",
|
|
"Pointer",
|
|
"Array",
|
|
"Struct",
|
|
"ComptimeFloat",
|
|
"ComptimeInt",
|
|
"Undefined",
|
|
"Null",
|
|
"Optional",
|
|
"ErrorUnion",
|
|
"ErrorSet",
|
|
"Enum",
|
|
"Union",
|
|
"Fn",
|
|
"BoundFn",
|
|
"Opaque",
|
|
"Frame",
|
|
"AnyFrame",
|
|
"Vector",
|
|
"EnumLiteral",
|
|
];
|
|
for (let i = 0; i < assertList.length; i += 1) {
|
|
if (map[assertList[i]] == null)
|
|
throw new Error("No type kind '" + assertList[i] + "' found");
|
|
}
|
|
return map;
|
|
}
|
|
|
|
function findTypeTypeId() {
|
|
for (let i = 0; i < zigAnalysis.types.length; i += 1) {
|
|
if (zigAnalysis.types[i].kind == typeKinds.Type) {
|
|
return i;
|
|
}
|
|
}
|
|
throw new Error("No type 'type' found");
|
|
}
|
|
|
|
function updateCurNav() {
|
|
curNav = {
|
|
showPrivDecls: false,
|
|
pkgNames: [],
|
|
pkgObjs: [],
|
|
declNames: [],
|
|
declObjs: [],
|
|
callName: null,
|
|
};
|
|
curNavSearch = "";
|
|
|
|
if (location.hash[0] === "#" && location.hash.length > 1) {
|
|
let query = location.hash.substring(1);
|
|
if (query[0] === "*") {
|
|
curNav.showPrivDecls = true;
|
|
query = query.substring(1);
|
|
}
|
|
|
|
let qpos = query.indexOf("?");
|
|
let nonSearchPart;
|
|
if (qpos === -1) {
|
|
nonSearchPart = query;
|
|
} else {
|
|
nonSearchPart = query.substring(0, qpos);
|
|
curNavSearch = decodeURIComponent(query.substring(qpos + 1));
|
|
}
|
|
|
|
let parts = nonSearchPart.split(";");
|
|
curNav.pkgNames = decodeURIComponent(parts[0]).split(".");
|
|
if (parts[1] != null) {
|
|
curNav.declNames = decodeURIComponent(parts[1]).split(".");
|
|
}
|
|
}
|
|
}
|
|
|
|
function onHashChange() {
|
|
updateCurNav();
|
|
if (domSearch.value !== curNavSearch) {
|
|
domSearch.value = curNavSearch;
|
|
}
|
|
render();
|
|
if (imFeelingLucky) {
|
|
imFeelingLucky = false;
|
|
activateSelectedResult();
|
|
}
|
|
}
|
|
|
|
function findSubDecl(parentType, childName) {
|
|
{
|
|
// Generic functions
|
|
if ("value" in parentType) {
|
|
const rv = resolveValue(parentType.value);
|
|
if ("type" in rv.expr) {
|
|
const t = zigAnalysis.types[rv.expr.type];
|
|
if (t.kind == typeKinds.Fn && t.generic_ret != null) {
|
|
const rgr = resolveValue({ expr: t.generic_ret });
|
|
if ("type" in rgr.expr) {
|
|
parentType = zigAnalysis.types[rgr.expr.type];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!parentType.pubDecls) return null;
|
|
for (let i = 0; i < parentType.pubDecls.length; i += 1) {
|
|
let declIndex = parentType.pubDecls[i];
|
|
let childDecl = zigAnalysis.decls[declIndex];
|
|
if (childDecl.name === childName) {
|
|
return childDecl;
|
|
}
|
|
}
|
|
if (!parentType.privDecls) return null;
|
|
for (let i = 0; i < parentType.privDecls.length; i += 1) {
|
|
let declIndex = parentType.privDecls[i];
|
|
let childDecl = zigAnalysis.decls[declIndex];
|
|
if (childDecl.name === childName) {
|
|
return childDecl;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function computeCanonicalPackagePaths() {
|
|
let list = new Array(zigAnalysis.packages.length);
|
|
// Now we try to find all the packages from root.
|
|
let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg];
|
|
// Breadth-first to keep the path shortest possible.
|
|
let stack = [
|
|
{
|
|
path: [],
|
|
pkg: rootPkg,
|
|
},
|
|
];
|
|
while (stack.length !== 0) {
|
|
let item = stack.shift();
|
|
for (let key in item.pkg.table) {
|
|
let childPkgIndex = item.pkg.table[key];
|
|
if (list[childPkgIndex] != null) continue;
|
|
let childPkg = zigAnalysis.packages[childPkgIndex];
|
|
if (childPkg == null) continue;
|
|
|
|
let newPath = item.path.concat([key]);
|
|
list[childPkgIndex] = newPath;
|
|
stack.push({
|
|
path: newPath,
|
|
pkg: childPkg,
|
|
});
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
function computeCanonDeclPaths() {
|
|
let list = new Array(zigAnalysis.decls.length);
|
|
canonTypeDecls = new Array(zigAnalysis.types.length);
|
|
|
|
for (let pkgI = 0; pkgI < zigAnalysis.packages.length; pkgI += 1) {
|
|
if (pkgI === zigAnalysis.rootPkg && rootIsStd) continue;
|
|
let pkg = zigAnalysis.packages[pkgI];
|
|
let pkgNames = canonPkgPaths[pkgI];
|
|
if (pkgNames === undefined) continue;
|
|
|
|
let stack = [
|
|
{
|
|
declNames: [],
|
|
type: zigAnalysis.types[pkg.main],
|
|
},
|
|
];
|
|
while (stack.length !== 0) {
|
|
let item = stack.shift();
|
|
|
|
if (isContainerType(item.type)) {
|
|
let t = item.type;
|
|
|
|
let len = t.pubDecls ? t.pubDecls.length : 0;
|
|
for (let declI = 0; declI < len; declI += 1) {
|
|
let mainDeclIndex = t.pubDecls[declI];
|
|
if (list[mainDeclIndex] != null) continue;
|
|
|
|
let decl = zigAnalysis.decls[mainDeclIndex];
|
|
let declVal = resolveValue(decl.value);
|
|
let declNames = item.declNames.concat([decl.name]);
|
|
list[mainDeclIndex] = {
|
|
pkgNames: pkgNames,
|
|
declNames: declNames,
|
|
};
|
|
if ("type" in declVal.expr) {
|
|
let value = zigAnalysis.types[declVal.expr.type];
|
|
if (declCanRepresentTypeKind(value.kind)) {
|
|
canonTypeDecls[declVal.type] = mainDeclIndex;
|
|
}
|
|
|
|
if (isContainerType(value)) {
|
|
stack.push({
|
|
declNames: declNames,
|
|
type: value,
|
|
});
|
|
}
|
|
|
|
// Generic fun/ction
|
|
if (value.kind == typeKinds.Fn && value.generic_ret != null) {
|
|
let resolvedVal = resolveValue({ expr: value.generic_ret });
|
|
if ("type" in resolvedVal.expr) {
|
|
let generic_type = zigAnalysis.types[resolvedVal.expr.type];
|
|
if (isContainerType(generic_type)) {
|
|
stack.push({
|
|
declNames: declNames,
|
|
type: generic_type,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
function getCanonDeclPath(index) {
|
|
if (canonDeclPaths == null) {
|
|
canonDeclPaths = computeCanonDeclPaths();
|
|
}
|
|
//let cd = (canonDeclPaths);
|
|
return canonDeclPaths[index];
|
|
}
|
|
|
|
function getCanonTypeDecl(index) {
|
|
getCanonDeclPath(0);
|
|
//let ct = (canonTypeDecls);
|
|
return canonTypeDecls[index];
|
|
}
|
|
|
|
function escapeHtml(text) {
|
|
return text.replace(/[&"<>]/g, function (m) {
|
|
return escapeHtmlReplacements[m];
|
|
});
|
|
}
|
|
|
|
function shortDescMarkdown(docs) {
|
|
const trimmed_docs = docs.trim();
|
|
let index = trimmed_docs.indexOf(".");
|
|
if (index < 0) {
|
|
index = trimmed_docs.indexOf("\n");
|
|
if (index < 0) {
|
|
index = trimmed_docs.length;
|
|
}
|
|
} else {
|
|
index += 1; // include the period
|
|
}
|
|
const slice = trimmed_docs.slice(0, index);
|
|
return markdown(slice);
|
|
}
|
|
|
|
function markdown(input) {
|
|
const raw_lines = input.split("\n"); // zig allows no '\r', so we don't need to split on CR
|
|
|
|
const lines = [];
|
|
|
|
// PHASE 1:
|
|
// Dissect lines and determine the type for each line.
|
|
// Also computes indentation level and removes unnecessary whitespace
|
|
|
|
let is_reading_code = false;
|
|
let code_indent = 0;
|
|
for (let line_no = 0; line_no < raw_lines.length; line_no++) {
|
|
const raw_line = raw_lines[line_no];
|
|
|
|
const line = {
|
|
indent: 0,
|
|
raw_text: raw_line,
|
|
text: raw_line.trim(),
|
|
type: "p", // p, h1 … h6, code, ul, ol, blockquote, skip, empty
|
|
ordered_number: -1, // NOTE: hack to make the type checker happy
|
|
};
|
|
|
|
if (!is_reading_code) {
|
|
while (
|
|
line.indent < line.raw_text.length &&
|
|
line.raw_text[line.indent] == " "
|
|
) {
|
|
line.indent += 1;
|
|
}
|
|
|
|
if (line.text.startsWith("######")) {
|
|
line.type = "h6";
|
|
line.text = line.text.substr(6);
|
|
} else if (line.text.startsWith("#####")) {
|
|
line.type = "h5";
|
|
line.text = line.text.substr(5);
|
|
} else if (line.text.startsWith("####")) {
|
|
line.type = "h4";
|
|
line.text = line.text.substr(4);
|
|
} else if (line.text.startsWith("###")) {
|
|
line.type = "h3";
|
|
line.text = line.text.substr(3);
|
|
} else if (line.text.startsWith("##")) {
|
|
line.type = "h2";
|
|
line.text = line.text.substr(2);
|
|
} else if (line.text.startsWith("#")) {
|
|
line.type = "h1";
|
|
line.text = line.text.substr(1);
|
|
} else if (line.text.startsWith("-")) {
|
|
line.type = "ul";
|
|
line.text = line.text.substr(1);
|
|
} else if (line.text.match(/^\d+\..*$/)) {
|
|
// if line starts with {number}{dot}
|
|
const match = line.text.match(/(\d+)\./);
|
|
line.type = "ul";
|
|
line.text = line.text.substr(match[0].length);
|
|
line.ordered_number = Number(match[1].length);
|
|
} else if (line.text == "```") {
|
|
line.type = "skip";
|
|
is_reading_code = true;
|
|
code_indent = line.indent;
|
|
} else if (line.text == "") {
|
|
line.type = "empty";
|
|
}
|
|
} else {
|
|
if (line.text == "```") {
|
|
is_reading_code = false;
|
|
line.type = "skip";
|
|
} else {
|
|
line.type = "code";
|
|
line.text = line.raw_text.substr(code_indent); // remove the indent of the ``` from all the code block
|
|
}
|
|
}
|
|
|
|
if (line.type != "skip") {
|
|
lines.push(line);
|
|
}
|
|
}
|
|
|
|
// PHASE 2:
|
|
// Render HTML from markdown lines.
|
|
// Look at each line and emit fitting HTML code
|
|
|
|
function markdownInlines(innerText) {
|
|
// inline types:
|
|
// **{INLINE}** : <strong>
|
|
// __{INLINE}__ : <u>
|
|
// ~~{INLINE}~~ : <s>
|
|
// *{INLINE}* : <emph>
|
|
// _{INLINE}_ : <emph>
|
|
// `{TEXT}` : <code>
|
|
// [{INLINE}]({URL}) : <a>
|
|
// ![{TEXT}]({URL}) : <img>
|
|
// [[std;format.fmt]] : <a> (inner link)
|
|
|
|
const formats = [
|
|
{
|
|
marker: "**",
|
|
tag: "strong",
|
|
},
|
|
{
|
|
marker: "~~",
|
|
tag: "s",
|
|
},
|
|
{
|
|
marker: "__",
|
|
tag: "u",
|
|
},
|
|
{
|
|
marker: "*",
|
|
tag: "em",
|
|
},
|
|
];
|
|
|
|
const stack = [];
|
|
|
|
let innerHTML = "";
|
|
let currentRun = "";
|
|
|
|
function flushRun() {
|
|
if (currentRun != "") {
|
|
innerHTML += escapeHtml(currentRun);
|
|
}
|
|
currentRun = "";
|
|
}
|
|
|
|
let parsing_code = false;
|
|
let codetag = "";
|
|
let in_code = false;
|
|
|
|
for (let i = 0; i < innerText.length; i++) {
|
|
if (parsing_code && in_code) {
|
|
if (innerText.substr(i, codetag.length) == codetag) {
|
|
// remove leading and trailing whitespace if string both starts and ends with one.
|
|
if (
|
|
currentRun[0] == " " &&
|
|
currentRun[currentRun.length - 1] == " "
|
|
) {
|
|
currentRun = currentRun.substr(1, currentRun.length - 2);
|
|
}
|
|
flushRun();
|
|
i += codetag.length - 1;
|
|
in_code = false;
|
|
parsing_code = false;
|
|
innerHTML += "</code>";
|
|
codetag = "";
|
|
} else {
|
|
currentRun += innerText[i];
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (innerText[i] == "`") {
|
|
flushRun();
|
|
if (!parsing_code) {
|
|
innerHTML += "<code>";
|
|
}
|
|
parsing_code = true;
|
|
codetag += "`";
|
|
continue;
|
|
}
|
|
|
|
if (parsing_code) {
|
|
currentRun += innerText[i];
|
|
in_code = true;
|
|
} else {
|
|
let any = false;
|
|
for (
|
|
let idx = stack.length > 0 ? -1 : 0;
|
|
idx < formats.length;
|
|
idx++
|
|
) {
|
|
const fmt = idx >= 0 ? formats[idx] : stack[stack.length - 1];
|
|
if (innerText.substr(i, fmt.marker.length) == fmt.marker) {
|
|
flushRun();
|
|
if (stack[stack.length - 1] == fmt) {
|
|
stack.pop();
|
|
innerHTML += "</" + fmt.tag + ">";
|
|
} else {
|
|
stack.push(fmt);
|
|
innerHTML += "<" + fmt.tag + ">";
|
|
}
|
|
i += fmt.marker.length - 1;
|
|
any = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!any) {
|
|
currentRun += innerText[i];
|
|
}
|
|
}
|
|
}
|
|
flushRun();
|
|
|
|
while (stack.length > 0) {
|
|
const fmt = stack.pop();
|
|
innerHTML += "</" + fmt.tag + ">";
|
|
}
|
|
|
|
return innerHTML;
|
|
}
|
|
|
|
function previousLineIs(type, line_no) {
|
|
if (line_no > 0) {
|
|
return lines[line_no - 1].type == type;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function nextLineIs(type, line_no) {
|
|
if (line_no < lines.length - 1) {
|
|
return lines[line_no + 1].type == type;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function getPreviousLineIndent(line_no) {
|
|
if (line_no > 0) {
|
|
return lines[line_no - 1].indent;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function getNextLineIndent(line_no) {
|
|
if (line_no < lines.length - 1) {
|
|
return lines[line_no + 1].indent;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
let html = "";
|
|
for (let line_no = 0; line_no < lines.length; line_no++) {
|
|
const line = lines[line_no];
|
|
|
|
switch (line.type) {
|
|
case "h1":
|
|
case "h2":
|
|
case "h3":
|
|
case "h4":
|
|
case "h5":
|
|
case "h6":
|
|
html +=
|
|
"<" +
|
|
line.type +
|
|
">" +
|
|
markdownInlines(line.text) +
|
|
"</" +
|
|
line.type +
|
|
">\n";
|
|
break;
|
|
|
|
case "ul":
|
|
case "ol":
|
|
if (
|
|
!previousLineIs("ul", line_no) ||
|
|
getPreviousLineIndent(line_no) < line.indent
|
|
) {
|
|
html += "<" + line.type + ">\n";
|
|
}
|
|
|
|
html += "<li>" + markdownInlines(line.text) + "</li>\n";
|
|
|
|
if (
|
|
!nextLineIs("ul", line_no) ||
|
|
getNextLineIndent(line_no) < line.indent
|
|
) {
|
|
html += "</" + line.type + ">\n";
|
|
}
|
|
break;
|
|
|
|
case "p":
|
|
if (!previousLineIs("p", line_no)) {
|
|
html += "<p>\n";
|
|
}
|
|
html += markdownInlines(line.text) + "\n";
|
|
if (!nextLineIs("p", line_no)) {
|
|
html += "</p>\n";
|
|
}
|
|
break;
|
|
|
|
case "code":
|
|
if (!previousLineIs("code", line_no)) {
|
|
html += "<pre><code>";
|
|
}
|
|
html += escapeHtml(line.text) + "\n";
|
|
if (!nextLineIs("code", line_no)) {
|
|
html += "</code></pre>\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return html;
|
|
}
|
|
|
|
function activateSelectedResult() {
|
|
if (domSectSearchResults.classList.contains("hidden")) {
|
|
return;
|
|
}
|
|
|
|
let liDom = domListSearchResults.children[curSearchIndex];
|
|
if (liDom == null && domListSearchResults.children.length !== 0) {
|
|
liDom = domListSearchResults.children[0];
|
|
}
|
|
if (liDom != null) {
|
|
let aDom = liDom.children[0];
|
|
location.href = aDom.getAttribute("href");
|
|
curSearchIndex = -1;
|
|
}
|
|
domSearch.blur();
|
|
}
|
|
|
|
function onSearchKeyDown(ev) {
|
|
switch (getKeyString(ev)) {
|
|
case "Enter":
|
|
// detect if this search changes anything
|
|
let terms1 = getSearchTerms();
|
|
startSearch();
|
|
updateCurNav();
|
|
let terms2 = getSearchTerms();
|
|
// we might have to wait for onHashChange to trigger
|
|
imFeelingLucky = terms1.join(" ") !== terms2.join(" ");
|
|
if (!imFeelingLucky) activateSelectedResult();
|
|
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
return;
|
|
case "Esc":
|
|
domSearch.value = "";
|
|
domSearch.blur();
|
|
curSearchIndex = -1;
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
startSearch();
|
|
return;
|
|
case "Up":
|
|
moveSearchCursor(-1);
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
return;
|
|
case "Down":
|
|
moveSearchCursor(1);
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
return;
|
|
default:
|
|
if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
|
|
|
|
curSearchIndex = -1;
|
|
ev.stopPropagation();
|
|
startAsyncSearch();
|
|
return;
|
|
}
|
|
}
|
|
|
|
function moveSearchCursor(dir) {
|
|
if (
|
|
curSearchIndex < 0 ||
|
|
curSearchIndex >= domListSearchResults.children.length
|
|
) {
|
|
if (dir > 0) {
|
|
curSearchIndex = -1 + dir;
|
|
} else if (dir < 0) {
|
|
curSearchIndex = domListSearchResults.children.length + dir;
|
|
}
|
|
} else {
|
|
curSearchIndex += dir;
|
|
}
|
|
if (curSearchIndex < 0) {
|
|
curSearchIndex = 0;
|
|
}
|
|
if (curSearchIndex >= domListSearchResults.children.length) {
|
|
curSearchIndex = domListSearchResults.children.length - 1;
|
|
}
|
|
renderSearchCursor();
|
|
}
|
|
|
|
function getKeyString(ev) {
|
|
let name;
|
|
let ignoreShift = false;
|
|
switch (ev.which) {
|
|
case 13:
|
|
name = "Enter";
|
|
break;
|
|
case 27:
|
|
name = "Esc";
|
|
break;
|
|
case 38:
|
|
name = "Up";
|
|
break;
|
|
case 40:
|
|
name = "Down";
|
|
break;
|
|
default:
|
|
ignoreShift = true;
|
|
name =
|
|
ev.key != null
|
|
? ev.key
|
|
: String.fromCharCode(ev.charCode || ev.keyCode);
|
|
}
|
|
if (!ignoreShift && ev.shiftKey) name = "Shift+" + name;
|
|
if (ev.altKey) name = "Alt+" + name;
|
|
if (ev.ctrlKey) name = "Ctrl+" + name;
|
|
return name;
|
|
}
|
|
|
|
function onWindowKeyDown(ev) {
|
|
switch (getKeyString(ev)) {
|
|
case "Esc":
|
|
if (!domHelpModal.classList.contains("hidden")) {
|
|
domHelpModal.classList.add("hidden");
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
}
|
|
break;
|
|
case "s":
|
|
domSearch.focus();
|
|
domSearch.select();
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
startAsyncSearch();
|
|
break;
|
|
case "?":
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
showHelpModal();
|
|
break;
|
|
}
|
|
}
|
|
|
|
function showHelpModal() {
|
|
domHelpModal.classList.remove("hidden");
|
|
domHelpModal.style.left =
|
|
window.innerWidth / 2 - domHelpModal.clientWidth / 2 + "px";
|
|
domHelpModal.style.top =
|
|
window.innerHeight / 2 - domHelpModal.clientHeight / 2 + "px";
|
|
domHelpModal.focus();
|
|
}
|
|
|
|
function clearAsyncSearch() {
|
|
if (searchTimer != null) {
|
|
clearTimeout(searchTimer);
|
|
searchTimer = null;
|
|
}
|
|
}
|
|
|
|
function startAsyncSearch() {
|
|
clearAsyncSearch();
|
|
searchTimer = setTimeout(startSearch, 100);
|
|
}
|
|
function startSearch() {
|
|
clearAsyncSearch();
|
|
let oldHash = location.hash;
|
|
let parts = oldHash.split("?");
|
|
let newPart2 = domSearch.value === "" ? "" : "?" + domSearch.value;
|
|
location.hash =
|
|
parts.length === 1 ? oldHash + newPart2 : parts[0] + newPart2;
|
|
}
|
|
function getSearchTerms() {
|
|
let list = curNavSearch.trim().split(/[ \r\n\t]+/);
|
|
list.sort();
|
|
return list;
|
|
}
|
|
function renderSearch() {
|
|
let matchedItems = [];
|
|
let ignoreCase = curNavSearch.toLowerCase() === curNavSearch;
|
|
let terms = getSearchTerms();
|
|
|
|
decl_loop: for (
|
|
let declIndex = 0;
|
|
declIndex < zigAnalysis.decls.length;
|
|
declIndex += 1
|
|
) {
|
|
let canonPath = getCanonDeclPath(declIndex);
|
|
if (canonPath == null) continue;
|
|
|
|
let decl = zigAnalysis.decls[declIndex];
|
|
let lastPkgName = canonPath.pkgNames[canonPath.pkgNames.length - 1];
|
|
let fullPathSearchText =
|
|
lastPkgName + "." + canonPath.declNames.join(".");
|
|
let astNode = zigAnalysis.astNodes[decl.src];
|
|
let fileAndDocs = ""; //zigAnalysis.files[astNode.file];
|
|
// TODO: understand what this piece of code is trying to achieve
|
|
// also right now `files` are expressed as a hashmap.
|
|
if (astNode.docs != null) {
|
|
fileAndDocs += "\n" + astNode.docs;
|
|
}
|
|
let fullPathSearchTextLower = fullPathSearchText;
|
|
if (ignoreCase) {
|
|
fullPathSearchTextLower = fullPathSearchTextLower.toLowerCase();
|
|
fileAndDocs = fileAndDocs.toLowerCase();
|
|
}
|
|
|
|
let points = 0;
|
|
for (let termIndex = 0; termIndex < terms.length; termIndex += 1) {
|
|
let term = terms[termIndex];
|
|
|
|
// exact, case sensitive match of full decl path
|
|
if (fullPathSearchText === term) {
|
|
points += 4;
|
|
continue;
|
|
}
|
|
// exact, case sensitive match of just decl name
|
|
if (decl.name == term) {
|
|
points += 3;
|
|
continue;
|
|
}
|
|
// substring, case insensitive match of full decl path
|
|
if (fullPathSearchTextLower.indexOf(term) >= 0) {
|
|
points += 2;
|
|
continue;
|
|
}
|
|
if (fileAndDocs.indexOf(term) >= 0) {
|
|
points += 1;
|
|
continue;
|
|
}
|
|
|
|
continue decl_loop;
|
|
}
|
|
|
|
matchedItems.push({
|
|
decl: decl,
|
|
path: canonPath,
|
|
points: points,
|
|
});
|
|
}
|
|
|
|
if (matchedItems.length !== 0) {
|
|
resizeDomList(
|
|
domListSearchResults,
|
|
matchedItems.length,
|
|
'<li><a href="#"></a></li>'
|
|
);
|
|
|
|
matchedItems.sort(function (a, b) {
|
|
let cmp = operatorCompare(b.points, a.points);
|
|
if (cmp != 0) return cmp;
|
|
return operatorCompare(a.decl.name, b.decl.name);
|
|
});
|
|
|
|
for (let i = 0; i < matchedItems.length; i += 1) {
|
|
let liDom = domListSearchResults.children[i];
|
|
let aDom = liDom.children[0];
|
|
let match = matchedItems[i];
|
|
let lastPkgName = match.path.pkgNames[match.path.pkgNames.length - 1];
|
|
aDom.textContent = lastPkgName + "." + match.path.declNames.join(".");
|
|
aDom.setAttribute(
|
|
"href",
|
|
navLink(match.path.pkgNames, match.path.declNames)
|
|
);
|
|
}
|
|
renderSearchCursor();
|
|
|
|
domSectSearchResults.classList.remove("hidden");
|
|
} else {
|
|
domSectSearchNoResults.classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
function renderSearchCursor() {
|
|
for (let i = 0; i < domListSearchResults.children.length; i += 1) {
|
|
let liDom = domListSearchResults.children[i];
|
|
if (curSearchIndex === i) {
|
|
liDom.classList.add("selected");
|
|
} else {
|
|
liDom.classList.remove("selected");
|
|
}
|
|
}
|
|
}
|
|
|
|
// function indexNodesToCalls() {
|
|
// let map = {};
|
|
// for (let i = 0; i < zigAnalysis.calls.length; i += 1) {
|
|
// let call = zigAnalysis.calls[i];
|
|
// let fn = zigAnalysis.fns[call.fn];
|
|
// if (map[fn.src] == null) {
|
|
// map[fn.src] = [i];
|
|
// } else {
|
|
// map[fn.src].push(i);
|
|
// }
|
|
// }
|
|
// return map;
|
|
// }
|
|
|
|
function byNameProperty(a, b) {
|
|
return operatorCompare(a.name, b.name);
|
|
}
|
|
})();
|