ton-assembly
Version:
TON assembler and disassembler
167 lines • 5.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCoverageSummary = exports.isExecutableLine = exports.buildFuncLineInfo = exports.buildLineInfo = void 0;
const buildLineInfo = (trace, asm) => {
const lines = asm.split("\n");
const perLineSteps = new Map();
for (const step of trace.steps) {
if (step.loc === undefined)
continue;
const line = step.loc.line;
perLineSteps.set(line + 1, [...(perLineSteps.get(line + 1) ?? []), step]);
if (step.loc.otherLines.length > 0) {
for (const otherLine of step.loc.otherLines) {
perLineSteps.set(otherLine + 1, [...(perLineSteps.get(otherLine + 1) ?? []), step]);
}
}
}
return lines.map((line, idx) => {
const info = perLineSteps.get(idx + 1);
if (info) {
const gasInfo = info.map(step => normalizeGas(step.gasCost));
return {
line,
info: {
$: "Covered",
hits: gasInfo.length,
gasCosts: gasInfo,
},
};
}
if (!(0, exports.isExecutableLine)(line)) {
return {
line,
info: {
$: "Skipped",
},
};
}
return {
line,
info: {
$: "Uncovered",
},
};
});
};
exports.buildLineInfo = buildLineInfo;
const buildFuncLineInfo = (traces, funcCode) => {
const lines = funcCode.split("\n");
const perLineStepsArray = new Map();
for (const trace of traces) {
const perLineSteps = new Map();
for (const step of trace.steps) {
if (step.sourceMapEntries.length === 0)
continue;
const line = step.sourceMapEntries[0]?.loc.line ?? 0;
perLineSteps.set(line, [...(perLineSteps.get(line) ?? []), step]);
}
for (const [line, steps] of perLineSteps.entries()) {
const perLineStep = perLineStepsArray.get(line);
if (perLineStep === undefined) {
perLineStepsArray.set(line, [steps]);
}
else {
perLineStep.push(steps);
}
}
}
return lines.map((line, idx) => {
const infos = perLineStepsArray.get(idx + 1);
if (infos) {
const gasInfo = infos.flatMap(it => it.map(step => normalizeGas(step.gasCost)));
return {
line,
info: {
$: "Covered",
hits: infos.length,
gasCosts: gasInfo,
},
};
}
if (!(0, exports.isExecutableLine)(line)) {
return {
line,
info: {
$: "Skipped",
},
};
}
return {
line,
info: {
$: "Uncovered",
},
};
});
};
exports.buildFuncLineInfo = buildFuncLineInfo;
const normalizeGas = (gas) => {
if (gas > 10000) {
return 26;
}
return gas;
};
const isExecutableLine = (line) => {
const trimmed = line.trim();
return (!trimmed.includes("=>") && // dictionary
trimmed !== "}" && // close braces
!trimmed.includes("} {") && // IFREFELSEREF
!trimmed.includes(";;") && // FunC comment line
!trimmed.includes("#pragma ") &&
!trimmed.includes("#include") &&
!trimmed.includes("inline {") && // function signature
!trimmed.includes("inline;") && // function signature
!trimmed.includes("inline_ref {") && // function signature
!trimmed.includes("inline_ref;") && // function signature
!trimmed.includes(" method_id {") && // method signature
!trimmed.includes('asm """') && // function signature
!trimmed.includes('asm "') && // function signature
!trimmed.includes("asm(") && // function signature
trimmed.length > 0);
};
exports.isExecutableLine = isExecutableLine;
const generateCoverageSummary = (lines) => {
const totalExecutableLines = lines.filter(line => (0, exports.isExecutableLine)(line.line)).length;
const coveredLines = lines.filter(line => (0, exports.isExecutableLine)(line.line) && line.info.$ === "Covered").length;
const uncoveredLines = totalExecutableLines - coveredLines;
const coveragePercentage = totalExecutableLines === 0 ? 0 : (coveredLines / totalExecutableLines) * 100;
let totalGas = 0;
let totalHits = 0;
const instructionMap = new Map();
for (const line of lines) {
if (line.info.$ !== "Covered")
continue;
const lineGas = line.info.gasCosts.reduce((sum, gas) => sum + gas, 0);
totalGas += lineGas;
totalHits += line.info.hits;
const trimmedLine = line.line.trim();
const instructionName = trimmedLine.split(/\s+/)[0];
if (instructionName !== undefined) {
const current = instructionMap.get(instructionName) ?? { totalGas: 0, hits: 0 };
instructionMap.set(instructionName, {
totalGas: current.totalGas + lineGas,
hits: current.hits + line.info.hits,
});
}
}
const instructionStats = [...instructionMap.entries()]
.map(([name, stats]) => ({
name,
totalGas: stats.totalGas,
totalHits: stats.hits,
avgGas: stats.hits === 0 ? 0 : Math.round((stats.totalGas / stats.hits) * 100) / 100,
}))
.sort((a, b) => b.totalGas - a.totalGas);
return {
totalLines: totalExecutableLines,
coveredLines,
uncoveredLines,
coveragePercentage,
totalGas,
totalHits,
instructionStats,
};
};
exports.generateCoverageSummary = generateCoverageSummary;
//# sourceMappingURL=data.js.map