mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 22:33:08 +00:00
This fixes the new search placeholder not disappearing if you type before it finished loading, and maybe some other things.
3409 lines
102 KiB
JavaScript
3409 lines
102 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");
|
|
const domSearchPlaceholder = document.getElementById("searchPlaceholder");
|
|
|
|
domSearch.disabled = false;
|
|
|
|
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);
|
|
domSearch.addEventListener("focus", ev => {
|
|
domSearchPlaceholder.classList.add("hidden");
|
|
});
|
|
domSearch.addEventListener("blur", ev => {
|
|
if (domSearch.value.length == 0)
|
|
domSearchPlaceholder.classList.remove("hidden");
|
|
});
|
|
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;
|
|
if (domSearch.value.length == 0)
|
|
domSearchPlaceholder.classList.remove("hidden");
|
|
else
|
|
domSearchPlaceholder.classList.add("hidden");
|
|
}
|
|
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>
|
|
//  : <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);
|
|
}
|
|
})();
|