import {
findMatchingBrace,
isBlank,
isTempIdent,
leadingWhitespace,
nextCodeLine,
parseAssignment,
} from "./postprocess-shared.js";
const OVERFLOW_BOUNDS = [
"-2147483648",
"0",
"-9223372036854775808",
"2147483647",
"4294967295",
"9223372036854775807",
"18446744073709551615",
];
export function collapseOverflowChecks(statements) {
let index = 0;
while (index < statements.length) {
const collapse = tryMatchOverflow(statements, index);
if (collapse) {
applyOverflowCollapse(statements, collapse);
continue;
}
index++;
}
}
function tryMatchOverflow(statements, idx) {
const line0 = statements[idx].trim();
if (line0 === "" || line0.startsWith("//")) return null;
const a1 = parseLetAssignment(line0);
if (!a1) return null;
const dupIdx = nextCodeLine(statements, idx + 1);
if (dupIdx < 0) return null;
const a2 = parseLetAssignment(statements[dupIdx].trim());
if (!a2 || a2.rhs !== a1.lhs) return null;
const boundIdx = nextCodeLine(statements, dupIdx + 1);
if (boundIdx < 0) return null;
const a3 = parseLetAssignment(statements[boundIdx].trim());
if (!a3 || !OVERFLOW_BOUNDS.includes(a3.rhs)) return null;
const ifIdx = nextCodeLine(statements, boundIdx + 1);
if (ifIdx < 0) return null;
const ifLine = statements[ifIdx].trim();
if (!ifLine.startsWith("if ") || !ifLine.endsWith("{")) return null;
if (!ifLine.includes(`${a2.lhs} <`) && !ifLine.includes(`${a2.lhs} ==`) && !ifLine.includes(`${a2.lhs} >`)) {
return null;
}
const ifBlockEnd = findMatchingBrace(statements, ifIdx);
if (ifBlockEnd < 0) return null;
let firstBody = null;
for (let i = ifIdx + 1; i < statements.length; i++) {
const t = statements[i].trim();
if (!isBlank(t)) {
firstBody = t;
break;
}
}
const isChecked = firstBody !== null && firstBody.startsWith("throw(");
let blankEnd = ifBlockEnd;
let elseUnwrap = null;
if (!isChecked) {
const next = nextCodeLine(statements, ifBlockEnd + 1);
if (next >= 0) {
const nt = statements[next].trim();
if (nt === "else {" || nt === "} else {") {
const elseEnd = findMatchingBrace(statements, next);
if (elseEnd >= 0) blankEnd = elseEnd;
}
}
} else {
const next = nextCodeLine(statements, ifBlockEnd + 1);
if (next >= 0) {
const nt = statements[next].trim();
if (nt === "else {" || nt === "} else {") {
const elseEnd = findMatchingBrace(statements, next);
if (elseEnd >= 0) elseUnwrap = [next, elseEnd];
}
}
}
return {
opLine: idx,
expr: a1.rhs,
resultVar: a1.lhs,
blankStart: idx + 1,
blankEnd,
isChecked,
elseUnwrap,
};
}
function applyOverflowCollapse(statements, c) {
if (c.isChecked) {
const wrapped = c.expr.startsWith("checked(") ? c.expr : `checked(${c.expr})`;
statements[c.opLine] = `${leadingWhitespace(statements[c.opLine])}let ${c.resultVar} = ${wrapped};`;
}
for (let i = c.blankStart; i <= c.blankEnd; i++) {
statements[i] = "";
}
if (c.elseUnwrap) {
statements[c.elseUnwrap[0]] = "";
statements[c.elseUnwrap[1]] = "";
}
if (!c.isChecked) {
const next = nextCodeLine(statements, c.blankEnd + 1);
if (next >= 0) {
const line = statements[next].trim();
if (!line.startsWith("let ") && !line.startsWith("if ") && !line.startsWith("//")) {
const a = parseAssignment(line);
if (a && isTempIdent(a.rhs) && a.rhs !== c.resultVar) {
statements[next] = `${leadingWhitespace(statements[next])}${a.lhs} = ${c.resultVar};`;
}
}
}
}
}
function parseLetAssignment(line) {
if (!line.startsWith("let ")) return null;
const rest = line.slice(4);
const semiPos = rest.indexOf(";");
if (semiPos < 0) return null;
const body = rest.slice(0, semiPos);
const eqPos = body.indexOf(" = ");
if (eqPos < 0) return null;
return { lhs: body.slice(0, eqPos).trim(), rhs: body.slice(eqPos + 3).trim() };
}